2013-11-08 22:18:10 +01:00
|
|
|
// system includes
|
|
|
|
#include <stdexcept>
|
|
|
|
#include <cassert>
|
|
|
|
#include <iomanip>
|
|
|
|
#include <cstdio>
|
|
|
|
|
|
|
|
// stl includes
|
|
|
|
#include <iostream>
|
|
|
|
#include <sstream>
|
|
|
|
#include <iterator>
|
|
|
|
|
|
|
|
// Qt includes
|
|
|
|
#include <QResource>
|
|
|
|
#include <QDateTime>
|
2017-03-01 15:23:53 +01:00
|
|
|
#include <QHostInfo>
|
2013-11-08 22:18:10 +01:00
|
|
|
|
|
|
|
// hyperion util includes
|
2018-12-28 18:12:45 +01:00
|
|
|
#include <hyperion/ImageProcessor.h>
|
2016-06-12 22:27:24 +02:00
|
|
|
#include "HyperionConfig.h"
|
2018-12-28 18:12:45 +01:00
|
|
|
#include <hyperion/Hyperion.h>
|
2013-11-08 22:18:10 +01:00
|
|
|
|
|
|
|
// project includes
|
|
|
|
#include "BoblightClientConnection.h"
|
|
|
|
|
2018-12-28 18:12:45 +01:00
|
|
|
BoblightClientConnection::BoblightClientConnection(Hyperion* hyperion, QTcpSocket *socket, const int priority)
|
2016-06-27 22:43:43 +02:00
|
|
|
: QObject()
|
|
|
|
, _locale(QLocale::C)
|
|
|
|
, _socket(socket)
|
2018-12-28 18:12:45 +01:00
|
|
|
, _imageProcessor(hyperion->getImageProcessor())
|
|
|
|
, _hyperion(hyperion)
|
2016-06-27 22:43:43 +02:00
|
|
|
, _receiveBuffer()
|
|
|
|
, _priority(priority)
|
2018-12-28 18:12:45 +01:00
|
|
|
, _ledColors(hyperion->getLedCount(), ColorRgb::BLACK)
|
2016-06-27 22:43:43 +02:00
|
|
|
, _log(Logger::getInstance("BOBLIGHT"))
|
2017-03-01 15:23:53 +01:00
|
|
|
, _clientAddress(QHostInfo::fromName(socket->peerAddress().toString()).hostName())
|
2013-11-08 22:18:10 +01:00
|
|
|
{
|
|
|
|
// initalize the locale. Start with the default C-locale
|
|
|
|
_locale.setNumberOptions(QLocale::OmitGroupSeparator | QLocale::RejectGroupSeparator);
|
|
|
|
|
|
|
|
// connect internal signals and slots
|
|
|
|
connect(_socket, SIGNAL(disconnected()), this, SLOT(socketClosed()));
|
|
|
|
connect(_socket, SIGNAL(readyRead()), this, SLOT(readData()));
|
|
|
|
}
|
|
|
|
|
|
|
|
BoblightClientConnection::~BoblightClientConnection()
|
|
|
|
{
|
|
|
|
if (_priority < 255)
|
|
|
|
{
|
|
|
|
// clear the current channel
|
|
|
|
_hyperion->clear(_priority);
|
|
|
|
_priority = 255;
|
|
|
|
}
|
|
|
|
|
|
|
|
delete _socket;
|
|
|
|
}
|
|
|
|
|
|
|
|
void BoblightClientConnection::readData()
|
|
|
|
{
|
|
|
|
_receiveBuffer += _socket->readAll();
|
|
|
|
|
|
|
|
int bytes = _receiveBuffer.indexOf('\n') + 1;
|
|
|
|
while(bytes > 0)
|
|
|
|
{
|
|
|
|
// create message string (strip the newline)
|
2016-01-06 17:31:23 +01:00
|
|
|
QString message = QString::fromLatin1(_receiveBuffer.data(), bytes-1);
|
2013-11-08 22:18:10 +01:00
|
|
|
// remove message data from buffer
|
|
|
|
_receiveBuffer = _receiveBuffer.mid(bytes);
|
|
|
|
|
2015-12-14 00:15:15 +01:00
|
|
|
// handle trimmed message
|
|
|
|
handleMessage(message.trimmed());
|
2013-11-08 22:18:10 +01:00
|
|
|
|
2013-11-09 10:33:16 +01:00
|
|
|
// drop messages if the buffer is too full
|
|
|
|
if (_receiveBuffer.size() > 100*1024)
|
|
|
|
{
|
2016-06-27 22:43:43 +02:00
|
|
|
Debug(_log, "server drops messages (buffer full)");
|
2013-11-09 10:33:16 +01:00
|
|
|
_receiveBuffer.clear();
|
|
|
|
}
|
|
|
|
|
2013-11-08 22:18:10 +01:00
|
|
|
// try too look up '\n' again
|
|
|
|
bytes = _receiveBuffer.indexOf('\n') + 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void BoblightClientConnection::socketClosed()
|
|
|
|
{
|
|
|
|
if (_priority < 255)
|
|
|
|
{
|
|
|
|
// clear the current channel
|
|
|
|
_hyperion->clear(_priority);
|
|
|
|
_priority = 255;
|
|
|
|
}
|
|
|
|
|
|
|
|
emit connectionClosed(this);
|
|
|
|
}
|
|
|
|
|
|
|
|
void BoblightClientConnection::handleMessage(const QString & message)
|
|
|
|
{
|
|
|
|
//std::cout << "boblight message: " << message.toStdString() << std::endl;
|
|
|
|
|
|
|
|
QStringList messageParts = message.split(" ", QString::SkipEmptyParts);
|
|
|
|
|
|
|
|
if (messageParts.size() > 0)
|
|
|
|
{
|
|
|
|
if (messageParts[0] == "hello")
|
|
|
|
{
|
|
|
|
sendMessage("hello\n");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
else if (messageParts[0] == "ping")
|
|
|
|
{
|
|
|
|
sendMessage("ping 1\n");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
else if (messageParts[0] == "get" && messageParts.size() > 1)
|
|
|
|
{
|
|
|
|
if (messageParts[1] == "version")
|
|
|
|
{
|
|
|
|
sendMessage("version 5\n");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
else if (messageParts[1] == "lights")
|
|
|
|
{
|
|
|
|
sendLightMessage();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (messageParts[0] == "set" && messageParts.size() > 2)
|
|
|
|
{
|
|
|
|
if (messageParts.size() > 3 && messageParts[1] == "light")
|
|
|
|
{
|
|
|
|
bool rc;
|
|
|
|
unsigned ledIndex = messageParts[2].toUInt(&rc);
|
|
|
|
if (rc && ledIndex < _ledColors.size())
|
|
|
|
{
|
|
|
|
if (messageParts[3] == "rgb" && messageParts.size() == 7)
|
|
|
|
{
|
2015-12-14 00:23:53 +01:00
|
|
|
// replace decimal comma with decimal point
|
|
|
|
messageParts[4].replace(',', '.');
|
|
|
|
messageParts[5].replace(',', '.');
|
|
|
|
messageParts[6].replace(',', '.');
|
|
|
|
|
2013-11-08 22:18:10 +01:00
|
|
|
bool rc1, rc2, rc3;
|
2013-12-12 23:12:22 +01:00
|
|
|
uint8_t red = qMax(0, qMin(255, int(255 * messageParts[4].toFloat(&rc1))));
|
|
|
|
|
2015-12-14 00:23:53 +01:00
|
|
|
// check for correct locale should not be needed anymore - please check!
|
2013-11-08 22:18:10 +01:00
|
|
|
if (!rc1)
|
|
|
|
{
|
|
|
|
// maybe a locale issue. switch to a locale with a comma instead of a dot as decimal seperator (or vice versa)
|
|
|
|
_locale = QLocale((_locale.decimalPoint() == QChar('.')) ? QLocale::Dutch : QLocale::C);
|
|
|
|
_locale.setNumberOptions(QLocale::OmitGroupSeparator | QLocale::RejectGroupSeparator);
|
|
|
|
|
|
|
|
// try again
|
2013-12-12 23:12:22 +01:00
|
|
|
red = qMax(0, qMin(255, int(255 * messageParts[4].toFloat(&rc1))));
|
2013-11-08 22:18:10 +01:00
|
|
|
}
|
|
|
|
|
2013-12-18 21:02:17 +01:00
|
|
|
uint8_t green = qMax(0, qMin(255, int(255 * messageParts[5].toFloat(&rc2))));
|
|
|
|
uint8_t blue = qMax(0, qMin(255, int(255 * messageParts[6].toFloat(&rc3))));
|
2013-11-08 22:18:10 +01:00
|
|
|
|
|
|
|
if (rc1 && rc2 && rc3)
|
|
|
|
{
|
2013-11-11 10:00:37 +01:00
|
|
|
ColorRgb & rgb = _ledColors[ledIndex];
|
2013-11-08 22:18:10 +01:00
|
|
|
rgb.red = red;
|
|
|
|
rgb.green = green;
|
|
|
|
rgb.blue = blue;
|
2013-12-12 23:12:22 +01:00
|
|
|
|
|
|
|
// send current color values to hyperion if this is the last led assuming leds values are send in order of id
|
|
|
|
if ((ledIndex == _ledColors.size() -1) && _priority < 255)
|
|
|
|
{
|
2018-12-27 23:11:32 +01:00
|
|
|
_hyperion->setInput(_priority, _ledColors);
|
2013-12-12 23:12:22 +01:00
|
|
|
}
|
|
|
|
|
2013-11-08 22:18:10 +01:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if(messageParts[3] == "speed" ||
|
2017-03-01 15:23:53 +01:00
|
|
|
messageParts[3] == "interpolation" ||
|
|
|
|
messageParts[3] == "use" ||
|
|
|
|
messageParts[3] == "singlechange")
|
2013-11-08 22:18:10 +01:00
|
|
|
{
|
|
|
|
// these message are ignored by Hyperion
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (messageParts.size() == 3 && messageParts[1] == "priority")
|
|
|
|
{
|
|
|
|
bool rc;
|
|
|
|
int prio = messageParts[2].toInt(&rc);
|
|
|
|
if (rc && prio != _priority)
|
|
|
|
{
|
|
|
|
if (_priority < 255)
|
|
|
|
{
|
|
|
|
// clear the current channel
|
|
|
|
_hyperion->clear(_priority);
|
2019-05-26 14:25:37 +02:00
|
|
|
|
|
|
|
// register new priority
|
|
|
|
_hyperion->registerInput(prio, hyperion::COMP_BOBLIGHTSERVER, QString("Boblight@%1").arg(_socket->peerAddress().toString()));
|
2013-11-08 22:18:10 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
_priority = prio;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (messageParts[0] == "sync")
|
|
|
|
{
|
|
|
|
// send current color values to hyperion
|
|
|
|
if (_priority < 255)
|
|
|
|
{
|
2018-12-27 23:11:32 +01:00
|
|
|
_hyperion->setInput(_priority, _ledColors);
|
2013-11-08 22:18:10 +01:00
|
|
|
}
|
2013-11-09 10:33:16 +01:00
|
|
|
return;
|
2013-11-08 22:18:10 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-03-01 15:23:53 +01:00
|
|
|
Debug(_log, "unknown boblight message: %s", QSTRING_CSTR(message));
|
2013-11-08 22:18:10 +01:00
|
|
|
}
|
|
|
|
|
2017-03-01 15:23:53 +01:00
|
|
|
void BoblightClientConnection::sendMessage(const QByteArray & message)
|
2013-11-08 22:18:10 +01:00
|
|
|
{
|
|
|
|
//std::cout << "send boblight message: " << message;
|
2017-03-01 15:23:53 +01:00
|
|
|
_socket->write(message);
|
2013-11-08 22:18:10 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
void BoblightClientConnection::sendLightMessage()
|
|
|
|
{
|
|
|
|
char buffer[256];
|
2017-03-01 15:23:53 +01:00
|
|
|
|
2013-11-08 22:18:10 +01:00
|
|
|
int n = snprintf(buffer, sizeof(buffer), "lights %d\n", _hyperion->getLedCount());
|
2017-03-01 15:23:53 +01:00
|
|
|
sendMessage(QByteArray(buffer, n));
|
2013-11-08 22:18:10 +01:00
|
|
|
|
2018-12-28 18:12:45 +01:00
|
|
|
double h0, h1, v0, v1;
|
2013-11-08 22:18:10 +01:00
|
|
|
for (unsigned i = 0; i < _hyperion->getLedCount(); ++i)
|
|
|
|
{
|
2018-12-28 18:12:45 +01:00
|
|
|
_imageProcessor->getScanParameters(i, h0, h1, v0, v1);
|
|
|
|
n = snprintf(buffer, sizeof(buffer), "light %03d scan %f %f %f %f\n", i, 100*v0, 100*v1, 100*h0, 100*h1);
|
|
|
|
sendMessage(QByteArray(buffer, n));
|
2013-11-08 22:18:10 +01:00
|
|
|
}
|
|
|
|
}
|