mirror of
https://github.com/hyperion-project/hyperion.ng.git
synced 2025-03-01 10:33:28 +00:00
Threading and more
- webui remove restarts - threading for LedDevice
This commit is contained in:
@@ -22,7 +22,7 @@
|
||||
#include <utils/SysInfo.h>
|
||||
#include <HyperionConfig.h>
|
||||
#include <utils/ColorSys.h>
|
||||
#include <leddevice/LedDevice.h>
|
||||
#include <leddevice/LedDeviceWrapper.h>
|
||||
#include <hyperion/GrabberWrapper.h>
|
||||
#include <utils/Process.h>
|
||||
#include <utils/JsonUtils.h>
|
||||
@@ -50,6 +50,8 @@ JsonAPI::JsonAPI(QString peerAddress, Logger* log, QObject* parent, bool noListe
|
||||
, _image_stream_timeout(0)
|
||||
, _led_stream_timeout(0)
|
||||
{
|
||||
Q_INIT_RESOURCE(JSONRPC_schemas);
|
||||
|
||||
// the JsonCB creates json messages you can subscribe to e.g. data change events; forward them to the parent client
|
||||
connect(_jsonCB, &JsonCB::newCallback, this, &JsonAPI::callbackMessage);
|
||||
|
||||
@@ -63,7 +65,6 @@ JsonAPI::JsonAPI(QString peerAddress, Logger* log, QObject* parent, bool noListe
|
||||
void JsonAPI::handleMessage(const QString& messageString)
|
||||
{
|
||||
const QString ident = "JsonRpc@"+_peerAddress;
|
||||
Q_INIT_RESOURCE(JSONRPC_schemas);
|
||||
QJsonObject message;
|
||||
// parse the message
|
||||
if(!JsonUtils::parse(ident, messageString, message, _log))
|
||||
@@ -408,7 +409,7 @@ void JsonAPI::handleServerInfoCommand(const QJsonObject& message, const QString&
|
||||
QJsonObject ledDevices;
|
||||
ledDevices["active"] = _hyperion->getActiveDevice();
|
||||
QJsonArray availableLedDevices;
|
||||
for (auto dev: LedDevice::getDeviceMap())
|
||||
for (auto dev: LedDeviceWrapper::getDeviceMap())
|
||||
{
|
||||
availableLedDevices.append(dev.first);
|
||||
}
|
||||
@@ -696,7 +697,7 @@ void JsonAPI::handleSchemaGetCommand(const QJsonObject& message, const QString&
|
||||
|
||||
// collect all LED Devices
|
||||
properties = schemaJson["properties"].toObject();
|
||||
alldevices = LedDevice::getLedDeviceSchemas();
|
||||
alldevices = LedDeviceWrapper::getLedDeviceSchemas();
|
||||
properties.insert("alldevices", alldevices);
|
||||
|
||||
// collect all available effect schemas
|
||||
|
@@ -1,6 +1,12 @@
|
||||
#include <hyperion/CaptureCont.h>
|
||||
|
||||
// hyperion includes
|
||||
#include <hyperion/Hyperion.h>
|
||||
|
||||
// utils includes
|
||||
#include <utils/GlobalSignals.h>
|
||||
|
||||
// qt includes
|
||||
#include <QTimer>
|
||||
|
||||
CaptureCont::CaptureCont(Hyperion* hyperion)
|
||||
@@ -56,11 +62,11 @@ void CaptureCont::setSystemCaptureEnable(const bool& enable)
|
||||
if(enable)
|
||||
{
|
||||
_hyperion->registerInput(_systemCaptPrio, hyperion::COMP_GRABBER);
|
||||
connect(_hyperion, &Hyperion::systemImage, this, &CaptureCont::handleSystemImage);
|
||||
connect(GlobalSignals::getInstance(), &GlobalSignals::setSystemImage, this, &CaptureCont::handleSystemImage);
|
||||
}
|
||||
else
|
||||
{
|
||||
disconnect(_hyperion, &Hyperion::systemImage, this, &CaptureCont::handleSystemImage);
|
||||
disconnect(GlobalSignals::getInstance(), &GlobalSignals::setSystemImage, 0, 0);
|
||||
_hyperion->clear(_systemCaptPrio);
|
||||
}
|
||||
_systemCaptEnabled = enable;
|
||||
@@ -75,11 +81,11 @@ void CaptureCont::setV4LCaptureEnable(const bool& enable)
|
||||
if(enable)
|
||||
{
|
||||
_hyperion->registerInput(_v4lCaptPrio, hyperion::COMP_V4L);
|
||||
connect(_hyperion, &Hyperion::v4lImage, this, &CaptureCont::handleV4lImage);
|
||||
connect(GlobalSignals::getInstance(), &GlobalSignals::setV4lImage, this, &CaptureCont::handleV4lImage);
|
||||
}
|
||||
else
|
||||
{
|
||||
disconnect(_hyperion, &Hyperion::v4lImage, this, &CaptureCont::handleV4lImage);
|
||||
disconnect(GlobalSignals::getInstance(), &GlobalSignals::setV4lImage, 0, 0);
|
||||
_hyperion->clear(_v4lCaptPrio);
|
||||
_v4lInactiveTimer->stop();
|
||||
}
|
||||
|
@@ -3,6 +3,9 @@
|
||||
#include <hyperion/Grabber.h>
|
||||
#include <HyperionConfig.h>
|
||||
|
||||
// utils includes
|
||||
#include <utils/GlobalSignals.h>
|
||||
|
||||
// qt
|
||||
#include <QTimer>
|
||||
|
||||
@@ -20,6 +23,11 @@ GrabberWrapper::GrabberWrapper(QString grabberName, Grabber * ggrabber, unsigned
|
||||
_image.resize(width, height);
|
||||
|
||||
connect(_timer, &QTimer::timeout, this, &GrabberWrapper::action);
|
||||
|
||||
// connect the image forwarding
|
||||
_grabberName.startsWith("V4L")
|
||||
? connect(this, &GrabberWrapper::systemImage, GlobalSignals::getInstance(), &GlobalSignals::setV4lImage)
|
||||
: connect(this, &GrabberWrapper::systemImage, GlobalSignals::getInstance(), &GlobalSignals::setSystemImage);
|
||||
}
|
||||
|
||||
GrabberWrapper::~GrabberWrapper()
|
||||
|
@@ -26,8 +26,7 @@
|
||||
#include <utils/hyperion.h>
|
||||
|
||||
// Leddevice includes
|
||||
#include <leddevice/LedDevice.h>
|
||||
#include <leddevice/LedDeviceFactory.h>
|
||||
#include <leddevice/LedDeviceWrapper.h>
|
||||
|
||||
#include <hyperion/MultiColorAdjustment.h>
|
||||
#include "LinearColorSmoothing.h"
|
||||
@@ -127,22 +126,23 @@ Hyperion::Hyperion(HyperionDaemon* daemon, const quint8& instance, const QString
|
||||
QJsonObject ledDevice = getSetting(settings::DEVICE).object();
|
||||
ledDevice["currentLedCount"] = int(_hwLedCount); // Inject led count info
|
||||
|
||||
_device = LedDeviceFactory::construct(ledDevice);
|
||||
_deviceSmooth = new LinearColorSmoothing(_device, getSetting(settings::SMOOTHING), this);
|
||||
_ledDeviceWrapper = new LedDeviceWrapper(this);
|
||||
connect(this, &Hyperion::componentStateChanged, _ledDeviceWrapper, &LedDeviceWrapper::handleComponentState);
|
||||
connect(this, &Hyperion::ledDeviceData, _ledDeviceWrapper, &LedDeviceWrapper::write);
|
||||
_ledDeviceWrapper->createLedDevice(ledDevice);
|
||||
|
||||
// smoothing
|
||||
_deviceSmooth = new LinearColorSmoothing(getSetting(settings::SMOOTHING), this);
|
||||
connect(this, &Hyperion::settingsChanged, _deviceSmooth, &LinearColorSmoothing::handleSettingsUpdate);
|
||||
|
||||
getComponentRegister().componentStateChanged(hyperion::COMP_LEDDEVICE, _device->componentState());
|
||||
|
||||
// create the effect engine and pipe the updateEmit; must be initialized after smoothing!
|
||||
// create the effect engine; needs to be initialized after smoothing!
|
||||
_effectEngine = new EffectEngine(this);
|
||||
connect(_effectEngine, &EffectEngine::effectListUpdated, this, &Hyperion::effectListUpdated);
|
||||
|
||||
// setup config state checks and initial shot
|
||||
checkConfigState();
|
||||
if(_fsWatcher.addPath(_configFile))
|
||||
{
|
||||
QObject::connect(&_fsWatcher, &QFileSystemWatcher::fileChanged, this, &Hyperion::checkConfigState);
|
||||
}
|
||||
else
|
||||
{
|
||||
_cTimer = new QTimer(this);
|
||||
@@ -153,6 +153,7 @@ Hyperion::Hyperion(HyperionDaemon* daemon, const quint8& instance, const QString
|
||||
|
||||
// initial startup effect
|
||||
hyperion::handleInitialEffect(this, getSetting(settings::FGEFFECT).object());
|
||||
|
||||
// handle background effect
|
||||
_BGEffectHandler = new BGEffectHandler(this);
|
||||
|
||||
@@ -163,7 +164,6 @@ Hyperion::Hyperion(HyperionDaemon* daemon, const quint8& instance, const QString
|
||||
update();
|
||||
|
||||
// boblight, can't live in global scope as it depends on layout
|
||||
|
||||
_boblightServer = new BoblightServer(this, getSetting(settings::BOBLSERVER));
|
||||
connect(this, &Hyperion::settingsChanged, _boblightServer, &BoblightServer::handleSettingsUpdate);
|
||||
}
|
||||
@@ -188,10 +188,10 @@ void Hyperion::freeObjects(bool emitCloseSignal)
|
||||
delete _captureCont;
|
||||
delete _effectEngine;
|
||||
//delete _deviceSmooth;
|
||||
delete _device;
|
||||
delete _raw2ledAdjustment;
|
||||
delete _messageForwarder;
|
||||
delete _settingsManager;
|
||||
delete _ledDeviceWrapper;
|
||||
}
|
||||
|
||||
void Hyperion::handleSettingsUpdate(const settings::type& type, const QJsonDocument& config)
|
||||
@@ -241,7 +241,7 @@ void Hyperion::handleSettingsUpdate(const settings::type& type, const QJsonDocum
|
||||
_hwLedCount = qMax(unsigned(getSetting(settings::DEVICE).object()["hardwareLedCount"].toInt(getLedCount())), getLedCount());
|
||||
|
||||
// update led count in device
|
||||
_device->setLedCount(_hwLedCount);
|
||||
//_ledDeviceWrapper->setLedCount(_hwLedCount);
|
||||
|
||||
// change in leds are also reflected in adjustment
|
||||
delete _raw2ledAdjustment;
|
||||
@@ -262,7 +262,7 @@ void Hyperion::handleSettingsUpdate(const settings::type& type, const QJsonDocum
|
||||
_hwLedCount = qMax(unsigned(dev["hardwareLedCount"].toInt(getLedCount())), getLedCount());
|
||||
|
||||
// force ledString update, if device ByteOrder changed
|
||||
if(_device->getColorOrder() != dev["colorOrder"].toString("rgb"))
|
||||
if(_ledDeviceWrapper->getColorOrder() != dev["colorOrder"].toString("rgb"))
|
||||
{
|
||||
_ledString = hyperion::createLedString(getSetting(settings::LEDS).array(), hyperion::createColorOrder(dev));
|
||||
_ledStringClone = hyperion::createLedStringClone(getSetting(settings::LEDS).array(), hyperion::createColorOrder(dev));
|
||||
@@ -276,16 +276,9 @@ void Hyperion::handleSettingsUpdate(const settings::type& type, const QJsonDocum
|
||||
// update led count
|
||||
_device->setLedCount(_hwLedCount);
|
||||
*/
|
||||
// do always reinit
|
||||
// TODO segfaulting in LinearColorSmoothing::queueColor triggert from QTimer because of device->setLEdValues (results from gdb debugging and testing)
|
||||
bool wasEnabled = _deviceSmooth->enabled();
|
||||
_deviceSmooth->stopTimer();
|
||||
delete _device;
|
||||
// do always reinit until the led devices can handle dynamic changes
|
||||
dev["currentLedCount"] = int(_hwLedCount); // Inject led count info
|
||||
_device = LedDeviceFactory::construct(dev);
|
||||
getComponentRegister().componentStateChanged(hyperion::COMP_LEDDEVICE, _device->componentState());
|
||||
if(wasEnabled)
|
||||
_deviceSmooth->startTimerDelayed();
|
||||
_ledDeviceWrapper->createLedDevice(dev);
|
||||
_lockUpdate = false;
|
||||
}
|
||||
// update once to push single color sets / adjustments/ ledlayout resizes and update ledBuffer color
|
||||
@@ -310,7 +303,7 @@ QString Hyperion::getConfigFileName() const
|
||||
|
||||
int Hyperion::getLatchTime() const
|
||||
{
|
||||
return _device->getLatchTime();
|
||||
return _ledDeviceWrapper->getLatchTime();
|
||||
}
|
||||
|
||||
unsigned Hyperion::addSmoothingConfig(int settlingTime_ms, double ledUpdateFrequency_hz, unsigned updateDelay)
|
||||
@@ -373,18 +366,14 @@ bool Hyperion::sourceAutoSelectEnabled()
|
||||
return _muxer.isSourceAutoSelectEnabled();
|
||||
}
|
||||
|
||||
void Hyperion::setNewComponentState(const hyperion::Components& component, const bool& state)
|
||||
{
|
||||
_componentRegister.componentStateChanged(component, state);
|
||||
}
|
||||
|
||||
void Hyperion::setComponentState(const hyperion::Components component, const bool state)
|
||||
{
|
||||
switch (component)
|
||||
{
|
||||
case hyperion::COMP_LEDDEVICE:
|
||||
_device->setEnable(state);
|
||||
getComponentRegister().componentStateChanged(hyperion::COMP_LEDDEVICE, _device->componentState());
|
||||
break;
|
||||
|
||||
default:
|
||||
emit componentStateChanged(component, state);
|
||||
}
|
||||
emit componentStateChanged(component, state);
|
||||
}
|
||||
|
||||
void Hyperion::registerInput(const int priority, const hyperion::Components& component, const QString& origin, const QString& owner, unsigned smooth_cfg)
|
||||
@@ -571,7 +560,7 @@ const VideoMode & Hyperion::getCurrentVideoMode()
|
||||
|
||||
const QString & Hyperion::getActiveDevice()
|
||||
{
|
||||
return _device->getActiveDevice();
|
||||
return _ledDeviceWrapper->getActiveDevice();
|
||||
}
|
||||
|
||||
void Hyperion::updatedComponentState(const hyperion::Components comp, const bool state)
|
||||
@@ -681,7 +670,7 @@ void Hyperion::update()
|
||||
}
|
||||
|
||||
// Write the data to the device
|
||||
if (_device->enabled())
|
||||
if (_ledDeviceWrapper->enabled())
|
||||
{
|
||||
_deviceSmooth->selectConfig(priorityInfo.smooth_cfg);
|
||||
|
||||
@@ -690,6 +679,6 @@ void Hyperion::update()
|
||||
_deviceSmooth->setLedValues(_ledBuffer);
|
||||
|
||||
if (! _deviceSmooth->enabled())
|
||||
_device->setLedValues(_ledBuffer);
|
||||
emit ledDeviceData(_ledBuffer);
|
||||
}
|
||||
}
|
||||
|
@@ -9,9 +9,8 @@
|
||||
|
||||
using namespace hyperion;
|
||||
|
||||
LinearColorSmoothing::LinearColorSmoothing( LedDevice * ledDevice, const QJsonDocument& config, Hyperion* hyperion)
|
||||
: LedDevice()
|
||||
, _ledDevice(ledDevice)
|
||||
LinearColorSmoothing::LinearColorSmoothing(const QJsonDocument& config, Hyperion* hyperion)
|
||||
: LedDevice(QJsonObject(), hyperion)
|
||||
, _log(Logger::getInstance("SMOOTHING"))
|
||||
, _hyperion(hyperion)
|
||||
, _updateInterval(1000)
|
||||
@@ -42,8 +41,7 @@ LinearColorSmoothing::LinearColorSmoothing( LedDevice * ledDevice, const QJsonDo
|
||||
|
||||
LinearColorSmoothing::~LinearColorSmoothing()
|
||||
{
|
||||
// Make sure to switch off the underlying led-device (because switchOff is no longer forwarded)
|
||||
_ledDevice->switchOff();
|
||||
|
||||
}
|
||||
|
||||
void LinearColorSmoothing::handleSettingsUpdate(const settings::type& type, const QJsonDocument& config)
|
||||
@@ -148,7 +146,8 @@ void LinearColorSmoothing::queueColors(const std::vector<ColorRgb> & ledColors)
|
||||
{
|
||||
// No output delay => immediate write
|
||||
if ( _writeToLedsEnable && !_pause)
|
||||
_ledDevice->setLedValues(ledColors);
|
||||
emit _hyperion->ledDeviceData(ledColors);
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -163,7 +162,7 @@ void LinearColorSmoothing::queueColors(const std::vector<ColorRgb> & ledColors)
|
||||
{
|
||||
if (!_pause)
|
||||
{
|
||||
_ledDevice->setLedValues(_outputQueue.front());
|
||||
emit _hyperion->ledDeviceData(_outputQueue.front());
|
||||
}
|
||||
_outputQueue.pop_front();
|
||||
}
|
||||
@@ -235,18 +234,3 @@ bool LinearColorSmoothing::selectConfig(unsigned cfg, const bool& force)
|
||||
_currentConfigId = 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
void LinearColorSmoothing::startTimerDelayed()
|
||||
{
|
||||
QTimer::singleShot(500, this, SLOT(delayStartTimer()));
|
||||
}
|
||||
|
||||
void LinearColorSmoothing::stopTimer()
|
||||
{
|
||||
_timer->stop();
|
||||
}
|
||||
|
||||
void LinearColorSmoothing::delayStartTimer()
|
||||
{
|
||||
_timer->start();
|
||||
}
|
||||
|
@@ -28,11 +28,10 @@ class LinearColorSmoothing : public LedDevice
|
||||
|
||||
public:
|
||||
/// Constructor
|
||||
/// @param LedDevice the led device
|
||||
/// @param config The configuration document smoothing
|
||||
/// @param hyperion The hyperion parent instance
|
||||
///
|
||||
LinearColorSmoothing(LedDevice *ledDevice, const QJsonDocument& config, Hyperion* hyperion);
|
||||
LinearColorSmoothing(const QJsonDocument& config, Hyperion* hyperion);
|
||||
|
||||
/// Destructor
|
||||
virtual ~LinearColorSmoothing();
|
||||
@@ -71,12 +70,6 @@ public:
|
||||
///
|
||||
bool selectConfig(unsigned cfg, const bool& force = false);
|
||||
|
||||
///
|
||||
/// @ Helper methods to start the timer with delay (see delayStartSmooth())
|
||||
///
|
||||
void startTimerDelayed();
|
||||
void stopTimer();
|
||||
|
||||
public slots:
|
||||
///
|
||||
/// @brief Handle settings update from Hyperion Settingsmanager emit or this constructor
|
||||
@@ -89,9 +82,6 @@ private slots:
|
||||
/// Timer callback which writes updated led values to the led device
|
||||
void updateLeds();
|
||||
|
||||
/// Delay timer slot to workaround the leddevice reconstruction segfault (dangling pointer)
|
||||
void delayStartTimer();
|
||||
|
||||
///
|
||||
/// @brief Handle component state changes
|
||||
/// @param component The component
|
||||
@@ -107,9 +97,6 @@ private:
|
||||
*/
|
||||
void queueColors(const std::vector<ColorRgb> & ledColors);
|
||||
|
||||
/// The led device
|
||||
LedDevice * _ledDevice;
|
||||
|
||||
/// Logger instance
|
||||
Logger* _log;
|
||||
|
||||
|
@@ -10,10 +10,9 @@
|
||||
#include "hyperion/Hyperion.h"
|
||||
#include <utils/JsonUtils.h>
|
||||
|
||||
LedDeviceRegistry LedDevice::_ledDeviceMap = LedDeviceRegistry();
|
||||
|
||||
LedDevice::LedDevice()
|
||||
: QObject()
|
||||
LedDevice::LedDevice(const QJsonObject& config, QObject* parent)
|
||||
: QObject(parent)
|
||||
, _devConfig(config)
|
||||
, _log(Logger::getInstance("LEDDEVICE"))
|
||||
, _ledBuffer(0)
|
||||
, _deviceReady(true)
|
||||
@@ -24,15 +23,16 @@ LedDevice::LedDevice()
|
||||
, _componentRegistered(false)
|
||||
, _enabled(true)
|
||||
{
|
||||
LedDevice::getLedDeviceSchemas();
|
||||
qRegisterMetaType<hyperion::Components>("hyperion::Components");
|
||||
|
||||
// setup timer
|
||||
_refresh_timer.setSingleShot(false);
|
||||
_refresh_timer.setInterval(0);
|
||||
connect(&_refresh_timer, SIGNAL(timeout()), this, SLOT(rewriteLeds()));
|
||||
}
|
||||
|
||||
LedDevice::~LedDevice()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
// dummy implemention
|
||||
int LedDevice::open()
|
||||
{
|
||||
@@ -55,17 +55,6 @@ void LedDevice::setEnable(bool enable)
|
||||
_enabled = enable;
|
||||
}
|
||||
|
||||
int LedDevice::addToDeviceMap(QString name, LedDeviceCreateFuncType funcPtr)
|
||||
{
|
||||
_ledDeviceMap.emplace(name,funcPtr);
|
||||
return 0;
|
||||
}
|
||||
|
||||
const LedDeviceRegistry& LedDevice::getDeviceMap()
|
||||
{
|
||||
return _ledDeviceMap;
|
||||
}
|
||||
|
||||
void LedDevice::setActiveDevice(QString dev)
|
||||
{
|
||||
_activeDevice = dev;
|
||||
@@ -88,42 +77,6 @@ bool LedDevice::init(const QJsonObject &deviceConfig)
|
||||
return true;
|
||||
}
|
||||
|
||||
QJsonObject LedDevice::getLedDeviceSchemas()
|
||||
{
|
||||
// make sure the resources are loaded (they may be left out after static linking)
|
||||
Q_INIT_RESOURCE(LedDeviceSchemas);
|
||||
|
||||
// read the json schema from the resource
|
||||
QDir d(":/leddevices/");
|
||||
QStringList l = d.entryList();
|
||||
QJsonObject result, schemaJson;
|
||||
|
||||
for(QString &item : l)
|
||||
{
|
||||
QString schemaPath(QString(":/leddevices/")+item);
|
||||
QString devName = item.remove("schema-");
|
||||
|
||||
QString data;
|
||||
if(!FileUtils::readFile(schemaPath, data, Logger::getInstance("LedDevice")))
|
||||
{
|
||||
throw std::runtime_error("ERROR: Schema not found: " + item.toStdString());
|
||||
}
|
||||
|
||||
QJsonObject schema;
|
||||
if(!JsonUtils::parse(schemaPath, data, schema, Logger::getInstance("LedDevice")))
|
||||
{
|
||||
throw std::runtime_error("ERROR: Json schema wrong of file: " + item.toStdString());
|
||||
}
|
||||
|
||||
schemaJson = schema;
|
||||
schemaJson["title"] = QString("edt_dev_spec_header_title");
|
||||
|
||||
result[devName] = schemaJson;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
int LedDevice::setLedValues(const std::vector<ColorRgb>& ledValues)
|
||||
{
|
||||
int retval = 0;
|
||||
|
@@ -7,10 +7,11 @@
|
||||
|
||||
// Leddevice includes
|
||||
#include <leddevice/LedDeviceFactory.h>
|
||||
#include <leddevice/LedDeviceWrapper.h>
|
||||
#include <utils/Logger.h>
|
||||
#include <leddevice/LedDevice.h>
|
||||
|
||||
// following file is auto generated by cmake! it contains all available leddevice headers
|
||||
// autogen
|
||||
#include "LedDevice_headers.h"
|
||||
|
||||
LedDevice * LedDeviceFactory::construct(const QJsonObject & deviceConfig)
|
||||
@@ -21,14 +22,7 @@ LedDevice * LedDeviceFactory::construct(const QJsonObject & deviceConfig)
|
||||
|
||||
QString type = deviceConfig["type"].toString("UNSPECIFIED").toLower();
|
||||
|
||||
#define REGISTER(className) LedDevice::addToDeviceMap(QString(#className).toLower(), LedDevice##className::construct);
|
||||
|
||||
// the REGISTER() calls are autogenerated by cmake.
|
||||
#include "LedDevice_register.cpp"
|
||||
|
||||
#undef REGISTER
|
||||
|
||||
const LedDeviceRegistry& devList = LedDevice::getDeviceMap();
|
||||
const LedDeviceRegistry& devList = LedDeviceWrapper::getDeviceMap();
|
||||
LedDevice* device = nullptr;
|
||||
try
|
||||
{
|
||||
@@ -56,7 +50,5 @@ LedDevice * LedDeviceFactory::construct(const QJsonObject & deviceConfig)
|
||||
device = LedDeviceFile::construct(QJsonObject());
|
||||
}
|
||||
|
||||
device->open();
|
||||
|
||||
return device;
|
||||
}
|
||||
|
148
libsrc/leddevice/LedDeviceWrapper.cpp
Normal file
148
libsrc/leddevice/LedDeviceWrapper.cpp
Normal file
@@ -0,0 +1,148 @@
|
||||
#include <leddevice/LedDeviceWrapper.h>
|
||||
|
||||
#include <leddevice/LedDevice.h>
|
||||
#include <leddevice/LedDeviceFactory.h>
|
||||
|
||||
// following file is auto generated by cmake! it contains all available leddevice headers
|
||||
#include "LedDevice_headers.h"
|
||||
|
||||
// util
|
||||
#include <hyperion/Hyperion.h>
|
||||
#include <utils/JsonUtils.h>
|
||||
|
||||
// qt
|
||||
#include <QThread>
|
||||
#include <QDir>
|
||||
|
||||
LedDeviceRegistry LedDeviceWrapper::_ledDeviceMap = LedDeviceRegistry();
|
||||
|
||||
LedDeviceWrapper::LedDeviceWrapper(Hyperion* hyperion)
|
||||
: QObject(hyperion)
|
||||
, _hyperion(hyperion)
|
||||
, _ledDevice(nullptr)
|
||||
{
|
||||
// prepare the device constrcutor map
|
||||
#define REGISTER(className) LedDeviceWrapper::addToDeviceMap(QString(#className).toLower(), LedDevice##className::construct);
|
||||
|
||||
// the REGISTER() calls are autogenerated by cmake.
|
||||
#include "LedDevice_register.cpp"
|
||||
|
||||
#undef REGISTER
|
||||
|
||||
_hyperion->setNewComponentState(hyperion::COMP_LEDDEVICE, true);
|
||||
}
|
||||
|
||||
LedDeviceWrapper::~LedDeviceWrapper()
|
||||
{
|
||||
stopDeviceThread();
|
||||
}
|
||||
|
||||
void LedDeviceWrapper::createLedDevice(const QJsonObject& config)
|
||||
{
|
||||
if(_ledDevice != nullptr)
|
||||
{
|
||||
stopDeviceThread();
|
||||
}
|
||||
|
||||
// create thread and device
|
||||
QThread* thread = new QThread(this);
|
||||
_ledDevice = LedDeviceFactory::construct(config);
|
||||
_ledDevice->moveToThread(thread);
|
||||
// setup thread management
|
||||
connect(thread, &QThread::started, _ledDevice, &LedDevice::start);
|
||||
connect(thread, &QThread::finished, thread, &QObject::deleteLater);
|
||||
connect(thread, &QThread::finished, _ledDevice, &QObject::deleteLater);
|
||||
|
||||
// further signals
|
||||
connect(this, &LedDeviceWrapper::write, _ledDevice, &LedDevice::write);
|
||||
connect(_ledDevice, &LedDevice::enableStateChanged, this, &LedDeviceWrapper::handleInternalEnableState);
|
||||
|
||||
// start the thread
|
||||
thread->start();
|
||||
}
|
||||
|
||||
const QJsonObject LedDeviceWrapper::getLedDeviceSchemas()
|
||||
{
|
||||
// make sure the resources are loaded (they may be left out after static linking)
|
||||
Q_INIT_RESOURCE(LedDeviceSchemas);
|
||||
|
||||
// read the json schema from the resource
|
||||
QDir d(":/leddevices/");
|
||||
QStringList l = d.entryList();
|
||||
QJsonObject result, schemaJson;
|
||||
|
||||
for(QString &item : l)
|
||||
{
|
||||
QString schemaPath(QString(":/leddevices/")+item);
|
||||
QString devName = item.remove("schema-");
|
||||
|
||||
QString data;
|
||||
if(!FileUtils::readFile(schemaPath, data, Logger::getInstance("LedDevice")))
|
||||
{
|
||||
throw std::runtime_error("ERROR: Schema not found: " + item.toStdString());
|
||||
}
|
||||
|
||||
QJsonObject schema;
|
||||
if(!JsonUtils::parse(schemaPath, data, schema, Logger::getInstance("LedDevice")))
|
||||
{
|
||||
throw std::runtime_error("ERROR: Json schema wrong of file: " + item.toStdString());
|
||||
}
|
||||
|
||||
schemaJson = schema;
|
||||
schemaJson["title"] = QString("edt_dev_spec_header_title");
|
||||
|
||||
result[devName] = schemaJson;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
int LedDeviceWrapper::addToDeviceMap(QString name, LedDeviceCreateFuncType funcPtr)
|
||||
{
|
||||
_ledDeviceMap.emplace(name,funcPtr);
|
||||
return 0;
|
||||
}
|
||||
|
||||
const LedDeviceRegistry& LedDeviceWrapper::getDeviceMap()
|
||||
{
|
||||
return _ledDeviceMap;
|
||||
}
|
||||
|
||||
int LedDeviceWrapper::getLatchTime()
|
||||
{
|
||||
return _ledDevice->getLatchTime();
|
||||
}
|
||||
|
||||
const QString & LedDeviceWrapper::getActiveDevice()
|
||||
{
|
||||
return _ledDevice->getActiveDevice();
|
||||
}
|
||||
|
||||
const QString & LedDeviceWrapper::getColorOrder()
|
||||
{
|
||||
return _ledDevice->getColorOrder();
|
||||
}
|
||||
|
||||
void LedDeviceWrapper::handleComponentState(const hyperion::Components component, const bool state)
|
||||
{
|
||||
if(component == hyperion::COMP_LEDDEVICE)
|
||||
{
|
||||
_ledDevice->setEnable(state);
|
||||
_hyperion->setNewComponentState(hyperion::COMP_LEDDEVICE, _ledDevice->componentState());
|
||||
_enabled = state;
|
||||
}
|
||||
}
|
||||
|
||||
void LedDeviceWrapper::handleInternalEnableState(bool newState)
|
||||
{
|
||||
_hyperion->setNewComponentState(hyperion::COMP_LEDDEVICE, newState);
|
||||
_enabled = newState;
|
||||
}
|
||||
|
||||
void LedDeviceWrapper::stopDeviceThread()
|
||||
{
|
||||
_ledDevice->switchOff();
|
||||
QThread* oldThread = _ledDevice->thread();
|
||||
delete _ledDevice; // fast desctruction
|
||||
oldThread->quit(); // non blocking
|
||||
}
|
@@ -201,7 +201,7 @@ void PhilipsHueBridge::resolveReply(QNetworkReply* reply)
|
||||
|
||||
void PhilipsHueBridge::post(QString route, QString content)
|
||||
{
|
||||
Debug(log, "Post %s: %s", QSTRING_CSTR(QString("http://IP/api/USR/%1").arg(route)), QSTRING_CSTR(content));
|
||||
//Debug(log, "Post %s: %s", QSTRING_CSTR(QString("http://IP/api/USR/%1").arg(route)), QSTRING_CSTR(content));
|
||||
|
||||
QNetworkRequest request(QString("http://%1/api/%2/%3").arg(host).arg(username).arg(route));
|
||||
manager.put(request, content.toLatin1());
|
||||
@@ -214,7 +214,7 @@ const std::set<QString> PhilipsHueLight::GAMUT_B_MODEL_IDS =
|
||||
const std::set<QString> PhilipsHueLight::GAMUT_C_MODEL_IDS =
|
||||
{ "LLC020", "LST002", "LCT011", "LCT012", "LCT010", "LCT014" };
|
||||
|
||||
PhilipsHueLight::PhilipsHueLight(Logger* log, PhilipsHueBridge& bridge, unsigned int id, QJsonObject values)
|
||||
PhilipsHueLight::PhilipsHueLight(Logger* log, PhilipsHueBridge* bridge, unsigned int id, QJsonObject values)
|
||||
: log(log)
|
||||
, bridge(bridge)
|
||||
, id(id)
|
||||
@@ -297,7 +297,7 @@ PhilipsHueLight::~PhilipsHueLight()
|
||||
|
||||
void PhilipsHueLight::set(QString state)
|
||||
{
|
||||
bridge.post(QString("lights/%1/state").arg(id), state);
|
||||
bridge->post(QString("lights/%1/state").arg(id), state);
|
||||
}
|
||||
|
||||
void PhilipsHueLight::setOn(bool on)
|
||||
@@ -345,18 +345,25 @@ LedDevice* LedDevicePhilipsHue::construct(const QJsonObject &deviceConfig)
|
||||
}
|
||||
|
||||
LedDevicePhilipsHue::LedDevicePhilipsHue(const QJsonObject& deviceConfig)
|
||||
: LedDevice()
|
||||
, bridge(_log, deviceConfig["output"].toString(), deviceConfig["username"].toString())
|
||||
: LedDevice(deviceConfig)
|
||||
, _bridge(nullptr)
|
||||
{
|
||||
_deviceReady = init(deviceConfig);
|
||||
|
||||
connect(&bridge, &PhilipsHueBridge::newLights, this, &LedDevicePhilipsHue::newLights);
|
||||
connect(this, &LedDevice::enableStateChanged, this, &LedDevicePhilipsHue::stateChanged);
|
||||
}
|
||||
|
||||
LedDevicePhilipsHue::~LedDevicePhilipsHue()
|
||||
{
|
||||
switchOff();
|
||||
delete _bridge;
|
||||
}
|
||||
|
||||
void LedDevicePhilipsHue::start()
|
||||
{
|
||||
_bridge = new PhilipsHueBridge(_log, _devConfig["output"].toString(), _devConfig["username"].toString());
|
||||
_deviceReady = init(_devConfig);
|
||||
|
||||
connect(_bridge, &PhilipsHueBridge::newLights, this, &LedDevicePhilipsHue::newLights);
|
||||
connect(this, &LedDevice::enableStateChanged, this, &LedDevicePhilipsHue::stateChanged);
|
||||
}
|
||||
|
||||
bool LedDevicePhilipsHue::init(const QJsonObject &deviceConfig)
|
||||
@@ -374,7 +381,7 @@ bool LedDevicePhilipsHue::init(const QJsonObject &deviceConfig)
|
||||
lightIds.push_back(i.toInt());
|
||||
}
|
||||
// get light info from bridge
|
||||
bridge.bConnect();
|
||||
_bridge->bConnect();
|
||||
|
||||
// adapt latchTime to count of user lightIds (bridge 10Hz max overall)
|
||||
newDC.insert("latchTime",QJsonValue(100*(int)lightIds.size()));
|
||||
@@ -399,7 +406,7 @@ void LedDevicePhilipsHue::newLights(QMap<quint16, QJsonObject> map)
|
||||
{
|
||||
if (map.contains(id))
|
||||
{
|
||||
lights.push_back(PhilipsHueLight(_log, bridge, id, map.value(id)));
|
||||
lights.push_back(PhilipsHueLight(_log, _bridge, id, map.value(id)));
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -427,7 +434,6 @@ int LedDevicePhilipsHue::write(const std::vector<ColorRgb> & ledValues)
|
||||
{
|
||||
// Get color.
|
||||
ColorRgb color = ledValues.at(idx);
|
||||
|
||||
// Scale colors from [0, 255] to [0, 1] and convert to xy space.
|
||||
CiColor xy = CiColor::rgbToCiColor(color.red / 255.0f, color.green / 255.0f, color.blue / 255.0f,
|
||||
light.getColorSpace());
|
||||
@@ -453,7 +459,7 @@ int LedDevicePhilipsHue::write(const std::vector<ColorRgb> & ledValues)
|
||||
void LedDevicePhilipsHue::stateChanged(bool newState)
|
||||
{
|
||||
if(newState)
|
||||
bridge.bConnect();
|
||||
_bridge->bConnect();
|
||||
else
|
||||
lights.clear();
|
||||
}
|
||||
|
@@ -139,7 +139,7 @@ class PhilipsHueLight
|
||||
{
|
||||
private:
|
||||
Logger* log;
|
||||
PhilipsHueBridge& bridge;
|
||||
PhilipsHueBridge* bridge;
|
||||
/// light id
|
||||
unsigned int id;
|
||||
bool on;
|
||||
@@ -172,7 +172,7 @@ public:
|
||||
/// @param bridge the bridge
|
||||
/// @param id the light id
|
||||
///
|
||||
PhilipsHueLight(Logger* log, PhilipsHueBridge& bridge, unsigned int id, QJsonObject values);
|
||||
PhilipsHueLight(Logger* log, PhilipsHueBridge* bridge, unsigned int id, QJsonObject values);
|
||||
~PhilipsHueLight();
|
||||
|
||||
///
|
||||
@@ -227,6 +227,10 @@ public:
|
||||
/// constructs leddevice
|
||||
static LedDevice* construct(const QJsonObject &deviceConfig);
|
||||
|
||||
public slots:
|
||||
/// thread start
|
||||
virtual void start();
|
||||
|
||||
private slots:
|
||||
/// creates new PhilipsHueLight(s) based on user lightid with bridge feedback
|
||||
///
|
||||
@@ -249,7 +253,7 @@ protected:
|
||||
|
||||
private:
|
||||
/// bridge class
|
||||
PhilipsHueBridge bridge;
|
||||
PhilipsHueBridge* _bridge;
|
||||
|
||||
///
|
||||
bool switchOffOnBlack;
|
||||
|
@@ -40,7 +40,7 @@ bool LedDeviceTinkerforge::init(const QJsonObject &deviceConfig)
|
||||
_uid = deviceConfig["uid"].toString();
|
||||
_interval = deviceConfig["rate"].toInt();
|
||||
|
||||
if ((unsigned)_ledCount > MAX_NUM_LEDS)
|
||||
if ((unsigned)_ledCount > MAX_NUM_LEDS)
|
||||
{
|
||||
Error(_log,"Invalid attempt to write led values. Not more than %d leds are allowed.", MAX_NUM_LEDS);
|
||||
return -1;
|
||||
@@ -68,7 +68,7 @@ int LedDeviceTinkerforge::open()
|
||||
if (_ipConnection != nullptr)
|
||||
{
|
||||
Error(_log, "Attempt to open existing connection; close before opening");
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Initialise a new connection
|
||||
@@ -76,10 +76,10 @@ int LedDeviceTinkerforge::open()
|
||||
ipcon_create(_ipConnection);
|
||||
|
||||
int connectionStatus = ipcon_connect(_ipConnection, QSTRING_CSTR(_host), _port);
|
||||
if (connectionStatus < 0)
|
||||
if (connectionStatus < 0)
|
||||
{
|
||||
Warning(_log, "Attempt to connect to master brick (%s:%d) failed with status %d", QSTRING_CSTR(_host), _port, connectionStatus);
|
||||
return -1;
|
||||
Error(_log, "Attempt to connect to master brick (%s:%d) failed with status %d", QSTRING_CSTR(_host), _port, connectionStatus);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Create the 'LedStrip'
|
||||
@@ -87,17 +87,20 @@ int LedDeviceTinkerforge::open()
|
||||
led_strip_create(_ledStrip, QSTRING_CSTR(_uid), _ipConnection);
|
||||
|
||||
int frameStatus = led_strip_set_frame_duration(_ledStrip, _interval);
|
||||
if (frameStatus < 0)
|
||||
if (frameStatus < 0)
|
||||
{
|
||||
Error(_log,"Attempt to connect to led strip bricklet (led_strip_set_frame_duration()) failed with status %d", frameStatus);
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int LedDeviceTinkerforge::write(const std::vector<ColorRgb> &ledValues)
|
||||
{
|
||||
if(!_deviceReady)
|
||||
return 0;
|
||||
|
||||
auto redIt = _redChannel.begin();
|
||||
auto greenIt = _greenChannel.begin();
|
||||
auto blueIt = _blueChannel.begin();
|
||||
@@ -115,7 +118,7 @@ int LedDeviceTinkerforge::write(const std::vector<ColorRgb> &ledValues)
|
||||
return transferLedData(_ledStrip, 0, _colorChannelSize, _redChannel.data(), _greenChannel.data(), _blueChannel.data());
|
||||
}
|
||||
|
||||
int LedDeviceTinkerforge::transferLedData(LEDStrip *ledStrip, unsigned index, unsigned length, uint8_t *redChannel, uint8_t *greenChannel, uint8_t *blueChannel)
|
||||
int LedDeviceTinkerforge::transferLedData(LEDStrip *ledStrip, unsigned index, unsigned length, uint8_t *redChannel, uint8_t *greenChannel, uint8_t *blueChannel)
|
||||
{
|
||||
if (length == 0 || index >= length || length > MAX_NUM_LEDS)
|
||||
{
|
||||
|
Reference in New Issue
Block a user