mirror of
https://github.com/hyperion-project/hyperion.ng.git
synced 2025-03-01 10:33:28 +00:00
Disentangle LedDevice/LinearColorSmoothing, Bug Fixes & Test support (#654)
* 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
This commit is contained in:
@@ -6,6 +6,8 @@
|
||||
#include <QStringList>
|
||||
#include <QDir>
|
||||
#include <QDateTime>
|
||||
#include <QEventLoop>
|
||||
#include <QTimer>
|
||||
|
||||
#include "hyperion/Hyperion.h"
|
||||
#include <utils/JsonUtils.h>
|
||||
@@ -15,32 +17,62 @@ LedDevice::LedDevice(const QJsonObject& config, QObject* parent)
|
||||
, _devConfig(config)
|
||||
, _log(Logger::getInstance("LEDDEVICE"))
|
||||
, _ledBuffer(0)
|
||||
, _deviceReady(true)
|
||||
, _refresh_timer()
|
||||
, _deviceReady(false)
|
||||
, _deviceInError(false)
|
||||
, _refresh_timer(new QTimer(this))
|
||||
, _refresh_timer_interval(0)
|
||||
, _last_write_time(QDateTime::currentMSecsSinceEpoch())
|
||||
, _latchTime_ms(0)
|
||||
, _componentRegistered(false)
|
||||
, _enabled(true)
|
||||
, _enabled(false)
|
||||
, _refresh_enabled (false)
|
||||
{
|
||||
// setup timer
|
||||
_refresh_timer.setInterval(0);
|
||||
connect(&_refresh_timer, SIGNAL(timeout()), this, SLOT(rewriteLeds()));
|
||||
// setup refreshTimer
|
||||
_refresh_timer->setTimerType(Qt::PreciseTimer);
|
||||
_refresh_timer->setInterval( _refresh_timer_interval );
|
||||
connect(_refresh_timer, SIGNAL(timeout()), this, SLOT(rewriteLeds()));
|
||||
}
|
||||
|
||||
LedDevice::~LedDevice()
|
||||
{
|
||||
|
||||
_refresh_timer->deleteLater();
|
||||
}
|
||||
|
||||
// dummy implemention
|
||||
int LedDevice::open()
|
||||
{
|
||||
setEnable (true);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void LedDevice::setInError(const QString& errorMsg)
|
||||
{
|
||||
_deviceInError = true;
|
||||
_deviceReady = false;
|
||||
_enabled = false;
|
||||
this->stopRefreshTimer();
|
||||
|
||||
Error(_log, "Device disabled, device '%s' signals error: '%s'", QSTRING_CSTR(_activeDeviceType), QSTRING_CSTR(errorMsg));
|
||||
emit enableStateChanged(_enabled);
|
||||
}
|
||||
|
||||
void LedDevice::close()
|
||||
{
|
||||
switchOff();
|
||||
this->stopRefreshTimer();
|
||||
}
|
||||
|
||||
void LedDevice::setEnable(bool enable)
|
||||
{
|
||||
if (!_deviceReady && enable)
|
||||
{
|
||||
Debug(_log, "Device '%s' was not ready! Trying to re-open.", QSTRING_CSTR(_activeDeviceType));
|
||||
if ( open() < 0 )
|
||||
{
|
||||
Error(_log, "Device '%s' cannot be enabled, as it is not ready!", QSTRING_CSTR(_activeDeviceType));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// emit signal when state changed
|
||||
if (_enabled != enable)
|
||||
{
|
||||
@@ -62,7 +94,7 @@ void LedDevice::setEnable(bool enable)
|
||||
_enabled = enable;
|
||||
}
|
||||
|
||||
void LedDevice::setActiveDeviceType(QString deviceType)
|
||||
void LedDevice::setActiveDeviceType(const QString& deviceType)
|
||||
{
|
||||
_activeDeviceType = deviceType;
|
||||
}
|
||||
@@ -71,50 +103,100 @@ bool LedDevice::init(const QJsonObject &deviceConfig)
|
||||
{
|
||||
_colorOrder = deviceConfig["colorOrder"].toString("RGB");
|
||||
_activeDeviceType = deviceConfig["type"].toString("file").toLower();
|
||||
setLedCount(deviceConfig["currentLedCount"].toInt(1)); // property injected to reflect real led count
|
||||
setLedCount(static_cast<unsigned int>( deviceConfig["currentLedCount"].toInt(1) )); // property injected to reflect real led count
|
||||
|
||||
_latchTime_ms = deviceConfig["latchTime"].toInt(_latchTime_ms);
|
||||
_refresh_timer.setInterval( deviceConfig["rewriteTime"].toInt( _refresh_timer_interval) );
|
||||
if (_refresh_timer.interval() <= (signed)_latchTime_ms )
|
||||
_latchTime_ms =deviceConfig["latchTime"].toInt( _latchTime_ms );
|
||||
_refresh_timer_interval = deviceConfig["rewriteTime"].toInt( _refresh_timer_interval);
|
||||
|
||||
if ( _refresh_timer_interval > 0 )
|
||||
{
|
||||
Warning(_log, "latchTime(%d) is bigger/equal rewriteTime(%d)", _refresh_timer.interval(), _latchTime_ms);
|
||||
_refresh_timer.setInterval(_latchTime_ms+10);
|
||||
}
|
||||
_refresh_enabled = true;
|
||||
|
||||
if (_refresh_timer_interval <= _latchTime_ms )
|
||||
{
|
||||
int new_refresh_timer_interval = _latchTime_ms + 10;
|
||||
Warning(_log, "latchTime(%d) is bigger/equal rewriteTime(%d), set rewriteTime to %dms", _latchTime_ms, _refresh_timer_interval, new_refresh_timer_interval);
|
||||
_refresh_timer_interval = new_refresh_timer_interval;
|
||||
_refresh_timer->setInterval( _refresh_timer_interval );
|
||||
}
|
||||
|
||||
//Debug(_log, "Refresh interval = %dms",_refresh_timer_interval );
|
||||
_refresh_timer->setInterval( _refresh_timer_interval );
|
||||
|
||||
_last_write_time = QDateTime::currentMSecsSinceEpoch();
|
||||
|
||||
this->startRefreshTimer();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
int LedDevice::setLedValues(const std::vector<ColorRgb>& ledValues)
|
||||
void LedDevice::startRefreshTimer()
|
||||
{
|
||||
if ( _deviceReady)
|
||||
{
|
||||
_refresh_timer->start();
|
||||
}
|
||||
}
|
||||
|
||||
void LedDevice::stopRefreshTimer()
|
||||
{
|
||||
_refresh_timer->stop();
|
||||
}
|
||||
|
||||
int LedDevice::updateLeds(const std::vector<ColorRgb>& ledValues)
|
||||
{
|
||||
int retval = 0;
|
||||
if (!_deviceReady || !_enabled)
|
||||
if ( !_deviceReady )
|
||||
{
|
||||
std::cout << "LedDevice::updateLeds(), LedDevice NOT ready!" << std::endl;
|
||||
return -1;
|
||||
|
||||
|
||||
// restart the timer
|
||||
if (_refresh_timer.interval() > 0)
|
||||
{
|
||||
_refresh_timer.start();
|
||||
}
|
||||
|
||||
if (_latchTime_ms == 0 || QDateTime::currentMSecsSinceEpoch()-_last_write_time >= _latchTime_ms)
|
||||
else
|
||||
{
|
||||
_ledValues = ledValues;
|
||||
retval = write(ledValues);
|
||||
_last_write_time = QDateTime::currentMSecsSinceEpoch();
|
||||
}
|
||||
//else Debug(_log, "latch %d", QDateTime::currentMSecsSinceEpoch()-_last_write_time);
|
||||
qint64 elapsedTime = QDateTime::currentMSecsSinceEpoch() - _last_write_time;
|
||||
if (_latchTime_ms == 0 || elapsedTime >= _latchTime_ms)
|
||||
{
|
||||
//std::cout << "LedDevice::updateLeds(), Elapsed time since last write (" << elapsedTime << ") ms > _latchTime_ms (" << _latchTime_ms << ") ms" << std::endl;
|
||||
retval = write(ledValues);
|
||||
_last_write_time = QDateTime::currentMSecsSinceEpoch();
|
||||
|
||||
// if device requires refreshing, save Led-Values and restart the timer
|
||||
if ( _refresh_enabled )
|
||||
{
|
||||
this->startRefreshTimer();
|
||||
_last_ledValues = ledValues;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
//std::cout << "LedDevice::updateLeds(), Skip write. _latchTime_ms (" << _latchTime_ms << ") ms > elapsedTime (" << elapsedTime << ") ms" << std::endl;
|
||||
if ( _refresh_enabled )
|
||||
{
|
||||
//Stop timer to allow for next non-refresh update
|
||||
this->stopRefreshTimer();
|
||||
}
|
||||
}
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
|
||||
int LedDevice::writeBlack()
|
||||
{
|
||||
return _deviceReady ? write(std::vector<ColorRgb>(_ledCount, ColorRgb::BLACK )) : -1;
|
||||
return _deviceReady ? updateLeds(std::vector<ColorRgb>(static_cast<unsigned long>(_ledCount), ColorRgb::BLACK )) : -1;
|
||||
}
|
||||
|
||||
int LedDevice::switchOff()
|
||||
{
|
||||
// Stop refresh timer to ensure that "write Black" is executed
|
||||
this->stopRefreshTimer();
|
||||
|
||||
if ( _latchTime_ms > 0 )
|
||||
{
|
||||
// Wait latchtime before writing black
|
||||
QEventLoop loop;
|
||||
QTimer::singleShot( _latchTime_ms, &loop, SLOT( quit() ) );
|
||||
loop.exec();
|
||||
}
|
||||
int rc = writeBlack();
|
||||
return rc;
|
||||
}
|
||||
@@ -124,7 +206,7 @@ int LedDevice::switchOn()
|
||||
return 0;
|
||||
}
|
||||
|
||||
void LedDevice::setLedCount(int ledCount)
|
||||
void LedDevice::setLedCount(unsigned int ledCount)
|
||||
{
|
||||
_ledCount = ledCount;
|
||||
_ledRGBCount = _ledCount * sizeof(ColorRgb);
|
||||
@@ -133,6 +215,35 @@ void LedDevice::setLedCount(int ledCount)
|
||||
|
||||
int LedDevice::rewriteLeds()
|
||||
{
|
||||
return _enabled ? write(_ledValues) : -1;
|
||||
int retval = -1;
|
||||
|
||||
if ( _deviceReady )
|
||||
{
|
||||
//qint64 elapsedTime = QDateTime::currentMSecsSinceEpoch() - _last_write_time;
|
||||
//std::cout << "LedDevice::rewriteLeds(): Rewrite Leds now, elapsedTime [" << elapsedTime << "] ms" << std::endl;
|
||||
// //:TESTING: Inject "white" output records to differentiate from normal writes
|
||||
// _last_ledValues.clear();
|
||||
// _last_ledValues.resize(static_cast<unsigned long>(_ledCount), ColorRgb::WHITE);
|
||||
// printLedValues(_last_ledValues);
|
||||
// //:TESTING:
|
||||
|
||||
retval = write(_last_ledValues);
|
||||
_last_write_time = QDateTime::currentMSecsSinceEpoch();
|
||||
}
|
||||
else
|
||||
{
|
||||
// If Device is not ready stop timer
|
||||
this->stopRefreshTimer();
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
|
||||
void LedDevice::printLedValues(const std::vector<ColorRgb>& ledValues )
|
||||
{
|
||||
std::cout << "LedValues [" << ledValues.size() <<"] [";
|
||||
for (const ColorRgb& color : ledValues)
|
||||
{
|
||||
std::cout << color;
|
||||
}
|
||||
std::cout << "]" << std::endl;
|
||||
}
|
||||
|
Reference in New Issue
Block a user