Commit 67145ea0aa0723d6e3f6ce96038bf4a883feda98

Authored by Jojo-1000
Committed by Moritz Wirger
1 parent 91594d47

Implement StateTransaction to combine more than one state change into one request.

include/hueplusplus/Group.h
@@ -33,6 +33,39 @@ @@ -33,6 +33,39 @@
33 33
34 namespace hueplusplus 34 namespace hueplusplus
35 { 35 {
  36 +class StateTransaction
  37 +{
  38 +public:
  39 + StateTransaction(const HueCommandAPI& commands, const std::string& path, const nlohmann::json& currentState);
  40 +
  41 + StateTransaction(const StateTransaction&) = delete;
  42 + StateTransaction(StateTransaction&&) = default;
  43 +
  44 + bool commit() &&;
  45 +
  46 + StateTransaction&& setOn(bool on) &&;
  47 + StateTransaction&& setBrightness(uint8_t brightness) &&;
  48 + StateTransaction&& setColorHue(uint16_t hue) &&;
  49 + StateTransaction&& setColorSaturation(uint8_t saturation) &&;
  50 + StateTransaction&& setColorHueSaturation(uint16_t hue, uint8_t saturation) &&;
  51 + StateTransaction&& setColorXY(float x, float y) &&;
  52 + StateTransaction&& setColorTemperature(unsigned int mired) &&;
  53 + StateTransaction&& setColorLoop(bool on) &&;
  54 + StateTransaction&& incrementBrightness(int increment) &&;
  55 + StateTransaction&& incrementSaturation(int increment) &&;
  56 + StateTransaction&& incrementHue(int increment) &&;
  57 + StateTransaction&& incrementColorTemperature(int increment) &&;
  58 + StateTransaction&& incrementColorXY(float xInc, float yInc) &&;
  59 + StateTransaction&& setScene(const std::string& scene) &&;
  60 + StateTransaction&& setTransition(uint16_t transition) &&;
  61 +
  62 +private:
  63 + const HueCommandAPI& commands;
  64 + std::string path;
  65 + nlohmann::json state;
  66 + nlohmann::json request;
  67 +};
  68 +
36 class Group 69 class Group
37 { 70 {
38 public: 71 public:
@@ -77,6 +110,8 @@ public: @@ -77,6 +110,8 @@ public:
77 std::string getActionColorMode(); 110 std::string getActionColorMode();
78 std::string getActionColorMode() const; 111 std::string getActionColorMode() const;
79 112
  113 + StateTransaction transaction();
  114 +
80 void setOn(bool on, uint8_t transition = 4); 115 void setOn(bool on, uint8_t transition = 4);
81 void setBrightness(uint8_t brightness, uint8_t transition = 4); 116 void setBrightness(uint8_t brightness, uint8_t transition = 4);
82 void setColorHueSaturation(uint16_t hue, uint8_t saturation, uint8_t transition = 4); 117 void setColorHueSaturation(uint16_t hue, uint8_t saturation, uint8_t transition = 4);
@@ -87,7 +122,7 @@ public: @@ -87,7 +122,7 @@ public:
87 void incrementSaturation(int increment, uint8_t transition = 4); 122 void incrementSaturation(int increment, uint8_t transition = 4);
88 void incrementHue(int increment, uint8_t transition = 4); 123 void incrementHue(int increment, uint8_t transition = 4);
89 void incrementColorTemperature(int increment, uint8_t transition = 4); 124 void incrementColorTemperature(int increment, uint8_t transition = 4);
90 - void incrementColorXY(float increment, uint8_t transition = 4); 125 + void incrementColorXY(float incX, float incY, uint8_t transition = 4);
91 void setScene(const std::string& scene, uint8_t transition = 4); 126 void setScene(const std::string& scene, uint8_t transition = 4);
92 127
93 protected: 128 protected:
src/Group.cpp
@@ -2,6 +2,132 @@ @@ -2,6 +2,132 @@
2 2
3 #include "hueplusplus/HueExceptionMacro.h" 3 #include "hueplusplus/HueExceptionMacro.h"
4 4
  5 +hueplusplus::StateTransaction::StateTransaction(
  6 + const HueCommandAPI& commands, const std::string& path, const nlohmann::json& currentState)
  7 + : commands(commands), path(path), state(state), request(nlohmann::json::object())
  8 +{}
  9 +
  10 +bool hueplusplus::StateTransaction::commit() &&
  11 +{
  12 + // Empty request or request with only transition makes no sense
  13 + if (!request.empty() || (request.size() == 1 && request.count("transition")))
  14 + {
  15 + if (!request.count("on"))
  16 + {
  17 + if (request.value("bri", 254) == 0)
  18 + {
  19 + // Turn off if brightness is 0
  20 + request["on"] = false;
  21 + }
  22 + else if (request.value("bri", 0) != 0 || request.count("colorloop") || request.count("hue")
  23 + || request.count("sat") || request.count("xy"))
  24 + {
  25 + // Turn on if it was turned off
  26 + request["on"] = true;
  27 + }
  28 + }
  29 +
  30 + commands.PUTRequest(path, request, CURRENT_FILE_INFO);
  31 + return true;
  32 + }
  33 + return false;
  34 +}
  35 +
  36 +hueplusplus::StateTransaction&& hueplusplus::StateTransaction::setOn(bool on) &&
  37 +{
  38 + request["on"] = on;
  39 + return std::move(*this);
  40 +}
  41 +
  42 +hueplusplus::StateTransaction&& hueplusplus::StateTransaction::setBrightness(uint8_t brightness) &&
  43 +{
  44 + request["bri"] = std::min<uint8_t>(brightness, 254);
  45 + return std::move(*this);
  46 +}
  47 +
  48 +hueplusplus::StateTransaction&& hueplusplus::StateTransaction::setColorSaturation(uint8_t saturation) &&
  49 +{
  50 + request["sat"] = std::min<uint8_t>(saturation, 254);
  51 + return std::move(*this);
  52 +}
  53 +
  54 +hueplusplus::StateTransaction&& hueplusplus::StateTransaction::setColorHue(uint16_t hue) &&
  55 +{
  56 + request["hue"] = hue;
  57 + return std::move(*this);
  58 +}
  59 +
  60 +hueplusplus::StateTransaction&& hueplusplus::StateTransaction::setColorHueSaturation(
  61 + uint16_t hue, uint8_t saturation) &&
  62 +{
  63 + request["hue"] = hue;
  64 + request["sat"] = std::min<uint8_t>(saturation, 254);
  65 + return std::move(*this);
  66 +}
  67 +
  68 +hueplusplus::StateTransaction&& hueplusplus::StateTransaction::setColorXY(float x, float y) &&
  69 +{
  70 + request["xy"] = {x, y};
  71 + return std::move(*this);
  72 +}
  73 +
  74 +hueplusplus::StateTransaction&& hueplusplus::StateTransaction::setColorTemperature(unsigned int mired) &&
  75 +{
  76 + request["ct"] = mired;
  77 + return std::move(*this);
  78 +}
  79 +
  80 +hueplusplus::StateTransaction&& hueplusplus::StateTransaction::setColorLoop(bool on) &&
  81 +{
  82 + request["effect"] = on ? "colorloop" : "none";
  83 + return std::move(*this);
  84 +}
  85 +
  86 +hueplusplus::StateTransaction&& hueplusplus::StateTransaction::incrementBrightness(int increment) &&
  87 +{
  88 + request["bri_inc"] = std::max(-254, std::min(increment, 254));
  89 + return std::move(*this);
  90 +}
  91 +
  92 +hueplusplus::StateTransaction&& hueplusplus::StateTransaction::incrementSaturation(int increment) &&
  93 +{
  94 + request["sat_inc"] = std::max(-254, std::min(increment, 254));
  95 + return std::move(*this);
  96 +}
  97 +
  98 +hueplusplus::StateTransaction&& hueplusplus::StateTransaction::incrementHue(int increment) &&
  99 +{
  100 + request["hue_inc"] = std::max(-65534, std::min(increment, 65534));
  101 + return std::move(*this);
  102 +}
  103 +
  104 +hueplusplus::StateTransaction&& hueplusplus::StateTransaction::incrementColorTemperature(int increment) &&
  105 +{
  106 + request["ct_inc"] = std::max(-65534, std::min(increment, 65534));
  107 + return std::move(*this);
  108 +}
  109 +
  110 +hueplusplus::StateTransaction&& hueplusplus::StateTransaction::incrementColorXY(float xInc, float yInc) &&
  111 +{
  112 + request["xy_inc"] = {std::min(-0.5f, std::max(xInc, 0.5f)), std::min(-0.5f, std::max(yInc, 0.5f))};
  113 + return std::move(*this);
  114 +}
  115 +
  116 +hueplusplus::StateTransaction&& hueplusplus::StateTransaction::setScene(const std::string& scene) &&
  117 +{
  118 + request["scene"] = scene;
  119 + return std::move(*this);
  120 +}
  121 +
  122 +hueplusplus::StateTransaction&& hueplusplus::StateTransaction::setTransition(uint16_t transition) &&
  123 +{
  124 + if (transition != 4)
  125 + {
  126 + request["transitiontime"] = transition;
  127 + }
  128 + return std::move(*this);
  129 +}
  130 +
5 hueplusplus::Group::Group(int id, const HueCommandAPI& commands, std::chrono::steady_clock::duration refreshDuration) 131 hueplusplus::Group::Group(int id, const HueCommandAPI& commands, std::chrono::steady_clock::duration refreshDuration)
6 : id(id), state("/groups/" + std::to_string(id), commands, refreshDuration), commands(commands) 132 : id(id), state("/groups/" + std::to_string(id), commands, refreshDuration), commands(commands)
7 { 133 {
@@ -134,6 +260,11 @@ std::string hueplusplus::Group::getActionColorMode() const @@ -134,6 +260,11 @@ std::string hueplusplus::Group::getActionColorMode() const
134 return state.GetValue().at("action").at("colormode").get<std::string>(); 260 return state.GetValue().at("action").at("colormode").get<std::string>();
135 } 261 }
136 262
  263 +hueplusplus::StateTransaction hueplusplus::Group::transaction()
  264 +{
  265 + return StateTransaction(commands, "/groups/" + std::to_string(id) + "/action", state.GetValue());
  266 +}
  267 +
137 void hueplusplus::Group::setOn(bool on, uint8_t transition) 268 void hueplusplus::Group::setOn(bool on, uint8_t transition)
138 { 269 {
139 nlohmann::json request = {{"on", on}}; 270 nlohmann::json request = {{"on", on}};
@@ -146,113 +277,57 @@ void hueplusplus::Group::setOn(bool on, uint8_t transition) @@ -146,113 +277,57 @@ void hueplusplus::Group::setOn(bool on, uint8_t transition)
146 277
147 void hueplusplus::Group::setBrightness(uint8_t brightness, uint8_t transition) 278 void hueplusplus::Group::setBrightness(uint8_t brightness, uint8_t transition)
148 { 279 {
149 - // TODO: turn on/off  
150 - nlohmann::json request = {{"bri", brightness}};  
151 - if (transition != 4)  
152 - {  
153 - request["transition"] = transition;  
154 - }  
155 - SendPutRequest(request, "/action", CURRENT_FILE_INFO); 280 + transaction().setBrightness(brightness).setTransition(transition).commit();
156 } 281 }
157 282
158 void hueplusplus::Group::setColorHueSaturation(uint16_t hue, uint8_t saturation, uint8_t transition) 283 void hueplusplus::Group::setColorHueSaturation(uint16_t hue, uint8_t saturation, uint8_t transition)
159 { 284 {
160 - nlohmann::json request = {{"hue", hue}, {"sat", saturation}};  
161 - if (transition != 4)  
162 - {  
163 - request["transition"] = transition;  
164 - }  
165 - SendPutRequest(request, "/action", CURRENT_FILE_INFO); 285 + transaction().setColorHueSaturation(hue, saturation).setTransition(transition).commit();
166 } 286 }
167 287
168 void hueplusplus::Group::setColorXY(float x, float y, uint8_t transition) 288 void hueplusplus::Group::setColorXY(float x, float y, uint8_t transition)
169 { 289 {
170 - nlohmann::json request = {{"xy", {x, y}}};  
171 - if (transition != 4)  
172 - {  
173 - request["transition"] = transition;  
174 - }  
175 - SendPutRequest(request, "/action", CURRENT_FILE_INFO); 290 + transaction().setColorXY(x, y).setTransition(transition).commit();
176 } 291 }
177 292
178 void hueplusplus::Group::setColorTemperature(unsigned int mired, uint8_t transition) 293 void hueplusplus::Group::setColorTemperature(unsigned int mired, uint8_t transition)
179 { 294 {
180 - nlohmann::json request = {{"ct", mired}};  
181 - if (transition != 4)  
182 - {  
183 - request["transition"] = transition;  
184 - }  
185 - SendPutRequest(request, "/action", CURRENT_FILE_INFO); 295 + transaction().setColorTemperature(mired).setTransition(transition).commit();
186 } 296 }
187 297
188 void hueplusplus::Group::setColorLoop(bool on, uint8_t transition) 298 void hueplusplus::Group::setColorLoop(bool on, uint8_t transition)
189 { 299 {
190 - nlohmann::json request = {{"effect", on ? "colorloop" : "none"}};  
191 - if (transition != 4)  
192 - {  
193 - request["transition"] = transition;  
194 - }  
195 - SendPutRequest(request, "/action", CURRENT_FILE_INFO); 300 + transaction().setColorLoop(on).setTransition(transition);
196 } 301 }
197 302
198 void hueplusplus::Group::incrementBrightness(int increment, uint8_t transition) 303 void hueplusplus::Group::incrementBrightness(int increment, uint8_t transition)
199 { 304 {
200 - nlohmann::json request = {{"bri_inc", increment}};  
201 - if (transition != 4)  
202 - {  
203 - request["transition"] = transition;  
204 - }  
205 - SendPutRequest(request, "/action", CURRENT_FILE_INFO); 305 + transaction().incrementBrightness(increment).setTransition(transition).commit();
206 } 306 }
207 307
208 void hueplusplus::Group::incrementSaturation(int increment, uint8_t transition) 308 void hueplusplus::Group::incrementSaturation(int increment, uint8_t transition)
209 { 309 {
210 - nlohmann::json request = {{"sat_inc", increment}};  
211 - if (transition != 4)  
212 - {  
213 - request["transition"] = transition;  
214 - }  
215 - SendPutRequest(request, "/action", CURRENT_FILE_INFO); 310 + transaction().incrementSaturation(increment).setTransition(transition).commit();
216 } 311 }
217 312
218 void hueplusplus::Group::incrementHue(int increment, uint8_t transition) 313 void hueplusplus::Group::incrementHue(int increment, uint8_t transition)
219 { 314 {
220 - nlohmann::json request = {{"hue_inc", increment}};  
221 - if (transition != 4)  
222 - {  
223 - request["transition"] = transition;  
224 - }  
225 - SendPutRequest(request, "/action", CURRENT_FILE_INFO); 315 + transaction().incrementHue(increment).setTransition(transition).commit();
226 } 316 }
227 317
228 void hueplusplus::Group::incrementColorTemperature(int increment, uint8_t transition) 318 void hueplusplus::Group::incrementColorTemperature(int increment, uint8_t transition)
229 { 319 {
230 - nlohmann::json request = {{"ct_inc", increment}};  
231 - if (transition != 4)  
232 - {  
233 - request["transition"] = transition;  
234 - }  
235 - SendPutRequest(request, "/action", CURRENT_FILE_INFO); 320 + transaction().incrementColorTemperature(increment).setTransition(transition).commit();
236 } 321 }
237 322
238 -void hueplusplus::Group::incrementColorXY(float increment, uint8_t transition) 323 +void hueplusplus::Group::incrementColorXY(float incX, float incY, uint8_t transition)
239 { 324 {
240 - nlohmann::json request = {{"xy_inc", increment}};  
241 - if (transition != 4)  
242 - {  
243 - request["transition"] = transition;  
244 - }  
245 - SendPutRequest(request, "/action", CURRENT_FILE_INFO); 325 + transaction().incrementColorXY(incX, incY).setTransition(transition).commit();
246 } 326 }
247 327
248 void hueplusplus::Group::setScene(const std::string& scene, uint8_t transition) 328 void hueplusplus::Group::setScene(const std::string& scene, uint8_t transition)
249 { 329 {
250 - nlohmann::json request = {{"scene", scene}};  
251 - if (transition != 4)  
252 - {  
253 - request["transition"] = transition;  
254 - }  
255 - SendPutRequest(request, "/action", CURRENT_FILE_INFO); 330 + transaction().setScene(scene).setTransition(transition).commit();
256 } 331 }
257 332
258 nlohmann::json hueplusplus::Group::SendPutRequest( 333 nlohmann::json hueplusplus::Group::SendPutRequest(