Condition.h
5.79 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
/**
\file Condition.h
Copyright Notice\n
Copyright (C) 2020 Jan Rogall - 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 <http://www.gnu.org/licenses/>.
**/
#ifndef INCLUDE_HUEPLUSPLUS_CONDITION_H
#define INCLUDE_HUEPLUSPLUS_CONDITION_H
#include "TimePattern.h"
#include "json/json.hpp"
namespace hueplusplus
{
//! \brief Condition for a Rule
//!
//! The condition checks whether a resource attribute (usually a Sensor value) matches the
//! specified Operator.
//!
//! Conditions from sensors can be created more easily using the makeCondition() helper functions.
class Condition
{
public:
//! \brief Specifies which operation is used to check the condition
enum class Operator
{
eq, //!< Attribute is equal to specified value (for bool and int)
gt, //!< Attribute is greater than specified value (for int)
lt, //!< Attribute is less than specified value (for int)
dx, //!< Attribute has changed (no value given)
ddx, //!< Delayed attribute has changed (no value given)
stable, //!< Stable for a given time. Does not trigger a rule change
notStable, //!< Not stable for a given time. Does not trigger a rule change
in, //!< Time is in the given interval (triggered on start time, local time)
notIn //!< Time is not in the interval (triggered on end time, local time)
};
public:
//! \brief Create a condition from any address on the bridge
//! \param address Path to an attribute of the bridge
//! \param op Operator used for comparison.
//! \param value String representation of the value to check against. Empty for some operators.
Condition(const std::string& address, Operator op, const std::string& value);
//! \brief Get address on the bridge
std::string getAddress() const;
//! \brief Get used operator
Operator getOperator() const;
//! \brief Get value the attribute is checked against
std::string getValue() const;
//! \brief Create the json form of the condition
//! \returns A json object with address, operator and value
nlohmann::json toJson() const;
//! \brief Parse condition from json value
//! \param json Json object with address, operator and value
//! \returns The parsed condition with the same values
//! \throws HueException when the operator is unknown.
static Condition parse(const nlohmann::json& json);
private:
std::string address;
Operator op;
std::string value;
};
namespace detail
{
//! Helper class to make creating conditions more convenient.
//! Specializations for each data type provide methods for the supported operators.
//! This allows the user to write <code>makeCondition(sensor).eq(value)</code>
template <typename T>
class ConditionHelper
{ };
//! General operators supported by all data types
class GeneralConditionHelper
{
public:
explicit GeneralConditionHelper(const std::string& address) : address(address) { }
Condition dx() { return Condition(address, Condition::Operator::dx, ""); }
Condition ddx() { return Condition(address, Condition::Operator::ddx, ""); }
//! Docs does not say anything about format of stable value
//! \todo Change to either duration or int for seconds
Condition stable(const std::string& value) { return Condition(address, Condition::Operator::dx, value); }
protected:
std::string address;
};
//! Operators supported by int conditions
template <>
class ConditionHelper<int> : public GeneralConditionHelper
{
public:
using GeneralConditionHelper::GeneralConditionHelper;
Condition eq(int value) { return create(Condition::Operator::eq, value); }
Condition gt(int value) { return create(Condition::Operator::gt, value); }
Condition lt(int value) { return create(Condition::Operator::eq, value); }
Condition create(Condition::Operator op, int value) { return Condition(address, op, std::to_string(value)); }
};
//! Operators supported by bool conditions
template <>
class ConditionHelper<bool> : public GeneralConditionHelper
{
public:
using GeneralConditionHelper::GeneralConditionHelper;
Condition eq(bool value) { return create(Condition::Operator::eq, value); }
Condition create(Condition::Operator op, bool value) { return Condition(address, op, value ? "true" : "false"); }
};
//! Operators supported by timestamp conditions
template <>
class ConditionHelper<time::AbsoluteTime> : public GeneralConditionHelper
{
public:
using GeneralConditionHelper::GeneralConditionHelper;
Condition in(const time::TimeInterval& interval) { return create(Condition::Operator::in, interval); }
Condition notIn(const time::TimeInterval& interval) { return create(Condition::Operator::notIn, interval); }
Condition create(Condition::Operator op, const time::AbsoluteTime& value)
{
return Condition(address, op, value.toString());
}
Condition create(Condition::Operator op, const time::TimeInterval& interval)
{
return Condition(address, op, interval.toString());
}
};
template <typename... Ts>
struct make_void
{
typedef void type;
};
//! c++17 void_t
template <typename... Ts>
using void_t = typename make_void<Ts...>::type;
} // namespace detail
} // namespace hueplusplus
#endif