eis/eqpalg/algs/exp_base.cpp

1778 lines
68 KiB
C++
Raw Normal View History

#include <eqpalg/algs/exp_base.h>
#include <eqpalg/exp_macro/get_macro_replaced_exp.h>
#include <eqpalg/table_struct/t_sample_mag.h>
#include <eqpalg/utility/build_alarm_info.h>
// #include <eqpalg/utility/entCentExit.h> ///<弃用
// #include <eqpalg/utility/instance_lock.h> ///<弃用
#include <float.h>
#include <memory>
#include <mix_cc/ihyper_db/utility.h>
#include <mix_cc/sql.h>
#include <mix_cc/sql/database/db2_t.h>
#include <mix_cc/type/mix_time.h>
#include <shm/TaskData.h>
#include <unordered_map>
#include <vector>
extern ProcessType glob_process_type;
ExpBase::ExpBase(const string &name, const mix_cc::json &rule_json,
const string &ruleId, size_t exp_type)
: AlgBase(name, rule_json, ruleId), exp_type_(exp_type) {
is_exp_alg_ = true;
logger_.reset(
new LOG("ExpBase-" + std::to_string(exp_type) + ":" + rule_name_,
AUTO_CATCH_PID));
}
ExpBase::~ExpBase() {
// AlgBase::~AlgBase();
}
int ExpBase::init() {
int ret = 0;
try {
ret += AlgBase::init(); /*1.tag点2.执行周期*/
fun_vars_init();
this->con_monitor_.setThreshold(100);
// 重新载入数据源配置信息
ret += this->reload_config_data_source(); /*3.数据源*/
// 在载入数据源信息完成后载入表达式配置之前必须刷新变量把变量信息初始化到mm_vars内
if (glob_process_type == ProcessType::kMon ||
glob_process_type == ProcessType::kTask) {
ret += this->first_fill_mm_vars(); /*4.数据项*/
}
// 必须在刷新变量后,才可以初始化表达式
ret += this->reload_config_exp_act(); /*5.动作表达式*/
if (feedback_mode_) {
ret += this->reload_config_exp_feedback(); /*6.反馈表达式*/
}
if (exp_type_ == ExpType::Bound || exp_type_ == ExpType::CondBound ||
exp_type_ == ExpType::BoundHoldTime) {
ret += this->reload_config_up_down(); /*7.上下限*/
this->reload_ci_dist();
this->last_load_time_ = chrono::system_clock::now();
}
if (exp_type_ == ExpType::BoundHoldTime) {
ret += this->reload_config_up_down_hold_time(); /*8.上下限-保持时间*/
}
} catch (const std::exception &e) {
logger_->Debug() << e.what() << ".location:" << BOOST_CURRENT_LOCATION
<< endl;
// std::throw_with_nested(
// mix_cc::Exception(-1, "load error", BOOST_CURRENT_LOCATION));
}
if (ret == 0) {
this->exp_is_wrong_ = false;
}
return ret;
}
AlarmInfo ExpBase::exec_mon() {
AlarmInfo out_alarm{};
/*----规则配置参数检查----start*/
if (this->exp_is_wrong_) {
if (!exp_wrong_is_alarmed_) {
std::string msg = rule_name_ + "配置参数加载异常,请检规则配置!";
mix_cc::time_range_t time_range(chrono::system_clock::now() - 20s,
chrono::system_clock::now());
if (!this->error_code_list_.empty()) {
for (auto item : this->error_code_list_) {
msg +=
ErrorCode::ErrorLocationDescription.at(int(item.error_location));
msg += ErrorCode::ErrorTypeDescription.at(int(item.error_type));
msg += "";
}
}
msg += this->error_message_str_;
auto alarm_task = utility::build_alarm_info(
MsgLevel::ERROR, rule_id_, rule_name_, "EXPACT", msg, time_range);
if (alarm_task.alarmed) {
last_alarm_time_ -= minutes(5);
alarm_poster_.alarm(alarm_task, &last_alarm_time_);
// logger_->Info() << rule_name_ << " alarm_task.alarmed " << std::endl;
}
exp_wrong_is_alarmed_ = true;
}
return out_alarm;
}
/*----规则配置参数检查----end*/
/*----定时载入置信区间---错峰调用--start*/
if (now_time_ - last_load_time_ >
(minutes(30) + save_interval_ms_ + rule_state_update_interval_ms_)) {
this->reload_ci_dist();
}
/*----定时载入置信区间-----end*/
try {
this->refresh_now_time();
// 根据数据来源种类,决定最后的执行过程
switch (data_source_) {
// 如果是共享内存,只需要执行当前周期的数据和表达式
// 并判断是否报警
case DataSource::MEMORY: {
try {
refresh_exp_vars_mem();
} catch (const std::exception &e) {
logger_->Error() << rule_id_ << ":refresh_exp_vars_mem()异常!"
<< e.what() << ",location:" << BOOST_CURRENT_LOCATION
<< endl;
return out_alarm;
}
if (this->refresh_counts_ < 11) {
/*首次载入刷mm_vars 11次 刷新mm_vars[pv1_10]*/
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> ExpBase::exec_task(mix_cc::time_range_t time_range) {
task_data_size = 0;
// string ss0 = "rm -rf /users/dsc/shm/TaskData_boost.mmap";
// system(ss0.c_str());
// logger_->Debug() << "rm -rf /users/dsc/shm/TaskData_boost.mmap" <<
// std::endl;
std::vector<AlarmInfo> out_alarms;
/*统计类,需要单独处理数据*/
if (this->exp_type_ == ExpType::Bound ||
this->exp_type_ == ExpType::CondBound ||
this->exp_type_ == ExpType::BoundHoldTime) {
this->refresh_counts_ = 0;
try {
/**
* 1.id
* 2.
* 3. db2 T_SAMPLE_STAT表
* 4. db2 T_SAMPLE_MAG
*/
logger_->Debug()
<< "stime:"
<< mix_cc::mix_time_t(time_range.get_left()).to_formatted_time()
<< ",endtime:"
<< mix_cc::mix_time_t(time_range.get_right()).to_formatted_time()
<< endl;
std::string sample_id = this->get_id(time_range);
if (sta_ptr_ == nullptr) {
logger_->Debug() << rule_name_ << " sta_ptr_ == nullptr" << endl;
sta_ptr_ = std::make_unique<DAA::STA>(rule_id_, rule_name_);
}
// TaskShm::TimeRecordPtr.get()->data_size = 0;
// TaskShm::TimeRecordPtr.get()->stime =
// mix_cc::mix_time_t(time_range.get_left()).to_milliseconds();
// TaskShm::TimeRecordPtr.get()->etime =
// mix_cc::mix_time_t(time_range.get_right()).to_milliseconds();
// TaskShm::TimeRecordPtr.get()
// ->
// operator[](exp_type_ * 1000 + task_seq)
// .data_size = 0;
// TaskShm::TimeRecordPtr.get()
// ->
// operator[](exp_type_ * 1000 + task_seq)
// .stime =
// mix_cc::mix_time_t(time_range.get_left()).to_milliseconds();
// TaskShm::TimeRecordPtr.get()
// ->
// operator[](exp_type_ * 1000 + task_seq)
// .etime =
// mix_cc::mix_time_t(time_range.get_right()).to_milliseconds();
logger_->Debug() << "reset_data()------1" << endl;
if ((time_range.get_right() - time_range.get_left()) <
this->query_interval_time_) {
this->query_time_range_ = time_range;
task_mon_pro(); /*累计数据*/
} else {
for (auto t = time_range.get_left(); t < time_range.get_right();
t += query_interval_time_) {
this->query_time_range_.set_left(t);
if (time_range.get_right() - t > query_interval_time_) {
this->query_time_range_.set_right(t + query_interval_time_);
} else {
this->query_time_range_.set_right(time_range.get_right());
}
task_mon_pro(); /*累计数据*/
}
}
logger_->Debug() << "reset_data()------1" << endl;
this->sta_ptr_->reset_data(); /*参数重置*/
logger_->Debug() << "reset_data()------2" << endl;
logger_->Debug() << "task_seq:" << task_seq << std::endl;
// size_t dataSize = TaskShm::TimeRecordPtr.get()
// ->
// operator[](exp_type_ * 1000 + task_seq)
// .data_size;
logger_->Debug() << "dataSize:" << task_data_size << std::endl;
for (size_t j = 0; j < task_data_size; j++) {
double dataJ = TaskShm::TaskRecordPtr.get()
->
operator[](exp_type_ * 1000 + task_seq)
.data_record[j];
// logger_->Debug() << "dataJ:" << dataJ << endl;
this->sta_ptr_->dist_add(dataJ);
}
logger_->Debug() << "reset_data()------3" << endl;
auto store_res = this->sta_ptr_->task_store_db2(sample_id);
logger_->Debug() << "reset_data()------4" << endl;
// if (this->sta_ptr_->task_update_ci_dist() == 0) {
// if (store_res == 0) {
// this->sample_result_ = this->sta_ptr_->get_sample_stat_str();
// /*存数据 T_SAMPLE_MAG*/
// T_SAMPLE_MAG tsm;
// auto inset_ret = exec<db2_t, size_t>(insert_into(tsm).set(
// tsm.ruleId() = this->rule_id_, tsm.result() = stat_result,
// tsm.type() = SampleType::T_SAMPLE_STAT, tsm.sampleid() =
// sample_id, tsm.usable() = 0, tsm.starttime() =
// mix_cc::mix_time_t(this->query_time_range_.get_left()),
// tsm.endtime() =
// mix_cc::mix_time_t(query_time_range_.get_right())));
// if (inset_ret.is_nothing()) {
// std::string error_msg =
// "ruleid size:" + std::to_string(rule_id_.size()) +
// ",result:" + stat_result + ",type:" + SampleType::T_SAMPLE_STAT
// + "smpleid size:" + std::to_string(sample_id.size());
// gb_logger_->log_info("T_SAMPLE_MAG 表插入失败:" + rule_name_ + ","
// +
// error_msg);
// return out_alarms;
// }
// return out_alarms;
// }
this->sample_result_ = this->sta_ptr_->get_sample_stat_str();
this->update_t_sample_mag(store_res);
this->alarm_poster_.zmqp_send(912, this->sample_result_);
TaskShm::TaskRecordPtr.get()->erase(exp_type_ * 1000 + task_seq);
logger_->Debug() << "|" << rule_id_ << "|" << rule_name_ << "|"
<< "统计完成info:" << sample_result_ << std::endl;
} catch (const std::exception &e) {
logger_->Error() << "ExpBase::exec_task:" << e.what()
<< ",location:" << BOOST_CURRENT_LOCATION << endl;
return out_alarms;
}
return 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 ExpBase::mon_proc() {
// 监控基本过程
double result_value;
filter_flag_ = false; ///<数据筛选结果 每次执行 初始化为 false
auto_fun_vars_reset();
try {
// 获得是否满足前提条件表达式
result_value = exp_act_->evaluate(); ///< 2/5用于 非反馈 上下限
if (exp_type_ == ExpType::Bound || exp_type_ == ExpType::BoundHoldTime) {
if (exp_feedback_ != nullptr) {
/*有数据筛选*/
try {
if (exp_feedback_->evaluate()) {
filter_flag_ = true;
}
} catch (...) {
logger_->Debug() << "ruleid:" << rule_id_ << ",exp_feedback_ ERROR!"
<< endl;
}
} else {
/*无数据筛选*/
filter_flag_ = true;
}
if (is_learning_ && filter_flag_ == true) {
rule_stat_.current_value = result_value; ///<共享内存
SingletonTemp<EqpStat>::GetInstance().add_stat_values(this->rule_id_,
result_value);
}
}
act_triggered_ = static_cast<bool>(result_value);
// 如果是反馈模式
if (feedback_mode_) {
feedback_done_ = false;
if (act_start_done()) {
if (rule_id_ == string(CMemVar::Const()->printRuleid)) {
logger_->Debug() << "act_start_done!" << std::endl;
print_exp_vars();
}
return AlarmInfo{};
}
if (act_not_hold()) {
if (rule_id_ == string(CMemVar::Const()->printRuleid)) {
logger_->Debug()
<< "act_not_hold!---fun_vars_.refresh_fun_vars---start"
<< std::endl;
print_exp_vars();
}
is_fun_vars_need_reset_ = true;
return AlarmInfo{};
}
if (act_done()) {
feedback_done_ = true;
this->query_time_range_.set_left(
query_time_range_.get_right() -
milliseconds(int(mm_vars["time"]))); ///<报警开始时间-动作开始时间
result_value = exp_result_->evaluate();
is_fun_vars_need_reset_ = true; ///<取了最后的结果,就可以重置了
this->rule_stat_.limit_down = limit_down_;
this->rule_stat_.limit_up = limit_up_;
rule_stat_.current_value = result_value; ///<共享内存
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;
///<动作反馈-变量 上下限----4
if (exp_type_ == ExpType::CondBound) {
if (this->is_learning_) {
SingletonTemp<EqpStat>::GetInstance().add_stat_values(
this->rule_id_, result_value);
}
if (this->detect_up_down(result_value)) {
///<共享内存
rule_stat_.alarm_value = result_value;
///<报警
std::string msg = "";
if (m_timemode) {
/*动作时间类*/
msg = error_str_ + ":" + DAA::double2str(result_value) +
"ms,时间范围:[0," + DAA::double2str(limit_up_) + "] ms";
} else {
msg = error_str_ + ":" + DAA::double2str(result_value) + unit_ +
",合理区间:[" + DAA::double2strLimit(limit_down_) + "," +
DAA::double2strLimit(limit_up_) + "]" + unit_;
}
logger_->Debug()
<< "报警!!!!" << msg << ",last_alarm_time_"
<< mix_cc::mix_time_t(last_alarm_time_).to_formatted_time()
<< endl;
// is_fun_vars_need_reset_ = true;
return utility::build_alarm_info(
utility::get_msg_level(limit_down_, limit_up_, result_value),
rule_id_, rule_name_, "EXP4", msg, this->get_alarm_time());
}
}
///<逻辑条件
else {
if (result_value) {
rule_stat_.alarm_value = result_value;
std::string msg_tag = "";
auto msg = rule_name_ + " " + error_str_ + msg_tag;
logger_->Debug()
<< "报警!!!!" << msg << ",last_alarm_time_"
<< mix_cc::mix_time_t(last_alarm_time_).to_formatted_time()
<< endl;
// is_fun_vars_need_reset_ = true;
return utility::build_alarm_info(MsgLevel::ERROR, rule_id_,
rule_name_, "EXP3", msg,
this->get_alarm_time());
}
}
} else if (act_timeout()) {
is_fun_vars_need_reset_ = true;
return this->get_timeout_alarm();
return AlarmInfo{};
}
}
// 不是动作反馈
else {
// print_exp_vars();
///< 变量-上下限-----2
if (exp_type_ == ExpType::Bound) {
if (filter_flag_ == true && this->detect_up_down(result_value)) {
///<共享内存
rule_stat_.alarm_value = result_value;
///<报警
auto msg = error_str_ + ":" + DAA::double2str(result_value) + unit_ +
",合理区间:[" + DAA::double2strLimit(limit_down_) + "," +
DAA::double2strLimit(limit_up_) + "]" + unit_;
logger_->Debug() << msg << endl;
this->query_time_range_.set_left(query_time_range_.get_right() -
delay_time_); //
is_fun_vars_need_reset_ = true;
return utility::build_alarm_info(MsgLevel::ERROR, rule_id_,
rule_name_, "EXP2", msg,
this->get_alarm_time());
}
}
///< 上下限 保持时间-------5
else if (exp_type_ == ExpType::BoundHoldTime) {
bool is_over_up_down =
this->detect_up_down(result_value); ///<当前数据是否超范围
if (!filter_flag_) {
/*前提条件不满足*/
act_start_time_ = this->now_time_; ///<重置开始时间 用于计算保持时间
act_started_ = false; ///<不满足 状态
} else {
/*前提条件满足*/
/*检查范围*/
if (is_over_up_down) {
/*超范围*/
if (!act_started_) {
// 首次检测到异常,记录开始时间
act_started_ = true;
act_start_time_ = this->now_time_;
}
/*检查时间*/
if ((hold_time_ <= delay_time_) ||
(now_time_ - act_start_time_ > hold_time_)) {
///<共享内存
rule_stat_.alarm_value = result_value;
///<报警
auto msg = error_str_ + ":" + DAA::double2str(result_value) +
unit_ + ",合理区间:[" +
DAA::double2strLimit(limit_down_) + "," +
DAA::double2strLimit(limit_up_) + "]" + unit_;
print_exp_vars();
this->query_time_range_.set_left(query_time_range_.get_right() -
delay_time_); //
is_fun_vars_need_reset_ = true;
act_start_time_ =
this->now_time_; ///<重置开始时间 用于计算保持时间
act_started_ = false;
return utility::build_alarm_info(
utility::get_msg_level(limit_down_, limit_up_, result_value),
rule_id_, rule_name_, "EXP5", msg, this->get_alarm_time());
}
} else {
act_start_time_ = this->now_time_; ///<重置开始时间 用于计算保持时间
act_started_ = false;
}
}
}
///<实时逻辑
else {
if (act_triggered_) {
rule_stat_.alarm_value = 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_); //
is_fun_vars_need_reset_ = true;
return utility::build_alarm_info(MsgLevel::ERROR, rule_id_,
rule_name_, "EXP1", msg,
this->get_alarm_time());
}
}
}
} catch (const std::exception &e) {
// std::throw_with_nested(
// mix_cc::Exception(-1, "mon_proc error", BOOST_CURRENT_LOCATION));
gb_logger_->log_error("rule_name:" + rule_name_ + ",error:" + e.what());
return AlarmInfo{};
}
return AlarmInfo{};
}
bool ExpBase::get_cycled_cron() {
auto now = system_clock::now();
if ((now - last_run_start_time_) > std::chrono::minutes(1)) {
last_run_start_time_ = now;
} else {
return false;
}
return true;
}
mix_cc::json ExpBase::exec_cron() {
if (this->get_cycled_cron()) {
if (this->exp_type_ == ExpType::Bound ||
this->exp_type_ == ExpType::CondBound ||
this->exp_type_ == ExpType::BoundHoldTime) {
int stat_size = this->cron_proc();
logger_->Debug() << this->rule_name_ << ",cron 统计数据量:" << stat_size
<< std::endl;
}
}
return {};
}
bool ExpBase::act_start_done() {
// 如果动作未开始且前提条件满足
if (!act_started_ && act_triggered_) {
// 则认为动作开始,并置动作开始时间为当前时间
act_started_ = true;
act_start_time_ = this->now_time_;
mm_vars["stime"] =
duration_cast<milliseconds>(now_time_.time_since_epoch()).count();
mm_vars["time"] = 0;
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)];
// 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["up_tag" + std::to_string(i + 1)] = 0;
mm_vars["dw_tag" + std::to_string(i + 1)] = 0;
mm_vars["mv2_tag" + std::to_string(i + 1)] = 0;
mm_vars["mv2_p" + std::to_string(i + 1)] = 0;
mm_vars["up_tag" + std::to_string(i + 1)] =
0 + (int)(mm_vars["p" + std::to_string(i + 1)] == 0 &&
mm_vars["tag" + std::to_string(i + 1)] == 1);
mm_vars["dw_tag" + std::to_string(i + 1)] =
0 + (int)(mm_vars["p" + std::to_string(i + 1)] == 1 &&
mm_vars["tag" + 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;
} else if (!act_started_ && !act_triggered_) {
is_fun_vars_need_reset_ = true;
}
return false;
}
int ExpBase::cron_proc() {
int size_data = 0;
this->refresh_now_time();
if (exp_type_ == ExpType::Bound || exp_type_ == ExpType::CondBound ||
exp_type_ == ExpType::BoundHoldTime) {
/*只保存有上下限的,2-监控变量-上下限4-动作反馈-上下限5-监控变量-上下限-持续*/
if (sta_ptr_ == nullptr) {
logger_->Debug() << rule_name_ << " sta_ptr_ == nullptr" << endl;
sta_ptr_ = std::make_unique<DAA::STA>(rule_id_, rule_name_);
this->sta_ptr_->update_ci_dist();
last_load_time_ = chrono::system_clock::now();
}
if (now_time_ - last_load_time_ > hours(CronUpdateDelay)) {
this->sta_ptr_->update_ci_dist();
last_load_time_ = now_time_;
}
this->rule_stat_.stat_values.clear();
SingletonTemp<EqpStat>::GetInstance().get_stat_values(this->rule_id_,
this->rule_stat_);
if (!this->rule_stat_.stat_values.empty()) {
size_data = this->rule_stat_.stat_values.size();
logger_->Debug() << rule_name_ << ",this->rule_stat_ size:" << size_data
<< endl;
if (sta_ptr_->is_init()) {
for (int i = 0; i < size_data; i++) {
sta_ptr_->dist_add(this->rule_stat_.stat_values[i]);
}
} else {
double max_data =
*(std::max_element(this->rule_stat_.stat_values.begin(),
this->rule_stat_.stat_values.end()));
double min_data =
*(std::min_element(this->rule_stat_.stat_values.begin(),
this->rule_stat_.stat_values.end()));
double range = (max_data - min_data) / double(DAA::STA_SIZE_MIN);
logger_->Debug() << "max:" << max_data << ",min:" << min_data
<< ",range:" << range << endl;
if (range < 0.1) {
range = 0.1;
}
if (sta_ptr_->init(range, min_data)) {
for (int i = 0; i < size_data; i++) {
sta_ptr_->dist_add(this->rule_stat_.stat_values[i]);
}
}
}
logger_->Debug() << rule_name_ << ",sta_ptr_ size:" << sta_ptr_->size()
<< endl;
sta_ptr_->store_db2();
}
this->rule_stat_.stat_values.clear();
this->rule_stat_.stat_values.shrink_to_fit();
}
return size_data;
}
bool ExpBase::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 ExpBase::act_done() {
// 如果动作已开始 刷新 mv2_tag[n]
if (act_started_) {
/*time :动作开始-当前时刻 的时间*/
mm_vars["time"] = mm_vars["now"] - mm_vars["stime"];
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;
}
mm_vars["up_tag" + std::to_string(i + 1)] +=
(int)(mm_vars["p" + std::to_string(i + 1)] == 0 &&
mm_vars["tag" + std::to_string(i + 1)] == 1);
mm_vars["dw_tag" + std::to_string(i + 1)] +=
(int)(mm_vars["p" + std::to_string(i + 1)] == 1 &&
mm_vars["tag" + std::to_string(i + 1)] == 0);
}
}
/*-----------根据最新变量计算feedback结果-----------*/
feedback_triggered_ = static_cast<bool>(exp_feedback_->evaluate());
/*-----------根据最新变量计算feedback结果-----------*/
// 如果动作处于开始状态,且反馈模式触发
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 ExpBase::act_timeout() {
//-32768 无限制
if (time_out_ == milliseconds(-32768)) {
// 重置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;
mm_vars["up_tag" + std::to_string(i + 1)] = 0;
mm_vars["dw_tag" + std::to_string(i + 1)] = 0;
this->logger_->Debug()
<< "mv2_tag" + std::to_string(i + 1)
<< ",up_tag" + std::to_string(i + 1)
<< ",dw_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)] << endl;
mm_vars["mv2_tag" + std::to_string(i + 1)] = 0;
mm_vars["mv2_p" + std::to_string(i + 1)] = 0;
mm_vars["up_tag" + std::to_string(i + 1)] = 0;
mm_vars["dw_tag" + std::to_string(i + 1)] = 0;
}
return true;
}
return false;
}
// 得到报警超时信息
AlarmInfo ExpBase::get_timeout_alarm() {
if (!m_timemode) {
return AlarmInfo{};
}
string msg =
rule_name_ + " 反馈超时:" + std::to_string(time_out_.count()) + " ms";
logger_->Debug() << msg << endl;
return utility::build_alarm_info(MsgLevel::ERROR, rule_id_, rule_name_,
"EXPACT", msg, query_time_range_);
}
int ExpBase::reload_config_exp_feedback() {
int res = 0;
// 获取feedback信息
if (rule_json_.at("function").at("action_start").contains("param")) {
//是否保持
keep_mode_ = std::stoi(rule_json_.at("function")
.at("action_start")
.at("param")
.at("hold")
.at("value")
.get<std::string>());
logger_->Debug() << "keep:" << keep_mode_ << endl;
//超时时间
time_out_ = milliseconds(std::stoi(rule_json_.at("function")
.at("action_end")
.at("param")
.at("timeout")
.at("value")
.get<std::string>()));
logger_->Debug() << "init timeout:" << time_out_.count() << endl;
// 如果超时时间小于3分钟则默认为超时时间为3分钟
if (time_out_ < minutes(3) && time_out_ != milliseconds(-32768)) {
time_out_ = minutes(3);
}
logger_->Debug() << "timeout:" << time_out_.count() << endl;
auto tmp_exp = string(rule_json_.at("function")
.at("action_end")
.at("value")
.get<std::string>());
exp_str_ = get_macro_replaced_exp(tmp_exp);
res += init_hold_exp_str(exp_str_);
auto fun_res = fun_vars_.add_exp_str(exp_str_, &mm_vars);
res += fun_res.first ? 0 : -1;
exp_str_ = fun_res.second;
if (rule_id_ == "28c1d627-1a8a-426b-9070-eea3c906c53c") {
logger_->Debug() << exp_str_ << ",fun_res first:" << fun_res.first
<< ",second:" << fun_res.second << std::endl;
}
auto messy_code = exp_messy_code_check(exp_str_);
if (messy_code == -1) {
this->error_code_list_.push_back(
{ErrorType::EnCodeError, ErrorLocation::FBExp});
res += messy_code;
}
// 构建feedback表达式
if (exp_feedback_ == nullptr && exp_str_ != "") {
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()
<< ",location:" << BOOST_CURRENT_LOCATION << endl;
this->error_code_list_.push_back(
{ErrorType::CalError, ErrorLocation::FBExp});
return -1;
}
}
} else {
time_out_ = milliseconds(600000);
}
// 获取监控变量信息
auto tmp_exp =
rule_json_.at("function").at("result").at("value").get<std::string>();
exp_str_ = get_macro_replaced_exp(tmp_exp);
res += init_hold_exp_str(exp_str_);
auto fun_res = fun_vars_.add_exp_str(exp_str_, &mm_vars);
res += fun_res.first ? 0 : -1;
exp_str_ = fun_res.second;
auto messy_code = exp_messy_code_check(exp_str_);
if (messy_code == -1) {
this->error_code_list_.push_back(
{ErrorType::EnCodeError, ErrorLocation::ResultExp});
res += messy_code;
}
// 如果结果表达式没有初始化,则初始化之后再次使用
if (exp_result_ == nullptr && exp_str_ != "") {
try {
exp_result_ =
std::make_unique<mix_cc::matheval::Expression>(exp_str_, &mm_vars);
logger_->Debug() << exp_str_ << ":" << exp_result_->evaluate() << endl;
} catch (const std::exception &e) {
logger_->Error() << exp_result_ << "计算错误:" << e.what()
<< ",location:" << BOOST_CURRENT_LOCATION << endl;
this->error_code_list_.push_back(
{ErrorType::CalError, ErrorLocation::ResultExp});
}
}
if (exp_str_.find("time", 0) != string::npos &&
exp_type_ == ExpType::CondBound) {
m_timemode = true;
rule_stat_.unit = "ms"; ///<时间的单位是 ms
} else {
m_timemode = false;
}
return res;
}
// 刷新共享内存所对应的变量
int ExpBase::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]在上一个动作周期的数值
double current =
SingletonTemplate<GlobaltemSharedMemory>::GetInstance()[m_tags[i]];
mm_vars[var_cache_.p_keys[i]] = mm_vars[var_cache_.tag_keys[i]];
mm_vars[var_cache_.tag_keys[i]] = current;
for (size_t j = pv_num_ - 1; j > 0; j--) {
mm_vars[var_cache_.pv_keys[i][j]] = mm_vars[var_cache_.pv_keys[i][j - 1]];
}
mm_vars[var_cache_.pv_keys[i][0]] = current;
// 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]];
// auto pv_str = "pv" + std::to_string(i + 1);
// // mm_vars[pv_str + "_10"] = mm_vars[pv_str + "_9"];
// // mm_vars[pv_str + "_9"] = mm_vars[pv_str + "_8"];
// // mm_vars[pv_str + "_8"] = mm_vars[pv_str + "_7"];
// // mm_vars[pv_str + "_7"] = mm_vars[pv_str + "_6"];
// // mm_vars[pv_str + "_6"] = mm_vars[pv_str + "_5"];
// mm_vars[pv_str + "_5"] = mm_vars[pv_str + "_4"];
// 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"] =
duration_cast<milliseconds>(now_time_.time_since_epoch()).count();
// 设置right的时间
this->fun_vars_.refresh_fun_vars(false, &mm_vars);
this->query_time_range_.set_right(now_time_);
refresh_hold_var();
return 0;
}
// 重新载入数据源配置
int ExpBase::reload_config_data_source() {
int res = 0;
if (!rule_json_.contains("datasource")) {
data_source_ = 0;
logger_->Debug()
<< "默认数据源为iHyerDB data source[0:iHyerDB1: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:iHyerDB1: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 res;
}
// 刷新对应ihd cache内第row行的数据变量
int ExpBase::refresh_exp_vars_ihd(int row) {
// modify 20260107
// 检查矩阵大小和索引有效性
if (queried_data_.rows() == 0 || queried_data_.cols() == 0) {
logger_->Error() << "refresh_exp_vars_ihd: queried_data_ 为空!" << endl;
return -1;
}
if (row < 0 || row >= queried_data_.rows()) {
logger_->Error() << "refresh_exp_vars_ihd: row索引 " << row
<< " 超出范围 [0, " << queried_data_.rows() - 1 << "]"
<< endl;
return -1;
}
if (static_cast<int>(m_tags.size()) > queried_data_.cols()) {
logger_->Error() << "refresh_exp_vars_ihd: m_tags.size() " << m_tags.size()
<< " 超出列数 " << queried_data_.cols() << endl;
return -1;
}
// 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 + "_10"] = mm_vars[pv_str + "_9"];
// mm_vars[pv_str + "_9"] = mm_vars[pv_str + "_8"];
// mm_vars[pv_str + "_8"] = mm_vars[pv_str + "_7"];
// mm_vars[pv_str + "_7"] = mm_vars[pv_str + "_6"];
// mm_vars[pv_str + "_6"] = mm_vars[pv_str + "_5"];
mm_vars[pv_str + "_5"] = mm_vars[pv_str + "_4"];
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();
this->fun_vars_.refresh_fun_vars(false, &mm_vars);
refresh_hold_var();
return 0;
}
// 程序启动时刻的,首次刷新变量数据
// 防止程序因为p1 pv1类似的变量导致程序的变量差值信息错误
int ExpBase::first_fill_mm_vars() {
/*-------动作反馈标记-重置------*/
logger_->Debug() << "-first_fill_mm_vars()-----mm_vars,size:"
<< mm_vars.size() << ",mm_vars..empty():" << mm_vars.empty()
<< std::endl;
// if (!mm_vars.empty()) {
// logger_->Debug() << " mm_vars.begin()->first:" << mm_vars.begin()->first
// << endl;
// }
this->act_started_ = false;
this->act_triggered_ = false;
this->feedback_triggered_ = false;
/*-------动作反馈标记-重置------*/
if (data_source_ == DataSource::MEMORY) {
for (unsigned int i = 0; i < m_tags.size(); i++) {
auto pv_str = "pv" + std::to_string(i + 1);
if (this->rule_id_ == "fba8df61-8a16-4a0e-80de-6e25aaf3d037") {
logger_->Debug() << "m_tags[" << i << "]:" << m_tags[i]
<< ",m_tags.size():" << m_tags.size() << "-----0------"
<< std::endl;
}
double value =
SingletonTemplate<GlobaltemSharedMemory>::GetInstance()[m_tags[i]];
if (this->rule_id_ == "fba8df61-8a16-4a0e-80de-6e25aaf3d037") {
logger_->Debug() << "m_tags[" << i << "]:" << m_tags[i]
<< ",m_tags.size():" << m_tags.size() << "-----1------"
<< ",value:" << value
<< "mm_vars.size:" << mm_vars.size() << std::endl;
}
if (this->rule_id_ == "fba8df61-8a16-4a0e-80de-6e25aaf3d037") {
logger_->Debug() << "s" + std::to_string(i + 1) << ",m_tags[" << i
<< "]:" << m_tags[i]
<< ",m_tags.size():" << m_tags.size() << "-----2-----"
<< std::endl;
}
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["up_tag" + std::to_string(i + 1)] = 0;
mm_vars["dw_tag" + 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[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[pv_str + "_5"] = value;
// mm_vars[pv_str + "_6"] = value;
// mm_vars[pv_str + "_7"] = value;
// mm_vars[pv_str + "_8"] = value;
// mm_vars[pv_str + "_9"] = value;
// mm_vars[pv_str + "_10"] = value;
// if (this->rule_id_ == "fba8df61-8a16-4a0e-80de-6e25aaf3d037") {
if (this->exp_type_ == -1) {
logger_->Debug() << "m_tags[" << i << "]:" << m_tags[i]
<< ",m_tags.size():" << m_tags.size() << "-----3-----"
<< "mm_vars.size:" << mm_vars.size() << std::endl;
}
}
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();
query_time_range_.set_left(now_time_ - 10s); ///<防止间隔时间太短查不到数据
query_time_range_.set_right(now_time_ - 5s); ///<防止间隔时间太短查不到数据
this->refresh_ihd_cache();
if (queried_data_.rows() == 0) {
logger_->Debug() << "time:"
<< mix_cc::mix_time_t(this->query_time_range_.get_left())
.to_formatted_time()
<< "~"
<< mix_cc::mix_time_t(
this->query_time_range_.get_right())
.to_formatted_time()
<< ",diff_time:"
<< std::chrono::duration_cast<milliseconds>(
query_time_range_.get_right() -
query_time_range_.get_left())
.count()
<< endl;
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["up_tag" + std::to_string(i + 1)] = 0;
mm_vars["dw_tag" + 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[pv_str + "_5"] = tmp_val;
// mm_vars[pv_str + "_6"] = tmp_val;
// mm_vars[pv_str + "_7"] = tmp_val;
// mm_vars[pv_str + "_8"] = tmp_val;
// mm_vars[pv_str + "_9"] = tmp_val;
// mm_vars[pv_str + "_10"] = tmp_val;
mm_vars["stime"] = 0;
mm_vars["now"] = 0;
mm_vars["etime"] = 0;
mm_vars["time"] = 0;
}
}
return 0;
}
int ExpBase::reload_config_exp_act() {
// 根据key对不同版本的算法都进行取值
int res = 0;
if (rule_json_.at("function").contains("action_start")) {
auto tmp_exp = rule_json_.at("function")
.at("action_start")
.at("value")
.get<std::string>();
exp_str_ = get_macro_replaced_exp(tmp_exp);
res += init_hold_exp_str(exp_str_);
auto fun_res = fun_vars_.add_exp_str(exp_str_, &mm_vars);
res += fun_res.first ? 0 : -1;
exp_str_ = fun_res.second;
feedback_mode_ = true;
auto messy_code = exp_messy_code_check(exp_str_);
if (messy_code == -1) {
this->error_code_list_.push_back(
{ErrorType::EnCodeError, ErrorLocation::ActExp});
res += messy_code;
}
} else if (rule_json_.at("function").contains("result")) {
if (rule_json_.at("function").contains("filter_exp")) {
auto tmp_exp = rule_json_.at("function")
.at("filter_exp")
.at("value")
.get<std::string>();
exp_str_ = get_macro_replaced_exp(tmp_exp);
res += init_hold_exp_str(exp_str_);
auto fun_res = fun_vars_.add_exp_str(exp_str_, &mm_vars);
res += fun_res.first ? 0 : -1;
exp_str_ = fun_res.second;
feedback_mode_ = false;
auto messy_code = exp_messy_code_check(exp_str_);
if (messy_code == -1) {
this->error_code_list_.push_back(
{ErrorType::EnCodeError, ErrorLocation::ActExp});
res += messy_code;
}
if (exp_feedback_ == nullptr && exp_str_ != "") {
try {
exp_feedback_ = std::make_unique<mix_cc::matheval::Expression>(
exp_str_, &mm_vars);
logger_->Debug() << "filter_exp exp_feedback_:" << exp_str_ << "="
<< exp_feedback_->evaluate() << endl;
} catch (const std::exception &e) {
logger_->Error() << "filter_exp exp_feedback_:" << exp_str_
<< "计算出错:" << e.what()
<< ",location:" << BOOST_CURRENT_LOCATION << endl;
this->error_code_list_.push_back(
{ErrorType::CalError, ErrorLocation::FBExp});
return -1;
}
} else {
logger_->Error() << "filter_exp exp_feedback_:"
<< "为空"
<< ",location:" << BOOST_CURRENT_LOCATION << endl;
this->error_code_list_.push_back(
{ErrorType::CalError, ErrorLocation::FBExp});
return -1;
}
}
auto tmp_exp =
rule_json_.at("function").at("result").at("value").get<std::string>();
exp_str_ = get_macro_replaced_exp(tmp_exp);
res += init_hold_exp_str(exp_str_);
auto fun_res = fun_vars_.add_exp_str(exp_str_, &mm_vars);
res += fun_res.first ? 0 : -1;
exp_str_ = fun_res.second;
feedback_mode_ = false;
auto messy_code = exp_messy_code_check(exp_str_);
if (messy_code == -1) {
this->error_code_list_.push_back(
{ErrorType::EnCodeError, ErrorLocation::ActExp});
res += messy_code;
}
}
if (exp_act_ == nullptr && exp_str_ != "") {
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()
<< ",location:" << BOOST_CURRENT_LOCATION << endl;
this->error_code_list_.push_back(
{ErrorType::CalError, ErrorLocation::ActExp});
return -1;
}
}
if (rule_json_.at("output").contains("error")) {
try {
error_str_ =
rule_json_.at("output").at("error").at("value").get<std::string>();
} catch (const std::exception &e) {
logger_->Error() << "output,error出错" << e.what()
<< ",location:" << BOOST_CURRENT_LOCATION << endl;
error_message_str_ += "报警内容格式异常!";
return -1;
}
}
return 0;
}
int ExpBase::reload_config_up_down() {
try {
if (rule_json_.at("function").at("result").contains("param")) {
if (rule_json_.at("function").at("result").at("param").contains("unit")) {
unit_ = rule_json_.at("function")
.at("result")
.at("param")
.at("unit")
.at("value")
.get<std::string>();
}
rule_stat_.unit = unit_;
limit_down_ = std::stod(rule_json_.at("function")
.at("result")
.at("param")
.at("limit_down")
.at("value")
.get<std::string>());
limit_up_ = std::stod(rule_json_.at("function")
.at("result")
.at("param")
.at("limit_up")
.at("value")
.get<std::string>());
this->rule_stat_.current_value = (limit_down_ + limit_up_) / 2;
if (-32768 == (int)limit_down_ && (int)limit_up_ != (int)limit_down_) {
this->rule_stat_.current_value = 0;
this->detect_mode_ = DetectMode::OnlyRight;
} else if ((-32768 == (int)limit_up_ || 32768 == (int)limit_up_ ||
32767 == (int)limit_up_) &&
(int)limit_up_ != (int)limit_down_) {
this->detect_mode_ = DetectMode::OnlyLeft;
this->rule_stat_.current_value = limit_down_ + 1;
} else if (-32768 == (int)limit_up_ &&
(int)limit_up_ == (int)limit_down_) {
this->detect_mode_ = DetectMode::ErrorMode;
}
///共享内存参数
logger_->Info() << rule_name_
<< ",detect_mode_[0-双侧1-仅left2-仅right3-错误]:"
<< detect_mode_ << ",limit_down:" << limit_down_ << ","
<< "limit_up:" << limit_up_ << std::endl;
this->rule_stat_.limit_down = limit_down_;
this->rule_stat_.limit_up = limit_up_;
}
if (rule_json_.contains("self_learning")) {
this->dist_mode_ = rule_json_.at("self_learning").at("mode").get<int>();
this->is_learning_ =
rule_json_.at("self_learning").at("is_learning").get<bool>();
logger_->Debug() << "is_learning_:" << is_learning_ << std::endl;
}
} catch (const std::exception &e) {
logger_->Error() << e.what() << ",location:" << BOOST_CURRENT_LOCATION
<< endl;
return -1;
}
return 0;
}
int ExpBase::reload_config_up_down_hold_time() {
try {
if (rule_json_.at("function")
.at("result")
.at("param")
.contains("hold_time")) {
hold_time_ = milliseconds(std::stoi(rule_json_.at("function")
.at("result")
.at("param")
.at("hold_time")
.at("value")
.get<std::string>()));
logger_->Info() << rule_name_ << "hold_time:" << hold_time_.count()
<< std::endl;
}
} catch (const std::exception &e) {
logger_->Error() << e.what() << ",location:" << BOOST_CURRENT_LOCATION
<< endl;
return -1;
}
return 0;
}
// 打印表达式信息
void ExpBase::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 ExpBase::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 ExpBase::set_usable(bool usable) {
// if (rule_id_ == "ded572f3-0572-40f8-a86c-fca82e9497dd") {
// logger_->Debug() << "------test--------" << BOOST_CURRENT_FUNCTION <<
// endl;
// }
this->refresh_counts_ = 0;
if (this->is_usable_) {
this->first_fill_mm_vars(); ///<打破原动作状态
}
AlgBase::set_usable(usable);
}
int ExpBase::refresh_hold_var() {
if (hold_times_.empty()) {
return 0;
} else {
for (map<std::string, std::unique_ptr<HoldTime>>::iterator iter =
hold_times_.begin();
iter != hold_times_.end(); iter++) {
mm_vars[iter->first] =
double(iter->second->update_value(mm_vars[iter->second->tagi]));
}
return 0;
}
}
int ExpBase::init_hold_exp_str(const std::string &exp_str) {
int res = 0;
try {
auto hold_sub_strs = HoldTime::find_substr(exp_str, "_HE");
bool flag;
double timeM;
std::string tagi;
std::string var_name;
for (auto sub_str : hold_sub_strs) {
std::tie(flag, timeM, tagi, var_name) = HoldTime::find_hold(sub_str);
if (flag) {
if (hold_times_.find(var_name) == hold_times_.end()) {
hold_times_.emplace(std::make_pair(
var_name, std::make_unique<HoldTime>(timeM, tagi, var_name)));
}
} else {
if (timeM) {
logger_->Error() << "hold结构结构不正确," << tagi << std::endl;
return -1;
}
}
}
refresh_hold_var();
} catch (const std::exception &e) {
logger_->Debug() << "ExpBase::init_hold_exp_str:" << e.what()
<< ",location:" << BOOST_CURRENT_LOCATION << endl;
return -1;
}
return res;
}
int ExpBase::exp_messy_code_check(const std::string &exp_str) {
for (char e_char : exp_str) {
if (e_char > 127 || e_char < 0) {
this->logger_->Error() << "表达式存在中文字符或乱码 tmp_exp:" << exp_str
<< " :" << e_char << ":" << int(e_char) << endl;
return -1;
}
}
return 0;
}
int ExpBase::reload_ci_dist() {
if (this->exp_type_ != ExpType::Bound &&
this->exp_type_ != ExpType::CondBound &&
this->exp_type_ != ExpType::BoundHoldTime) {
return 0;
}
last_load_time_ = now_time_;
if (this->dist_mode_ != 0) {
mix_cc::float_range_t dist_range;
if (this->dist_mode_ == DistMode::Online) {
dist_range = DAA::STA::select_from_t_rule_feature(this->rule_id_);
} else if (this->dist_mode_ == DistMode::Offline) {
dist_range = DAA::STA::select_from_t_sample_mag(this->rule_id_);
}
if (dist_range.get_distance() == 0 ||
dist_range.get_left() > dist_range.get_right()) {
logger_->Error() << "区间不合法![" << dist_range.get_left() << ","
<< dist_range.get_right() << "]" << endl;
return -1;
}
this->limit_down_ = dist_range.get_left();
this->limit_up_ = dist_range.get_right();
this->rule_stat_.limit_down = limit_down_;
this->rule_stat_.limit_up = limit_up_;
this->rule_stat_.current_value =
(this->limit_down_ + this->limit_up_) / 2; ///<页面展示
logger_->Info()
<< "更新置信区间,[" << dist_range.get_left() << ","
<< dist_range.get_right() << "]"
<< ",type[0-手动设置的区间;1-在线更新的区间2-离线分析的区间]:"
<< this->dist_mode_ << endl;
}
return 0;
}
void ExpBase::query_ihd_data() {
vector<string> ihd_tags = m_tags;
// if (this->prr_ > 0) {
// switch (this->prr_) {
// case PRR::None:
// break;
// case PRR::EntRunning:
// ihd_tags.push_back(string(CMemVar::Const()->UnitNo) + "_" +
// string(CMemVar::Const()->ent_run_state));
// break;
// case PRR::ACDRunning:
// ihd_tags.push_back(string(CMemVar::Const()->UnitNo) + "_" +
// string(CMemVar::Const()->acd_run_state));
// break;
// case PRR::AXTRunning:
// ihd_tags.push_back(string(CMemVar::Const()->UnitNo) + "_" +
// string(CMemVar::Const()->axt_run_state));
// break;
// case PRR::TCMRunning:
// ihd_tags.push_back(string(CMemVar::Const()->UnitNo) + "_" +
// string(CMemVar::Const()->tcm_run_state));
// break;
// default:
// break;
// }
// }
auto queried_batch_maybe = mix_cc::ihd::make_query_batch_maybe(
ihd_tags, query_time_range_, this->ihd_min_time_particles_);
if (queried_batch_maybe.is_nothing()) {
queried_time_.clear();
queried_data_ = typename decltype(queried_batch_maybe)::type::Mat2d{};
gb_logger_->log_error("Tag点没有查到相应的信息");
return;
}
auto queried_bath = queried_batch_maybe.unsafe_get_just();
auto result_maybe = mix_cc::ihd::read_data_with_time_maybe(&queried_bath);
if (result_maybe.is_nothing()) {
queried_time_.clear();
queried_data_ = typename decltype(queried_batch_maybe)::type::Mat2d{};
gb_logger_->log_error("Tag点没有查到相应的数据");
return;
}
std::tie(queried_time_, queried_data_) = result_maybe.unsafe_get_just();
}
void ExpBase::task_mon_pro() {
/*1.查数据
*2.
*/
query_ihd_data(); /*查询m_tags+运行前提条件(如果有,放置在最后一列)*/
logger_->Debug() << rule_name_ << ",ihd size:" << queried_data_.size()
<< endl;
for (auto i = 0; i < queried_data_.rows(); i++) {
refresh_exp_vars_ihd(i);
if (this->refresh_counts_ < 3) {
this->refresh_counts_++;
} else {
auto res = task_base_proc();
if (res.is_valid && this->task_prr(i)) {
// TaskShm::TaskRecordPtr.get()
// ->
// operator[](exp_type_ * 1000 + task_seq)
// .data_record[TaskShm::TimeRecordPtr.get()
// ->
// operator[](exp_type_ * 1000 + task_seq)
// .data_size++] = res.value;
TaskShm::TaskRecordPtr.get()
->
operator[](exp_type_ * 1000 + task_seq)
.data_record[task_data_size++] = res.value;
this->sta_ptr_->running_stat_add(res.value);
}
}
}
}
string ExpBase::get_id(mix_cc::time_range_t time_range) {
// return this->rule_id_.substr(3, 9) + "_" +
// std::to_string(time_range.get_left().time_since_epoch().count()) +
// "_" +
// std::to_string(time_range.get_right().time_since_epoch().count());
this->sample_id_ =
this->rule_id_.substr(3, 21) + "_" +
std::to_string(std::chrono::duration_cast<std::chrono::milliseconds>(
time_range.get_left().time_since_epoch())
.count()) +
"_" +
std::to_string(std::chrono::duration_cast<std::chrono::milliseconds>(
time_range.get_right().time_since_epoch())
.count());
return this->sample_id_;
}
TaskReturnType ExpBase::task_base_proc() {
TaskReturnType task_return_data;
double result_value = 0;
// logger_->Debug() << "task_base_proc()---1" << endl;
try {
// 获得是否满足前提条件表达式
result_value = exp_act_->evaluate(); ///< 2/5用于 非反馈 上下限
act_triggered_ = static_cast<bool>(result_value);
// 检测是否是表达式-反馈模式
if (feedback_mode_) {
// 如果是表达式反馈-模式,检测是否满足反馈条件
if (act_start_done() || act_not_hold()) {
return task_return_data;
}
// feedback_triggered_ = static_cast<bool>(exp_feedback_->evaluate());
// 如果所有前提动作和条件均满足
if (act_done()) {
result_value = exp_result_->evaluate();
print_exp_vars();
// 并且数据合法
if (!std::isnan(result_value)) {
task_return_data.is_valid = true;
task_return_data.value = result_value;
return task_return_data;
}
} else if (act_timeout()) {
// 如果超时,则返回
return task_return_data;
}
}
// 表达式-样本,无需反馈
else if (!std::isnan(result_value)) {
if (exp_feedback_ != nullptr) {
if (exp_feedback_->evaluate()) {
task_return_data.is_valid = true;
task_return_data.value = result_value;
logger_->Debug() << "实时值:" << result_value << endl;
print_exp_vars();
}
} else {
task_return_data.is_valid = true;
task_return_data.value = result_value;
}
return task_return_data;
}
} catch (const std::exception &e) {
this->logger_->Error() << "ExpBase::task_base_proc():" << e.what()
<< ",location:" << BOOST_CURRENT_LOCATION << endl;
return task_return_data;
}
return task_return_data;
}
int ExpBase::update_t_sample_mag(bool vlid) {
T_SAMPLE_MAG tsm;
auto update_ret = exec<db2_t, size_t>(
update(tsm)
.set(tsm.result() = this->sample_result_,
tsm.type() = this->sample_type_, tsm.usable() = 0,
tsm.starttime() =
mix_cc::mix_time_t(this->task_time_range_.get_left()),
tsm.endtime() =
mix_cc::mix_time_t(this->task_time_range_.get_right()),
tsm.verify() = (vlid ? 1 : 3))
.where(tsm.sampleid() = this->sample_id_,
tsm.ruleId() = this->rule_id_));
if (!update_ret.is_nothing()) {
auto res = update_ret.unsafe_get_just();
if (res == 0) {
auto inset_ret = exec<db2_t, size_t>(insert_into(tsm).set(
tsm.ruleId() = this->rule_id_, tsm.result() = this->sample_result_,
tsm.type() = this->sample_type_, tsm.sampleid() = this->sample_id_,
tsm.usable() = 0,
tsm.starttime() =
mix_cc::mix_time_t(this->task_time_range_.get_left()),
tsm.endtime() =
mix_cc::mix_time_t(this->task_time_range_.get_right()),
tsm.verify() = (vlid ? 1 : 3)));
if (inset_ret.is_nothing()) {
logger_->Error() << "T_SAMPLE_MAG,插入数据失败" << std::endl;
return -2;
}
}
} else {
gb_logger_->log_error("T_SAMPLE_MAG 表更新失败:" + rule_name_);
return -1;
}
gb_logger_->log_info(
"T_SAMPLE_MAG更新:" + rule_name_ +
",vlid[true-计算成功false-计算失败]:" + std::to_string(vlid)) +
",结果:" + this->sample_result_;
return 0;
}
bool ExpBase::detect_up_down(const double &value) {
switch (this->detect_mode_) {
case DetectMode::Default:
return value < this->limit_down_ || value > limit_up_;
break;
case DetectMode::OnlyLeft:
return value < limit_down_;
break;
case DetectMode::OnlyRight:
return value > limit_up_;
break;
default:
return false;
break;
}
return false;
}
bool ExpBase::task_prr(int row) {
if (this->prr_ == 1) {
exp_mpdule_ptr_->update(queried_data_, queried_time_, row);
bool prr_result = (bool)exp_mpdule_ptr_->get_value("pre_result");
return prr_result;
}
return true;
}
void ExpBase::reset_dev_data() {
if (glob_process_type == ProcessType::kMon) {
if (exp_type_ == ExpType::Bound || exp_type_ == ExpType::CondBound ||
exp_type_ == ExpType::BoundHoldTime) {
// logger_->Debug() << "reset_dev_data()---1" << endl;
int res = DAA::STA::delete_statistics_data(this->rule_id_);
if (res != 0) {
logger_->Debug() << "DAA::STA::delete_statistics_data(this->rule_id_) "
"存在删除失败的表!"
<< endl;
}
this->reload_config_up_down(); /*7.上下限*/
this->reload_ci_dist();
this->last_load_time_ = chrono::system_clock::now();
SingletonTemp<EqpStat>::GetInstance().update_static(this->rule_id_,
false);
}
}
}
void ExpBase::save_rule_norm_data() {
if (feedback_mode_ && feedback_done_ ||
((exp_type_ == ExpType::Bound || exp_type_ == ExpType::BoundHoldTime) &&
filter_flag_ == true)) {
int64_t default_lt =
mix_cc::mix_time_t(now_time_).to_milliseconds() - 1000 * 5;
int64_t stime = mm_vars["stime"];
int64_t lt = std::min(default_lt, stime);
data_info_.update(lt, mix_cc::mix_time_t(now_time_).to_milliseconds());
} else {
if (con_monitor_.getCurrentState()) {
AlgBase::save_rule_norm_data();
} else {
/*查不到数据,无法保存*/
data_info_.update(mix_cc::mix_time_t(now_time_).to_milliseconds(),
mix_cc::mix_time_t(now_time_).to_milliseconds());
}
}
}
void ExpBase::fun_vars_init() {
string prr_exp = this->exp_mpdule_ptr_->get_exp_str("pre_result");
if (prr_exp == "") {
return;
}
auto fun_res = fun_vars_.add_exp_str(prr_exp, &mm_vars);
}
bool ExpBase::get_prr() {
if (this->prr_ == 1) {
exp_mpdule_ptr_->update();
bool prr_result = (bool)exp_mpdule_ptr_->get_value("pre_result");
this->now_prr_ = prr_result;
if (rule_id_ == string(CMemVar::Const()->printRuleid)) {
logger_->Debug() << "ruleid:" << this->rule_id_
<< ",rulename:" << this->rule_name_
<< " get_prr():" << prr_result << std::endl;
}
if (!this->now_prr_) {
/*-------动作反馈标记-重置------*/
this->act_started_ = false;
this->act_triggered_ = false;
this->feedback_triggered_ = false;
}
return prr_result;
}
now_prr_ = true;
return true;
}
void ExpBase::auto_fun_vars_reset() {
if (is_fun_vars_need_reset_) {
if (rule_id_ == string(CMemVar::Const()->printRuleid)) {
logger_->Debug() << "auto_fun_vars_reset,重置fun_vars_状态!--start"
<< std::endl;
print_exp_vars();
}
this->fun_vars_.refresh_fun_vars(true, &mm_vars);
if (rule_id_ == string(CMemVar::Const()->printRuleid)) {
logger_->Debug() << "auto_fun_vars_reset,重置fun_vars_状态!--end"
<< std::endl;
print_exp_vars();
}
}
is_fun_vars_need_reset_ = false;
}