Commit cd30bc7443f7fede4fce158b792397f44962b39c

Authored by Jojo-1000
Committed by Moritz Wirger
1 parent 1eaf314c

Implement APICache to cache json values returned by the Hue API.

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
1 1 set(hueplusplus_SOURCES
  2 + APICache.cpp
2 3 BaseHttpHandler.cpp
3 4 ExtendedColorHueStrategy.cpp
4 5 ExtendedColorTemperatureStrategy.cpp
... ...
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&amp; 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&amp; 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&amp; 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&amp; 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&amp; 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&amp; 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&amp; 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&amp; 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&lt;std::reference_wrapper&lt;HueLight&gt;&gt; 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&amp; 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&amp; 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&amp; 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&amp; 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&amp; 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&amp; 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&amp; 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&amp; 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&amp; 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&amp; 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&amp; 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&amp;
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&amp;
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&amp;
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&amp;
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));
... ...