168 lines
6.0 KiB
C++
168 lines
6.0 KiB
C++
|
||
#include <base/BitTool.h>
|
||
#include <eqpalg/algs/trend_slope.h>
|
||
#include <eqpalg/utility/build_alarm_info.h>
|
||
#include <utility/StringHelper.h>
|
||
#include <limits>
|
||
#include <string>
|
||
#include <vector>
|
||
#include "mix_cc/ihyper_db/read_data_stats.h"
|
||
/*计算次数,采用6次出现连续3次*/
|
||
#define CS_AVG_SIZE 6
|
||
const double MAX_SLOPE = 100000000; ///<用于设置单边区间的无用侧
|
||
|
||
TrendSlope::TrendSlope(const string name, const mix_cc::json& rule_json,
|
||
const string ruleId)
|
||
: AlgBase(name, rule_json, ruleId) {
|
||
logger_.reset(new LOG("TrendSlope:" + rule_name_, AUTO_CATCH_PID));
|
||
}
|
||
|
||
TrendSlope::~TrendSlope() {
|
||
// AlgBase::~AlgBase();
|
||
}
|
||
|
||
int TrendSlope::init() {
|
||
int res = 0;
|
||
try {
|
||
res += AlgBase::init();
|
||
double interval_time = std::stod(rule_json_.at("function")
|
||
.at("limit_error")
|
||
.at("param")
|
||
.at("interval_time")
|
||
.at("value")
|
||
.get<std::string>());
|
||
limit_time_interval_ = seconds(int(interval_time * 60));
|
||
|
||
limit_slope_ = std::stod(rule_json_.at("function")
|
||
.at("limit_error")
|
||
.at("param")
|
||
.at("diff")
|
||
.at("value")
|
||
.get<std::string>());
|
||
if (limit_slope_ > 0) {
|
||
// this->rule_stat_.limit_down = -MAX_SLOPE;
|
||
this->rule_stat_.limit_down = -32768;
|
||
this->rule_stat_.limit_up = limit_slope_;
|
||
} else {
|
||
this->rule_stat_.limit_down = limit_slope_;
|
||
// this->rule_stat_.limit_up = MAX_SLOPE;
|
||
this->rule_stat_.limit_up = -32768;
|
||
}
|
||
this->rule_stat_.current_value = 0;
|
||
logger_->Debug() << "区间:[" << this->rule_stat_.limit_down << ","
|
||
<< this->rule_stat_.limit_up << "]"
|
||
<< ",当期值:" << this->rule_stat_.current_value << endl;
|
||
error_content_ =
|
||
rule_json_.at("output").at("error").at("value").get<std::string>();
|
||
logger_->Debug() << "Time interval between:" << limit_time_interval_.count()
|
||
<< "ms,slope:" << limit_slope_ << ",报警内容:"
|
||
<< error_content_ << endl;
|
||
this->data_source_ = DataSource::IHDB;
|
||
|
||
} catch (const std::exception& e) {
|
||
std::throw_with_nested(
|
||
mix_cc::Exception(-1, "load error", BOOST_CURRENT_LOCATION));
|
||
}
|
||
return res;
|
||
}
|
||
|
||
AlarmInfo TrendSlope::exec_mon() {
|
||
AlarmInfo out_alarm{};
|
||
int count_error = 0;
|
||
this->refresh_now_time();
|
||
this->refresh_ihd_cache();
|
||
double avg[CS_AVG_SIZE] = {0.0};
|
||
double f_slope = 0.0;
|
||
double f_slope_max = 0; ///<斜率最大值
|
||
try {
|
||
/* before --> now*/
|
||
// 检查6个周期的时间内数据的斜率是否小于目标斜率
|
||
for (int i = 0; i < CS_AVG_SIZE; i++) {
|
||
query_time_range_.set_left(now_time_ -
|
||
(limit_time_interval_ * (CS_AVG_SIZE - i)));
|
||
query_time_range_.set_right(
|
||
now_time_ - (limit_time_interval_ * (CS_AVG_SIZE - i - 1)));
|
||
if (!query_time_range_.valid()) {
|
||
logger_->Error() << "时间数据 不合法" << std::endl;
|
||
}
|
||
logger_->Debug() << "时间范围"
|
||
<< mix_cc::mix_time_t(query_time_range_.get_left())
|
||
.to_formatted_time()
|
||
<< " "
|
||
<< mix_cc::mix_time_t(query_time_range_.get_right())
|
||
.to_formatted_time()
|
||
<< std::endl;
|
||
auto data_maybe = mix_cc::ihd::read_data_stats_maybe(
|
||
m_tags[0], query_time_range_, HD3_STATS_TYPE_ARITH_MEAN);
|
||
if (data_maybe.is_nothing()) {
|
||
logger_->Error() << rule_name_ << ":ihd查询异常!" << std::endl;
|
||
return {};
|
||
}
|
||
avg[i] = data_maybe.unsafe_get_just();
|
||
logger_->Debug() << "avg[" << i << "]:" << avg[i] << endl;
|
||
}
|
||
|
||
string msgslope;
|
||
for (int i = 0; i < CS_AVG_SIZE; i++) {
|
||
if (i > 0) {
|
||
f_slope = static_cast<int>(1000.0 * (avg[i] - avg[i - 1]) + 0.5);
|
||
f_slope = f_slope / 1000;
|
||
f_slope_max = (abs(f_slope_max) > abs(f_slope)) ? f_slope_max : f_slope;
|
||
if ((limit_slope_ > 0 && f_slope > limit_slope_) ||
|
||
(limit_slope_ < 0 && f_slope < limit_slope_)) {
|
||
msgslope += " " + std::to_string(f_slope);
|
||
count_error++;
|
||
logger_->Debug() << msgslope << endl;
|
||
} else {
|
||
if (count_error < 3) {
|
||
msgslope = "";
|
||
count_error = 0;
|
||
} else {
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
rule_stat_.current_value = f_slope_max; ///<共享内存
|
||
// if (limit_slope_ > 0) {
|
||
// rule_stat_.limit_down = 0;
|
||
// rule_stat_.limit_up = limit_slope_;
|
||
// } else {
|
||
// rule_stat_.limit_down = limit_slope_;
|
||
// rule_stat_.limit_up = 0;
|
||
// }
|
||
|
||
if (count_error >= 3) {
|
||
rule_stat_.alarm_value = rule_stat_.current_value;
|
||
string msg = error_content_ + " 斜率变化量:" + msgslope;
|
||
logger_->Debug() << msg << endl;
|
||
|
||
query_time_range_.set_right(now_time_);
|
||
query_time_range_.set_left(now_time_ -
|
||
(limit_time_interval_ * (CS_AVG_SIZE)));
|
||
return utility::build_alarm_info(MsgLevel::ERROR, rule_id_, rule_name_,
|
||
"SLOPE", msg, query_time_range_);
|
||
}
|
||
} catch (const std::exception& e) {
|
||
std::throw_with_nested(
|
||
mix_cc::Exception(-1, "calc error", BOOST_CURRENT_LOCATION));
|
||
}
|
||
|
||
// return AlarmInfo{};
|
||
return out_alarm;
|
||
}
|
||
|
||
std::vector<AlarmInfo> TrendSlope::exec_task(mix_cc::time_range_t time_range) {
|
||
std::vector<AlarmInfo> result;
|
||
for (auto now_time = time_range.get_left();
|
||
now_time <= time_range.get_right(); now_time += delay_time_) {
|
||
this->now_time_ = now_time;
|
||
auto rr1 = this->exec_mon();
|
||
if (rr1.alarmed) {
|
||
result.push_back(rr1);
|
||
}
|
||
}
|
||
return result;
|
||
}
|