mirror of https://github.com/nymea/nymea.git
220 lines
8.0 KiB
C++
220 lines
8.0 KiB
C++
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
|
* *
|
|
* Copyright (C) 2015 Simon Stuerz <simon.stuerz@guh.guru> *
|
|
* *
|
|
* This file is part of guh. *
|
|
* *
|
|
* Guh is free software: you can redistribute it and/or modify *
|
|
* it under the terms of the GNU General Public License as published by *
|
|
* the Free Software Foundation, version 2 of the License. *
|
|
* *
|
|
* Guh is distributed in the hope that it will be useful, *
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
|
* GNU General Public License for more details. *
|
|
* *
|
|
* You should have received a copy of the GNU General Public License *
|
|
* along with guh. If not, see <http://www.gnu.org/licenses/>. *
|
|
* *
|
|
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
|
|
|
#include "jsonrpcserver.h"
|
|
#include "extern-plugininfo.h"
|
|
|
|
JsonRpcServer::JsonRpcServer(QObject *parent) :
|
|
QObject(parent),
|
|
m_id(0)
|
|
{
|
|
m_manager = new TuneManager(31337, this);
|
|
|
|
connect(m_manager, &TuneManager::tuneConnectionStatusChanged, this, &JsonRpcServer::connectionStatusChanged);
|
|
connect(m_manager, &TuneManager::dataReady, this, &JsonRpcServer::processData);
|
|
|
|
}
|
|
|
|
void JsonRpcServer::start()
|
|
{
|
|
m_manager->start();
|
|
}
|
|
|
|
void JsonRpcServer::stop()
|
|
{
|
|
m_manager->stop();
|
|
}
|
|
|
|
bool JsonRpcServer::tuneAvailable()
|
|
{
|
|
return m_manager->tuneAvailable();
|
|
}
|
|
|
|
bool JsonRpcServer::sync(QList<Device *> deviceList)
|
|
{
|
|
if (!tuneAvailable()) {
|
|
return false;
|
|
}
|
|
|
|
QVariantMap message;
|
|
QVariantMap params;
|
|
QVariantList moods;
|
|
QVariantMap tune;
|
|
foreach (Device* device, deviceList) {
|
|
if (device->deviceClassId() == moodDeviceClassId) {
|
|
QVariantMap mood;
|
|
mood.insert("name", device->paramValue("name"));
|
|
mood.insert("deviceId", device->id());
|
|
mood.insert("position", device->paramValue("position"));
|
|
mood.insert("icon", device->paramValue("icon"));
|
|
QVariantMap states;
|
|
states.insert("value", device->stateValue(valueStateTypeId).toInt());
|
|
states.insert("active", device->stateValue(activeStateTypeId).toBool());
|
|
mood.insert("states", states);
|
|
moods.append(mood);
|
|
}
|
|
if (device->deviceClassId() == tuneDeviceClassId) {
|
|
tune.insert("name", device->paramValue("name"));
|
|
tune.insert("deviceId", device->id());
|
|
tune.insert("brightness", device->stateValue(brightnessStateTypeId).toInt());
|
|
tune.insert("power", device->stateValue(powerStateTypeId).toBool());
|
|
}
|
|
}
|
|
m_id++;
|
|
params.insert("moods", moods);
|
|
params.insert("tune", tune);
|
|
message.insert("method", "Items.Sync");
|
|
message.insert("id", m_id);
|
|
message.insert("params", params);
|
|
|
|
m_requests.insert(m_id, message);
|
|
|
|
QJsonDocument jsonDoc = QJsonDocument::fromVariant(message);
|
|
qCDebug(dcTune) << jsonDoc.toJson();
|
|
m_manager->sendData(jsonDoc.toJson(QJsonDocument::Compact));
|
|
return true;
|
|
}
|
|
|
|
void JsonRpcServer::executeAction(Device *device, const Action &action)
|
|
{
|
|
QVariantMap message;
|
|
QVariantMap params;
|
|
|
|
params.insert("deviceId", device->id());
|
|
params.insert("actionId", action.id());
|
|
|
|
if (device->deviceClassId() == moodDeviceClassId) {
|
|
message.insert("method", "Mood.ExecuteAction");
|
|
if (action.actionTypeId() == valueActionTypeId) {
|
|
params.insert("value", action.param("value").value().toInt());
|
|
params.insert("active", device->stateValue(activeStateTypeId).toBool());
|
|
} else if (action.actionTypeId() == activeActionTypeId) {
|
|
params.insert("value", device->stateValue(valueStateTypeId).toInt());
|
|
params.insert("active", action.param("active").value().toBool());
|
|
}
|
|
} else if(device->deviceClassId() == tuneDeviceClassId) {
|
|
message.insert("method", "Tune.ExecuteAction");
|
|
if (action.actionTypeId() == brightnessActionTypeId) {
|
|
params.insert("brightness", action.param("brightness").value().toInt());
|
|
params.insert("power", device->stateValue(powerStateTypeId).toBool());
|
|
} else if (action.actionTypeId() == powerActionTypeId) {
|
|
params.insert("brightness", device->stateValue(brightnessStateTypeId).toInt());
|
|
params.insert("power", action.param("power").value().toBool());
|
|
}
|
|
}
|
|
|
|
m_id++;
|
|
message.insert("id", m_id);
|
|
message.insert("params", params);
|
|
|
|
m_requests.insert(m_id, message);
|
|
|
|
QJsonDocument jsonDoc = QJsonDocument::fromVariant(message);
|
|
qCDebug(dcTune) << jsonDoc.toJson();
|
|
m_manager->sendData(jsonDoc.toJson(QJsonDocument::Compact));
|
|
}
|
|
|
|
QByteArray JsonRpcServer::formatResponse(int commandId, const QVariantMap &responseParams)
|
|
{
|
|
QVariantMap responseMap;
|
|
responseMap.insert("id", commandId);
|
|
responseMap.insert("success", true);
|
|
responseMap.insert("params", responseParams);
|
|
QJsonDocument jsonDoc = QJsonDocument::fromVariant(responseMap);
|
|
return jsonDoc.toJson(QJsonDocument::Compact);
|
|
}
|
|
|
|
QByteArray JsonRpcServer::formatErrorResponse(int commandId, const QString &errorMessage)
|
|
{
|
|
QVariantMap responseMap;
|
|
responseMap.insert("id", commandId);
|
|
responseMap.insert("success", false);
|
|
responseMap.insert("error", errorMessage);
|
|
QJsonDocument jsonDoc = QJsonDocument::fromVariant(responseMap);
|
|
return jsonDoc.toJson(QJsonDocument::Compact);
|
|
}
|
|
|
|
void JsonRpcServer::handleResponse(const QVariantMap &response)
|
|
{
|
|
int responseId = response.value("id").toInt();
|
|
|
|
if (!m_requests.contains(responseId)) {
|
|
qCWarning(dcTune) << "got a response without a corresponding request!!!!";
|
|
return;
|
|
}
|
|
|
|
// remove it request because we have a response now...
|
|
QVariantMap request = m_requests.take(responseId);
|
|
|
|
// Note: maby we have to do something if any request fails
|
|
if (!response.value("success").toBool()) {
|
|
qCWarning(dcTune) << "error for request:" << request << response.value("error").toString();
|
|
}
|
|
|
|
// check if this is a response to an action execution
|
|
if (response.contains("actionId")) {
|
|
emit gotActionResponse(response);
|
|
}
|
|
}
|
|
|
|
void JsonRpcServer::processData(const QByteArray &data)
|
|
{
|
|
QJsonParseError error;
|
|
QJsonDocument jsonDoc = QJsonDocument::fromJson(data, &error);
|
|
|
|
if(error.error != QJsonParseError::NoError) {
|
|
qCWarning(dcTune) << "failed to parse data" << data << ":" << error.errorString();
|
|
return;
|
|
}
|
|
|
|
QVariantMap message = jsonDoc.toVariant().toMap();
|
|
|
|
// check if the message has an id
|
|
if (!message.contains("id")) {
|
|
qCWarning(dcTune) << "message does not contain a valid id" << message;
|
|
return;
|
|
}
|
|
|
|
// if this is a response message to a request
|
|
if (message.contains("success") && !message.contains("method")) {
|
|
handleResponse(message);
|
|
return;
|
|
}
|
|
|
|
// otherwise we need a method
|
|
if (!message.contains("method")) {
|
|
qCWarning(dcTune) << "message does not contain a valid method" << message;
|
|
return;
|
|
}
|
|
|
|
int commandId = message.value("id").toInt();
|
|
|
|
if (message.value("method").toString() == "Mood.SyncStates") {
|
|
emit gotMoodSync(message.value("params").toMap());
|
|
m_manager->sendData(formatResponse(commandId));
|
|
}
|
|
|
|
if (message.value("method").toString() == "Tune.SyncStates") {
|
|
emit gotTuneSync(message.value("params").toMap());
|
|
m_manager->sendData(formatResponse(commandId));
|
|
}
|
|
|
|
}
|