diff --git a/.vscode/tasks.json b/.vscode/tasks.json index b3ccdfda..e1a1605e 100644 --- a/.vscode/tasks.json +++ b/.vscode/tasks.json @@ -12,7 +12,7 @@ { "label": "build", "type": "shell", - "command": "make -j16", + "command": "make -j16 install", "problemMatcher": "$gcc", "options": { "cwd": "${workspaceFolder}/_build" diff --git a/src/bin/calaos_server/Audio/AVRRose.cpp b/src/bin/calaos_server/Audio/AVRRose.cpp index 6ba27812..5b63ca94 100644 --- a/src/bin/calaos_server/Audio/AVRRose.cpp +++ b/src/bin/calaos_server/Audio/AVRRose.cpp @@ -19,17 +19,21 @@ ** ******************************************************************************/ #include "AVRRose.h" +#include "UrlDownloader.h" using namespace Calaos; +const int HIFIROSE_DEFAULT_PORT = 9283; + /* HifiRose devices are using a simple REST API without any authentication or security. */ AVRRose::AVRRose(Params &p): - AVReceiver(p, 0, AVR_CON_CUSTOM) + AVReceiver(p, HIFIROSE_DEFAULT_PORT, AVR_CON_CUSTOM) { + cInfoDom("hifirose") << params["host"]; } AVRRose::~AVRRose() @@ -38,10 +42,35 @@ AVRRose::~AVRRose() void AVRRose::Power(bool on, int zone) { + pollStatus([on, this]() + { + if ((on && power_main) || + (!on && !power_main)) + return; + + Json d = { + { "barControl", "remote_bar_order_sleep_on_off" }, + { "value", "-1" } + }; + + postRequest("remote_bar_order", d.dump(), [this](const string &) + { + pollStatus(); + }); + }); } void AVRRose::setVolume(int volume, int zone) { + Json d = { + { "volumeType", "volume_set" }, + { "volumeValue", Utils::to_string(volume) } + }; + + postRequest("volume", d.dump(), [this](const string &) + { + pollStatus(); + }); } void AVRRose::selectInputSource(int source, int zone) @@ -51,3 +80,91 @@ void AVRRose::selectInputSource(int source, int zone) void AVRRose::sendCustomCommand(string command) { } + +void AVRRose::pollStatus(std::function nextCb) +{ + postRequest("get_current_state", {}, [this, nextCb](const string &data) + { + Json jdoc; + try + { + jdoc = Json::parse(data); + if (!jdoc.is_object()) + { + cWarningDom("hifirose") << "Invalid JSON data"; + return; + } + + string code = jdoc["code"]; + + if (code == "SLEEP") + { + power_main = false; + state_changed_1.emit("power", "false"); + } + else if (code == "G0000") + { + power_main = true; + state_changed_1.emit("power", "true"); + } + else + { + cWarningDom("hifirose") << "Unknown status code: " << jdoc["code"]; + } + } + catch(const std::exception& e) + { + cWarningDom("hifirose") << "Error parsing '" << data << "':" << e.what(); + } + + //Get current volume + Json d = { + { "volumeType", "volume_get" } + }; + + postRequest("volume", d.dump(), [this, nextCb](const string &dataRes) + { + Json jdocvol; + try + { + jdocvol = Json::parse(dataRes); + if (!jdocvol.is_object()) + { + cWarningDom("hifirose") << "Invalid JSON data"; + return; + } + + volume_main = jdocvol["volumeValue"]; + state_changed_1.emit("volume", Utils::to_string(volume_main)); + } + catch(const std::exception& e) + { + cWarningDom("hifirose") << "Error parsing '" << dataRes << "':" << e.what(); + } + + if (nextCb) + nextCb(); + }); + }); +} + +void AVRRose::postRequest(string urlPath, string data, std::function dataCb) +{ + string url = "http://" + host + ":" + Utils::to_string(port) + "/" + urlPath; + + UrlDownloader *dl = new UrlDownloader(url, true); + dl->setHeader("Content-Type", "application/json"); + dl->httpPost({}, data); + + dl->m_signalCompleteData.connect([dataCb](const string &dataRes, int status) + { + if (status != 200) + { + cErrorDom("hifirose") << "Error while posting data to HifiRose device: " << status; + return; + } + + if (dataCb) + dataCb(dataRes); + }); +} diff --git a/src/bin/calaos_server/Audio/AVRRose.h b/src/bin/calaos_server/Audio/AVRRose.h index c0168b04..6b1275ec 100644 --- a/src/bin/calaos_server/Audio/AVRRose.h +++ b/src/bin/calaos_server/Audio/AVRRose.h @@ -32,8 +32,8 @@ class AVRRose: public AVReceiver { protected: - int inputFromString(string source); - string inputToString(int source); + void postRequest(string urlPath, string data, std::function dataCb); + void pollStatus(std::function nextCb = nullptr); public: AVRRose(Params &p);