Commit 59d03c52dd4eee0f30b7064b58e4bb9eb5117d5a

Authored by Jojo-1000
Committed by Moritz Wirger
1 parent 4a7edd72

Add group class for groups of HueLight.

include/hueplusplus/Group.h 0 → 100644
  1 +/**
  2 + \file Group.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_GROUP_H
  24 +#define INCLUDE_HUEPLUSPLUS_GROUP_H
  25 +
  26 +#include <string>
  27 +#include <vector>
  28 +
  29 +#include "APICache.h"
  30 +#include "HueCommandAPI.h"
  31 +
  32 +#include "json/json.hpp"
  33 +
  34 +namespace hueplusplus
  35 +{
  36 + class Group
  37 + {
  38 + public:
  39 + Group(int id, const HueCommandAPI& commands);
  40 +
  41 + virtual ~Group() = default;
  42 +
  43 + int getId() const;
  44 + std::string getName() const;
  45 + std::string getType() const;
  46 + std::vector<int> getLightIds() const;
  47 +
  48 + void setName(const std::string& name);
  49 + void setLights(const std::vector<int>& ids);
  50 +
  51 + std::string getRoomType() const;
  52 + void setRoomType(const std::string& type);
  53 +
  54 + bool getAllOn() const;
  55 + bool getAnyOn() const;
  56 +
  57 + bool getActionOn() const;
  58 + std::pair<uint16_t, uint8_t> getActionHueSaturation() const;
  59 + unsigned int getActionBrightness() const;
  60 + unsigned int getActionColorTemperature() const;
  61 + std::pair<float, float> getActionColorXY() const;
  62 + std::string getActionColorMode() const;
  63 +
  64 + void setOn(bool on, uint8_t transition = 4);
  65 + void setBrightness(uint8_t brightness, uint8_t transition = 4);
  66 + void setColorHueSaturation(uint16_t hue, uint8_t saturation, uint8_t transition = 4);
  67 + void setColorXY(float x, float y, uint8_t transition = 4);
  68 + void setColorTemperature(unsigned int mired, uint8_t transition = 4);
  69 + void setColorLoop(bool on, uint8_t transition = 4);
  70 + void incrementBrightness(int increment, uint8_t transition = 4);
  71 + void incrementSaturation(int increment, uint8_t transition = 4);
  72 + void incrementHue(int increment, uint8_t transition = 4);
  73 + void incrementColorTemperature(int increment, uint8_t transition = 4);
  74 + void incrementColorXY(float increment, uint8_t transition = 4);
  75 + void setScene(const std::string& scene, uint8_t transition = 4);
  76 + protected:
  77 + nlohmann::json SendPutRequest(const nlohmann::json& request, const std::string& subPath, FileInfo fileInfo);
  78 +
  79 + protected:
  80 + int id;
  81 + APICache state;
  82 + HueCommandAPI commands;
  83 + };
  84 +} // namespace hueplusplus
  85 +
  86 +#endif
0 87 \ No newline at end of file
... ...
src/CMakeLists.txt
... ... @@ -3,6 +3,7 @@ set(hueplusplus_SOURCES
3 3 BaseHttpHandler.cpp
4 4 ExtendedColorHueStrategy.cpp
5 5 ExtendedColorTemperatureStrategy.cpp
  6 + Group.cpp
6 7 Hue.cpp
7 8 HueCommandAPI.cpp
8 9 HueDeviceTypes.cpp
... ...
src/Group.cpp 0 → 100644
  1 +#include "hueplusplus/Group.h"
  2 +
  3 +#include "hueplusplus/HueExceptionMacro.h"
  4 +
  5 +hueplusplus::Group::Group(int id, const HueCommandAPI& commands)
  6 + : id(id), state("/groups/" + std::to_string(id), commands, std::chrono::seconds(10)), commands(commands)
  7 +{}
  8 +
  9 +int hueplusplus::Group::getId() const
  10 +{
  11 + return id;
  12 +}
  13 +
  14 +std::string hueplusplus::Group::getName() const
  15 +{
  16 + return state.GetValue().at("name").get<std::string>();
  17 +}
  18 +
  19 +std::string hueplusplus::Group::getType() const
  20 +{
  21 + return state.GetValue().at("type").get<std::string>();
  22 +}
  23 +
  24 +std::vector<int> hueplusplus::Group::getLightIds() const
  25 +{
  26 + const nlohmann::json& lights = state.GetValue().at("lights");
  27 + std::vector<int> ids(lights.size());
  28 + for (const nlohmann::json& id : lights)
  29 + {
  30 + ids.push_back(std::stoi(id.get<std::string>()));
  31 + }
  32 + return ids;
  33 +}
  34 +
  35 +void hueplusplus::Group::setName(const std::string& name)
  36 +{
  37 + nlohmann::json request = {{"name", name}};
  38 + SendPutRequest(request, "", CURRENT_FILE_INFO);
  39 +}
  40 +
  41 +void hueplusplus::Group::setLights(const std::vector<int>& ids)
  42 +{
  43 + nlohmann::json lights = nlohmann::json::array();
  44 + for (int id : ids)
  45 + {
  46 + lights.push_back(std::to_string(id));
  47 + }
  48 + SendPutRequest({{"lights", lights}}, "", CURRENT_FILE_INFO);
  49 +}
  50 +
  51 +bool hueplusplus::Group::getAllOn() const
  52 +{
  53 + return state.GetValue().at("state").at("all_on").get<bool>();
  54 +}
  55 +
  56 +bool hueplusplus::Group::getAnyOn() const
  57 +{
  58 + return state.GetValue().at("state").at("any_on").get<bool>();
  59 +}
  60 +
  61 +bool hueplusplus::Group::getActionOn() const
  62 +{
  63 + return state.GetValue().at("action").at("on").get<bool>();
  64 +}
  65 +
  66 +std::pair<uint16_t, uint8_t> hueplusplus::Group::getActionHueSaturation() const
  67 +{
  68 + const nlohmann::json& action = state.GetValue().at("action");
  69 +
  70 + return std::make_pair(action.at("hue").get<int>(), action.at("sat").get<int>());
  71 +}
  72 +
  73 +unsigned int hueplusplus::Group::getActionBrightness() const
  74 +{
  75 + return state.GetValue().at("action").at("bri").get<int>();
  76 +}
  77 +
  78 +unsigned int hueplusplus::Group::getActionColorTemperature() const
  79 +{
  80 + return state.GetValue().at("action").at("ct").get<int>();
  81 +}
  82 +
  83 +std::pair<float, float> hueplusplus::Group::getActionColorXY() const
  84 +{
  85 + const nlohmann::json& xy = state.GetValue().at("action").at("xy");
  86 + return std::pair<float, float>(xy[0].get<float>(), xy[1].get<float>());
  87 +}
  88 +
  89 +std::string hueplusplus::Group::getActionColorMode() const
  90 +{
  91 + return state.GetValue().at("action").at("colormode").get<std::string>();
  92 +}
  93 +
  94 +void hueplusplus::Group::setOn(bool on, uint8_t transition)
  95 +{
  96 + nlohmann::json request = {{"on", on}};
  97 + if (transition != 4)
  98 + {
  99 + request["transition"] = transition;
  100 + }
  101 + SendPutRequest(request, "/action", CURRENT_FILE_INFO);
  102 +}
  103 +
  104 +void hueplusplus::Group::setBrightness(uint8_t brightness, uint8_t transition)
  105 +{
  106 + // TODO: turn on/off
  107 + nlohmann::json request = {{"bri", brightness}};
  108 + if (transition != 4)
  109 + {
  110 + request["transition"] = transition;
  111 + }
  112 + SendPutRequest(request, "/action", CURRENT_FILE_INFO);
  113 +}
  114 +
  115 +void hueplusplus::Group::setColorHueSaturation(uint16_t hue, uint8_t saturation, uint8_t transition)
  116 +{
  117 + nlohmann::json request = {{"hue", hue}, {"sat", saturation}};
  118 + if (transition != 4)
  119 + {
  120 + request["transition"] = transition;
  121 + }
  122 + SendPutRequest(request, "/action", CURRENT_FILE_INFO);
  123 +}
  124 +
  125 +void hueplusplus::Group::setColorXY(float x, float y, uint8_t transition)
  126 +{
  127 + nlohmann::json request = {{"xy", {x, y}}};
  128 + if (transition != 4)
  129 + {
  130 + request["transition"] = transition;
  131 + }
  132 + SendPutRequest(request, "/action", CURRENT_FILE_INFO);
  133 +}
  134 +
  135 +void hueplusplus::Group::setColorTemperature(unsigned int mired, uint8_t transition)
  136 +{
  137 + nlohmann::json request = {{"ct", mired}};
  138 + if (transition != 4)
  139 + {
  140 + request["transition"] = transition;
  141 + }
  142 + SendPutRequest(request, "/action", CURRENT_FILE_INFO);
  143 +}
  144 +
  145 +void hueplusplus::Group::setColorLoop(bool on, uint8_t transition)
  146 +{
  147 + nlohmann::json request = {{"effect", on ? "colorloop" : "none"}};
  148 + if (transition != 4)
  149 + {
  150 + request["transition"] = transition;
  151 + }
  152 + SendPutRequest(request, "/action", CURRENT_FILE_INFO);
  153 +}
  154 +
  155 +void hueplusplus::Group::incrementBrightness(int increment, uint8_t transition)
  156 +{
  157 + nlohmann::json request = {{"bri_inc", increment}};
  158 + if (transition != 4)
  159 + {
  160 + request["transition"] = transition;
  161 + }
  162 + SendPutRequest(request, "/action", CURRENT_FILE_INFO);
  163 +}
  164 +
  165 +void hueplusplus::Group::incrementSaturation(int increment, uint8_t transition)
  166 +{
  167 + nlohmann::json request = {{"sat_inc", increment}};
  168 + if (transition != 4)
  169 + {
  170 + request["transition"] = transition;
  171 + }
  172 + SendPutRequest(request, "/action", CURRENT_FILE_INFO);
  173 +}
  174 +
  175 +void hueplusplus::Group::incrementHue(int increment, uint8_t transition)
  176 +{
  177 + nlohmann::json request = {{"hue_inc", increment}};
  178 + if (transition != 4)
  179 + {
  180 + request["transition"] = transition;
  181 + }
  182 + SendPutRequest(request, "/action", CURRENT_FILE_INFO);
  183 +}
  184 +
  185 +void hueplusplus::Group::incrementColorTemperature(int increment, uint8_t transition)
  186 +{
  187 + nlohmann::json request = {{"ct_inc", increment}};
  188 + if (transition != 4)
  189 + {
  190 + request["transition"] = transition;
  191 + }
  192 + SendPutRequest(request, "/action", CURRENT_FILE_INFO);
  193 +}
  194 +
  195 +void hueplusplus::Group::incrementColorXY(float increment, uint8_t transition)
  196 +{
  197 + nlohmann::json request = {{"xy_inc", increment}};
  198 + if (transition != 4)
  199 + {
  200 + request["transition"] = transition;
  201 + }
  202 + SendPutRequest(request, "/action", CURRENT_FILE_INFO);
  203 +}
  204 +
  205 +void hueplusplus::Group::setScene(const std::string& scene, uint8_t transition)
  206 +{
  207 + nlohmann::json request = {{"scene", scene}};
  208 + if (transition != 4)
  209 + {
  210 + request["transition"] = transition;
  211 + }
  212 + SendPutRequest(request, "/action", CURRENT_FILE_INFO);
  213 +}
  214 +
  215 +nlohmann::json hueplusplus::Group::SendPutRequest(
  216 + const nlohmann::json& request, const std::string& subPath, FileInfo fileInfo)
  217 +{
  218 + return commands.PUTRequest("/groups/" + std::to_string(id) + subPath, request, std::move(fileInfo));
  219 +}
  220 +
  221 +std::string hueplusplus::Group::getRoomType() const
  222 +{
  223 + return state.GetValue().at("class").get<std::string>();
  224 +}
  225 +
  226 +void hueplusplus::Group::setRoomType(const std::string& type)
  227 +{
  228 + SendPutRequest({{"class", type}}, "", CURRENT_FILE_INFO);
  229 +}
... ...
src/HueCommandAPI.cpp
... ... @@ -115,9 +115,15 @@ nlohmann::json HueCommandAPI::HandleError(FileInfo fileInfo, const nlohmann::jso
115 115 {
116 116 throw HueAPIResponseException::Create(std::move(fileInfo), response);
117 117 }
118   - else if (response.is_array() && response.size() > 0 && response[0].count("error"))
  118 + else if (response.is_array())
119 119 {
120   - throw HueAPIResponseException::Create(std::move(fileInfo), response[0]);
  120 + // Check if array contains error response
  121 + auto it
  122 + = std::find_if(response.begin(), response.end(), [](const nlohmann::json& v) { return v.count("error"); });
  123 + if (it != response.end())
  124 + {
  125 + throw HueAPIResponseException::Create(std::move(fileInfo), it.value());
  126 + }
121 127 }
122 128 return response;
123 129 }
... ...