290 lines
10 KiB
C++
290 lines
10 KiB
C++
|
|
/******************************************************************************************************************
|
||
|
|
* Action instruction algorithm(study sample data online,compare with sample
|
||
|
|
*data)
|
||
|
|
*
|
||
|
|
* arg[0] action expression
|
||
|
|
* arg[1] feedback expression
|
||
|
|
* arg[2] expression of judgment result
|
||
|
|
*
|
||
|
|
* feedback expression
|
||
|
|
* arg[2] expression of judgment result
|
||
|
|
*
|
||
|
|
* 1.0 2020-12-17 zoufuzhou
|
||
|
|
* 1.1 2021-3 c@t add DTW
|
||
|
|
******************************************************************************************************************/
|
||
|
|
#include <base/BitTool.h>
|
||
|
|
#include <dao/DBMag.h>
|
||
|
|
#include <eqpalg/algs/AlgExpTrendSampleMan.h>
|
||
|
|
#include <utility/StringHelper.h>
|
||
|
|
#include <algorithm>
|
||
|
|
|
||
|
|
// add static modules
|
||
|
|
|
||
|
|
extern std::map<std::string, ITEM> glob_items;
|
||
|
|
|
||
|
|
int AlgExpTrendSampleMan::init() {
|
||
|
|
LOG d("AlgExpTrendSampleMan::init", AUTO_CATCH_PID);
|
||
|
|
prev_execution_act_triggered__triggered_ = false;
|
||
|
|
int ret = 0;
|
||
|
|
m_btime = 0;
|
||
|
|
try {
|
||
|
|
|
||
|
|
this->sample_analysis->Init("T_STA_SAMPLE", test_mode_, archive_interval_day_, judge_diff_);
|
||
|
|
int index = atoi(m_sampletag.substr(3).c_str());
|
||
|
|
string tag = "";
|
||
|
|
if (index > 0 && m_tags.size() >= index) {
|
||
|
|
tag = m_tags[index - 1];
|
||
|
|
}
|
||
|
|
d.Debug() << "archive:" << archive_interval_day_ << endl;
|
||
|
|
string dbwhere = " tagname = '" + tag + "'";
|
||
|
|
if (m_json_param["sample"]["datestart"][1].asString() != "" &&
|
||
|
|
m_json_param["sample"]["dateend"][1].asString() != "") {
|
||
|
|
dbwhere += " AND TAGDATE >= TO_DATE ('" +
|
||
|
|
m_json_param["sample"]["datestart"][1].asString() +
|
||
|
|
"','YYYY-MM-DD') and TAGDATE <= TO_DATE ('" +
|
||
|
|
m_json_param["sample"]["dateend"][1].asString() +
|
||
|
|
"','YYYY-MM-DD')";
|
||
|
|
}
|
||
|
|
d.Debug() << "where:" << dbwhere << endl;
|
||
|
|
this->sample_analysis->Read(dbwhere);
|
||
|
|
|
||
|
|
} catch (const std::exception &e) {
|
||
|
|
d.Error() <<mix_cc::get_nested_exception(e) << std::endl;
|
||
|
|
ret = -1;
|
||
|
|
}
|
||
|
|
return ret;
|
||
|
|
}
|
||
|
|
|
||
|
|
AlgExpTrendSampleMan::AlgExpTrendSampleMan(const string &name,
|
||
|
|
const Json::Value &rulejson,
|
||
|
|
const string &ruleId)
|
||
|
|
: AlgBase(name, rulejson, ruleId),
|
||
|
|
AlgExp(name, rulejson, ruleId) {
|
||
|
|
LOG d("AlgExpTrendSampleMan::AlgExpTrendSampleMan", AUTO_CATCH_PID);
|
||
|
|
|
||
|
|
keep_mode_ = m_json_param["action_condition"]["action_hold"][1].asInt();
|
||
|
|
m_modest = m_json_param["action_condition"]["mode"][1].asInt();
|
||
|
|
d.Debug() << "keep:" << keep_mode_ << " mode stat_tools:" << m_modest << endl;
|
||
|
|
archive_interval_day_ = m_json_param["sample"]["archive"][1].asInt();
|
||
|
|
|
||
|
|
m_sampletag = m_json_param["sample"]["tag"][1].asString();
|
||
|
|
StringHelper::Trim(m_sampletag);
|
||
|
|
|
||
|
|
test_mode_ = m_json_param["alarm_option"]["mode"][1].asInt();
|
||
|
|
judge_diff_ = m_json_param["alarm_option"]["value"][1].asDouble();
|
||
|
|
d.Debug() << "modejudge(0: absolute difference, 1: error percentage (%), 2: "
|
||
|
|
"normal value signal (%) 3: trend):"
|
||
|
|
<< test_mode_ << " samplediff:" << judge_diff_ << endl;
|
||
|
|
|
||
|
|
this->init();
|
||
|
|
m_expstr = string(m_json_param["action_condition"]["action_start"][1].asString());
|
||
|
|
exp_act_ = new MathExpression(m_expstr.c_str(), mm_vars);
|
||
|
|
d.Debug() << m_expstr << ":" << exp_act_->evaluate() << endl;
|
||
|
|
|
||
|
|
m_expstr = string(m_json_param["action_condition"]["action_end"][1].asString());
|
||
|
|
exp_feedback_ = new MathExpression(m_expstr.c_str(), mm_vars);
|
||
|
|
d.Debug() << m_expstr << ":" << exp_feedback_->evaluate() << endl;
|
||
|
|
|
||
|
|
// m_expstr = string (m_json_param["alarm_option"]["var"][1].asString());
|
||
|
|
// StringHelper::Trim(m_expstr);
|
||
|
|
m_expstr = m_sampletag;
|
||
|
|
|
||
|
|
// if(m_expstr.find("time",0) != string::npos)
|
||
|
|
if (m_expstr == "time") {
|
||
|
|
m_timemode = true;
|
||
|
|
} else {
|
||
|
|
m_timemode = false;
|
||
|
|
}
|
||
|
|
|
||
|
|
if (exp_act_ == NULL) {
|
||
|
|
exp_act_ = new MathExpression(m_expstr.c_str(), mm_vars);
|
||
|
|
d.Debug() << m_expstr << ":" << exp_act_->evaluate() << endl;
|
||
|
|
}
|
||
|
|
|
||
|
|
if (m_modest == DATA_STAT::HISTORY) {
|
||
|
|
this->malloc_ihd_mem();
|
||
|
|
}
|
||
|
|
d.Debug() << "Init Success" << std::endl;
|
||
|
|
}
|
||
|
|
|
||
|
|
AlgExpTrendSampleMan::~AlgExpTrendSampleMan() {
|
||
|
|
delete exp_act_;
|
||
|
|
delete exp_feedback_;
|
||
|
|
}
|
||
|
|
|
||
|
|
int AlgExpTrendSampleMan::calculate(string &outjson) {
|
||
|
|
LOG d("AlgExpTrendSampleMan::calculate|" + rule_name_, AUTO_CATCH_PID);
|
||
|
|
int ret = 0;
|
||
|
|
outjson = "";
|
||
|
|
|
||
|
|
|
||
|
|
// d.Debug()<<rule_name_<<" datasource:"<<data_source_<<endl;
|
||
|
|
|
||
|
|
try {
|
||
|
|
// d.Debug()<<"m_tags.size():"<<m_tags.size()<<endl;
|
||
|
|
if (m_modest == DATA_STAT::ACTUAL) {
|
||
|
|
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)];
|
||
|
|
if (data_source_ == DataSource::MEMORY) {
|
||
|
|
mm_vars["tag" + std::to_string(i + 1)] =
|
||
|
|
glob_items[m_tags[i]].value;
|
||
|
|
} else {
|
||
|
|
if (ihd_tools_->QuerySnapshot(m_tags[i], &mp_hdRec[i]) == NULL) {
|
||
|
|
mm_vars["tag" + std::to_string(i + 1)] =
|
||
|
|
mp_hdRec[i].NumberValue();
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
ret = this->mon_proc(outjson, mp_hdRec);
|
||
|
|
} else {
|
||
|
|
ret = this->QueryDB3Record();
|
||
|
|
if (ret != NULL) {
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
|
||
|
|
for (int i = 0; i < tag_count_; i++) {
|
||
|
|
for (int j = 0; j < m_tags.size(); j++) {
|
||
|
|
mm_vars["p" + std::to_string(j + 1)] =
|
||
|
|
mm_vars["tag" + std::to_string(j + 1)];
|
||
|
|
mm_vars["tag" + std::to_string(j + 1)] =
|
||
|
|
records_queried_[j][i].NumberValue();
|
||
|
|
// records_queried_[j][i].
|
||
|
|
}
|
||
|
|
ret = this->mon_proc(outjson, &records_queried_[0][i]);
|
||
|
|
if (ret == NULL && outjson != "") {
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
if(this->m_btime == 0)
|
||
|
|
{
|
||
|
|
this->SetHDTime(&query_time_region_.right, this->mstime());
|
||
|
|
}
|
||
|
|
this->free_ihd_mem();
|
||
|
|
}
|
||
|
|
|
||
|
|
} catch (const std::exception &e) {
|
||
|
|
d.Error() <<mix_cc::get_nested_exception(e) << std::endl;
|
||
|
|
ret = -1;
|
||
|
|
}
|
||
|
|
return ret;
|
||
|
|
}
|
||
|
|
|
||
|
|
int AlgExpTrendSampleMan::mon_proc(string &outjson, HD3Record *hdRec) {
|
||
|
|
LOG d("AlgExpTrendSampleMan::mon_proc|" + rule_name_, AUTO_CATCH_PID);
|
||
|
|
int ret = 0;
|
||
|
|
outjson = "";
|
||
|
|
bool act_triggered_ = false;
|
||
|
|
bool feedback_triggered_ = false;
|
||
|
|
double act_triggered_ = 0.0;
|
||
|
|
long long timediff = 0;
|
||
|
|
|
||
|
|
try {
|
||
|
|
act_triggered_ = (bool)exp_act_->evaluate();
|
||
|
|
feedback_triggered_ = (bool)exp_feedback_->evaluate();
|
||
|
|
// d.Debug()<<"act_triggered_:"<<setw(2)<<act_triggered_<<",feedback_triggered_:"<<setw(2)<<feedback_triggered_<<endl;
|
||
|
|
// this->print_exp_vars();
|
||
|
|
if (m_btime == 0 && act_triggered_) {
|
||
|
|
if (m_modest == DATA_STAT::ACTUAL &&
|
||
|
|
data_source_ == DataSource::MEMORY) {
|
||
|
|
m_btime = this->mstime();
|
||
|
|
this->SetHDTime(&query_time_region_.left, m_btime);
|
||
|
|
} else {
|
||
|
|
// set left and begin time
|
||
|
|
this->SetHDTime(&query_time_region_.left, hdRec);
|
||
|
|
// btime = left = hdRec.time
|
||
|
|
m_btime = this->ToMsTime(&query_time_region_.left);
|
||
|
|
}
|
||
|
|
|
||
|
|
d.Debug() << " action start " << m_btime << endl;
|
||
|
|
this->print_exp_vars();
|
||
|
|
|
||
|
|
for (unsigned int i = 0; i < m_tags.size(); i++) {
|
||
|
|
mm_vars["s" + std::to_string(i + 1)] =
|
||
|
|
mm_vars["tag" + std::to_string(i + 1)];
|
||
|
|
}
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
|
||
|
|
if (m_btime > 0 && keep_mode_ && !act_triggered_) {
|
||
|
|
// btime = 0, but should not be i n this one
|
||
|
|
m_btime = 0;
|
||
|
|
this->print_exp_vars();
|
||
|
|
d.Debug() << " action signal is not holding " << endl;
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
|
||
|
|
if (m_btime > 0 && feedback_triggered_) {
|
||
|
|
if (m_modest == DATA_STAT::ACTUAL &&
|
||
|
|
data_source_ == DataSource::MEMORY) {
|
||
|
|
this->SetHDTime(&query_time_region_.left, m_btime);
|
||
|
|
this->SetHDTime(&query_time_region_.right, this->mstime());
|
||
|
|
} else {
|
||
|
|
this->SetHDTime(&query_time_region_.left, m_btime);
|
||
|
|
this->SetHDTime(&query_time_region_.right, hdRec);
|
||
|
|
}
|
||
|
|
|
||
|
|
timediff = this->ToMsTime(&query_time_region_.right) - m_btime;
|
||
|
|
mm_vars["time"] = timediff;
|
||
|
|
this->print_exp_vars(m_expstr);
|
||
|
|
d.Debug() << " action time[" << m_btime << ","
|
||
|
|
<< this->ToMsTime(&query_time_region_.right)
|
||
|
|
<< "],timediff:" << timediff << endl;
|
||
|
|
if (query_time_region_.right.nSec <= query_time_region_.left.nSec) {
|
||
|
|
d.Error() << "Time Range is Error !" << std::endl;
|
||
|
|
m_btime = 0;
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
|
||
|
|
// 得到查询的结果
|
||
|
|
std::vector<double> sample_data;
|
||
|
|
|
||
|
|
sample_data = hd_com.QueryBatchFixedSize(
|
||
|
|
m_tags[atoi(m_sampletag.substr(3).c_str()) - 1],
|
||
|
|
mix_cc::ihd::ConvertHdTr2Tr(query_time_region_), SAMPLE_COUNT);
|
||
|
|
d.Debug() << "Query Data Success, Tag Name:"
|
||
|
|
<< m_tags[stoi(m_sampletag.substr(3)) - 1]
|
||
|
|
<< " value:" << sample_data[0] << std::endl;
|
||
|
|
// sample_analysis->Learning(sample_data);
|
||
|
|
|
||
|
|
// delete
|
||
|
|
// ret = this->GetHDTrend(m_expstr);
|
||
|
|
if (ret == NULL) {
|
||
|
|
d.Debug() << "HaveSample:" << this->sample_analysis->HaveSample() << endl;
|
||
|
|
if (this->sample_analysis->HaveSample()) {
|
||
|
|
// int total =
|
||
|
|
// this->sample_analysis->GetProperty()->data.vtrend.size() > SAMPLE_COUNT
|
||
|
|
// ? SAMPLE_COUNT
|
||
|
|
// : this->sample_analysis->GetProperty()->data.vtrend.size();
|
||
|
|
|
||
|
|
// Todo: Need Test
|
||
|
|
double dtw_val = sample_analysis->CalcDTWValue(sample_data);
|
||
|
|
double total = 0;
|
||
|
|
std::for_each(sample_data.begin(),sample_data.end(),[&total](double x)
|
||
|
|
{
|
||
|
|
total += abs(x);
|
||
|
|
});
|
||
|
|
d.Debug() << "RESULT = " << dtw_val << " Total = " <<total << std::endl;
|
||
|
|
|
||
|
|
if (dtw_val > total * judge_diff_) {
|
||
|
|
msg = rule_name_ + " " + m_json_param["alarm_option"]["error"][1].asString();
|
||
|
|
d.Debug() << msg << endl;
|
||
|
|
msg = this->build_alarm_info(MsgLevel::ERROR, rule_id_, rule_name_,
|
||
|
|
"TREND_SMP", msg, query_time_region_);
|
||
|
|
if (!msg.empty())
|
||
|
|
outjson = msg;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
this->sample_analysis->Learning(sample_data);
|
||
|
|
}
|
||
|
|
m_btime = 0;
|
||
|
|
|
||
|
|
}
|
||
|
|
|
||
|
|
} catch (const std::exception &e) {
|
||
|
|
d.Error() <<mix_cc::get_nested_exception(e) << std::endl;
|
||
|
|
ret = -1;
|
||
|
|
}
|
||
|
|
return ret;
|
||
|
|
}
|