From ba83843d3d6559206f0f0f7bf8ce1f1e0b85c98f Mon Sep 17 00:00:00 2001 From: Ansel Zandegran Date: Sun, 4 Feb 2018 23:19:34 +0100 Subject: [PATCH] WIP: Mode change done --- libsrc/leddevice/dev_net/LedDeviceAurora.cpp | 203 +++++++++++++++++++ libsrc/leddevice/dev_net/LedDeviceAurora.h | 67 ++++++ 2 files changed, 270 insertions(+) create mode 100644 libsrc/leddevice/dev_net/LedDeviceAurora.cpp create mode 100644 libsrc/leddevice/dev_net/LedDeviceAurora.h diff --git a/libsrc/leddevice/dev_net/LedDeviceAurora.cpp b/libsrc/leddevice/dev_net/LedDeviceAurora.cpp new file mode 100644 index 00000000..02d05103 --- /dev/null +++ b/libsrc/leddevice/dev_net/LedDeviceAurora.cpp @@ -0,0 +1,203 @@ + +// Local-Hyperion includes +#include "LedDeviceAurora.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +// qt includes +#include +#include +#include + +struct addrinfo vints, *serverinfo, *pt; +//char udpbuffer[1024]; +int sockfp; +int update_num; +LedDevice* LedDeviceAurora::construct(const QJsonObject &deviceConfig) +{ + return new LedDeviceAurora(deviceConfig); +} + +LedDeviceAurora::LedDeviceAurora(const QJsonObject &deviceConfig) { + init(deviceConfig); +} + +bool LedDeviceAurora::init(const QJsonObject &deviceConfig) { + const QString hostname = deviceConfig["output"].toString(); + const QString key = deviceConfig["key"].toString(); + + manager = new QNetworkAccessManager(); + QString port; + // Read Panel count and panel Ids + QByteArray response = get(hostname, key, "panelLayout/layout"); + QJsonParseError error; + QJsonDocument doc = QJsonDocument::fromJson(response, &error); + if (error.error != QJsonParseError::NoError) + { + throw std::runtime_error("No Layout found. Check hostname and auth key"); + } + //Debug + QString strJson(doc.toJson(QJsonDocument::Compact)); + std::cout << strJson.toUtf8().constData() << std::endl; + + QJsonObject json = doc.object(); + + //Debug + //Json::FastWriter fastWriter; + //std::cout << fastWriter.write(json); + + panelCount = json["numPanels"].toInt(); + std::cout << panelCount << std::endl; + QJsonObject positionDataJson = doc.object()["positionData"].toObject(); + QJsonArray positionData = json["positionData"].toArray(); + // Loop over all children. + foreach (const QJsonValue & value, positionData) { + QJsonObject panelObj = value.toObject(); + int panelId = panelObj["panelId"].toInt(); + panelIds.push_back(panelId); + } + + // Check if we found enough lights. + if (panelIds.size() != panelCount) { + throw std::runtime_error("Not enough lights found"); + }else { + std::cout << "All panel Ids found: "<< panelIds.size() << std::endl; + } + + // Set Aurora to UDP Mode + QByteArray modeResponse = changeMode(hostname, key, "effects"); + QJsonDocument configDoc = QJsonDocument::fromJson(modeResponse, &error); + if (error.error != QJsonParseError::NoError) + { + throw std::runtime_error("Could not change mode"); + } + QJsonObject configJson = doc.object(); + + // Get UDP port + port = configJson["streamControlPort"].toString(); + + std::cout << "hostname " << hostname.toStdString() << " port " << port.toStdString() << std::endl; + /* + int rv; + + memset(&vints, 0, sizeof vints); + vints.ai_family = AF_UNSPEC; + vints.ai_socktype = SOCK_DGRAM; + + if ((rv = getaddrinfo(hostname.c_str() , port.c_str(), &vints, &serverinfo)) != 0) { + fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(rv)); + assert(rv==0); + } + + // loop through all the results and make a socket + for(pt = serverinfo; pt != NULL; pt = pt->ai_next) { + if ((sockfp = socket(pt->ai_family, pt->ai_socktype, + pt->ai_protocol)) == -1) { + perror("talker: socket"); + continue; + } + + break; + } + + if (pt == NULL) { + fprintf(stderr, "talker: failed to create socket\n"); + assert(pt!=NULL); + }*/ + std::cout << "Started successfully "; + return true; +} + +QString LedDeviceAurora::getUrl(QString host, QString token, QString route) { + return QString("http://%1:16021/api/v1/%2/%3").arg(host).arg(token).arg(route); +} + +QByteArray LedDeviceAurora::get(QString host, QString token, QString route) { + QString url = getUrl(host, token, route); + // Perfrom request + QNetworkRequest request(url); + QNetworkReply* reply = manager->get(request); + // Connect requestFinished signal to quit slot of the loop. + QEventLoop loop; + loop.connect(reply, SIGNAL(finished()), SLOT(quit())); + // Go into the loop until the request is finished. + loop.exec(); + // Read all data of the response. + QByteArray response = reply->readAll(); + // Free space. + reply->deleteLater(); + // Return response + return response; +} + +QByteArray LedDeviceAurora::putJson(QString url, QString json) { + // Perfrom request + QNetworkRequest request(url); + QNetworkReply* reply = manager->put(request, json.toUtf8()); + // Connect requestFinished signal to quit slot of the loop. + QEventLoop loop; + loop.connect(reply, SIGNAL(finished()), SLOT(quit())); + // Go into the loop until the request is finished. + loop.exec(); + // Read all data of the response. + QByteArray response = reply->readAll(); + // Free space. + reply->deleteLater(); + // Return response + return response; +} + +QByteArray LedDeviceAurora::changeMode(QString host, QString token, QString route) { + QString url = getUrl(host, token, route); + QString jsondata( "{\"write\" : {\"command\" : \"display\", \"animType\" : \"extControl\"}}"); //Enable UDP Mode + return putJson(url, jsondata); +} + +LedDeviceAurora::~LedDeviceAurora() +{ + delete manager; +} + +int LedDeviceAurora::write(const std::vector & ledValues) +{ + uint udpBufferSize = panelCount * 7 + 1; + char udpbuffer[udpBufferSize]; + update_num++; + update_num &= 0xf; + + int i=0; + int panelCounter = 0; + udpbuffer[i++] = panelCount; + for (const ColorRgb& color : ledValues) + { + if (i panelCount) { + break; + } + //printf ("c.red %d sz c.red %d\n", color.red, sizeof(color.red)); + } + sendto(sockfp, udpbuffer, i, 0, pt->ai_addr, pt->ai_addrlen); + + return 0; +} + +int LedDeviceAurora::switchOff() +{ + return 0; +} diff --git a/libsrc/leddevice/dev_net/LedDeviceAurora.h b/libsrc/leddevice/dev_net/LedDeviceAurora.h new file mode 100644 index 00000000..57b9c495 --- /dev/null +++ b/libsrc/leddevice/dev_net/LedDeviceAurora.h @@ -0,0 +1,67 @@ +#pragma once +// STL includes +#include +#include +#include + +// Leddevice includes +#include +// Qt includes +#include +#include +#include +#include +/// +/// Implementation of the LedDevice that write the led-colors to an +/// ASCII-textfile('/home/pi/LedDevice.out') +/// +class LedDeviceAurora : public LedDevice +{ +public: + /// + /// Constructs the test-device, which opens an output stream to the file + /// + LedDeviceAurora(const QJsonObject &deviceConfig); + + /// + /// Destructor of this test-device + /// + virtual ~LedDeviceAurora(); + + /// Switch the leds off + virtual int switchOff(); + /// constructs leddevice + static LedDevice* construct(const QJsonObject &deviceConfig); +protected: + /// + /// Writes the RGB-Color values to the leds. + /// + /// @param[in] ledValues The RGB-color per led + /// + /// @return Zero on success else negative + /// + virtual int write(const std::vector & ledValues); + + bool init(const QJsonObject &deviceConfig); + +private: + /// The outputstream + // std::ofstream _ofs; + // QNetworkAccessManager object for sending requests. + QNetworkAccessManager* manager; + + // the number of leds (needed when switching off) + + size_t panelCount; + /// Array of the pannel ids. + std::vector panelIds; + QByteArray get(QString host, QString token, QString route); + QByteArray putJson(QString url, QString json); + QByteArray changeMode(QString host, QString token, QString route); + /// + /// @param route + /// + /// @return the full URL of the request. + /// + QString getUrl(QString host, QString token, QString route); +};