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);
|
||
} |