659 lines
24 KiB
C++
659 lines
24 KiB
C++
|
|
/******************************************************************************************************************
|
|||
|
|
* Action instruction algorithm
|
|||
|
|
*表达式反馈算法
|
|||
|
|
* arg[0] action expression
|
|||
|
|
* arg[1] feedback expression
|
|||
|
|
* arg[2] expression of judgment result
|
|||
|
|
*
|
|||
|
|
* 1.0 2020-12-17 zoufuzhou
|
|||
|
|
******************************************************************************************************************/
|
|||
|
|
#include <eqpalg/algs/exp.h>
|
|||
|
|
#include <eqpalg/exp_macro/get_macro_replaced_exp.h>
|
|||
|
|
#include <eqpalg/utility/build_alarm_info.h>
|
|||
|
|
#include <eqpalg/utility/entCentExit.h>
|
|||
|
|
#include <eqpalg/utility/instance_lock.h>
|
|||
|
|
#include <float.h>
|
|||
|
|
#include <mix_cc/ihyper_db/utility.h>
|
|||
|
|
#include <mix_cc/type/mix_time.h>
|
|||
|
|
#include <memory>
|
|||
|
|
#include <unordered_map>
|
|||
|
|
#include <vector>
|
|||
|
|
Exp::Exp(const string& name, const mix_cc::json& rule_json,
|
|||
|
|
const string& ruleId, size_t dims)
|
|||
|
|
: AlgBase(name, rule_json, ruleId), dims_(dims) {
|
|||
|
|
logger_.reset(new LOG("Exp:" + rule_name_, AUTO_CATCH_PID));
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
Exp::~Exp() {
|
|||
|
|
// utility::unlock_file(rule_id_);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
int Exp::init() {
|
|||
|
|
int ret = 0;
|
|||
|
|
try {
|
|||
|
|
ret += AlgBase::init(); /*1.tag点;2.执行周期*/
|
|||
|
|
// 重新载入数据源配置信息
|
|||
|
|
ret += this->reload_config_data_source(); /*3.数据源*/
|
|||
|
|
// 在载入数据源信息完成后,载入表达式配置之前,必须刷新变量,把变量信息初始化到mm_vars内
|
|||
|
|
ret += this->first_fill_mm_vars(); /*4.数据项*/
|
|||
|
|
// 必须在刷新变量后,才可以初始化表达式
|
|||
|
|
ret += this->reload_config_exp_act(); /*5.动作表达式*/
|
|||
|
|
if (feedback_mode_) {
|
|||
|
|
ret += this->reload_config_exp_feedback(); /*6.反馈表达式*/
|
|||
|
|
}
|
|||
|
|
} catch (const std::exception& e) {
|
|||
|
|
std::throw_with_nested(
|
|||
|
|
mix_cc::Exception(-1, "load error", BOOST_CURRENT_LOCATION));
|
|||
|
|
}
|
|||
|
|
return ret;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
AlarmInfo Exp::exec_mon() {
|
|||
|
|
AlarmInfo out_alarm{};
|
|||
|
|
try {
|
|||
|
|
this->refresh_now_time();
|
|||
|
|
// 根据数据来源种类,决定最后的执行过程
|
|||
|
|
switch (data_source_) {
|
|||
|
|
// 如果是共享内存,只需要执行当前周期的数据和表达式
|
|||
|
|
// 并判断是否报警
|
|||
|
|
case DataSource::MEMORY: {
|
|||
|
|
refresh_exp_vars_mem();
|
|||
|
|
if (this->refresh_counts_ < 3) {
|
|||
|
|
this->refresh_counts_++;
|
|||
|
|
} else {
|
|||
|
|
out_alarm = mon_proc();
|
|||
|
|
}
|
|||
|
|
} break;
|
|||
|
|
// 如果是ihyperDB
|
|||
|
|
case DataSource::IHDB:
|
|||
|
|
// 需要先重新载入ihyperDB的缓存数据
|
|||
|
|
refresh_ihd_cache();
|
|||
|
|
// 然后刷以此把缓存中的数据取出
|
|||
|
|
for (auto i = 0; i < queried_data_.rows(); i++) {
|
|||
|
|
refresh_exp_vars_ihd(i);
|
|||
|
|
if (!out_alarm.alarmed) {
|
|||
|
|
auto tmp = mon_proc();
|
|||
|
|
if (tmp.alarmed) {
|
|||
|
|
out_alarm = (tmp);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
break;
|
|||
|
|
default:
|
|||
|
|
break;
|
|||
|
|
}
|
|||
|
|
} catch (const std::exception& e) {
|
|||
|
|
gb_logger_->log_exception(e);
|
|||
|
|
}
|
|||
|
|
return out_alarm;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 单次执行
|
|||
|
|
std::vector<AlarmInfo> Exp::exec_task(mix_cc::time_range_t time_range) {
|
|||
|
|
std::vector<AlarmInfo> out_alarms;
|
|||
|
|
try {
|
|||
|
|
// 刷一遍 mmvar 防止p1_3数据错误带来的问题
|
|||
|
|
now_time_ = time_range.get_left() - query_interval_time_;
|
|||
|
|
if (this->delay_time_ > this->ihd_min_time_particles_ &&
|
|||
|
|
(this->delay_time_.count() % this->ihd_min_time_particles_.count() ==
|
|||
|
|
0)) {
|
|||
|
|
refresh_ihd_cache(this->delay_time_);
|
|||
|
|
} else {
|
|||
|
|
refresh_ihd_cache();
|
|||
|
|
}
|
|||
|
|
for (auto i = 0; i < queried_data_.rows(); i++) {
|
|||
|
|
refresh_exp_vars_ihd(i);
|
|||
|
|
}
|
|||
|
|
// 对每个ihdb 查询周期的数据,进行处理
|
|||
|
|
for (auto now_time = time_range.get_left();
|
|||
|
|
now_time <= time_range.get_right(); now_time += query_interval_time_) {
|
|||
|
|
this->now_time_ = now_time;
|
|||
|
|
if (this->delay_time_ > this->ihd_min_time_particles_ &&
|
|||
|
|
(this->delay_time_.count() % this->ihd_min_time_particles_.count() ==
|
|||
|
|
0)) {
|
|||
|
|
refresh_ihd_cache(this->delay_time_);
|
|||
|
|
} else {
|
|||
|
|
refresh_ihd_cache();
|
|||
|
|
}
|
|||
|
|
for (auto i = 0; i < queried_data_.rows(); i++) {
|
|||
|
|
refresh_exp_vars_ihd(i);
|
|||
|
|
// gb_logger_->log_info(this->rule_name_+":测试");
|
|||
|
|
auto tmp = mon_proc();
|
|||
|
|
if (tmp.alarmed) {
|
|||
|
|
// gb_logger_->log_info(this->rule_name_+"满足报警");
|
|||
|
|
out_alarms.push_back(tmp);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
// utility::unlock_file(rule_id_);
|
|||
|
|
gb_logger_->log_info("本次测试报警数量:" +
|
|||
|
|
std::to_string(out_alarms.size()));
|
|||
|
|
auto msg =
|
|||
|
|
rule_name_ + "本次测试报警数量:" + std::to_string(out_alarms.size());
|
|||
|
|
auto alarm_task = utility::build_alarm_info(
|
|||
|
|
MsgLevel::INFO, rule_id_, rule_name_, "EXPACT", msg, time_range);
|
|||
|
|
out_alarms.clear();
|
|||
|
|
out_alarms.push_back(alarm_task);
|
|||
|
|
} catch (const std::exception& e) {
|
|||
|
|
gb_logger_->log_exception(e);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
return out_alarms;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
AlarmInfo Exp::mon_proc() {
|
|||
|
|
// 监控基本过程
|
|||
|
|
double result_value;
|
|||
|
|
try {
|
|||
|
|
// 获得是否满足前提条件表达式
|
|||
|
|
act_triggered_ = static_cast<bool>(exp_act_->evaluate());
|
|||
|
|
// 如果是反馈模式
|
|||
|
|
if (feedback_mode_) {
|
|||
|
|
// 获得是否满足反馈条件表达式
|
|||
|
|
feedback_triggered_ = static_cast<bool>(exp_feedback_->evaluate());
|
|||
|
|
// 如果
|
|||
|
|
if (act_start_done()) {
|
|||
|
|
// print_exp_vars();
|
|||
|
|
return AlarmInfo{};
|
|||
|
|
}
|
|||
|
|
if (act_not_hold()) {
|
|||
|
|
return AlarmInfo{};
|
|||
|
|
}
|
|||
|
|
if (act_done()) {
|
|||
|
|
result_value = exp_result_->evaluate();
|
|||
|
|
print_exp_vars();
|
|||
|
|
logger_->Debug() << " action end:"
|
|||
|
|
<< mix_cc::mix_time_t(query_time_range_.get_right())
|
|||
|
|
.to_formatted_time()
|
|||
|
|
<< " timediff:" << mm_vars["time"]
|
|||
|
|
<< " exp:" << exp_str_ << "=" << result_value << endl;
|
|||
|
|
|
|||
|
|
if (result_value) {
|
|||
|
|
std::string msg_tag = "";
|
|||
|
|
if (exp_str_ == "isEntOK" || exp_str_ == "isCentOK" ||
|
|||
|
|
exp_str_ == "isExitOK") {
|
|||
|
|
for (int i = 0; i < m_tags.size(); i++) {
|
|||
|
|
msg_tag +=
|
|||
|
|
"tag" + std::to_string(i + 1) + ":" +
|
|||
|
|
std::to_string(mm_vars["tag" + std::to_string(i + 1)]) + " ";
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
if (exp_str_.find("mx_tag") != std::string::npos) {
|
|||
|
|
for (int i = 0; i < m_tags.size(); i++) {
|
|||
|
|
// msg_tag +=
|
|||
|
|
// "max(tag" + std::to_string(i + 1) + "):" +
|
|||
|
|
// std::to_string(mm_vars["mx_tag" + std::to_string(i + 1)]) +
|
|||
|
|
// " " + "min(tag" + std::to_string(i + 1) + "):" +
|
|||
|
|
// std::to_string(mm_vars["mi_tag" + std::to_string(i + 1)]) +
|
|||
|
|
// " ";
|
|||
|
|
msg_tag +=
|
|||
|
|
std::to_string(mm_vars["mx_tag" + std::to_string(i + 1)] -
|
|||
|
|
mm_vars["mi_tag" + std::to_string(i + 1)]) +
|
|||
|
|
" ";
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
auto msg = rule_name_ + " " + error_str_ + msg_tag;
|
|||
|
|
logger_->Debug() << msg << endl;
|
|||
|
|
return utility::build_alarm_info(MsgLevel::ERROR, rule_id_,
|
|||
|
|
rule_name_, "EXPACT", msg,
|
|||
|
|
query_time_range_);
|
|||
|
|
}
|
|||
|
|
} else if (act_timeout()) {
|
|||
|
|
return this->get_timeout_alarm();
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
// 不是动作反馈,则act_triggered_ 即为报警触发条件 2021-10-27
|
|||
|
|
else {
|
|||
|
|
if (act_triggered_) {
|
|||
|
|
print_exp_vars();
|
|||
|
|
auto msg = rule_name_ + " " + error_str_;
|
|||
|
|
logger_->Debug() << msg << endl;
|
|||
|
|
this->query_time_range_.set_left(query_time_range_.get_right() -
|
|||
|
|
delay_time_); //
|
|||
|
|
return utility::build_alarm_info(MsgLevel::ERROR, rule_id_, rule_name_,
|
|||
|
|
"EXP", msg, query_time_range_);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
} catch (const std::exception& e) {
|
|||
|
|
std::throw_with_nested(
|
|||
|
|
mix_cc::Exception(-1, "mon_proc error", BOOST_CURRENT_LOCATION));
|
|||
|
|
}
|
|||
|
|
return AlarmInfo{};
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
mix_cc::json Exp::exec_cron() { return {}; }
|
|||
|
|
|
|||
|
|
bool Exp::act_start_done() {
|
|||
|
|
// 如果动作未开始且前提条件满足
|
|||
|
|
if (!act_started_ && act_triggered_) {
|
|||
|
|
// 则认为动作开始,并置动作开始时间为当前时间
|
|||
|
|
act_started_ = true;
|
|||
|
|
act_start_time_ = this->now_time_;
|
|||
|
|
for (unsigned int i = 0; i < m_tags.size(); i++) {
|
|||
|
|
// s[n] 表示tag[n]在动作开始时刻的起始值
|
|||
|
|
mm_vars["s" + std::to_string(i + 1)] =
|
|||
|
|
mm_vars["tag" + std::to_string(i + 1)];
|
|||
|
|
mm_vars["stime"] =
|
|||
|
|
duration_cast<milliseconds>(now_time_.time_since_epoch()).count();
|
|||
|
|
// mv2 变量
|
|||
|
|
mm_vars["mx_tag" + std::to_string(i + 1)] =
|
|||
|
|
mm_vars["tag" + std::to_string(i + 1)];
|
|||
|
|
mm_vars["mi_tag" + std::to_string(i + 1)] =
|
|||
|
|
mm_vars["tag" + std::to_string(i + 1)];
|
|||
|
|
// mm_vars["mx_p" + std::to_string(i + 1)] =
|
|||
|
|
// mm_vars["p" + std::to_string(i + 1)];
|
|||
|
|
// mm_vars["mi_p" + std::to_string(i + 1)] =
|
|||
|
|
// mm_vars["p" + std::to_string(i + 1)];
|
|||
|
|
|
|||
|
|
mm_vars["mv2_tag" + std::to_string(i + 1)] = 0;
|
|||
|
|
mm_vars["mv2_p" + std::to_string(i + 1)] = 0;
|
|||
|
|
if (mm_vars["tag" + std::to_string(i + 1)] == 1) {
|
|||
|
|
mm_vars["mv2_tag" + std::to_string(i + 1)] = 1;
|
|||
|
|
}
|
|||
|
|
if (mm_vars["p" + std::to_string(i + 1)] == 1) {
|
|||
|
|
mm_vars["mv2_p" + std::to_string(i + 1)] = 1;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
// 重设query time range 的 left,使得时间下限为报警的时间开始
|
|||
|
|
this->query_time_range_.set_left(now_time_);
|
|||
|
|
|
|||
|
|
// 检查动作开时间条件是否错误
|
|||
|
|
logger_->Debug() << " action start:"
|
|||
|
|
<< mix_cc::mix_time_t(act_start_time_).to_formatted_time()
|
|||
|
|
<< endl;
|
|||
|
|
return true;
|
|||
|
|
}
|
|||
|
|
return false;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
AlarmInfo Exp::cron_proc() { return AlarmInfo{}; }
|
|||
|
|
|
|||
|
|
bool Exp::act_not_hold() {
|
|||
|
|
// 如果动作开始,且需要保持,且动作开始没有被触发,
|
|||
|
|
if (act_started_ && keep_mode_ && !act_triggered_) {
|
|||
|
|
// 开始条件act_started置为假,即动作停止
|
|||
|
|
act_started_ = false;
|
|||
|
|
logger_->Debug() << " action signal is not holding " << endl;
|
|||
|
|
return true;
|
|||
|
|
}
|
|||
|
|
return false;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
bool Exp::act_done() {
|
|||
|
|
// 如果动作已开始 刷新 mv2_tag[n]
|
|||
|
|
if (act_started_) {
|
|||
|
|
for (unsigned int i = 0; i < m_tags.size(); i++) {
|
|||
|
|
mm_vars["mx_tag" + std::to_string(i + 1)] =
|
|||
|
|
std::max(mm_vars["tag" + std::to_string(i + 1)],
|
|||
|
|
mm_vars["mx_tag" + std::to_string(i + 1)]);
|
|||
|
|
mm_vars["mi_tag" + std::to_string(i + 1)] =
|
|||
|
|
std::min(mm_vars["tag" + std::to_string(i + 1)],
|
|||
|
|
mm_vars["mi_tag" + std::to_string(i + 1)]);
|
|||
|
|
// mm_vars["mx_p" + std::to_string(i + 1)] =
|
|||
|
|
// std::max(mm_vars["p" + std::to_string(i + 1)],
|
|||
|
|
// mm_vars["mx_p" + std::to_string(i + 1)]);
|
|||
|
|
// mm_vars["mi_p" + std::to_string(i + 1)] =
|
|||
|
|
// std::min(mm_vars["p" + std::to_string(i + 1)],
|
|||
|
|
// mm_vars["mi_p" + std::to_string(i + 1)]);
|
|||
|
|
if (mm_vars["tag" + std::to_string(i + 1)] == 1) {
|
|||
|
|
mm_vars["mv2_tag" + std::to_string(i + 1)] += 1;
|
|||
|
|
}
|
|||
|
|
if (mm_vars["p" + std::to_string(i + 1)] == 1) {
|
|||
|
|
mm_vars["mv2_p" + std::to_string(i + 1)] += 1;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
// 如果动作处于开始状态,且反馈模式触发
|
|||
|
|
if (act_started_ && feedback_triggered_) {
|
|||
|
|
// 则记录下结束时间
|
|||
|
|
mm_vars["etime"] = mm_vars["now"];
|
|||
|
|
mm_vars["time"] = mm_vars["etime"] - mm_vars["stime"];
|
|||
|
|
act_started_ = false;
|
|||
|
|
return true;
|
|||
|
|
}
|
|||
|
|
return false;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 表达式系统触发-反馈动作超时
|
|||
|
|
bool Exp::act_timeout() {
|
|||
|
|
if (time_out_ == milliseconds(0)) {
|
|||
|
|
// 重置mv_tag 防止崩溃
|
|||
|
|
for (unsigned int i = 0; i < m_tags.size(); i++) {
|
|||
|
|
if (abs(mm_vars["mv2_tag" + std::to_string(i + 1)] - DBL_MAX) < 2.0) {
|
|||
|
|
mm_vars["mv2_tag" + std::to_string(i + 1)] = 0;
|
|||
|
|
mm_vars["mv2_p" + std::to_string(i + 1)] = 0;
|
|||
|
|
this->logger_->Debug()
|
|||
|
|
<< "mv2_tag" + std::to_string(i + 1) << "已达上限,被清空" << endl;
|
|||
|
|
act_started_ = false;
|
|||
|
|
return true; //不再继续
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
return false;
|
|||
|
|
}
|
|||
|
|
// 如果当动作处于开始状态 当前时间减去开始时间大于超时时间,则认为超时
|
|||
|
|
if (act_started_ && (now_time_ - act_start_time_) > time_out_) {
|
|||
|
|
act_started_ = false;
|
|||
|
|
// 超时 重置 防止崩溃
|
|||
|
|
logger_->Debug() << "动作反馈超时,mv2_tag将被重置" << endl;
|
|||
|
|
for (unsigned int i = 0; i < m_tags.size(); i++) {
|
|||
|
|
logger_->Debug() << "当前mv2_tag" << i + 1 << "="
|
|||
|
|
<< mm_vars["mv2_tag" + std::to_string(i + 1)] << "s"
|
|||
|
|
<< endl;
|
|||
|
|
mm_vars["mv2_tag" + std::to_string(i + 1)] = 0;
|
|||
|
|
mm_vars["mv2_p" + std::to_string(i + 1)] = 0;
|
|||
|
|
}
|
|||
|
|
return true;
|
|||
|
|
}
|
|||
|
|
return false;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 得到报警超时信息
|
|||
|
|
AlarmInfo Exp::get_timeout_alarm() {
|
|||
|
|
auto msg = rule_name_ + " no feedback on the action";
|
|||
|
|
logger_->Debug() << msg << endl;
|
|||
|
|
return utility::build_alarm_info(MsgLevel::ERROR, rule_id_, rule_name_,
|
|||
|
|
"EXPACT", msg, query_time_range_);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
int Exp::reload_config_exp_feedback() {
|
|||
|
|
// 获取feedback信息
|
|||
|
|
if (rule_json_.at("action_condition").contains("action_hold")) {
|
|||
|
|
// 判断是否保持
|
|||
|
|
keep_mode_ =
|
|||
|
|
rule_json_.at("action_condition").at("action_hold").at(1).get<int>();
|
|||
|
|
logger_->Debug() << "keep:" << keep_mode_ << endl;
|
|||
|
|
time_out_ = milliseconds(
|
|||
|
|
rule_json_.at("interval").at("timeout").at(1).get<int64_t>());
|
|||
|
|
// 如果超时时间小于3分钟,则默认为超时时间为3分钟
|
|||
|
|
if (time_out_ < minutes(3) && time_out_ != milliseconds(0)) {
|
|||
|
|
time_out_ = minutes(3);
|
|||
|
|
}
|
|||
|
|
// 获取feedback表达式
|
|||
|
|
logger_->Debug() << "timeout:" << time_out_.count() << endl;
|
|||
|
|
auto tmp_exp = string(rule_json_.at("action_condition")
|
|||
|
|
.at("action_end")
|
|||
|
|
.at(1)
|
|||
|
|
.get<std::string>());
|
|||
|
|
exp_str_ = get_macro_replaced_exp(tmp_exp);
|
|||
|
|
// 构建feedback表达式
|
|||
|
|
// exp_feedback_ =
|
|||
|
|
// std::make_unique<mix_cc::matheval::Expression>(exp_str_, &mm_vars);
|
|||
|
|
// logger_->Debug() << exp_str_ << ":" << exp_feedback_->evaluate() << endl;
|
|||
|
|
|
|||
|
|
// 2022-1-18 测试
|
|||
|
|
try {
|
|||
|
|
exp_feedback_ =
|
|||
|
|
std::make_unique<mix_cc::matheval::Expression>(exp_str_, &mm_vars);
|
|||
|
|
logger_->Debug() << exp_str_ << ":" << exp_feedback_->evaluate() << endl;
|
|||
|
|
} catch (const std::exception& e) {
|
|||
|
|
logger_->Error() << exp_str_ << "计算错误:" << e.what() << endl;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
} else {
|
|||
|
|
time_out_ = milliseconds(600000);
|
|||
|
|
}
|
|||
|
|
// 获取监控变量信息
|
|||
|
|
auto tmp_exp =
|
|||
|
|
rule_json_.at("alarm_option").at("value").at(1).get<std::string>();
|
|||
|
|
exp_str_ = get_macro_replaced_exp(tmp_exp);
|
|||
|
|
// 获取
|
|||
|
|
error_str_ =
|
|||
|
|
rule_json_.at("alarm_option").at("error").at(1).get<std::string>();
|
|||
|
|
// 如果结果表达式没有初始化,则初始化之后再次使用
|
|||
|
|
try {
|
|||
|
|
if (exp_result_ == nullptr) {
|
|||
|
|
exp_result_ =
|
|||
|
|
std::make_unique<mix_cc::matheval::Expression>(exp_str_, &mm_vars);
|
|||
|
|
logger_->Debug() << exp_str_ << ":" << exp_result_->evaluate() << endl;
|
|||
|
|
} else {
|
|||
|
|
logger_->Info() << "指针已经初始化完成" << exp_str_ << ":"
|
|||
|
|
<< exp_result_->evaluate() << endl;
|
|||
|
|
}
|
|||
|
|
} catch (const std::exception& e) {
|
|||
|
|
logger_->Error() << exp_result_ << "计算错误:" << e.what() << endl;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// if (exp_result_ == nullptr) {
|
|||
|
|
// exp_result_ =
|
|||
|
|
// std::make_unique<mix_cc::matheval::Expression>(exp_str_, &mm_vars);
|
|||
|
|
// logger_->Debug() << exp_str_ << ":" << exp_result_->evaluate() << endl;
|
|||
|
|
// } else {
|
|||
|
|
// logger_->Info() << "指针已经初始化完成" << exp_str_ << ":"
|
|||
|
|
// << exp_result_->evaluate() << endl;
|
|||
|
|
// }
|
|||
|
|
if (exp_str_.find("time", 0) != string::npos) {
|
|||
|
|
m_timemode = true;
|
|||
|
|
} else {
|
|||
|
|
m_timemode = false;
|
|||
|
|
}
|
|||
|
|
return 0;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 刷新共享内存所对应的变量
|
|||
|
|
int Exp::refresh_exp_vars_mem() {
|
|||
|
|
refresh_now_time();
|
|||
|
|
for (unsigned int i = 0; i < m_tags.size(); i++) {
|
|||
|
|
// s[n] 表示tag[n]在动作开始时刻的起始值
|
|||
|
|
// p[n] 表示tag[n]在上一个动作周期的数值
|
|||
|
|
mm_vars["p" + std::to_string(i + 1)] =
|
|||
|
|
mm_vars["tag" + std::to_string(i + 1)];
|
|||
|
|
mm_vars["tag" + std::to_string(i + 1)] =
|
|||
|
|
SingletonTemplate<GlobaltemSharedMemory>::GetInstance()[m_tags[i]];
|
|||
|
|
mm_vars["now"] =
|
|||
|
|
duration_cast<milliseconds>(now_time_.time_since_epoch()).count();
|
|||
|
|
auto pv_str = "pv" + std::to_string(i + 1);
|
|||
|
|
mm_vars[pv_str + "_4"] = mm_vars[pv_str + "_3"];
|
|||
|
|
mm_vars[pv_str + "_3"] = mm_vars[pv_str + "_2"];
|
|||
|
|
mm_vars[pv_str + "_2"] = mm_vars[pv_str + "_1"];
|
|||
|
|
mm_vars[pv_str + "_1"] = mm_vars[pv_str + "_0"];
|
|||
|
|
mm_vars[pv_str + "_0"] = mm_vars["tag" + std::to_string(i + 1)];
|
|||
|
|
}
|
|||
|
|
mm_vars["isEntOK"] = SingletonTemplate<entCentExit>::GetInstance().isEntOK();
|
|||
|
|
mm_vars["isCentOK"] =
|
|||
|
|
SingletonTemplate<entCentExit>::GetInstance().isCentOK();
|
|||
|
|
mm_vars["isExitOK"] =
|
|||
|
|
SingletonTemplate<entCentExit>::GetInstance().isExitOK();
|
|||
|
|
// 设置right的时间
|
|||
|
|
this->query_time_range_.set_right(now_time_);
|
|||
|
|
return 0;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 重新载入数据源配置
|
|||
|
|
int Exp::reload_config_data_source() {
|
|||
|
|
int res = 0;
|
|||
|
|
if (!rule_json_.contains("datasource")) {
|
|||
|
|
data_source_ = 0;
|
|||
|
|
logger_->Debug()
|
|||
|
|
<< "默认数据源为iHyerDB! data source[0:iHyerDB,1:memory]:"
|
|||
|
|
<< data_source_ << endl;
|
|||
|
|
return 0;
|
|||
|
|
}
|
|||
|
|
try {
|
|||
|
|
data_source_ =
|
|||
|
|
std::stoi(rule_json_.at("datasource").at("value").get<std::string>());
|
|||
|
|
logger_->Debug() << "data source[0:iHyerDB,1:memory]:" << data_source_
|
|||
|
|
<< endl;
|
|||
|
|
} catch (const std::exception& e) {
|
|||
|
|
gb_logger_->log_error(std::string("ExpBase::reload_config_data_source()") +
|
|||
|
|
e.what());
|
|||
|
|
this->error_code_list_.push_back(
|
|||
|
|
{ErrorType::Empty, ErrorLocation::DataSource});
|
|||
|
|
return -1;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
return 0;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 刷新对应ihd cache内第row行的数据变量
|
|||
|
|
int Exp::refresh_exp_vars_ihd(int row) {
|
|||
|
|
// i <= row 原本查询时间对应的是[t1,t2)
|
|||
|
|
// 则queried_time_内部的时间也一定是[t1,t2)
|
|||
|
|
for (unsigned int i = 0; i < m_tags.size(); i++) {
|
|||
|
|
mm_vars["p" + std::to_string(i + 1)] =
|
|||
|
|
mm_vars["tag" + std::to_string(i + 1)];
|
|||
|
|
mm_vars["tag" + std::to_string(i + 1)] = queried_data_(row, i);
|
|||
|
|
auto pv_str = "pv" + std::to_string(i + 1);
|
|||
|
|
mm_vars[pv_str + "_4"] = mm_vars[pv_str + "_3"];
|
|||
|
|
mm_vars[pv_str + "_3"] = mm_vars[pv_str + "_2"];
|
|||
|
|
mm_vars[pv_str + "_2"] = mm_vars[pv_str + "_1"];
|
|||
|
|
mm_vars[pv_str + "_1"] = mm_vars[pv_str + "_0"];
|
|||
|
|
mm_vars[pv_str + "_0"] = mm_vars["tag" + std::to_string(i + 1)];
|
|||
|
|
//
|
|||
|
|
mm_vars["now"] = mix_cc::mix_time_t(queried_time_[row]).to_milliseconds();
|
|||
|
|
// right一定小于t2
|
|||
|
|
this->query_time_range_.set_right(queried_time_[row]);
|
|||
|
|
// 当前时间 == 上次执行的结束时间
|
|||
|
|
this->now_time_ = queried_time_[row];
|
|||
|
|
}
|
|||
|
|
mm_vars["isEntOK"] =
|
|||
|
|
SingletonTemplate<entCentExit>::GetInstance().isEntOK_ihd();
|
|||
|
|
mm_vars["isCentOK"] =
|
|||
|
|
SingletonTemplate<entCentExit>::GetInstance().isCentOK_ihd();
|
|||
|
|
mm_vars["isExitOK"] =
|
|||
|
|
SingletonTemplate<entCentExit>::GetInstance().isExitOK_ihd();
|
|||
|
|
return 0;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 程序启动时刻的,首次刷新变量数据
|
|||
|
|
// 防止程序因为p1 pv1类似的变量,导致程序的变量差值信息错误
|
|||
|
|
int Exp::first_fill_mm_vars() {
|
|||
|
|
if (data_source_ == DataSource::MEMORY) {
|
|||
|
|
mm_vars["isEntOK"] = false;
|
|||
|
|
mm_vars["isCentOK"] = false;
|
|||
|
|
mm_vars["isExitOK"] = false;
|
|||
|
|
for (unsigned int i = 0; i < m_tags.size(); i++) {
|
|||
|
|
auto pv_str = "pv" + std::to_string(i + 1);
|
|||
|
|
auto value =
|
|||
|
|
SingletonTemplate<GlobaltemSharedMemory>::GetInstance()[m_tags[i]];
|
|||
|
|
mm_vars["s" + std::to_string(i + 1)] = value;
|
|||
|
|
mm_vars["p" + std::to_string(i + 1)] = value;
|
|||
|
|
mm_vars["tag" + std::to_string(i + 1)] = value;
|
|||
|
|
mm_vars["mv2_tag" + std::to_string(i + 1)] = 0;
|
|||
|
|
mm_vars["mv2_p" + std::to_string(i + 1)] = 0;
|
|||
|
|
mm_vars["mx_tag" + std::to_string(i + 1)] =
|
|||
|
|
mm_vars["tag" + std::to_string(i + 1)];
|
|||
|
|
mm_vars["mi_tag" + std::to_string(i + 1)] =
|
|||
|
|
mm_vars["tag" + std::to_string(i + 1)];
|
|||
|
|
// mm_vars["mx_p" + std::to_string(i + 1)] =
|
|||
|
|
// mm_vars["p" + std::to_string(i + 1)];
|
|||
|
|
// mm_vars["mi_p" + std::to_string(i + 1)] =
|
|||
|
|
// mm_vars["p" + std::to_string(i + 1)];
|
|||
|
|
mm_vars[pv_str + "_0"] = value;
|
|||
|
|
mm_vars[pv_str + "_1"] = value;
|
|||
|
|
mm_vars[pv_str + "_2"] = value;
|
|||
|
|
mm_vars[pv_str + "_3"] = value;
|
|||
|
|
mm_vars[pv_str + "_4"] = value;
|
|||
|
|
mm_vars["stime"] = 0;
|
|||
|
|
mm_vars["now"] = 0;
|
|||
|
|
mm_vars["etime"] = 0;
|
|||
|
|
mm_vars["time"] = 0;
|
|||
|
|
}
|
|||
|
|
} else if (data_source_ == DataSource::IHDB) {
|
|||
|
|
this->refresh_now_time();
|
|||
|
|
this->refresh_ihd_cache();
|
|||
|
|
if (queried_data_.rows() == 0) {
|
|||
|
|
logger_->Error() << "first_fill_mm_vars(),IHDB查询异常,未查到数据!"
|
|||
|
|
<< endl;
|
|||
|
|
this->error_code_list_.push_back(
|
|||
|
|
{ErrorType::Empty, ErrorLocation::DataValue});
|
|||
|
|
return -1;
|
|||
|
|
}
|
|||
|
|
mm_vars["isEntOK"] = false;
|
|||
|
|
mm_vars["isCentOK"] = false;
|
|||
|
|
mm_vars["isExitOK"] = false;
|
|||
|
|
for (unsigned int i = 0; i < m_tags.size(); i++) {
|
|||
|
|
auto pv_str = "pv" + std::to_string(i + 1);
|
|||
|
|
auto rows = queried_data_.rows() - 1;
|
|||
|
|
auto tmp_val = queried_data_(rows, i);
|
|||
|
|
mm_vars["s" + std::to_string(i + 1)] = tmp_val;
|
|||
|
|
mm_vars["p" + std::to_string(i + 1)] = tmp_val;
|
|||
|
|
mm_vars["tag" + std::to_string(i + 1)] = tmp_val;
|
|||
|
|
mm_vars["mv2_tag" + std::to_string(i + 1)] = 0;
|
|||
|
|
mm_vars["mv2_p" + std::to_string(i + 1)] = 0;
|
|||
|
|
mm_vars["mx_tag" + std::to_string(i + 1)] =
|
|||
|
|
mm_vars["tag" + std::to_string(i + 1)];
|
|||
|
|
mm_vars["mi_tag" + std::to_string(i + 1)] =
|
|||
|
|
mm_vars["tag" + std::to_string(i + 1)];
|
|||
|
|
// mm_vars["mx_p" + std::to_string(i + 1)] =
|
|||
|
|
// mm_vars["p" + std::to_string(i + 1)];
|
|||
|
|
// mm_vars["mi_p" + std::to_string(i + 1)] =
|
|||
|
|
// mm_vars["p" + std::to_string(i + 1)];
|
|||
|
|
mm_vars[pv_str + "_0"] = tmp_val;
|
|||
|
|
mm_vars[pv_str + "_1"] = tmp_val;
|
|||
|
|
mm_vars[pv_str + "_2"] = tmp_val;
|
|||
|
|
mm_vars[pv_str + "_3"] = tmp_val;
|
|||
|
|
mm_vars[pv_str + "_4"] = tmp_val;
|
|||
|
|
mm_vars["stime"] = 0;
|
|||
|
|
mm_vars["now"] = 0;
|
|||
|
|
mm_vars["etime"] = 0;
|
|||
|
|
mm_vars["time"] = 0;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
return 0;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
int Exp::reload_config_exp_act() {
|
|||
|
|
// 根据key,对不同版本的算法都进行取值
|
|||
|
|
if (rule_json_.at("action_condition").contains("action_start")) {
|
|||
|
|
auto tmp_exp = rule_json_.at("action_condition")
|
|||
|
|
.at("action_start")
|
|||
|
|
.at(1)
|
|||
|
|
.get<std::string>();
|
|||
|
|
exp_str_ = get_macro_replaced_exp(tmp_exp);
|
|||
|
|
feedback_mode_ = true;
|
|||
|
|
} else if (rule_json_.at("action_condition").contains("value")) {
|
|||
|
|
auto tmp_exp =
|
|||
|
|
rule_json_.at("action_condition").at("value").at(1).get<std::string>();
|
|||
|
|
exp_str_ = get_macro_replaced_exp(tmp_exp);
|
|||
|
|
if (rule_json_.at("action_condition").contains("error")) {
|
|||
|
|
error_str_ = rule_json_.at("action_condition")
|
|||
|
|
.at("error")
|
|||
|
|
.at(1)
|
|||
|
|
.get<std::string>();
|
|||
|
|
}
|
|||
|
|
feedback_mode_ = false;
|
|||
|
|
}
|
|||
|
|
if (exp_act_ == nullptr && exp_str_ != "") {
|
|||
|
|
// exp_act_ =
|
|||
|
|
// std::make_unique<mix_cc::matheval::Expression>(exp_str_, &mm_vars);
|
|||
|
|
// logger_->Debug() << "exp_act:" << exp_str_ << "=" << exp_act_->evaluate()
|
|||
|
|
// << endl;
|
|||
|
|
|
|||
|
|
// 2022-1-18 测试
|
|||
|
|
try {
|
|||
|
|
exp_act_ =
|
|||
|
|
std::make_unique<mix_cc::matheval::Expression>(exp_str_, &mm_vars);
|
|||
|
|
logger_->Debug() << "exp_act:" << exp_str_ << "=" << exp_act_->evaluate()
|
|||
|
|
<< endl;
|
|||
|
|
} catch (const std::exception& e) {
|
|||
|
|
logger_->Error() << "exp_act:" << exp_str_ << "计算出错:" << e.what()
|
|||
|
|
<< endl;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
return 0;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 打印表达式信息
|
|||
|
|
void Exp::print_exp_vars(const string& expstr) {
|
|||
|
|
std::map<std::string, double>::iterator it;
|
|||
|
|
logger_->Debug() << "exp:" << expstr << " parameter:";
|
|||
|
|
for (it = mm_vars.begin(); it != mm_vars.end(); it++) {
|
|||
|
|
logger_->Debug() << " " << it->first << ":" << it->second;
|
|||
|
|
}
|
|||
|
|
logger_->Debug() << endl;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
void Exp::set_last_alarm_time(TimePoint time_point) {
|
|||
|
|
this->refresh_counts_ = 0;
|
|||
|
|
if (this->is_usable_) {
|
|||
|
|
this->first_fill_mm_vars(); ///<打破原动作状态
|
|||
|
|
}
|
|||
|
|
AlgBase::set_last_alarm_time(time_point);
|
|||
|
|
}
|
|||
|
|
void Exp::set_usable(bool usable) {
|
|||
|
|
this->refresh_counts_ = 0;
|
|||
|
|
if (this->is_usable_) {
|
|||
|
|
this->first_fill_mm_vars(); ///<打破原动作状态
|
|||
|
|
}
|
|||
|
|
AlgBase::set_usable(usable);
|
|||
|
|
}
|