diff --git a/include/hueplusplus/Group.h b/include/hueplusplus/Group.h
index 0cb947b..8e7426e 100644
--- a/include/hueplusplus/Group.h
+++ b/include/hueplusplus/Group.h
@@ -28,44 +28,12 @@
#include "APICache.h"
#include "HueCommandAPI.h"
+#include "StateTransaction.h"
#include "json/json.hpp"
namespace hueplusplus
{
-class StateTransaction
-{
-public:
- StateTransaction(const HueCommandAPI& commands, const std::string& path, const nlohmann::json& currentState);
-
- StateTransaction(const StateTransaction&) = delete;
- StateTransaction(StateTransaction&&) = default;
-
- bool commit() &&;
-
- StateTransaction&& setOn(bool on) &&;
- StateTransaction&& setBrightness(uint8_t brightness) &&;
- StateTransaction&& setColorHue(uint16_t hue) &&;
- StateTransaction&& setColorSaturation(uint8_t saturation) &&;
- StateTransaction&& setColorHueSaturation(uint16_t hue, uint8_t saturation) &&;
- StateTransaction&& setColorXY(float x, float y) &&;
- StateTransaction&& setColorTemperature(unsigned int mired) &&;
- StateTransaction&& setColorLoop(bool on) &&;
- StateTransaction&& incrementBrightness(int increment) &&;
- StateTransaction&& incrementSaturation(int increment) &&;
- StateTransaction&& incrementHue(int increment) &&;
- StateTransaction&& incrementColorTemperature(int increment) &&;
- StateTransaction&& incrementColorXY(float xInc, float yInc) &&;
- StateTransaction&& setScene(const std::string& scene) &&;
- StateTransaction&& setTransition(uint16_t transition) &&;
-
-private:
- const HueCommandAPI& commands;
- std::string path;
- nlohmann::json state;
- nlohmann::json request;
-};
-
class Group
{
public:
diff --git a/include/hueplusplus/HueLight.h b/include/hueplusplus/HueLight.h
index 6531241..9f6138f 100644
--- a/include/hueplusplus/HueLight.h
+++ b/include/hueplusplus/HueLight.h
@@ -30,6 +30,7 @@
#include "ColorHueStrategy.h"
#include "ColorTemperatureStrategy.h"
#include "HueCommandAPI.h"
+#include "StateTransaction.h"
#include "json/json.hpp"
@@ -78,7 +79,7 @@ LLC020 // Hue Go, Color Gamut C, ECL
};*/
//! enum that specifies the color type of all HueLights
-enum ColorType
+enum class ColorType
{
UNDEFINED, //!< ColorType for this light is unknown or undefined
NONE, //!< light has no specific ColorType
@@ -676,6 +677,8 @@ public:
return false;
};
+ virtual StateTransaction transaction();
+
protected:
//! \brief Protected ctor that is used by \ref Hue class.
//!
diff --git a/include/hueplusplus/StateTransaction.h b/include/hueplusplus/StateTransaction.h
new file mode 100644
index 0000000..178f690
--- /dev/null
+++ b/include/hueplusplus/StateTransaction.h
@@ -0,0 +1,71 @@
+/**
+ \file StateTransaction.h
+ Copyright Notice\n
+ Copyright (C) 2020 Jan Rogall - developer\n
+ Copyright (C) 2020 Moritz Wirger - developer\n
+
+ This file is part of hueplusplus.
+
+ hueplusplus is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ hueplusplus is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with hueplusplus. If not, see .
+**/
+
+#ifndef INCLUDE_HUEPLUSPLUS_STATE_TRANSACTION_H
+#define INCLUDE_HUEPLUSPLUS_STATE_TRANSACTION_H
+
+#include
+
+#include "HueCommandAPI.h"
+
+#include "json/json.hpp"
+
+namespace hueplusplus
+{
+class StateTransaction
+{
+public:
+ StateTransaction(const HueCommandAPI& commands, const std::string& path, const nlohmann::json& currentState);
+
+ StateTransaction(const StateTransaction&) = delete;
+ StateTransaction(StateTransaction&&) = default;
+
+ bool commit() &&;
+
+ StateTransaction&& setOn(bool on) &&;
+ StateTransaction&& setBrightness(uint8_t brightness) &&;
+ StateTransaction&& setColorHue(uint16_t hue) &&;
+ StateTransaction&& setColorSaturation(uint8_t saturation) &&;
+ StateTransaction&& setColorHueSaturation(uint16_t hue, uint8_t saturation) &&;
+ StateTransaction&& setColorXY(float x, float y) &&;
+ StateTransaction&& setColorTemperature(unsigned int mired) &&;
+ StateTransaction&& setColorLoop(bool on) &&;
+ StateTransaction&& incrementBrightness(int increment) &&;
+ StateTransaction&& incrementSaturation(int increment) &&;
+ StateTransaction&& incrementHue(int increment) &&;
+ StateTransaction&& incrementColorTemperature(int increment) &&;
+ StateTransaction&& incrementColorXY(float xInc, float yInc) &&;
+ StateTransaction&& setTransition(uint16_t transition) &&;
+ StateTransaction&& alert() &&;
+ StateTransaction&& longAlert() &&;
+ StateTransaction&& stopAlert() &&;
+
+protected:
+ const HueCommandAPI& commands;
+ std::string path;
+ nlohmann::json state;
+ nlohmann::json request;
+};
+
+} // namespace hueplusplus
+
+#endif
\ No newline at end of file
diff --git a/include/hueplusplus/Utils.h b/include/hueplusplus/Utils.h
index d34e297..4c547d1 100644
--- a/include/hueplusplus/Utils.h
+++ b/include/hueplusplus/Utils.h
@@ -66,12 +66,22 @@ nlohmann::json safeGetMemberHelper(const nlohmann::json& json, std::size_t index
//! \brief Function for validating that a request was executed correctly
//!
+//! \param path The path the PUT request was made to
//! \param request The request that was sent initially
//! \param reply The reply that was received
-//! \param lightId The identifier of the light
//! \return True if request was executed correctly
+bool validatePUTReply(const std::string& path, const nlohmann::json& request, const nlohmann::json& reply);
+
bool validateReplyForLight(const nlohmann::json& request, const nlohmann::json& reply, int lightId);
+//! \brief Checks equality to 4 decimal places
+//!
+//! Floats in Hue json responses are rounded to 4 decimal places.
+inline bool floatEquals(float lhs, float rhs)
+{
+ return std::abs(lhs - rhs) <= 1E-4f;
+}
+
//! \brief Returns the object/array member or null if it does not exist
//!
//! \param json The base json value
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index c7d1f74..aa09a70 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -14,7 +14,7 @@ set(hueplusplus_SOURCES
SimpleColorTemperatureStrategy.cpp
UPnP.cpp
Utils.cpp
-)
+ StateTransaction.cpp)
# on windows we want to compile the WinHttpHandler
if(WIN32)
diff --git a/src/ExtendedColorHueStrategy.cpp b/src/ExtendedColorHueStrategy.cpp
index 169bf63..2cce861 100644
--- a/src/ExtendedColorHueStrategy.cpp
+++ b/src/ExtendedColorHueStrategy.cpp
@@ -200,8 +200,8 @@ bool ExtendedColorHueStrategy::alertRGB(uint8_t r, uint8_t g, uint8_t b, HueLigh
{
// Careful, only use state until any light function might refresh the value and invalidate the reference
const nlohmann::json& state = light.state.GetValue()["state"];
- std::string cType = state["colormode"];
- bool on = state["on"];
+ std::string cType = state["colormode"].get();
+ bool on = state["on"].get();
if (cType == "hs")
{
uint16_t oldHue = state["hue"].get();
diff --git a/src/Group.cpp b/src/Group.cpp
index 293560c..af72776 100644
--- a/src/Group.cpp
+++ b/src/Group.cpp
@@ -2,159 +2,35 @@
#include "hueplusplus/HueExceptionMacro.h"
-hueplusplus::StateTransaction::StateTransaction(
- const HueCommandAPI& commands, const std::string& path, const nlohmann::json& currentState)
- : commands(commands), path(path), state(state), request(nlohmann::json::object())
-{}
-
-bool hueplusplus::StateTransaction::commit() &&
-{
- // Empty request or request with only transition makes no sense
- if (!request.empty() || (request.size() == 1 && request.count("transition")))
- {
- if (!request.count("on"))
- {
- if (request.value("bri", 254) == 0)
- {
- // Turn off if brightness is 0
- request["on"] = false;
- }
- else if (request.value("bri", 0) != 0 || request.count("colorloop") || request.count("hue")
- || request.count("sat") || request.count("xy"))
- {
- // Turn on if it was turned off
- request["on"] = true;
- }
- }
-
- commands.PUTRequest(path, request, CURRENT_FILE_INFO);
- return true;
- }
- return false;
-}
-
-hueplusplus::StateTransaction&& hueplusplus::StateTransaction::setOn(bool on) &&
-{
- request["on"] = on;
- return std::move(*this);
-}
-
-hueplusplus::StateTransaction&& hueplusplus::StateTransaction::setBrightness(uint8_t brightness) &&
-{
- request["bri"] = std::min(brightness, 254);
- return std::move(*this);
-}
-
-hueplusplus::StateTransaction&& hueplusplus::StateTransaction::setColorSaturation(uint8_t saturation) &&
-{
- request["sat"] = std::min(saturation, 254);
- return std::move(*this);
-}
-
-hueplusplus::StateTransaction&& hueplusplus::StateTransaction::setColorHue(uint16_t hue) &&
-{
- request["hue"] = hue;
- return std::move(*this);
-}
-
-hueplusplus::StateTransaction&& hueplusplus::StateTransaction::setColorHueSaturation(
- uint16_t hue, uint8_t saturation) &&
-{
- request["hue"] = hue;
- request["sat"] = std::min(saturation, 254);
- return std::move(*this);
-}
-
-hueplusplus::StateTransaction&& hueplusplus::StateTransaction::setColorXY(float x, float y) &&
-{
- request["xy"] = {x, y};
- return std::move(*this);
-}
-
-hueplusplus::StateTransaction&& hueplusplus::StateTransaction::setColorTemperature(unsigned int mired) &&
-{
- request["ct"] = mired;
- return std::move(*this);
-}
-
-hueplusplus::StateTransaction&& hueplusplus::StateTransaction::setColorLoop(bool on) &&
+namespace hueplusplus
{
- request["effect"] = on ? "colorloop" : "none";
- return std::move(*this);
-}
-
-hueplusplus::StateTransaction&& hueplusplus::StateTransaction::incrementBrightness(int increment) &&
-{
- request["bri_inc"] = std::max(-254, std::min(increment, 254));
- return std::move(*this);
-}
-
-hueplusplus::StateTransaction&& hueplusplus::StateTransaction::incrementSaturation(int increment) &&
-{
- request["sat_inc"] = std::max(-254, std::min(increment, 254));
- return std::move(*this);
-}
-
-hueplusplus::StateTransaction&& hueplusplus::StateTransaction::incrementHue(int increment) &&
-{
- request["hue_inc"] = std::max(-65534, std::min(increment, 65534));
- return std::move(*this);
-}
-
-hueplusplus::StateTransaction&& hueplusplus::StateTransaction::incrementColorTemperature(int increment) &&
-{
- request["ct_inc"] = std::max(-65534, std::min(increment, 65534));
- return std::move(*this);
-}
-
-hueplusplus::StateTransaction&& hueplusplus::StateTransaction::incrementColorXY(float xInc, float yInc) &&
-{
- request["xy_inc"] = {std::min(-0.5f, std::max(xInc, 0.5f)), std::min(-0.5f, std::max(yInc, 0.5f))};
- return std::move(*this);
-}
-
-hueplusplus::StateTransaction&& hueplusplus::StateTransaction::setScene(const std::string& scene) &&
-{
- request["scene"] = scene;
- return std::move(*this);
-}
-
-hueplusplus::StateTransaction&& hueplusplus::StateTransaction::setTransition(uint16_t transition) &&
-{
- if (transition != 4)
- {
- request["transitiontime"] = transition;
- }
- return std::move(*this);
-}
-
-hueplusplus::Group::Group(int id, const HueCommandAPI& commands, std::chrono::steady_clock::duration refreshDuration)
+Group::Group(int id, const HueCommandAPI& commands, std::chrono::steady_clock::duration refreshDuration)
: id(id), state("/groups/" + std::to_string(id), commands, refreshDuration), commands(commands)
{
state.Refresh();
}
-void hueplusplus::Group::Refresh()
+void Group::Refresh()
{
state.Refresh();
}
-int hueplusplus::Group::getId() const
+int Group::getId() const
{
return id;
}
-std::string hueplusplus::Group::getName() const
+std::string Group::getName() const
{
return state.GetValue().at("name").get();
}
-std::string hueplusplus::Group::getType() const
+std::string Group::getType() const
{
return state.GetValue().at("type").get();
}
-std::vector hueplusplus::Group::getLightIds() const
+std::vector Group::getLightIds() const
{
const nlohmann::json& lights = state.GetValue().at("lights");
std::vector ids;
@@ -166,13 +42,13 @@ std::vector hueplusplus::Group::getLightIds() const
return ids;
}
-void hueplusplus::Group::setName(const std::string& name)
+void Group::setName(const std::string& name)
{
nlohmann::json request = {{"name", name}};
SendPutRequest(request, "", CURRENT_FILE_INFO);
}
-void hueplusplus::Group::setLights(const std::vector& ids)
+void Group::setLights(const std::vector& ids)
{
nlohmann::json lights = nlohmann::json::array();
for (int id : ids)
@@ -182,90 +58,91 @@ void hueplusplus::Group::setLights(const std::vector& ids)
SendPutRequest({{"lights", lights}}, "", CURRENT_FILE_INFO);
}
-bool hueplusplus::Group::getAllOn()
+bool Group::getAllOn()
{
return state.GetValue().at("state").at("all_on").get();
}
-bool hueplusplus::Group::getAllOn() const
+bool Group::getAllOn() const
{
return state.GetValue().at("state").at("all_on").get();
}
-bool hueplusplus::Group::getAnyOn()
+bool Group::getAnyOn()
{
return state.GetValue().at("state").at("any_on").get();
}
-bool hueplusplus::Group::getAnyOn() const
+bool Group::getAnyOn() const
{
return state.GetValue().at("state").at("any_on").get();
}
-bool hueplusplus::Group::getActionOn()
+bool Group::getActionOn()
{
return state.GetValue().at("action").at("on").get();
}
-bool hueplusplus::Group::getActionOn() const
+bool Group::getActionOn() const
{
return state.GetValue().at("action").at("on").get();
}
-std::pair hueplusplus::Group::getActionHueSaturation()
+std::pair Group::getActionHueSaturation()
{
const nlohmann::json& action = state.GetValue().at("action");
return std::make_pair(action.at("hue").get(), action.at("sat").get());
}
-std::pair hueplusplus::Group::getActionHueSaturation() const
+std::pair Group::getActionHueSaturation() const
{
const nlohmann::json& action = state.GetValue().at("action");
return std::make_pair(action.at("hue").get(), action.at("sat").get());
}
-unsigned int hueplusplus::Group::getActionBrightness()
+unsigned int Group::getActionBrightness()
{
return state.GetValue().at("action").at("bri").get();
}
-unsigned int hueplusplus::Group::getActionBrightness() const
+unsigned int Group::getActionBrightness() const
{
return state.GetValue().at("action").at("bri").get();
}
-unsigned int hueplusplus::Group::getActionColorTemperature()
+unsigned int Group::getActionColorTemperature()
{
return state.GetValue().at("action").at("ct").get();
}
-unsigned int hueplusplus::Group::getActionColorTemperature() const
+unsigned int Group::getActionColorTemperature() const
{
return state.GetValue().at("action").at("ct").get();
}
-std::pair hueplusplus::Group::getActionColorXY()
+std::pair Group::getActionColorXY()
{
const nlohmann::json& xy = state.GetValue().at("action").at("xy");
return std::pair(xy[0].get(), xy[1].get());
}
-std::pair hueplusplus::Group::getActionColorXY() const
+std::pair Group::getActionColorXY() const
{
const nlohmann::json& xy = state.GetValue().at("action").at("xy");
return std::pair(xy[0].get(), xy[1].get());
}
-std::string hueplusplus::Group::getActionColorMode()
+std::string Group::getActionColorMode()
{
return state.GetValue().at("action").at("colormode").get();
}
-std::string hueplusplus::Group::getActionColorMode() const
+std::string Group::getActionColorMode() const
{
return state.GetValue().at("action").at("colormode").get();
}
-hueplusplus::StateTransaction hueplusplus::Group::transaction()
+StateTransaction Group::transaction()
{
- return StateTransaction(commands, "/groups/" + std::to_string(id) + "/action", state.GetValue());
+ // Do not pass state, because it is not the state of ALL lights in the group
+ return StateTransaction(commands, "/groups/" + std::to_string(id) + "/action", nlohmann::json::object());
}
-void hueplusplus::Group::setOn(bool on, uint8_t transition)
+void Group::setOn(bool on, uint8_t transition)
{
nlohmann::json request = {{"on", on}};
if (transition != 4)
@@ -275,83 +152,83 @@ void hueplusplus::Group::setOn(bool on, uint8_t transition)
SendPutRequest(request, "/action", CURRENT_FILE_INFO);
}
-void hueplusplus::Group::setBrightness(uint8_t brightness, uint8_t transition)
+void Group::setBrightness(uint8_t brightness, uint8_t transition)
{
transaction().setBrightness(brightness).setTransition(transition).commit();
}
-void hueplusplus::Group::setColorHueSaturation(uint16_t hue, uint8_t saturation, uint8_t transition)
+void Group::setColorHueSaturation(uint16_t hue, uint8_t saturation, uint8_t transition)
{
transaction().setColorHueSaturation(hue, saturation).setTransition(transition).commit();
}
-void hueplusplus::Group::setColorXY(float x, float y, uint8_t transition)
+void Group::setColorXY(float x, float y, uint8_t transition)
{
transaction().setColorXY(x, y).setTransition(transition).commit();
}
-void hueplusplus::Group::setColorTemperature(unsigned int mired, uint8_t transition)
+void Group::setColorTemperature(unsigned int mired, uint8_t transition)
{
transaction().setColorTemperature(mired).setTransition(transition).commit();
}
-void hueplusplus::Group::setColorLoop(bool on, uint8_t transition)
+void Group::setColorLoop(bool on, uint8_t transition)
{
transaction().setColorLoop(on).setTransition(transition);
}
-void hueplusplus::Group::incrementBrightness(int increment, uint8_t transition)
+void Group::incrementBrightness(int increment, uint8_t transition)
{
transaction().incrementBrightness(increment).setTransition(transition).commit();
}
-void hueplusplus::Group::incrementSaturation(int increment, uint8_t transition)
+void Group::incrementSaturation(int increment, uint8_t transition)
{
transaction().incrementSaturation(increment).setTransition(transition).commit();
}
-void hueplusplus::Group::incrementHue(int increment, uint8_t transition)
+void Group::incrementHue(int increment, uint8_t transition)
{
transaction().incrementHue(increment).setTransition(transition).commit();
}
-void hueplusplus::Group::incrementColorTemperature(int increment, uint8_t transition)
+void Group::incrementColorTemperature(int increment, uint8_t transition)
{
transaction().incrementColorTemperature(increment).setTransition(transition).commit();
}
-void hueplusplus::Group::incrementColorXY(float incX, float incY, uint8_t transition)
+void Group::incrementColorXY(float incX, float incY, uint8_t transition)
{
transaction().incrementColorXY(incX, incY).setTransition(transition).commit();
}
-void hueplusplus::Group::setScene(const std::string& scene, uint8_t transition)
+void Group::setScene(const std::string& scene, uint8_t transition)
{
- transaction().setScene(scene).setTransition(transition).commit();
+ SendPutRequest({ {"scene", scene} }, "/action", CURRENT_FILE_INFO);
}
-nlohmann::json hueplusplus::Group::SendPutRequest(
- const nlohmann::json& request, const std::string& subPath, FileInfo fileInfo)
+nlohmann::json Group::SendPutRequest(const nlohmann::json& request, const std::string& subPath, FileInfo fileInfo)
{
return commands.PUTRequest("/groups/" + std::to_string(id) + subPath, request, std::move(fileInfo));
}
-std::string hueplusplus::Group::getRoomType() const
+std::string Group::getRoomType() const
{
return state.GetValue().at("class").get();
}
-void hueplusplus::Group::setRoomType(const std::string& type)
+void Group::setRoomType(const std::string& type)
{
SendPutRequest({{"class", type}}, "", CURRENT_FILE_INFO);
}
-std::string hueplusplus::Group::getModelId() const
+std::string Group::getModelId() const
{
return state.GetValue().at("modelid").get();
}
-std::string hueplusplus::Group::getUniqueId() const
+std::string Group::getUniqueId() const
{
return state.GetValue().at("uniqueid").get();
}
+} // namespace hueplusplus
diff --git a/src/HueLight.cpp b/src/HueLight.cpp
index fafc7a2..3ff0c87 100644
--- a/src/HueLight.cpp
+++ b/src/HueLight.cpp
@@ -34,60 +34,22 @@ namespace hueplusplus
{
bool HueLight::On(uint8_t transition)
{
- nlohmann::json request = nlohmann::json::object();
- if (transition != 4)
- {
- request["transitiontime"] = transition;
- }
- if (state.GetValue()["state"]["on"] != true)
- {
- request["on"] = true;
- }
-
- if (!request.count("on"))
- {
- // Nothing needs to be changed
- return true;
- }
-
- nlohmann::json reply = SendPutRequest(request, "/state", CURRENT_FILE_INFO);
-
- // Check whether request was successful
- return utils::validateReplyForLight(request, reply, id);
+ return transaction().setOn(true).setTransition(transition).commit();
}
bool HueLight::Off(uint8_t transition)
{
- nlohmann::json request = nlohmann::json::object();
- if (transition != 4)
- {
- request["transitiontime"] = transition;
- }
- if (state.GetValue()["state"]["on"] != false)
- {
- request["on"] = false;
- }
-
- if (!request.count("on"))
- {
- // Nothing needs to be changed
- return true;
- }
-
- nlohmann::json reply = SendPutRequest(request, "/state", CURRENT_FILE_INFO);
-
- // Check whether request was successful
- return utils::validateReplyForLight(request, reply, id);
+ return transaction().setOn(false).setTransition(transition).commit();
}
bool HueLight::isOn()
{
- return state.GetValue()["state"]["on"].get();
+ return state.GetValue().at("state").at("on").get();
}
bool HueLight::isOn() const
{
- return state.GetValue()["state"]["on"].get();
+ return state.GetValue().at("state").at("on").get();
}
int HueLight::getId() const
@@ -173,12 +135,12 @@ unsigned int HueLight::MiredToKelvin(unsigned int mired) const
bool HueLight::alert()
{
- nlohmann::json request;
- request["alert"] = "select";
-
- nlohmann::json reply = SendPutRequest(request, "/state", CURRENT_FILE_INFO);
+ return transaction().alert().commit();
+}
- return utils::validateReplyForLight(request, reply, id);
+StateTransaction HueLight::transaction()
+{
+ return StateTransaction(commands, "/lights/" + std::to_string(id) + "/state", state.GetValue().at("state"));
}
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 colorTempStrategy,
std::shared_ptr colorHueStrategy, std::chrono::steady_clock::duration refreshDuration)
: id(id),
+ state("/lights/" + std::to_string(id), commands, refreshDuration),
+ colorType(ColorType::NONE),
brightnessStrategy(std::move(brightnessStrategy)),
colorTemperatureStrategy(std::move(colorTempStrategy)),
colorHueStrategy(std::move(colorHueStrategy)),
- commands(commands),
- state("/lights/" + std::to_string(id), commands, refreshDuration)
-
+ commands(commands)
{
state.Refresh();
}
diff --git a/src/SimpleBrightnessStrategy.cpp b/src/SimpleBrightnessStrategy.cpp
index 185d7ce..3a37a4b 100644
--- a/src/SimpleBrightnessStrategy.cpp
+++ b/src/SimpleBrightnessStrategy.cpp
@@ -34,49 +34,7 @@ namespace hueplusplus
bool SimpleBrightnessStrategy::setBrightness(unsigned int bri, uint8_t transition, HueLight& light) const
{
// Careful, only use state until any light function might refresh the value and invalidate the reference
- const nlohmann::json& state = light.state.GetValue()["state"];
- if (bri == 0)
- {
- if (state["on"] == true)
- {
- return light.Off(transition);
- }
- else
- {
- return true;
- }
- }
- else
- {
- nlohmann::json request = nlohmann::json::object();
- if (transition != 4)
- {
- request["transitiontime"] = transition;
- }
- if (state["on"] != true)
- {
- request["on"] = true;
- }
- if (state["bri"] != bri)
- {
- if (bri > 254)
- {
- bri = 254;
- }
- request["bri"] = bri;
- }
-
- if (!request.count("on") && !request.count("bri"))
- {
- // Nothing needs to be changed
- return true;
- }
-
- nlohmann::json reply = light.SendPutRequest(request, "/state", CURRENT_FILE_INFO);
-
- // Check whether request was successful
- return utils::validateReplyForLight(request, reply, light.id);
- }
+ return light.transaction().setBrightness(bri).setTransition(transition).commit();
}
unsigned int SimpleBrightnessStrategy::getBrightness(HueLight& light) const
diff --git a/src/SimpleColorHueStrategy.cpp b/src/SimpleColorHueStrategy.cpp
index dac0a79..e3dcbcc 100644
--- a/src/SimpleColorHueStrategy.cpp
+++ b/src/SimpleColorHueStrategy.cpp
@@ -34,140 +34,22 @@ namespace hueplusplus
{
bool SimpleColorHueStrategy::setColorHue(uint16_t hue, uint8_t transition, HueLight& light) const
{
- // Careful, only use state until any light function might refresh the value and invalidate the reference
- const nlohmann::json& state = light.state.GetValue()["state"];
- nlohmann::json request = nlohmann::json::object();
- if (transition != 4)
- {
- request["transitiontime"] = transition;
- }
- if (state["on"] != true)
- {
- request["on"] = true;
- }
- if (state["hue"] != hue || state["colormode"] != "hs")
- {
- hue = hue % 65535;
- request["hue"] = hue;
- }
-
- if (!request.count("on") && !request.count("hue"))
- {
- // Nothing needs to be changed
- return true;
- }
-
- nlohmann::json reply = light.SendPutRequest(request, "/state", CURRENT_FILE_INFO);
-
- // Check whether request was successful
- return utils::validateReplyForLight(request, reply, light.id);
+ return light.transaction().setColorHue(hue).setTransition(transition).commit();
}
bool SimpleColorHueStrategy::setColorSaturation(uint8_t sat, uint8_t transition, HueLight& light) const
{
- // Careful, only use state until any light function might refresh the value and invalidate the reference
- const nlohmann::json& state = light.state.GetValue()["state"];
- nlohmann::json request = nlohmann::json::object();
- if (transition != 4)
- {
- request["transitiontime"] = transition;
- }
- if (state["on"] != true)
- {
- request["on"] = true;
- }
- if (state["sat"] != sat)
- {
- if (sat > 254)
- {
- sat = 254;
- }
- request["sat"] = sat;
- }
-
- if (!request.count("on") && !request.count("sat"))
- {
- // Nothing needs to be changed
- return true;
- }
-
- nlohmann::json reply = light.SendPutRequest(request, "/state", CURRENT_FILE_INFO);
-
- // Check whether request was successful
- return utils::validateReplyForLight(request, reply, light.id);
+ return light.transaction().setColorSaturation(sat).setTransition(transition).commit();
}
bool SimpleColorHueStrategy::setColorHueSaturation(uint16_t hue, uint8_t sat, uint8_t transition, HueLight& light) const
{
- // Careful, only use state until any light function might refresh the value and invalidate the reference
- const nlohmann::json& state = light.state.GetValue()["state"];
- nlohmann::json request = nlohmann::json::object();
-
- if (transition != 4)
- {
- request["transitiontime"] = transition;
- }
- if (state["on"] != true)
- {
- request["on"] = true;
- }
- if (state["hue"] != hue || state["colormode"] != "hs")
- {
- hue = hue % 65535;
- request["hue"] = hue;
- }
- if (state["sat"] != sat || state["colormode"] != "hs")
- {
- if (sat > 254)
- {
- sat = 254;
- }
- request["sat"] = sat;
- }
-
- if (!request.count("on") && !request.count("hue") && !request.count("sat"))
- {
- // Nothing needs to be changed
- return true;
- }
-
- nlohmann::json reply = light.SendPutRequest(request, "/state", CURRENT_FILE_INFO);
-
- // Check whether request was successful
- return utils::validateReplyForLight(request, reply, light.id);
+ return light.transaction().setColorHueSaturation(hue, sat).setTransition(transition).commit();
}
bool SimpleColorHueStrategy::setColorXY(float x, float y, uint8_t transition, HueLight& light) const
{
- // Careful, only use state until any light function might refresh the value and invalidate the reference
- const nlohmann::json& state = light.state.GetValue()["state"];
- nlohmann::json request = nlohmann::json::object();
-
- if (transition != 4)
- {
- request["transitiontime"] = transition;
- }
- if (state["on"] != true)
- {
- request["on"] = true;
- }
- if (std::abs(state["xy"][0].get() - x) > 1E-4f || std::abs(state["xy"][1].get() - y) > 1E-4f
- || state["colormode"] != "xy")
- {
- request["xy"][0] = x;
- request["xy"][1] = y;
- }
-
- if (!request.count("on") && !request.count("xy"))
- {
- // Nothing needs to be changed
- return true;
- }
-
- nlohmann::json reply = light.SendPutRequest(request, "/state", CURRENT_FILE_INFO);
-
- // Check whether request was successful
- return utils::validateReplyForLight(request, reply, light.id);
+ return light.transaction().setColorXY(x, y).setTransition(transition).commit();
}
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_
bool SimpleColorHueStrategy::setColorLoop(bool on, HueLight& light) const
{
- // colorloop
- // Careful, only use state until any light function might refresh the value and invalidate the reference
- const nlohmann::json& state = light.state.GetValue()["state"];
- nlohmann::json request = nlohmann::json::object();
-
- if (state["on"] != true)
- {
- request["on"] = true;
- }
- std::string effect;
- if ((effect = on ? "colorloop" : "none") != state["effect"])
- {
- request["effect"] = effect;
- }
- if (!request.count("on") && !request.count("effect"))
- {
- // Nothing needs to be changed
- return true;
- }
-
- nlohmann::json reply = light.SendPutRequest(request, "/state", CURRENT_FILE_INFO);
-
- // Check whether request was successful
- return utils::validateReplyForLight(request, reply, light.id);
+ return light.transaction().setColorLoop(true).commit();
}
bool SimpleColorHueStrategy::alertHueSaturation(uint16_t hue, uint8_t sat, HueLight& light) const
diff --git a/src/SimpleColorTemperatureStrategy.cpp b/src/SimpleColorTemperatureStrategy.cpp
index 02c96b5..9da0e98 100644
--- a/src/SimpleColorTemperatureStrategy.cpp
+++ b/src/SimpleColorTemperatureStrategy.cpp
@@ -34,40 +34,7 @@ namespace hueplusplus
{
bool SimpleColorTemperatureStrategy::setColorTemperature(unsigned int mired, uint8_t transition, HueLight& light) const
{
- // Careful, only use state until any light function might refresh the value and invalidate the reference
- const nlohmann::json& state = light.state.GetValue()["state"];
- nlohmann::json request = nlohmann::json::object();
- if (transition != 4)
- {
- request["transitiontime"] = transition;
- }
- if (state["on"] != true)
- {
- request["on"] = true;
- }
- if (state["ct"] != mired)
- {
- if (mired > 500)
- {
- mired = 500;
- }
- if (mired < 153)
- {
- mired = 153;
- }
- request["ct"] = mired;
- }
-
- if (!request.count("on") && !request.count("ct"))
- {
- // Nothing needs to be changed
- return true;
- }
-
- nlohmann::json reply = light.SendPutRequest(request, "/state", CURRENT_FILE_INFO);
-
- // Check whether request was successful
- return utils::validateReplyForLight(request, reply, light.id);
+ return light.transaction().setColorTemperature(mired).setTransition(transition).commit();
}
bool SimpleColorTemperatureStrategy::alertTemperature(unsigned int mired, HueLight& light) const
diff --git a/src/StateTransaction.cpp b/src/StateTransaction.cpp
new file mode 100644
index 0000000..90d2fa9
--- /dev/null
+++ b/src/StateTransaction.cpp
@@ -0,0 +1,199 @@
+/**
+ \file StateTransaction.cpp
+ Copyright Notice\n
+ Copyright (C) 2020 Jan Rogall - developer\n
+ Copyright (C) 2020 Moritz Wirger - developer\n
+
+ This file is part of hueplusplus.
+
+ hueplusplus is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ hueplusplus is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with hueplusplus. If not, see .
+**/
+
+#include "hueplusplus/StateTransaction.h"
+
+#include "hueplusplus/HueExceptionMacro.h"
+#include "hueplusplus/StateTransaction.h"
+#include "hueplusplus/Utils.h"
+
+namespace hueplusplus
+{
+StateTransaction::StateTransaction(
+ const HueCommandAPI& commands, const std::string& path, const nlohmann::json& currentState)
+ : commands(commands), path(path), state(currentState), request(nlohmann::json::object())
+{}
+
+bool StateTransaction::commit() &&
+{
+ // Empty request or request with only transition makes no sense
+ if (!request.empty() && !(request.size() == 1 && request.count("transitiontime")))
+ {
+ if (!request.count("on"))
+ {
+ if (request.value("bri", 254) == 0 && state.value("on", true))
+ {
+ // Turn off if brightness is 0
+ request["on"] = false;
+ }
+ else if (!state.value("on", false)
+ && (request.value("bri", 0) != 0 || request.count("effect") || request.count("hue")
+ || request.count("sat") || request.count("xy") || request.count("ct")))
+ {
+ // Turn on if it was turned off
+ request["on"] = true;
+ }
+ }
+
+ nlohmann::json reply = commands.PUTRequest(path, request, CURRENT_FILE_INFO);
+ return utils::validatePUTReply(path, request, reply);
+ }
+ return true;
+}
+
+StateTransaction&& StateTransaction::setOn(bool on) &&
+{
+ if (!state.count("on") || state["on"] != on)
+ {
+ request["on"] = on;
+ }
+ return std::move(*this);
+}
+
+StateTransaction&& StateTransaction::setBrightness(uint8_t brightness) &&
+{
+ uint8_t clamped = std::min(brightness, 254);
+ if (!state.count("bri") || state["bri"].get() != clamped)
+ {
+ request["bri"] = clamped;
+ }
+ return std::move(*this);
+}
+
+StateTransaction&& StateTransaction::setColorSaturation(uint8_t saturation) &&
+{
+ uint8_t clamped = std::min(saturation, 254);
+ if (!state.count("sat") || state["sat"].get() != clamped || state.value("colormode", "") != "hs")
+ {
+ request["sat"] = clamped;
+ }
+ return std::move(*this);
+}
+
+StateTransaction&& StateTransaction::setColorHue(uint16_t hue) &&
+{
+ if (!state.count("hue") || state["hue"].get() != hue || state.value("colormode", "") != "hs")
+ {
+ request["hue"] = hue;
+ }
+ return std::move(*this);
+}
+
+StateTransaction&& StateTransaction::setColorHueSaturation(uint16_t hue, uint8_t saturation) &&
+{
+ if (!state.count("hue") || state["hue"].get() != hue)
+ {
+ request["hue"] = hue;
+ }
+ uint8_t clamped = std::min(saturation, 254);
+ if (!state.count("sat") || state["sat"].get() != clamped)
+ {
+ request["sat"] = clamped;
+ }
+ return std::move(*this);
+}
+
+StateTransaction&& StateTransaction::setColorXY(float x, float y) &&
+{
+ if (!state.count("xy") || !state.count("colormode") || !state["xy"].is_array()
+ || !utils::floatEquals(state["xy"][0].get(), x) || !utils::floatEquals(state["xy"][1].get(), y)
+ || state["colormode"] != "xy")
+ {
+ request["xy"] = {x, y};
+ }
+ return std::move(*this);
+}
+
+StateTransaction&& StateTransaction::setColorTemperature(unsigned int mired) &&
+{
+ unsigned int clamped = std::max(153u, std::min(mired, 500u));
+ if (state.value("ct", 0u) != clamped || state.value("colormode", "") != "ct")
+ {
+ request["ct"] = clamped;
+ }
+ return std::move(*this);
+}
+
+StateTransaction&& StateTransaction::setColorLoop(bool on) &&
+{
+ std::string effect = on ? "colorloop" : "none";
+ if (state.value("effect", "") != effect)
+ {
+ request["effect"] = effect;
+ }
+ return std::move(*this);
+}
+
+StateTransaction&& StateTransaction::incrementBrightness(int increment) &&
+{
+ request["bri_inc"] = std::max(-254, std::min(increment, 254));
+ return std::move(*this);
+}
+
+StateTransaction&& StateTransaction::incrementSaturation(int increment) &&
+{
+ request["sat_inc"] = std::max(-254, std::min(increment, 254));
+ return std::move(*this);
+}
+
+StateTransaction&& StateTransaction::incrementHue(int increment) &&
+{
+ request["hue_inc"] = std::max(-65534, std::min(increment, 65534));
+ return std::move(*this);
+}
+
+StateTransaction&& StateTransaction::incrementColorTemperature(int increment) &&
+{
+ request["ct_inc"] = std::max(-65534, std::min(increment, 65534));
+ return std::move(*this);
+}
+
+StateTransaction&& StateTransaction::incrementColorXY(float xInc, float yInc) &&
+{
+ request["xy_inc"] = {std::min(-0.5f, std::max(xInc, 0.5f)), std::min(-0.5f, std::max(yInc, 0.5f))};
+ return std::move(*this);
+}
+
+StateTransaction&& StateTransaction::setTransition(uint16_t transition) &&
+{
+ if (transition != 4)
+ {
+ request["transitiontime"] = transition;
+ }
+ return std::move(*this);
+}
+StateTransaction&& StateTransaction::alert() &&
+{
+ request["alert"] = "select";
+ return std::move(*this);
+}
+StateTransaction&& StateTransaction::longAlert() &&
+{
+ request["alert"] = "lselect";
+ return std::move(*this);
+}
+StateTransaction&& StateTransaction::stopAlert() &&
+{
+ request["alert"] = "none";
+ return std::move(*this);
+}
+} // namespace hueplusplus
\ No newline at end of file
diff --git a/src/Utils.cpp b/src/Utils.cpp
index a95e67b..491cfec 100644
--- a/src/Utils.cpp
+++ b/src/Utils.cpp
@@ -28,10 +28,14 @@ namespace hueplusplus
{
namespace utils
{
-bool validateReplyForLight(const nlohmann::json& request, const nlohmann::json& reply, int lightId)
+bool validatePUTReply(const std::string& path, const nlohmann::json& request, const nlohmann::json& reply)
{
+ std::string pathAppend = path;
+ if (pathAppend.back() != '/')
+ {
+ pathAppend.push_back('/');
+ }
bool success = false;
- std::string path = "/lights/" + std::to_string(lightId) + "/state/";
for (auto it = reply.begin(); it != reply.end(); ++it)
{
success = it.value().count("success");
@@ -42,9 +46,9 @@ bool validateReplyForLight(const nlohmann::json& request, const nlohmann::json&
for (auto successIt = successObject.begin(); successIt != successObject.end(); ++successIt)
{
const std::string successPath = successIt.key();
- if (successPath.find(path) == 0)
+ if (successPath.find(pathAppend) == 0)
{
- const std::string valueKey = successPath.substr(path.size());
+ const std::string valueKey = successPath.substr(pathAppend.size());
auto requestIt = request.find(valueKey);
success = requestIt != request.end();
if (success)
@@ -58,7 +62,8 @@ bool validateReplyForLight(const nlohmann::json& request, const nlohmann::json&
}
else
{
- success = requestIt.value() == successIt.value();
+ success = requestIt.value() == successIt.value()
+ || (successIt.value().is_string() && successIt.value() == "Updated.");
}
if (!success)
{
@@ -80,5 +85,10 @@ bool validateReplyForLight(const nlohmann::json& request, const nlohmann::json&
}
return success;
}
+
+bool validateReplyForLight(const nlohmann::json& request, const nlohmann::json& reply, int lightId)
+{
+ return validatePUTReply("/lights/" + std::to_string(lightId) + "/state/", request, reply);
+}
} // namespace utils
} // namespace hueplusplus
diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt
index fe61852..51a423c 100644
--- a/test/CMakeLists.txt
+++ b/test/CMakeLists.txt
@@ -70,6 +70,9 @@ add_custom_target("unittest"
find_program( GCOV_PATH gcov )
find_program( LCOV_PATH lcov )
+mark_as_advanced(GCOV_PATH)
+mark_as_advanced(LCOV_PATH)
+
if(LCOV_PATH AND GCOV_PATH)
# GCov
include(CodeCoverage.cmake)
diff --git a/test/test_HueLight.cpp b/test/test_HueLight.cpp
index a8b3edd..d38ef48 100644
--- a/test/test_HueLight.cpp
+++ b/test/test_HueLight.cpp
@@ -69,7 +69,7 @@ protected:
hue_bridge_state["lights"]["2"] = nlohmann::json::object();
hue_bridge_state["lights"]["2"]["state"] = nlohmann::json::object();
hue_bridge_state["lights"]["2"]["state"]["on"] = false;
- hue_bridge_state["lights"]["2"]["state"]["bri"] = 254;
+ hue_bridge_state["lights"]["2"]["state"]["bri"] = 0;
hue_bridge_state["lights"]["2"]["state"]["ct"] = 366;
hue_bridge_state["lights"]["2"]["state"]["hue"] = 123456;
hue_bridge_state["lights"]["2"]["state"]["sat"] = 123;
@@ -514,7 +514,7 @@ TEST_F(HueLightTest, setBrightness)
prep_ret[1]["success"]["/lights/3/state/on"] = true;
prep_ret[2] = nlohmann::json::object();
prep_ret[2]["success"] = nlohmann::json::object();
- prep_ret[2]["success"]["/lights/3/state/bri"] = 254;
+ prep_ret[2]["success"]["/lights/3/state/bri"] = 253;
EXPECT_CALL(*handler, PUTJson("/api/" + getBridgeUsername() + "/lights/3/state", _, getBridgeIp(), 80))
.Times(1)
.WillOnce(Return(prep_ret));
@@ -525,7 +525,7 @@ TEST_F(HueLightTest, setBrightness)
EXPECT_EQ(false, test_light_1.setBrightness(200));
EXPECT_EQ(true, test_light_2.setBrightness(0, 2));
- EXPECT_EQ(true, test_light_3.setBrightness(255, 0));
+ EXPECT_EQ(true, test_light_3.setBrightness(253, 0));
}
TEST_F(HueLightTest, getBrightness)
@@ -538,10 +538,10 @@ TEST_F(HueLightTest, getBrightness)
HueLight test_light_3 = test_bridge.getLight(3);
EXPECT_EQ(254, ctest_light_1.getBrightness());
- EXPECT_EQ(254, ctest_light_2.getBrightness());
+ EXPECT_EQ(0, ctest_light_2.getBrightness());
EXPECT_EQ(254, ctest_light_3.getBrightness());
EXPECT_EQ(254, test_light_1.getBrightness());
- EXPECT_EQ(254, test_light_2.getBrightness());
+ EXPECT_EQ(0, test_light_2.getBrightness());
EXPECT_EQ(254, test_light_3.getBrightness());
}
diff --git a/test/test_SimpleBrightnessStrategy.cpp b/test/test_SimpleBrightnessStrategy.cpp
index 38179ad..a63421b 100644
--- a/test/test_SimpleBrightnessStrategy.cpp
+++ b/test/test_SimpleBrightnessStrategy.cpp
@@ -46,33 +46,30 @@ TEST(SimpleBrightnessStrategy, setBrightness)
.WillRepeatedly(Return(nlohmann::json::object()));
MockHueLight test_light(handler);
- EXPECT_CALL(test_light, Off(_)).Times(AtLeast(1)).WillRepeatedly(Return(true));
- nlohmann::json prep_ret;
- prep_ret = nlohmann::json::array();
- prep_ret[0] = nlohmann::json::object();
- prep_ret[0]["success"] = nlohmann::json::object();
- prep_ret[0]["success"]["/lights/1/state/transitiontime"] = 6;
- prep_ret[1] = nlohmann::json::object();
- prep_ret[1]["success"] = nlohmann::json::object();
- prep_ret[1]["success"]["/lights/1/state/on"] = true;
- prep_ret[2] = nlohmann::json::object();
- prep_ret[2]["success"] = nlohmann::json::object();
- prep_ret[2]["success"]["/lights/1/state/bri"] = 50;
- EXPECT_CALL(test_light, SendPutRequest(_, "/state", _)).Times(1).WillOnce(Return(prep_ret));
+ const std::string statePath = "/api/" + getBridgeUsername() + "/lights/1/state";
+ nlohmann::json prep_ret
+ = {{{"success", {{"/lights/1/state/on", false}}}}, {{"success", {{"/lights/1/state/bri", 0}}}}};
+ EXPECT_CALL(*handler, PUTJson(statePath, _, getBridgeIp(), getBridgePort())).Times(1).WillOnce(Return(prep_ret));
test_light.getState()["state"]["on"] = true;
EXPECT_EQ(true, SimpleBrightnessStrategy().setBrightness(0, 4, test_light));
+ // Only set brightness, already off
test_light.getState()["state"]["on"] = false;
+ prep_ret = {{{"success", {{"/lights/1/state/bri", 0}}}}};
+ EXPECT_CALL(*handler, PUTJson(statePath, _, getBridgeIp(), getBridgePort())).Times(1).WillOnce(Return(prep_ret));
EXPECT_EQ(true, SimpleBrightnessStrategy().setBrightness(0, 4, test_light));
+ prep_ret = {{{"success", {{"/lights/1/state/on", true}}}}, {{"success", {{"/lights/1/state/bri", 50}}}}};
+ EXPECT_CALL(*handler, PUTJson(statePath, _, getBridgeIp(), getBridgePort())).Times(1).WillOnce(Return(prep_ret));
test_light.getState()["state"]["bri"] = 0;
EXPECT_EQ(true, SimpleBrightnessStrategy().setBrightness(50, 6, test_light));
test_light.getState()["state"]["on"] = true;
test_light.getState()["state"]["bri"] = 50;
+ // No request because state matches
EXPECT_EQ(true, SimpleBrightnessStrategy().setBrightness(50, 6, test_light));
- prep_ret[2]["success"]["/lights/1/state/bri"] = 254;
- EXPECT_CALL(test_light, SendPutRequest(_, "/state", _)).Times(1).WillOnce(Return(prep_ret));
+ prep_ret[1]["success"]["/lights/1/state/bri"] = 254;
+ EXPECT_CALL(*handler, PUTJson(statePath, _, getBridgeIp(), getBridgePort())).Times(1).WillOnce(Return(prep_ret));
test_light.getState()["state"]["on"] = false;
EXPECT_EQ(true, SimpleBrightnessStrategy().setBrightness(255, 6, test_light));
}
diff --git a/test/test_SimpleColorHueStrategy.cpp b/test/test_SimpleColorHueStrategy.cpp
index 2216d81..4c432ff 100644
--- a/test/test_SimpleColorHueStrategy.cpp
+++ b/test/test_SimpleColorHueStrategy.cpp
@@ -45,6 +45,8 @@ TEST(SimpleColorHueStrategy, setColorHue)
.WillRepeatedly(Return(nlohmann::json::object()));
MockHueLight test_light(handler);
+ const std::string statePath = "/api/" + getBridgeUsername() + "/lights/1/state";
+
nlohmann::json prep_ret;
prep_ret = nlohmann::json::array();
prep_ret[0] = nlohmann::json::object();
@@ -56,7 +58,7 @@ TEST(SimpleColorHueStrategy, setColorHue)
prep_ret[2] = nlohmann::json::object();
prep_ret[2]["success"] = nlohmann::json::object();
prep_ret[2]["success"]["/lights/1/state/hue"] = 30500;
- EXPECT_CALL(test_light, SendPutRequest(_, "/state", _)).Times(1).WillOnce(Return(prep_ret));
+ EXPECT_CALL(*handler, PUTJson(statePath, _, getBridgeIp(), getBridgePort())).Times(1).WillOnce(Return(prep_ret));
test_light.getState()["state"]["on"] = true;
test_light.getState()["state"]["hue"] = 200;
@@ -77,6 +79,8 @@ TEST(SimpleColorHueStrategy, setColorSaturation)
.WillRepeatedly(Return(nlohmann::json::object()));
MockHueLight test_light(handler);
+ const std::string statePath = "/api/" + getBridgeUsername() + "/lights/1/state";
+
nlohmann::json prep_ret;
prep_ret = nlohmann::json::array();
prep_ret[0] = nlohmann::json::object();
@@ -88,7 +92,7 @@ TEST(SimpleColorHueStrategy, setColorSaturation)
prep_ret[2] = nlohmann::json::object();
prep_ret[2]["success"] = nlohmann::json::object();
prep_ret[2]["success"]["/lights/1/state/sat"] = 254;
- EXPECT_CALL(test_light, SendPutRequest(_, "/state", _)).Times(1).WillOnce(Return(prep_ret));
+ EXPECT_CALL(*handler, PUTJson(statePath, _, getBridgeIp(), getBridgePort())).Times(1).WillOnce(Return(prep_ret));
test_light.getState()["state"]["on"] = true;
test_light.getState()["state"]["sat"] = 100;
@@ -109,6 +113,8 @@ TEST(SimpleColorHueStrategy, setColorHueSaturation)
.WillRepeatedly(Return(nlohmann::json::object()));
MockHueLight test_light(handler);
+ const std::string statePath = "/api/" + getBridgeUsername() + "/lights/1/state";
+
nlohmann::json prep_ret;
prep_ret = nlohmann::json::array();
prep_ret[0] = nlohmann::json::object();
@@ -123,7 +129,7 @@ TEST(SimpleColorHueStrategy, setColorHueSaturation)
prep_ret[3] = nlohmann::json::object();
prep_ret[3]["success"] = nlohmann::json::object();
prep_ret[3]["success"]["/lights/1/state/sat"] = 254;
- EXPECT_CALL(test_light, SendPutRequest(_, "/state", _)).Times(1).WillOnce(Return(prep_ret));
+ EXPECT_CALL(*handler, PUTJson(statePath, _, getBridgeIp(), getBridgePort())).Times(1).WillOnce(Return(prep_ret));
test_light.getState()["state"]["on"] = true;
test_light.getState()["state"]["sat"] = 100;
@@ -145,6 +151,8 @@ TEST(SimpleColorHueStrategy, setColorXY)
.WillRepeatedly(Return(nlohmann::json::object()));
MockHueLight test_light(handler);
+ const std::string statePath = "/api/" + getBridgeUsername() + "/lights/1/state";
+
nlohmann::json prep_ret;
prep_ret = nlohmann::json::array();
prep_ret[0] = nlohmann::json::object();
@@ -157,7 +165,7 @@ TEST(SimpleColorHueStrategy, setColorXY)
prep_ret[2]["success"] = nlohmann::json::object();
prep_ret[2]["success"]["/lights/1/state/xy"][0] = 0.2355;
prep_ret[2]["success"]["/lights/1/state/xy"][1] = 0.1234;
- EXPECT_CALL(test_light, SendPutRequest(_, "/state", _)).Times(1).WillOnce(Return(prep_ret));
+ EXPECT_CALL(*handler, PUTJson(statePath, _, getBridgeIp(), getBridgePort())).Times(1).WillOnce(Return(prep_ret));
test_light.getState()["state"]["on"] = true;
test_light.getState()["state"]["xy"][0] = 0.1f;
@@ -198,6 +206,8 @@ TEST(SimpleColorHueStrategy, setColorLoop)
.WillRepeatedly(Return(nlohmann::json::object()));
MockHueLight test_light(handler);
+ const std::string statePath = "/api/" + getBridgeUsername() + "/lights/1/state";
+
nlohmann::json prep_ret;
prep_ret = nlohmann::json::array();
prep_ret[0] = nlohmann::json::object();
@@ -206,7 +216,7 @@ TEST(SimpleColorHueStrategy, setColorLoop)
prep_ret[1] = nlohmann::json::object();
prep_ret[1]["success"] = nlohmann::json::object();
prep_ret[1]["success"]["/lights/1/state/effect"] = "colorloop";
- EXPECT_CALL(test_light, SendPutRequest(_, "/state", _)).Times(1).WillOnce(Return(prep_ret));
+ EXPECT_CALL(*handler, PUTJson(statePath, _, getBridgeIp(), getBridgePort())).Times(1).WillOnce(Return(prep_ret));
test_light.getState()["state"]["on"] = true;
test_light.getState()["state"]["effect"] = "colorloop";
diff --git a/test/test_SimpleColorTemperatureStrategy.cpp b/test/test_SimpleColorTemperatureStrategy.cpp
index 3385870..8d6c845 100644
--- a/test/test_SimpleColorTemperatureStrategy.cpp
+++ b/test/test_SimpleColorTemperatureStrategy.cpp
@@ -46,6 +46,8 @@ TEST(SimpleColorTemperatureStrategy, setColorTemperature)
.WillRepeatedly(Return(nlohmann::json::object()));
MockHueLight test_light(handler);
+ const std::string statePath = "/api/" + getBridgeUsername() + "/lights/1/state";
+
nlohmann::json prep_ret;
prep_ret = nlohmann::json::array();
prep_ret[0] = nlohmann::json::object();
@@ -57,21 +59,22 @@ TEST(SimpleColorTemperatureStrategy, setColorTemperature)
prep_ret[2] = nlohmann::json::object();
prep_ret[2]["success"] = nlohmann::json::object();
prep_ret[2]["success"]["/lights/1/state/ct"] = 155;
- EXPECT_CALL(test_light, SendPutRequest(_, "/state", _)).Times(1).WillOnce(Return(prep_ret));
+ EXPECT_CALL(*handler, PUTJson(statePath, _, getBridgeIp(), getBridgePort())).Times(1).WillOnce(Return(prep_ret));
test_light.getState()["state"]["on"] = true;
test_light.getState()["state"]["ct"] = 200;
+ test_light.getState()["state"]["colormode"] = "ct";
EXPECT_EQ(true, SimpleColorTemperatureStrategy().setColorTemperature(200, 4, test_light));
test_light.getState()["state"]["on"] = false;
EXPECT_EQ(true, SimpleColorTemperatureStrategy().setColorTemperature(155, 6, test_light));
- prep_ret[2]["success"]["/lights/1/state/ct"] = 153;
- EXPECT_CALL(test_light, SendPutRequest(_, "/state", _)).Times(1).WillOnce(Return(prep_ret));
+ prep_ret = {{{"success", {{"/lights/1/state/transitiontime", 6}}}}, {{"success", {{"/lights/1/state/ct", 153}}}}};
+ EXPECT_CALL(*handler, PUTJson(statePath, _, getBridgeIp(), getBridgePort())).Times(1).WillOnce(Return(prep_ret));
EXPECT_EQ(true, SimpleColorTemperatureStrategy().setColorTemperature(0, 6, test_light));
- prep_ret[2]["success"]["/lights/1/state/ct"] = 500;
- EXPECT_CALL(test_light, SendPutRequest(_, "/state", _)).Times(1).WillOnce(Return(prep_ret));
+ prep_ret[1]["success"]["/lights/1/state/ct"] = 500;
+ EXPECT_CALL(*handler, PUTJson(statePath, _, getBridgeIp(), getBridgePort())).Times(1).WillOnce(Return(prep_ret));
EXPECT_EQ(true, SimpleColorTemperatureStrategy().setColorTemperature(600, 6, test_light));
}