Commit d3e59bb1835dbad6bb1a0a3e36343d313d2a5b7e
Committed by
Moritz Wirger
1 parent
67145ea0
Generalize StateTransaction to also work for HueLight state.
Showing
18 changed files
with
413 additions
and
516 deletions
include/hueplusplus/Group.h
| ... | ... | @@ -28,44 +28,12 @@ |
| 28 | 28 | |
| 29 | 29 | #include "APICache.h" |
| 30 | 30 | #include "HueCommandAPI.h" |
| 31 | +#include "StateTransaction.h" | |
| 31 | 32 | |
| 32 | 33 | #include "json/json.hpp" |
| 33 | 34 | |
| 34 | 35 | namespace hueplusplus |
| 35 | 36 | { |
| 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 | - | |
| 69 | 37 | class Group |
| 70 | 38 | { |
| 71 | 39 | public: | ... | ... |
include/hueplusplus/HueLight.h
| ... | ... | @@ -30,6 +30,7 @@ |
| 30 | 30 | #include "ColorHueStrategy.h" |
| 31 | 31 | #include "ColorTemperatureStrategy.h" |
| 32 | 32 | #include "HueCommandAPI.h" |
| 33 | +#include "StateTransaction.h" | |
| 33 | 34 | |
| 34 | 35 | #include "json/json.hpp" |
| 35 | 36 | |
| ... | ... | @@ -78,7 +79,7 @@ LLC020 // Hue Go, Color Gamut C, ECL |
| 78 | 79 | };*/ |
| 79 | 80 | |
| 80 | 81 | //! enum that specifies the color type of all HueLights |
| 81 | -enum ColorType | |
| 82 | +enum class ColorType | |
| 82 | 83 | { |
| 83 | 84 | UNDEFINED, //!< ColorType for this light is unknown or undefined |
| 84 | 85 | NONE, //!< light has no specific ColorType |
| ... | ... | @@ -676,6 +677,8 @@ public: |
| 676 | 677 | return false; |
| 677 | 678 | }; |
| 678 | 679 | |
| 680 | + virtual StateTransaction transaction(); | |
| 681 | + | |
| 679 | 682 | protected: |
| 680 | 683 | //! \brief Protected ctor that is used by \ref Hue class. |
| 681 | 684 | //! | ... | ... |
include/hueplusplus/StateTransaction.h
0 → 100644
| 1 | +/** | |
| 2 | + \file StateTransaction.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_HUEPLUSPLUS_STATE_TRANSACTION_H | |
| 24 | +#define INCLUDE_HUEPLUSPLUS_STATE_TRANSACTION_H | |
| 25 | + | |
| 26 | +#include <string> | |
| 27 | + | |
| 28 | +#include "HueCommandAPI.h" | |
| 29 | + | |
| 30 | +#include "json/json.hpp" | |
| 31 | + | |
| 32 | +namespace hueplusplus | |
| 33 | +{ | |
| 34 | +class StateTransaction | |
| 35 | +{ | |
| 36 | +public: | |
| 37 | + StateTransaction(const HueCommandAPI& commands, const std::string& path, const nlohmann::json& currentState); | |
| 38 | + | |
| 39 | + StateTransaction(const StateTransaction&) = delete; | |
| 40 | + StateTransaction(StateTransaction&&) = default; | |
| 41 | + | |
| 42 | + bool commit() &&; | |
| 43 | + | |
| 44 | + StateTransaction&& setOn(bool on) &&; | |
| 45 | + StateTransaction&& setBrightness(uint8_t brightness) &&; | |
| 46 | + StateTransaction&& setColorHue(uint16_t hue) &&; | |
| 47 | + StateTransaction&& setColorSaturation(uint8_t saturation) &&; | |
| 48 | + StateTransaction&& setColorHueSaturation(uint16_t hue, uint8_t saturation) &&; | |
| 49 | + StateTransaction&& setColorXY(float x, float y) &&; | |
| 50 | + StateTransaction&& setColorTemperature(unsigned int mired) &&; | |
| 51 | + StateTransaction&& setColorLoop(bool on) &&; | |
| 52 | + StateTransaction&& incrementBrightness(int increment) &&; | |
| 53 | + StateTransaction&& incrementSaturation(int increment) &&; | |
| 54 | + StateTransaction&& incrementHue(int increment) &&; | |
| 55 | + StateTransaction&& incrementColorTemperature(int increment) &&; | |
| 56 | + StateTransaction&& incrementColorXY(float xInc, float yInc) &&; | |
| 57 | + StateTransaction&& setTransition(uint16_t transition) &&; | |
| 58 | + StateTransaction&& alert() &&; | |
| 59 | + StateTransaction&& longAlert() &&; | |
| 60 | + StateTransaction&& stopAlert() &&; | |
| 61 | + | |
| 62 | +protected: | |
| 63 | + const HueCommandAPI& commands; | |
| 64 | + std::string path; | |
| 65 | + nlohmann::json state; | |
| 66 | + nlohmann::json request; | |
| 67 | +}; | |
| 68 | + | |
| 69 | +} // namespace hueplusplus | |
| 70 | + | |
| 71 | +#endif | |
| 0 | 72 | \ No newline at end of file | ... | ... |
include/hueplusplus/Utils.h
| ... | ... | @@ -66,12 +66,22 @@ nlohmann::json safeGetMemberHelper(const nlohmann::json& json, std::size_t index |
| 66 | 66 | |
| 67 | 67 | //! \brief Function for validating that a request was executed correctly |
| 68 | 68 | //! |
| 69 | +//! \param path The path the PUT request was made to | |
| 69 | 70 | //! \param request The request that was sent initially |
| 70 | 71 | //! \param reply The reply that was received |
| 71 | -//! \param lightId The identifier of the light | |
| 72 | 72 | //! \return True if request was executed correctly |
| 73 | +bool validatePUTReply(const std::string& path, const nlohmann::json& request, const nlohmann::json& reply); | |
| 74 | + | |
| 73 | 75 | bool validateReplyForLight(const nlohmann::json& request, const nlohmann::json& reply, int lightId); |
| 74 | 76 | |
| 77 | +//! \brief Checks equality to 4 decimal places | |
| 78 | +//! | |
| 79 | +//! Floats in Hue json responses are rounded to 4 decimal places. | |
| 80 | +inline bool floatEquals(float lhs, float rhs) | |
| 81 | +{ | |
| 82 | + return std::abs(lhs - rhs) <= 1E-4f; | |
| 83 | +} | |
| 84 | + | |
| 75 | 85 | //! \brief Returns the object/array member or null if it does not exist |
| 76 | 86 | //! |
| 77 | 87 | //! \param json The base json value | ... | ... |
src/CMakeLists.txt
src/ExtendedColorHueStrategy.cpp
| ... | ... | @@ -200,8 +200,8 @@ bool ExtendedColorHueStrategy::alertRGB(uint8_t r, uint8_t g, uint8_t b, HueLigh |
| 200 | 200 | { |
| 201 | 201 | // Careful, only use state until any light function might refresh the value and invalidate the reference |
| 202 | 202 | const nlohmann::json& state = light.state.GetValue()["state"]; |
| 203 | - std::string cType = state["colormode"]; | |
| 204 | - bool on = state["on"]; | |
| 203 | + std::string cType = state["colormode"].get<std::string>(); | |
| 204 | + bool on = state["on"].get<bool>(); | |
| 205 | 205 | if (cType == "hs") |
| 206 | 206 | { |
| 207 | 207 | uint16_t oldHue = state["hue"].get<uint16_t>(); | ... | ... |
src/Group.cpp
| ... | ... | @@ -2,159 +2,35 @@ |
| 2 | 2 | |
| 3 | 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) && | |
| 5 | +namespace hueplusplus | |
| 81 | 6 | { |
| 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 | - | |
| 131 | -hueplusplus::Group::Group(int id, const HueCommandAPI& commands, std::chrono::steady_clock::duration refreshDuration) | |
| 7 | +Group::Group(int id, const HueCommandAPI& commands, std::chrono::steady_clock::duration refreshDuration) | |
| 132 | 8 | : id(id), state("/groups/" + std::to_string(id), commands, refreshDuration), commands(commands) |
| 133 | 9 | { |
| 134 | 10 | state.Refresh(); |
| 135 | 11 | } |
| 136 | 12 | |
| 137 | -void hueplusplus::Group::Refresh() | |
| 13 | +void Group::Refresh() | |
| 138 | 14 | { |
| 139 | 15 | state.Refresh(); |
| 140 | 16 | } |
| 141 | 17 | |
| 142 | -int hueplusplus::Group::getId() const | |
| 18 | +int Group::getId() const | |
| 143 | 19 | { |
| 144 | 20 | return id; |
| 145 | 21 | } |
| 146 | 22 | |
| 147 | -std::string hueplusplus::Group::getName() const | |
| 23 | +std::string Group::getName() const | |
| 148 | 24 | { |
| 149 | 25 | return state.GetValue().at("name").get<std::string>(); |
| 150 | 26 | } |
| 151 | 27 | |
| 152 | -std::string hueplusplus::Group::getType() const | |
| 28 | +std::string Group::getType() const | |
| 153 | 29 | { |
| 154 | 30 | return state.GetValue().at("type").get<std::string>(); |
| 155 | 31 | } |
| 156 | 32 | |
| 157 | -std::vector<int> hueplusplus::Group::getLightIds() const | |
| 33 | +std::vector<int> Group::getLightIds() const | |
| 158 | 34 | { |
| 159 | 35 | const nlohmann::json& lights = state.GetValue().at("lights"); |
| 160 | 36 | std::vector<int> ids; |
| ... | ... | @@ -166,13 +42,13 @@ std::vector<int> hueplusplus::Group::getLightIds() const |
| 166 | 42 | return ids; |
| 167 | 43 | } |
| 168 | 44 | |
| 169 | -void hueplusplus::Group::setName(const std::string& name) | |
| 45 | +void Group::setName(const std::string& name) | |
| 170 | 46 | { |
| 171 | 47 | nlohmann::json request = {{"name", name}}; |
| 172 | 48 | SendPutRequest(request, "", CURRENT_FILE_INFO); |
| 173 | 49 | } |
| 174 | 50 | |
| 175 | -void hueplusplus::Group::setLights(const std::vector<int>& ids) | |
| 51 | +void Group::setLights(const std::vector<int>& ids) | |
| 176 | 52 | { |
| 177 | 53 | nlohmann::json lights = nlohmann::json::array(); |
| 178 | 54 | for (int id : ids) |
| ... | ... | @@ -182,90 +58,91 @@ void hueplusplus::Group::setLights(const std::vector<int>& ids) |
| 182 | 58 | SendPutRequest({{"lights", lights}}, "", CURRENT_FILE_INFO); |
| 183 | 59 | } |
| 184 | 60 | |
| 185 | -bool hueplusplus::Group::getAllOn() | |
| 61 | +bool Group::getAllOn() | |
| 186 | 62 | { |
| 187 | 63 | return state.GetValue().at("state").at("all_on").get<bool>(); |
| 188 | 64 | } |
| 189 | -bool hueplusplus::Group::getAllOn() const | |
| 65 | +bool Group::getAllOn() const | |
| 190 | 66 | { |
| 191 | 67 | return state.GetValue().at("state").at("all_on").get<bool>(); |
| 192 | 68 | } |
| 193 | 69 | |
| 194 | -bool hueplusplus::Group::getAnyOn() | |
| 70 | +bool Group::getAnyOn() | |
| 195 | 71 | { |
| 196 | 72 | return state.GetValue().at("state").at("any_on").get<bool>(); |
| 197 | 73 | } |
| 198 | -bool hueplusplus::Group::getAnyOn() const | |
| 74 | +bool Group::getAnyOn() const | |
| 199 | 75 | { |
| 200 | 76 | return state.GetValue().at("state").at("any_on").get<bool>(); |
| 201 | 77 | } |
| 202 | 78 | |
| 203 | -bool hueplusplus::Group::getActionOn() | |
| 79 | +bool Group::getActionOn() | |
| 204 | 80 | { |
| 205 | 81 | return state.GetValue().at("action").at("on").get<bool>(); |
| 206 | 82 | } |
| 207 | -bool hueplusplus::Group::getActionOn() const | |
| 83 | +bool Group::getActionOn() const | |
| 208 | 84 | { |
| 209 | 85 | return state.GetValue().at("action").at("on").get<bool>(); |
| 210 | 86 | } |
| 211 | 87 | |
| 212 | -std::pair<uint16_t, uint8_t> hueplusplus::Group::getActionHueSaturation() | |
| 88 | +std::pair<uint16_t, uint8_t> Group::getActionHueSaturation() | |
| 213 | 89 | { |
| 214 | 90 | const nlohmann::json& action = state.GetValue().at("action"); |
| 215 | 91 | |
| 216 | 92 | return std::make_pair(action.at("hue").get<int>(), action.at("sat").get<int>()); |
| 217 | 93 | } |
| 218 | -std::pair<uint16_t, uint8_t> hueplusplus::Group::getActionHueSaturation() const | |
| 94 | +std::pair<uint16_t, uint8_t> Group::getActionHueSaturation() const | |
| 219 | 95 | { |
| 220 | 96 | const nlohmann::json& action = state.GetValue().at("action"); |
| 221 | 97 | |
| 222 | 98 | return std::make_pair(action.at("hue").get<int>(), action.at("sat").get<int>()); |
| 223 | 99 | } |
| 224 | 100 | |
| 225 | -unsigned int hueplusplus::Group::getActionBrightness() | |
| 101 | +unsigned int Group::getActionBrightness() | |
| 226 | 102 | { |
| 227 | 103 | return state.GetValue().at("action").at("bri").get<int>(); |
| 228 | 104 | } |
| 229 | -unsigned int hueplusplus::Group::getActionBrightness() const | |
| 105 | +unsigned int Group::getActionBrightness() const | |
| 230 | 106 | { |
| 231 | 107 | return state.GetValue().at("action").at("bri").get<int>(); |
| 232 | 108 | } |
| 233 | 109 | |
| 234 | -unsigned int hueplusplus::Group::getActionColorTemperature() | |
| 110 | +unsigned int Group::getActionColorTemperature() | |
| 235 | 111 | { |
| 236 | 112 | return state.GetValue().at("action").at("ct").get<int>(); |
| 237 | 113 | } |
| 238 | -unsigned int hueplusplus::Group::getActionColorTemperature() const | |
| 114 | +unsigned int Group::getActionColorTemperature() const | |
| 239 | 115 | { |
| 240 | 116 | return state.GetValue().at("action").at("ct").get<int>(); |
| 241 | 117 | } |
| 242 | 118 | |
| 243 | -std::pair<float, float> hueplusplus::Group::getActionColorXY() | |
| 119 | +std::pair<float, float> Group::getActionColorXY() | |
| 244 | 120 | { |
| 245 | 121 | const nlohmann::json& xy = state.GetValue().at("action").at("xy"); |
| 246 | 122 | return std::pair<float, float>(xy[0].get<float>(), xy[1].get<float>()); |
| 247 | 123 | } |
| 248 | -std::pair<float, float> hueplusplus::Group::getActionColorXY() const | |
| 124 | +std::pair<float, float> Group::getActionColorXY() const | |
| 249 | 125 | { |
| 250 | 126 | const nlohmann::json& xy = state.GetValue().at("action").at("xy"); |
| 251 | 127 | return std::pair<float, float>(xy[0].get<float>(), xy[1].get<float>()); |
| 252 | 128 | } |
| 253 | 129 | |
| 254 | -std::string hueplusplus::Group::getActionColorMode() | |
| 130 | +std::string Group::getActionColorMode() | |
| 255 | 131 | { |
| 256 | 132 | return state.GetValue().at("action").at("colormode").get<std::string>(); |
| 257 | 133 | } |
| 258 | -std::string hueplusplus::Group::getActionColorMode() const | |
| 134 | +std::string Group::getActionColorMode() const | |
| 259 | 135 | { |
| 260 | 136 | return state.GetValue().at("action").at("colormode").get<std::string>(); |
| 261 | 137 | } |
| 262 | 138 | |
| 263 | -hueplusplus::StateTransaction hueplusplus::Group::transaction() | |
| 139 | +StateTransaction Group::transaction() | |
| 264 | 140 | { |
| 265 | - return StateTransaction(commands, "/groups/" + std::to_string(id) + "/action", state.GetValue()); | |
| 141 | + // Do not pass state, because it is not the state of ALL lights in the group | |
| 142 | + return StateTransaction(commands, "/groups/" + std::to_string(id) + "/action", nlohmann::json::object()); | |
| 266 | 143 | } |
| 267 | 144 | |
| 268 | -void hueplusplus::Group::setOn(bool on, uint8_t transition) | |
| 145 | +void Group::setOn(bool on, uint8_t transition) | |
| 269 | 146 | { |
| 270 | 147 | nlohmann::json request = {{"on", on}}; |
| 271 | 148 | if (transition != 4) |
| ... | ... | @@ -275,83 +152,83 @@ void hueplusplus::Group::setOn(bool on, uint8_t transition) |
| 275 | 152 | SendPutRequest(request, "/action", CURRENT_FILE_INFO); |
| 276 | 153 | } |
| 277 | 154 | |
| 278 | -void hueplusplus::Group::setBrightness(uint8_t brightness, uint8_t transition) | |
| 155 | +void Group::setBrightness(uint8_t brightness, uint8_t transition) | |
| 279 | 156 | { |
| 280 | 157 | transaction().setBrightness(brightness).setTransition(transition).commit(); |
| 281 | 158 | } |
| 282 | 159 | |
| 283 | -void hueplusplus::Group::setColorHueSaturation(uint16_t hue, uint8_t saturation, uint8_t transition) | |
| 160 | +void Group::setColorHueSaturation(uint16_t hue, uint8_t saturation, uint8_t transition) | |
| 284 | 161 | { |
| 285 | 162 | transaction().setColorHueSaturation(hue, saturation).setTransition(transition).commit(); |
| 286 | 163 | } |
| 287 | 164 | |
| 288 | -void hueplusplus::Group::setColorXY(float x, float y, uint8_t transition) | |
| 165 | +void Group::setColorXY(float x, float y, uint8_t transition) | |
| 289 | 166 | { |
| 290 | 167 | transaction().setColorXY(x, y).setTransition(transition).commit(); |
| 291 | 168 | } |
| 292 | 169 | |
| 293 | -void hueplusplus::Group::setColorTemperature(unsigned int mired, uint8_t transition) | |
| 170 | +void Group::setColorTemperature(unsigned int mired, uint8_t transition) | |
| 294 | 171 | { |
| 295 | 172 | transaction().setColorTemperature(mired).setTransition(transition).commit(); |
| 296 | 173 | } |
| 297 | 174 | |
| 298 | -void hueplusplus::Group::setColorLoop(bool on, uint8_t transition) | |
| 175 | +void Group::setColorLoop(bool on, uint8_t transition) | |
| 299 | 176 | { |
| 300 | 177 | transaction().setColorLoop(on).setTransition(transition); |
| 301 | 178 | } |
| 302 | 179 | |
| 303 | -void hueplusplus::Group::incrementBrightness(int increment, uint8_t transition) | |
| 180 | +void Group::incrementBrightness(int increment, uint8_t transition) | |
| 304 | 181 | { |
| 305 | 182 | transaction().incrementBrightness(increment).setTransition(transition).commit(); |
| 306 | 183 | } |
| 307 | 184 | |
| 308 | -void hueplusplus::Group::incrementSaturation(int increment, uint8_t transition) | |
| 185 | +void Group::incrementSaturation(int increment, uint8_t transition) | |
| 309 | 186 | { |
| 310 | 187 | transaction().incrementSaturation(increment).setTransition(transition).commit(); |
| 311 | 188 | } |
| 312 | 189 | |
| 313 | -void hueplusplus::Group::incrementHue(int increment, uint8_t transition) | |
| 190 | +void Group::incrementHue(int increment, uint8_t transition) | |
| 314 | 191 | { |
| 315 | 192 | transaction().incrementHue(increment).setTransition(transition).commit(); |
| 316 | 193 | } |
| 317 | 194 | |
| 318 | -void hueplusplus::Group::incrementColorTemperature(int increment, uint8_t transition) | |
| 195 | +void Group::incrementColorTemperature(int increment, uint8_t transition) | |
| 319 | 196 | { |
| 320 | 197 | transaction().incrementColorTemperature(increment).setTransition(transition).commit(); |
| 321 | 198 | } |
| 322 | 199 | |
| 323 | -void hueplusplus::Group::incrementColorXY(float incX, float incY, uint8_t transition) | |
| 200 | +void Group::incrementColorXY(float incX, float incY, uint8_t transition) | |
| 324 | 201 | { |
| 325 | 202 | transaction().incrementColorXY(incX, incY).setTransition(transition).commit(); |
| 326 | 203 | } |
| 327 | 204 | |
| 328 | -void hueplusplus::Group::setScene(const std::string& scene, uint8_t transition) | |
| 205 | +void Group::setScene(const std::string& scene, uint8_t transition) | |
| 329 | 206 | { |
| 330 | - transaction().setScene(scene).setTransition(transition).commit(); | |
| 207 | + SendPutRequest({ {"scene", scene} }, "/action", CURRENT_FILE_INFO); | |
| 331 | 208 | } |
| 332 | 209 | |
| 333 | -nlohmann::json hueplusplus::Group::SendPutRequest( | |
| 334 | - const nlohmann::json& request, const std::string& subPath, FileInfo fileInfo) | |
| 210 | +nlohmann::json Group::SendPutRequest(const nlohmann::json& request, const std::string& subPath, FileInfo fileInfo) | |
| 335 | 211 | { |
| 336 | 212 | return commands.PUTRequest("/groups/" + std::to_string(id) + subPath, request, std::move(fileInfo)); |
| 337 | 213 | } |
| 338 | 214 | |
| 339 | -std::string hueplusplus::Group::getRoomType() const | |
| 215 | +std::string Group::getRoomType() const | |
| 340 | 216 | { |
| 341 | 217 | return state.GetValue().at("class").get<std::string>(); |
| 342 | 218 | } |
| 343 | 219 | |
| 344 | -void hueplusplus::Group::setRoomType(const std::string& type) | |
| 220 | +void Group::setRoomType(const std::string& type) | |
| 345 | 221 | { |
| 346 | 222 | SendPutRequest({{"class", type}}, "", CURRENT_FILE_INFO); |
| 347 | 223 | } |
| 348 | 224 | |
| 349 | -std::string hueplusplus::Group::getModelId() const | |
| 225 | +std::string Group::getModelId() const | |
| 350 | 226 | { |
| 351 | 227 | return state.GetValue().at("modelid").get<std::string>(); |
| 352 | 228 | } |
| 353 | 229 | |
| 354 | -std::string hueplusplus::Group::getUniqueId() const | |
| 230 | +std::string Group::getUniqueId() const | |
| 355 | 231 | { |
| 356 | 232 | return state.GetValue().at("uniqueid").get<std::string>(); |
| 357 | 233 | } |
| 234 | +} // namespace hueplusplus | ... | ... |
src/HueLight.cpp
| ... | ... | @@ -34,60 +34,22 @@ namespace hueplusplus |
| 34 | 34 | { |
| 35 | 35 | bool HueLight::On(uint8_t transition) |
| 36 | 36 | { |
| 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); | |
| 37 | + return transaction().setOn(true).setTransition(transition).commit(); | |
| 57 | 38 | } |
| 58 | 39 | |
| 59 | 40 | bool HueLight::Off(uint8_t transition) |
| 60 | 41 | { |
| 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); | |
| 42 | + return transaction().setOn(false).setTransition(transition).commit(); | |
| 81 | 43 | } |
| 82 | 44 | |
| 83 | 45 | bool HueLight::isOn() |
| 84 | 46 | { |
| 85 | - return state.GetValue()["state"]["on"].get<bool>(); | |
| 47 | + return state.GetValue().at("state").at("on").get<bool>(); | |
| 86 | 48 | } |
| 87 | 49 | |
| 88 | 50 | bool HueLight::isOn() const |
| 89 | 51 | { |
| 90 | - return state.GetValue()["state"]["on"].get<bool>(); | |
| 52 | + return state.GetValue().at("state").at("on").get<bool>(); | |
| 91 | 53 | } |
| 92 | 54 | |
| 93 | 55 | int HueLight::getId() const |
| ... | ... | @@ -173,12 +135,12 @@ unsigned int HueLight::MiredToKelvin(unsigned int mired) const |
| 173 | 135 | |
| 174 | 136 | bool HueLight::alert() |
| 175 | 137 | { |
| 176 | - nlohmann::json request; | |
| 177 | - request["alert"] = "select"; | |
| 178 | - | |
| 179 | - nlohmann::json reply = SendPutRequest(request, "/state", CURRENT_FILE_INFO); | |
| 138 | + return transaction().alert().commit(); | |
| 139 | +} | |
| 180 | 140 | |
| 181 | - return utils::validateReplyForLight(request, reply, id); | |
| 141 | +StateTransaction HueLight::transaction() | |
| 142 | +{ | |
| 143 | + return StateTransaction(commands, "/lights/" + std::to_string(id) + "/state", state.GetValue().at("state")); | |
| 182 | 144 | } |
| 183 | 145 | |
| 184 | 146 | HueLight::HueLight(int id, const HueCommandAPI& commands) : HueLight(id, commands, nullptr, nullptr, nullptr) {} |
| ... | ... | @@ -187,12 +149,12 @@ HueLight::HueLight(int id, const HueCommandAPI& commands, std::shared_ptr<const |
| 187 | 149 | std::shared_ptr<const ColorTemperatureStrategy> colorTempStrategy, |
| 188 | 150 | std::shared_ptr<const ColorHueStrategy> colorHueStrategy, std::chrono::steady_clock::duration refreshDuration) |
| 189 | 151 | : id(id), |
| 152 | + state("/lights/" + std::to_string(id), commands, refreshDuration), | |
| 153 | + colorType(ColorType::NONE), | |
| 190 | 154 | brightnessStrategy(std::move(brightnessStrategy)), |
| 191 | 155 | colorTemperatureStrategy(std::move(colorTempStrategy)), |
| 192 | 156 | colorHueStrategy(std::move(colorHueStrategy)), |
| 193 | - commands(commands), | |
| 194 | - state("/lights/" + std::to_string(id), commands, refreshDuration) | |
| 195 | - | |
| 157 | + commands(commands) | |
| 196 | 158 | { |
| 197 | 159 | state.Refresh(); |
| 198 | 160 | } | ... | ... |
src/SimpleBrightnessStrategy.cpp
| ... | ... | @@ -34,49 +34,7 @@ namespace hueplusplus |
| 34 | 34 | bool SimpleBrightnessStrategy::setBrightness(unsigned int bri, uint8_t transition, HueLight& light) const |
| 35 | 35 | { |
| 36 | 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"]; | |
| 38 | - if (bri == 0) | |
| 39 | - { | |
| 40 | - if (state["on"] == true) | |
| 41 | - { | |
| 42 | - return light.Off(transition); | |
| 43 | - } | |
| 44 | - else | |
| 45 | - { | |
| 46 | - return true; | |
| 47 | - } | |
| 48 | - } | |
| 49 | - else | |
| 50 | - { | |
| 51 | - nlohmann::json request = nlohmann::json::object(); | |
| 52 | - if (transition != 4) | |
| 53 | - { | |
| 54 | - request["transitiontime"] = transition; | |
| 55 | - } | |
| 56 | - if (state["on"] != true) | |
| 57 | - { | |
| 58 | - request["on"] = true; | |
| 59 | - } | |
| 60 | - if (state["bri"] != bri) | |
| 61 | - { | |
| 62 | - if (bri > 254) | |
| 63 | - { | |
| 64 | - bri = 254; | |
| 65 | - } | |
| 66 | - request["bri"] = bri; | |
| 67 | - } | |
| 68 | - | |
| 69 | - if (!request.count("on") && !request.count("bri")) | |
| 70 | - { | |
| 71 | - // Nothing needs to be changed | |
| 72 | - return true; | |
| 73 | - } | |
| 74 | - | |
| 75 | - nlohmann::json reply = light.SendPutRequest(request, "/state", CURRENT_FILE_INFO); | |
| 76 | - | |
| 77 | - // Check whether request was successful | |
| 78 | - return utils::validateReplyForLight(request, reply, light.id); | |
| 79 | - } | |
| 37 | + return light.transaction().setBrightness(bri).setTransition(transition).commit(); | |
| 80 | 38 | } |
| 81 | 39 | |
| 82 | 40 | unsigned int SimpleBrightnessStrategy::getBrightness(HueLight& light) const | ... | ... |
src/SimpleColorHueStrategy.cpp
| ... | ... | @@ -34,140 +34,22 @@ namespace hueplusplus |
| 34 | 34 | { |
| 35 | 35 | bool SimpleColorHueStrategy::setColorHue(uint16_t hue, uint8_t transition, HueLight& light) const |
| 36 | 36 | { |
| 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"]; | |
| 39 | - nlohmann::json request = nlohmann::json::object(); | |
| 40 | - if (transition != 4) | |
| 41 | - { | |
| 42 | - request["transitiontime"] = transition; | |
| 43 | - } | |
| 44 | - if (state["on"] != true) | |
| 45 | - { | |
| 46 | - request["on"] = true; | |
| 47 | - } | |
| 48 | - if (state["hue"] != hue || state["colormode"] != "hs") | |
| 49 | - { | |
| 50 | - hue = hue % 65535; | |
| 51 | - request["hue"] = hue; | |
| 52 | - } | |
| 53 | - | |
| 54 | - if (!request.count("on") && !request.count("hue")) | |
| 55 | - { | |
| 56 | - // Nothing needs to be changed | |
| 57 | - return true; | |
| 58 | - } | |
| 59 | - | |
| 60 | - nlohmann::json reply = light.SendPutRequest(request, "/state", CURRENT_FILE_INFO); | |
| 61 | - | |
| 62 | - // Check whether request was successful | |
| 63 | - return utils::validateReplyForLight(request, reply, light.id); | |
| 37 | + return light.transaction().setColorHue(hue).setTransition(transition).commit(); | |
| 64 | 38 | } |
| 65 | 39 | |
| 66 | 40 | bool SimpleColorHueStrategy::setColorSaturation(uint8_t sat, uint8_t transition, HueLight& light) const |
| 67 | 41 | { |
| 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"]; | |
| 70 | - nlohmann::json request = nlohmann::json::object(); | |
| 71 | - if (transition != 4) | |
| 72 | - { | |
| 73 | - request["transitiontime"] = transition; | |
| 74 | - } | |
| 75 | - if (state["on"] != true) | |
| 76 | - { | |
| 77 | - request["on"] = true; | |
| 78 | - } | |
| 79 | - if (state["sat"] != sat) | |
| 80 | - { | |
| 81 | - if (sat > 254) | |
| 82 | - { | |
| 83 | - sat = 254; | |
| 84 | - } | |
| 85 | - request["sat"] = sat; | |
| 86 | - } | |
| 87 | - | |
| 88 | - if (!request.count("on") && !request.count("sat")) | |
| 89 | - { | |
| 90 | - // Nothing needs to be changed | |
| 91 | - return true; | |
| 92 | - } | |
| 93 | - | |
| 94 | - nlohmann::json reply = light.SendPutRequest(request, "/state", CURRENT_FILE_INFO); | |
| 95 | - | |
| 96 | - // Check whether request was successful | |
| 97 | - return utils::validateReplyForLight(request, reply, light.id); | |
| 42 | + return light.transaction().setColorSaturation(sat).setTransition(transition).commit(); | |
| 98 | 43 | } |
| 99 | 44 | |
| 100 | 45 | bool SimpleColorHueStrategy::setColorHueSaturation(uint16_t hue, uint8_t sat, uint8_t transition, HueLight& light) const |
| 101 | 46 | { |
| 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"]; | |
| 104 | - nlohmann::json request = nlohmann::json::object(); | |
| 105 | - | |
| 106 | - if (transition != 4) | |
| 107 | - { | |
| 108 | - request["transitiontime"] = transition; | |
| 109 | - } | |
| 110 | - if (state["on"] != true) | |
| 111 | - { | |
| 112 | - request["on"] = true; | |
| 113 | - } | |
| 114 | - if (state["hue"] != hue || state["colormode"] != "hs") | |
| 115 | - { | |
| 116 | - hue = hue % 65535; | |
| 117 | - request["hue"] = hue; | |
| 118 | - } | |
| 119 | - if (state["sat"] != sat || state["colormode"] != "hs") | |
| 120 | - { | |
| 121 | - if (sat > 254) | |
| 122 | - { | |
| 123 | - sat = 254; | |
| 124 | - } | |
| 125 | - request["sat"] = sat; | |
| 126 | - } | |
| 127 | - | |
| 128 | - if (!request.count("on") && !request.count("hue") && !request.count("sat")) | |
| 129 | - { | |
| 130 | - // Nothing needs to be changed | |
| 131 | - return true; | |
| 132 | - } | |
| 133 | - | |
| 134 | - nlohmann::json reply = light.SendPutRequest(request, "/state", CURRENT_FILE_INFO); | |
| 135 | - | |
| 136 | - // Check whether request was successful | |
| 137 | - return utils::validateReplyForLight(request, reply, light.id); | |
| 47 | + return light.transaction().setColorHueSaturation(hue, sat).setTransition(transition).commit(); | |
| 138 | 48 | } |
| 139 | 49 | |
| 140 | 50 | bool SimpleColorHueStrategy::setColorXY(float x, float y, uint8_t transition, HueLight& light) const |
| 141 | 51 | { |
| 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"]; | |
| 144 | - nlohmann::json request = nlohmann::json::object(); | |
| 145 | - | |
| 146 | - if (transition != 4) | |
| 147 | - { | |
| 148 | - request["transitiontime"] = transition; | |
| 149 | - } | |
| 150 | - if (state["on"] != true) | |
| 151 | - { | |
| 152 | - request["on"] = true; | |
| 153 | - } | |
| 154 | - if (std::abs(state["xy"][0].get<float>() - x) > 1E-4f || std::abs(state["xy"][1].get<float>() - y) > 1E-4f | |
| 155 | - || state["colormode"] != "xy") | |
| 156 | - { | |
| 157 | - request["xy"][0] = x; | |
| 158 | - request["xy"][1] = y; | |
| 159 | - } | |
| 160 | - | |
| 161 | - if (!request.count("on") && !request.count("xy")) | |
| 162 | - { | |
| 163 | - // Nothing needs to be changed | |
| 164 | - return true; | |
| 165 | - } | |
| 166 | - | |
| 167 | - nlohmann::json reply = light.SendPutRequest(request, "/state", CURRENT_FILE_INFO); | |
| 168 | - | |
| 169 | - // Check whether request was successful | |
| 170 | - return utils::validateReplyForLight(request, reply, light.id); | |
| 52 | + return light.transaction().setColorXY(x, y).setTransition(transition).commit(); | |
| 171 | 53 | } |
| 172 | 54 | |
| 173 | 55 | bool SimpleColorHueStrategy::setColorRGB(uint8_t r, uint8_t g, uint8_t b, uint8_t transition, HueLight& light) const |
| ... | ... | @@ -198,30 +80,7 @@ bool SimpleColorHueStrategy::setColorRGB(uint8_t r, uint8_t g, uint8_t b, uint8_ |
| 198 | 80 | |
| 199 | 81 | bool SimpleColorHueStrategy::setColorLoop(bool on, HueLight& light) const |
| 200 | 82 | { |
| 201 | - // colorloop | |
| 202 | - // Careful, only use state until any light function might refresh the value and invalidate the reference | |
| 203 | - const nlohmann::json& state = light.state.GetValue()["state"]; | |
| 204 | - nlohmann::json request = nlohmann::json::object(); | |
| 205 | - | |
| 206 | - if (state["on"] != true) | |
| 207 | - { | |
| 208 | - request["on"] = true; | |
| 209 | - } | |
| 210 | - std::string effect; | |
| 211 | - if ((effect = on ? "colorloop" : "none") != state["effect"]) | |
| 212 | - { | |
| 213 | - request["effect"] = effect; | |
| 214 | - } | |
| 215 | - if (!request.count("on") && !request.count("effect")) | |
| 216 | - { | |
| 217 | - // Nothing needs to be changed | |
| 218 | - return true; | |
| 219 | - } | |
| 220 | - | |
| 221 | - nlohmann::json reply = light.SendPutRequest(request, "/state", CURRENT_FILE_INFO); | |
| 222 | - | |
| 223 | - // Check whether request was successful | |
| 224 | - return utils::validateReplyForLight(request, reply, light.id); | |
| 83 | + return light.transaction().setColorLoop(true).commit(); | |
| 225 | 84 | } |
| 226 | 85 | |
| 227 | 86 | bool SimpleColorHueStrategy::alertHueSaturation(uint16_t hue, uint8_t sat, HueLight& light) const | ... | ... |
src/SimpleColorTemperatureStrategy.cpp
| ... | ... | @@ -34,40 +34,7 @@ namespace hueplusplus |
| 34 | 34 | { |
| 35 | 35 | bool SimpleColorTemperatureStrategy::setColorTemperature(unsigned int mired, uint8_t transition, HueLight& light) const |
| 36 | 36 | { |
| 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"]; | |
| 39 | - nlohmann::json request = nlohmann::json::object(); | |
| 40 | - if (transition != 4) | |
| 41 | - { | |
| 42 | - request["transitiontime"] = transition; | |
| 43 | - } | |
| 44 | - if (state["on"] != true) | |
| 45 | - { | |
| 46 | - request["on"] = true; | |
| 47 | - } | |
| 48 | - if (state["ct"] != mired) | |
| 49 | - { | |
| 50 | - if (mired > 500) | |
| 51 | - { | |
| 52 | - mired = 500; | |
| 53 | - } | |
| 54 | - if (mired < 153) | |
| 55 | - { | |
| 56 | - mired = 153; | |
| 57 | - } | |
| 58 | - request["ct"] = mired; | |
| 59 | - } | |
| 60 | - | |
| 61 | - if (!request.count("on") && !request.count("ct")) | |
| 62 | - { | |
| 63 | - // Nothing needs to be changed | |
| 64 | - return true; | |
| 65 | - } | |
| 66 | - | |
| 67 | - nlohmann::json reply = light.SendPutRequest(request, "/state", CURRENT_FILE_INFO); | |
| 68 | - | |
| 69 | - // Check whether request was successful | |
| 70 | - return utils::validateReplyForLight(request, reply, light.id); | |
| 37 | + return light.transaction().setColorTemperature(mired).setTransition(transition).commit(); | |
| 71 | 38 | } |
| 72 | 39 | |
| 73 | 40 | bool SimpleColorTemperatureStrategy::alertTemperature(unsigned int mired, HueLight& light) const | ... | ... |
src/StateTransaction.cpp
0 → 100644
| 1 | +/** | |
| 2 | + \file StateTransaction.cpp | |
| 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 | +#include "hueplusplus/StateTransaction.h" | |
| 24 | + | |
| 25 | +#include "hueplusplus/HueExceptionMacro.h" | |
| 26 | +#include "hueplusplus/StateTransaction.h" | |
| 27 | +#include "hueplusplus/Utils.h" | |
| 28 | + | |
| 29 | +namespace hueplusplus | |
| 30 | +{ | |
| 31 | +StateTransaction::StateTransaction( | |
| 32 | + const HueCommandAPI& commands, const std::string& path, const nlohmann::json& currentState) | |
| 33 | + : commands(commands), path(path), state(currentState), request(nlohmann::json::object()) | |
| 34 | +{} | |
| 35 | + | |
| 36 | +bool StateTransaction::commit() && | |
| 37 | +{ | |
| 38 | + // Empty request or request with only transition makes no sense | |
| 39 | + if (!request.empty() && !(request.size() == 1 && request.count("transitiontime"))) | |
| 40 | + { | |
| 41 | + if (!request.count("on")) | |
| 42 | + { | |
| 43 | + if (request.value("bri", 254) == 0 && state.value("on", true)) | |
| 44 | + { | |
| 45 | + // Turn off if brightness is 0 | |
| 46 | + request["on"] = false; | |
| 47 | + } | |
| 48 | + else if (!state.value("on", false) | |
| 49 | + && (request.value("bri", 0) != 0 || request.count("effect") || request.count("hue") | |
| 50 | + || request.count("sat") || request.count("xy") || request.count("ct"))) | |
| 51 | + { | |
| 52 | + // Turn on if it was turned off | |
| 53 | + request["on"] = true; | |
| 54 | + } | |
| 55 | + } | |
| 56 | + | |
| 57 | + nlohmann::json reply = commands.PUTRequest(path, request, CURRENT_FILE_INFO); | |
| 58 | + return utils::validatePUTReply(path, request, reply); | |
| 59 | + } | |
| 60 | + return true; | |
| 61 | +} | |
| 62 | + | |
| 63 | +StateTransaction&& StateTransaction::setOn(bool on) && | |
| 64 | +{ | |
| 65 | + if (!state.count("on") || state["on"] != on) | |
| 66 | + { | |
| 67 | + request["on"] = on; | |
| 68 | + } | |
| 69 | + return std::move(*this); | |
| 70 | +} | |
| 71 | + | |
| 72 | +StateTransaction&& StateTransaction::setBrightness(uint8_t brightness) && | |
| 73 | +{ | |
| 74 | + uint8_t clamped = std::min<uint8_t>(brightness, 254); | |
| 75 | + if (!state.count("bri") || state["bri"].get<unsigned int>() != clamped) | |
| 76 | + { | |
| 77 | + request["bri"] = clamped; | |
| 78 | + } | |
| 79 | + return std::move(*this); | |
| 80 | +} | |
| 81 | + | |
| 82 | +StateTransaction&& StateTransaction::setColorSaturation(uint8_t saturation) && | |
| 83 | +{ | |
| 84 | + uint8_t clamped = std::min<uint8_t>(saturation, 254); | |
| 85 | + if (!state.count("sat") || state["sat"].get<unsigned int>() != clamped || state.value("colormode", "") != "hs") | |
| 86 | + { | |
| 87 | + request["sat"] = clamped; | |
| 88 | + } | |
| 89 | + return std::move(*this); | |
| 90 | +} | |
| 91 | + | |
| 92 | +StateTransaction&& StateTransaction::setColorHue(uint16_t hue) && | |
| 93 | +{ | |
| 94 | + if (!state.count("hue") || state["hue"].get<int>() != hue || state.value("colormode", "") != "hs") | |
| 95 | + { | |
| 96 | + request["hue"] = hue; | |
| 97 | + } | |
| 98 | + return std::move(*this); | |
| 99 | +} | |
| 100 | + | |
| 101 | +StateTransaction&& StateTransaction::setColorHueSaturation(uint16_t hue, uint8_t saturation) && | |
| 102 | +{ | |
| 103 | + if (!state.count("hue") || state["hue"].get<int>() != hue) | |
| 104 | + { | |
| 105 | + request["hue"] = hue; | |
| 106 | + } | |
| 107 | + uint8_t clamped = std::min<uint8_t>(saturation, 254); | |
| 108 | + if (!state.count("sat") || state["sat"].get<unsigned int>() != clamped) | |
| 109 | + { | |
| 110 | + request["sat"] = clamped; | |
| 111 | + } | |
| 112 | + return std::move(*this); | |
| 113 | +} | |
| 114 | + | |
| 115 | +StateTransaction&& StateTransaction::setColorXY(float x, float y) && | |
| 116 | +{ | |
| 117 | + if (!state.count("xy") || !state.count("colormode") || !state["xy"].is_array() | |
| 118 | + || !utils::floatEquals(state["xy"][0].get<float>(), x) || !utils::floatEquals(state["xy"][1].get<float>(), y) | |
| 119 | + || state["colormode"] != "xy") | |
| 120 | + { | |
| 121 | + request["xy"] = {x, y}; | |
| 122 | + } | |
| 123 | + return std::move(*this); | |
| 124 | +} | |
| 125 | + | |
| 126 | +StateTransaction&& StateTransaction::setColorTemperature(unsigned int mired) && | |
| 127 | +{ | |
| 128 | + unsigned int clamped = std::max(153u, std::min(mired, 500u)); | |
| 129 | + if (state.value("ct", 0u) != clamped || state.value("colormode", "") != "ct") | |
| 130 | + { | |
| 131 | + request["ct"] = clamped; | |
| 132 | + } | |
| 133 | + return std::move(*this); | |
| 134 | +} | |
| 135 | + | |
| 136 | +StateTransaction&& StateTransaction::setColorLoop(bool on) && | |
| 137 | +{ | |
| 138 | + std::string effect = on ? "colorloop" : "none"; | |
| 139 | + if (state.value("effect", "") != effect) | |
| 140 | + { | |
| 141 | + request["effect"] = effect; | |
| 142 | + } | |
| 143 | + return std::move(*this); | |
| 144 | +} | |
| 145 | + | |
| 146 | +StateTransaction&& StateTransaction::incrementBrightness(int increment) && | |
| 147 | +{ | |
| 148 | + request["bri_inc"] = std::max(-254, std::min(increment, 254)); | |
| 149 | + return std::move(*this); | |
| 150 | +} | |
| 151 | + | |
| 152 | +StateTransaction&& StateTransaction::incrementSaturation(int increment) && | |
| 153 | +{ | |
| 154 | + request["sat_inc"] = std::max(-254, std::min(increment, 254)); | |
| 155 | + return std::move(*this); | |
| 156 | +} | |
| 157 | + | |
| 158 | +StateTransaction&& StateTransaction::incrementHue(int increment) && | |
| 159 | +{ | |
| 160 | + request["hue_inc"] = std::max(-65534, std::min(increment, 65534)); | |
| 161 | + return std::move(*this); | |
| 162 | +} | |
| 163 | + | |
| 164 | +StateTransaction&& StateTransaction::incrementColorTemperature(int increment) && | |
| 165 | +{ | |
| 166 | + request["ct_inc"] = std::max(-65534, std::min(increment, 65534)); | |
| 167 | + return std::move(*this); | |
| 168 | +} | |
| 169 | + | |
| 170 | +StateTransaction&& StateTransaction::incrementColorXY(float xInc, float yInc) && | |
| 171 | +{ | |
| 172 | + request["xy_inc"] = {std::min(-0.5f, std::max(xInc, 0.5f)), std::min(-0.5f, std::max(yInc, 0.5f))}; | |
| 173 | + return std::move(*this); | |
| 174 | +} | |
| 175 | + | |
| 176 | +StateTransaction&& StateTransaction::setTransition(uint16_t transition) && | |
| 177 | +{ | |
| 178 | + if (transition != 4) | |
| 179 | + { | |
| 180 | + request["transitiontime"] = transition; | |
| 181 | + } | |
| 182 | + return std::move(*this); | |
| 183 | +} | |
| 184 | +StateTransaction&& StateTransaction::alert() && | |
| 185 | +{ | |
| 186 | + request["alert"] = "select"; | |
| 187 | + return std::move(*this); | |
| 188 | +} | |
| 189 | +StateTransaction&& StateTransaction::longAlert() && | |
| 190 | +{ | |
| 191 | + request["alert"] = "lselect"; | |
| 192 | + return std::move(*this); | |
| 193 | +} | |
| 194 | +StateTransaction&& StateTransaction::stopAlert() && | |
| 195 | +{ | |
| 196 | + request["alert"] = "none"; | |
| 197 | + return std::move(*this); | |
| 198 | +} | |
| 199 | +} // namespace hueplusplus | |
| 0 | 200 | \ No newline at end of file | ... | ... |
src/Utils.cpp
| ... | ... | @@ -28,10 +28,14 @@ namespace hueplusplus |
| 28 | 28 | { |
| 29 | 29 | namespace utils |
| 30 | 30 | { |
| 31 | -bool validateReplyForLight(const nlohmann::json& request, const nlohmann::json& reply, int lightId) | |
| 31 | +bool validatePUTReply(const std::string& path, const nlohmann::json& request, const nlohmann::json& reply) | |
| 32 | 32 | { |
| 33 | + std::string pathAppend = path; | |
| 34 | + if (pathAppend.back() != '/') | |
| 35 | + { | |
| 36 | + pathAppend.push_back('/'); | |
| 37 | + } | |
| 33 | 38 | bool success = false; |
| 34 | - std::string path = "/lights/" + std::to_string(lightId) + "/state/"; | |
| 35 | 39 | for (auto it = reply.begin(); it != reply.end(); ++it) |
| 36 | 40 | { |
| 37 | 41 | success = it.value().count("success"); |
| ... | ... | @@ -42,9 +46,9 @@ bool validateReplyForLight(const nlohmann::json& request, const nlohmann::json& |
| 42 | 46 | for (auto successIt = successObject.begin(); successIt != successObject.end(); ++successIt) |
| 43 | 47 | { |
| 44 | 48 | const std::string successPath = successIt.key(); |
| 45 | - if (successPath.find(path) == 0) | |
| 49 | + if (successPath.find(pathAppend) == 0) | |
| 46 | 50 | { |
| 47 | - const std::string valueKey = successPath.substr(path.size()); | |
| 51 | + const std::string valueKey = successPath.substr(pathAppend.size()); | |
| 48 | 52 | auto requestIt = request.find(valueKey); |
| 49 | 53 | success = requestIt != request.end(); |
| 50 | 54 | if (success) |
| ... | ... | @@ -58,7 +62,8 @@ bool validateReplyForLight(const nlohmann::json& request, const nlohmann::json& |
| 58 | 62 | } |
| 59 | 63 | else |
| 60 | 64 | { |
| 61 | - success = requestIt.value() == successIt.value(); | |
| 65 | + success = requestIt.value() == successIt.value() | |
| 66 | + || (successIt.value().is_string() && successIt.value() == "Updated."); | |
| 62 | 67 | } |
| 63 | 68 | if (!success) |
| 64 | 69 | { |
| ... | ... | @@ -80,5 +85,10 @@ bool validateReplyForLight(const nlohmann::json& request, const nlohmann::json& |
| 80 | 85 | } |
| 81 | 86 | return success; |
| 82 | 87 | } |
| 88 | + | |
| 89 | +bool validateReplyForLight(const nlohmann::json& request, const nlohmann::json& reply, int lightId) | |
| 90 | +{ | |
| 91 | + return validatePUTReply("/lights/" + std::to_string(lightId) + "/state/", request, reply); | |
| 92 | +} | |
| 83 | 93 | } // namespace utils |
| 84 | 94 | } // namespace hueplusplus | ... | ... |
test/CMakeLists.txt
| ... | ... | @@ -70,6 +70,9 @@ add_custom_target("unittest" |
| 70 | 70 | find_program( GCOV_PATH gcov ) |
| 71 | 71 | find_program( LCOV_PATH lcov ) |
| 72 | 72 | |
| 73 | +mark_as_advanced(GCOV_PATH) | |
| 74 | +mark_as_advanced(LCOV_PATH) | |
| 75 | + | |
| 73 | 76 | if(LCOV_PATH AND GCOV_PATH) |
| 74 | 77 | # GCov |
| 75 | 78 | include(CodeCoverage.cmake) | ... | ... |
test/test_HueLight.cpp
| ... | ... | @@ -69,7 +69,7 @@ protected: |
| 69 | 69 | hue_bridge_state["lights"]["2"] = nlohmann::json::object(); |
| 70 | 70 | hue_bridge_state["lights"]["2"]["state"] = nlohmann::json::object(); |
| 71 | 71 | hue_bridge_state["lights"]["2"]["state"]["on"] = false; |
| 72 | - hue_bridge_state["lights"]["2"]["state"]["bri"] = 254; | |
| 72 | + hue_bridge_state["lights"]["2"]["state"]["bri"] = 0; | |
| 73 | 73 | hue_bridge_state["lights"]["2"]["state"]["ct"] = 366; |
| 74 | 74 | hue_bridge_state["lights"]["2"]["state"]["hue"] = 123456; |
| 75 | 75 | hue_bridge_state["lights"]["2"]["state"]["sat"] = 123; |
| ... | ... | @@ -514,7 +514,7 @@ TEST_F(HueLightTest, setBrightness) |
| 514 | 514 | prep_ret[1]["success"]["/lights/3/state/on"] = true; |
| 515 | 515 | prep_ret[2] = nlohmann::json::object(); |
| 516 | 516 | prep_ret[2]["success"] = nlohmann::json::object(); |
| 517 | - prep_ret[2]["success"]["/lights/3/state/bri"] = 254; | |
| 517 | + prep_ret[2]["success"]["/lights/3/state/bri"] = 253; | |
| 518 | 518 | EXPECT_CALL(*handler, PUTJson("/api/" + getBridgeUsername() + "/lights/3/state", _, getBridgeIp(), 80)) |
| 519 | 519 | .Times(1) |
| 520 | 520 | .WillOnce(Return(prep_ret)); |
| ... | ... | @@ -525,7 +525,7 @@ TEST_F(HueLightTest, setBrightness) |
| 525 | 525 | |
| 526 | 526 | EXPECT_EQ(false, test_light_1.setBrightness(200)); |
| 527 | 527 | EXPECT_EQ(true, test_light_2.setBrightness(0, 2)); |
| 528 | - EXPECT_EQ(true, test_light_3.setBrightness(255, 0)); | |
| 528 | + EXPECT_EQ(true, test_light_3.setBrightness(253, 0)); | |
| 529 | 529 | } |
| 530 | 530 | |
| 531 | 531 | TEST_F(HueLightTest, getBrightness) |
| ... | ... | @@ -538,10 +538,10 @@ TEST_F(HueLightTest, getBrightness) |
| 538 | 538 | HueLight test_light_3 = test_bridge.getLight(3); |
| 539 | 539 | |
| 540 | 540 | EXPECT_EQ(254, ctest_light_1.getBrightness()); |
| 541 | - EXPECT_EQ(254, ctest_light_2.getBrightness()); | |
| 541 | + EXPECT_EQ(0, ctest_light_2.getBrightness()); | |
| 542 | 542 | EXPECT_EQ(254, ctest_light_3.getBrightness()); |
| 543 | 543 | EXPECT_EQ(254, test_light_1.getBrightness()); |
| 544 | - EXPECT_EQ(254, test_light_2.getBrightness()); | |
| 544 | + EXPECT_EQ(0, test_light_2.getBrightness()); | |
| 545 | 545 | EXPECT_EQ(254, test_light_3.getBrightness()); |
| 546 | 546 | } |
| 547 | 547 | ... | ... |
test/test_SimpleBrightnessStrategy.cpp
| ... | ... | @@ -46,33 +46,30 @@ TEST(SimpleBrightnessStrategy, setBrightness) |
| 46 | 46 | .WillRepeatedly(Return(nlohmann::json::object())); |
| 47 | 47 | MockHueLight test_light(handler); |
| 48 | 48 | |
| 49 | - EXPECT_CALL(test_light, Off(_)).Times(AtLeast(1)).WillRepeatedly(Return(true)); | |
| 50 | - nlohmann::json prep_ret; | |
| 51 | - prep_ret = nlohmann::json::array(); | |
| 52 | - prep_ret[0] = nlohmann::json::object(); | |
| 53 | - prep_ret[0]["success"] = nlohmann::json::object(); | |
| 54 | - prep_ret[0]["success"]["/lights/1/state/transitiontime"] = 6; | |
| 55 | - prep_ret[1] = nlohmann::json::object(); | |
| 56 | - prep_ret[1]["success"] = nlohmann::json::object(); | |
| 57 | - prep_ret[1]["success"]["/lights/1/state/on"] = true; | |
| 58 | - prep_ret[2] = nlohmann::json::object(); | |
| 59 | - prep_ret[2]["success"] = nlohmann::json::object(); | |
| 60 | - prep_ret[2]["success"]["/lights/1/state/bri"] = 50; | |
| 61 | - EXPECT_CALL(test_light, SendPutRequest(_, "/state", _)).Times(1).WillOnce(Return(prep_ret)); | |
| 49 | + const std::string statePath = "/api/" + getBridgeUsername() + "/lights/1/state"; | |
| 62 | 50 | |
| 51 | + nlohmann::json prep_ret | |
| 52 | + = {{{"success", {{"/lights/1/state/on", false}}}}, {{"success", {{"/lights/1/state/bri", 0}}}}}; | |
| 53 | + EXPECT_CALL(*handler, PUTJson(statePath, _, getBridgeIp(), getBridgePort())).Times(1).WillOnce(Return(prep_ret)); | |
| 63 | 54 | test_light.getState()["state"]["on"] = true; |
| 64 | 55 | EXPECT_EQ(true, SimpleBrightnessStrategy().setBrightness(0, 4, test_light)); |
| 56 | + // Only set brightness, already off | |
| 65 | 57 | test_light.getState()["state"]["on"] = false; |
| 58 | + prep_ret = {{{"success", {{"/lights/1/state/bri", 0}}}}}; | |
| 59 | + EXPECT_CALL(*handler, PUTJson(statePath, _, getBridgeIp(), getBridgePort())).Times(1).WillOnce(Return(prep_ret)); | |
| 66 | 60 | EXPECT_EQ(true, SimpleBrightnessStrategy().setBrightness(0, 4, test_light)); |
| 67 | 61 | |
| 62 | + prep_ret = {{{"success", {{"/lights/1/state/on", true}}}}, {{"success", {{"/lights/1/state/bri", 50}}}}}; | |
| 63 | + EXPECT_CALL(*handler, PUTJson(statePath, _, getBridgeIp(), getBridgePort())).Times(1).WillOnce(Return(prep_ret)); | |
| 68 | 64 | test_light.getState()["state"]["bri"] = 0; |
| 69 | 65 | EXPECT_EQ(true, SimpleBrightnessStrategy().setBrightness(50, 6, test_light)); |
| 70 | 66 | test_light.getState()["state"]["on"] = true; |
| 71 | 67 | test_light.getState()["state"]["bri"] = 50; |
| 68 | + // No request because state matches | |
| 72 | 69 | EXPECT_EQ(true, SimpleBrightnessStrategy().setBrightness(50, 6, test_light)); |
| 73 | 70 | |
| 74 | - prep_ret[2]["success"]["/lights/1/state/bri"] = 254; | |
| 75 | - EXPECT_CALL(test_light, SendPutRequest(_, "/state", _)).Times(1).WillOnce(Return(prep_ret)); | |
| 71 | + prep_ret[1]["success"]["/lights/1/state/bri"] = 254; | |
| 72 | + EXPECT_CALL(*handler, PUTJson(statePath, _, getBridgeIp(), getBridgePort())).Times(1).WillOnce(Return(prep_ret)); | |
| 76 | 73 | test_light.getState()["state"]["on"] = false; |
| 77 | 74 | EXPECT_EQ(true, SimpleBrightnessStrategy().setBrightness(255, 6, test_light)); |
| 78 | 75 | } | ... | ... |
test/test_SimpleColorHueStrategy.cpp
| ... | ... | @@ -45,6 +45,8 @@ TEST(SimpleColorHueStrategy, setColorHue) |
| 45 | 45 | .WillRepeatedly(Return(nlohmann::json::object())); |
| 46 | 46 | MockHueLight test_light(handler); |
| 47 | 47 | |
| 48 | + const std::string statePath = "/api/" + getBridgeUsername() + "/lights/1/state"; | |
| 49 | + | |
| 48 | 50 | nlohmann::json prep_ret; |
| 49 | 51 | prep_ret = nlohmann::json::array(); |
| 50 | 52 | prep_ret[0] = nlohmann::json::object(); |
| ... | ... | @@ -56,7 +58,7 @@ TEST(SimpleColorHueStrategy, setColorHue) |
| 56 | 58 | prep_ret[2] = nlohmann::json::object(); |
| 57 | 59 | prep_ret[2]["success"] = nlohmann::json::object(); |
| 58 | 60 | prep_ret[2]["success"]["/lights/1/state/hue"] = 30500; |
| 59 | - EXPECT_CALL(test_light, SendPutRequest(_, "/state", _)).Times(1).WillOnce(Return(prep_ret)); | |
| 61 | + EXPECT_CALL(*handler, PUTJson(statePath, _, getBridgeIp(), getBridgePort())).Times(1).WillOnce(Return(prep_ret)); | |
| 60 | 62 | |
| 61 | 63 | test_light.getState()["state"]["on"] = true; |
| 62 | 64 | test_light.getState()["state"]["hue"] = 200; |
| ... | ... | @@ -77,6 +79,8 @@ TEST(SimpleColorHueStrategy, setColorSaturation) |
| 77 | 79 | .WillRepeatedly(Return(nlohmann::json::object())); |
| 78 | 80 | MockHueLight test_light(handler); |
| 79 | 81 | |
| 82 | + const std::string statePath = "/api/" + getBridgeUsername() + "/lights/1/state"; | |
| 83 | + | |
| 80 | 84 | nlohmann::json prep_ret; |
| 81 | 85 | prep_ret = nlohmann::json::array(); |
| 82 | 86 | prep_ret[0] = nlohmann::json::object(); |
| ... | ... | @@ -88,7 +92,7 @@ TEST(SimpleColorHueStrategy, setColorSaturation) |
| 88 | 92 | prep_ret[2] = nlohmann::json::object(); |
| 89 | 93 | prep_ret[2]["success"] = nlohmann::json::object(); |
| 90 | 94 | prep_ret[2]["success"]["/lights/1/state/sat"] = 254; |
| 91 | - EXPECT_CALL(test_light, SendPutRequest(_, "/state", _)).Times(1).WillOnce(Return(prep_ret)); | |
| 95 | + EXPECT_CALL(*handler, PUTJson(statePath, _, getBridgeIp(), getBridgePort())).Times(1).WillOnce(Return(prep_ret)); | |
| 92 | 96 | |
| 93 | 97 | test_light.getState()["state"]["on"] = true; |
| 94 | 98 | test_light.getState()["state"]["sat"] = 100; |
| ... | ... | @@ -109,6 +113,8 @@ TEST(SimpleColorHueStrategy, setColorHueSaturation) |
| 109 | 113 | .WillRepeatedly(Return(nlohmann::json::object())); |
| 110 | 114 | MockHueLight test_light(handler); |
| 111 | 115 | |
| 116 | + const std::string statePath = "/api/" + getBridgeUsername() + "/lights/1/state"; | |
| 117 | + | |
| 112 | 118 | nlohmann::json prep_ret; |
| 113 | 119 | prep_ret = nlohmann::json::array(); |
| 114 | 120 | prep_ret[0] = nlohmann::json::object(); |
| ... | ... | @@ -123,7 +129,7 @@ TEST(SimpleColorHueStrategy, setColorHueSaturation) |
| 123 | 129 | prep_ret[3] = nlohmann::json::object(); |
| 124 | 130 | prep_ret[3]["success"] = nlohmann::json::object(); |
| 125 | 131 | prep_ret[3]["success"]["/lights/1/state/sat"] = 254; |
| 126 | - EXPECT_CALL(test_light, SendPutRequest(_, "/state", _)).Times(1).WillOnce(Return(prep_ret)); | |
| 132 | + EXPECT_CALL(*handler, PUTJson(statePath, _, getBridgeIp(), getBridgePort())).Times(1).WillOnce(Return(prep_ret)); | |
| 127 | 133 | |
| 128 | 134 | test_light.getState()["state"]["on"] = true; |
| 129 | 135 | test_light.getState()["state"]["sat"] = 100; |
| ... | ... | @@ -145,6 +151,8 @@ TEST(SimpleColorHueStrategy, setColorXY) |
| 145 | 151 | .WillRepeatedly(Return(nlohmann::json::object())); |
| 146 | 152 | MockHueLight test_light(handler); |
| 147 | 153 | |
| 154 | + const std::string statePath = "/api/" + getBridgeUsername() + "/lights/1/state"; | |
| 155 | + | |
| 148 | 156 | nlohmann::json prep_ret; |
| 149 | 157 | prep_ret = nlohmann::json::array(); |
| 150 | 158 | prep_ret[0] = nlohmann::json::object(); |
| ... | ... | @@ -157,7 +165,7 @@ TEST(SimpleColorHueStrategy, setColorXY) |
| 157 | 165 | prep_ret[2]["success"] = nlohmann::json::object(); |
| 158 | 166 | prep_ret[2]["success"]["/lights/1/state/xy"][0] = 0.2355; |
| 159 | 167 | prep_ret[2]["success"]["/lights/1/state/xy"][1] = 0.1234; |
| 160 | - EXPECT_CALL(test_light, SendPutRequest(_, "/state", _)).Times(1).WillOnce(Return(prep_ret)); | |
| 168 | + EXPECT_CALL(*handler, PUTJson(statePath, _, getBridgeIp(), getBridgePort())).Times(1).WillOnce(Return(prep_ret)); | |
| 161 | 169 | |
| 162 | 170 | test_light.getState()["state"]["on"] = true; |
| 163 | 171 | test_light.getState()["state"]["xy"][0] = 0.1f; |
| ... | ... | @@ -198,6 +206,8 @@ TEST(SimpleColorHueStrategy, setColorLoop) |
| 198 | 206 | .WillRepeatedly(Return(nlohmann::json::object())); |
| 199 | 207 | MockHueLight test_light(handler); |
| 200 | 208 | |
| 209 | + const std::string statePath = "/api/" + getBridgeUsername() + "/lights/1/state"; | |
| 210 | + | |
| 201 | 211 | nlohmann::json prep_ret; |
| 202 | 212 | prep_ret = nlohmann::json::array(); |
| 203 | 213 | prep_ret[0] = nlohmann::json::object(); |
| ... | ... | @@ -206,7 +216,7 @@ TEST(SimpleColorHueStrategy, setColorLoop) |
| 206 | 216 | prep_ret[1] = nlohmann::json::object(); |
| 207 | 217 | prep_ret[1]["success"] = nlohmann::json::object(); |
| 208 | 218 | prep_ret[1]["success"]["/lights/1/state/effect"] = "colorloop"; |
| 209 | - EXPECT_CALL(test_light, SendPutRequest(_, "/state", _)).Times(1).WillOnce(Return(prep_ret)); | |
| 219 | + EXPECT_CALL(*handler, PUTJson(statePath, _, getBridgeIp(), getBridgePort())).Times(1).WillOnce(Return(prep_ret)); | |
| 210 | 220 | |
| 211 | 221 | test_light.getState()["state"]["on"] = true; |
| 212 | 222 | test_light.getState()["state"]["effect"] = "colorloop"; | ... | ... |
test/test_SimpleColorTemperatureStrategy.cpp
| ... | ... | @@ -46,6 +46,8 @@ TEST(SimpleColorTemperatureStrategy, setColorTemperature) |
| 46 | 46 | .WillRepeatedly(Return(nlohmann::json::object())); |
| 47 | 47 | MockHueLight test_light(handler); |
| 48 | 48 | |
| 49 | + const std::string statePath = "/api/" + getBridgeUsername() + "/lights/1/state"; | |
| 50 | + | |
| 49 | 51 | nlohmann::json prep_ret; |
| 50 | 52 | prep_ret = nlohmann::json::array(); |
| 51 | 53 | prep_ret[0] = nlohmann::json::object(); |
| ... | ... | @@ -57,21 +59,22 @@ TEST(SimpleColorTemperatureStrategy, setColorTemperature) |
| 57 | 59 | prep_ret[2] = nlohmann::json::object(); |
| 58 | 60 | prep_ret[2]["success"] = nlohmann::json::object(); |
| 59 | 61 | prep_ret[2]["success"]["/lights/1/state/ct"] = 155; |
| 60 | - EXPECT_CALL(test_light, SendPutRequest(_, "/state", _)).Times(1).WillOnce(Return(prep_ret)); | |
| 62 | + EXPECT_CALL(*handler, PUTJson(statePath, _, getBridgeIp(), getBridgePort())).Times(1).WillOnce(Return(prep_ret)); | |
| 61 | 63 | |
| 62 | 64 | test_light.getState()["state"]["on"] = true; |
| 63 | 65 | test_light.getState()["state"]["ct"] = 200; |
| 66 | + test_light.getState()["state"]["colormode"] = "ct"; | |
| 64 | 67 | EXPECT_EQ(true, SimpleColorTemperatureStrategy().setColorTemperature(200, 4, test_light)); |
| 65 | 68 | |
| 66 | 69 | test_light.getState()["state"]["on"] = false; |
| 67 | 70 | EXPECT_EQ(true, SimpleColorTemperatureStrategy().setColorTemperature(155, 6, test_light)); |
| 68 | 71 | |
| 69 | - prep_ret[2]["success"]["/lights/1/state/ct"] = 153; | |
| 70 | - EXPECT_CALL(test_light, SendPutRequest(_, "/state", _)).Times(1).WillOnce(Return(prep_ret)); | |
| 72 | + prep_ret = {{{"success", {{"/lights/1/state/transitiontime", 6}}}}, {{"success", {{"/lights/1/state/ct", 153}}}}}; | |
| 73 | + EXPECT_CALL(*handler, PUTJson(statePath, _, getBridgeIp(), getBridgePort())).Times(1).WillOnce(Return(prep_ret)); | |
| 71 | 74 | EXPECT_EQ(true, SimpleColorTemperatureStrategy().setColorTemperature(0, 6, test_light)); |
| 72 | 75 | |
| 73 | - prep_ret[2]["success"]["/lights/1/state/ct"] = 500; | |
| 74 | - EXPECT_CALL(test_light, SendPutRequest(_, "/state", _)).Times(1).WillOnce(Return(prep_ret)); | |
| 76 | + prep_ret[1]["success"]["/lights/1/state/ct"] = 500; | |
| 77 | + EXPECT_CALL(*handler, PUTJson(statePath, _, getBridgeIp(), getBridgePort())).Times(1).WillOnce(Return(prep_ret)); | |
| 75 | 78 | EXPECT_EQ(true, SimpleColorTemperatureStrategy().setColorTemperature(600, 6, test_light)); |
| 76 | 79 | } |
| 77 | 80 | ... | ... |