Commit c6e6f5be3293ad55240cb51088c1eaca5493e00d
Committed by
Moritz Wirger
1 parent
c5123c13
Add helper functions for creating conditions from sensors.
Showing
9 changed files
with
262 additions
and
47 deletions
include/hueplusplus/CLIPSensors.h
| @@ -123,6 +123,8 @@ public: | @@ -123,6 +123,8 @@ public: | ||
| 123 | static constexpr const char* typeStr = "CLIPOpenClose"; | 123 | static constexpr const char* typeStr = "CLIPOpenClose"; |
| 124 | }; | 124 | }; |
| 125 | 125 | ||
| 126 | +detail::ConditionHelper<bool> makeCondition(const CLIPOpenClose& sensor); | ||
| 127 | + | ||
| 126 | //! \brief CLIP sensor to detect presence | 128 | //! \brief CLIP sensor to detect presence |
| 127 | class CLIPPresence : public BaseCLIP | 129 | class CLIPPresence : public BaseCLIP |
| 128 | { | 130 | { |
| @@ -187,6 +189,8 @@ public: | @@ -187,6 +189,8 @@ public: | ||
| 187 | static constexpr const char* typeStr = "CLIPHumidity"; | 189 | static constexpr const char* typeStr = "CLIPHumidity"; |
| 188 | }; | 190 | }; |
| 189 | 191 | ||
| 192 | +detail::ConditionHelper<int> makeCondition(const CLIPHumidity& sensor); | ||
| 193 | + | ||
| 190 | //! \brief CLIP sensor for light level | 194 | //! \brief CLIP sensor for light level |
| 191 | class CLIPLightLevel : public BaseCLIP | 195 | class CLIPLightLevel : public BaseCLIP |
| 192 | { | 196 | { |
| @@ -257,6 +261,8 @@ public: | @@ -257,6 +261,8 @@ public: | ||
| 257 | static constexpr const char* typeStr = "CLIPGenericFlag"; | 261 | static constexpr const char* typeStr = "CLIPGenericFlag"; |
| 258 | }; | 262 | }; |
| 259 | 263 | ||
| 264 | +detail::ConditionHelper<bool> makeCondition(const CLIPGenericFlag& sensor); | ||
| 265 | + | ||
| 260 | //! \brief CLIP sensor for a generic 3rd party status | 266 | //! \brief CLIP sensor for a generic 3rd party status |
| 261 | //! | 267 | //! |
| 262 | //! Can be created by POST. | 268 | //! Can be created by POST. |
| @@ -278,6 +284,9 @@ public: | @@ -278,6 +284,9 @@ public: | ||
| 278 | //! \brief CLIPGenericStatus sensor type name | 284 | //! \brief CLIPGenericStatus sensor type name |
| 279 | static constexpr const char* typeStr = "CLIPGenericStatus"; | 285 | static constexpr const char* typeStr = "CLIPGenericStatus"; |
| 280 | }; | 286 | }; |
| 287 | + | ||
| 288 | +detail::ConditionHelper<int> makeCondition(const CLIPGenericStatus& sensor); | ||
| 289 | + | ||
| 281 | } // namespace sensors | 290 | } // namespace sensors |
| 282 | } // namespace hueplusplus | 291 | } // namespace hueplusplus |
| 283 | 292 |
include/hueplusplus/Condition.h
0 → 100644
| 1 | +/** | ||
| 2 | + \file ConditionHelper.h | ||
| 3 | + Copyright Notice\n | ||
| 4 | + Copyright (C) 2020 Jan Rogall - developer\n | ||
| 5 | + | ||
| 6 | + This file is part of hueplusplus. | ||
| 7 | + | ||
| 8 | + hueplusplus is free software: you can redistribute it and/or modify | ||
| 9 | + it under the terms of the GNU Lesser General Public License as published by | ||
| 10 | + the Free Software Foundation, either version 3 of the License, or | ||
| 11 | + (at your option) any later version. | ||
| 12 | + | ||
| 13 | + hueplusplus is distributed in the hope that it will be useful, | ||
| 14 | + but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 15 | + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 16 | + GNU Lesser General Public License for more details. | ||
| 17 | + | ||
| 18 | + You should have received a copy of the GNU Lesser General Public License | ||
| 19 | + along with hueplusplus. If not, see <http://www.gnu.org/licenses/>. | ||
| 20 | +**/ | ||
| 21 | + | ||
| 22 | +#ifndef INCLUDE_HUEPLUSPLUS_CONDITION_H | ||
| 23 | +#define INCLUDE_HUEPLUSPLUS_CONDITION_H | ||
| 24 | + | ||
| 25 | +#include "TimePattern.h" | ||
| 26 | + | ||
| 27 | +#include "json/json.hpp" | ||
| 28 | + | ||
| 29 | +namespace hueplusplus | ||
| 30 | +{ | ||
| 31 | + | ||
| 32 | +class Condition | ||
| 33 | +{ | ||
| 34 | +public: | ||
| 35 | + //! \brief Specifies which operation is used to check the condition | ||
| 36 | + enum class Operator | ||
| 37 | + { | ||
| 38 | + eq, //!< Attribute is equal to specified value (for bool and int) | ||
| 39 | + gt, //!< Attribute is greater than specified value (for int) | ||
| 40 | + lt, //!< Attribute is less than specified value (for int) | ||
| 41 | + dx, //!< Attribute has changed (no value given) | ||
| 42 | + ddx, //!< Delayed attribute has changed (no value given) | ||
| 43 | + stable, //!< Stable for a given time. Does not trigger a rule change | ||
| 44 | + notStable, //!< Not stable for a given time. Does not trigger a rule change | ||
| 45 | + in, //!< Time is in the given interval (triggered on start time, local time) | ||
| 46 | + notIn //!< Time is not in the interval (triggered on end time, local time) | ||
| 47 | + }; | ||
| 48 | + | ||
| 49 | +public: | ||
| 50 | + //! \brief Create a condition from any address on the bridge | ||
| 51 | + Condition(const std::string& address, Operator op, const std::string& value); | ||
| 52 | + | ||
| 53 | + std::string getAddress() const; | ||
| 54 | + Operator getOperator() const; | ||
| 55 | + std::string getValue() const; | ||
| 56 | + | ||
| 57 | + nlohmann::json toJson() const; | ||
| 58 | + | ||
| 59 | + static Condition parse(const nlohmann::json& json); | ||
| 60 | + | ||
| 61 | +private: | ||
| 62 | + std::string address; | ||
| 63 | + Operator op; | ||
| 64 | + std::string value; | ||
| 65 | +}; | ||
| 66 | + | ||
| 67 | +namespace detail | ||
| 68 | +{ | ||
| 69 | +template <typename T> | ||
| 70 | +class ConditionHelper | ||
| 71 | +{ }; | ||
| 72 | + | ||
| 73 | +//! General operators supported by all data types | ||
| 74 | +class GeneralConditionHelper | ||
| 75 | +{ | ||
| 76 | +public: | ||
| 77 | + explicit GeneralConditionHelper(const std::string& address) : address(address) { } | ||
| 78 | + | ||
| 79 | + Condition dx() { return Condition(address, Condition::Operator::dx, ""); } | ||
| 80 | + Condition ddx() { return Condition(address, Condition::Operator::ddx, ""); } | ||
| 81 | + //! Docs does not say anything about format of stable value | ||
| 82 | + //! \todo Change to either duration or int for seconds | ||
| 83 | + Condition stable(const std::string& value) { return Condition(address, Condition::Operator::dx, value); } | ||
| 84 | + | ||
| 85 | +protected: | ||
| 86 | + std::string address; | ||
| 87 | +}; | ||
| 88 | + | ||
| 89 | +//! Operators supported by int conditions | ||
| 90 | +template <> | ||
| 91 | +class ConditionHelper<int> : public GeneralConditionHelper | ||
| 92 | +{ | ||
| 93 | +public: | ||
| 94 | + using GeneralConditionHelper::GeneralConditionHelper; | ||
| 95 | + | ||
| 96 | + Condition eq(int value) { return create(Condition::Operator::eq, value); } | ||
| 97 | + Condition gt(int value) { return create(Condition::Operator::gt, value); } | ||
| 98 | + Condition lt(int value) { return create(Condition::Operator::eq, value); } | ||
| 99 | + | ||
| 100 | + Condition create(Condition::Operator op, int value) { return Condition(address, op, std::to_string(value)); } | ||
| 101 | +}; | ||
| 102 | + | ||
| 103 | +//! Operators supported by bool conditions | ||
| 104 | +template <> | ||
| 105 | +class ConditionHelper<bool> : public GeneralConditionHelper | ||
| 106 | +{ | ||
| 107 | +public: | ||
| 108 | + using GeneralConditionHelper::GeneralConditionHelper; | ||
| 109 | + | ||
| 110 | + Condition eq(bool value) { return create(Condition::Operator::eq, value); } | ||
| 111 | + | ||
| 112 | + Condition create(Condition::Operator op, bool value) { return Condition(address, op, value ? "true" : "false"); } | ||
| 113 | +}; | ||
| 114 | + | ||
| 115 | +//! Operators supported by timestamp conditions | ||
| 116 | +template <> | ||
| 117 | +class ConditionHelper<time::AbsoluteTime> : public GeneralConditionHelper | ||
| 118 | +{ | ||
| 119 | +public: | ||
| 120 | + using GeneralConditionHelper::GeneralConditionHelper; | ||
| 121 | + | ||
| 122 | + Condition in(const time::TimeInterval& interval) { return create(Condition::Operator::in, interval); } | ||
| 123 | + Condition notIn(const time::TimeInterval& interval) { return create(Condition::Operator::notIn, interval); } | ||
| 124 | + | ||
| 125 | + Condition create(Condition::Operator op, const time::AbsoluteTime& value) | ||
| 126 | + { | ||
| 127 | + return Condition(address, op, value.toString()); | ||
| 128 | + } | ||
| 129 | + Condition create(Condition::Operator op, const time::TimeInterval& interval) | ||
| 130 | + { | ||
| 131 | + return Condition(address, op, interval.toString()); | ||
| 132 | + } | ||
| 133 | +}; | ||
| 134 | + | ||
| 135 | +template <typename... Ts> | ||
| 136 | +struct make_void | ||
| 137 | +{ | ||
| 138 | + typedef void type; | ||
| 139 | +}; | ||
| 140 | +template <typename... Ts> | ||
| 141 | +using void_t = typename make_void<Ts...>::type; | ||
| 142 | + | ||
| 143 | +} // namespace detail | ||
| 144 | + | ||
| 145 | +} // namespace hueplusplus | ||
| 146 | + | ||
| 147 | +#endif |
include/hueplusplus/Rule.h
| @@ -26,46 +26,13 @@ | @@ -26,46 +26,13 @@ | ||
| 26 | 26 | ||
| 27 | #include "APICache.h" | 27 | #include "APICache.h" |
| 28 | #include "Action.h" | 28 | #include "Action.h" |
| 29 | +#include "Condition.h" | ||
| 29 | #include "HueCommandAPI.h" | 30 | #include "HueCommandAPI.h" |
| 30 | #include "TimePattern.h" | 31 | #include "TimePattern.h" |
| 31 | 32 | ||
| 32 | namespace hueplusplus | 33 | namespace hueplusplus |
| 33 | { | 34 | { |
| 34 | 35 | ||
| 35 | -class Condition | ||
| 36 | -{ | ||
| 37 | -public: | ||
| 38 | - //! \brief Specifies which operation is used to check the condition | ||
| 39 | - enum class Operator | ||
| 40 | - { | ||
| 41 | - eq, //!< Attribute is equal to specified value (for bool and int) | ||
| 42 | - gt, //!< Attribute is greater than specified value (for int) | ||
| 43 | - lt, //!< Attribute is less than specified value (for int) | ||
| 44 | - dx, //!< Attribute has changed (no value given) | ||
| 45 | - ddx, //!< Delayed attribute has changed (no value given) | ||
| 46 | - stable, //!< Stable for a given time | ||
| 47 | - not_stable, //!< Not stable for a given time | ||
| 48 | - in, //!< Time is in the given interval (triggered on start time) | ||
| 49 | - not_in //!< Time is not in the interval (triggered on end time) | ||
| 50 | - }; | ||
| 51 | - | ||
| 52 | -public: | ||
| 53 | - Condition(const std::string& address, Operator op, const std::string& value); | ||
| 54 | - | ||
| 55 | - std::string getAddress() const; | ||
| 56 | - Operator getOperator() const; | ||
| 57 | - std::string getValue() const; | ||
| 58 | - | ||
| 59 | - nlohmann::json toJson() const; | ||
| 60 | - | ||
| 61 | - static Condition parse(const nlohmann::json& json); | ||
| 62 | - | ||
| 63 | -private: | ||
| 64 | - std::string address; | ||
| 65 | - Operator op; | ||
| 66 | - std::string value; | ||
| 67 | -}; | ||
| 68 | - | ||
| 69 | class Rule | 36 | class Rule |
| 70 | { | 37 | { |
| 71 | public: | 38 | public: |
include/hueplusplus/Sensor.h
| @@ -26,6 +26,7 @@ | @@ -26,6 +26,7 @@ | ||
| 26 | #include <memory> | 26 | #include <memory> |
| 27 | 27 | ||
| 28 | #include "BaseDevice.h" | 28 | #include "BaseDevice.h" |
| 29 | +#include "Condition.h" | ||
| 29 | #include "HueCommandAPI.h" | 30 | #include "HueCommandAPI.h" |
| 30 | #include "TimePattern.h" | 31 | #include "TimePattern.h" |
| 31 | 32 | ||
| @@ -183,6 +184,11 @@ public: | @@ -183,6 +184,11 @@ public: | ||
| 183 | //! The state can usually only be set on CLIP sensors, not on physical devices. | 184 | //! The state can usually only be set on CLIP sensors, not on physical devices. |
| 184 | void setStateAttribute(const std::string& key, const nlohmann::json& value); | 185 | void setStateAttribute(const std::string& key, const nlohmann::json& value); |
| 185 | 186 | ||
| 187 | + //! \brief Get address of the given state attribute, used for conditions | ||
| 188 | + //! \param key Key in the state object | ||
| 189 | + //! \returns \c key prefixed with the path to the sensor state | ||
| 190 | + std::string getStateAddress(const std::string& key) const; | ||
| 191 | + | ||
| 186 | //! \brief Check if the sensor is Hue certified | 192 | //! \brief Check if the sensor is Hue certified |
| 187 | bool isCertified() const; | 193 | bool isCertified() const; |
| 188 | //! \brief Check if the sensor is primary sensor of the device | 194 | //! \brief Check if the sensor is primary sensor of the device |
| @@ -345,6 +351,36 @@ public: | @@ -345,6 +351,36 @@ public: | ||
| 345 | static constexpr const char* typeStr = "Daylight"; | 351 | static constexpr const char* typeStr = "Daylight"; |
| 346 | }; | 352 | }; |
| 347 | 353 | ||
| 354 | +detail::ConditionHelper<bool> makeCondition(const DaylightSensor& sensor); | ||
| 355 | + | ||
| 356 | +template <typename SensorT, detail::void_t<decltype(std::declval<const SensorT>().getLastUpdated())>* = nullptr> | ||
| 357 | +detail::ConditionHelper<time::AbsoluteTime> makeConditionLastUpdate(const SensorT& sensor) | ||
| 358 | +{ | ||
| 359 | + return detail::ConditionHelper<time::AbsoluteTime>( | ||
| 360 | + "/sensors/" + std::to_string(sensor.getId()) + "/state/lastupdated"); | ||
| 361 | +} | ||
| 362 | + | ||
| 363 | +template <typename ButtonSensor, detail::void_t<decltype(std::declval<const ButtonSensor>().getButtonEvent())>* = nullptr> | ||
| 364 | +detail::ConditionHelper<int> makeCondition(const ButtonSensor& sensor) | ||
| 365 | +{ | ||
| 366 | + return detail::ConditionHelper<int>( | ||
| 367 | + "/sensors/" + std::to_string(sensor.getId()) + "/state/buttonevent"); | ||
| 368 | +} | ||
| 369 | + | ||
| 370 | +template <typename PresenceSensor, detail::void_t<decltype(std::declval<const PresenceSensor>().getPresence())>* = nullptr> | ||
| 371 | +detail::ConditionHelper<bool> makeCondition(const PresenceSensor& sensor) | ||
| 372 | +{ | ||
| 373 | + return detail::ConditionHelper<bool>( | ||
| 374 | + "/sensors/" + std::to_string(sensor.getId()) + "/state/presence"); | ||
| 375 | +} | ||
| 376 | + | ||
| 377 | +template <typename TemperatureSensor, detail::void_t<decltype(std::declval<const TemperatureSensor>().getPresence())>* = nullptr> | ||
| 378 | +detail::ConditionHelper<int> makeCondition(const TemperatureSensor& sensor) | ||
| 379 | +{ | ||
| 380 | + return detail::ConditionHelper<int>( | ||
| 381 | + "/sensors/" + std::to_string(sensor.getId()) + "/state/temperature"); | ||
| 382 | +} | ||
| 383 | + | ||
| 348 | } // namespace sensors | 384 | } // namespace sensors |
| 349 | 385 | ||
| 350 | } // namespace hueplusplus | 386 | } // namespace hueplusplus |
include/hueplusplus/ZLLSensors.h
| @@ -319,6 +319,10 @@ public: | @@ -319,6 +319,10 @@ public: | ||
| 319 | //! \brief ZLLLightLevel sensor type name | 319 | //! \brief ZLLLightLevel sensor type name |
| 320 | static constexpr const char* typeStr = "ZLLLightLevel"; | 320 | static constexpr const char* typeStr = "ZLLLightLevel"; |
| 321 | }; | 321 | }; |
| 322 | + | ||
| 323 | +detail::ConditionHelper<bool> makeConditionDark(const ZLLLightLevel& sensor); | ||
| 324 | +detail::ConditionHelper<bool> makeConditionDaylight(const ZLLLightLevel& sensor); | ||
| 325 | +detail::ConditionHelper<int> makeConditionLightLevel(const ZLLLightLevel& sensor); | ||
| 322 | } // namespace sensors | 326 | } // namespace sensors |
| 323 | } // namespace hueplusplus | 327 | } // namespace hueplusplus |
| 324 | 328 |
src/CLIPSensors.cpp
| @@ -99,6 +99,12 @@ void CLIPOpenClose::setOpen(bool open) | @@ -99,6 +99,12 @@ void CLIPOpenClose::setOpen(bool open) | ||
| 99 | sendPutRequest("/state", nlohmann::json {{"open", open}}, CURRENT_FILE_INFO); | 99 | sendPutRequest("/state", nlohmann::json {{"open", open}}, CURRENT_FILE_INFO); |
| 100 | } | 100 | } |
| 101 | 101 | ||
| 102 | + | ||
| 103 | +detail::ConditionHelper<bool> makeCondition(const CLIPOpenClose& sensor) | ||
| 104 | +{ | ||
| 105 | + return detail::ConditionHelper<bool>("/sensors/" + std::to_string(sensor.getId()) + "/state/open"); | ||
| 106 | +} | ||
| 107 | + | ||
| 102 | constexpr const char* CLIPPresence::typeStr; | 108 | constexpr const char* CLIPPresence::typeStr; |
| 103 | 109 | ||
| 104 | bool CLIPPresence::getPresence() const | 110 | bool CLIPPresence::getPresence() const |
| @@ -132,6 +138,11 @@ void CLIPHumidity::setHumidity(int humidity) | @@ -132,6 +138,11 @@ void CLIPHumidity::setHumidity(int humidity) | ||
| 132 | sendPutRequest("/state", nlohmann::json {{"humidity", humidity}}, CURRENT_FILE_INFO); | 138 | sendPutRequest("/state", nlohmann::json {{"humidity", humidity}}, CURRENT_FILE_INFO); |
| 133 | } | 139 | } |
| 134 | 140 | ||
| 141 | +detail::ConditionHelper<int> makeCondition(const CLIPHumidity& sensor) | ||
| 142 | +{ | ||
| 143 | + return detail::ConditionHelper<int>("/sensors/" + std::to_string(sensor.getId()) + "/state/humidity"); | ||
| 144 | +} | ||
| 145 | + | ||
| 135 | constexpr const char* CLIPLightLevel::typeStr; | 146 | constexpr const char* CLIPLightLevel::typeStr; |
| 136 | 147 | ||
| 137 | int CLIPLightLevel::getDarkThreshold() const | 148 | int CLIPLightLevel::getDarkThreshold() const |
| @@ -184,6 +195,11 @@ void CLIPGenericFlag::setFlag(bool flag) | @@ -184,6 +195,11 @@ void CLIPGenericFlag::setFlag(bool flag) | ||
| 184 | sendPutRequest("/state", nlohmann::json {{"flag", flag}}, CURRENT_FILE_INFO); | 195 | sendPutRequest("/state", nlohmann::json {{"flag", flag}}, CURRENT_FILE_INFO); |
| 185 | } | 196 | } |
| 186 | 197 | ||
| 198 | +detail::ConditionHelper<bool> makeCondition(const CLIPGenericFlag& sensor) | ||
| 199 | +{ | ||
| 200 | + return detail::ConditionHelper<bool>("/sensors/" + std::to_string(sensor.getId()) + "/state/flag"); | ||
| 201 | +} | ||
| 202 | + | ||
| 187 | constexpr const char* CLIPGenericStatus::typeStr; | 203 | constexpr const char* CLIPGenericStatus::typeStr; |
| 188 | 204 | ||
| 189 | int CLIPGenericStatus::getStatus() const | 205 | int CLIPGenericStatus::getStatus() const |
| @@ -195,5 +211,10 @@ void CLIPGenericStatus::setStatus(int status) | @@ -195,5 +211,10 @@ void CLIPGenericStatus::setStatus(int status) | ||
| 195 | { | 211 | { |
| 196 | sendPutRequest("/state", nlohmann::json {{"status", status}}, CURRENT_FILE_INFO); | 212 | sendPutRequest("/state", nlohmann::json {{"status", status}}, CURRENT_FILE_INFO); |
| 197 | } | 213 | } |
| 214 | + | ||
| 215 | +detail::ConditionHelper<int> makeCondition(const CLIPGenericStatus& sensor) | ||
| 216 | +{ | ||
| 217 | + return detail::ConditionHelper<int>("/sensors/" + std::to_string(sensor.getId()) + "/state/status"); | ||
| 218 | +} | ||
| 198 | } // namespace sensors | 219 | } // namespace sensors |
| 199 | } // namespace hueplusplus | 220 | } // namespace hueplusplus |
| 200 | \ No newline at end of file | 221 | \ No newline at end of file |
src/Rule.cpp
| @@ -19,6 +19,7 @@ | @@ -19,6 +19,7 @@ | ||
| 19 | along with hueplusplus. If not, see <http://www.gnu.org/licenses/>. | 19 | along with hueplusplus. If not, see <http://www.gnu.org/licenses/>. |
| 20 | **/ | 20 | **/ |
| 21 | 21 | ||
| 22 | +#include <hueplusplus/HueExceptionMacro.h> | ||
| 22 | #include <hueplusplus/Rule.h> | 23 | #include <hueplusplus/Rule.h> |
| 23 | 24 | ||
| 24 | namespace hueplusplus | 25 | namespace hueplusplus |
| @@ -62,14 +63,14 @@ nlohmann::json Condition::toJson() const | @@ -62,14 +63,14 @@ nlohmann::json Condition::toJson() const | ||
| 62 | case Operator::stable: | 63 | case Operator::stable: |
| 63 | opStr = "stable"; | 64 | opStr = "stable"; |
| 64 | break; | 65 | break; |
| 65 | - case Operator::not_stable: | ||
| 66 | - opStr = "eq"; | 66 | + case Operator::notStable: |
| 67 | + opStr = "not stable"; | ||
| 67 | break; | 68 | break; |
| 68 | case Operator::in: | 69 | case Operator::in: |
| 69 | - opStr = "eq"; | 70 | + opStr = "in"; |
| 70 | break; | 71 | break; |
| 71 | - case Operator::not_in: | ||
| 72 | - opStr = "eq"; | 72 | + case Operator::notIn: |
| 73 | + opStr = "not in"; | ||
| 73 | break; | 74 | break; |
| 74 | } | 75 | } |
| 75 | 76 | ||
| @@ -107,17 +108,21 @@ Condition Condition::parse(const nlohmann::json& json) | @@ -107,17 +108,21 @@ Condition Condition::parse(const nlohmann::json& json) | ||
| 107 | { | 108 | { |
| 108 | op = Operator::stable; | 109 | op = Operator::stable; |
| 109 | } | 110 | } |
| 110 | - else if (opStr == "not_stable") | 111 | + else if (opStr == "not stable") |
| 111 | { | 112 | { |
| 112 | - op = Operator::not_stable; | 113 | + op = Operator::notStable; |
| 113 | } | 114 | } |
| 114 | else if (opStr == "in") | 115 | else if (opStr == "in") |
| 115 | { | 116 | { |
| 116 | op = Operator::in; | 117 | op = Operator::in; |
| 117 | } | 118 | } |
| 118 | - else if (opStr == "not_in") | 119 | + else if (opStr == "not in") |
| 120 | + { | ||
| 121 | + op = Operator::notIn; | ||
| 122 | + } | ||
| 123 | + else | ||
| 119 | { | 124 | { |
| 120 | - op = Operator::not_in; | 125 | + throw HueException("Unknown condition operator: " + opStr, CURRENT_FILE_INFO); |
| 121 | } | 126 | } |
| 122 | 127 | ||
| 123 | return Condition(address, op, value); | 128 | return Condition(address, op, value); |
| @@ -185,9 +190,9 @@ std::vector<Condition> Rule::getConditions() const | @@ -185,9 +190,9 @@ std::vector<Condition> Rule::getConditions() const | ||
| 185 | return result; | 190 | return result; |
| 186 | } | 191 | } |
| 187 | 192 | ||
| 188 | -std::vector<ScheduleCommand> Rule::getActions() const | 193 | +std::vector<Action> Rule::getActions() const |
| 189 | { | 194 | { |
| 190 | - std::vector<ScheduleCommand> result; | 195 | + std::vector<Action> result; |
| 191 | const nlohmann::json& actions = state.getValue().at("actions"); | 196 | const nlohmann::json& actions = state.getValue().at("actions"); |
| 192 | for (const nlohmann::json& a : actions) | 197 | for (const nlohmann::json& a : actions) |
| 193 | { | 198 | { |
src/Sensor.cpp
| @@ -203,6 +203,11 @@ void Sensor::setStateAttribute(const std::string& key, const nlohmann::json& val | @@ -203,6 +203,11 @@ void Sensor::setStateAttribute(const std::string& key, const nlohmann::json& val | ||
| 203 | sendPutRequest("/state", nlohmann::json {{key, value}}, CURRENT_FILE_INFO); | 203 | sendPutRequest("/state", nlohmann::json {{key, value}}, CURRENT_FILE_INFO); |
| 204 | } | 204 | } |
| 205 | 205 | ||
| 206 | +std::string Sensor::getStateAddress(const std::string& key) const | ||
| 207 | +{ | ||
| 208 | + return path + "/state/" + key; | ||
| 209 | +} | ||
| 210 | + | ||
| 206 | nlohmann::json Sensor::getConfig() const | 211 | nlohmann::json Sensor::getConfig() const |
| 207 | { | 212 | { |
| 208 | return state.getValue().at("config"); | 213 | return state.getValue().at("config"); |
| @@ -270,7 +275,7 @@ bool DaylightSensor::isOn() const | @@ -270,7 +275,7 @@ bool DaylightSensor::isOn() const | ||
| 270 | 275 | ||
| 271 | void DaylightSensor::setOn(bool on) | 276 | void DaylightSensor::setOn(bool on) |
| 272 | { | 277 | { |
| 273 | - sendPutRequest("/config", { {"on", on} }, CURRENT_FILE_INFO); | 278 | + sendPutRequest("/config", {{"on", on}}, CURRENT_FILE_INFO); |
| 274 | } | 279 | } |
| 275 | 280 | ||
| 276 | bool DaylightSensor::hasBatteryState() const | 281 | bool DaylightSensor::hasBatteryState() const |
| @@ -333,9 +338,15 @@ time::AbsoluteTime DaylightSensor::getLastUpdated() const | @@ -333,9 +338,15 @@ time::AbsoluteTime DaylightSensor::getLastUpdated() const | ||
| 333 | auto it = stateJson.find("lastupdated"); | 338 | auto it = stateJson.find("lastupdated"); |
| 334 | if (it == stateJson.end() || !it->is_string() || *it == "none") | 339 | if (it == stateJson.end() || !it->is_string() || *it == "none") |
| 335 | { | 340 | { |
| 336 | - return time::AbsoluteTime(std::chrono::system_clock::time_point(std::chrono::seconds{ 0 })); | 341 | + return time::AbsoluteTime(std::chrono::system_clock::time_point(std::chrono::seconds {0})); |
| 337 | } | 342 | } |
| 338 | return time::AbsoluteTime::parseUTC(it->get<std::string>()); | 343 | return time::AbsoluteTime::parseUTC(it->get<std::string>()); |
| 339 | } | 344 | } |
| 345 | + | ||
| 346 | +detail::ConditionHelper<bool> makeCondition(const DaylightSensor& sensor) | ||
| 347 | +{ | ||
| 348 | + return detail::ConditionHelper<bool>("/sensors/" + std::to_string(sensor.getId()) + "/state/daylight"); | ||
| 349 | +} | ||
| 350 | + | ||
| 340 | } // namespace sensors | 351 | } // namespace sensors |
| 341 | } // namespace hueplusplus | 352 | } // namespace hueplusplus |
src/ZLLSensors.cpp
| @@ -293,5 +293,20 @@ time::AbsoluteTime ZLLLightLevel::getLastUpdated() const | @@ -293,5 +293,20 @@ time::AbsoluteTime ZLLLightLevel::getLastUpdated() const | ||
| 293 | } | 293 | } |
| 294 | return time::AbsoluteTime::parseUTC(it->get<std::string>()); | 294 | return time::AbsoluteTime::parseUTC(it->get<std::string>()); |
| 295 | } | 295 | } |
| 296 | + | ||
| 297 | +detail::ConditionHelper<bool> makeConditionDark(const ZLLLightLevel& sensor) | ||
| 298 | +{ | ||
| 299 | + return detail::ConditionHelper<bool>("/sensors/" + std::to_string(sensor.getId()) + "/state/dark"); | ||
| 300 | +} | ||
| 301 | + | ||
| 302 | +detail::ConditionHelper<bool> makeConditionDaylight(const ZLLLightLevel& sensor) | ||
| 303 | +{ | ||
| 304 | + return detail::ConditionHelper<bool>("/sensors/" + std::to_string(sensor.getId()) + "/state/daylight"); | ||
| 305 | +} | ||
| 306 | + | ||
| 307 | +detail::ConditionHelper<int> makeConditionLightLevel(const ZLLLightLevel& sensor) | ||
| 308 | +{ | ||
| 309 | + return detail::ConditionHelper<int>("/sensors/" + std::to_string(sensor.getId()) + "/state/lightlevel"); | ||
| 310 | +} | ||
| 296 | } // namespace sensors | 311 | } // namespace sensors |
| 297 | } // namespace hueplusplus | 312 | } // namespace hueplusplus |
| 298 | \ No newline at end of file | 313 | \ No newline at end of file |