Commit 3719728f5637054c27831ee9889470afe8c5b987

Authored by Jojo-1000
Committed by Moritz Wirger
1 parent 1f966e6e

Implement generic sensor.

include/hueplusplus/CLIPSensors.h
... ... @@ -28,20 +28,9 @@ namespace hueplusplus
28 28 {
29 29 namespace sensors
30 30 {
31   -class CLIPSwitch : public BaseDevice
  31 +class BaseCLIP : public BaseDevice
32 32 {
33 33 public:
34   - CLIPSwitch(Sensor sensor) : BaseDevice(std::move(sensor)) { }
35   -
36   - int getButtonEvent() const;
37   -
38   - static constexpr const char* typeStr = "CLIPSwitch";
39   -};
40   -class CLIPOpenClose : public BaseDevice
41   -{
42   -public:
43   - CLIPOpenClose(Sensor sensor) : BaseDevice(std::move(sensor)) { }
44   -
45 34 bool isOn() const;
46 35 void setOn(bool on);
47 36  
... ... @@ -55,100 +44,65 @@ public:
55 44 std::string getURL() const;
56 45 void setURL(const std::string& url);
57 46  
58   - bool isOpen() const;
59   -
60 47 time::AbsoluteTime getLastUpdated() const;
61   -
62   - static constexpr const char* typeStr = "CLIPOpenClose";
  48 +protected:
  49 + BaseCLIP(Sensor sensor) : BaseDevice(std::move(sensor)) { }
63 50 };
  51 +class CLIPSwitch : public BaseCLIP
  52 +{
  53 +public:
  54 + CLIPSwitch(Sensor sensor) : BaseCLIP(std::move(sensor)) { }
  55 +
  56 + int getButtonEvent() const;
  57 + void setButtonEvent(int code);
64 58  
65   -class CLIPPresence : public BaseDevice
  59 + static constexpr const char* typeStr = "CLIPSwitch";
  60 +};
  61 +class CLIPOpenClose : public BaseCLIP
66 62 {
67 63 public:
68   - bool isOn() const;
69   - void setOn(bool on);
  64 + CLIPOpenClose(Sensor sensor) : BaseCLIP(std::move(sensor)) { }
70 65  
71   - bool hasBattery() const;
72   - int getBatteryState() const;
73   - void setBatteryState(int percent);
  66 + bool isOpen() const;
74 67  
75   - bool isReachable() const;
  68 + static constexpr const char* typeStr = "CLIPOpenClose";
  69 +};
76 70  
77   - bool hasURL() const;
78   - std::string getURL() const;
79   - void setURL(const std::string& url);
  71 +class CLIPPresence : public BaseCLIP
  72 +{
  73 +public:
  74 + CLIPPresence(Sensor sensor) : BaseCLIP(std::move(sensor)) { }
80 75  
81 76 bool getPresence() const;
82 77 void setPresence(bool presence);
83 78  
84   - time::AbsoluteTime getLastUpdated() const;
85   -
86 79 static constexpr const char* typeStr = "CLIPPresence";
87 80 };
88 81  
89   -class CLIPTemperature : public BaseDevice
  82 +class CLIPTemperature : public BaseCLIP
90 83 {
91 84 public:
92   - CLIPTemperature(Sensor sensor) : BaseDevice(std::move(sensor)) { }
93   -
94   - bool isOn() const;
95   - void setOn(bool on);
96   -
97   - bool hasBattery() const;
98   - int getBatteryState() const;
99   - void setBatteryState(int percent);
100   -
101   - bool isReachable() const;
102   -
103   - bool hasURL() const;
104   - std::string getURL() const;
105   - void setURL(const std::string& url);
  85 + CLIPTemperature(Sensor sensor) : BaseCLIP(std::move(sensor)) { }
106 86  
107 87 int getTemperature() const;
108 88 void setTemperature(int temperature);
109 89  
110   - time::AbsoluteTime getLastUpdated() const;
111   -
112 90 static constexpr const char* typeStr = "CLIPTemperature";
113 91 };
114   -class CLIPHumidity : public BaseDevice
  92 +class CLIPHumidity : public BaseCLIP
115 93 {
116 94 public:
117   - CLIPHumidity(Sensor sensor) : BaseDevice(std::move(sensor)) { }
118   -
119   - bool isOn() const;
120   - void setOn(bool on);
121   -
122   - bool hasBattery() const;
123   - int getBatteryState() const;
124   - void setBatteryState(int percent);
125   -
126   - bool isReachable() const;
127   -
128   - bool hasURL() const;
129   - std::string getURL() const;
130   - void setURL(const std::string& url);
  95 + CLIPHumidity(Sensor sensor) : BaseCLIP(std::move(sensor)) { }
131 96  
132 97 int getHumidity() const;
133 98 void setHumidity(int humidity);
134 99  
135   - time::AbsoluteTime getLastUpdated() const;
136   -
137 100 static constexpr const char* typeStr = "CLIPHumidity";
138 101 };
139   -class CLIPLightLevel : public BaseDevice
  102 +class CLIPLightLevel : public BaseCLIP
140 103 {
141 104 public:
142   - CLIPLightLevel(Sensor sensor) : BaseDevice(std::move(sensor)) { }
143   -
144   - bool isOn() const;
145   - void setOn(bool on);
146   -
147   - bool hasBattery() const;
148   - int getBatteryState() const;
149   - void setBatteryState(int percent);
150   -
151   - bool isReachable() const;
  105 + CLIPLightLevel(Sensor sensor) : BaseCLIP(std::move(sensor)) { }
152 106  
153 107 int getDarkThreshold() const;
154 108 void setDarkThreshold(int threshold);
... ... @@ -156,10 +110,6 @@ public:
156 110 int getThresholdOffset() const;
157 111 void setThresholdOffset(int offset);
158 112  
159   - bool hasURL() const;
160   - std::string getURL() const;
161   - void setURL(const std::string& url);
162   -
163 113 void setLightLevel(int level);
164 114 int getLightLevel() const;
165 115 bool isDark() const;
... ... @@ -167,46 +117,20 @@ public:
167 117  
168 118 static constexpr const char* typeStr = "CLIPLightLevel";
169 119 };
170   -class CLIPGenericFlag : public BaseDevice
  120 +class CLIPGenericFlag : public BaseCLIP
171 121 {
172 122 public:
173   - CLIPGenericFlag(Sensor sensor) : BaseDevice(std::move(sensor)) { }
174   -
175   - bool isOn() const;
176   - void setOn(bool on);
177   -
178   - bool hasBattery() const;
179   - int getBatteryState() const;
180   - void setBatteryState(int percent);
181   -
182   - bool isReachable() const;
183   -
184   - bool hasURL() const;
185   - std::string getURL() const;
186   - void setURL(const std::string& url);
  123 + CLIPGenericFlag(Sensor sensor) : BaseCLIP(std::move(sensor)) { }
187 124  
188 125 bool getFlag() const;
189 126 void setFlag(bool flag);
190 127  
191 128 static constexpr const char* typeStr = "CLIPGenericFlag";
192 129 };
193   -class CLIPGenericStatus : public BaseDevice
  130 +class CLIPGenericStatus : public BaseCLIP
194 131 {
195 132 public:
196   - CLIPGenericStatus(Sensor sensor) : BaseDevice(std::move(sensor)) { }
197   -
198   - bool isOn() const;
199   - void setOn(bool on);
200   -
201   - bool hasBattery() const;
202   - int getBatteryState() const;
203   - void setBatteryState(int percent);
204   -
205   - bool isReachable() const;
206   -
207   - bool hasURL() const;
208   - std::string getURL() const;
209   - void setURL(const std::string& url);
  133 + CLIPGenericStatus(Sensor sensor) : BaseCLIP(std::move(sensor)) { }
210 134  
211 135 int getStatus() const;
212 136 void setStatus(int status);
... ...
include/hueplusplus/Sensor.h
... ... @@ -32,6 +32,12 @@
32 32  
33 33 namespace hueplusplus
34 34 {
  35 +enum class Alert
  36 +{
  37 + none,
  38 + select,
  39 + lselect
  40 +};
35 41 //!
36 42 //! Generic class for Hue sensors
37 43 //!
... ... @@ -51,11 +57,11 @@ public:
51 57 bool hasBatteryState() const;
52 58 // Battery state in percent
53 59 int getBatteryState() const;
54   - bool isReachable() const;
  60 + void setBatteryState(int percent);
55 61  
56 62 bool hasAlert() const;
57   - std::string getLastAlert() const;
58   - void sendAlert(const std::string& alert);
  63 + Alert getLastAlert() const;
  64 + void sendAlert(Alert type);
59 65  
60 66 bool hasReachable() const;
61 67 bool isReachable() const;
... ... @@ -76,7 +82,7 @@ public:
76 82 void setLEDIndication(bool on);
77 83  
78 84 nlohmann::json getState() const;
79   - time::AbsoluteTime getLastUpdated() const;
  85 + void setStateAttribute(const std::string& key, const nlohmann::json& value);
80 86  
81 87 bool isCertified() const;
82 88 bool isPrimary() const;
... ...
include/hueplusplus/ZLLSensors.h
... ... @@ -28,13 +28,6 @@ namespace hueplusplus
28 28 {
29 29 namespace sensors
30 30 {
31   -enum class Alert
32   -{
33   - none,
34   - select,
35   - lselect
36   -};
37   -
38 31 class ZGPSwitch : public BaseDevice
39 32 {
40 33 public:
... ...
src/Sensor.cpp
... ... @@ -21,54 +21,168 @@
21 21  
22 22 #include "hueplusplus/Sensor.h"
23 23  
  24 +#include "hueplusplus/HueExceptionMacro.h"
  25 +#include "hueplusplus/Utils.h"
24 26 #include "json/json.hpp"
25 27  
26 28 namespace hueplusplus
27 29 {
28   -int Sensor::getButtonEvent()
  30 +bool Sensor::hasOn() const
29 31 {
30   - if (hasButtonEvent())
  32 + return state.getValue().at("config").count("on") != 0;
  33 +}
  34 +
  35 +bool Sensor::isOn() const
  36 +{
  37 + return state.getValue().at("config").at("on").get<bool>();
  38 +}
  39 +
  40 +void Sensor::setOn(bool on)
  41 +{
  42 + sendPutRequest("/config", {"on", on}, CURRENT_FILE_INFO);
  43 +}
  44 +
  45 +bool Sensor::hasBatteryState() const
  46 +{
  47 + return state.getValue().at("config").count("battery") != 0;
  48 +}
  49 +int Sensor::getBatteryState() const
  50 +{
  51 + return state.getValue().at("config").at("battery").get<int>();
  52 +}
  53 +void Sensor::setBatteryState(int percent)
  54 +{
  55 + sendPutRequest("/config", nlohmann::json {{"battery", percent}}, CURRENT_FILE_INFO);
  56 +}
  57 +bool Sensor::hasAlert() const
  58 +{
  59 + return state.getValue().at("config").count("alert") != 0;
  60 +}
  61 +Alert Sensor::getLastAlert() const
  62 +{
  63 + std::string alert = state.getValue().at("config").at("alert").get<std::string>();
  64 + if (alert == "select")
31 65 {
32   - return state.getValue().at("state").at("buttonevent");
  66 + return Alert::select;
  67 + }
  68 + else if (alert == "lselect")
  69 + {
  70 + return Alert::lselect;
  71 + }
  72 + else
  73 + {
  74 + return Alert::none;
33 75 }
34   - return 0;
35 76 }
36   -
37   -int Sensor::getButtonEvent() const
  77 +void Sensor::sendAlert(Alert type)
38 78 {
39   - if (hasButtonEvent())
  79 + std::string alertStr;
  80 + switch (type)
40 81 {
41   - return state.getValue().at("state").at("buttonevent");
  82 + case Alert::lselect:
  83 + alertStr = "lselect";
  84 + break;
  85 + case Alert::select:
  86 + alertStr = "select";
  87 + break;
  88 + default:
  89 + alertStr = "none";
  90 + break;
42 91 }
43   - return 0;
  92 + sendPutRequest("/state", nlohmann::json {{"alert", alertStr}}, CURRENT_FILE_INFO);
  93 +}
  94 +bool Sensor::hasReachable() const
  95 +{
  96 + return state.getValue().at("config").count("reachable") != 0;
  97 +}
  98 +bool Sensor::isReachable() const
  99 +{
  100 + // If not present, always assume it is reachable (for daylight sensor)
  101 + return state.getValue().at("config").value("reachable", true);
44 102 }
45 103  
46   -int Sensor::getStatus()
  104 +time::AbsoluteTime Sensor::getLastUpdated() const
47 105 {
48   - if (hasStatus())
  106 + const nlohmann::json& stateJson = state.getValue().at("state");
  107 + auto it = stateJson.find("lastupdated");
  108 + if (it == stateJson.end() || !it->is_string() || *it == "none")
49 109 {
50   - return state.getValue().at("state").at("status");
  110 + return time::AbsoluteTime(std::chrono::system_clock::time_point(std::chrono::seconds {0}));
51 111 }
52   - return 0;
  112 + return time::AbsoluteTime::parseUTC(it->get<std::string>());
53 113 }
54 114  
55   -int Sensor::getStatus() const
  115 +bool Sensor::hasUserTest() const
56 116 {
57   - if (hasStatus())
  117 + return state.getValue().at("config").count("usertest") != 0;
  118 +}
  119 +void Sensor::setUserTest(bool enabled)
  120 +{
  121 + sendPutRequest("/config", nlohmann::json {{"usertest", enabled}}, CURRENT_FILE_INFO);
  122 +}
  123 +
  124 +bool Sensor::hasURL() const
  125 +{
  126 + return state.getValue().at("config").count("url") != 0;
  127 +}
  128 +std::string Sensor::getURL() const
  129 +{
  130 + return state.getValue().at("config").at("url").get<std::string>();
  131 +}
  132 +void Sensor::setURL(const std::string& url)
  133 +{
  134 + sendPutRequest("/config", nlohmann::json {{"url", url}}, CURRENT_FILE_INFO);
  135 +}
  136 +
  137 +std::vector<std::string> Sensor::getPendingConfig() const
  138 +{
  139 + const nlohmann::json& config = state.getValue().at("config");
  140 + const auto pendingIt = config.find("pending");
  141 + if (pendingIt == config.end() || !pendingIt->is_array())
  142 + {
  143 + return {};
  144 + }
  145 + std::vector<std::string> result;
  146 + result.reserve(pendingIt->size());
  147 + for (const nlohmann::json& pending : *pendingIt)
58 148 {
59   - return state.getValue().at("state").at("status");
  149 + result.push_back(pending.get<std::string>());
60 150 }
61   - return 0;
  151 + return result;
  152 +}
  153 +
  154 +bool Sensor::hasLEDIndication() const
  155 +{
  156 + return state.getValue().at("config").count("ledindication") != 0;
  157 +}
  158 +bool Sensor::getLEDIndication() const
  159 +{
  160 + return state.getValue().at("config").at("ledindication").get<bool>();
  161 +}
  162 +void Sensor::setLEDIndication(bool on)
  163 +{
  164 + sendPutRequest("/config", nlohmann::json {{"ledindication", on}}, CURRENT_FILE_INFO);
  165 +}
  166 +
  167 +nlohmann::json Sensor::getState() const
  168 +{
  169 + return state.getValue().at("state");
  170 +}
  171 +void Sensor::setStateAttribute(const std::string& key, const nlohmann::json& value)
  172 +{
  173 + sendPutRequest("/state", nlohmann::json {{"key", value}}, CURRENT_FILE_INFO);
62 174 }
63 175  
64   -bool Sensor::hasButtonEvent() const
  176 +bool Sensor::isCertified() const
65 177 {
66   - return state.getValue().at("state").count("buttonevent") != 0;
  178 + nlohmann::json certified = utils::safeGetMember(state.getValue(), "capabilities", "certified");
  179 + return certified.is_boolean() && certified.get<bool>();
67 180 }
68 181  
69   -bool Sensor::hasStatus() const
  182 +bool Sensor::isPrimary() const
70 183 {
71   - return state.getValue().at("state").count("status") != 0;
  184 + nlohmann::json primary = utils::safeGetMember(state.getValue(), "capabilities", "primary");
  185 + return primary.is_boolean() && primary.get<bool>();
72 186 }
73 187  
74 188 Sensor::Sensor(int id, const HueCommandAPI& commands, std::chrono::steady_clock::duration refreshDuration)
... ...