359 lines
13 KiB
C++
359 lines
13 KiB
C++
//==============================================================================
|
|
/**
|
|
@file HSDConnectionManager.cpp
|
|
|
|
@brief Wrapper to implement the communication with the Stream Dock application
|
|
**/
|
|
//==============================================================================
|
|
|
|
#include "HSDConnectionManager.h"
|
|
|
|
#include "NlohmannJSONUtils.h"
|
|
#include "HSDLogger.h"
|
|
|
|
void HSDConnectionManager::OnOpen(WebsocketClient* inClient, websocketpp::connection_hdl inConnectionHandler) {
|
|
HSDLogger::LogMessage("OnOpen");
|
|
|
|
// Register plugin with StreamDock
|
|
json jsonObject;
|
|
jsonObject["event"] = mRegisterEvent;
|
|
jsonObject["uuid"] = mPluginUUID;
|
|
|
|
websocketpp::lib::error_code ec;
|
|
mWebsocket.send(mConnectionHandle, jsonObject.dump(), websocketpp::frame::opcode::text, ec);
|
|
}
|
|
|
|
void HSDConnectionManager::OnFail(WebsocketClient* inClient, websocketpp::connection_hdl inConnectionHandler) {
|
|
std::string reason;
|
|
|
|
if (inClient) {
|
|
WebsocketClient::connection_ptr connection = inClient->get_con_from_hdl(inConnectionHandler);
|
|
if (connection) {
|
|
reason = connection->get_ec().message();
|
|
}
|
|
}
|
|
|
|
HSDLogger::LogMessage("Failed with reason: {}" + reason);
|
|
|
|
if (mAsioContext) {
|
|
HSDLogger::LogMessage("Stopping ASIO context");
|
|
mAsioContext->stop();
|
|
}
|
|
}
|
|
|
|
void HSDConnectionManager::OnClose(WebsocketClient* inClient, websocketpp::connection_hdl inConnectionHandler) {
|
|
std::string reason;
|
|
|
|
if (inClient) {
|
|
WebsocketClient::connection_ptr connection = inClient->get_con_from_hdl(inConnectionHandler);
|
|
if (connection) {
|
|
reason = connection->get_remote_close_reason();
|
|
}
|
|
}
|
|
|
|
HSDLogger::LogMessage("Close with reason: " + reason);
|
|
|
|
if (mAsioContext) {
|
|
HSDLogger::LogMessage("Stopping ASIO context");
|
|
mAsioContext->stop();
|
|
}
|
|
}
|
|
|
|
void HSDConnectionManager::OnMessage(websocketpp::connection_hdl, WebsocketClient::message_ptr inMsg) {
|
|
if (inMsg && inMsg->get_opcode() == websocketpp::frame::opcode::text) {
|
|
std::string message = inMsg->get_payload();
|
|
HSDLogger::LogMessage("OnMessage: " + message);
|
|
|
|
try {
|
|
json receivedJson = json::parse(message);
|
|
|
|
std::string event = NlohmannJSONUtils::GetStringByName(receivedJson, kESDSDKCommonEvent);
|
|
std::string context = NlohmannJSONUtils::GetStringByName(receivedJson, kESDSDKCommonContext);
|
|
std::string action = NlohmannJSONUtils::GetStringByName(receivedJson, kESDSDKCommonAction);
|
|
std::string deviceID = NlohmannJSONUtils::GetStringByName(receivedJson, kESDSDKCommonDevice);
|
|
json payload;
|
|
NlohmannJSONUtils::GetObjectByName(receivedJson, kESDSDKCommonPayload, payload);
|
|
|
|
if (event == kESDSDKEventKeyDown) {
|
|
mPlugin->KeyDownForAction(action, context, payload, deviceID);
|
|
}
|
|
else if (event == kESDSDKEventKeyUp) {
|
|
mPlugin->KeyUpForAction(action, context, payload, deviceID);
|
|
}
|
|
else if (event == kESDSDKEventWillAppear) {
|
|
mPlugin->WillAppearForAction(action, context, payload, deviceID);
|
|
}
|
|
else if (event == kESDSDKEventWillDisappear) {
|
|
mPlugin->WillDisappearForAction(action, context, payload, deviceID);
|
|
}
|
|
else if (event == kESDSDKEventDidReceiveSettings) {
|
|
mPlugin->DidReceiveSettings(action, context, payload, deviceID);
|
|
}
|
|
else if (event == kESDSDKEventDidReceiveGlobalSettings) {
|
|
mPlugin->DidReceiveGlobalSettings(payload);
|
|
}
|
|
else if (event == kESDSDKEventDeviceDidConnect) {
|
|
json deviceInfo;
|
|
NlohmannJSONUtils::GetObjectByName(receivedJson, kESDSDKCommonDeviceInfo, deviceInfo);
|
|
mPlugin->DeviceDidConnect(deviceID, deviceInfo);
|
|
}
|
|
else if (event == kESDSDKEventDeviceDidDisconnect) {
|
|
mPlugin->DeviceDidDisconnect(deviceID);
|
|
}
|
|
else if (event == kESDSDKEventSendToPlugin) {
|
|
mPlugin->SendToPlugin(action, context, payload, deviceID);
|
|
}
|
|
else if (event == kESDSDKEventSystemDidWakeUp) {
|
|
mPlugin->SystemDidWakeUp();
|
|
}
|
|
else if (event == kESDSDKEventDialDown) {
|
|
mPlugin->DialDownForAction(action, context, payload, deviceID);
|
|
}
|
|
else if (event == kESDSDKEventDialUp) {
|
|
mPlugin->DialUpForAction(action, context, payload, deviceID);
|
|
}
|
|
else if (event == kESDSDKEventDialRotate) {
|
|
mPlugin->DialRotateForAction(action, context, payload, deviceID);
|
|
}
|
|
}
|
|
catch (...) {
|
|
}
|
|
}
|
|
}
|
|
|
|
HSDConnectionManager::HSDConnectionManager(
|
|
int inPort,
|
|
const std::string& inPluginUUID,
|
|
const std::string& inRegisterEvent,
|
|
const std::string& inInfo,
|
|
HSDBasePlugin* inPlugin)
|
|
: mPort(inPort),
|
|
mPluginUUID(inPluginUUID),
|
|
mRegisterEvent(inRegisterEvent),
|
|
mPlugin(inPlugin) {
|
|
if (inPlugin) {
|
|
inPlugin->SetConnectionManager(this);
|
|
}
|
|
}
|
|
|
|
void HSDConnectionManager::Run() {
|
|
try {
|
|
// Create the endpoint
|
|
mWebsocket.clear_access_channels(websocketpp::log::alevel::all);
|
|
mWebsocket.clear_error_channels(websocketpp::log::elevel::all);
|
|
|
|
// Initialize ASIO
|
|
auto ctx = std::make_shared<asio::io_context>();
|
|
mWebsocket.init_asio(ctx.get());
|
|
mAsioContext = ctx;
|
|
|
|
// Register our message handler
|
|
mWebsocket.set_open_handler(websocketpp::lib::bind(
|
|
&HSDConnectionManager::OnOpen, this,
|
|
&mWebsocket, websocketpp::lib::placeholders::_1));
|
|
mWebsocket.set_fail_handler(websocketpp::lib::bind(
|
|
&HSDConnectionManager::OnFail, this,
|
|
&mWebsocket, websocketpp::lib::placeholders::_1));
|
|
mWebsocket.set_close_handler(websocketpp::lib::bind(
|
|
&HSDConnectionManager::OnClose, this,
|
|
&mWebsocket, websocketpp::lib::placeholders::_1));
|
|
mWebsocket.set_message_handler(websocketpp::lib::bind(
|
|
&HSDConnectionManager::OnMessage, this,
|
|
websocketpp::lib::placeholders::_1, websocketpp::lib::placeholders::_2));
|
|
|
|
// Get connection handle
|
|
websocketpp::lib::error_code ec;
|
|
std::string uri = "ws://127.0.0.1:" + std::to_string(mPort);
|
|
WebsocketClient::connection_ptr connection = mWebsocket.get_connection(uri, ec);
|
|
if (ec) {
|
|
HSDLogger::LogMessage("Connect initialization error: " + ec.message());
|
|
return;
|
|
}
|
|
mConnectionHandle = connection->get_handle();
|
|
|
|
// Note that connect here only requests a connection. No network messages
|
|
// are exchanged until the event loop starts running in the next line.
|
|
mWebsocket.connect(connection);
|
|
|
|
// Start the ASIO io_service run loop
|
|
// this will cause a single connection to be made to the server.
|
|
// mWebsocket.run() will exit when this connection is closed.
|
|
mWebsocket.run();
|
|
}
|
|
catch (websocketpp::exception const& e) {
|
|
// Prevent an unused variable warning in release builds
|
|
(void)e;
|
|
std::string whatString = e.what();
|
|
HSDLogger::LogMessage("Websocket threw an exception: " + whatString);
|
|
}
|
|
}
|
|
|
|
void HSDConnectionManager::SetTitle(
|
|
const std::string& inTitle,
|
|
const std::string& inContext,
|
|
ESDSDKTarget inTarget,
|
|
int inState) {
|
|
json jsonObject;
|
|
|
|
jsonObject[kESDSDKCommonEvent] = kESDSDKEventSetTitle;
|
|
jsonObject[kESDSDKCommonContext] = inContext;
|
|
|
|
json payload;
|
|
payload[kESDSDKPayloadTarget] = inTarget;
|
|
payload[kESDSDKPayloadTitle] = inTitle;
|
|
if (inState >= 0) {
|
|
payload[kESDSDKPayloadState] = inState;
|
|
}
|
|
jsonObject[kESDSDKCommonPayload] = payload;
|
|
|
|
websocketpp::lib::error_code ec;
|
|
mWebsocket.send(mConnectionHandle, jsonObject.dump(), websocketpp::frame::opcode::text, ec);
|
|
}
|
|
|
|
void HSDConnectionManager::SetImage(
|
|
const std::string& inBase64ImageString,
|
|
const std::string& inContext,
|
|
ESDSDKTarget inTarget,
|
|
int inState) {
|
|
json jsonObject;
|
|
|
|
jsonObject[kESDSDKCommonEvent] = kESDSDKEventSetImage;
|
|
jsonObject[kESDSDKCommonContext] = inContext;
|
|
|
|
json payload;
|
|
payload[kESDSDKPayloadTarget] = inTarget;
|
|
const std::string prefix = "data:image/png;base64,";
|
|
if (inBase64ImageString.empty() ||
|
|
inBase64ImageString.substr(0, prefix.length()).find(prefix) == 0) {
|
|
payload[kESDSDKPayloadImage] = inBase64ImageString;
|
|
}
|
|
else {
|
|
payload[kESDSDKPayloadImage] = "data:image/png;base64," + inBase64ImageString;
|
|
}
|
|
if (inState >= 0) {
|
|
payload[kESDSDKPayloadState] = inState;
|
|
}
|
|
jsonObject[kESDSDKCommonPayload] = payload;
|
|
|
|
websocketpp::lib::error_code ec;
|
|
mWebsocket.send(mConnectionHandle, jsonObject.dump(), websocketpp::frame::opcode::text, ec);
|
|
}
|
|
|
|
void HSDConnectionManager::ShowAlertForContext(const std::string& inContext) {
|
|
json jsonObject;
|
|
|
|
jsonObject[kESDSDKCommonEvent] = kESDSDKEventShowAlert;
|
|
jsonObject[kESDSDKCommonContext] = inContext;
|
|
|
|
websocketpp::lib::error_code ec;
|
|
mWebsocket.send(mConnectionHandle, jsonObject.dump(), websocketpp::frame::opcode::text, ec);
|
|
}
|
|
|
|
void HSDConnectionManager::ShowOKForContext(const std::string& inContext) {
|
|
json jsonObject;
|
|
|
|
jsonObject[kESDSDKCommonEvent] = kESDSDKEventShowOK;
|
|
jsonObject[kESDSDKCommonContext] = inContext;
|
|
|
|
websocketpp::lib::error_code ec;
|
|
mWebsocket.send(mConnectionHandle, jsonObject.dump(), websocketpp::frame::opcode::text, ec);
|
|
}
|
|
|
|
void HSDConnectionManager::SetSettings(
|
|
const json& inSettings,
|
|
const std::string& inContext) {
|
|
json jsonObject;
|
|
|
|
jsonObject[kESDSDKCommonEvent] = kESDSDKEventSetSettings;
|
|
jsonObject[kESDSDKCommonContext] = inContext;
|
|
jsonObject[kESDSDKCommonPayload] = inSettings;
|
|
|
|
websocketpp::lib::error_code ec;
|
|
mWebsocket.send(mConnectionHandle, jsonObject.dump(), websocketpp::frame::opcode::text, ec);
|
|
}
|
|
|
|
void HSDConnectionManager::SetState(int inState, const std::string& inContext) {
|
|
json jsonObject;
|
|
|
|
json payload;
|
|
payload[kESDSDKPayloadState] = inState;
|
|
|
|
jsonObject[kESDSDKCommonEvent] = kESDSDKEventSetState;
|
|
jsonObject[kESDSDKCommonContext] = inContext;
|
|
jsonObject[kESDSDKCommonPayload] = payload;
|
|
|
|
websocketpp::lib::error_code ec;
|
|
mWebsocket.send(mConnectionHandle, jsonObject.dump(), websocketpp::frame::opcode::text, ec);
|
|
}
|
|
|
|
void HSDConnectionManager::SendToPropertyInspector(
|
|
const std::string& inAction,
|
|
const std::string& inContext,
|
|
const json& inPayload) {
|
|
json jsonObject;
|
|
|
|
jsonObject[kESDSDKCommonEvent] = kESDSDKEventSendToPropertyInspector;
|
|
jsonObject[kESDSDKCommonContext] = inContext;
|
|
jsonObject[kESDSDKCommonAction] = inAction;
|
|
jsonObject[kESDSDKCommonPayload] = inPayload;
|
|
|
|
websocketpp::lib::error_code ec;
|
|
mWebsocket.send(mConnectionHandle, jsonObject.dump(), websocketpp::frame::opcode::text, ec);
|
|
}
|
|
|
|
void HSDConnectionManager::SwitchToProfile(const std::string& inDeviceID, const std::string& inProfileName) {
|
|
if (!inDeviceID.empty()) {
|
|
json jsonObject;
|
|
|
|
jsonObject[kESDSDKCommonEvent] = kESDSDKEventSwitchToProfile;
|
|
jsonObject[kESDSDKCommonContext] = mPluginUUID;
|
|
jsonObject[kESDSDKCommonDevice] = inDeviceID;
|
|
|
|
if (!inProfileName.empty()) {
|
|
json payload;
|
|
payload[kESDSDKPayloadProfile] = inProfileName;
|
|
jsonObject[kESDSDKCommonPayload] = payload;
|
|
}
|
|
|
|
websocketpp::lib::error_code ec;
|
|
mWebsocket.send(mConnectionHandle, jsonObject.dump(), websocketpp::frame::opcode::text, ec);
|
|
}
|
|
}
|
|
|
|
void HSDConnectionManager::LogMessage(const std::string& inMessage) {
|
|
if (!inMessage.empty()) {
|
|
json jsonObject;
|
|
|
|
jsonObject[kESDSDKCommonEvent] = kESDSDKEventLogMessage;
|
|
|
|
json payload;
|
|
payload[kESDSDKPayloadMessage] = inMessage;
|
|
jsonObject[kESDSDKCommonPayload] = payload;
|
|
|
|
websocketpp::lib::error_code ec;
|
|
mWebsocket.send(mConnectionHandle, jsonObject.dump(), websocketpp::frame::opcode::text, ec);
|
|
}
|
|
}
|
|
|
|
void HSDConnectionManager::GetGlobalSettings() {
|
|
json jsonObject{ {kESDSDKCommonEvent, kESDSDKEventGetGlobalSettings},
|
|
{kESDSDKCommonContext, mPluginUUID} };
|
|
websocketpp::lib::error_code ec;
|
|
mWebsocket.send(mConnectionHandle, jsonObject.dump(), websocketpp::frame::opcode::text, ec);
|
|
}
|
|
|
|
void HSDConnectionManager::SetGlobalSettings(const json& inSettings) {
|
|
json jsonObject;
|
|
|
|
jsonObject[kESDSDKCommonEvent] = kESDSDKEventSetGlobalSettings;
|
|
jsonObject[kESDSDKCommonContext] = mPluginUUID;
|
|
jsonObject[kESDSDKCommonPayload] = inSettings;
|
|
|
|
websocketpp::lib::error_code ec;
|
|
mWebsocket.send(mConnectionHandle, jsonObject.dump(), websocketpp::frame::opcode::text, ec);
|
|
}
|
|
|
|
std::shared_ptr<asio::io_context> HSDConnectionManager::GetAsioContext() const {
|
|
return mAsioContext;
|
|
}
|