diff --git a/include/udplistener/UDPListener.h b/include/udplistener/UDPListener.h new file mode 100644 index 00000000..ad587691 --- /dev/null +++ b/include/udplistener/UDPListener.h @@ -0,0 +1,62 @@ +#pragma once + +// system includes +#include + +// Qt includes +#include +#include + +// Hyperion includes +#include + +class UDPClientConnection; + +/// +/// This class creates a UDP server which accepts connections from boblight clients. +/// +class UDPListener : public QObject +{ + Q_OBJECT + +public: + /// + /// UDPListener constructor + /// @param hyperion Hyperion instance + /// @param port port number on which to start listening for connections + /// + UDPListener(Hyperion * hyperion, const int priority, const int timeout, uint16_t port = 2801); + ~UDPListener(); + + /// + /// @return the port number on which this UDP listens for incoming connections + /// + uint16_t getPort() const; + +private slots: + /// + /// Slot which is called when a client tries to create a new connection + /// + void readPendingDatagrams(); + void processTheDatagram(const QByteArray * _datagram); + + +private: + /// Hyperion instance + Hyperion * _hyperion; + + /// The UDP server object + QUdpSocket * _server; + + /// List with open connections + QSet _openConnections; + + /// hyperion priority + int _priority; + + /// hyperion priority + int _timeout; + + /// The latest led color data + std::vector _ledColors; +}; diff --git a/libsrc/CMakeLists.txt b/libsrc/CMakeLists.txt index 2d109c02..4a8da206 100644 --- a/libsrc/CMakeLists.txt +++ b/libsrc/CMakeLists.txt @@ -9,6 +9,7 @@ add_subdirectory(jsonserver) add_subdirectory(protoserver) add_subdirectory(bonjour) add_subdirectory(boblightserver) +add_subdirectory(udplistener) add_subdirectory(leddevice) add_subdirectory(utils) add_subdirectory(xbmcvideochecker) diff --git a/libsrc/udplistener/CMakeLists.txt b/libsrc/udplistener/CMakeLists.txt new file mode 100644 index 00000000..9d7c007b --- /dev/null +++ b/libsrc/udplistener/CMakeLists.txt @@ -0,0 +1,32 @@ + +# Define the current source locations +set(CURRENT_HEADER_DIR ${CMAKE_SOURCE_DIR}/include/udplistener) +set(CURRENT_SOURCE_DIR ${CMAKE_SOURCE_DIR}/libsrc/udplistener) + +# Group the headers that go through the MOC compiler +set(UDPListener_QT_HEADERS + ${CURRENT_HEADER_DIR}/UDPListener.h +) + +set(UDPListener_HEADERS +) + +set(UDPListener_SOURCES + ${CURRENT_SOURCE_DIR}/UDPListener.cpp +) + +qt5_wrap_cpp(UDPListener_HEADERS_MOC ${UDPListener_QT_HEADERS}) + +add_library(udplistener + ${UDPListener_HEADERS} + ${UDPListener_QT_HEADERS} + ${UDPListener_SOURCES} + ${UDPListener_HEADERS_MOC} +) + +qt5_use_modules(udplistener Widgets) + +target_link_libraries(udplistener + hyperion + hyperion-utils + ${QT_LIBRARIES}) diff --git a/libsrc/udplistener/UDPListener.cpp b/libsrc/udplistener/UDPListener.cpp new file mode 100644 index 00000000..9dc06056 --- /dev/null +++ b/libsrc/udplistener/UDPListener.cpp @@ -0,0 +1,83 @@ +// system includes +#include + +// project includes +#include + +// hyperion util includes +#include "hyperion/ImageProcessorFactory.h" +#include "hyperion/ImageProcessor.h" +#include "utils/ColorRgb.h" +#include "HyperionConfig.h" + +UDPListener::UDPListener(Hyperion *hyperion, const int priority, const int timeout, uint16_t port) : + QObject(), + _hyperion(hyperion), + _server(), + _openConnections(), + _priority(priority), + _timeout(timeout), + _ledColors(hyperion->getLedCount(), ColorRgb::BLACK) + +{ + _server = new QUdpSocket(this); + if (!_server->bind(QHostAddress::Any, port)) + { + throw std::runtime_error("UDPLISTENER ERROR: server could not bind to port"); + } + + // Set trigger for incoming connections + connect(_server, SIGNAL(readyRead()), this, SLOT(readPendingDatagrams())); +} + +UDPListener::~UDPListener() +{ + // clear the current channel + _hyperion->clear(_priority); +} + +uint16_t UDPListener::getPort() const +{ + return _server->localPort(); +} + + +void UDPListener::readPendingDatagrams() +{ + while (_server->hasPendingDatagrams()) { + QByteArray datagram; + datagram.resize(_server->pendingDatagramSize()); + QHostAddress sender; + quint16 senderPort; + + _server->readDatagram(datagram.data(), datagram.size(), + &sender, &senderPort); + +// std::cout << "UDPLISTENER INFO: new packet from " << std::endl; + processTheDatagram(&datagram); + + } +} + + +void UDPListener::processTheDatagram(const QByteArray * datagram) +{ +// std::cout << "udp message: " << datagram->data() << std::endl; + + int packlen = datagram->size()/3; + int ledlen = _ledColors.size(); +// int maxled = std::min(datagram->size()/3, _ledColors.size()); + int maxled = std::min(packlen , ledlen); + + for (int ledIndex=0; ledIndex < maxled; ledIndex++) { + ColorRgb & rgb = _ledColors[ledIndex]; + rgb.red = datagram->at(ledIndex*3+0); + rgb.green = datagram->at(ledIndex*3+1); + rgb.blue = datagram->at(ledIndex*3+2); +// printf("%02x%02x%02x%02x ", ledIndex, rgb.red, rgb.green, rgb.blue); + } +// printf ("\n"); + + _hyperion->setColors(_priority, _ledColors, _timeout, -1); + +} diff --git a/src/hyperiond/CMakeLists.txt b/src/hyperiond/CMakeLists.txt index cae89651..3ee7d6ba 100644 --- a/src/hyperiond/CMakeLists.txt +++ b/src/hyperiond/CMakeLists.txt @@ -9,6 +9,7 @@ target_link_libraries(hyperiond effectengine jsonserver boblightserver + udplistener protoserver webconfig bonjour diff --git a/src/hyperiond/hyperiond.cpp b/src/hyperiond/hyperiond.cpp index 60d3922f..0b32e718 100644 --- a/src/hyperiond/hyperiond.cpp +++ b/src/hyperiond/hyperiond.cpp @@ -17,6 +17,7 @@ #include #include #include +#include #include "hyperiond.h" @@ -28,6 +29,7 @@ HyperionDaemon::HyperionDaemon(std::string configFile, QObject *parent) , _jsonServer(nullptr) , _protoServer(nullptr) , _boblightServer(nullptr) + , _udpListener(nullptr) , _v4l2Grabber(nullptr) , _dispmanx(nullptr) , _amlGrabber(nullptr) @@ -51,6 +53,7 @@ HyperionDaemon::~HyperionDaemon() delete _jsonServer; delete _protoServer; delete _boblightServer; + delete _udpListener; delete _webConfig; } @@ -217,6 +220,18 @@ void HyperionDaemon::startNetworkServices() Info(_log, "Boblight server created and started on port %d", _boblightServer->getPort()); } + // Create UDP listener if configuration is present + if (_config.isMember("udpListener")) + { + const Json::Value & udpListenerConfig = _config["udpListener"]; + _udpListener = new UDPListener(hyperion, + udpListenerConfig.get("priority",890).asInt(), + udpListenerConfig.get("timeout",10000).asInt(), + udpListenerConfig["port"].asUInt() + ); + Info(_log, "UDP listener created and started on port %d", _udpListener->getPort()); + } + // zeroconf const Json::Value & deviceConfig = _config["device"]; const std::string deviceName = deviceConfig.get("name", "").asString(); diff --git a/src/hyperiond/hyperiond.h b/src/hyperiond/hyperiond.h index fd1354d2..8ed6899c 100644 --- a/src/hyperiond/hyperiond.h +++ b/src/hyperiond/hyperiond.h @@ -39,6 +39,7 @@ #include #include #include +#include class HyperionDaemon : public QObject { @@ -67,6 +68,7 @@ private: JsonServer* _jsonServer; ProtoServer* _protoServer; BoblightServer* _boblightServer; + UDPListener* _udpListener; V4L2Wrapper* _v4l2Grabber; DispmanxWrapper* _dispmanx; AmlogicWrapper* _amlGrabber;