7#ifndef stateRuleEngine_indiCompRules_hpp
8#define stateRuleEngine_indiCompRules_hpp
13#include "../../libMagAOX/libMagAOX.hpp"
44 else if( cstr ==
"Neq" )
48 else if( cstr ==
"Lt" )
52 else if( cstr ==
"Gt" )
56 else if( cstr ==
"LtEq" )
60 else if( cstr ==
"GtEq" )
64 else if( cstr ==
"And" )
68 else if( cstr ==
"Nand" )
72 else if( cstr ==
"Or" )
76 else if( cstr ==
"Nor" )
80 else if( cstr ==
"Xor" )
84 else if( cstr ==
"Xnor" )
88 else if( cstr ==
"Imply" )
92 else if( cstr ==
"Nimply" )
98 throw mx::exception( mx::error_t::invalidarg, cstr +
" is not a valid comparison" );
134 throw mx::exception( mx::error_t::invalidarg,
"comparison is not valid" );
157 else if( pstr ==
"info" )
161 else if( pstr ==
"caution" )
165 else if( pstr ==
"warning" )
169 else if( pstr ==
"alert" )
175 throw mx::exception( mx::error_t::invalidarg, pstr +
" is not a valid priority" );
192 return ( rv.index() > 0 );
285 const std::string &
message(
bool settime =
false )
289 if( clock_gettime( CLOCK_ISIO, &
m_lastMsg ) < 0 )
291 throw mx::exception( mx::errno2error_t( errno ),
"getting message time" );
307 if( clock_gettime( CLOCK_ISIO, &ts ) < 0 )
309 throw mx::exception( mx::errno2error_t( errno ),
"getting current time" );
312 return ( 1.0 * ts.tv_sec + ts.tv_nsec / 1e9 ) - ( 1.0 *
m_lastMsg.tv_sec +
m_lastMsg.tv_nsec / 1e9 );
423 const std::string &str2
439 rv =
"operator not valid for string comparison";
453 const pcf::IndiElement::SwitchStateType &sw2
469 rv =
"operator not valid for switch comparison";
493 if( fabs( num1 - num2 ) <= tol )
497 if( fabs( num1 - num2 ) > tol )
509 if( fabs( num1 - num2 ) <= tol )
511 else if( num1 < num2 )
515 if( fabs( num1 - num2 ) <= tol )
517 else if( num1 > num2 )
521 rv =
"operator not valid for compNum";
576 rv =
"operator not valid for ruleCompRule";
612 throw mx::exception( mx::error_t::invalidarg,
"property is nullptr" );
617 throw mx::exception( mx::error_t::invalidconfig,
"property is not correct type" );
659 rv =
"property is null";
663 rv =
"element is not found";
705 if( property ==
nullptr )
707 throw mx::exception( mx::error_t::invalidarg,
"property is nullptr" );
710 if( property->getType() !=
m_type )
712 throw mx::exception( mx::error_t::invalidconfig,
"property is not correct type" );
749 if( property ==
nullptr )
751 throw mx::exception( mx::error_t::invalidarg,
"property is nullptr" );
754 if( property->getType() !=
m_type )
756 throw mx::exception( mx::error_t::invalidconfig,
"property is not correct type" );
799 rv =
"property1 is null";
805 rv =
"element1 is not found";
811 rv =
"property2 is null";
817 rv =
"element2 is not found";
835 static constexpr char name[] =
"numVal";
868 void tol(
const double &t )
872 throw mx::exception( mx::error_t::invalidarg,
"tolerance can't be negative" );
901 throw mx::exception( mx::error_t::invalidconfig, std::get<std::string>( rv ) );
904 double val = ( *m_property )[
m_element].get<
double>();
909 throw mx::exception( mx::error_t::invalidconfig, std::get<std::string>( rv ) );
912 return std::get<bool>( rv );
924 static constexpr char name[] =
"txtVal";
964 throw mx::exception( mx::error_t::invalidconfig, std::get<std::string>( rv ) );
970 throw mx::exception( mx::error_t::invalidconfig, std::get<std::string>( rv ) );
973 return std::get<bool>( rv );
985 static constexpr char name[] =
"swVal";
989 pcf::IndiElement::UnknownSwitchState };
998 void target(
const pcf::IndiElement::SwitchStateType &ss )
1008 void target(
const std::string &switchState )
1010 if( switchState ==
"On" )
1014 else if( switchState ==
"Off" )
1020 throw mx::exception( mx::error_t::invalidarg,
"invalid switch state" );
1028 const pcf::IndiElement::SwitchStateType &
target()
1047 throw mx::exception( mx::error_t::invalidconfig, std::get<std::string>( rv ) );
1053 throw mx::exception( mx::error_t::invalidconfig, std::get<std::string>( rv ) );
1056 return std::get<bool>( rv );
1068 static constexpr char name[] =
"timeDiff";
1105 throw mx::exception( mx::error_t::invalidarg,
"tolerance can't be negative" );
1134 throw mx::exception( mx::error_t::invalidconfig, std::get<std::string>( rv ) );
1138 clock_gettime( CLOCK_ISIO, &now );
1140 double val = ( 1.0 * now.tv_sec + now.tv_nsec / 1e9 ) - ( *
m_property )[
m_element].get<
double>();
1145 throw mx::exception( mx::error_t::invalidconfig, std::get<std::string>( rv ) );
1148 return std::get<bool>( rv );
1158 static constexpr char name[] =
"elCompNum";
1179 throw mx::exception( mx::error_t::invalidarg,
"tolerance can't be negative" );
1208 throw mx::exception( mx::error_t::invalidconfig, std::get<std::string>( rv ) );
1214 throw mx::exception( mx::error_t::invalidconfig, std::get<std::string>( rv ) );
1217 return std::get<bool>( rv );
1226 static constexpr char name[] =
"elCompTxt";
1247 throw mx::exception( mx::error_t::invalidconfig, std::get<std::string>( rv ) );
1253 throw mx::exception( mx::error_t::invalidconfig, std::get<std::string>( rv ) );
1256 return std::get<bool>( rv );
1266 static constexpr char name[] =
"elCompSw";
1287 throw mx::exception( mx::error_t::invalidconfig, std::get<std::string>( rv ) );
1293 throw mx::exception( mx::error_t::invalidconfig, std::get<std::string>( rv ) );
1296 return std::get<bool>( rv );
1312 static constexpr char name[] =
"multiSwitchCombo";
1345 invalidBraces =
false;
1348 for(
size_t n = 0; n <
m_format.size(); ++n )
1359 invalidBraces =
true;
1365 invalidBraces =
true;
1376 bool &multiOnLatched
1382 for(
auto &&el :
property->getElements() )
1384 if( el.second.getSwitchState() == pcf::IndiElement::On )
1397 multiOnLatched =
false;
1403 multiOnLatched =
false;
1407 if( !multiOnLatched )
1416 std::format(
"multiSwitchCombo rule {} found multiple switch elements On in {}; using empty string",
1421 multiOnLatched =
true;
1431 size_t valueIndex = 0;
1433 for(
size_t n = 0; n <
m_format.size(); ++n )
1437 combo += values[valueIndex];
1490 throw mx::exception( mx::error_t::invalidarg,
"property is nullptr" );
1493 if(
property->getType() != pcf::IndiProperty::Switch )
1495 throw mx::exception( mx::error_t::invalidconfig,
"property is not correct type" );
1511 throw mx::exception( mx::error_t::invalidarg,
"source property index out of range" );
1525 throw mx::exception( mx::error_t::invalidarg,
"source property key index out of range" );
1560 throw mx::exception( mx::error_t::invalidarg,
"targetProperty is nullptr" );
1563 if(
property->getType() != pcf::IndiProperty::Switch )
1565 throw mx::exception( mx::error_t::invalidconfig,
"targetProperty is not correct type" );
1600 return "no source switch properties configured";
1605 return "source switch configuration is inconsistent";
1612 return std::format(
"property{} is nullptr", n + 1 );
1615 if(
m_properties[n]->getType() != pcf::IndiProperty::Switch )
1617 return std::format(
"property{} is not a switch property", n + 1 );
1622 return std::format(
"property{} key is empty", n + 1 );
1628 return "targetProperty is nullptr";
1633 return "targetProperty is not a switch property";
1638 return "targetProperty key is empty";
1641 bool invalidBraces =
false;
1645 return "format only supports literal {} placeholders";
1651 "format placeholder count {} does not match numSwitches {}", placeholders,
m_properties.size() );
1656 return "operator not valid for multiSwitchComboRule";
1676 throw mx::exception( mx::error_t::invalidconfig, std::get<std::string>( rv ) );
1679 std::vector<std::string> activeNames;
1690 std::string comboName =
formatCombo( activeNames );
1694 rv =
compTxt( comboName, targetName );
1697 throw mx::exception( mx::error_t::invalidconfig, std::get<std::string>( rv ) );
1700 return std::get<bool>( rv );
1728 static constexpr char name[] =
"ruleComp";
1793 rv =
"rule1 is nullptr";
1797 rv =
"rule2 is nullptr";
1833 throw mx::exception( mx::error_t::invalidconfig, std::get<std::string>( rv ) );
1839 throw mx::exception( mx::error_t::invalidconfig, std::get<std::string>( rv ) );
1842 return std::get<bool>( rv );
std::string comp2string(const ruleComparison &comparison)
Get the string representation of a ruleComparison member.
ruleComparison
Logical comparisons for the INDI rules.
@ Xnor
boolean xnor, equivalent to equal
@ LtEq
Less than or equal to.
@ Xor
boolean xor, equivalent to not equal
@ GtEq
Greater than or equal to.
ruleComparison string2comp(const std::string &cstr)
Get the ruleComparison member from a string representation.
rulePriority string2priority(const std::string &pstr)
Get the rulePriority member from a string representation.
rulePriority
Reporting priorities for rules.
@ caution
Caution – make sure you know what you're doing.
@ warning
Warning – something is probably wrong, you should check.
@ alert
Alert – something is definitely wrong, you should take action.
@ info
For information only.
Compare two elements based on their numeric values.
virtual bool value()
Get the value of this rule.
const double & tol()
Get the tolerance.
double m_tol
The tolerance for the comparison.
elCompNumRule()
Default c'tor.
void tol(const double &t)
Set the tolerance.
static constexpr char name[]
Name of this rule, used by config system.
Compare two elements based on their switch values.
static constexpr char name[]
Name of this rule, used by config system.
elCompSwRule()
Default c'tor.
virtual bool value()
Get the value of this rule.
Compare two elements based on their text values.
virtual bool value()
Get the value of this rule.
elCompTxtRule()
Default c'tor.
static constexpr char name[]
Name of this rule, used by config system.
Virtual base-class for all rules.
static constexpr double default_alert_msg_delay
int m_messageCount
Number of times the message has been sent.
void messageCount(int mc)
Set the message count.
virtual ~indiCompRule()
Virtual destructor.
rulePriority m_priority
The reporting priority for this rule.
const timespec & lastMsg()
double m_messageDelay
Delay between sending messages.
virtual boolorerr_t valid()=0
Report whether the rule is valid as configured.
int messageCount()
Get the message count.
boolorerr_t compSw(const pcf::IndiElement::SwitchStateType &sw1, const pcf::IndiElement::SwitchStateType &sw2)
Compare two switches.
void messageDelay(double md)
Set the message delay.
bool timeToSend()
Check if it's time to send a message.
boolorerr_t compNum(const double &num1, const double &num2, const double &tol)
Compare two numbers.
virtual bool value()=0
Get the value of this rule.
std::variant< bool, std::string > boolorerr_t
In-band error reporting type.
boolorerr_t compTxt(const std::string &str1, const std::string &str2)
Compare two strings.
const ruleComparison & comparison()
Get the rule comparison.
timespec m_lastMsg
Time the message was last sent.
static constexpr double default_warning_msg_delay
void priority(const rulePriority &p, double delay=-1)
Set priority of this rule.
void comparison(const ruleComparison &c)
Set the comparison for this rule.
ruleComparison m_comparison
The comparison for this rule.
static constexpr double default_info_msg_delay
bool isError(boolorerr_t rv)
Check if returned value indicates an error.
virtual ruleComparison defaultComparison() const
Get the default comparison for this rule type.
std::string m_message
The message used for notifications.
virtual bool popRuntimeDiagnostic(std::string &diagnostic)
Pop one pending runtime diagnostic, if any.
const std::string & message(bool settime=false)
Get the message.
double messageDelay()
Get the message delay.
void message(const std::string &m)
Set the message.
const rulePriority & priority()
Get the rule priority.
boolorerr_t compBool(const bool &b1, const bool &b2)
Compare two booleans.
static constexpr double default_caution_msg_delay
double sinceLastMsg()
Get the time since the last message.
int incMessageCount()
Increment the message count.
Build and compare a switch-name combination against a target switch vector.
const std::string & format()
Get the literal format string.
std::vector< std::string > m_pendingDiagnostics
Runtime diagnostics that should be logged without failing evaluation.
std::vector< bool > m_multiOn
Per-source latch state used to avoid repeated multi-On diagnostics.
std::string m_ruleName
The configuration-section name of this rule, used in diagnostics.
const pcf::IndiProperty * targetProperty()
Get the target switch property.
const pcf::IndiProperty * property(size_t n)
Get a source switch property by index.
size_t formatPlaceholders(bool &invalidBraces) const
Count plain {} placeholders and reject any other brace usage.
std::vector< pcf::IndiProperty * > m_properties
The source switch properties in format-substitution order.
std::vector< std::string > m_propertyKeys
The config keys for the source switch properties, used in diagnostics.
std::string m_format
The literal format string used to combine source switch names.
const std::string & targetPropertyKey()
Get the target property key used in diagnostics.
const std::string & propertyKey(size_t n)
Get a source property key by index.
std::string activeName(pcf::IndiProperty *property, const std::string &propertyKey, bool &multiOnLatched)
Resolve the active element name for a switch property.
virtual ruleComparison defaultComparison() const
Get the default comparison for this rule type.
void targetProperty(pcf::IndiProperty *property)
Set the target switch property.
void property(pcf::IndiProperty *property, const std::string &propertyKey)
Append one source switch property.
virtual boolorerr_t valid()
Check if this rule is valid as configured.
static constexpr char name[]
Name of this rule, used by config system.
virtual bool popRuntimeDiagnostic(std::string &diagnostic)
Pop one pending runtime diagnostic, if any.
const std::string & ruleName()
Get the configured rule name.
std::string formatCombo(const std::vector< std::string > &values) const
Apply literal {} substitution to build the comparison string.
void format(const std::string &format)
Set the literal format string for the source switch names.
virtual bool value()
Get the value of this rule.
multiSwitchComboRule()
Default c'tor.
size_t numSwitches()
Get the number of configured source switch properties.
void targetPropertyKey(const std::string &propertyKey)
Set the target property key used in diagnostics.
std::string m_targetPropertyKey
The config key for the target property, used in diagnostics.
pcf::IndiProperty * m_targetProperty
The target switch property whose active element name is compared.
bool m_targetMultiOn
Latch state used to avoid repeated target multi-On diagnostics.
void ruleName(const std::string &ruleName)
Set the rule name used in diagnostics.
Compare the value of a number element to a target.
const double & target()
Get the target.
numValRule()
Default c'tor.
double m_tol
The tolerance for the comparison.
double m_target
The target value for comparison.
const double & tol()
Get the tolerance.
void target(const double &tgt)
Set the target for the comparison.
void tol(const double &t)
Set the tolerance.
virtual bool value()
Get the value of this rule.
static constexpr char name[]
Name of this rule, used by config system.
A rule base class for testing an element in one property.
const pcf::IndiProperty * property()
Get the property pointer.
std::string m_element
The element name within the property.
int m_type
The property type, from pcf::IndiProperty::Type.
onePropRule(int type)
Constructor. You must provide the property type to construct a onePropRule.
const std::string & element()
Get the element name.
void property(pcf::IndiProperty *property)
Set the property pointer.
void element(const std::string &el)
Set the element name.
pcf::IndiProperty * m_property
Pointer to the property.
virtual boolorerr_t valid()
Check if this rule is valid.
A rule to compare two rules.
ruleCompRule()
Default c'tor.
const indiCompRule * rule2()
Get the pointer to the first rule.
void rule2(indiCompRule *r)
Set the pointer to the second rule.
void rule1(indiCompRule *r)
Set the pointer to the first rule.
static constexpr char name[]
Name of this rule, used by config system.
indiCompRule * m_rule1
rule one
const indiCompRule * rule1()
Get the pointer to the first rule.
virtual ruleComparison defaultComparison() const
Get the default comparison for this rule type.
virtual boolorerr_t valid()
Check if this rule is valid.
virtual bool popRuntimeDiagnostic(std::string &diagnostic)
Pop one pending runtime diagnostic from either child rule.
virtual bool value()
Get the value of this rule.
indiCompRule * m_rule2
rule two
Compare the value of a switch to a target value.
virtual bool value()
Get the value of this rule.
void target(const pcf::IndiElement::SwitchStateType &ss)
Set the target for the comparison.
const pcf::IndiElement::SwitchStateType & target()
Get the target.
swValRule()
Default c'tor.
void target(const std::string &switchState)
Set the target for the comparison.
pcf::IndiElement::SwitchStateType m_target
The target value for comparison.
static constexpr char name[]
Name of this rule, used by config system.
Compare the difference in time between a value and now.
timeDiffRule()
Default c'tor.
static constexpr char name[]
Name of this rule, used by config system.
void target(const double &tgt)
Set the target for the comparison.
const double & target()
Get the target.
double m_tol
The tolerance for the comparison.
void tol(const double &t)
Set the tolerance.
const double & tol()
Get the tolerance.
virtual bool value()
Get the value of this rule.
double m_target
The target value for comparison.
A rule base class for testing elements in two properties.
int m_type
The property type, from pcf::IndiProperty::Type.
const std::string & element1()
Get the first element name.
void property1(pcf::IndiProperty *property)
Set the first property pointer.
virtual boolorerr_t valid()
Check if this rule is valid.
void element2(const std::string &el)
Set the second element name.
std::string m_element2
The element name within the second property.
twoPropRule(int type)
Constructor. You must provide the property type to construct a twoPropRule.
void element1(const std::string &el)
Set the first element name.
const pcf::IndiProperty * property2()
Get the second property pointer.
const std::string & element2()
Get the second element name.
void property2(pcf::IndiProperty *property)
Set the second property pointer.
std::string m_element1
The element name within the first property.
pcf::IndiProperty * m_property2
Pointer to the second property.
const pcf::IndiProperty * property1()
Get the first property pointer.
pcf::IndiProperty * m_property1
Pointer to the first property.
Compare the value of a text element to a target value.
void target(const std::string &target)
Set the target for the comparison.
static constexpr char name[]
Name of this rule, used by config system.
std::string m_target
The target value for comparison.
txtValRule()
Default c'tor.
virtual bool value()
Get the value of this rule.
const std::string & target()
Get the target.