Commit 67145ea0aa0723d6e3f6ce96038bf4a883feda98
Committed by
Moritz Wirger
1 parent
91594d47
Implement StateTransaction to combine more than one state change into one request.
Showing
2 changed files
with
179 additions
and
69 deletions
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( |