mirror of
https://github.com/hyperion-project/hyperion.ng.git
synced 2023-10-10 13:36:59 +02:00
ed5455458b
* Handle Exceptions in main & Pythoninit * Have SSDPDiscover generic again * Have SSDPDiscover generic again * Change Info- to Debug logs as technical service messages * Nanoleaf - When switched on, ensure UDP mode * Include SQL Database in Cross-Compile instructions * Fix Clazy (QT code checker) and clang Warnings * Stop LedDevice:write for disabled device * Nanoleaf: Fix uint printfs * NanoLeaf: Fix indents to tabs * NanoLeaf - Add debug verbosity switches * Device switchability support, FileDevice with timestamp support * Nanoleaf Light Panels now support External Control V2 * Enhance LedDeviceFile by Timestamp + fix readyness * Stop color stream, if LedDevice disabled * Nanoleaf - remove switchability * Fix MultiColorAdjustment, if led-range is greater lednum * Fix logging * LedFileDevice/LedDevice - add testing support * New "Led Test" effect * LedDeviceFile - Add chrono include + Allow Led rewrites for testing * Stabilize Effects for LedDevices where latchtime = 0 * Update LedDeviceFile, allow latchtime = 0 * Distangle LinearColorSmoothing and LEDDevice, Fix Effect configuration updates * Updates LedDeviceFile - Initialize via Open * Updates LedDeviceNanoleaf - Initialize via Open, Remove throwing exceptions * Updates ProviderUDP - Remove throwing exceptions * Framebuffer - Use precise timer * TestSpi - Align to LedDevice updates * Pretty Print CrossCompileHowTo as markdown-file * Ensure that output is only written when LedDevice is ready * Align APA102 Device to new device staging * Logger - Remove clang warnings on extra semicolon * Devices SPI - Align to Device stages and methods * Fix cppcheck and clang findings * Add Code-Template for new Devices * Align devices to stages and methods, clean-up some code * Allow to reopen LedDevice without restart * Revert change "Remove Connect (PriorityMuxer::visiblePriorityChanged -> Hyperion::update) due to double writes" * Remove visiblePriorityChanged from LedDevice to decouple LedDevice from hyperion logic * Expose LedDevice getLedCount and align signedness
190 lines
4.9 KiB
C++
190 lines
4.9 KiB
C++
#include "LedDeviceFadeCandy.h"
|
|
|
|
static const signed MAX_NUM_LEDS = 10000; // OPC can handle 21845 leds - in theory, fadecandy device should handle 10000 leds
|
|
static const unsigned OPC_SET_PIXELS = 0; // OPC command codes
|
|
static const unsigned OPC_SYS_EX = 255; // OPC command codes
|
|
static const unsigned OPC_HEADER_SIZE = 4; // OPC header size
|
|
|
|
LedDeviceFadeCandy::LedDeviceFadeCandy(const QJsonObject &deviceConfig)
|
|
: LedDevice()
|
|
, _client(nullptr)
|
|
{
|
|
_devConfig = deviceConfig;
|
|
_deviceReady = false;
|
|
}
|
|
|
|
LedDeviceFadeCandy::~LedDeviceFadeCandy()
|
|
{
|
|
_client->deleteLater();
|
|
}
|
|
|
|
LedDevice* LedDeviceFadeCandy::construct(const QJsonObject &deviceConfig)
|
|
{
|
|
return new LedDeviceFadeCandy(deviceConfig);
|
|
}
|
|
|
|
bool LedDeviceFadeCandy::init(const QJsonObject &deviceConfig)
|
|
{
|
|
bool isInitOK = LedDevice::init(deviceConfig);
|
|
|
|
if ( isInitOK )
|
|
{
|
|
if (_ledCount > MAX_NUM_LEDS)
|
|
{
|
|
//Error(_log, "fadecandy/opc: Invalid attempt to write led values. Not more than %d leds are allowed.", MAX_NUM_LEDS);
|
|
QString errortext = QString ("More LED configured than allowed (%1)").arg(MAX_NUM_LEDS);
|
|
this->setInError(errortext);
|
|
isInitOK = false;
|
|
}
|
|
else
|
|
{
|
|
_host = deviceConfig["output"].toString("127.0.0.1");
|
|
_port = deviceConfig["port"].toInt(7890);
|
|
_channel = deviceConfig["channel"].toInt(0);
|
|
_gamma = deviceConfig["gamma"].toDouble(1.0);
|
|
_noDither = ! deviceConfig["dither"].toBool(false);
|
|
_noInterp = ! deviceConfig["interpolation"].toBool(false);
|
|
_manualLED = deviceConfig["manualLed"].toBool(false);
|
|
_ledOnOff = deviceConfig["ledOn"].toBool(false);
|
|
_setFcConfig = deviceConfig["setFcConfig"].toBool(false);
|
|
|
|
_whitePoint_r = 1.0;
|
|
_whitePoint_g = 1.0;
|
|
_whitePoint_b = 1.0;
|
|
|
|
const QJsonArray whitePointConfig = deviceConfig["whitePoint"].toArray();
|
|
if ( !whitePointConfig.isEmpty() && whitePointConfig.size() == 3 )
|
|
{
|
|
_whitePoint_r = whitePointConfig[0].toDouble() / 255.0;
|
|
_whitePoint_g = whitePointConfig[1].toDouble() / 255.0;
|
|
_whitePoint_b = whitePointConfig[2].toDouble() / 255.0;
|
|
}
|
|
|
|
_opc_data.resize( _ledRGBCount + OPC_HEADER_SIZE );
|
|
_opc_data[0] = _channel;
|
|
_opc_data[1] = OPC_SET_PIXELS;
|
|
_opc_data[2] = _ledRGBCount >> 8;
|
|
_opc_data[3] = _ledRGBCount & 0xff;
|
|
}
|
|
}
|
|
return isInitOK;
|
|
}
|
|
|
|
bool LedDeviceFadeCandy::initNetwork()
|
|
{
|
|
bool isInitOK = true;
|
|
|
|
// TODO: Add Network-Error handling
|
|
_client = new QTcpSocket(this);
|
|
return isInitOK;
|
|
}
|
|
|
|
int LedDeviceFadeCandy::open()
|
|
{
|
|
int retval = -1;
|
|
_deviceReady = false;
|
|
|
|
if ( init(_devConfig) )
|
|
{
|
|
if ( !initNetwork() )
|
|
{
|
|
this->setInError( "Network error!" );
|
|
}
|
|
else
|
|
{
|
|
_deviceReady = true;
|
|
setEnable(true);
|
|
retval = 0;
|
|
}
|
|
}
|
|
return retval;
|
|
}
|
|
|
|
void LedDeviceFadeCandy::close()
|
|
{
|
|
LedDevice::close();
|
|
|
|
// LedDevice specific closing activites
|
|
_client->close();
|
|
}
|
|
|
|
|
|
bool LedDeviceFadeCandy::isConnected()
|
|
{
|
|
return _client->state() == QAbstractSocket::ConnectedState;
|
|
}
|
|
|
|
bool LedDeviceFadeCandy::tryConnect()
|
|
{
|
|
if ( _client->state() == QAbstractSocket::UnconnectedState ) {
|
|
_client->connectToHost( _host, _port);
|
|
if ( _client->waitForConnected(1000) )
|
|
{
|
|
Info(_log,"fadecandy/opc: connected to %s:%i on channel %i", QSTRING_CSTR(_host), _port, _channel);
|
|
if (_setFcConfig)
|
|
{
|
|
sendFadeCandyConfiguration();
|
|
}
|
|
}
|
|
}
|
|
|
|
return isConnected();
|
|
}
|
|
|
|
int LedDeviceFadeCandy::write( const std::vector<ColorRgb> & ledValues )
|
|
{
|
|
uint idx = OPC_HEADER_SIZE;
|
|
for (const ColorRgb& color : ledValues)
|
|
{
|
|
_opc_data[idx ] = unsigned( color.red );
|
|
_opc_data[idx+1] = unsigned( color.green );
|
|
_opc_data[idx+2] = unsigned( color.blue );
|
|
idx += 3;
|
|
}
|
|
|
|
return ( transferData()<0 ? -1 : 0 );
|
|
}
|
|
|
|
int LedDeviceFadeCandy::transferData()
|
|
{
|
|
if (LedDevice::enabled())
|
|
if ( isConnected() || tryConnect() )
|
|
return _client->write( _opc_data, _opc_data.size() );
|
|
|
|
return -2;
|
|
}
|
|
|
|
int LedDeviceFadeCandy::sendSysEx(uint8_t systemId, uint8_t commandId, QByteArray msg)
|
|
{
|
|
if ( isConnected() )
|
|
{
|
|
QByteArray sysExData;
|
|
ssize_t data_size = msg.size() + 4;
|
|
sysExData.resize( 4 + OPC_HEADER_SIZE );
|
|
|
|
sysExData[0] = 0;
|
|
sysExData[1] = OPC_SYS_EX;
|
|
sysExData[2] = data_size >>8;
|
|
sysExData[3] = data_size &0xff;
|
|
sysExData[4] = systemId >>8;
|
|
sysExData[5] = systemId &0xff;
|
|
sysExData[6] = commandId >>8;
|
|
sysExData[7] = commandId &0xff;
|
|
|
|
sysExData += msg;
|
|
|
|
return _client->write( sysExData, sysExData.size() );
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
void LedDeviceFadeCandy::sendFadeCandyConfiguration()
|
|
{
|
|
Debug(_log, "send configuration to fadecandy");
|
|
QString data = "{\"gamma\": "+QString::number(_gamma,'g',4)+", \"whitepoint\": ["+QString::number(_whitePoint_r,'g',4)+", "+QString::number(_whitePoint_g,'g',4)+", "+QString::number(_whitePoint_b,'g',4)+"]}";
|
|
sendSysEx(1, 1, data.toLocal8Bit() );
|
|
|
|
char firmware_data = ((uint8_t)_noDither | ((uint8_t)_noInterp << 1) | ((uint8_t)_manualLED << 2) | ((uint8_t)_ledOnOff << 3) );
|
|
sendSysEx(1, 2, QByteArray(1,firmware_data) );
|
|
}
|