/** \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()) { assert(currentState.is_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 (!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; } else if(request.value("bri", 254) == 0 && state.value("on", true)) { // Turn off if brightness is 0 request["on"] = false; } } 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::setColorXY(float x, float y) && { float clampedX = std::max(0.f, std::min(x, 1.f)); float clampedY = std::max(0.f, std::min(y, 1.f)); if (!state.count("xy") || !state.count("colormode") || !state["xy"].is_array() || !utils::floatEquals(state["xy"][0].get(), clampedX) || !utils::floatEquals(state["xy"][1].get(), clampedY) || state["colormode"] != "xy") { request["xy"] = {clampedX, clampedY}; } 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::max(-0.5f, std::min(xInc, 0.5f)), std::max(-0.5f, std::min(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