From 6f43fe11967489d17f0ecbc20fce685586474b85 Mon Sep 17 00:00:00 2001 From: penfold42 Date: Tue, 31 May 2016 07:58:31 +1000 Subject: [PATCH] New QT based udp driver (#662) * Removed -HUP so the default -TERM signal is sent instead. - hyperiond only listens for TERM and INT. HUP is often used to get an exe to reread its config Changed pgrep to add '-x' so it wont partial match on the exe name. - I have multiple instances with multiple hyperiond-instance1 names - this ensures the service script only kills the right process * reversing errant change to hyperion.systemd.sh * cleaned up a couple of compiler warnings * moved bitpair_to_byte initialiser to (hopefully) work with older GCC * compiler warning in udp driver removed some tabs in ws2812b.cpp * formatting - spaces to tabs * moved rpi_281x to tag sk6812-v1.0 * moving to my fork of rpi_281x * half way thru re merging the newudp support * Whoops.... dont know how it compiled before.. * Removed debugging that was commented out Former-commit-id: ac4330422f93f3d594dfcba5593759288298d25e --- libsrc/leddevice/CMakeLists.txt | 4 ++ libsrc/leddevice/LedDeviceFactory.cpp | 11 ++++ libsrc/leddevice/LedDeviceUdpRaw.cpp | 41 +++++++++++++ libsrc/leddevice/LedDeviceUdpRaw.h | 43 ++++++++++++++ libsrc/leddevice/LedUdpDevice.cpp | 85 +++++++++++++++++++++++++++ libsrc/leddevice/LedUdpDevice.h | 66 +++++++++++++++++++++ 6 files changed, 250 insertions(+) create mode 100644 libsrc/leddevice/LedDeviceUdpRaw.cpp create mode 100644 libsrc/leddevice/LedDeviceUdpRaw.h create mode 100644 libsrc/leddevice/LedUdpDevice.cpp create mode 100644 libsrc/leddevice/LedUdpDevice.h diff --git a/libsrc/leddevice/CMakeLists.txt b/libsrc/leddevice/CMakeLists.txt index efdbffa6..7d3ea06e 100755 --- a/libsrc/leddevice/CMakeLists.txt +++ b/libsrc/leddevice/CMakeLists.txt @@ -38,6 +38,8 @@ SET(Leddevice_HEADERS ${CURRENT_SOURCE_DIR}/LedDeviceFile.h ${CURRENT_SOURCE_DIR}/LedDeviceFadeCandy.h ${CURRENT_SOURCE_DIR}/LedDeviceUdp.h + ${CURRENT_SOURCE_DIR}/LedDeviceUdpRaw.h + ${CURRENT_SOURCE_DIR}/LedUdpDevice.h ${CURRENT_SOURCE_DIR}/LedDeviceHyperionUsbasp.h ${CURRENT_SOURCE_DIR}/LedDeviceTpm2.h ${CURRENT_SOURCE_DIR}/LedDeviceAtmo.h @@ -62,6 +64,8 @@ SET(Leddevice_SOURCES ${CURRENT_SOURCE_DIR}/LedDeviceFile.cpp ${CURRENT_SOURCE_DIR}/LedDeviceFadeCandy.cpp ${CURRENT_SOURCE_DIR}/LedDeviceUdp.cpp + ${CURRENT_SOURCE_DIR}/LedDeviceUdpRaw.cpp + ${CURRENT_SOURCE_DIR}/LedUdpDevice.cpp ${CURRENT_SOURCE_DIR}/LedDeviceHyperionUsbasp.cpp ${CURRENT_SOURCE_DIR}/LedDevicePhilipsHue.cpp ${CURRENT_SOURCE_DIR}/LedDeviceTpm2.cpp diff --git a/libsrc/leddevice/LedDeviceFactory.cpp b/libsrc/leddevice/LedDeviceFactory.cpp index 689ef91f..ed07249c 100755 --- a/libsrc/leddevice/LedDeviceFactory.cpp +++ b/libsrc/leddevice/LedDeviceFactory.cpp @@ -33,6 +33,7 @@ #include "LedDeviceFile.h" #include "LedDeviceFadeCandy.h" #include "LedDeviceUdp.h" +#include "LedDeviceUdpRaw.h" #include "LedDeviceHyperionUsbasp.h" #include "LedDevicePhilipsHue.h" #include "LedDeviceTpm2.h" @@ -318,6 +319,16 @@ LedDevice * LedDeviceFactory::construct(const Json::Value & deviceConfig) const unsigned maxPacket = deviceConfig["maxpacket"].asInt(); device = new LedDeviceUdp(output, rate, protocol, maxPacket); } + else if (type == "udpraw") + { + const std::string output = deviceConfig["output"].asString(); + const unsigned rate = deviceConfig["rate"].asInt(); + const unsigned latchtime = deviceConfig.get("latchtime",500000).asInt(); + + LedDeviceUdpRaw* deviceUdpRaw = new LedDeviceUdpRaw(output, rate, latchtime); + deviceUdpRaw->open(); + device = deviceUdpRaw; + } else if (type == "tpm2") { const std::string output = deviceConfig["output"].asString(); diff --git a/libsrc/leddevice/LedDeviceUdpRaw.cpp b/libsrc/leddevice/LedDeviceUdpRaw.cpp new file mode 100644 index 00000000..5880b2f9 --- /dev/null +++ b/libsrc/leddevice/LedDeviceUdpRaw.cpp @@ -0,0 +1,41 @@ + +// STL includes +#include +#include +#include + +// Linux includes +#include +#include + +// hyperion local includes +#include "LedDeviceUdpRaw.h" + +LedDeviceUdpRaw::LedDeviceUdpRaw(const std::string& outputDevice, const unsigned baudrate) : + LedUdpDevice(outputDevice, baudrate, 500000), + mLedCount(0) +{ + // empty +} + +LedDeviceUdpRaw::LedDeviceUdpRaw(const std::string& outputDevice, const unsigned baudrate, const unsigned latchTime) : + LedUdpDevice(outputDevice, baudrate, latchTime), + mLedCount(0) +{ + // empty +} + +int LedDeviceUdpRaw::write(const std::vector &ledValues) +{ + mLedCount = ledValues.size(); + + const unsigned dataLen = ledValues.size() * sizeof(ColorRgb); + const uint8_t * dataPtr = reinterpret_cast(ledValues.data()); + + return writeBytes(dataLen, dataPtr); +} + +int LedDeviceUdpRaw::switchOff() +{ + return write(std::vector(mLedCount, ColorRgb{0,0,0})); +} diff --git a/libsrc/leddevice/LedDeviceUdpRaw.h b/libsrc/leddevice/LedDeviceUdpRaw.h new file mode 100644 index 00000000..4ddf8098 --- /dev/null +++ b/libsrc/leddevice/LedDeviceUdpRaw.h @@ -0,0 +1,43 @@ +#pragma once + +// STL includes +#include + +// hyperion incluse +#include "LedUdpDevice.h" + +/// +/// Implementation of the LedDevice interface for writing to Ws2801 led device. +/// +class LedDeviceUdpRaw : public LedUdpDevice +{ +public: + /// + /// Constructs the LedDevice for a string containing leds of the type Ws2801 + /// + /// @param outputDevice The name of the output device (eg '/etc/SpiDev.0.0') + /// @param baudrate The used baudrate for writing to the output device + /// + LedDeviceUdpRaw(const std::string& outputDevice, + const unsigned baudrate); + + LedDeviceUdpRaw(const std::string& outputDevice, + const unsigned baudrate, + const unsigned latchTime); + + /// + /// Writes the led color values to the led-device + /// + /// @param ledValues The color-value per led + /// @return Zero on succes else negative + /// + virtual int write(const std::vector &ledValues); + + /// Switch the leds off + virtual int switchOff(); + +private: + + /// the number of leds (needed when switching off) + size_t mLedCount; +}; diff --git a/libsrc/leddevice/LedUdpDevice.cpp b/libsrc/leddevice/LedUdpDevice.cpp new file mode 100644 index 00000000..b8126592 --- /dev/null +++ b/libsrc/leddevice/LedUdpDevice.cpp @@ -0,0 +1,85 @@ + +// STL includes +#include +#include +#include + +// Linux includes +#include +#include + +#include +#include +#include + +// Local Hyperion includes +#include "LedUdpDevice.h" + + +LedUdpDevice::LedUdpDevice(const std::string& outputDevice, const unsigned baudrate, const int latchTime_ns) : + mDeviceName(outputDevice), + mBaudRate_Hz(baudrate), + mLatchTime_ns(latchTime_ns), + mFid(-1) +{ + udpSocket = new QUdpSocket(); + QString str = QString::fromStdString(mDeviceName); + QStringList _list = str.split(":"); + if (_list.size() != 2) { + printf ("ERROR: LedUdpDevice: Error parsing hostname:port\n"); + exit (-1); + } + QHostInfo info = QHostInfo::fromName(_list.at(0)); + if (!info.addresses().isEmpty()) { + _address = info.addresses().first(); + // use the first IP address + } + _port = _list.at(1).toInt(); +} + +LedUdpDevice::~LedUdpDevice() +{ +// close(mFid); +} + +int LedUdpDevice::open() +{ + udpSocket->bind(QHostAddress::Any, 7755); + + +/* + if (mFid < 0) + { + std::cerr << "Failed to open device('" << mDeviceName << "') " << std::endl; + return -1; + } +*/ + + return 0; +} + +int LedUdpDevice::writeBytes(const unsigned size, const uint8_t * data) +{ +/* + if (mFid < 0) + { + return -1; + } +*/ + +// int retVal = udpSocket->writeDatagram((const char *)data,size,QHostAddress::LocalHost,9998); + int retVal = udpSocket->writeDatagram((const char *)data,size,_address,_port); + + if (retVal == 0 && mLatchTime_ns > 0) + { + // The 'latch' time for latching the shifted-value into the leds + timespec latchTime; + latchTime.tv_sec = 0; + latchTime.tv_nsec = mLatchTime_ns; + + // Sleep to latch the leds (only if write succesfull) + nanosleep(&latchTime, NULL); + } + + return retVal; +} diff --git a/libsrc/leddevice/LedUdpDevice.h b/libsrc/leddevice/LedUdpDevice.h new file mode 100644 index 00000000..cd9e2463 --- /dev/null +++ b/libsrc/leddevice/LedUdpDevice.h @@ -0,0 +1,66 @@ +#pragma once + +#include + +// Linux-SPI includes +#include + +// Hyperion includes +#include + +/// +/// The LedUdpDevice implements an abstract base-class for LedDevices using the SPI-device. +/// +class LedUdpDevice : public LedDevice +{ +public: + /// + /// Constructs the LedDevice attached to a SPI-device + /// + /// @param[in] outputDevice The name of the output device (eg '/etc/UdpDev.0.0') + /// @param[in] baudrate The used baudrate for writing to the output device + /// @param[in] latchTime_ns The latch-time to latch in the values across the SPI-device (negative + /// means no latch required) [ns] + /// + LedUdpDevice(const std::string& outputDevice, const unsigned baudrate, const int latchTime_ns = -1); + + /// + /// Destructor of the LedDevice; closes the output device if it is open + /// + virtual ~LedUdpDevice(); + + /// + /// Opens and configures the output device + /// + /// @return Zero on succes else negative + /// + int open(); + +protected: + /// + /// Writes the given bytes/bits to the SPI-device and sleeps the latch time to ensure that the + /// values are latched. + /// + /// @param[in[ size The length of the data + /// @param[in] data The data + /// + /// @return Zero on succes else negative + /// + int writeBytes(const unsigned size, const uint8_t *data); + +private: + /// The name of the output device + const std::string mDeviceName; + /// The used baudrate of the output device + const int mBaudRate_Hz; + /// The time which the device should be untouched after a write + const int mLatchTime_ns; + + /// The File Identifier of the opened output device (or -1 if not opened) + int mFid; + /// + QUdpSocket *udpSocket; + QHostAddress _address; + quint16 _port; +}; +