Files
checker_host/base/check_cfg.h
2023-11-27 14:31:00 +08:00

651 lines
15 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#ifndef CHECK_CFG_H
#define CHECK_CFG_H
#include <QFile>
#include <QJsonObject>
#include <QJsonDocument>
#include <QJsonParseError>
#include "QJsonValue"
#include <QJsonArray>
#include "QByteArray"
#include "stdint-gcc.h"
#include "QList"
#include "QString"
#include <QDebug>
#include "base/mycfg.h"
#define JVALUE_TO_BOOL(v, j) \
{ \
if (j.type() == QJsonValue::Bool) \
v = j.toBool(); \
else \
qWarning() << #j << "json not a bool value"; \
}
#define JVALUE_TO_INT(v, j) \
{ \
if (j.type() == QJsonValue::Double) \
v = j.toInt(); \
else \
{ \
v = 0; \
qWarning() << #j << "json not a int value"; \
} \
}
#define JVALUE_TO_U8(v, j) \
{ \
if (j.type() == QJsonValue::Double) \
v = (uint8_t)j.toInt(); \
else \
{ \
v = 0; \
qWarning() << #j << "json not a int value"; \
} \
}
#define JVALUE_TO_U16(v, j) \
{ \
if (j.type() == QJsonValue::Double) \
v = (uint16_t)j.toInt(); \
else \
{ \
v = 0; \
qWarning() << #j << "json not a int value"; \
} \
}
#define JVALUE_TO_STR(v, j) \
{ \
if (j.type() == QJsonValue::String) \
v = j.toString(); \
else \
qWarning() << #j << "json not a string value"; \
}
#define JVALUE_IS_ARRAY(j) \
if (j.type() != QJsonValue::Array) \
{ \
qWarning() << #j << "json not a array"; \
} \
else
class check_range;
class check_task;
class check_err;
class check_suberr;
class my_json
{
public:
my_json() {}
~my_json() {}
template <typename T>
void json_to_list(QJsonObject j, QString key, QList<T> &list,
T (my_json::*json_to_value)(QJsonValue v))
{
QJsonValue value = j.value(key);
JVALUE_IS_ARRAY(value)
{
QJsonArray array = value.toArray();
for (int i = 0; i < array.size(); i++)
{
QJsonValue item = array.at(i);
list.append((this->*json_to_value)(item));
}
}
}
uint8_t json_to_u8(QJsonValue v)
{
uint8_t r;
JVALUE_TO_U8(r, v);
return r;
}
uint16_t json_to_u16(QJsonValue v)
{
uint16_t r;
JVALUE_TO_U16(r, v);
return r;
}
int json_to_int(QJsonValue v)
{
int r;
JVALUE_TO_INT(r, v);
return r;
}
QString json_to_str(QJsonValue v)
{
QString r;
JVALUE_TO_STR(r, v);
return r;
}
check_range json_to_range(QJsonValue v);
check_task json_to_task(QJsonValue v);
check_err json_to_err(QJsonValue v);
check_suberr json_to_suberr(QJsonValue v);
};
// 范围
class check_range
{
public:
check_range(uint16_t min, uint16_t max)
{
this->min = min;
this->max = max;
}
check_range(QJsonObject j)
{
JVALUE_TO_U16(min, j.value("Min"));
JVALUE_TO_U16(max, j.value("Max"));
if (min > max)
qWarning() << "the range min=" << min << "max=" << max << "is empty.";
}
check_range(const check_range &b)
{
min = b.min;
max = b.max;
}
~check_range()
{
}
check_range &operator=(const check_range &b)
{
min = b.min;
max = b.max;
return *this;
}
// 如果在范围内则范围true
bool in_range(uint16_t a)
{
if (a >= min && a <= max)
return true;
else
return false;
}
// private:
uint16_t min;
uint16_t max;
};
// 任务参数
class check_task
{
public:
check_task()
{
task_id = 0;
index = 0;
param_num = 0;
return_num = 0;
err_jump = 0;
retry = 0;
}
check_task(QJsonObject j)
{
my_json m;
JVALUE_TO_STR(brief, j.value("TaskBrief"));
JVALUE_TO_U8(task_id, j.value("TaskID"));
JVALUE_TO_U8(index, j.value("TaskIndex"));
JVALUE_TO_U8(err_jump, j.value("ErrJumpTo"));
JVALUE_TO_U8(retry, j.value("RetryCount"));
JVALUE_TO_U8(param_num, j.value("ParamCount"));
JVALUE_TO_U8(return_num, j.value("ReturnCount"));
m.json_to_list(j, "ParamInfo", params_info, &my_json::json_to_str);
m.json_to_list(j, "ReturnInfo", returns_info, &my_json::json_to_str);
m.json_to_list(j, "ParamVal", params, &my_json::json_to_u16);
m.json_to_list(j, "TestStandard", ranges, &my_json::json_to_range);
JVALUE_TO_U8(failed_code, j.value("ExecuteErrCode"));
m.json_to_list(j, "ResultErrCode", ret_failed_code, &my_json::json_to_u8);
}
check_task(const check_task &b)
{
brief = b.brief;
task_id = b.task_id;
index = b.index;
param_num = b.param_num;
params_info = b.params_info;
params = b.params;
ranges = b.ranges;
return_num = b.return_num;
returns_info = b.returns_info;
err_jump = b.err_jump;
retry = b.retry;
failed_code = b.failed_code;
ret_failed_code = b.ret_failed_code;
}
~check_task()
{
}
check_task &operator=(const check_task &b)
{
brief = b.brief;
task_id = b.task_id;
index = b.index;
param_num = b.param_num;
params_info = b.params_info;
params = b.params;
ranges = b.ranges;
return_num = b.return_num;
returns_info = b.returns_info;
err_jump = b.err_jump;
retry = b.retry;
failed_code = b.failed_code;
ret_failed_code = b.ret_failed_code;
return *this;
}
myarray to_byte_array()
{
myarray t;
t.append(task_id);
t.append(index);
t.append(retry);
t.append(err_jump);
t.append((param_num & 0x0f) | (return_num << 4));
for (int i = 0; i < params.size(); i++)
{
t.append(uint8_t(params[i] & 0xff));
t.append(uint8_t(params[i] >> 8));
}
if (param_num != params.size())
{
qWarning() << "name=" << brief << " param_num!=params.size().";
}
if (return_num > returns_info.size())
{
qWarning() << "name=" << brief << " return_num>returns_info.size().";
}
if (ch_errcode.size() != ranges.size())
{
qWarning() << "name=" << brief << " ch_errcode.size()!=ranges.size().";
}
return t;
}
QList<check_range> get_ranges()
{
return ranges;
}
QJsonObject returns_to_json(bool ack, myarray data)
{
QJsonObject j;
QJsonArray a;
QJsonArray ret_err;
ch_errcode.clear();
j.insert("TaskBrief", brief);
j.insert("TaskIndex", get_index());
j.insert("TaskID", get_task_id());
j.insert("Ack", ack);
if (ack != true)
{
// 添加流程错误
j.insert("ExecuteErrCode", failed_code);
ch_errcode.append(failed_code);
}
else
{
j.insert("ExecuteErrCode", 0);
}
{
if ((data.size() / 2) < return_num)
qWarning() << "data size too less.";
else
{
for (int i = 0; i < return_num; i++)
{
QJsonObject t;
int value = data[i * 2] | (data[i * 2 + 1] << 8);
if (returns_info.size() > i)
t.insert("ReturnInfo", returns_info[i]);
else
t.insert("ReturnInfo", "unknown");
t.insert("Return", value);
// 判断值域
if (ranges.size() > i)
{
// qDebug()<<"rang:"<<ranges[i].min<<ranges[i].max<<value<<endl;
bool b = ranges[i].in_range(value);
t.insert("InRange", b);
if (b == true)
ret_err.append(0);
else
{
if (ret_failed_code.size() > i)
{
ret_err.append(ret_failed_code[i]);
ch_errcode.append(ret_failed_code[i]);
}
else
ret_err.append(0);
}
}
else
{
t.insert("InRange", true);
ret_err.append(0);
}
a.append(t);
}
}
}
// qDebug()<<"task="<<get_brief()<<"ch_errcode="<<ch_errcode<<endl;
j.insert("Returns", a);
j.insert("ResultErrCode", ret_err);
return j;
}
QList<uint8_t> get_ch_errcode()
{
// qDebug()<<"task="<<get_brief()<<"ch_errcode="<<ch_errcode<<endl;
return ch_errcode;
}
QString get_brief() { return brief; }
uint8_t get_task_id() { return task_id; }
uint8_t get_index() { return index; }
int get_return_num() { return return_num; }
QList<QString> get_return_info() { return returns_info; }
int get_err_jump() { return err_jump; }
uint8_t get_failed_code() { return failed_code; }
QList<uint8_t> get_ret_failed_code() { return ret_failed_code; }
private:
// 任务简要描述
QString brief;
// 对应从机的检测项目
uint8_t task_id;
// 此任务执行的次序
uint8_t index;
// 此任务参数个数
uint8_t param_num;
// 参数介绍
QList<QString> params_info;
// 参数指
QList<uint16_t> params;
// 参数范围
QList<check_range> ranges;
// 返回值个数
uint8_t return_num;
// 返回值说明
QList<QString> returns_info;
// 失败时跳转到任务
uint8_t err_jump;
// 失败后重试次数
uint8_t retry;
// 此任务失败时的错误代码
uint8_t failed_code;
// 此任务返回值错误时的错误代码
QList<uint8_t> ret_failed_code;
// 解析时此任务产生的错误代码
QList<uint8_t> ch_errcode;
};
class check_err
{
public:
check_err() {}
check_err(QJsonObject j)
{
my_json m;
JVALUE_TO_STR(info, j.value("Info"));
JVALUE_TO_U8(code, j.value("MajorErrCode"));
m.json_to_list(j, "SubErrCode", sub_errs, &my_json::json_to_u8);
}
check_err(const check_err &b)
{
info = b.info;
code = b.code;
sub_errs = b.sub_errs;
}
~check_err() {}
check_err &operator=(const check_err &b)
{
info = b.info;
code = b.code;
sub_errs = b.sub_errs;
return *this;
}
void append(uint8_t suberr)
{
sub_errs.append(suberr);
}
void append(QList<uint8_t> suberrs)
{
this->sub_errs.append(suberrs);
}
bool operator==(const uint8_t code)
{
return this->code == code;
}
QString get_err_string()
{
return info;
}
QString operator()()
{
return info;
}
bool in_range(uint8_t err)
{
foreach (uint8_t i, sub_errs)
{
if (i == err)
return true;
}
return false;
}
uint8_t get_code() { return code; }
QList<uint8_t> get_subcodes() { return sub_errs; }
private:
QString info;
uint8_t code;
QList<uint8_t> sub_errs;
};
class check_suberr
{
public:
check_suberr() {}
check_suberr(QJsonObject j)
{
JVALUE_TO_STR(info, j.value("Info"));
JVALUE_TO_U8(code, j.value("ErrCode"));
}
check_suberr(const check_suberr &b)
{
info = b.info;
code = b.code;
}
~check_suberr() {}
check_suberr &operator=(const check_suberr &b)
{
info = b.info;
code = b.code;
return *this;
}
bool operator==(const uint8_t code)
{
return this->code == code;
}
QString get_err_string()
{
return info;
}
QString operator()()
{
return info;
}
private:
QString info;
uint8_t code;
};
class check_value
{
public:
check_value()
{
}
~check_value()
{
}
private:
QString info;
uint16_t value;
};
#pragma pack(1)
typedef struct
{
uint16_t max;
uint16_t min;
uint8_t err;
} scheme_range_def;
typedef struct
{
uint8_t taskid;
uint8_t taskindex;
uint8_t item_num;
uint8_t err;
scheme_range_def range[16];
} scheme_task_def;
typedef struct
{
uint8_t err;
uint8_t suberr_num;
uint8_t suberr[30];
} marerr_def;
typedef struct
{
uint8_t slave_data[2048];
uint32_t plan_id;
uint32_t timeout_m;
uint32_t task_num;
uint32_t marerr_num;
marerr_def marerr[21];
scheme_task_def task[0];
} scheme_def;
#pragma pack()
// 检测序列
class check_cfg
{
public:
check_cfg();
~check_cfg();
void reload();
bool updata(QString jstring);
myarray tasks_to_byte_array();
myarray tasksid_to_byte_array();
myarray scheme_to_byte_array();
void scheme_json_to_struct();
const scheme_def *check_scheme(void)
{
if (scheme_ == nullptr)
{
qWarning() << "scheme_ ptr is null,application will failed.";
}
return scheme_;
}
int check_scheme_size()
{
return scheme_struct_size;
}
// 获取检测方案id
int get_plan_id();
// 把方案id转化为具体信息
QString planid_to_String(int id);
QString get_brief() { return brief; }
// 获取适配的从机软件版本号
QList<uint16_t> &get_slave_soft_versions();
// 获取适配的从机硬件版本号
QList<uint16_t> &get_slave_hard_versions();
// 获取方案执行最长时间
int get_check_time_out();
// 获取任务id最大值
uint8_t get_task_id_max();
// 根据错误号返回错误字符串
QString get_err_string(int err);
// 获取检测任务个数
int get_check_task_num();
// 根据序列指获取对应的任务参数
check_task get_task(int index);
// 返回返回值个数
int get_return_num()
{
int ret = 0;
for (int i = 0; i < tasks.size(); i++)
{
ret += tasks[i].get_return_num();
}
return ret;
}
// 返回返回值参数
QStringList get_return_info()
{
return check_ret_items;
}
// 返回参数错误位 data为原始检测数据去除16字节执行结果
myarray returns_to_paramerr(myarray data);
// 返回任务执行结果的json data为原始检测数据(包含16字节执行结果)
QJsonObject returns_to_json(myarray data);
// 返回执行结果的json字符串
QString returns_to_jstring(myarray data)
{
QJsonDocument doc;
doc.setObject(returns_to_json(data));
return doc.toJson();
}
QString scheme_to_jstring()
{
return json_doc.toJson();
}
// 返回主错误列表
QList<check_err> get_ch_merrcode();
// 错误代码在范围内时返回true并把对应主错误代码添加进l
bool in_err_range(QList<check_err> &l, uint8_t code);
private:
// 提取指定任务的执行结果
bool get_return_ack_by_index(myarray data, int index);
void clear()
{
slave_soft_versions.clear();
slave_hard_versions.clear();
errs.clear();
suberrs.clear();
tasks.clear();
check_ret_items.clear();
}
private:
mycfg *cfg_;
QJsonDocument json_doc;
myarray check_cfg_data;
int plan_id;
QString brief;
QList<uint16_t> slave_soft_versions;
QList<uint16_t> slave_hard_versions;
int time_out_s; // 小板超时时间
int time_out_m; // 主板超时时间
uint8_t task_id_max;
QList<check_err> errs;
QList<check_suberr> suberrs;
QList<check_task> tasks;
// 检测时产生的错误代码
QList<uint8_t> ch_errcode;
// 返回值项目
QStringList check_ret_items;
// 把方案解析为结构体的形式
scheme_def *scheme_;
int scheme_struct_size;
};
check_cfg *check_plan();
#endif // CHECK_CFG_H