#include <websocketpp/config/asio_client.hpp>
#include <websocketpp/client.hpp>
#include <cjson/cJSON.h>
#include <iostream>
#include <iomanip>
#include <ctime>
namespace wlib = websocketpp::lib;
namespace ssl = boost::asio::ssl;
typedef websocketpp::client<websocketpp::config::asio_tls_client> wclient;
typedef wlib::shared_ptr<wlib::asio::ssl::context> context_ptr;
const char* ENDPOINT = "wss://ws.twelvedata.com/v1/quotes/price?apikey=YOUR_API_KEY_HERE";
const char* SUBSCRIBE_ACTION = "{"\
"\"action\": \"subscribe\"," \
"\"params\": {" \
"\"symbols\": \"TSLA\"" \
"}" \
"}";
int main() {
wclient::connection_ptr connection;
wlib::error_code error_code;
wclient client;
client.set_access_channels(websocketpp::log::alevel::all);
client.clear_access_channels(websocketpp::log::alevel::frame_payload);
client.set_error_channels(websocketpp::log::elevel::all);
// Initialize Boost.ASIO
client.init_asio();
// Set TLS initialize handler
client.set_tls_init_handler(wlib::bind([](auto* hostname, auto hdl) {
context_ptr context = wlib::make_shared<ssl::context>(ssl::context::sslv23);
context->set_verify_mode(ssl::verify_none);
return context;
}, ENDPOINT, websocketpp::lib::placeholders::_1));
// Is called after the WebSocket handshake is complete
client.set_open_handler([&client](auto hdl) {
// Send subscribe action to stream
client.send(hdl, SUBSCRIBE_ACTION, websocketpp::frame::opcode::text);
});
// Receive and handle messages from server
client.set_message_handler([](auto hdl, wclient::message_ptr message) {
cJSON* json = cJSON_Parse(message->get_payload().c_str());
if (json == nullptr) {
std::cout << "received invalid JSON: " << std::endl << message->get_payload() << std::endl;
return;
}
// Get event type
cJSON* eventTypeField = cJSON_GetObjectItem(json, "event");
if (eventTypeField == nullptr) {
std::cout << "unknown JSON structure" << std::endl;
return;
}
// Extract string from event type
const char* eventType = cJSON_GetStringValue(eventTypeField);
if (strcmp(eventType, "subscribe-status") == 0) {
cJSON* statusField = cJSON_GetObjectItem(json, "status");
const char* status = cJSON_GetStringValue(statusField);
if (strcmp(status, "ok") != 0) {
std::cout << "Failed subscribe to stream" << std::endl;
return;
}
cJSON* successField = cJSON_GetObjectItem(json, "success");
cJSON* failsField = cJSON_GetObjectItem(json, "fails");
// Iterate over the symbols that were successfully subscribed
for (int idx = 0; idx < cJSON_GetArraySize(successField); idx++) {
cJSON* item = cJSON_GetArrayItem(successField, idx);
cJSON* symbolField = cJSON_GetObjectItem(item, "symbol");
const char* symbol = cJSON_GetStringValue(symbolField);
std::cout << "Success subscribed to `"<< symbol << "` " << "symbol." << std::endl;
}
// If we're unable to subscribe to some symbols
for (int idx = 0; 0 < cJSON_GetArraySize(failsField); idx++) {
cJSON* item = cJSON_GetArrayItem(failsField, idx);
cJSON* symbolField = cJSON_GetObjectItem(item, "symbol");
const char* symbol = cJSON_GetStringValue(symbolField);
std::cout << "Failed to subscribe on `"<< symbol << "` " << "symbol." << std::endl;
}
return;
}
if (strcmp(eventType, "price") == 0) {
cJSON* timestampField = cJSON_GetObjectItem(json, "timestamp");
cJSON* currencyField = cJSON_GetObjectItem(json, "currency");
cJSON* symbolField = cJSON_GetObjectItem(json, "symbol");
cJSON* priceField = cJSON_GetObjectItem(json, "price");
time_t time = timestampField->valueint;
std::cout << "[" << std::put_time(gmtime(&time), "%I:%M:%S %p") << "]: ";
std::cout << "The symbol `" << cJSON_GetStringValue(symbolField) << "` ";
std::cout << "has changed price to " << priceField->valuedouble << " ";
if (currencyField != nullptr) {
std::cout << "(" << cJSON_GetStringValue(currencyField) << ")" << std::endl;
} else {
std::cout << std::endl;
}
return;
}
// Free memory of JSON structure
cJSON_Delete(json);
});
// New connection to WebSocket endpoint
connection = client.get_connection(ENDPOINT, error_code);
if (error_code) {
std::cout << "Failed connection. Message: " << error_code.message() << std::endl;
return -1;
}
// Connect to websocket endpoint
client.connect(connection);
client.run();
}
-