diff --git a/CHANGELOG.md b/CHANGELOG.md index 42eef6ef..0b932200 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 c2fa61a5..714a25b7 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) @@ -1278,30 +1282,8 @@ void LedDevicePhilipsHue::stop() int LedDevicePhilipsHue::open() { - int retval = -1; - _isDeviceReady = false; - - if( _useHueEntertainmentAPI ) - { - if ( openStream() ) - { - // Everything is OK, device is ready - _isDeviceReady = true; - retval = 0; - } - 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 - } - } - else - { - // Classic mode, everything is OK, device is ready - _isDeviceReady = true; - retval = 0; - } + int retval = 0; + _isDeviceReady = true; return retval; } @@ -1315,6 +1297,40 @@ int LedDevicePhilipsHue::close() return retval; } +bool LedDevicePhilipsHue::switchOn() + { + Debug(_log, ""); + + bool rc = false; + + if ( _isOn ) + { + rc = true; + } + else + { + if ( _isEnabled && _isDeviceInitialised ) + { + storeState(); + + if ( _useHueEntertainmentAPI) + { + if ( openStream() ) + { + _isOn = true; + rc = true; + } + } + else if ( powerOn() ) + { + _isOn = true; + rc = true; + } + } +} + return rc; +} + bool LedDevicePhilipsHue::switchOff() { Debug(_log, ""); @@ -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 baac3cdd..1ed2be6c 100644 --- a/libsrc/leddevice/dev_net/LedDevicePhilipsHue.h +++ b/libsrc/leddevice/dev_net/LedDevicePhilipsHue.h @@ -152,12 +152,11 @@ public: /// @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 @@ public: 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 @@ protected: /// /// @return True if success /// - //bool switchOn() override; + bool switchOn() override; /// /// @brief Switch the LEDs off. @@ -525,7 +535,6 @@ private: /// 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.