diff --git a/assets/webconfig/js/wizard.js b/assets/webconfig/js/wizard.js index 09a5cd14..aeee28c8 100644 --- a/assets/webconfig/js/wizard.js +++ b/assets/webconfig/js/wizard.js @@ -1263,7 +1263,7 @@ function startWizardWLED(e) var hostAddress = conf_editor.getEditor("root.specificOptions.host").getValue(); if(hostAddress != "") { - getProperties_wled(hostAddress); + getProperties_wled(hostAddress,"info"); identify_wled(hostAddress) } diff --git a/docs/development/LedDevice_Flows.drawio b/docs/development/LedDevice_Flows.drawio new file mode 100644 index 00000000..c7646141 --- /dev/null +++ b/docs/development/LedDevice_Flows.drawio @@ -0,0 +1 @@ +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 \ No newline at end of file diff --git a/docs/development/LedDevice_Flows.png b/docs/development/LedDevice_Flows.png new file mode 100644 index 00000000..f6ce9ee0 Binary files /dev/null and b/docs/development/LedDevice_Flows.png differ diff --git a/include/hyperion/Hyperion.h b/include/hyperion/Hyperion.h index 09d8be6b..9b301e2f 100644 --- a/include/hyperion/Hyperion.h +++ b/include/hyperion/Hyperion.h @@ -473,6 +473,9 @@ private slots: /// void handleNewVideoMode(VideoMode mode) { _currVideoMode = mode; } + + void handlPriorityChangedLedDevice(const quint8& priority); + private: friend class HyperionDaemon; friend class HyperionIManager; diff --git a/include/hyperion/PriorityMuxer.h b/include/hyperion/PriorityMuxer.h index fb444628..c1feedf5 100644 --- a/include/hyperion/PriorityMuxer.h +++ b/include/hyperion/PriorityMuxer.h @@ -109,6 +109,13 @@ public: /// int getCurrentPriority() const { return _currentPriority; } + /// + /// Returns the previous priority before current priority + /// + /// @return The previous priority + /// + int getPreviousPriority() const { return _previousPriority; } + /// /// Returns the state (enabled/disabled) of a specific priority channel /// @param priority The priority channel @@ -193,13 +200,6 @@ signals: /// void timeRunner(); - /// - /// @brief A priority has been added (registerInput()) or deleted, method clear or timeout clear - /// @param priority The priority which has changed - /// @param state If true it was added else it was removed! - /// - void priorityChanged(quint8 priority, bool state); - /// /// @brief Emits whenever the visible priority has changed /// @param priority The new visible priority @@ -261,6 +261,9 @@ private: /// The current priority (lowest value in _activeInputs) int _currentPriority; + /// The previous priority before current priority + int _previousPriority; + /// The manual select priority set with setPriority int _manualSelectedPriority; diff --git a/include/leddevice/LedDevice.h b/include/leddevice/LedDevice.h index c58fa925..a9dcf0c5 100644 --- a/include/leddevice/LedDevice.h +++ b/include/leddevice/LedDevice.h @@ -64,13 +64,6 @@ public: /// void setLedCount(unsigned int ledCount); - /// - /// @brief Check, if the device is enabled. - /// - /// @return True, if enabled - /// - bool isEnabled() const { return _isEnabled; } - /// /// @brief Set a device's latch time. /// @@ -81,6 +74,15 @@ public: /// void setLatchTime(int latchTime_ms); + /// + /// @brief Set a device's rewrite time. + /// + /// Rewrite time is the time frame a devices requires to be refreshed, if no updated happened in the meantime. + /// + /// @param[in] rewriteTime_ms Rewrite time in milliseconds + /// + void setRewriteTime(int rewriteTime_ms); + /// /// @brief Discover devices of this type available (for configuration). /// @note Mainly used for network devices. Allows to find devices, e.g. via ssdp, mDNS or cloud ways. @@ -172,15 +174,6 @@ public slots: /// virtual int updateLeds(const std::vector& ledValues); - /// - /// @brief Enables/disables the device for output. - /// - /// If the device is not ready, it will not be enabled. - /// - /// @param[in] enable The new state of the device - /// - void setEnable(bool enable); - /// /// @brief Get the currently defined LatchTime. /// @@ -188,6 +181,13 @@ public slots: /// int getLatchTime() const { return _latchTime_ms; } + /// + /// @brief Get the currently defined RewriteTime. + /// + /// @return Rewrite time in milliseconds + /// + int getRewriteTime() const { return _refreshTimerInterval_ms; } + /// /// @brief Get the number of LEDs supported by the device. /// @@ -212,7 +212,46 @@ public slots: /// /// @return True, if enabled /// - inline bool componentState() const { return isEnabled(); } + inline bool componentState() const { return _isEnabled; } + + /// + /// @brief Enables the device for output. + /// + /// If the device is not ready, it will not be enabled. + /// + void enable(); + + /// + /// @brief Disables the device for output. + /// + void disable(); + + /// + /// @brief Switch the LEDs on. + /// + /// Takes care that the device is opened and powered-on. + /// Depending on the configuration, the device may store its current state for later restore. + /// @see powerOn, storeState + /// + /// @return True, if success + /// + virtual bool switchOn(); + + /// + /// @brief Switch the LEDs off. + /// + /// Takes care that the LEDs and device are switched-off and device is closed. + /// Depending on the configuration, the device may be powered-off or restored to its previous state. + /// @see powerOff, restoreState + /// + /// @return True, if success + /// + virtual bool switchOff(); + + bool switchOnOff(bool onState) + { + return onState == true ? switchOn() : switchOff(); + } signals: /// @@ -264,28 +303,6 @@ protected: /// virtual int writeBlack(int numberOfBlack=1); - /// - /// @brief Switch the LEDs on. - /// - /// Takes care that the device is opened and powered-on. - /// Depending on the configuration, the device may store its current state for later restore. - /// @see powerOn, storeState - /// - /// @return True, if success - /// - virtual bool switchOn(); - - /// - /// @brief Switch the LEDs off. - /// - /// Takes care that the LEDs and device are switched-off and device is closed. - /// Depending on the configuration, the device may be powered-off or restored to its previous state. - /// @see powerOff, restoreState - /// - /// @return True, if success - /// - virtual bool switchOff(); - /// /// @brief Power-/turn on the LED-device. /// @@ -378,6 +395,9 @@ protected: /// Is the device ready for processing? bool _isDeviceReady; + /// Is the device switched on? + bool _isOn; + /// Is the device in error state and stopped? bool _isDeviceInError; diff --git a/include/leddevice/LedDeviceWrapper.h b/include/leddevice/LedDeviceWrapper.h index 0413d03e..4526bc03 100644 --- a/include/leddevice/LedDeviceWrapper.h +++ b/include/leddevice/LedDeviceWrapper.h @@ -90,8 +90,27 @@ signals: /// int updateLeds(const std::vector& ledValues); - void setEnable(bool enable); - void closeLedDevice(); + /// + /// @brief Enables the LED-Device. + /// + void enable(); + + /// + /// @brief Disables the LED-Device. + /// + void disable(); + + /// + /// @brief Switch the LEDs on. + /// + void switchOn(); + + /// + /// @brief Switch the LEDs off. + /// + void switchOff(); + + void stopLedDevice(); private slots: /// diff --git a/libsrc/hyperion/Hyperion.cpp b/libsrc/hyperion/Hyperion.cpp index 90de57c5..b5b81003 100644 --- a/libsrc/hyperion/Hyperion.cpp +++ b/libsrc/hyperion/Hyperion.cpp @@ -87,6 +87,7 @@ void Hyperion::start() // connect Hyperion::update with Muxer visible priority changes as muxer updates independent connect(&_muxer, &PriorityMuxer::visiblePriorityChanged, this, &Hyperion::update); + connect(&_muxer, &PriorityMuxer::visiblePriorityChanged, this, &Hyperion::handlPriorityChangedLedDevice); connect(&_muxer, &PriorityMuxer::visibleComponentChanged, this, &Hyperion::handleVisibleComponentChanged); // listens for ComponentRegister changes of COMP_ALL to perform core enable/disable actions @@ -530,6 +531,26 @@ void Hyperion::handleVisibleComponentChanged(hyperion::Components comp) _raw2ledAdjustment->setBacklightEnabled((comp != hyperion::COMP_COLOR && comp != hyperion::COMP_EFFECT)); } +void Hyperion::handlPriorityChangedLedDevice(const quint8& priority) +{ + quint8 previousPriority = _muxer.getPreviousPriority(); + + Debug(_log,"priority[%u], previousPriority[%u]", priority, previousPriority); + if ( priority == PriorityMuxer::LOWEST_PRIORITY) + { + Debug(_log,"No source left -> switch LED-Device off"); + emit _ledDeviceWrapper->switchOff(); + } + else + { + if ( previousPriority == PriorityMuxer::LOWEST_PRIORITY ) + { + Debug(_log,"new source available -> switch LED-Device on"); + emit _ledDeviceWrapper->switchOn(); + } + } +} + void Hyperion::update() { // Obtain the current priority channel diff --git a/libsrc/hyperion/PriorityMuxer.cpp b/libsrc/hyperion/PriorityMuxer.cpp index b029434c..b7687e25 100644 --- a/libsrc/hyperion/PriorityMuxer.cpp +++ b/libsrc/hyperion/PriorityMuxer.cpp @@ -18,6 +18,7 @@ PriorityMuxer::PriorityMuxer(int ledCount, QObject * parent) : QObject(parent) , _log(Logger::getInstance("HYPERION")) , _currentPriority(PriorityMuxer::LOWEST_PRIORITY) + , _previousPriority(_currentPriority) , _manualSelectedPriority(256) , _activeInputs() , _lowestPriorityInfo() @@ -156,7 +157,6 @@ void PriorityMuxer::registerInput(int priority, hyperion::Components component, if(newInput) { Debug(_log,"Register new input '%s/%s' with priority %d as inactive", QSTRING_CSTR(origin), hyperion::componentToIdString(component), priority); - emit priorityChanged(priority, true); emit prioritiesChanged(); return; } @@ -255,7 +255,6 @@ bool PriorityMuxer::clearInput(uint8_t priority) Debug(_log,"Removed source priority %d",priority); // on clear success update _currentPriority setCurrentTime(); - emit priorityChanged(priority, false); emit prioritiesChanged(); return true; } @@ -266,6 +265,7 @@ void PriorityMuxer::clearAll(bool forceClearAll) { if (forceClearAll) { + _previousPriority = _currentPriority; _activeInputs.clear(); _currentPriority = PriorityMuxer::LOWEST_PRIORITY; _activeInputs[_currentPriority] = _lowestPriorityInfo; @@ -296,7 +296,6 @@ void PriorityMuxer::setCurrentTime() quint8 tPrio = infoIt->priority; infoIt = _activeInputs.erase(infoIt); Debug(_log,"Timeout clear for priority %d",tPrio); - emit priorityChanged(tPrio, false); emit prioritiesChanged(); } else @@ -329,6 +328,7 @@ void PriorityMuxer::setCurrentTime() // apply & emit on change (after apply!) if (_currentPriority != newPriority) { + _previousPriority = _currentPriority; _currentPriority = newPriority; Debug(_log, "Set visible priority to %d", newPriority); emit visiblePriorityChanged(newPriority); diff --git a/libsrc/leddevice/LedDevice.cpp b/libsrc/leddevice/LedDevice.cpp index 4d727b20..4229f2da 100644 --- a/libsrc/leddevice/LedDevice.cpp +++ b/libsrc/leddevice/LedDevice.cpp @@ -28,6 +28,7 @@ LedDevice::LedDevice(const QJsonObject& deviceConfig, QObject* parent) , _isEnabled(false) , _isDeviceInitialised(false) , _isDeviceReady(false) + , _isOn(false) , _isDeviceInError(false) , _isInSwitchOff (false) , _lastWriteTime(QDateTime::currentDateTime()) @@ -62,14 +63,15 @@ void LedDevice::start() { // Everything is OK -> enable device _isDeviceInitialised = true; - setEnable(true); + this->enable(); } } void LedDevice::stop() { - setEnable(false); + this->disable(); this->stopRefreshTimer(); + Info(_log, " Stopped LedDevice '%s'", QSTRING_CSTR(_activeDeviceType) ); } int LedDevice::open() @@ -99,27 +101,39 @@ void LedDevice::setInError(const QString& errorMsg) emit enableStateChanged(_isEnabled); } -void LedDevice::setEnable(bool enable) +void LedDevice::enable() { - bool isSwitched = false; - // switch off device when disabled, default: set black to LEDs when they should go off - if ( _isEnabled && !enable) + if ( !_isEnabled ) { - isSwitched = switchOff(); - } - else - { - // switch on device when enabled - if ( !_isEnabled && enable) + _isDeviceInError = false; + + if ( ! _isDeviceReady ) { - isSwitched = switchOn(); + open(); + } + + if ( _isDeviceReady ) + { + _isEnabled = true; + if ( switchOn() ) + { + emit enableStateChanged(_isEnabled); + } } } +} - if ( isSwitched ) +void LedDevice::disable() +{ + if ( _isEnabled ) { - _isEnabled = enable; - emit enableStateChanged(enable); + _isEnabled = false; + this->stopRefreshTimer(); + + switchOff(); + close(); + + emit enableStateChanged(_isEnabled); } } @@ -133,30 +147,11 @@ bool LedDevice::init(const QJsonObject &deviceConfig) Debug(_log, "deviceConfig: [%s]", QString(QJsonDocument(_devConfig).toJson(QJsonDocument::Compact)).toUtf8().constData() ); _colorOrder = deviceConfig["colorOrder"].toString("RGB"); - setLedCount(static_cast( deviceConfig["currentLedCount"].toInt(1) )); // property injected to reflect real led count - _latchTime_ms =deviceConfig["latchTime"].toInt( _latchTime_ms ); - _refreshTimerInterval_ms = deviceConfig["rewriteTime"].toInt( _refreshTimerInterval_ms); + setLedCount( static_cast( deviceConfig["currentLedCount"].toInt(1) ) ); // property injected to reflect real led count + setLatchTime( deviceConfig["latchTime"].toInt( _latchTime_ms ) ); + setRewriteTime ( deviceConfig["rewriteTime"].toInt( _refreshTimerInterval_ms) ); - if ( _refreshTimerInterval_ms > 0 ) - { - _isRefreshEnabled = true; - - if (_refreshTimerInterval_ms <= _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, _refreshTimerInterval_ms, new_refresh_timer_interval); - _refreshTimerInterval_ms = new_refresh_timer_interval; - _refreshTimer->setInterval( _refreshTimerInterval_ms ); - } - - Debug(_log, "Refresh interval = %dms",_refreshTimerInterval_ms ); - _refreshTimer->setInterval( _refreshTimerInterval_ms ); - - _lastWriteTime = QDateTime::currentDateTime(); - - this->startRefreshTimer(); - } return true; } @@ -176,9 +171,9 @@ void LedDevice::stopRefreshTimer() int LedDevice::updateLeds(const std::vector& ledValues) { int retval = 0; - if ( !isEnabled() || !_isDeviceReady || _isDeviceInError ) + if ( !_isEnabled || !_isOn || !_isDeviceReady || _isDeviceInError ) { - //std::cout << "LedDevice::updateLeds(), LedDevice NOT ready!" << std::endl; + //std::cout << "LedDevice::updateLeds(), LedDevice NOT ready! "; return -1; } else @@ -256,20 +251,20 @@ int LedDevice::writeBlack(int numberOfBlack) bool LedDevice::switchOn() { bool rc = false; - if ( _isDeviceInitialised && ! _isDeviceReady && ! _isEnabled ) + + if ( _isOn ) { - _isDeviceInError = false; - if ( open() < 0 ) - { - rc = false; - } - else + rc = true; + } + else + { + if ( _isEnabled &&_isDeviceInitialised ) { storeState(); if ( powerOn() ) { - _isEnabled = true; + _isOn = true; rc = true; } } @@ -281,38 +276,37 @@ bool LedDevice::switchOff() { bool rc = false; - if ( _isDeviceInitialised ) + if ( !_isOn ) { - // Disable device to ensure no standard Led updates are written/processed - _isEnabled = false; - _isInSwitchOff = true; - - this->stopRefreshTimer(); - rc = true; - - if ( _isDeviceReady ) + } + else + { + if ( _isDeviceInitialised ) { - if ( _isRestoreOrigState ) - { - //Restore devices state - restoreState(); - } - else - { - powerOff(); - } + // Disable device to ensure no standard Led updates are written/processed + _isOn = false; + _isInSwitchOff = true; - } - if ( close() < 0 ) - { - rc = false; + rc = true; + + if ( _isDeviceReady ) + { + if ( _isRestoreOrigState ) + { + //Restore devices state + restoreState(); + } + else + { + powerOff(); + } + } } } return rc; } - bool LedDevice::powerOff() { bool rc = false; @@ -403,7 +397,33 @@ void LedDevice::setLedCount(unsigned int ledCount) void LedDevice::setLatchTime( int latchTime_ms ) { _latchTime_ms = latchTime_ms; - Debug(_log, "LatchTime updated to %dms", this->getLatchTime()); + Debug(_log, "LatchTime updated to %dms", _latchTime_ms); +} + +void LedDevice::setRewriteTime( int rewriteTime_ms ) +{ + _refreshTimerInterval_ms = rewriteTime_ms; + + if ( _refreshTimerInterval_ms > 0 ) + { + + _isRefreshEnabled = true; + + if (_refreshTimerInterval_ms <= _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, _refreshTimerInterval_ms, new_refresh_timer_interval); + _refreshTimerInterval_ms = new_refresh_timer_interval; + _refreshTimer->setInterval( _refreshTimerInterval_ms ); + } + + Debug(_log, "Refresh interval = %dms",_refreshTimerInterval_ms ); + _refreshTimer->setInterval( _refreshTimerInterval_ms ); + + _lastWriteTime = QDateTime::currentDateTime(); + } + + Debug(_log, "RewriteTime updated to %dms", _refreshTimerInterval_ms); } void LedDevice::printLedValues(const std::vector& ledValues) diff --git a/libsrc/leddevice/LedDeviceWrapper.cpp b/libsrc/leddevice/LedDeviceWrapper.cpp index f03dce46..43a35e79 100644 --- a/libsrc/leddevice/LedDeviceWrapper.cpp +++ b/libsrc/leddevice/LedDeviceWrapper.cpp @@ -52,14 +52,19 @@ void LedDeviceWrapper::createLedDevice(const QJsonObject& config) thread->setObjectName("LedDeviceThread"); _ledDevice = LedDeviceFactory::construct(config); _ledDevice->moveToThread(thread); - // setup thread management connect(thread, &QThread::started, _ledDevice, &LedDevice::start); // further signals connect(this, &LedDeviceWrapper::updateLeds, _ledDevice, &LedDevice::updateLeds, Qt::QueuedConnection); - connect(this, &LedDeviceWrapper::setEnable, _ledDevice, &LedDevice::setEnable); - connect(this, &LedDeviceWrapper::closeLedDevice, _ledDevice, &LedDevice::stop, Qt::BlockingQueuedConnection); + + connect(this, &LedDeviceWrapper::enable, _ledDevice, &LedDevice::enable); + connect(this, &LedDeviceWrapper::disable, _ledDevice, &LedDevice::disable); + + connect(this, &LedDeviceWrapper::switchOn, _ledDevice, &LedDevice::switchOn); + connect(this, &LedDeviceWrapper::switchOff, _ledDevice, &LedDevice::switchOff); + + connect(this, &LedDeviceWrapper::stopLedDevice, _ledDevice, &LedDevice::stop, Qt::BlockingQueuedConnection); connect(_ledDevice, &LedDevice::enableStateChanged, this, &LedDeviceWrapper::handleInternalEnableState, Qt::QueuedConnection); @@ -155,7 +160,14 @@ void LedDeviceWrapper::handleComponentState(hyperion::Components component, bool { if(component == hyperion::COMP_LEDDEVICE) { - emit setEnable(state); + if ( state ) + { + emit enable(); + } + else + { + emit disable(); + } //Get device's state, considering situations where it is not ready bool deviceState = false; @@ -169,13 +181,17 @@ void LedDeviceWrapper::handleInternalEnableState(bool newState) { _hyperion->setNewComponentState(hyperion::COMP_LEDDEVICE, newState); _enabled = newState; + + if (_enabled) + { + _hyperion->update(); + } } void LedDeviceWrapper::stopDeviceThread() { // turns the LEDs off & stop refresh timers - emit closeLedDevice(); - std::cout << "[hyperiond LedDeviceWrapper] LedDevice \'" << QSTRING_CSTR(getActiveDeviceType()) << "\' closed" << std::endl; + emit stopLedDevice(); // get current thread QThread* oldThread = _ledDevice->thread(); diff --git a/libsrc/leddevice/dev_net/LedDeviceNanoleaf.cpp b/libsrc/leddevice/dev_net/LedDeviceNanoleaf.cpp index 706d59b3..5b45a4d5 100644 --- a/libsrc/leddevice/dev_net/LedDeviceNanoleaf.cpp +++ b/libsrc/leddevice/dev_net/LedDeviceNanoleaf.cpp @@ -116,11 +116,12 @@ LedDeviceNanoleaf::~LedDeviceNanoleaf() bool LedDeviceNanoleaf::init(const QJsonObject &deviceConfig) { // Overwrite non supported/required features - _devConfig["latchTime"] = 0; + setLatchTime(0); + setRewriteTime(0); + if (deviceConfig["rewriteTime"].toInt(0) > 0) { Info (_log, "Device Nanoleaf does not require rewrites. Refresh time is ignored."); - _devConfig["rewriteTime"] = 0; } DebugIf(verbose, _log, "deviceConfig: [%s]", QString(QJsonDocument(_devConfig).toJson(QJsonDocument::Compact)).toUtf8().constData() ); @@ -133,7 +134,7 @@ bool LedDeviceNanoleaf::init(const QJsonObject &deviceConfig) Debug(_log, "DeviceType : %s", QSTRING_CSTR( this->getActiveDeviceType() )); Debug(_log, "LedCount : %u", configuredLedCount); Debug(_log, "ColorOrder : %s", QSTRING_CSTR( this->getColorOrder() )); - Debug(_log, "RefreshTime : %d", _refreshTimerInterval_ms); + Debug(_log, "RewriteTime : %d", this->getRewriteTime()); Debug(_log, "LatchTime : %d", this->getLatchTime()); // Read panel organisation configuration @@ -356,8 +357,6 @@ int LedDeviceNanoleaf::open() int retval = -1; _isDeviceReady = false; - // Set Nanoleaf to External Control (UDP) mode - Debug(_log, "Set Nanoleaf to External Control (UDP) streaming mode"); QJsonDocument responseDoc = changeToExternalControlMode(); // Resolve port for Light Panels QJsonObject jsonStreamControllInfo = responseDoc.object(); @@ -488,6 +487,8 @@ bool LedDeviceNanoleaf::powerOn() { if ( _isDeviceReady) { + changeToExternalControlMode(); + //Power-on Nanoleaf device _restApi->setPath(API_STATE); _restApi->put( getOnOffRequest(true) ); @@ -514,6 +515,7 @@ QString LedDeviceNanoleaf::getOnOffRequest(bool isOn) const QJsonDocument LedDeviceNanoleaf::changeToExternalControlMode() { + Debug(_log, "Set Nanoleaf to External Control (UDP) streaming mode"); _extControlVersion = EXTCTRLVER_V2; //Enable UDP Mode v2 diff --git a/libsrc/leddevice/dev_net/LedDeviceWled.cpp b/libsrc/leddevice/dev_net/LedDeviceWled.cpp index 64b5fec0..4884e3f3 100644 --- a/libsrc/leddevice/dev_net/LedDeviceWled.cpp +++ b/libsrc/leddevice/dev_net/LedDeviceWled.cpp @@ -215,15 +215,10 @@ QJsonObject LedDeviceWled::getProperties(const QJsonObject& params) apiPort = API_DEFAULT_PORT; } - if ( filter.startsWith("/") ) - filter.remove(0,1); - initRestAPI(apiHost, apiPort); - _restApi->setPath(API_PATH_INFO); + _restApi->setPath(filter); - // Perform request - // TODO: WLED::getProperties - Check, if filter is supported - httpResponse response = _restApi->put(filter); + httpResponse response = _restApi->get(); if ( response.error() ) { Warning (_log, "%s get properties failed with error: '%s'", QSTRING_CSTR(_activeDeviceType), QSTRING_CSTR(response.getErrorReason())); diff --git a/libsrc/leddevice/dev_net/LedDeviceYeelight.cpp b/libsrc/leddevice/dev_net/LedDeviceYeelight.cpp index 602c6d5f..2fe39504 100644 --- a/libsrc/leddevice/dev_net/LedDeviceYeelight.cpp +++ b/libsrc/leddevice/dev_net/LedDeviceYeelight.cpp @@ -997,10 +997,11 @@ LedDevice* LedDeviceYeelight::construct(const QJsonObject &deviceConfig) bool LedDeviceYeelight::init(const QJsonObject &deviceConfig) { // Overwrite non supported/required features + setRewriteTime(0); + if (deviceConfig["rewriteTime"].toInt(0) > 0) { Info (_log, "Yeelights do not require rewrites. Refresh time is ignored."); - _devConfig["rewriteTime"] = 0; } DebugIf(verbose, _log, "deviceConfig: [%s]", QString(QJsonDocument(_devConfig).toJson(QJsonDocument::Compact)).toUtf8().constData() ); @@ -1012,7 +1013,7 @@ bool LedDeviceYeelight::init(const QJsonObject &deviceConfig) Debug(_log, "DeviceType : %s", QSTRING_CSTR( this->getActiveDeviceType() )); Debug(_log, "LedCount : %u", this->getLedCount()); Debug(_log, "ColorOrder : %s", QSTRING_CSTR( this->getColorOrder() )); - Debug(_log, "RefreshTime : %d", _refreshTimerInterval_ms); + Debug(_log, "RewriteTime : %d", this->getRewriteTime()); Debug(_log, "LatchTime : %d", this->getLatchTime()); //Get device specific configuration diff --git a/libsrc/leddevice/dev_serial/ProviderRs232.cpp b/libsrc/leddevice/dev_serial/ProviderRs232.cpp index 735806da..bab2ca6d 100644 --- a/libsrc/leddevice/dev_serial/ProviderRs232.cpp +++ b/libsrc/leddevice/dev_serial/ProviderRs232.cpp @@ -193,7 +193,7 @@ void ProviderRs232::setInError(const QString& errorMsg) int ProviderRs232::writeBytes(const qint64 size, const uint8_t *data) { - DebugIf(_isInSwitchOff, _log, "_inClosing [%d], enabled [%d], _deviceReady [%d], _frameDropCounter [%d]", _isInSwitchOff, this->isEnabled(), _isDeviceReady, _frameDropCounter); + DebugIf(_isInSwitchOff, _log, "_inClosing [%d], enabled [%d], _deviceReady [%d], _frameDropCounter [%d]", _isInSwitchOff, _isEnabled, _isDeviceReady, _frameDropCounter); int rc = 0; if (!_rs232Port.isOpen()) @@ -249,7 +249,7 @@ int ProviderRs232::writeBytes(const qint64 size, const uint8_t *data) } } - DebugIf(_isInSwitchOff, _log, "[%d], _inClosing[%d], enabled [%d], _deviceReady [%d]", rc, _isInSwitchOff, this->isEnabled(), _isDeviceReady); + DebugIf(_isInSwitchOff, _log, "[%d], _inClosing[%d], enabled [%d], _deviceReady [%d]", rc, _isInSwitchOff, _isEnabled, _isDeviceReady); return rc; }