2013-10-11 10:06:24 +02:00
|
|
|
// system includes
|
|
|
|
#include <stdexcept>
|
|
|
|
#include <cassert>
|
|
|
|
|
|
|
|
// stl includes
|
|
|
|
#include <iostream>
|
|
|
|
#include <sstream>
|
|
|
|
#include <iterator>
|
|
|
|
|
|
|
|
// Qt includes
|
2013-10-13 20:22:32 +02:00
|
|
|
#include <QRgb>
|
2013-10-11 10:06:24 +02:00
|
|
|
#include <QResource>
|
|
|
|
#include <QDateTime>
|
|
|
|
|
|
|
|
// hyperion util includes
|
|
|
|
#include "hyperion/ImageProcessorFactory.h"
|
|
|
|
#include "hyperion/ImageProcessor.h"
|
2013-11-11 10:00:37 +01:00
|
|
|
#include "utils/ColorRgb.h"
|
2013-10-11 10:06:24 +02:00
|
|
|
|
|
|
|
// project includes
|
|
|
|
#include "ProtoClientConnection.h"
|
|
|
|
|
2016-07-16 22:51:31 +02:00
|
|
|
ProtoClientConnection::ProtoClientConnection(QTcpSocket *socket)
|
|
|
|
: QObject()
|
|
|
|
, _socket(socket)
|
|
|
|
, _imageProcessor(ImageProcessorFactory::getInstance().newImageProcessor())
|
|
|
|
, _hyperion(Hyperion::getInstance())
|
|
|
|
, _receiveBuffer()
|
|
|
|
, _priority(-1)
|
2013-10-11 10:06:24 +02:00
|
|
|
{
|
|
|
|
// connect internal signals and slots
|
|
|
|
connect(_socket, SIGNAL(disconnected()), this, SLOT(socketClosed()));
|
|
|
|
connect(_socket, SIGNAL(readyRead()), this, SLOT(readData()));
|
2016-12-30 13:58:25 +01:00
|
|
|
connect(_hyperion, SIGNAL(imageToLedsMappingChanged(int)), _imageProcessor, SLOT(setLedMappingType(int)));
|
|
|
|
|
2016-07-16 22:51:31 +02:00
|
|
|
_priorityChannelName = "proto@"+ _socket->peerAddress().toString().toStdString();
|
2013-10-11 10:06:24 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
ProtoClientConnection::~ProtoClientConnection()
|
|
|
|
{
|
|
|
|
delete _socket;
|
|
|
|
}
|
|
|
|
|
|
|
|
void ProtoClientConnection::readData()
|
|
|
|
{
|
|
|
|
_receiveBuffer += _socket->readAll();
|
|
|
|
|
|
|
|
// check if we can read a message size
|
|
|
|
if (_receiveBuffer.size() <= 4)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// read the message size
|
|
|
|
uint32_t messageSize =
|
|
|
|
((_receiveBuffer[0]<<24) & 0xFF000000) |
|
|
|
|
((_receiveBuffer[1]<<16) & 0x00FF0000) |
|
|
|
|
((_receiveBuffer[2]<< 8) & 0x0000FF00) |
|
|
|
|
((_receiveBuffer[3] ) & 0x000000FF);
|
|
|
|
|
|
|
|
// check if we can read a complete message
|
|
|
|
if ((uint32_t) _receiveBuffer.size() < messageSize + 4)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// read a message
|
|
|
|
proto::HyperionRequest message;
|
2013-10-13 17:58:41 +02:00
|
|
|
if (!message.ParseFromArray(_receiveBuffer.data() + 4, messageSize))
|
2013-10-11 10:06:24 +02:00
|
|
|
{
|
2013-10-13 17:58:41 +02:00
|
|
|
sendErrorReply("Unable to parse message");
|
2013-10-11 10:06:24 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// handle the message
|
|
|
|
handleMessage(message);
|
|
|
|
|
|
|
|
// remove message data from buffer
|
|
|
|
_receiveBuffer = _receiveBuffer.mid(messageSize + 4);
|
|
|
|
}
|
|
|
|
|
|
|
|
void ProtoClientConnection::socketClosed()
|
|
|
|
{
|
2016-07-16 22:51:31 +02:00
|
|
|
_hyperion->unRegisterPriority(_priorityChannelName);
|
2013-10-11 10:06:24 +02:00
|
|
|
emit connectionClosed(this);
|
|
|
|
}
|
|
|
|
|
2016-06-07 23:12:18 +02:00
|
|
|
void ProtoClientConnection::setGrabbingMode(const GrabbingMode mode)
|
|
|
|
{
|
|
|
|
int grabbing_mode = (int)mode;
|
|
|
|
proto::HyperionReply gMode;
|
|
|
|
|
|
|
|
// create proto message
|
|
|
|
gMode.set_type(proto::HyperionReply::GRABBING);
|
|
|
|
gMode.set_grabbing(grabbing_mode);
|
|
|
|
|
|
|
|
// send message
|
|
|
|
sendMessage(gMode);
|
|
|
|
}
|
|
|
|
|
|
|
|
void ProtoClientConnection::setVideoMode(const VideoMode videoMode)
|
|
|
|
{
|
|
|
|
int video_Mode = (int)videoMode;
|
|
|
|
proto::HyperionReply vMode;
|
|
|
|
|
|
|
|
// create proto message
|
|
|
|
vMode.set_type(proto::HyperionReply::VIDEO);
|
|
|
|
vMode.set_grabbing(video_Mode);
|
|
|
|
|
|
|
|
// send message
|
|
|
|
sendMessage(vMode);
|
|
|
|
}
|
|
|
|
|
2013-10-11 10:06:24 +02:00
|
|
|
void ProtoClientConnection::handleMessage(const proto::HyperionRequest & message)
|
|
|
|
{
|
2016-02-08 16:56:23 +01:00
|
|
|
// forward messages
|
2016-02-15 18:25:18 +01:00
|
|
|
emit newMessage(&message);
|
2016-02-08 16:56:23 +01:00
|
|
|
|
2016-07-16 22:51:31 +02:00
|
|
|
int prevPriority = _priority;
|
2013-10-11 10:06:24 +02:00
|
|
|
switch (message.command())
|
|
|
|
{
|
|
|
|
case proto::HyperionRequest::COLOR:
|
|
|
|
if (!message.HasExtension(proto::ColorRequest::colorRequest))
|
|
|
|
{
|
|
|
|
sendErrorReply("Received COLOR command without ColorRequest");
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
handleColorCommand(message.GetExtension(proto::ColorRequest::colorRequest));
|
|
|
|
break;
|
|
|
|
case proto::HyperionRequest::IMAGE:
|
|
|
|
if (!message.HasExtension(proto::ImageRequest::imageRequest))
|
|
|
|
{
|
|
|
|
sendErrorReply("Received IMAGE command without ImageRequest");
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
handleImageCommand(message.GetExtension(proto::ImageRequest::imageRequest));
|
|
|
|
break;
|
|
|
|
case proto::HyperionRequest::CLEAR:
|
|
|
|
if (!message.HasExtension(proto::ClearRequest::clearRequest))
|
|
|
|
{
|
|
|
|
sendErrorReply("Received CLEAR command without ClearRequest");
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
handleClearCommand(message.GetExtension(proto::ClearRequest::clearRequest));
|
|
|
|
break;
|
|
|
|
case proto::HyperionRequest::CLEARALL:
|
|
|
|
handleClearallCommand();
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
handleNotImplemented();
|
|
|
|
}
|
2016-07-16 22:51:31 +02:00
|
|
|
|
|
|
|
if (prevPriority != _priority)
|
|
|
|
{
|
|
|
|
_hyperion->registerPriority(_priorityChannelName, _priority);
|
|
|
|
prevPriority = _priority;
|
|
|
|
}
|
2013-10-11 10:06:24 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void ProtoClientConnection::handleColorCommand(const proto::ColorRequest &message)
|
|
|
|
{
|
|
|
|
// extract parameters
|
2016-07-16 22:51:31 +02:00
|
|
|
_priority = message.priority();
|
2013-10-11 10:06:24 +02:00
|
|
|
int duration = message.has_duration() ? message.duration() : -1;
|
2013-11-11 10:00:37 +01:00
|
|
|
ColorRgb color;
|
2013-10-13 20:22:32 +02:00
|
|
|
color.red = qRed(message.rgbcolor());
|
|
|
|
color.green = qGreen(message.rgbcolor());
|
|
|
|
color.blue = qBlue(message.rgbcolor());
|
2013-10-11 10:06:24 +02:00
|
|
|
|
|
|
|
// set output
|
2016-07-16 22:51:31 +02:00
|
|
|
_hyperion->setColor(_priority, color, duration);
|
2013-10-11 10:06:24 +02:00
|
|
|
|
|
|
|
// send reply
|
|
|
|
sendSuccessReply();
|
|
|
|
}
|
|
|
|
|
|
|
|
void ProtoClientConnection::handleImageCommand(const proto::ImageRequest &message)
|
|
|
|
{
|
|
|
|
// extract parameters
|
2016-07-16 22:51:31 +02:00
|
|
|
_priority = message.priority();
|
2013-10-11 10:06:24 +02:00
|
|
|
int duration = message.has_duration() ? message.duration() : -1;
|
|
|
|
int width = message.imagewidth();
|
|
|
|
int height = message.imageheight();
|
|
|
|
const std::string & imageData = message.imagedata();
|
|
|
|
|
|
|
|
// check consistency of the size of the received data
|
|
|
|
if ((int) imageData.size() != width*height*3)
|
|
|
|
{
|
|
|
|
sendErrorReply("Size of image data does not match with the width and height");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// set width and height of the image processor
|
|
|
|
_imageProcessor->setSize(width, height);
|
|
|
|
|
2013-11-11 10:00:37 +01:00
|
|
|
// create ImageRgb
|
|
|
|
Image<ColorRgb> image(width, height);
|
2013-10-11 10:06:24 +02:00
|
|
|
memcpy(image.memptr(), imageData.c_str(), imageData.size());
|
|
|
|
|
|
|
|
// process the image
|
2013-11-11 10:00:37 +01:00
|
|
|
std::vector<ColorRgb> ledColors = _imageProcessor->process(image);
|
2016-07-16 22:51:31 +02:00
|
|
|
_hyperion->setColors(_priority, ledColors, duration);
|
2016-12-30 20:18:41 +01:00
|
|
|
_hyperion->setImage(_priority, image, duration);
|
2013-10-11 10:06:24 +02:00
|
|
|
|
|
|
|
// send reply
|
|
|
|
sendSuccessReply();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void ProtoClientConnection::handleClearCommand(const proto::ClearRequest &message)
|
|
|
|
{
|
|
|
|
// extract parameters
|
2016-07-16 22:51:31 +02:00
|
|
|
_priority = message.priority();
|
2013-10-11 10:06:24 +02:00
|
|
|
|
|
|
|
// clear priority
|
2016-07-16 22:51:31 +02:00
|
|
|
_hyperion->clear(_priority);
|
|
|
|
_hyperion->unRegisterPriority(_priorityChannelName);
|
2013-10-11 10:06:24 +02:00
|
|
|
// send reply
|
|
|
|
sendSuccessReply();
|
|
|
|
}
|
|
|
|
|
|
|
|
void ProtoClientConnection::handleClearallCommand()
|
|
|
|
{
|
|
|
|
// clear priority
|
|
|
|
_hyperion->clearall();
|
|
|
|
|
|
|
|
// send reply
|
|
|
|
sendSuccessReply();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void ProtoClientConnection::handleNotImplemented()
|
|
|
|
{
|
|
|
|
sendErrorReply("Command not implemented");
|
|
|
|
}
|
|
|
|
|
|
|
|
void ProtoClientConnection::sendMessage(const google::protobuf::Message &message)
|
|
|
|
{
|
|
|
|
std::string serializedReply = message.SerializeAsString();
|
|
|
|
uint32_t size = serializedReply.size();
|
|
|
|
uint8_t sizeData[] = {uint8_t(size >> 24), uint8_t(size >> 16), uint8_t(size >> 8), uint8_t(size)};
|
|
|
|
_socket->write((const char *) sizeData, sizeof(sizeData));
|
|
|
|
_socket->write(serializedReply.data(), serializedReply.length());
|
|
|
|
_socket->flush();
|
|
|
|
}
|
|
|
|
|
|
|
|
void ProtoClientConnection::sendSuccessReply()
|
|
|
|
{
|
|
|
|
// create reply
|
|
|
|
proto::HyperionReply reply;
|
2016-06-07 23:12:18 +02:00
|
|
|
reply.set_type(proto::HyperionReply::REPLY);
|
2013-10-11 10:06:24 +02:00
|
|
|
reply.set_success(true);
|
|
|
|
|
|
|
|
// send reply
|
|
|
|
sendMessage(reply);
|
|
|
|
}
|
|
|
|
|
|
|
|
void ProtoClientConnection::sendErrorReply(const std::string &error)
|
|
|
|
{
|
|
|
|
// create reply
|
|
|
|
proto::HyperionReply reply;
|
2016-06-07 23:12:18 +02:00
|
|
|
reply.set_type(proto::HyperionReply::REPLY);
|
2013-10-11 10:06:24 +02:00
|
|
|
reply.set_success(false);
|
|
|
|
reply.set_error(error);
|
|
|
|
|
|
|
|
// send reply
|
|
|
|
sendMessage(reply);
|
|
|
|
}
|