OpenRGB/dependencies/hueplusplus-1.2.0/include/hueplusplus/Condition.h
2025-02-14 23:16:53 -06:00

168 lines
5.8 KiB
C++

/**
\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 <nlohmann/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