Have working monitorlink expressions

pull/3530/head
Isaac Connor 2022-07-14 17:25:51 -04:00
parent e4bd2d351a
commit 1798d95b8b
6 changed files with 134 additions and 57 deletions

@ -1 +1 @@
Subproject commit 1b40f1661f93f50fd5805f239d1e466a3bcf888f Subproject commit eab32851421ffe54fec0229c3efc44c642bc8d46

View File

@ -307,6 +307,7 @@ public:
bool isAlarmed(); bool isAlarmed();
bool inAlarm(); bool inAlarm();
bool hasAlarmed(); bool hasAlarmed();
int score();
}; };
protected: protected:

View File

@ -157,7 +157,7 @@ bool Monitor::MonitorLink::connect() {
return true; return true;
} }
return false; return connected;
} // end bool Monitor::MonitorLink::connect() } // end bool Monitor::MonitorLink::connect()
bool Monitor::MonitorLink::disconnect() { bool Monitor::MonitorLink::disconnect() {
@ -214,17 +214,21 @@ bool Monitor::MonitorLink::inAlarm() {
return( shared_data->state == ALARM || shared_data->state == ALERT ); return( shared_data->state == ALARM || shared_data->state == ALERT );
} }
bool Monitor::MonitorLink::hasAlarmed() { int Monitor::MonitorLink::score() {
if (zone_id and (zone_index >= 0)) { if (zone_id and (zone_index >= 0)) {
Debug(1, "Checking zone %u, zone_index is %d, score is %d", zone_id, zone_index, zone_scores[zone_index]); Debug(1, "Checking zone %u, zone_index is %d, score is %d", zone_id, zone_index, zone_scores[zone_index]);
if (zone_scores[zone_index] > 0) { return zone_scores[zone_index];
return true;
}
} }
if (shared_data->state == ALARM) { if (shared_data->state == ALARM) {
Debug(1, "State is %d", shared_data->state); Debug(1, "Checking all zones score is %d", shared_data->last_frame_score);
return true; return shared_data->last_frame_score;
} }
Debug(1, "not alarmed. %d", shared_data->state);
return 0;
}
bool Monitor::MonitorLink::hasAlarmed() {
return this->score() > 0;
last_event_id = shared_data->last_event_id; last_event_id = shared_data->last_event_id;
return false; return false;
} }

View File

@ -60,30 +60,35 @@ bool MonitorLinkExpression::evaluate() {
Warning("%s", std::string(result.message).c_str()); Warning("%s", std::string(result.message).c_str());
return false; return false;
} }
return true; return result.score > 0;
} }
MonitorLinkExpression::result MonitorLinkExpression::result
MonitorLinkExpression::visit(Node const & node) { MonitorLinkExpression::visit(Node const & node) {
Debug(1, "visit: Node: %p", &node); Debug(1, "visit: Node: %p Token: %d value %s",
//Debug(1, "visit: Node: left %p right: %p", node.left, node.right); &node,
static_cast<int>(node.token.type()),
std::string(node.token.value()).c_str()
);
if (node.token.type() == Token::TokenType::monitorlink) { if (node.token.type() == Token::TokenType::monitorlink) {
return { true, node.token.value() }; Debug(1, "Have monitorlink, return true, value");
return { true, "", node.token.score() };
} else if (nullptr == node.left || nullptr == node.right) { } else if (nullptr == node.left || nullptr == node.right) {
return { false, "Missing operand" }; return { false, "Missing operand", 0 };
} }
Debug(1, "Token: %d", static_cast<int>(node.token.type()));
Debug(1, "Token: value %s", std::string(node.token.value()).c_str());
switch ( node.token.type() ) { switch (node.token.type()) {
case Token::TokenType::logical_and: case Token::TokenType::logical_and:
Debug(1, "and");
return visit_logical_and(node); return visit_logical_and(node);
case Token::TokenType::logical_or : case Token::TokenType::logical_or :
Debug(1, "or"); Debug(1, "or");
return visit_logical_or(node);
case Token::TokenType::logical_comma : case Token::TokenType::logical_comma :
Debug(1, "comma"); Debug(1, "comma");
return visit_logical_or(node); return visit_logical_or(node);
default: default:
Debug(1, "unknown");
return { false, "Unknown token type" }; return { false, "Unknown token type" };
} }
} }
@ -99,7 +104,10 @@ MonitorLinkExpression::visit_logical_and(MonitorLinkExpression::Node const & nod
left.message.empty() ? right.message : left.message left.message.empty() ? right.message : left.message
}; };
return { left.success && right.success, message }; Debug(1, "aND left score %d right score %d", left.score, right.score);
return { left.success && right.success, message,
((left.score and right.score) ? left.score + right.score : 0)
};
} }
MonitorLinkExpression::result MonitorLinkExpression::result
@ -113,7 +121,12 @@ MonitorLinkExpression::visit_logical_or(MonitorLinkExpression::Node const & node
left.message.empty() ? right.message : left.message left.message.empty() ? right.message : left.message
}; };
return { left.success || right.success, message }; Debug(1, "Or left score %d right score %d", left.score, right.score);
return {
left.success || right.success,
message,
((left.score or right.score) ? left.score + right.score : 0)
};
} }
std::unique_ptr<MonitorLinkExpression::Node> std::unique_ptr<MonitorLinkExpression::Node>
@ -126,12 +139,8 @@ MonitorLinkExpression::parse_expression( Tokens const & tokens, std::size_t & cu
// First token could me a parenthesis or monitorlink. Otherwise invalid. // First token could me a parenthesis or monitorlink. Otherwise invalid.
//auto left{ std::make_unique<Node>(tokens[current]) }; auto left{ parse_and_operation(tokens, current) };
//if ( tokens[current].is(
//parse_and_operation(tokens, current) };
/*
if ( if (
has_unused(tokens, current) has_unused(tokens, current)
and and
@ -142,24 +151,34 @@ MonitorLinkExpression::parse_expression( Tokens const & tokens, std::size_t & cu
Debug(1, "parse_expression: not or, Returning left %s", std::string(left->token.value()).c_str()); Debug(1, "parse_expression: not or, Returning left %s", std::string(left->token.value()).c_str());
return left; return left;
} }
*/
std::unique_ptr<MonitorLinkExpression::Node> left; /*
if (tokens[current].is(Token::TokenType::monitorlink)) { if (tokens[current].is(Token::TokenType::monitorlink)) {
Debug(1, "Left is a monitorlink");
left = std::make_unique<Node>(tokens[current]); left = std::make_unique<Node>(tokens[current]);
current++; current++;
} else { } else {
Debug(1, "Left is not a monitorlink, parsing and");
left = parse_and_operation(tokens, current); left = parse_and_operation(tokens, current);
// invalid // invalid
//return nullptr; //return nullptr;
} }
*/
while (has_unused(tokens, current) && tokens[ current ].is( Token::TokenType::logical_or )) { while (has_unused(tokens, current) and
(
tokens[current].is(Token::TokenType::logical_or)
or
tokens[current].is(Token::TokenType::logical_comma)
)
) {
Debug(1, "Have or adding it");
auto logical_or{ std::make_unique<Node>( Token::TokenType::logical_or ) }; auto logical_or{ std::make_unique<Node>( Token::TokenType::logical_or ) };
current++;
auto right{ parse_and_operation( tokens, current ) }; auto right{ parse_and_operation( tokens, current ) };
if ( right == nullptr ) { if (right == nullptr) {
Debug(1, "null from right side"); Debug(1, "null from right side");
return nullptr; return nullptr;
} }
@ -208,8 +227,11 @@ MonitorLinkExpression::parse_and_operation( Tokens const & tokens, std::size_t &
} }
std::unique_ptr<MonitorLinkExpression::Node> std::unique_ptr<MonitorLinkExpression::Node>
MonitorLinkExpression::parse_parentheses(Tokens const & tokens, std::size_t & current) { MonitorLinkExpression::parse_parentheses(Tokens const &tokens, std::size_t &current) {
if (!has_unused(tokens, current)) return nullptr; if (!has_unused(tokens, current)) {
Debug(1, "No unused...");
return nullptr;
}
if (tokens[current].is(Token::TokenType::lp)) { if (tokens[current].is(Token::TokenType::lp)) {
++current; ++current;
@ -221,6 +243,11 @@ MonitorLinkExpression::parse_parentheses(Tokens const & tokens, std::size_t & cu
if (tokens[ current++ ].is(Token::TokenType::rp)) { if (tokens[ current++ ].is(Token::TokenType::rp)) {
return expression; return expression;
} }
} else if (tokens[current].is(Token::TokenType::monitorlink)) {
Debug(1, "Have monitorlink, returning it");
auto link {std::make_unique<Node>(tokens[current])};
current++;
return link;
} }
return nullptr; return nullptr;

View File

@ -66,6 +66,7 @@ class MonitorLinkExpression {
* Message in case of the fault. * Message in case of the fault.
*/ */
std::string_view message{}; std::string_view message{};
int score {-1};
}; };
public: public:

View File

@ -55,6 +55,7 @@ class Token {
token_type_pair{ "(", TokenType::lp }, token_type_pair{ "(", TokenType::lp },
token_type_pair{ ")", TokenType::rp } token_type_pair{ ")", TokenType::rp }
}; };
//constexpr TokenType to_token_type( std::string_view const value ) noexcept; //constexpr TokenType to_token_type( std::string_view const value ) noexcept;
constexpr TokenType to_token_type( std::string_view const value ) noexcept { constexpr TokenType to_token_type( std::string_view const value ) noexcept {
auto find_matching { auto find_matching {
@ -71,50 +72,49 @@ class Token {
} }
}; };
if ( auto const symbol{ find_matching(symbols) };
auto const symbol{ find_matching( symbols ) }; if (symbol != std::cend(symbols)) {
symbol != std::cend( symbols )
) {
return symbol->second; return symbol->second;
} }
return TokenType::monitorlink; return TokenType::monitorlink;
} } // end constexpr TokenType to_token_type( std::string_view const value )
public: public:
Token(TokenType const type, std::string_view const value) Token(TokenType const type, std::string_view const value)
: type_(type) : type_(type)
, value_(value) , value_(value)
, monitor_link_(nullptr) , monitor_link_(nullptr)
{ {
if (type_ == TokenType::monitorlink) { if (type_ == TokenType::monitorlink) {
auto colon_position = value_.find(':'); auto colon_position = value_.find(':');
unsigned int monitor_id = 0; unsigned int monitor_id = 0;
unsigned int zone_id = 0; unsigned int zone_id = 0;
std::string monitor_name; std::string monitor_name;
std::string zone_name; std::string zone_name;
if (colon_position != std::string::npos) { if (colon_position != std::string::npos) {
// Has a zone specification // Has a zone specification
monitor_id = std::stoul(std::string(value_.substr(0, colon_position))); monitor_id = std::stoul(std::string(value_.substr(0, colon_position)));
zone_id = std::stoul(std::string(value_.substr(colon_position+1, std::string::npos))); zone_id = std::stoul(std::string(value_.substr(colon_position+1, std::string::npos)));
} else {
monitor_id = std::stoul(std::string(value_));
}
Debug(1, "Have linked monitor %d zone %d", monitor_id, zone_id);
std::shared_ptr<Monitor> monitor = Monitor::Load(monitor_id, false, Monitor::QUERY);
monitor_link_ = new Monitor::MonitorLink(monitor, zone_id);
} else { } else {
monitor_id = std::stoul(std::string(value_)); Debug( 1, "Not a monitor link value is %s", std::string(value_).c_str());
} }
Debug(1, "Have linked monitor %d zone %d", monitor_id, zone_id);
std::shared_ptr<Monitor> monitor = Monitor::Load(monitor_id, false, Monitor::QUERY);
monitor_link_ = new Monitor::MonitorLink(monitor, zone_id);
} }
}
constexpr Token() noexcept : constexpr Token() noexcept :
type_(TokenType::unknown), type_(TokenType::unknown),
value_(""), value_(""),
monitor_link_(nullptr) monitor_link_(nullptr)
{ { }
}
//Token( TokenType const type, std::string_view const value ); //Token( TokenType const type, std::string_view const value );
constexpr Token( Token && rhs ) noexcept = default; constexpr Token( Token && rhs ) noexcept = default;
@ -126,11 +126,33 @@ class Token {
, monitor_link_(nullptr) , monitor_link_(nullptr)
{} {}
constexpr Token( std::string_view const value ) noexcept Token( std::string_view const value ) noexcept
: type_ (to_token_type(value)) : type_ (to_token_type(value))
, value_(value) , value_(value)
, monitor_link_(nullptr) , monitor_link_(nullptr)
{} {
if (type_ == TokenType::monitorlink) {
auto colon_position = value_.find(':');
unsigned int monitor_id = 0;
unsigned int zone_id = 0;
std::string monitor_name;
std::string zone_name;
if (colon_position != std::string::npos) {
// Has a zone specification
monitor_id = std::stoul(std::string(value_.substr(0, colon_position)));
zone_id = std::stoul(std::string(value_.substr(colon_position+1, std::string::npos)));
} else {
monitor_id = std::stoul(std::string(value_));
}
Debug(1, "Have linked monitor %d zone %d", monitor_id, zone_id);
std::shared_ptr<Monitor> monitor = Monitor::Load(monitor_id, false, Monitor::QUERY);
monitor_link_ = new Monitor::MonitorLink(monitor, zone_id);
} else {
Debug( 1, "Not a monitor link value is %s", std::string(value_).c_str());
}
}
Token & operator=( Token && rhs ) noexcept = default; Token & operator=( Token && rhs ) noexcept = default;
Token & operator=( Token const & rhs ) noexcept = default; Token & operator=( Token const & rhs ) noexcept = default;
@ -145,6 +167,7 @@ class Token {
type_ = type; type_ = type;
value_ = "";//to_token_keyword( type ); value_ = "";//to_token_keyword( type );
} }
} }
constexpr TokenType type() const noexcept { return type_; } constexpr TokenType type() const noexcept { return type_; }
@ -152,6 +175,7 @@ class Token {
constexpr void value( std::string_view const value ) noexcept { constexpr void value( std::string_view const value ) noexcept {
type_ = to_token_type( value ); type_ = to_token_type( value );
value_ = value; value_ = value;
} }
[[ nodiscard ]] constexpr std::string_view value() const noexcept { [[ nodiscard ]] constexpr std::string_view value() const noexcept {
@ -174,6 +198,26 @@ class Token {
return is(first) || is(second); return is(first) || is(second);
} }
[[ nodiscard ]] constexpr bool hasAlarmed() const {
return (monitor_link_ && monitor_link_->connect() && monitor_link_->hasAlarmed());
}
[[ nodiscard ]] constexpr int score() const {
if ( monitor_link_ ) {
if (!monitor_link_->isConnected() ) {
Debug(1, "connecting");
if (!monitor_link_->connect()) {
Debug(1, "failed");
return 0;
}
}
int s = monitor_link_->score();
Debug(1, "Score from monitor %s is %d", monitor_link_->Name(), s);
return s;
}
return 0;
}
private: private:
TokenType type_; TokenType type_;
std::string_view value_; std::string_view value_;