Commit cd30bc7443f7fede4fce158b792397f44962b39c
Committed by
Moritz Wirger
1 parent
1eaf314c
Implement APICache to cache json values returned by the Hue API.
Showing
21 changed files
with
395 additions
and
394 deletions
include/hueplusplus/APICache.h
0 → 100644
| 1 | +/** | |
| 2 | + \file APICache.h | |
| 3 | + Copyright Notice\n | |
| 4 | + Copyright (C) 2020 Jan Rogall - developer\n | |
| 5 | + Copyright (C) 2020 Moritz Wirger - developer\n | |
| 6 | + | |
| 7 | + This file is part of hueplusplus. | |
| 8 | + | |
| 9 | + hueplusplus is free software: you can redistribute it and/or modify | |
| 10 | + it under the terms of the GNU Lesser General Public License as published by | |
| 11 | + the Free Software Foundation, either version 3 of the License, or | |
| 12 | + (at your option) any later version. | |
| 13 | + | |
| 14 | + hueplusplus is distributed in the hope that it will be useful, | |
| 15 | + but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| 16 | + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
| 17 | + GNU Lesser General Public License for more details. | |
| 18 | + | |
| 19 | + You should have received a copy of the GNU Lesser General Public License | |
| 20 | + along with hueplusplus. If not, see <http://www.gnu.org/licenses/>. | |
| 21 | +**/ | |
| 22 | + | |
| 23 | +#ifndef INCLUDE_API_CACHE_H | |
| 24 | +#define INCLUDE_API_CACHE_H | |
| 25 | + | |
| 26 | +#include <chrono> | |
| 27 | +#include <string> | |
| 28 | + | |
| 29 | +#include "HueCommandAPI.h" | |
| 30 | + | |
| 31 | +namespace hueplusplus | |
| 32 | +{ | |
| 33 | +//! \brief Caches API GET requests and refreshes regularly. | |
| 34 | +class APICache | |
| 35 | +{ | |
| 36 | +public: | |
| 37 | + //! \brief Constructs APICache | |
| 38 | + //! \param path URL appended after username, may be empty. | |
| 39 | + //! \param commands HueCommandAPI for making API requests. | |
| 40 | + //! \param refresh Interval between cache refreshing. May be 0 to always refresh. | |
| 41 | + APICache(const std::string& path, const HueCommandAPI& commands, std::chrono::steady_clock::duration refresh); | |
| 42 | + | |
| 43 | + //! \brief Refresh cache now. | |
| 44 | + //! \throws std::system_error when system or socket operations fail | |
| 45 | + //! \throws HueException when response contained no body | |
| 46 | + //! \throws HueAPIResponseException when response contains an error | |
| 47 | + //! \throws nlohmann::json::parse_error when response could not be parsed | |
| 48 | + void Refresh(); | |
| 49 | + | |
| 50 | + //! \brief Get cached value, refresh if necessary. | |
| 51 | + //! \throws std::system_error when system or socket operations fail | |
| 52 | + //! \throws HueException when response contained no body | |
| 53 | + //! \throws HueAPIResponseException when response contains an error | |
| 54 | + //! \throws nlohmann::json::parse_error when response could not be parsed | |
| 55 | + nlohmann::json& GetValue(); | |
| 56 | + //! \brief Get cached value, does not refresh. | |
| 57 | + const nlohmann::json& GetValue() const; | |
| 58 | + | |
| 59 | + //! \brief Get duration between refreshes. | |
| 60 | + std::chrono::steady_clock::duration GetRefreshDuration() const; | |
| 61 | + | |
| 62 | +private: | |
| 63 | + std::string path; | |
| 64 | + HueCommandAPI commands; | |
| 65 | + std::chrono::steady_clock::duration refreshDuration; | |
| 66 | + std::chrono::steady_clock::time_point lastRefresh; | |
| 67 | + nlohmann::json value; | |
| 68 | +}; | |
| 69 | +} // namespace hueplusplus | |
| 70 | + | |
| 71 | +#endif | ... | ... |
include/hueplusplus/Hue.h
| ... | ... | @@ -29,6 +29,7 @@ |
| 29 | 29 | #include <utility> |
| 30 | 30 | #include <vector> |
| 31 | 31 | |
| 32 | +#include "APICache.h" | |
| 32 | 33 | #include "BrightnessStrategy.h" |
| 33 | 34 | #include "ColorHueStrategy.h" |
| 34 | 35 | #include "ColorTemperatureStrategy.h" |
| ... | ... | @@ -123,8 +124,8 @@ public: |
| 123 | 124 | //! \param username String that specifies the username that is used to control |
| 124 | 125 | //! the bridge. This needs to be acquired in \ref requestUsername |
| 125 | 126 | //! \param handler HttpHandler for communication with the bridge |
| 126 | - Hue(const std::string& ip, const int port, const std::string& username, | |
| 127 | - std::shared_ptr<const IHttpHandler> handler); | |
| 127 | + Hue(const std::string& ip, const int port, const std::string& username, std::shared_ptr<const IHttpHandler> handler, | |
| 128 | + std::chrono::steady_clock::duration refreshDuration = std::chrono::seconds(10)); | |
| 128 | 129 | |
| 129 | 130 | //! \brief Function to get the ip address of the hue bridge |
| 130 | 131 | //! |
| ... | ... | @@ -249,19 +250,10 @@ public: |
| 249 | 250 | } |
| 250 | 251 | |
| 251 | 252 | private: |
| 252 | - //! \brief Function that refreshes the local \ref state of the Hue bridge | |
| 253 | - //! \throws std::system_error when system or socket operations fail | |
| 254 | - //! \throws HueException when response contained no body | |
| 255 | - //! \throws HueAPIResponseException when response contains an error | |
| 256 | - //! \throws nlohmann::json::parse_error when response could not be parsed | |
| 257 | - void refreshState(); | |
| 258 | - | |
| 259 | -private: | |
| 260 | 253 | std::string ip; //!< IP-Address of the hue bridge in dotted decimal notation |
| 261 | 254 | //!< like "192.168.2.1" |
| 262 | 255 | std::string username; //!< Username that is ussed to access the hue bridge |
| 263 | 256 | int port; |
| 264 | - nlohmann::json state; //!< The state of the hue bridge as it is returned from it | |
| 265 | 257 | std::map<uint8_t, HueLight> lights; //!< Maps ids to HueLights that are controlled by this bridge |
| 266 | 258 | |
| 267 | 259 | std::shared_ptr<BrightnessStrategy> simpleBrightnessStrategy; //!< Strategy that is used for controlling the |
| ... | ... | @@ -278,6 +270,7 @@ private: |
| 278 | 270 | std::shared_ptr<const IHttpHandler> http_handler; //!< A IHttpHandler that is used to communicate with the |
| 279 | 271 | //!< bridge |
| 280 | 272 | HueCommandAPI commands; //!< A HueCommandAPI that is used to communicate with the bridge |
| 273 | + APICache stateCache; //!< The state of the hue bridge as it is returned from it | |
| 281 | 274 | }; |
| 282 | 275 | } // namespace hueplusplus |
| 283 | 276 | ... | ... |
include/hueplusplus/HueLight.h
| ... | ... | @@ -25,6 +25,7 @@ |
| 25 | 25 | |
| 26 | 26 | #include <memory> |
| 27 | 27 | |
| 28 | +#include "APICache.h" | |
| 28 | 29 | #include "BrightnessStrategy.h" |
| 29 | 30 | #include "ColorHueStrategy.h" |
| 30 | 31 | #include "ColorTemperatureStrategy.h" |
| ... | ... | @@ -698,7 +699,8 @@ protected: |
| 698 | 699 | //! \throws nlohmann::json::parse_error when response could not be parsed |
| 699 | 700 | HueLight(int id, const HueCommandAPI& commands, std::shared_ptr<const BrightnessStrategy> brightnessStrategy, |
| 700 | 701 | std::shared_ptr<const ColorTemperatureStrategy> colorTempStrategy, |
| 701 | - std::shared_ptr<const ColorHueStrategy> colorHueStrategy); | |
| 702 | + std::shared_ptr<const ColorHueStrategy> colorHueStrategy, | |
| 703 | + std::chrono::steady_clock::duration refreshDuration = std::chrono::seconds(10)); | |
| 702 | 704 | |
| 703 | 705 | //! \brief Protected function that sets the brightness strategy. |
| 704 | 706 | //! |
| ... | ... | @@ -735,26 +737,6 @@ protected: |
| 735 | 737 | //! \param commandAPI the new HueCommandAPI |
| 736 | 738 | virtual void setCommandAPI(const HueCommandAPI& commandAPI) { commands = commandAPI; }; |
| 737 | 739 | |
| 738 | - //! \brief Function that turns the light on without refreshing its state. | |
| 739 | - //! | |
| 740 | - //! \param transition Optional parameter to set the transition from current state to new standard is 4 = 400ms | |
| 741 | - //! \return Bool that is true on success | |
| 742 | - //! \throws std::system_error when system or socket operations fail | |
| 743 | - //! \throws HueException when response contained no body | |
| 744 | - //! \throws HueAPIResponseException when response contains an error | |
| 745 | - //! \throws nlohmann::json::parse_error when response could not be parsed | |
| 746 | - virtual bool OnNoRefresh(uint8_t transition = 4); | |
| 747 | - | |
| 748 | - //! \brief Function that turns the light off without refreshing its state. | |
| 749 | - //! | |
| 750 | - //! \param transition Optional parameter to set the transition from current state to new standard is 4 = 400ms | |
| 751 | - //! \return Bool that is true on success | |
| 752 | - //! \throws std::system_error when system or socket operations fail | |
| 753 | - //! \throws HueException when response contained no body | |
| 754 | - //! \throws HueAPIResponseException when response contains an error | |
| 755 | - //! \throws nlohmann::json::parse_error when response could not be parsed | |
| 756 | - virtual bool OffNoRefresh(uint8_t transition = 4); | |
| 757 | - | |
| 758 | 740 | //! \brief Utility function to send a put request to the light. |
| 759 | 741 | //! |
| 760 | 742 | //! \throws nlohmann::json::parse_error if the reply could not be parsed |
| ... | ... | @@ -768,16 +750,9 @@ protected: |
| 768 | 750 | //! \throws nlohmann::json::parse_error when response could not be parsed |
| 769 | 751 | virtual nlohmann::json SendPutRequest(const nlohmann::json& request, const std::string& subPath, FileInfo fileInfo); |
| 770 | 752 | |
| 771 | - //! \brief Virtual function that refreshes the \ref state of the light. | |
| 772 | - //! \throws std::system_error when system or socket operations fail | |
| 773 | - //! \throws HueException when response contained no body | |
| 774 | - //! \throws HueAPIResponseException when response contains an error | |
| 775 | - //! \throws nlohmann::json::parse_error when response could not be parsed | |
| 776 | - virtual void refreshState(); | |
| 777 | - | |
| 778 | 753 | protected: |
| 779 | 754 | int id; //!< holds the id of the light |
| 780 | - nlohmann::json state; //!< holds the current state of the light updated by \ref refreshState | |
| 755 | + APICache state; //!< holds the current state of the light updated by \ref refreshState | |
| 781 | 756 | ColorType colorType; //!< holds the \ref ColorType of the light |
| 782 | 757 | |
| 783 | 758 | std::shared_ptr<const BrightnessStrategy> | ... | ... |
src/APICache.cpp
0 → 100644
| 1 | +#include "hueplusplus/APICache.h" | |
| 2 | +/** | |
| 3 | + \file BaseHttpHandler.cpp | |
| 4 | + Copyright Notice\n | |
| 5 | + Copyright (C) 2020 Jan Rogall - developer\n | |
| 6 | + Copyright (C) 2020 Moritz Wirger - developer\n | |
| 7 | + | |
| 8 | + This file is part of hueplusplus. | |
| 9 | + | |
| 10 | + hueplusplus is free software: you can redistribute it and/or modify | |
| 11 | + it under the terms of the GNU Lesser General Public License as published by | |
| 12 | + the Free Software Foundation, either version 3 of the License, or | |
| 13 | + (at your option) any later version. | |
| 14 | + | |
| 15 | + hueplusplus is distributed in the hope that it will be useful, | |
| 16 | + but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| 17 | + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
| 18 | + GNU Lesser General Public License for more details. | |
| 19 | + | |
| 20 | + You should have received a copy of the GNU Lesser General Public License | |
| 21 | + along with hueplusplus. If not, see <http://www.gnu.org/licenses/>. | |
| 22 | +**/ | |
| 23 | + | |
| 24 | +#include "hueplusplus/HueExceptionMacro.h" | |
| 25 | + | |
| 26 | +hueplusplus::APICache::APICache( | |
| 27 | + const std::string& path, const HueCommandAPI& commands, std::chrono::steady_clock::duration refresh) | |
| 28 | + : path(path), | |
| 29 | + commands(commands), | |
| 30 | + refreshDuration(refresh), | |
| 31 | + lastRefresh(std::chrono::steady_clock::duration::zero()) | |
| 32 | +{} | |
| 33 | + | |
| 34 | +void hueplusplus::APICache::Refresh() { | |
| 35 | + value = commands.GETRequest(path, nlohmann::json::object(), CURRENT_FILE_INFO); | |
| 36 | +} | |
| 37 | + | |
| 38 | +nlohmann::json& hueplusplus::APICache::GetValue() | |
| 39 | +{ | |
| 40 | + if (std::chrono::steady_clock::now() >= lastRefresh + refreshDuration) | |
| 41 | + { | |
| 42 | + Refresh(); | |
| 43 | + } | |
| 44 | + return value; | |
| 45 | +} | |
| 46 | + | |
| 47 | +const nlohmann::json& hueplusplus::APICache::GetValue() const | |
| 48 | +{ | |
| 49 | + return value; | |
| 50 | +} | |
| 51 | + | |
| 52 | +std::chrono::steady_clock::duration hueplusplus::APICache::GetRefreshDuration() const | |
| 53 | +{ | |
| 54 | + return refreshDuration; | |
| 55 | +} | ... | ... |
src/CMakeLists.txt
src/ExtendedColorHueStrategy.cpp
| ... | ... | @@ -32,13 +32,14 @@ namespace hueplusplus |
| 32 | 32 | { |
| 33 | 33 | bool ExtendedColorHueStrategy::alertHueSaturation(uint16_t hue, uint8_t sat, HueLight& light) const |
| 34 | 34 | { |
| 35 | - light.refreshState(); | |
| 36 | - std::string cType = light.state["state"]["colormode"].get<std::string>(); | |
| 37 | - bool on = light.state["state"]["on"].get<bool>(); | |
| 35 | + // Careful, only use state until any light function might refresh the value and invalidate the reference | |
| 36 | + const nlohmann::json& state = light.state.GetValue()["state"]; | |
| 37 | + std::string cType = state["colormode"].get<std::string>(); | |
| 38 | + bool on = state["on"].get<bool>(); | |
| 38 | 39 | if (cType == "hs") |
| 39 | 40 | { |
| 40 | - uint16_t oldHue = light.state["state"]["hue"].get<uint16_t>(); | |
| 41 | - uint8_t oldSat = light.state["state"]["sat"].get<uint8_t>(); | |
| 41 | + uint16_t oldHue = state["hue"].get<uint16_t>(); | |
| 42 | + uint8_t oldSat = state["sat"].get<uint8_t>(); | |
| 42 | 43 | if (!light.setColorHueSaturation(hue, sat, 1)) |
| 43 | 44 | { |
| 44 | 45 | return false; |
| ... | ... | @@ -52,7 +53,7 @@ bool ExtendedColorHueStrategy::alertHueSaturation(uint16_t hue, uint8_t sat, Hue |
| 52 | 53 | if (!on) |
| 53 | 54 | { |
| 54 | 55 | light.setColorHueSaturation(oldHue, oldSat, 1); |
| 55 | - return light.OffNoRefresh(1); | |
| 56 | + return light.Off(1); | |
| 56 | 57 | } |
| 57 | 58 | else |
| 58 | 59 | { |
| ... | ... | @@ -61,8 +62,8 @@ bool ExtendedColorHueStrategy::alertHueSaturation(uint16_t hue, uint8_t sat, Hue |
| 61 | 62 | } |
| 62 | 63 | else if (cType == "xy") |
| 63 | 64 | { |
| 64 | - float oldX = light.state["state"]["xy"][0].get<float>(); | |
| 65 | - float oldY = light.state["state"]["xy"][1].get<float>(); | |
| 65 | + float oldX = state["xy"][0].get<float>(); | |
| 66 | + float oldY = state["xy"][1].get<float>(); | |
| 66 | 67 | if (!light.setColorHueSaturation(hue, sat, 1)) |
| 67 | 68 | { |
| 68 | 69 | return false; |
| ... | ... | @@ -76,7 +77,7 @@ bool ExtendedColorHueStrategy::alertHueSaturation(uint16_t hue, uint8_t sat, Hue |
| 76 | 77 | if (!on) |
| 77 | 78 | { |
| 78 | 79 | light.setColorXY(oldX, oldY, 1); |
| 79 | - return light.OffNoRefresh(1); | |
| 80 | + return light.Off(1); | |
| 80 | 81 | } |
| 81 | 82 | else |
| 82 | 83 | { |
| ... | ... | @@ -85,7 +86,7 @@ bool ExtendedColorHueStrategy::alertHueSaturation(uint16_t hue, uint8_t sat, Hue |
| 85 | 86 | } |
| 86 | 87 | else if (cType == "ct") |
| 87 | 88 | { |
| 88 | - uint16_t oldCT = light.state["state"]["ct"].get<uint16_t>(); | |
| 89 | + uint16_t oldCT = state["ct"].get<uint16_t>(); | |
| 89 | 90 | if (!light.setColorHueSaturation(hue, sat, 1)) |
| 90 | 91 | { |
| 91 | 92 | return false; |
| ... | ... | @@ -99,7 +100,7 @@ bool ExtendedColorHueStrategy::alertHueSaturation(uint16_t hue, uint8_t sat, Hue |
| 99 | 100 | if (!on) |
| 100 | 101 | { |
| 101 | 102 | light.setColorTemperature(oldCT, 1); |
| 102 | - return light.OffNoRefresh(1); | |
| 103 | + return light.Off(1); | |
| 103 | 104 | } |
| 104 | 105 | else |
| 105 | 106 | { |
| ... | ... | @@ -114,13 +115,14 @@ bool ExtendedColorHueStrategy::alertHueSaturation(uint16_t hue, uint8_t sat, Hue |
| 114 | 115 | |
| 115 | 116 | bool ExtendedColorHueStrategy::alertXY(float x, float y, HueLight& light) const |
| 116 | 117 | { |
| 117 | - light.refreshState(); | |
| 118 | - std::string cType = light.state["state"]["colormode"].get<std::string>(); | |
| 119 | - bool on = light.state["state"]["on"].get<bool>(); | |
| 118 | + // Careful, only use state until any light function might refresh the value and invalidate the reference | |
| 119 | + const nlohmann::json& state = light.state.GetValue()["state"]; | |
| 120 | + std::string cType = state["colormode"].get<std::string>(); | |
| 121 | + bool on = state["on"].get<bool>(); | |
| 120 | 122 | if (cType == "hs") |
| 121 | 123 | { |
| 122 | - uint16_t oldHue = light.state["state"]["hue"].get<uint16_t>(); | |
| 123 | - uint8_t oldSat = light.state["state"]["sat"].get<uint8_t>(); | |
| 124 | + uint16_t oldHue = state["hue"].get<uint16_t>(); | |
| 125 | + uint8_t oldSat = state["sat"].get<uint8_t>(); | |
| 124 | 126 | if (!light.setColorXY(x, y, 1)) |
| 125 | 127 | { |
| 126 | 128 | return false; |
| ... | ... | @@ -134,7 +136,7 @@ bool ExtendedColorHueStrategy::alertXY(float x, float y, HueLight& light) const |
| 134 | 136 | if (!on) |
| 135 | 137 | { |
| 136 | 138 | light.setColorHueSaturation(oldHue, oldSat, 1); |
| 137 | - return light.OffNoRefresh(1); | |
| 139 | + return light.Off(1); | |
| 138 | 140 | } |
| 139 | 141 | else |
| 140 | 142 | { |
| ... | ... | @@ -143,8 +145,8 @@ bool ExtendedColorHueStrategy::alertXY(float x, float y, HueLight& light) const |
| 143 | 145 | } |
| 144 | 146 | else if (cType == "xy") |
| 145 | 147 | { |
| 146 | - float oldX = light.state["state"]["xy"][0].get<float>(); | |
| 147 | - float oldY = light.state["state"]["xy"][1].get<float>(); | |
| 148 | + float oldX = state["xy"][0].get<float>(); | |
| 149 | + float oldY = state["xy"][1].get<float>(); | |
| 148 | 150 | if (!light.setColorXY(x, y, 1)) |
| 149 | 151 | { |
| 150 | 152 | return false; |
| ... | ... | @@ -158,7 +160,7 @@ bool ExtendedColorHueStrategy::alertXY(float x, float y, HueLight& light) const |
| 158 | 160 | if (!on) |
| 159 | 161 | { |
| 160 | 162 | light.setColorXY(oldX, oldY, 1); |
| 161 | - return light.OffNoRefresh(1); | |
| 163 | + return light.Off(1); | |
| 162 | 164 | } |
| 163 | 165 | else |
| 164 | 166 | { |
| ... | ... | @@ -167,7 +169,7 @@ bool ExtendedColorHueStrategy::alertXY(float x, float y, HueLight& light) const |
| 167 | 169 | } |
| 168 | 170 | else if (cType == "ct") |
| 169 | 171 | { |
| 170 | - uint16_t oldCT = light.state["state"]["ct"].get<uint16_t>(); | |
| 172 | + uint16_t oldCT = state["ct"].get<uint16_t>(); | |
| 171 | 173 | if (!light.setColorXY(x, y, 1)) |
| 172 | 174 | { |
| 173 | 175 | return false; |
| ... | ... | @@ -181,7 +183,7 @@ bool ExtendedColorHueStrategy::alertXY(float x, float y, HueLight& light) const |
| 181 | 183 | if (!on) |
| 182 | 184 | { |
| 183 | 185 | light.setColorTemperature(oldCT, 1); |
| 184 | - return light.OffNoRefresh(1); | |
| 186 | + return light.Off(1); | |
| 185 | 187 | } |
| 186 | 188 | else |
| 187 | 189 | { |
| ... | ... | @@ -196,13 +198,14 @@ bool ExtendedColorHueStrategy::alertXY(float x, float y, HueLight& light) const |
| 196 | 198 | |
| 197 | 199 | bool ExtendedColorHueStrategy::alertRGB(uint8_t r, uint8_t g, uint8_t b, HueLight& light) const |
| 198 | 200 | { |
| 199 | - light.refreshState(); | |
| 200 | - std::string cType = light.state["state"]["colormode"].get<std::string>(); | |
| 201 | - bool on = light.state["state"]["on"].get<bool>(); | |
| 201 | + // Careful, only use state until any light function might refresh the value and invalidate the reference | |
| 202 | + const nlohmann::json& state = light.state.GetValue()["state"]; | |
| 203 | + std::string cType = state["colormode"]; | |
| 204 | + bool on = state["on"]; | |
| 202 | 205 | if (cType == "hs") |
| 203 | 206 | { |
| 204 | - uint16_t oldHue = light.state["state"]["hue"].get<uint16_t>(); | |
| 205 | - uint8_t oldSat = light.state["state"]["sat"].get<uint8_t>(); | |
| 207 | + uint16_t oldHue = state["hue"].get<uint16_t>(); | |
| 208 | + uint8_t oldSat = state["sat"].get<uint8_t>(); | |
| 206 | 209 | if (!light.setColorRGB(r, g, b, 1)) |
| 207 | 210 | { |
| 208 | 211 | return false; |
| ... | ... | @@ -216,7 +219,7 @@ bool ExtendedColorHueStrategy::alertRGB(uint8_t r, uint8_t g, uint8_t b, HueLigh |
| 216 | 219 | if (!on) |
| 217 | 220 | { |
| 218 | 221 | light.setColorHueSaturation(oldHue, oldSat, 1); |
| 219 | - return light.OffNoRefresh(1); | |
| 222 | + return light.Off(1); | |
| 220 | 223 | } |
| 221 | 224 | else |
| 222 | 225 | { |
| ... | ... | @@ -225,8 +228,8 @@ bool ExtendedColorHueStrategy::alertRGB(uint8_t r, uint8_t g, uint8_t b, HueLigh |
| 225 | 228 | } |
| 226 | 229 | else if (cType == "xy") |
| 227 | 230 | { |
| 228 | - float oldX = light.state["state"]["xy"][0].get<float>(); | |
| 229 | - float oldY = light.state["state"]["xy"][1].get<float>(); | |
| 231 | + float oldX = state["xy"][0].get<float>(); | |
| 232 | + float oldY = state["xy"][1].get<float>(); | |
| 230 | 233 | if (!light.setColorRGB(r, g, b, 1)) |
| 231 | 234 | { |
| 232 | 235 | return false; |
| ... | ... | @@ -240,7 +243,7 @@ bool ExtendedColorHueStrategy::alertRGB(uint8_t r, uint8_t g, uint8_t b, HueLigh |
| 240 | 243 | if (!on) |
| 241 | 244 | { |
| 242 | 245 | light.setColorXY(oldX, oldY, 1); |
| 243 | - return light.OffNoRefresh(1); | |
| 246 | + return light.Off(1); | |
| 244 | 247 | } |
| 245 | 248 | else |
| 246 | 249 | { |
| ... | ... | @@ -249,7 +252,7 @@ bool ExtendedColorHueStrategy::alertRGB(uint8_t r, uint8_t g, uint8_t b, HueLigh |
| 249 | 252 | } |
| 250 | 253 | else if (cType == "ct") |
| 251 | 254 | { |
| 252 | - uint16_t oldCT = light.state["state"]["ct"].get<uint16_t>(); | |
| 255 | + uint16_t oldCT = state["ct"].get<uint16_t>(); | |
| 253 | 256 | if (!light.setColorRGB(r, g, b, 1)) |
| 254 | 257 | { |
| 255 | 258 | return false; |
| ... | ... | @@ -263,7 +266,7 @@ bool ExtendedColorHueStrategy::alertRGB(uint8_t r, uint8_t g, uint8_t b, HueLigh |
| 263 | 266 | if (!on) |
| 264 | 267 | { |
| 265 | 268 | light.setColorTemperature(oldCT, 1); |
| 266 | - return light.OffNoRefresh(1); | |
| 269 | + return light.Off(1); | |
| 267 | 270 | } |
| 268 | 271 | else |
| 269 | 272 | { | ... | ... |
src/ExtendedColorTemperatureStrategy.cpp
| ... | ... | @@ -35,17 +35,18 @@ namespace hueplusplus |
| 35 | 35 | bool ExtendedColorTemperatureStrategy::setColorTemperature( |
| 36 | 36 | unsigned int mired, uint8_t transition, HueLight& light) const |
| 37 | 37 | { |
| 38 | - light.refreshState(); | |
| 38 | + // Careful, only use state until any light function might refresh the value and invalidate the reference | |
| 39 | + const nlohmann::json& state = light.state.GetValue()["state"]; | |
| 39 | 40 | nlohmann::json request = nlohmann::json::object(); |
| 40 | 41 | if (transition != 4) |
| 41 | 42 | { |
| 42 | 43 | request["transitiontime"] = transition; |
| 43 | 44 | } |
| 44 | - if (light.state["state"]["on"] != true) | |
| 45 | + if (state["on"] != true) | |
| 45 | 46 | { |
| 46 | 47 | request["on"] = true; |
| 47 | 48 | } |
| 48 | - if (light.state["state"]["ct"] != mired || light.state["state"]["colormode"] != "ct") | |
| 49 | + if (state["ct"] != mired || state["colormode"] != "ct") | |
| 49 | 50 | { |
| 50 | 51 | if (mired > 500) |
| 51 | 52 | { |
| ... | ... | @@ -72,13 +73,14 @@ bool ExtendedColorTemperatureStrategy::setColorTemperature( |
| 72 | 73 | |
| 73 | 74 | bool ExtendedColorTemperatureStrategy::alertTemperature(unsigned int mired, HueLight& light) const |
| 74 | 75 | { |
| 75 | - light.refreshState(); | |
| 76 | - std::string cType = light.state["state"]["colormode"].get<std::string>(); | |
| 77 | - bool on = light.state["state"]["on"].get<bool>(); | |
| 76 | + // Careful, only use state until any light function might refresh the value and invalidate the reference | |
| 77 | + const nlohmann::json& state = light.state.GetValue()["state"]; | |
| 78 | + std::string cType = state["colormode"].get<std::string>(); | |
| 79 | + bool on = state["on"].get<bool>(); | |
| 78 | 80 | if (cType == "hs") |
| 79 | 81 | { |
| 80 | - uint16_t oldHue = light.state["state"]["hue"].get<uint16_t>(); | |
| 81 | - uint8_t oldSat = light.state["state"]["sat"].get<uint8_t>(); | |
| 82 | + uint16_t oldHue = state["hue"].get<uint16_t>(); | |
| 83 | + uint8_t oldSat = state["sat"].get<uint8_t>(); | |
| 82 | 84 | if (!light.setColorTemperature(mired, 1)) |
| 83 | 85 | { |
| 84 | 86 | return false; |
| ... | ... | @@ -92,7 +94,7 @@ bool ExtendedColorTemperatureStrategy::alertTemperature(unsigned int mired, HueL |
| 92 | 94 | if (!on) |
| 93 | 95 | { |
| 94 | 96 | light.setColorHueSaturation(oldHue, oldSat, 1); |
| 95 | - return light.OffNoRefresh(1); | |
| 97 | + return light.Off(1); | |
| 96 | 98 | } |
| 97 | 99 | else |
| 98 | 100 | { |
| ... | ... | @@ -101,8 +103,8 @@ bool ExtendedColorTemperatureStrategy::alertTemperature(unsigned int mired, HueL |
| 101 | 103 | } |
| 102 | 104 | else if (cType == "xy") |
| 103 | 105 | { |
| 104 | - float oldX = light.state["state"]["xy"][0].get<float>(); | |
| 105 | - float oldY = light.state["state"]["xy"][1].get<float>(); | |
| 106 | + float oldX = state["xy"][0].get<float>(); | |
| 107 | + float oldY = state["xy"][1].get<float>(); | |
| 106 | 108 | if (!light.setColorTemperature(mired, 1)) |
| 107 | 109 | { |
| 108 | 110 | return false; |
| ... | ... | @@ -116,7 +118,7 @@ bool ExtendedColorTemperatureStrategy::alertTemperature(unsigned int mired, HueL |
| 116 | 118 | if (!on) |
| 117 | 119 | { |
| 118 | 120 | light.setColorXY(oldX, oldY, 1); |
| 119 | - return light.OffNoRefresh(1); | |
| 121 | + return light.Off(1); | |
| 120 | 122 | } |
| 121 | 123 | else |
| 122 | 124 | { |
| ... | ... | @@ -125,7 +127,7 @@ bool ExtendedColorTemperatureStrategy::alertTemperature(unsigned int mired, HueL |
| 125 | 127 | } |
| 126 | 128 | else if (cType == "ct") |
| 127 | 129 | { |
| 128 | - uint16_t oldCT = light.state["state"]["ct"].get<uint16_t>(); | |
| 130 | + uint16_t oldCT = state["ct"].get<uint16_t>(); | |
| 129 | 131 | if (!light.setColorTemperature(mired, 1)) |
| 130 | 132 | { |
| 131 | 133 | return false; |
| ... | ... | @@ -139,7 +141,7 @@ bool ExtendedColorTemperatureStrategy::alertTemperature(unsigned int mired, HueL |
| 139 | 141 | if (!on) |
| 140 | 142 | { |
| 141 | 143 | light.setColorTemperature(oldCT, 1); |
| 142 | - return light.OffNoRefresh(1); | |
| 144 | + return light.Off(1); | |
| 143 | 145 | } |
| 144 | 146 | else |
| 145 | 147 | { | ... | ... |
src/Hue.cpp
| ... | ... | @@ -135,8 +135,8 @@ std::string HueFinder::ParseDescription(const std::string& description) |
| 135 | 135 | return std::string(); |
| 136 | 136 | } |
| 137 | 137 | |
| 138 | -Hue::Hue( | |
| 139 | - const std::string& ip, const int port, const std::string& username, std::shared_ptr<const IHttpHandler> handler) | |
| 138 | +Hue::Hue(const std::string& ip, const int port, const std::string& username, | |
| 139 | + std::shared_ptr<const IHttpHandler> handler, std::chrono::steady_clock::duration refreshDuration) | |
| 140 | 140 | : ip(ip), |
| 141 | 141 | port(port), |
| 142 | 142 | username(username), |
| ... | ... | @@ -146,7 +146,8 @@ Hue::Hue( |
| 146 | 146 | simpleColorTemperatureStrategy(std::make_shared<SimpleColorTemperatureStrategy>()), |
| 147 | 147 | extendedColorTemperatureStrategy(std::make_shared<ExtendedColorTemperatureStrategy>()), |
| 148 | 148 | http_handler(std::move(handler)), |
| 149 | - commands(ip, port, username, http_handler) | |
| 149 | + commands(ip, port, username, http_handler), | |
| 150 | + stateCache("", commands, refreshDuration) | |
| 150 | 151 | {} |
| 151 | 152 | |
| 152 | 153 | std::string Hue::getBridgeIP() |
| ... | ... | @@ -189,6 +190,7 @@ std::string Hue::requestUsername() |
| 189 | 190 | username = jsonUser.get<std::string>(); |
| 190 | 191 | // Update commands with new username and ip |
| 191 | 192 | commands = HueCommandAPI(ip, port, username, http_handler); |
| 193 | + stateCache = APICache("", commands, stateCache.GetRefreshDuration()); | |
| 192 | 194 | std::cout << "Success! Link button was pressed!\n"; |
| 193 | 195 | std::cout << "Username is \"" << username << "\"\n"; |
| 194 | 196 | break; |
| ... | ... | @@ -228,18 +230,16 @@ HueLight& Hue::getLight(int id) |
| 228 | 230 | auto pos = lights.find(id); |
| 229 | 231 | if (pos != lights.end()) |
| 230 | 232 | { |
| 231 | - pos->second.refreshState(); | |
| 233 | + pos->second.state.Refresh(); | |
| 232 | 234 | return pos->second; |
| 233 | 235 | } |
| 234 | - refreshState(); | |
| 235 | - if (!state["lights"].count(std::to_string(id))) | |
| 236 | + const nlohmann::json& lightsCache = stateCache.GetValue()["lights"]; | |
| 237 | + if (!lightsCache.count(std::to_string(id))) | |
| 236 | 238 | { |
| 237 | 239 | std::cerr << "Error in Hue getLight(): light with id " << id << " is not valid\n"; |
| 238 | 240 | throw HueException(CURRENT_FILE_INFO, "Light id is not valid"); |
| 239 | 241 | } |
| 240 | - // std::cout << state["lights"][std::to_string(id)] << std::endl; | |
| 241 | - std::string type = state["lights"][std::to_string(id)]["modelid"].get<std::string>(); | |
| 242 | - // std::cout << type << std::endl; | |
| 242 | + std::string type = lightsCache[std::to_string(id)]["modelid"].get<std::string>(); | |
| 243 | 243 | auto light = MakeHueLight()(type, id, commands, simpleBrightnessStrategy, extendedColorTemperatureStrategy, |
| 244 | 244 | simpleColorTemperatureStrategy, extendedColorHueStrategy, simpleColorHueStrategy); |
| 245 | 245 | lights.emplace(id, light); |
| ... | ... | @@ -260,9 +260,9 @@ bool Hue::removeLight(int id) |
| 260 | 260 | |
| 261 | 261 | std::vector<std::reference_wrapper<HueLight>> Hue::getAllLights() |
| 262 | 262 | { |
| 263 | - refreshState(); | |
| 264 | - nlohmann::json lightsState = state["lights"]; | |
| 265 | - for (nlohmann::json::iterator it = lightsState.begin(); it != lightsState.end(); ++it) | |
| 263 | + // No reference because getLight may invalidate it | |
| 264 | + nlohmann::json lightsState = stateCache.GetValue()["lights"]; | |
| 265 | + for (auto it = lightsState.begin(); it != lightsState.end(); ++it) | |
| 266 | 266 | { |
| 267 | 267 | getLight(std::stoi(it.key())); |
| 268 | 268 | } |
| ... | ... | @@ -276,13 +276,12 @@ std::vector<std::reference_wrapper<HueLight>> Hue::getAllLights() |
| 276 | 276 | |
| 277 | 277 | bool Hue::lightExists(int id) |
| 278 | 278 | { |
| 279 | - refreshState(); | |
| 280 | 279 | auto pos = lights.find(id); |
| 281 | 280 | if (pos != lights.end()) |
| 282 | 281 | { |
| 283 | 282 | return true; |
| 284 | 283 | } |
| 285 | - if (state["lights"].count(std::to_string(id))) | |
| 284 | + if (stateCache.GetValue()["lights"].count(std::to_string(id))) | |
| 286 | 285 | { |
| 287 | 286 | return true; |
| 288 | 287 | } |
| ... | ... | @@ -296,7 +295,7 @@ bool Hue::lightExists(int id) const |
| 296 | 295 | { |
| 297 | 296 | return true; |
| 298 | 297 | } |
| 299 | - if (state["lights"].count(std::to_string(id))) | |
| 298 | + if (stateCache.GetValue()["lights"].count(std::to_string(id))) | |
| 300 | 299 | { |
| 301 | 300 | return true; |
| 302 | 301 | } |
| ... | ... | @@ -437,23 +436,4 @@ std::string Hue::getPictureOfModel(const std::string& model_id) const |
| 437 | 436 | } |
| 438 | 437 | return ret; |
| 439 | 438 | } |
| 440 | - | |
| 441 | -void Hue::refreshState() | |
| 442 | -{ | |
| 443 | - if (username.empty()) | |
| 444 | - { | |
| 445 | - return; | |
| 446 | - } | |
| 447 | - nlohmann::json answer = commands.GETRequest("", nlohmann::json::object(), CURRENT_FILE_INFO); | |
| 448 | - if (answer.is_object() && answer.count("lights")) | |
| 449 | - { | |
| 450 | - state = answer; | |
| 451 | - } | |
| 452 | - else | |
| 453 | - { | |
| 454 | - std::cout << "Answer in Hue::refreshState of http_handler->GETJson(...) is " | |
| 455 | - "not expected!\nAnswer:\n\t" | |
| 456 | - << answer.dump() << std::endl; | |
| 457 | - } | |
| 458 | -} | |
| 459 | 439 | } // namespace hueplusplus | ... | ... |
src/HueCommandAPI.cpp
| ... | ... | @@ -81,7 +81,7 @@ nlohmann::json HueCommandAPI::PUTRequest(const std::string& path, const nlohmann |
| 81 | 81 | nlohmann::json HueCommandAPI::PUTRequest( |
| 82 | 82 | const std::string& path, const nlohmann::json& request, FileInfo fileInfo) const |
| 83 | 83 | { |
| 84 | - return HandleError(fileInfo, | |
| 84 | + return HandleError(std::move(fileInfo), | |
| 85 | 85 | RunWithTimeout(timeout, minDelay, [&]() { return httpHandler->PUTJson(CombinedPath(path), request, ip); })); |
| 86 | 86 | } |
| 87 | 87 | |
| ... | ... | @@ -93,7 +93,7 @@ nlohmann::json HueCommandAPI::GETRequest(const std::string& path, const nlohmann |
| 93 | 93 | nlohmann::json HueCommandAPI::GETRequest( |
| 94 | 94 | const std::string& path, const nlohmann::json& request, FileInfo fileInfo) const |
| 95 | 95 | { |
| 96 | - return HandleError(fileInfo, | |
| 96 | + return HandleError(std::move(fileInfo), | |
| 97 | 97 | RunWithTimeout(timeout, minDelay, [&]() { return httpHandler->GETJson(CombinedPath(path), request, ip); })); |
| 98 | 98 | } |
| 99 | 99 | |
| ... | ... | @@ -105,7 +105,7 @@ nlohmann::json HueCommandAPI::DELETERequest(const std::string& path, const nlohm |
| 105 | 105 | nlohmann::json HueCommandAPI::DELETERequest( |
| 106 | 106 | const std::string& path, const nlohmann::json& request, FileInfo fileInfo) const |
| 107 | 107 | { |
| 108 | - return HandleError(fileInfo, | |
| 108 | + return HandleError(std::move(fileInfo), | |
| 109 | 109 | RunWithTimeout(timeout, minDelay, [&]() { return httpHandler->DELETEJson(CombinedPath(path), request, ip); })); |
| 110 | 110 | } |
| 111 | 111 | ... | ... |
src/HueLight.cpp
| 1 | 1 | /** |
| 2 | - \file HueLight.cpp | |
| 3 | - Copyright Notice\n | |
| 4 | - Copyright (C) 2017 Jan Rogall - developer\n | |
| 5 | - Copyright (C) 2017 Moritz Wirger - developer\n | |
| 2 | + \file HueLight.cpp | |
| 3 | + Copyright Notice\n | |
| 4 | + Copyright (C) 2017 Jan Rogall - developer\n | |
| 5 | + Copyright (C) 2017 Moritz Wirger - developer\n | |
| 6 | 6 | |
| 7 | - This file is part of hueplusplus. | |
| 7 | + This file is part of hueplusplus. | |
| 8 | 8 | |
| 9 | - hueplusplus is free software: you can redistribute it and/or modify | |
| 10 | - it under the terms of the GNU Lesser General Public License as published by | |
| 11 | - the Free Software Foundation, either version 3 of the License, or | |
| 12 | - (at your option) any later version. | |
| 9 | + hueplusplus is free software: you can redistribute it and/or modify | |
| 10 | + it under the terms of the GNU Lesser General Public License as published by | |
| 11 | + the Free Software Foundation, either version 3 of the License, or | |
| 12 | + (at your option) any later version. | |
| 13 | 13 | |
| 14 | - hueplusplus is distributed in the hope that it will be useful, | |
| 15 | - but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| 16 | - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
| 17 | - GNU Lesser General Public License for more details. | |
| 14 | + hueplusplus is distributed in the hope that it will be useful, | |
| 15 | + but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| 16 | + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
| 17 | + GNU Lesser General Public License for more details. | |
| 18 | 18 | |
| 19 | - You should have received a copy of the GNU Lesser General Public License | |
| 20 | - along with hueplusplus. If not, see <http://www.gnu.org/licenses/>. | |
| 19 | + You should have received a copy of the GNU Lesser General Public License | |
| 20 | + along with hueplusplus. If not, see <http://www.gnu.org/licenses/>. | |
| 21 | 21 | **/ |
| 22 | 22 | |
| 23 | 23 | #include "hueplusplus/HueLight.h" |
| ... | ... | @@ -34,25 +34,60 @@ namespace hueplusplus |
| 34 | 34 | { |
| 35 | 35 | bool HueLight::On(uint8_t transition) |
| 36 | 36 | { |
| 37 | - refreshState(); | |
| 38 | - return OnNoRefresh(transition); | |
| 37 | + nlohmann::json request = nlohmann::json::object(); | |
| 38 | + if (transition != 4) | |
| 39 | + { | |
| 40 | + request["transitiontime"] = transition; | |
| 41 | + } | |
| 42 | + if (state.GetValue()["state"]["on"] != true) | |
| 43 | + { | |
| 44 | + request["on"] = true; | |
| 45 | + } | |
| 46 | + | |
| 47 | + if (!request.count("on")) | |
| 48 | + { | |
| 49 | + // Nothing needs to be changed | |
| 50 | + return true; | |
| 51 | + } | |
| 52 | + | |
| 53 | + nlohmann::json reply = SendPutRequest(request, "/state", CURRENT_FILE_INFO); | |
| 54 | + | |
| 55 | + // Check whether request was successful | |
| 56 | + return utils::validateReplyForLight(request, reply, id); | |
| 39 | 57 | } |
| 40 | 58 | |
| 41 | 59 | bool HueLight::Off(uint8_t transition) |
| 42 | 60 | { |
| 43 | - refreshState(); | |
| 44 | - return OffNoRefresh(transition); | |
| 61 | + nlohmann::json request = nlohmann::json::object(); | |
| 62 | + if (transition != 4) | |
| 63 | + { | |
| 64 | + request["transitiontime"] = transition; | |
| 65 | + } | |
| 66 | + if (state.GetValue()["state"]["on"] != false) | |
| 67 | + { | |
| 68 | + request["on"] = false; | |
| 69 | + } | |
| 70 | + | |
| 71 | + if (!request.count("on")) | |
| 72 | + { | |
| 73 | + // Nothing needs to be changed | |
| 74 | + return true; | |
| 75 | + } | |
| 76 | + | |
| 77 | + nlohmann::json reply = SendPutRequest(request, "/state", CURRENT_FILE_INFO); | |
| 78 | + | |
| 79 | + // Check whether request was successful | |
| 80 | + return utils::validateReplyForLight(request, reply, id); | |
| 45 | 81 | } |
| 46 | 82 | |
| 47 | 83 | bool HueLight::isOn() |
| 48 | 84 | { |
| 49 | - refreshState(); | |
| 50 | - return state["state"]["on"].get<bool>(); | |
| 85 | + return state.GetValue()["state"]["on"].get<bool>(); | |
| 51 | 86 | } |
| 52 | 87 | |
| 53 | 88 | bool HueLight::isOn() const |
| 54 | 89 | { |
| 55 | - return state["state"]["on"].get<bool>(); | |
| 90 | + return state.GetValue()["state"]["on"].get<bool>(); | |
| 56 | 91 | } |
| 57 | 92 | |
| 58 | 93 | int HueLight::getId() const |
| ... | ... | @@ -62,70 +97,52 @@ int HueLight::getId() const |
| 62 | 97 | |
| 63 | 98 | std::string HueLight::getType() const |
| 64 | 99 | { |
| 65 | - return state["type"].get<std::string>(); | |
| 100 | + return state.GetValue()["type"].get<std::string>(); | |
| 66 | 101 | } |
| 67 | 102 | |
| 68 | 103 | std::string HueLight::getName() |
| 69 | 104 | { |
| 70 | - refreshState(); | |
| 71 | - return state["name"].get<std::string>(); | |
| 105 | + return state.GetValue()["name"].get<std::string>(); | |
| 72 | 106 | } |
| 73 | 107 | |
| 74 | 108 | std::string HueLight::getName() const |
| 75 | 109 | { |
| 76 | - return state["name"].get<std::string>(); | |
| 110 | + return state.GetValue()["name"].get<std::string>(); | |
| 77 | 111 | } |
| 78 | 112 | |
| 79 | 113 | std::string HueLight::getModelId() const |
| 80 | 114 | { |
| 81 | - return state["modelid"].get<std::string>(); | |
| 115 | + return state.GetValue()["modelid"].get<std::string>(); | |
| 82 | 116 | } |
| 83 | 117 | |
| 84 | 118 | std::string HueLight::getUId() const |
| 85 | 119 | { |
| 86 | - if (state.count("uniqueid")) | |
| 87 | - { | |
| 88 | - return state["uniqueid"].get<std::string>(); | |
| 89 | - } | |
| 90 | - return std::string(); | |
| 120 | + return state.GetValue().value("uniqueid", std::string()); | |
| 91 | 121 | } |
| 92 | 122 | |
| 93 | 123 | std::string HueLight::getManufacturername() const |
| 94 | 124 | { |
| 95 | - if (state.count("manufacturername")) | |
| 96 | - { | |
| 97 | - return state["manufacturername"].get<std::string>(); | |
| 98 | - } | |
| 99 | - return std::string(); | |
| 125 | + return state.GetValue().value("manufacturername", std::string()); | |
| 100 | 126 | } |
| 101 | 127 | |
| 102 | 128 | std::string HueLight::getProductname() const |
| 103 | 129 | { |
| 104 | - if (state.count("productname")) | |
| 105 | - { | |
| 106 | - return state["productname"].get<std::string>(); | |
| 107 | - } | |
| 108 | - return std::string(); | |
| 130 | + return state.GetValue().value("productname", std::string()); | |
| 109 | 131 | } |
| 110 | 132 | |
| 111 | 133 | std::string HueLight::getLuminaireUId() const |
| 112 | 134 | { |
| 113 | - if (state.count("luminaireuniqueid")) | |
| 114 | - { | |
| 115 | - return state["luminaireuniqueid"].get<std::string>(); | |
| 116 | - } | |
| 117 | - return std::string(); | |
| 135 | + return state.GetValue().value("luminaireuniqueid", std::string()); | |
| 118 | 136 | } |
| 119 | 137 | |
| 120 | 138 | std::string HueLight::getSwVersion() |
| 121 | 139 | { |
| 122 | - refreshState(); | |
| 123 | - return state["swversion"].get<std::string>(); | |
| 140 | + return state.GetValue()["swversion"].get<std::string>(); | |
| 124 | 141 | } |
| 125 | 142 | |
| 126 | 143 | std::string HueLight::getSwVersion() const |
| 127 | 144 | { |
| 128 | - return state["swversion"].get<std::string>(); | |
| 145 | + return state.GetValue()["swversion"].get<std::string>(); | |
| 129 | 146 | } |
| 130 | 147 | |
| 131 | 148 | bool HueLight::setName(const std::string& name) |
| ... | ... | @@ -134,8 +151,9 @@ bool HueLight::setName(const std::string& name) |
| 134 | 151 | request["name"] = name; |
| 135 | 152 | nlohmann::json reply = SendPutRequest(request, "/name", CURRENT_FILE_INFO); |
| 136 | 153 | |
| 137 | - // Check whether request was successful | |
| 138 | - return utils::safeGetMember(reply, 0, "success", "/lights/" + std::to_string(id) + "/name") == name; | |
| 154 | + // Check whether request was successful (returned name is not necessarily the actually set name) | |
| 155 | + // If it already exists, a number is added, if it is too long to be returned, "Updated" is returned | |
| 156 | + return utils::safeGetMember(reply, 0, "success", "/lights/" + std::to_string(id) + "/name").is_string(); | |
| 139 | 157 | } |
| 140 | 158 | |
| 141 | 159 | ColorType HueLight::getColorType() const |
| ... | ... | @@ -167,89 +185,20 @@ HueLight::HueLight(int id, const HueCommandAPI& commands) : HueLight(id, command |
| 167 | 185 | |
| 168 | 186 | HueLight::HueLight(int id, const HueCommandAPI& commands, std::shared_ptr<const BrightnessStrategy> brightnessStrategy, |
| 169 | 187 | std::shared_ptr<const ColorTemperatureStrategy> colorTempStrategy, |
| 170 | - std::shared_ptr<const ColorHueStrategy> colorHueStrategy) | |
| 188 | + std::shared_ptr<const ColorHueStrategy> colorHueStrategy, std::chrono::steady_clock::duration refreshDuration) | |
| 171 | 189 | : id(id), |
| 172 | 190 | brightnessStrategy(std::move(brightnessStrategy)), |
| 173 | 191 | colorTemperatureStrategy(std::move(colorTempStrategy)), |
| 174 | 192 | colorHueStrategy(std::move(colorHueStrategy)), |
| 175 | - commands(commands) | |
| 176 | - | |
| 177 | -{ | |
| 178 | - refreshState(); | |
| 179 | -} | |
| 193 | + commands(commands), | |
| 194 | + state("/lights/" + std::to_string(id), commands, refreshDuration) | |
| 180 | 195 | |
| 181 | -bool HueLight::OnNoRefresh(uint8_t transition) | |
| 182 | 196 | { |
| 183 | - nlohmann::json request = nlohmann::json::object(); | |
| 184 | - if (transition != 4) | |
| 185 | - { | |
| 186 | - request["transitiontime"] = transition; | |
| 187 | - } | |
| 188 | - if (state["state"]["on"] != true) | |
| 189 | - { | |
| 190 | - request["on"] = true; | |
| 191 | - } | |
| 192 | - | |
| 193 | - if (!request.count("on")) | |
| 194 | - { | |
| 195 | - // Nothing needs to be changed | |
| 196 | - return true; | |
| 197 | - } | |
| 198 | - | |
| 199 | - nlohmann::json reply = SendPutRequest(request, "/state", CURRENT_FILE_INFO); | |
| 200 | - | |
| 201 | - // Check whether request was successful | |
| 202 | - return utils::validateReplyForLight(request, reply, id); | |
| 203 | -} | |
| 204 | - | |
| 205 | -bool HueLight::OffNoRefresh(uint8_t transition) | |
| 206 | -{ | |
| 207 | - nlohmann::json request = nlohmann::json::object(); | |
| 208 | - if (transition != 4) | |
| 209 | - { | |
| 210 | - request["transitiontime"] = transition; | |
| 211 | - } | |
| 212 | - if (state["state"]["on"] != false) | |
| 213 | - { | |
| 214 | - request["on"] = false; | |
| 215 | - } | |
| 216 | - | |
| 217 | - if (!request.count("on")) | |
| 218 | - { | |
| 219 | - // Nothing needs to be changed | |
| 220 | - return true; | |
| 221 | - } | |
| 222 | - | |
| 223 | - nlohmann::json reply = SendPutRequest(request, "/state", CURRENT_FILE_INFO); | |
| 224 | - | |
| 225 | - // Check whether request was successful | |
| 226 | - return utils::validateReplyForLight(request, reply, id); | |
| 197 | + state.Refresh(); | |
| 227 | 198 | } |
| 228 | 199 | |
| 229 | 200 | nlohmann::json HueLight::SendPutRequest(const nlohmann::json& request, const std::string& subPath, FileInfo fileInfo) |
| 230 | 201 | { |
| 231 | 202 | return commands.PUTRequest("/lights/" + std::to_string(id) + subPath, request, std::move(fileInfo)); |
| 232 | 203 | } |
| 233 | - | |
| 234 | -void HueLight::refreshState() | |
| 235 | -{ | |
| 236 | - // std::chrono::steady_clock::time_point start = | |
| 237 | - // std::chrono::steady_clock::now(); std::cout << "\tRefreshing lampstate of | |
| 238 | - // lamp with id: " << id << ", ip: " << ip << "\n"; | |
| 239 | - nlohmann::json answer | |
| 240 | - = commands.GETRequest("/lights/" + std::to_string(id), nlohmann::json::object(), CURRENT_FILE_INFO); | |
| 241 | - if (answer.count("state")) | |
| 242 | - { | |
| 243 | - state = answer; | |
| 244 | - } | |
| 245 | - else | |
| 246 | - { | |
| 247 | - std::cout << "Answer in HueLight::refreshState of " | |
| 248 | - "http_handler->GETJson(...) is not expected!\nAnswer:\n\t" | |
| 249 | - << answer.dump() << std::endl; | |
| 250 | - } | |
| 251 | - // std::cout << "\tRefresh state took: " << | |
| 252 | - // std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::steady_clock::now() | |
| 253 | - // - start).count() << "ms" << std::endl; | |
| 254 | -} | |
| 255 | 204 | } // namespace hueplusplus | ... | ... |
src/SimpleBrightnessStrategy.cpp
| ... | ... | @@ -33,12 +33,13 @@ namespace hueplusplus |
| 33 | 33 | { |
| 34 | 34 | bool SimpleBrightnessStrategy::setBrightness(unsigned int bri, uint8_t transition, HueLight& light) const |
| 35 | 35 | { |
| 36 | - light.refreshState(); | |
| 36 | + // Careful, only use state until any light function might refresh the value and invalidate the reference | |
| 37 | + const nlohmann::json& state = light.state.GetValue()["state"]; | |
| 37 | 38 | if (bri == 0) |
| 38 | 39 | { |
| 39 | - if (light.state["state"]["on"] == true) | |
| 40 | + if (state["on"] == true) | |
| 40 | 41 | { |
| 41 | - return light.OffNoRefresh(transition); | |
| 42 | + return light.Off(transition); | |
| 42 | 43 | } |
| 43 | 44 | else |
| 44 | 45 | { |
| ... | ... | @@ -52,11 +53,11 @@ bool SimpleBrightnessStrategy::setBrightness(unsigned int bri, uint8_t transitio |
| 52 | 53 | { |
| 53 | 54 | request["transitiontime"] = transition; |
| 54 | 55 | } |
| 55 | - if (light.state["state"]["on"] != true) | |
| 56 | + if (state["on"] != true) | |
| 56 | 57 | { |
| 57 | 58 | request["on"] = true; |
| 58 | 59 | } |
| 59 | - if (light.state["state"]["bri"] != bri) | |
| 60 | + if (state["bri"] != bri) | |
| 60 | 61 | { |
| 61 | 62 | if (bri > 254) |
| 62 | 63 | { |
| ... | ... | @@ -80,12 +81,11 @@ bool SimpleBrightnessStrategy::setBrightness(unsigned int bri, uint8_t transitio |
| 80 | 81 | |
| 81 | 82 | unsigned int SimpleBrightnessStrategy::getBrightness(HueLight& light) const |
| 82 | 83 | { |
| 83 | - light.refreshState(); | |
| 84 | - return light.state["state"]["bri"].get<unsigned int>(); | |
| 84 | + return light.state.GetValue()["state"]["bri"].get<unsigned int>(); | |
| 85 | 85 | } |
| 86 | 86 | |
| 87 | 87 | unsigned int SimpleBrightnessStrategy::getBrightness(const HueLight& light) const |
| 88 | 88 | { |
| 89 | - return light.state["state"]["bri"].get<unsigned int>(); | |
| 89 | + return light.state.GetValue()["state"]["bri"].get<unsigned int>(); | |
| 90 | 90 | } |
| 91 | 91 | } // namespace hueplusplus | ... | ... |
src/SimpleColorHueStrategy.cpp
| ... | ... | @@ -34,17 +34,18 @@ namespace hueplusplus |
| 34 | 34 | { |
| 35 | 35 | bool SimpleColorHueStrategy::setColorHue(uint16_t hue, uint8_t transition, HueLight& light) const |
| 36 | 36 | { |
| 37 | - light.refreshState(); | |
| 37 | + // Careful, only use state until any light function might refresh the value and invalidate the reference | |
| 38 | + const nlohmann::json& state = light.state.GetValue()["state"]; | |
| 38 | 39 | nlohmann::json request = nlohmann::json::object(); |
| 39 | 40 | if (transition != 4) |
| 40 | 41 | { |
| 41 | 42 | request["transitiontime"] = transition; |
| 42 | 43 | } |
| 43 | - if (light.state["state"]["on"] != true) | |
| 44 | + if (state["on"] != true) | |
| 44 | 45 | { |
| 45 | 46 | request["on"] = true; |
| 46 | 47 | } |
| 47 | - if (light.state["state"]["hue"] != hue || light.state["state"]["colormode"] != "hs") | |
| 48 | + if (state["hue"] != hue || state["colormode"] != "hs") | |
| 48 | 49 | { |
| 49 | 50 | hue = hue % 65535; |
| 50 | 51 | request["hue"] = hue; |
| ... | ... | @@ -64,17 +65,18 @@ bool SimpleColorHueStrategy::setColorHue(uint16_t hue, uint8_t transition, HueLi |
| 64 | 65 | |
| 65 | 66 | bool SimpleColorHueStrategy::setColorSaturation(uint8_t sat, uint8_t transition, HueLight& light) const |
| 66 | 67 | { |
| 67 | - light.refreshState(); | |
| 68 | + // Careful, only use state until any light function might refresh the value and invalidate the reference | |
| 69 | + const nlohmann::json& state = light.state.GetValue()["state"]; | |
| 68 | 70 | nlohmann::json request = nlohmann::json::object(); |
| 69 | 71 | if (transition != 4) |
| 70 | 72 | { |
| 71 | 73 | request["transitiontime"] = transition; |
| 72 | 74 | } |
| 73 | - if (light.state["state"]["on"] != true) | |
| 75 | + if (state["on"] != true) | |
| 74 | 76 | { |
| 75 | 77 | request["on"] = true; |
| 76 | 78 | } |
| 77 | - if (light.state["state"]["sat"] != sat) | |
| 79 | + if (state["sat"] != sat) | |
| 78 | 80 | { |
| 79 | 81 | if (sat > 254) |
| 80 | 82 | { |
| ... | ... | @@ -97,23 +99,24 @@ bool SimpleColorHueStrategy::setColorSaturation(uint8_t sat, uint8_t transition, |
| 97 | 99 | |
| 98 | 100 | bool SimpleColorHueStrategy::setColorHueSaturation(uint16_t hue, uint8_t sat, uint8_t transition, HueLight& light) const |
| 99 | 101 | { |
| 100 | - light.refreshState(); | |
| 102 | + // Careful, only use state until any light function might refresh the value and invalidate the reference | |
| 103 | + const nlohmann::json& state = light.state.GetValue()["state"]; | |
| 101 | 104 | nlohmann::json request = nlohmann::json::object(); |
| 102 | 105 | |
| 103 | 106 | if (transition != 4) |
| 104 | 107 | { |
| 105 | 108 | request["transitiontime"] = transition; |
| 106 | 109 | } |
| 107 | - if (light.state["state"]["on"] != true) | |
| 110 | + if (state["on"] != true) | |
| 108 | 111 | { |
| 109 | 112 | request["on"] = true; |
| 110 | 113 | } |
| 111 | - if (light.state["state"]["hue"] != hue || light.state["state"]["colormode"] != "hs") | |
| 114 | + if (state["hue"] != hue || state["colormode"] != "hs") | |
| 112 | 115 | { |
| 113 | 116 | hue = hue % 65535; |
| 114 | 117 | request["hue"] = hue; |
| 115 | 118 | } |
| 116 | - if (light.state["state"]["sat"] != sat || light.state["state"]["colormode"] != "hs") | |
| 119 | + if (state["sat"] != sat || state["colormode"] != "hs") | |
| 117 | 120 | { |
| 118 | 121 | if (sat > 254) |
| 119 | 122 | { |
| ... | ... | @@ -136,20 +139,21 @@ bool SimpleColorHueStrategy::setColorHueSaturation(uint16_t hue, uint8_t sat, ui |
| 136 | 139 | |
| 137 | 140 | bool SimpleColorHueStrategy::setColorXY(float x, float y, uint8_t transition, HueLight& light) const |
| 138 | 141 | { |
| 139 | - light.refreshState(); | |
| 142 | + // Careful, only use state until any light function might refresh the value and invalidate the reference | |
| 143 | + const nlohmann::json& state = light.state.GetValue()["state"]; | |
| 140 | 144 | nlohmann::json request = nlohmann::json::object(); |
| 141 | 145 | |
| 142 | 146 | if (transition != 4) |
| 143 | 147 | { |
| 144 | 148 | request["transitiontime"] = transition; |
| 145 | 149 | } |
| 146 | - if (light.state["state"]["on"] != true) | |
| 150 | + if (state["on"] != true) | |
| 147 | 151 | { |
| 148 | 152 | request["on"] = true; |
| 149 | 153 | } |
| 150 | - if (std::abs(light.state["state"]["xy"][0].get<float>() - x) > 1E-4f | |
| 151 | - || std::abs(light.state["state"]["xy"][1].get<float>() - y) > 1E-4f | |
| 152 | - || light.state["state"]["colormode"] != "xy") | |
| 154 | + if (std::abs(state["xy"][0].get<float>() - x) > 1E-4f | |
| 155 | + || std::abs(state["xy"][1].get<float>() - y) > 1E-4f | |
| 156 | + || state["colormode"] != "xy") | |
| 153 | 157 | { |
| 154 | 158 | request["xy"][0] = x; |
| 155 | 159 | request["xy"][1] = y; |
| ... | ... | @@ -171,7 +175,7 @@ bool SimpleColorHueStrategy::setColorRGB(uint8_t r, uint8_t g, uint8_t b, uint8_ |
| 171 | 175 | { |
| 172 | 176 | if ((r == 0) && (g == 0) && (b == 0)) |
| 173 | 177 | { |
| 174 | - return light.OffNoRefresh(); | |
| 178 | + return light.Off(); | |
| 175 | 179 | } |
| 176 | 180 | |
| 177 | 181 | const float red = float(r) / 255; |
| ... | ... | @@ -196,15 +200,16 @@ bool SimpleColorHueStrategy::setColorRGB(uint8_t r, uint8_t g, uint8_t b, uint8_ |
| 196 | 200 | bool SimpleColorHueStrategy::setColorLoop(bool on, HueLight& light) const |
| 197 | 201 | { |
| 198 | 202 | // colorloop |
| 199 | - light.refreshState(); | |
| 203 | + // Careful, only use state until any light function might refresh the value and invalidate the reference | |
| 204 | + const nlohmann::json& state = light.state.GetValue()["state"]; | |
| 200 | 205 | nlohmann::json request = nlohmann::json::object(); |
| 201 | 206 | |
| 202 | - if (light.state["state"]["on"] != true) | |
| 207 | + if (state["on"] != true) | |
| 203 | 208 | { |
| 204 | 209 | request["on"] = true; |
| 205 | 210 | } |
| 206 | 211 | std::string effect; |
| 207 | - if ((effect = on ? "colorloop" : "none") != light.state["state"]["effect"]) | |
| 212 | + if ((effect = on ? "colorloop" : "none") != state["effect"]) | |
| 208 | 213 | { |
| 209 | 214 | request["effect"] = effect; |
| 210 | 215 | } |
| ... | ... | @@ -222,13 +227,14 @@ bool SimpleColorHueStrategy::setColorLoop(bool on, HueLight& light) const |
| 222 | 227 | |
| 223 | 228 | bool SimpleColorHueStrategy::alertHueSaturation(uint16_t hue, uint8_t sat, HueLight& light) const |
| 224 | 229 | { |
| 225 | - light.refreshState(); | |
| 226 | - std::string cType = light.state["state"]["colormode"].get<std::string>(); | |
| 227 | - bool on = light.state["state"]["on"].get<bool>(); | |
| 230 | + // Careful, only use state until any light function might refresh the value and invalidate the reference | |
| 231 | + const nlohmann::json& state = light.state.GetValue()["state"]; | |
| 232 | + std::string cType = state["colormode"].get<std::string>(); | |
| 233 | + bool on = state["on"].get<bool>(); | |
| 228 | 234 | if (cType == "hs") |
| 229 | 235 | { |
| 230 | - uint16_t oldHue = light.state["state"]["hue"].get<uint16_t>(); | |
| 231 | - uint8_t oldSat = light.state["state"]["sat"].get<uint8_t>(); | |
| 236 | + uint16_t oldHue = state["hue"].get<uint16_t>(); | |
| 237 | + uint8_t oldSat = state["sat"].get<uint8_t>(); | |
| 232 | 238 | if (!light.setColorHueSaturation(hue, sat, 1)) |
| 233 | 239 | { |
| 234 | 240 | return false; |
| ... | ... | @@ -242,7 +248,7 @@ bool SimpleColorHueStrategy::alertHueSaturation(uint16_t hue, uint8_t sat, HueLi |
| 242 | 248 | if (!on) |
| 243 | 249 | { |
| 244 | 250 | light.setColorHueSaturation(oldHue, oldSat, 1); |
| 245 | - return light.OffNoRefresh(1); | |
| 251 | + return light.Off(1); | |
| 246 | 252 | } |
| 247 | 253 | else |
| 248 | 254 | { |
| ... | ... | @@ -251,8 +257,8 @@ bool SimpleColorHueStrategy::alertHueSaturation(uint16_t hue, uint8_t sat, HueLi |
| 251 | 257 | } |
| 252 | 258 | else if (cType == "xy") |
| 253 | 259 | { |
| 254 | - float oldX = light.state["state"]["xy"][0].get<float>(); | |
| 255 | - float oldY = light.state["state"]["xy"][1].get<float>(); | |
| 260 | + float oldX = state["xy"][0].get<float>(); | |
| 261 | + float oldY = state["xy"][1].get<float>(); | |
| 256 | 262 | if (!light.setColorHueSaturation(hue, sat, 1)) |
| 257 | 263 | { |
| 258 | 264 | return false; |
| ... | ... | @@ -266,7 +272,7 @@ bool SimpleColorHueStrategy::alertHueSaturation(uint16_t hue, uint8_t sat, HueLi |
| 266 | 272 | if (!on) |
| 267 | 273 | { |
| 268 | 274 | light.setColorXY(oldX, oldY, 1); |
| 269 | - return light.OffNoRefresh(1); | |
| 275 | + return light.Off(1); | |
| 270 | 276 | } |
| 271 | 277 | else |
| 272 | 278 | { |
| ... | ... | @@ -281,13 +287,14 @@ bool SimpleColorHueStrategy::alertHueSaturation(uint16_t hue, uint8_t sat, HueLi |
| 281 | 287 | |
| 282 | 288 | bool SimpleColorHueStrategy::alertXY(float x, float y, HueLight& light) const |
| 283 | 289 | { |
| 284 | - light.refreshState(); | |
| 285 | - std::string cType = light.state["state"]["colormode"].get<std::string>(); | |
| 286 | - bool on = light.state["state"]["on"].get<bool>(); | |
| 290 | + // Careful, only use state until any light function might refresh the value and invalidate the reference | |
| 291 | + const nlohmann::json& state = light.state.GetValue()["state"]; | |
| 292 | + std::string cType = state["colormode"].get<std::string>(); | |
| 293 | + bool on = state["on"].get<bool>(); | |
| 287 | 294 | if (cType == "hs") |
| 288 | 295 | { |
| 289 | - uint16_t oldHue = light.state["state"]["hue"].get<uint16_t>(); | |
| 290 | - uint8_t oldSat = light.state["state"]["sat"].get<uint8_t>(); | |
| 296 | + uint16_t oldHue = state["hue"].get<uint16_t>(); | |
| 297 | + uint8_t oldSat = state["sat"].get<uint8_t>(); | |
| 291 | 298 | if (!light.setColorXY(x, y, 1)) |
| 292 | 299 | { |
| 293 | 300 | return false; |
| ... | ... | @@ -301,7 +308,7 @@ bool SimpleColorHueStrategy::alertXY(float x, float y, HueLight& light) const |
| 301 | 308 | if (!on) |
| 302 | 309 | { |
| 303 | 310 | light.setColorHueSaturation(oldHue, oldSat, 1); |
| 304 | - return light.OffNoRefresh(1); | |
| 311 | + return light.Off(1); | |
| 305 | 312 | } |
| 306 | 313 | else |
| 307 | 314 | { |
| ... | ... | @@ -310,8 +317,8 @@ bool SimpleColorHueStrategy::alertXY(float x, float y, HueLight& light) const |
| 310 | 317 | } |
| 311 | 318 | else if (cType == "xy") |
| 312 | 319 | { |
| 313 | - float oldX = light.state["state"]["xy"][0].get<float>(); | |
| 314 | - float oldY = light.state["state"]["xy"][1].get<float>(); | |
| 320 | + float oldX = state["xy"][0].get<float>(); | |
| 321 | + float oldY = state["xy"][1].get<float>(); | |
| 315 | 322 | if (!light.setColorXY(x, y, 1)) |
| 316 | 323 | { |
| 317 | 324 | return false; |
| ... | ... | @@ -325,7 +332,7 @@ bool SimpleColorHueStrategy::alertXY(float x, float y, HueLight& light) const |
| 325 | 332 | if (!on) |
| 326 | 333 | { |
| 327 | 334 | light.setColorXY(oldX, oldY, 1); |
| 328 | - return light.OffNoRefresh(1); | |
| 335 | + return light.Off(1); | |
| 329 | 336 | } |
| 330 | 337 | else |
| 331 | 338 | { |
| ... | ... | @@ -340,13 +347,14 @@ bool SimpleColorHueStrategy::alertXY(float x, float y, HueLight& light) const |
| 340 | 347 | |
| 341 | 348 | bool SimpleColorHueStrategy::alertRGB(uint8_t r, uint8_t g, uint8_t b, HueLight& light) const |
| 342 | 349 | { |
| 343 | - light.refreshState(); | |
| 344 | - std::string cType = light.state["state"]["colormode"].get<std::string>(); | |
| 345 | - bool on = light.state["state"]["on"].get<bool>(); | |
| 350 | + // Careful, only use state until any light function might refresh the value and invalidate the reference | |
| 351 | + const nlohmann::json& state = light.state.GetValue()["state"]; | |
| 352 | + std::string cType = state["colormode"].get<std::string>(); | |
| 353 | + bool on = state["on"].get<bool>(); | |
| 346 | 354 | if (cType == "hs") |
| 347 | 355 | { |
| 348 | - uint16_t oldHue = light.state["state"]["hue"].get<uint16_t>(); | |
| 349 | - uint8_t oldSat = light.state["state"]["sat"].get<uint8_t>(); | |
| 356 | + uint16_t oldHue = state["hue"].get<uint16_t>(); | |
| 357 | + uint8_t oldSat = state["sat"].get<uint8_t>(); | |
| 350 | 358 | if (!light.setColorRGB(r, g, b, 1)) |
| 351 | 359 | { |
| 352 | 360 | return false; |
| ... | ... | @@ -360,7 +368,7 @@ bool SimpleColorHueStrategy::alertRGB(uint8_t r, uint8_t g, uint8_t b, HueLight& |
| 360 | 368 | if (!on) |
| 361 | 369 | { |
| 362 | 370 | light.setColorHueSaturation(oldHue, oldSat, 1); |
| 363 | - return light.OffNoRefresh(1); | |
| 371 | + return light.Off(1); | |
| 364 | 372 | } |
| 365 | 373 | else |
| 366 | 374 | { |
| ... | ... | @@ -369,8 +377,8 @@ bool SimpleColorHueStrategy::alertRGB(uint8_t r, uint8_t g, uint8_t b, HueLight& |
| 369 | 377 | } |
| 370 | 378 | else if (cType == "xy") |
| 371 | 379 | { |
| 372 | - float oldX = light.state["state"]["xy"][0].get<float>(); | |
| 373 | - float oldY = light.state["state"]["xy"][1].get<float>(); | |
| 380 | + float oldX = state["xy"][0].get<float>(); | |
| 381 | + float oldY = state["xy"][1].get<float>(); | |
| 374 | 382 | if (!light.setColorRGB(r, g, b, 1)) |
| 375 | 383 | { |
| 376 | 384 | return false; |
| ... | ... | @@ -384,7 +392,7 @@ bool SimpleColorHueStrategy::alertRGB(uint8_t r, uint8_t g, uint8_t b, HueLight& |
| 384 | 392 | if (!on) |
| 385 | 393 | { |
| 386 | 394 | light.setColorXY(oldX, oldY, 1); |
| 387 | - return light.OffNoRefresh(1); | |
| 395 | + return light.Off(1); | |
| 388 | 396 | } |
| 389 | 397 | else |
| 390 | 398 | { |
| ... | ... | @@ -399,24 +407,26 @@ bool SimpleColorHueStrategy::alertRGB(uint8_t r, uint8_t g, uint8_t b, HueLight& |
| 399 | 407 | |
| 400 | 408 | std::pair<uint16_t, uint8_t> SimpleColorHueStrategy::getColorHueSaturation(HueLight& light) const |
| 401 | 409 | { |
| 402 | - light.refreshState(); | |
| 403 | - return std::make_pair(light.state["state"]["hue"].get<uint16_t>(), light.state["state"]["sat"].get<uint8_t>()); | |
| 410 | + // Save value, so there are no inconsistent results if it is refreshed between two calls | |
| 411 | + const nlohmann::json& state = light.state.GetValue()["state"]; | |
| 412 | + return std::make_pair(state["hue"].get<uint16_t>(), state["sat"].get<uint8_t>()); | |
| 404 | 413 | } |
| 405 | 414 | |
| 406 | 415 | std::pair<uint16_t, uint8_t> SimpleColorHueStrategy::getColorHueSaturation(const HueLight& light) const |
| 407 | 416 | { |
| 408 | - return std::make_pair(light.state["state"]["hue"].get<uint16_t>(), light.state["state"]["sat"].get<uint8_t>()); | |
| 417 | + return std::make_pair(light.state.GetValue()["state"]["hue"].get<uint16_t>(), light.state.GetValue()["state"]["sat"].get<uint8_t>()); | |
| 409 | 418 | } |
| 410 | 419 | |
| 411 | 420 | std::pair<float, float> SimpleColorHueStrategy::getColorXY(HueLight& light) const |
| 412 | 421 | { |
| 413 | - light.refreshState(); | |
| 414 | - return std::make_pair(light.state["state"]["xy"][0].get<float>(), light.state["state"]["xy"][1].get<float>()); | |
| 422 | + // Save value, so there are no inconsistent results if it is refreshed between two calls | |
| 423 | + const nlohmann::json& state = light.state.GetValue()["state"]; | |
| 424 | + return std::make_pair(state["xy"][0].get<float>(), state["xy"][1].get<float>()); | |
| 415 | 425 | } |
| 416 | 426 | |
| 417 | 427 | std::pair<float, float> SimpleColorHueStrategy::getColorXY(const HueLight& light) const |
| 418 | 428 | { |
| 419 | - return std::make_pair(light.state["state"]["xy"][0].get<float>(), light.state["state"]["xy"][1].get<float>()); | |
| 429 | + return std::make_pair(light.state.GetValue()["state"]["xy"][0].get<float>(), light.state.GetValue()["state"]["xy"][1].get<float>()); | |
| 420 | 430 | } |
| 421 | 431 | /*bool SimpleColorHueStrategy::pointInTriangle(float pointx, float pointy, float |
| 422 | 432 | x0, float y0, float x1, float y1, float x2, float y2) | ... | ... |
src/SimpleColorTemperatureStrategy.cpp
| ... | ... | @@ -34,17 +34,18 @@ namespace hueplusplus |
| 34 | 34 | { |
| 35 | 35 | bool SimpleColorTemperatureStrategy::setColorTemperature(unsigned int mired, uint8_t transition, HueLight& light) const |
| 36 | 36 | { |
| 37 | - light.refreshState(); | |
| 37 | + // Careful, only use state until any light function might refresh the value and invalidate the reference | |
| 38 | + const nlohmann::json& state = light.state.GetValue()["state"]; | |
| 38 | 39 | nlohmann::json request = nlohmann::json::object(); |
| 39 | 40 | if (transition != 4) |
| 40 | 41 | { |
| 41 | 42 | request["transitiontime"] = transition; |
| 42 | 43 | } |
| 43 | - if (light.state["state"]["on"] != true) | |
| 44 | + if (state["on"] != true) | |
| 44 | 45 | { |
| 45 | 46 | request["on"] = true; |
| 46 | 47 | } |
| 47 | - if (light.state["state"]["ct"] != mired) | |
| 48 | + if (state["ct"] != mired) | |
| 48 | 49 | { |
| 49 | 50 | if (mired > 500) |
| 50 | 51 | { |
| ... | ... | @@ -71,12 +72,13 @@ bool SimpleColorTemperatureStrategy::setColorTemperature(unsigned int mired, uin |
| 71 | 72 | |
| 72 | 73 | bool SimpleColorTemperatureStrategy::alertTemperature(unsigned int mired, HueLight& light) const |
| 73 | 74 | { |
| 74 | - light.refreshState(); | |
| 75 | - std::string cType = light.state["state"]["colormode"].get<std::string>(); | |
| 76 | - bool on = light.state["state"]["on"].get<bool>(); | |
| 75 | + // Careful, only use state until any light function might refresh the value and invalidate the reference | |
| 76 | + const nlohmann::json& state = light.state.GetValue()["state"]; | |
| 77 | + std::string cType = state["colormode"].get<std::string>(); | |
| 78 | + bool on = state["on"].get<bool>(); | |
| 77 | 79 | if (cType == "ct") |
| 78 | 80 | { |
| 79 | - uint16_t oldCT = light.state["state"]["ct"].get<uint16_t>(); | |
| 81 | + uint16_t oldCT = state["ct"].get<uint16_t>(); | |
| 80 | 82 | if (!light.setColorTemperature(mired, 1)) |
| 81 | 83 | { |
| 82 | 84 | return false; |
| ... | ... | @@ -90,7 +92,7 @@ bool SimpleColorTemperatureStrategy::alertTemperature(unsigned int mired, HueLig |
| 90 | 92 | if (!on) |
| 91 | 93 | { |
| 92 | 94 | light.setColorTemperature(oldCT, 1); |
| 93 | - return light.OffNoRefresh(1); | |
| 95 | + return light.Off(1); | |
| 94 | 96 | } |
| 95 | 97 | else |
| 96 | 98 | { |
| ... | ... | @@ -105,12 +107,11 @@ bool SimpleColorTemperatureStrategy::alertTemperature(unsigned int mired, HueLig |
| 105 | 107 | |
| 106 | 108 | unsigned int SimpleColorTemperatureStrategy::getColorTemperature(HueLight& light) const |
| 107 | 109 | { |
| 108 | - light.refreshState(); | |
| 109 | - return light.state["state"]["ct"].get<unsigned int>(); | |
| 110 | + return light.state.GetValue()["state"]["ct"].get<unsigned int>(); | |
| 110 | 111 | } |
| 111 | 112 | |
| 112 | 113 | unsigned int SimpleColorTemperatureStrategy::getColorTemperature(const HueLight& light) const |
| 113 | 114 | { |
| 114 | - return light.state["state"]["ct"].get<unsigned int>(); | |
| 115 | + return light.state.GetValue()["state"]["ct"].get<unsigned int>(); | |
| 115 | 116 | } |
| 116 | 117 | } // namespace hueplusplus | ... | ... |
test/mocks/mock_HueLight.h
| ... | ... | @@ -37,9 +37,13 @@ class MockHueLight : public hueplusplus::HueLight |
| 37 | 37 | { |
| 38 | 38 | public: |
| 39 | 39 | MockHueLight(std::shared_ptr<const hueplusplus::IHttpHandler> handler) |
| 40 | - : HueLight(1, hueplusplus::HueCommandAPI(getBridgeIp(), getBridgePort(), getBridgeUsername(), handler)){}; | |
| 40 | + : HueLight(1, hueplusplus::HueCommandAPI(getBridgeIp(), getBridgePort(), getBridgeUsername(), handler), nullptr, | |
| 41 | + nullptr, nullptr, std::chrono::steady_clock::duration::max()) | |
| 42 | + { | |
| 43 | + // Set refresh duration to max, so random refreshes do not hinder the test setups | |
| 44 | + } | |
| 41 | 45 | |
| 42 | - nlohmann::json& getState() { return state; }; | |
| 46 | + nlohmann::json& getState() { return state.GetValue(); } | |
| 43 | 47 | |
| 44 | 48 | MOCK_METHOD1(On, bool(uint8_t transition)); |
| 45 | 49 | |
| ... | ... | @@ -121,14 +125,8 @@ public: |
| 121 | 125 | |
| 122 | 126 | MOCK_METHOD1(setColorLoop, bool(bool on)); |
| 123 | 127 | |
| 124 | - MOCK_METHOD1(OnNoRefresh, bool(uint8_t transition)); | |
| 125 | - | |
| 126 | - MOCK_METHOD1(OffNoRefresh, bool(uint8_t transition)); | |
| 127 | - | |
| 128 | 128 | MOCK_METHOD3(SendPutRequest, |
| 129 | 129 | nlohmann::json(const nlohmann::json& request, const std::string& subPath, hueplusplus::FileInfo fileInfo)); |
| 130 | - | |
| 131 | - MOCK_METHOD0(refreshState, void()); | |
| 132 | 130 | }; |
| 133 | 131 | |
| 134 | 132 | #endif | ... | ... |
test/test_ExtendedColorHueStrategy.cpp
| ... | ... | @@ -44,7 +44,6 @@ TEST(ExtendedColorHueStrategy, alertHueSaturation) |
| 44 | 44 | .Times(AtLeast(1)) |
| 45 | 45 | .WillRepeatedly(Return(nlohmann::json::object())); |
| 46 | 46 | MockHueLight test_light(handler); |
| 47 | - EXPECT_CALL(test_light, refreshState()).Times(AtLeast(1)).WillRepeatedly(Return()); | |
| 48 | 47 | |
| 49 | 48 | test_light.getState()["state"]["colormode"] = "invalid"; |
| 50 | 49 | test_light.getState()["state"]["on"] = false; |
| ... | ... | @@ -65,7 +64,7 @@ TEST(ExtendedColorHueStrategy, alertHueSaturation) |
| 65 | 64 | |
| 66 | 65 | EXPECT_EQ(true, ExtendedColorHueStrategy().alertHueSaturation(200, 100, test_light)); |
| 67 | 66 | |
| 68 | - EXPECT_CALL(test_light, OffNoRefresh(_)).Times(AtLeast(1)).WillRepeatedly(Return(true)); | |
| 67 | + EXPECT_CALL(test_light, Off(_)).Times(AtLeast(1)).WillRepeatedly(Return(true)); | |
| 69 | 68 | test_light.getState()["state"]["on"] = false; |
| 70 | 69 | EXPECT_EQ(true, ExtendedColorHueStrategy().alertHueSaturation(200, 100, test_light)); |
| 71 | 70 | |
| ... | ... | @@ -85,7 +84,7 @@ TEST(ExtendedColorHueStrategy, alertHueSaturation) |
| 85 | 84 | EXPECT_CALL(test_light, setColorXY(_, _, 1)).Times(AtLeast(2)).WillRepeatedly(Return(true)); |
| 86 | 85 | EXPECT_EQ(true, ExtendedColorHueStrategy().alertHueSaturation(200, 100, test_light)); |
| 87 | 86 | |
| 88 | - EXPECT_CALL(test_light, OffNoRefresh(_)).Times(AtLeast(1)).WillRepeatedly(Return(true)); | |
| 87 | + EXPECT_CALL(test_light, Off(_)).Times(AtLeast(1)).WillRepeatedly(Return(true)); | |
| 89 | 88 | test_light.getState()["state"]["on"] = false; |
| 90 | 89 | EXPECT_EQ(true, ExtendedColorHueStrategy().alertHueSaturation(200, 100, test_light)); |
| 91 | 90 | |
| ... | ... | @@ -104,7 +103,7 @@ TEST(ExtendedColorHueStrategy, alertHueSaturation) |
| 104 | 103 | EXPECT_CALL(test_light, setColorTemperature(_, 1)).Times(AtLeast(2)).WillRepeatedly(Return(true)); |
| 105 | 104 | EXPECT_EQ(true, ExtendedColorHueStrategy().alertHueSaturation(200, 100, test_light)); |
| 106 | 105 | |
| 107 | - EXPECT_CALL(test_light, OffNoRefresh(_)).Times(AtLeast(1)).WillRepeatedly(Return(true)); | |
| 106 | + EXPECT_CALL(test_light, Off(_)).Times(AtLeast(1)).WillRepeatedly(Return(true)); | |
| 108 | 107 | test_light.getState()["state"]["on"] = false; |
| 109 | 108 | EXPECT_EQ(true, ExtendedColorHueStrategy().alertHueSaturation(200, 100, test_light)); |
| 110 | 109 | } |
| ... | ... | @@ -118,7 +117,6 @@ TEST(ExtendedColorHueStrategy, alertXY) |
| 118 | 117 | .Times(AtLeast(1)) |
| 119 | 118 | .WillRepeatedly(Return(nlohmann::json::object())); |
| 120 | 119 | MockHueLight test_light(handler); |
| 121 | - EXPECT_CALL(test_light, refreshState()).Times(AtLeast(1)).WillRepeatedly(Return()); | |
| 122 | 120 | |
| 123 | 121 | test_light.getState()["state"]["colormode"] = "invalid"; |
| 124 | 122 | test_light.getState()["state"]["on"] = false; |
| ... | ... | @@ -139,7 +137,7 @@ TEST(ExtendedColorHueStrategy, alertXY) |
| 139 | 137 | EXPECT_CALL(test_light, setColorHueSaturation(_, _, 1)).Times(AtLeast(2)).WillRepeatedly(Return(true)); |
| 140 | 138 | EXPECT_EQ(true, ExtendedColorHueStrategy().alertXY(0.1f, 0.1f, test_light)); |
| 141 | 139 | |
| 142 | - EXPECT_CALL(test_light, OffNoRefresh(_)).Times(AtLeast(1)).WillRepeatedly(Return(true)); | |
| 140 | + EXPECT_CALL(test_light, Off(_)).Times(AtLeast(1)).WillRepeatedly(Return(true)); | |
| 143 | 141 | test_light.getState()["state"]["on"] = false; |
| 144 | 142 | EXPECT_EQ(true, ExtendedColorHueStrategy().alertXY(0.1f, 0.1f, test_light)); |
| 145 | 143 | |
| ... | ... | @@ -153,7 +151,7 @@ TEST(ExtendedColorHueStrategy, alertXY) |
| 153 | 151 | |
| 154 | 152 | EXPECT_EQ(true, ExtendedColorHueStrategy().alertXY(0.1f, 0.1f, test_light)); |
| 155 | 153 | |
| 156 | - EXPECT_CALL(test_light, OffNoRefresh(_)).Times(AtLeast(1)).WillRepeatedly(Return(true)); | |
| 154 | + EXPECT_CALL(test_light, Off(_)).Times(AtLeast(1)).WillRepeatedly(Return(true)); | |
| 157 | 155 | test_light.getState()["state"]["on"] = false; |
| 158 | 156 | EXPECT_EQ(true, ExtendedColorHueStrategy().alertXY(0.1f, 0.1f, test_light)); |
| 159 | 157 | |
| ... | ... | @@ -169,7 +167,7 @@ TEST(ExtendedColorHueStrategy, alertXY) |
| 169 | 167 | EXPECT_CALL(test_light, setColorTemperature(_, 1)).Times(AtLeast(2)).WillRepeatedly(Return(true)); |
| 170 | 168 | EXPECT_EQ(true, ExtendedColorHueStrategy().alertXY(0.1f, 0.1f, test_light)); |
| 171 | 169 | |
| 172 | - EXPECT_CALL(test_light, OffNoRefresh(_)).Times(AtLeast(1)).WillRepeatedly(Return(true)); | |
| 170 | + EXPECT_CALL(test_light, Off(_)).Times(AtLeast(1)).WillRepeatedly(Return(true)); | |
| 173 | 171 | test_light.getState()["state"]["on"] = false; |
| 174 | 172 | EXPECT_EQ(true, ExtendedColorHueStrategy().alertXY(0.1f, 0.1f, test_light)); |
| 175 | 173 | } |
| ... | ... | @@ -183,7 +181,6 @@ TEST(ExtendedColorHueStrategy, alertRGB) |
| 183 | 181 | .Times(AtLeast(1)) |
| 184 | 182 | .WillRepeatedly(Return(nlohmann::json::object())); |
| 185 | 183 | MockHueLight test_light(handler); |
| 186 | - EXPECT_CALL(test_light, refreshState()).Times(AtLeast(1)).WillRepeatedly(Return()); | |
| 187 | 184 | |
| 188 | 185 | test_light.getState()["state"]["colormode"] = "invalid"; |
| 189 | 186 | test_light.getState()["state"]["on"] = false; |
| ... | ... | @@ -205,7 +202,7 @@ TEST(ExtendedColorHueStrategy, alertRGB) |
| 205 | 202 | EXPECT_CALL(test_light, setColorHueSaturation(_, _, 1)).Times(AtLeast(2)).WillRepeatedly(Return(true)); |
| 206 | 203 | EXPECT_EQ(true, ExtendedColorHueStrategy().alertRGB(128, 128, 128, test_light)); |
| 207 | 204 | |
| 208 | - EXPECT_CALL(test_light, OffNoRefresh(_)).Times(AtLeast(1)).WillRepeatedly(Return(true)); | |
| 205 | + EXPECT_CALL(test_light, Off(_)).Times(AtLeast(1)).WillRepeatedly(Return(true)); | |
| 209 | 206 | test_light.getState()["state"]["on"] = false; |
| 210 | 207 | EXPECT_EQ(true, ExtendedColorHueStrategy().alertRGB(128, 128, 128, test_light)); |
| 211 | 208 | |
| ... | ... | @@ -225,7 +222,7 @@ TEST(ExtendedColorHueStrategy, alertRGB) |
| 225 | 222 | EXPECT_CALL(test_light, setColorXY(_, _, 1)).Times(AtLeast(2)).WillRepeatedly(Return(true)); |
| 226 | 223 | EXPECT_EQ(true, ExtendedColorHueStrategy().alertRGB(128, 128, 128, test_light)); |
| 227 | 224 | |
| 228 | - EXPECT_CALL(test_light, OffNoRefresh(_)).Times(AtLeast(1)).WillRepeatedly(Return(true)); | |
| 225 | + EXPECT_CALL(test_light, Off(_)).Times(AtLeast(1)).WillRepeatedly(Return(true)); | |
| 229 | 226 | test_light.getState()["state"]["on"] = false; |
| 230 | 227 | EXPECT_EQ(true, ExtendedColorHueStrategy().alertRGB(128, 128, 128, test_light)); |
| 231 | 228 | |
| ... | ... | @@ -244,7 +241,7 @@ TEST(ExtendedColorHueStrategy, alertRGB) |
| 244 | 241 | EXPECT_CALL(test_light, setColorTemperature(_, 1)).Times(AtLeast(2)).WillRepeatedly(Return(true)); |
| 245 | 242 | EXPECT_EQ(true, ExtendedColorHueStrategy().alertRGB(128, 128, 128, test_light)); |
| 246 | 243 | |
| 247 | - EXPECT_CALL(test_light, OffNoRefresh(_)).Times(AtLeast(1)).WillRepeatedly(Return(true)); | |
| 244 | + EXPECT_CALL(test_light, Off(_)).Times(AtLeast(1)).WillRepeatedly(Return(true)); | |
| 248 | 245 | test_light.getState()["state"]["on"] = false; |
| 249 | 246 | EXPECT_EQ(true, ExtendedColorHueStrategy().alertRGB(128, 128, 128, test_light)); |
| 250 | 247 | } | ... | ... |
test/test_ExtendedColorTemperatureStrategy.cpp
| ... | ... | @@ -44,7 +44,7 @@ TEST(ExtendedColorTemperatureStrategy, setColorTemperature) |
| 44 | 44 | .Times(AtLeast(1)) |
| 45 | 45 | .WillRepeatedly(Return(nlohmann::json::object())); |
| 46 | 46 | MockHueLight test_light(handler); |
| 47 | - EXPECT_CALL(test_light, refreshState()).Times(AtLeast(1)).WillRepeatedly(Return()); | |
| 47 | + | |
| 48 | 48 | nlohmann::json prep_ret; |
| 49 | 49 | prep_ret = nlohmann::json::array(); |
| 50 | 50 | prep_ret[0] = nlohmann::json::object(); |
| ... | ... | @@ -84,7 +84,6 @@ TEST(ExtendedColorTemperatureStrategy, alertTemperature) |
| 84 | 84 | .Times(AtLeast(1)) |
| 85 | 85 | .WillRepeatedly(Return(nlohmann::json::object())); |
| 86 | 86 | MockHueLight test_light(handler); |
| 87 | - EXPECT_CALL(test_light, refreshState()).Times(AtLeast(1)).WillRepeatedly(Return()); | |
| 88 | 87 | |
| 89 | 88 | test_light.getState()["state"]["colormode"] = "invalid"; |
| 90 | 89 | test_light.getState()["state"]["on"] = false; |
| ... | ... | @@ -107,7 +106,7 @@ TEST(ExtendedColorTemperatureStrategy, alertTemperature) |
| 107 | 106 | EXPECT_CALL(test_light, setColorHueSaturation(_, _, 1)).Times(AtLeast(2)).WillRepeatedly(Return(true)); |
| 108 | 107 | EXPECT_EQ(true, ExtendedColorTemperatureStrategy().alertTemperature(400, test_light)); |
| 109 | 108 | |
| 110 | - EXPECT_CALL(test_light, OffNoRefresh(_)).Times(AtLeast(1)).WillRepeatedly(Return(true)); | |
| 109 | + EXPECT_CALL(test_light, Off(_)).Times(AtLeast(1)).WillRepeatedly(Return(true)); | |
| 111 | 110 | test_light.getState()["state"]["on"] = false; |
| 112 | 111 | EXPECT_EQ(true, ExtendedColorTemperatureStrategy().alertTemperature(400, test_light)); |
| 113 | 112 | ... | ... |
test/test_Hue.cpp
| ... | ... | @@ -449,12 +449,12 @@ TEST(Hue, getAllLights) |
| 449 | 449 | |
| 450 | 450 | EXPECT_CALL( |
| 451 | 451 | *handler, GETJson("/api/" + getBridgeUsername(), nlohmann::json::object(), getBridgeIp(), getBridgePort())) |
| 452 | - .Times(2) | |
| 452 | + .Times(AtLeast(1)) | |
| 453 | 453 | .WillRepeatedly(Return(hue_bridge_state)); |
| 454 | 454 | |
| 455 | 455 | EXPECT_CALL(*handler, |
| 456 | 456 | GETJson("/api/" + getBridgeUsername() + "/lights/1", nlohmann::json::object(), getBridgeIp(), getBridgePort())) |
| 457 | - .Times(2) | |
| 457 | + .Times(AtLeast(1)) | |
| 458 | 458 | .WillRepeatedly(Return(hue_bridge_state["lights"]["1"])); |
| 459 | 459 | |
| 460 | 460 | Hue test_bridge(getBridgeIp(), getBridgePort(), getBridgeUsername(), handler); |
| ... | ... | @@ -531,12 +531,3 @@ TEST(Hue, getPictureOfLight) |
| 531 | 531 | |
| 532 | 532 | EXPECT_EQ("e27_waca", test_bridge.getPictureOfLight(1)); |
| 533 | 533 | } |
| 534 | - | |
| 535 | -TEST(Hue, refreshState) | |
| 536 | -{ | |
| 537 | - std::shared_ptr<MockHttpHandler> handler = std::make_shared<MockHttpHandler>(); | |
| 538 | - Hue test_bridge(getBridgeIp(), getBridgePort(), "", handler); // NULL as username leads to segfault | |
| 539 | - | |
| 540 | - std::vector<std::reference_wrapper<HueLight>> test_lights = test_bridge.getAllLights(); | |
| 541 | - EXPECT_EQ(test_lights.size(), 0); | |
| 542 | -} | ... | ... |
test/test_HueLight.cpp
| ... | ... | @@ -888,19 +888,3 @@ TEST_F(HueLightTest, setColorLoop) |
| 888 | 888 | EXPECT_EQ(false, test_light_2.setColorLoop(false)); |
| 889 | 889 | EXPECT_EQ(false, test_light_3.setColorLoop(true)); |
| 890 | 890 | } |
| 891 | - | |
| 892 | -TEST_F(HueLightTest, refreshState) | |
| 893 | -{ | |
| 894 | - using namespace ::testing; | |
| 895 | - test_bridge.getLight(1); | |
| 896 | - test_bridge.getLight(2); | |
| 897 | - test_bridge.getLight(3); | |
| 898 | - | |
| 899 | - EXPECT_CALL( | |
| 900 | - *handler, GETJson("/api/" + getBridgeUsername() + "/lights/1", nlohmann::json::object(), getBridgeIp(), 80)) | |
| 901 | - .Times(2) | |
| 902 | - .WillRepeatedly(Return(nlohmann::json::object())); | |
| 903 | - | |
| 904 | - const HueLight ctest_light_1 = test_bridge.getLight(1); | |
| 905 | - HueLight test_light_1 = test_bridge.getLight(1); | |
| 906 | -} | ... | ... |
test/test_SimpleBrightnessStrategy.cpp
| ... | ... | @@ -45,8 +45,8 @@ TEST(SimpleBrightnessStrategy, setBrightness) |
| 45 | 45 | .Times(AtLeast(1)) |
| 46 | 46 | .WillRepeatedly(Return(nlohmann::json::object())); |
| 47 | 47 | MockHueLight test_light(handler); |
| 48 | - EXPECT_CALL(test_light, refreshState()).Times(AtLeast(1)).WillRepeatedly(Return()); | |
| 49 | - EXPECT_CALL(test_light, OffNoRefresh(_)).Times(AtLeast(1)).WillRepeatedly(Return(true)); | |
| 48 | + | |
| 49 | + EXPECT_CALL(test_light, Off(_)).Times(AtLeast(1)).WillRepeatedly(Return(true)); | |
| 50 | 50 | nlohmann::json prep_ret; |
| 51 | 51 | prep_ret = nlohmann::json::array(); |
| 52 | 52 | prep_ret[0] = nlohmann::json::object(); |
| ... | ... | @@ -86,7 +86,6 @@ TEST(SimpleBrightnessStrategy, getBrightness) |
| 86 | 86 | .Times(AtLeast(1)) |
| 87 | 87 | .WillRepeatedly(Return(nlohmann::json::object())); |
| 88 | 88 | MockHueLight test_light(handler); |
| 89 | - EXPECT_CALL(test_light, refreshState()).Times(AtLeast(1)).WillRepeatedly(Return()); | |
| 90 | 89 | |
| 91 | 90 | test_light.getState()["state"]["bri"] = 200; |
| 92 | 91 | EXPECT_EQ(200, SimpleBrightnessStrategy().getBrightness(test_light)); | ... | ... |
test/test_SimpleColorHueStrategy.cpp
| ... | ... | @@ -44,7 +44,7 @@ TEST(SimpleColorHueStrategy, setColorHue) |
| 44 | 44 | .Times(AtLeast(1)) |
| 45 | 45 | .WillRepeatedly(Return(nlohmann::json::object())); |
| 46 | 46 | MockHueLight test_light(handler); |
| 47 | - EXPECT_CALL(test_light, refreshState()).Times(AtLeast(1)).WillRepeatedly(Return()); | |
| 47 | + | |
| 48 | 48 | nlohmann::json prep_ret; |
| 49 | 49 | prep_ret = nlohmann::json::array(); |
| 50 | 50 | prep_ret[0] = nlohmann::json::object(); |
| ... | ... | @@ -76,7 +76,7 @@ TEST(SimpleColorHueStrategy, setColorSaturation) |
| 76 | 76 | .Times(AtLeast(1)) |
| 77 | 77 | .WillRepeatedly(Return(nlohmann::json::object())); |
| 78 | 78 | MockHueLight test_light(handler); |
| 79 | - EXPECT_CALL(test_light, refreshState()).Times(AtLeast(1)).WillRepeatedly(Return()); | |
| 79 | + | |
| 80 | 80 | nlohmann::json prep_ret; |
| 81 | 81 | prep_ret = nlohmann::json::array(); |
| 82 | 82 | prep_ret[0] = nlohmann::json::object(); |
| ... | ... | @@ -108,7 +108,7 @@ TEST(SimpleColorHueStrategy, setColorHueSaturation) |
| 108 | 108 | .Times(AtLeast(1)) |
| 109 | 109 | .WillRepeatedly(Return(nlohmann::json::object())); |
| 110 | 110 | MockHueLight test_light(handler); |
| 111 | - EXPECT_CALL(test_light, refreshState()).Times(AtLeast(1)).WillRepeatedly(Return()); | |
| 111 | + | |
| 112 | 112 | nlohmann::json prep_ret; |
| 113 | 113 | prep_ret = nlohmann::json::array(); |
| 114 | 114 | prep_ret[0] = nlohmann::json::object(); |
| ... | ... | @@ -144,7 +144,7 @@ TEST(SimpleColorHueStrategy, setColorXY) |
| 144 | 144 | .Times(AtLeast(1)) |
| 145 | 145 | .WillRepeatedly(Return(nlohmann::json::object())); |
| 146 | 146 | MockHueLight test_light(handler); |
| 147 | - EXPECT_CALL(test_light, refreshState()).Times(AtLeast(1)).WillRepeatedly(Return()); | |
| 147 | + | |
| 148 | 148 | nlohmann::json prep_ret; |
| 149 | 149 | prep_ret = nlohmann::json::array(); |
| 150 | 150 | prep_ret[0] = nlohmann::json::object(); |
| ... | ... | @@ -184,7 +184,7 @@ TEST(SimpleColorHueStrategy, setColorRGB) |
| 184 | 184 | |
| 185 | 185 | EXPECT_EQ(true, SimpleColorHueStrategy().setColorRGB(255, 255, 255, 4, test_light)); |
| 186 | 186 | |
| 187 | - EXPECT_CALL(test_light, OffNoRefresh(4)).Times(1).WillOnce(Return(true)); | |
| 187 | + EXPECT_CALL(test_light, Off(4)).Times(1).WillOnce(Return(true)); | |
| 188 | 188 | EXPECT_EQ(true, SimpleColorHueStrategy().setColorRGB(0, 0, 0, 4, test_light)); |
| 189 | 189 | } |
| 190 | 190 | |
| ... | ... | @@ -197,7 +197,7 @@ TEST(SimpleColorHueStrategy, setColorLoop) |
| 197 | 197 | .Times(AtLeast(1)) |
| 198 | 198 | .WillRepeatedly(Return(nlohmann::json::object())); |
| 199 | 199 | MockHueLight test_light(handler); |
| 200 | - EXPECT_CALL(test_light, refreshState()).Times(AtLeast(1)).WillRepeatedly(Return()); | |
| 200 | + | |
| 201 | 201 | nlohmann::json prep_ret; |
| 202 | 202 | prep_ret = nlohmann::json::array(); |
| 203 | 203 | prep_ret[0] = nlohmann::json::object(); |
| ... | ... | @@ -226,7 +226,6 @@ TEST(SimpleColorHueStrategy, alertHueSaturation) |
| 226 | 226 | .Times(AtLeast(1)) |
| 227 | 227 | .WillRepeatedly(Return(nlohmann::json::object())); |
| 228 | 228 | MockHueLight test_light(handler); |
| 229 | - EXPECT_CALL(test_light, refreshState()).Times(AtLeast(1)).WillRepeatedly(Return()); | |
| 230 | 229 | |
| 231 | 230 | test_light.getState()["state"]["colormode"] = "invalid"; |
| 232 | 231 | test_light.getState()["state"]["on"] = false; |
| ... | ... | @@ -247,7 +246,7 @@ TEST(SimpleColorHueStrategy, alertHueSaturation) |
| 247 | 246 | |
| 248 | 247 | EXPECT_EQ(true, SimpleColorHueStrategy().alertHueSaturation(200, 100, test_light)); |
| 249 | 248 | |
| 250 | - EXPECT_CALL(test_light, OffNoRefresh(_)).Times(AtLeast(1)).WillRepeatedly(Return(true)); | |
| 249 | + EXPECT_CALL(test_light, Off(_)).Times(AtLeast(1)).WillRepeatedly(Return(true)); | |
| 251 | 250 | test_light.getState()["state"]["on"] = false; |
| 252 | 251 | EXPECT_EQ(true, SimpleColorHueStrategy().alertHueSaturation(200, 100, test_light)); |
| 253 | 252 | |
| ... | ... | @@ -267,7 +266,7 @@ TEST(SimpleColorHueStrategy, alertHueSaturation) |
| 267 | 266 | EXPECT_CALL(test_light, setColorXY(_, _, 1)).Times(AtLeast(2)).WillRepeatedly(Return(true)); |
| 268 | 267 | EXPECT_EQ(true, SimpleColorHueStrategy().alertHueSaturation(200, 100, test_light)); |
| 269 | 268 | |
| 270 | - EXPECT_CALL(test_light, OffNoRefresh(_)).Times(AtLeast(1)).WillRepeatedly(Return(true)); | |
| 269 | + EXPECT_CALL(test_light, Off(_)).Times(AtLeast(1)).WillRepeatedly(Return(true)); | |
| 271 | 270 | test_light.getState()["state"]["on"] = false; |
| 272 | 271 | EXPECT_EQ(true, SimpleColorHueStrategy().alertHueSaturation(200, 100, test_light)); |
| 273 | 272 | } |
| ... | ... | @@ -281,7 +280,6 @@ TEST(SimpleColorHueStrategy, alertXY) |
| 281 | 280 | .Times(AtLeast(1)) |
| 282 | 281 | .WillRepeatedly(Return(nlohmann::json::object())); |
| 283 | 282 | MockHueLight test_light(handler); |
| 284 | - EXPECT_CALL(test_light, refreshState()).Times(AtLeast(1)).WillRepeatedly(Return()); | |
| 285 | 283 | |
| 286 | 284 | test_light.getState()["state"]["colormode"] = "invalid"; |
| 287 | 285 | test_light.getState()["state"]["on"] = false; |
| ... | ... | @@ -302,7 +300,7 @@ TEST(SimpleColorHueStrategy, alertXY) |
| 302 | 300 | EXPECT_CALL(test_light, setColorHueSaturation(_, _, 1)).Times(AtLeast(2)).WillRepeatedly(Return(true)); |
| 303 | 301 | EXPECT_EQ(true, SimpleColorHueStrategy().alertXY(0.1f, 0.1f, test_light)); |
| 304 | 302 | |
| 305 | - EXPECT_CALL(test_light, OffNoRefresh(_)).Times(AtLeast(1)).WillRepeatedly(Return(true)); | |
| 303 | + EXPECT_CALL(test_light, Off(_)).Times(AtLeast(1)).WillRepeatedly(Return(true)); | |
| 306 | 304 | test_light.getState()["state"]["on"] = false; |
| 307 | 305 | EXPECT_EQ(true, SimpleColorHueStrategy().alertXY(0.1f, 0.1f, test_light)); |
| 308 | 306 | |
| ... | ... | @@ -316,7 +314,7 @@ TEST(SimpleColorHueStrategy, alertXY) |
| 316 | 314 | |
| 317 | 315 | EXPECT_EQ(true, SimpleColorHueStrategy().alertXY(0.1f, 0.1f, test_light)); |
| 318 | 316 | |
| 319 | - EXPECT_CALL(test_light, OffNoRefresh(_)).Times(AtLeast(1)).WillRepeatedly(Return(true)); | |
| 317 | + EXPECT_CALL(test_light, Off(_)).Times(AtLeast(1)).WillRepeatedly(Return(true)); | |
| 320 | 318 | test_light.getState()["state"]["on"] = false; |
| 321 | 319 | EXPECT_EQ(true, SimpleColorHueStrategy().alertXY(0.1f, 0.1f, test_light)); |
| 322 | 320 | } |
| ... | ... | @@ -330,7 +328,6 @@ TEST(SimpleColorHueStrategy, alertRGB) |
| 330 | 328 | .Times(AtLeast(1)) |
| 331 | 329 | .WillRepeatedly(Return(nlohmann::json::object())); |
| 332 | 330 | MockHueLight test_light(handler); |
| 333 | - EXPECT_CALL(test_light, refreshState()).Times(AtLeast(1)).WillRepeatedly(Return()); | |
| 334 | 331 | |
| 335 | 332 | test_light.getState()["state"]["colormode"] = "invalid"; |
| 336 | 333 | test_light.getState()["state"]["on"] = false; |
| ... | ... | @@ -352,7 +349,7 @@ TEST(SimpleColorHueStrategy, alertRGB) |
| 352 | 349 | EXPECT_CALL(test_light, setColorHueSaturation(_, _, 1)).Times(AtLeast(2)).WillRepeatedly(Return(true)); |
| 353 | 350 | EXPECT_EQ(true, SimpleColorHueStrategy().alertRGB(128, 128, 128, test_light)); |
| 354 | 351 | |
| 355 | - EXPECT_CALL(test_light, OffNoRefresh(_)).Times(AtLeast(1)).WillRepeatedly(Return(true)); | |
| 352 | + EXPECT_CALL(test_light, Off(_)).Times(AtLeast(1)).WillRepeatedly(Return(true)); | |
| 356 | 353 | test_light.getState()["state"]["on"] = false; |
| 357 | 354 | EXPECT_EQ(true, SimpleColorHueStrategy().alertRGB(128, 128, 128, test_light)); |
| 358 | 355 | |
| ... | ... | @@ -372,7 +369,7 @@ TEST(SimpleColorHueStrategy, alertRGB) |
| 372 | 369 | EXPECT_CALL(test_light, setColorXY(_, _, 1)).Times(AtLeast(2)).WillRepeatedly(Return(true)); |
| 373 | 370 | EXPECT_EQ(true, SimpleColorHueStrategy().alertRGB(128, 128, 128, test_light)); |
| 374 | 371 | |
| 375 | - EXPECT_CALL(test_light, OffNoRefresh(_)).Times(AtLeast(1)).WillRepeatedly(Return(true)); | |
| 372 | + EXPECT_CALL(test_light, Off(_)).Times(AtLeast(1)).WillRepeatedly(Return(true)); | |
| 376 | 373 | test_light.getState()["state"]["on"] = false; |
| 377 | 374 | EXPECT_EQ(true, SimpleColorHueStrategy().alertRGB(128, 128, 128, test_light)); |
| 378 | 375 | } |
| ... | ... | @@ -386,7 +383,6 @@ TEST(SimpleColorHueStrategy, getColorHueSaturation) |
| 386 | 383 | .Times(AtLeast(1)) |
| 387 | 384 | .WillRepeatedly(Return(nlohmann::json::object())); |
| 388 | 385 | MockHueLight test_light(handler); |
| 389 | - EXPECT_CALL(test_light, refreshState()).Times(AtLeast(1)).WillRepeatedly(Return()); | |
| 390 | 386 | |
| 391 | 387 | test_light.getState()["state"]["hue"] = 5000; |
| 392 | 388 | test_light.getState()["state"]["sat"] = 128; |
| ... | ... | @@ -407,7 +403,6 @@ TEST(SimpleColorHueStrategy, getColorXY) |
| 407 | 403 | .Times(AtLeast(1)) |
| 408 | 404 | .WillRepeatedly(Return(nlohmann::json::object())); |
| 409 | 405 | MockHueLight test_light(handler); |
| 410 | - EXPECT_CALL(test_light, refreshState()).Times(AtLeast(1)).WillRepeatedly(Return()); | |
| 411 | 406 | |
| 412 | 407 | test_light.getState()["state"]["xy"][0] = 0.1234; |
| 413 | 408 | test_light.getState()["state"]["xy"][1] = 0.1234; | ... | ... |
test/test_SimpleColorTemperatureStrategy.cpp
| ... | ... | @@ -45,7 +45,7 @@ TEST(SimpleColorTemperatureStrategy, setColorTemperature) |
| 45 | 45 | .Times(AtLeast(1)) |
| 46 | 46 | .WillRepeatedly(Return(nlohmann::json::object())); |
| 47 | 47 | MockHueLight test_light(handler); |
| 48 | - EXPECT_CALL(test_light, refreshState()).Times(AtLeast(1)).WillRepeatedly(Return()); | |
| 48 | + | |
| 49 | 49 | nlohmann::json prep_ret; |
| 50 | 50 | prep_ret = nlohmann::json::array(); |
| 51 | 51 | prep_ret[0] = nlohmann::json::object(); |
| ... | ... | @@ -84,7 +84,6 @@ TEST(SimpleColorTemperatureStrategy, alertTemperature) |
| 84 | 84 | .Times(AtLeast(1)) |
| 85 | 85 | .WillRepeatedly(Return(nlohmann::json::object())); |
| 86 | 86 | MockHueLight test_light(handler); |
| 87 | - EXPECT_CALL(test_light, refreshState()).Times(AtLeast(1)).WillRepeatedly(Return()); | |
| 88 | 87 | |
| 89 | 88 | test_light.getState()["state"]["colormode"] = "invalid"; |
| 90 | 89 | test_light.getState()["state"]["on"] = false; |
| ... | ... | @@ -104,7 +103,7 @@ TEST(SimpleColorTemperatureStrategy, alertTemperature) |
| 104 | 103 | |
| 105 | 104 | EXPECT_EQ(true, SimpleColorTemperatureStrategy().alertTemperature(400, test_light)); |
| 106 | 105 | |
| 107 | - EXPECT_CALL(test_light, OffNoRefresh(_)).Times(AtLeast(1)).WillRepeatedly(Return(true)); | |
| 106 | + EXPECT_CALL(test_light, Off(_)).Times(AtLeast(1)).WillRepeatedly(Return(true)); | |
| 108 | 107 | test_light.getState()["state"]["on"] = false; |
| 109 | 108 | EXPECT_EQ(true, SimpleColorTemperatureStrategy().alertTemperature(400, test_light)); |
| 110 | 109 | } |
| ... | ... | @@ -118,7 +117,6 @@ TEST(SimpleColorTemperatureStrategy, getColorTemperature) |
| 118 | 117 | .Times(AtLeast(1)) |
| 119 | 118 | .WillRepeatedly(Return(nlohmann::json::object())); |
| 120 | 119 | MockHueLight test_light(handler); |
| 121 | - EXPECT_CALL(test_light, refreshState()).Times(AtLeast(1)).WillRepeatedly(Return()); | |
| 122 | 120 | |
| 123 | 121 | test_light.getState()["state"]["ct"] = 200; |
| 124 | 122 | EXPECT_EQ(200, SimpleColorTemperatureStrategy().getColorTemperature(test_light)); | ... | ... |