diff --git a/CHANGELOG.md b/CHANGELOG.md index 42eef6efd..0b9322004 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -31,6 +31,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Change links from http to https (#1067) ### Fixed +- Properly save Hue light state between sessions (#1014) - AVAHI included in Webserver (#996) - Also allow an 8-LED configuration when using Karatelight (#1037) - Fix #1007 - LED's retain last state after clearing a source (#1008) @@ -42,6 +43,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Fix typos (#1051) - Fix Python reset thread state + ### Removed - Replace Multi-Lightpack by multi-instance Lightpack configuration (#1049) diff --git a/libsrc/leddevice/dev_net/LedDevicePhilipsHue.cpp b/libsrc/leddevice/dev_net/LedDevicePhilipsHue.cpp index c2fa61a5a..714a25b74 100644 --- a/libsrc/leddevice/dev_net/LedDevicePhilipsHue.cpp +++ b/libsrc/leddevice/dev_net/LedDevicePhilipsHue.cpp @@ -419,13 +419,7 @@ void LedDevicePhilipsHueBridge::log(const char* msg, const char* type, ...) cons QJsonDocument LedDevicePhilipsHueBridge::getAllBridgeInfos() { - // Read Groups/ Lights and Light-Ids - _restApi->setPath(API_ROOT); - - httpResponse response = _restApi->get(); - checkApiError(response.getBody()); - - return response.getBody(); + return get(API_ROOT); } bool LedDevicePhilipsHueBridge::initMaps() @@ -628,6 +622,15 @@ bool LedDevicePhilipsHueBridge::checkApiError(const QJsonDocument &response) return apiError; } +QJsonDocument LedDevicePhilipsHueBridge::get(const QString& route) +{ + _restApi->setPath(route); + + httpResponse response = _restApi->get(); + checkApiError(response.getBody()); + return response.getBody(); +} + QJsonDocument LedDevicePhilipsHueBridge::post(const QString& route, const QString& content) { _restApi->setPath(route); @@ -637,6 +640,12 @@ QJsonDocument LedDevicePhilipsHueBridge::post(const QString& route, const QStrin return response.getBody(); } +QJsonDocument LedDevicePhilipsHueBridge::getLightState(unsigned int lightId) +{ + DebugIf( verbose, _log, "GetLightState [%u]", lightId ); + return get( QString("%1/%2").arg( API_LIGHTS ).arg( lightId ) ); +} + void LedDevicePhilipsHueBridge::setLightState(unsigned int lightId, const QString &state) { DebugIf( verbose, _log, "SetLightState [%u]: %s", lightId, QSTRING_CSTR(state) ); @@ -645,10 +654,8 @@ void LedDevicePhilipsHueBridge::setLightState(unsigned int lightId, const QStrin QJsonDocument LedDevicePhilipsHueBridge::getGroupState(unsigned int groupId) { - _restApi->setPath( QString("%1/%2").arg( API_GROUPS ).arg( groupId ) ); - httpResponse response = _restApi->get(); - checkApiError(response.getBody()); - return response.getBody(); + DebugIf( verbose, _log, "GetGroupState [%u]", groupId ); + return get( QString("%1/%2").arg( API_GROUPS ).arg( groupId ) ); } QJsonDocument LedDevicePhilipsHueBridge::setGroupState(unsigned int groupId, bool state) @@ -712,8 +719,6 @@ PhilipsHueLight::PhilipsHueLight(Logger* log, unsigned int id, QJsonObject value _colorBlack = {0.0, 0.0, 0.0}; } - saveOriginalState(values); - _lightname = values["name"].toString().trimmed().replace("\"", ""); Info(_log, "Light ID %d (\"%s\", LED index \"%d\") created", id, QSTRING_CSTR(_lightname), ledidx ); } @@ -806,7 +811,6 @@ LedDevicePhilipsHue::LedDevicePhilipsHue(const QJsonObject& deviceConfig) , _switchOffOnBlack(false) , _brightnessFactor(1.0) , _transitionTime(1) - , _lightStatesRestored(false) , _isInitLeds(false) , _lightsCount(0) , _groupId(0) @@ -1277,42 +1281,54 @@ void LedDevicePhilipsHue::stop() } int LedDevicePhilipsHue::open() +{ + int retval = 0; + _isDeviceReady = true; + + return retval; +} + +int LedDevicePhilipsHue::close() { int retval = -1; - _isDeviceReady = false; - if( _useHueEntertainmentAPI ) + retval = LedDevicePhilipsHueBridge::close(); + + return retval; +} + +bool LedDevicePhilipsHue::switchOn() { - if ( openStream() ) + Debug(_log, ""); + + bool rc = false; + + if ( _isOn ) { - // Everything is OK, device is ready - _isDeviceReady = true; - retval = 0; + rc = true; } else { - // TODO: Stop device (or fallback to classic mode) - suggest to stop device to meet user expectation - //_useHueEntertainmentAPI = false; -to be removed, if 1 - // Everything is OK, device is ready + if ( _isEnabled && _isDeviceInitialised ) + { + storeState(); + + if ( _useHueEntertainmentAPI) + { + if ( openStream() ) + { + _isOn = true; + rc = true; } } - else + else if ( powerOn() ) { - // Classic mode, everything is OK, device is ready - _isDeviceReady = true; - retval = 0; + _isOn = true; + rc = true; + } } - - return retval; } - -int LedDevicePhilipsHue::close() -{ - int retval = -1; - - retval = LedDevicePhilipsHueBridge::close(); - - return retval; + return rc; } bool LedDevicePhilipsHue::switchOff() @@ -1322,7 +1338,10 @@ bool LedDevicePhilipsHue::switchOff() this->stopBlackTimeoutTimer(); stop_retry_left = 3; + if (_useHueEntertainmentAPI) + { stopStream(); + } return LedDevicePhilipsHueBridge::switchOff(); } @@ -1563,11 +1582,14 @@ bool LedDevicePhilipsHue::storeState() if ( _isRestoreOrigState ) { - // Save device's original state - //_orignalStateValues = get device's state; - - // TODO: Move saveOriginalState out of the HueLight constructor, - // as the light state may have change since last close and needs to be stored again before reopen + if( !_lightIds.empty() ) + { + for ( PhilipsHueLight& light : _lights ) + { + QJsonObject values = getLightState(light.getId()).object(); + light.saveOriginalState(values); + } + } } return rc; @@ -1577,11 +1599,9 @@ bool LedDevicePhilipsHue::restoreState() { bool rc = true; - if ( _isRestoreOrigState && !_lightStatesRestored ) + if ( _isRestoreOrigState ) { // Restore device's original state - _lightStatesRestored = true; - if( !_lightIds.empty() ) { for ( PhilipsHueLight& light : _lights ) diff --git a/libsrc/leddevice/dev_net/LedDevicePhilipsHue.h b/libsrc/leddevice/dev_net/LedDevicePhilipsHue.h index baac3cddd..1ed2be6c2 100644 --- a/libsrc/leddevice/dev_net/LedDevicePhilipsHue.h +++ b/libsrc/leddevice/dev_net/LedDevicePhilipsHue.h @@ -152,12 +152,11 @@ class PhilipsHueLight /// @return the color space of the light determined by the model id reported by the bridge. CiColorTriangle getColorSpace() const; + void saveOriginalState(const QJsonObject& values); QString getOriginalState() const; private: - void saveOriginalState(const QJsonObject& values); - Logger* _log; /// light id unsigned int _id; @@ -200,12 +199,23 @@ class LedDevicePhilipsHueBridge : public ProviderUdpSSL bool initRestAPI(const QString &hostname, int port, const QString &token ); /// - /// @param route the route of the POST request. + /// @brief Perform a REST-API GET + /// + /// @param route the route of the GET request. /// + /// @return the content of the GET request. + /// + QJsonDocument get(const QString& route); + + /// + /// @brief Perform a REST-API POST + /// + /// @param route the route of the POST request. /// @param content the content of the POST request. /// QJsonDocument post(const QString& route, const QString& content); + QJsonDocument getLightState(unsigned int lightId); void setLightState(unsigned int lightId = 0, const QString &state = ""); QMap getLightMap() const; @@ -421,7 +431,7 @@ public slots: /// /// @return True if success /// - //bool switchOn() override; + bool switchOn() override; /// /// @brief Switch the LEDs off. @@ -525,7 +535,6 @@ private slots: /// The default of the Hue lights is 400 ms, but we may want it snappier. int _transitionTime; - bool _lightStatesRestored; bool _isInitLeds; /// Array of the light ids.