重新构建的批检仪主板程序

This commit is contained in:
andy
2023-11-26 23:05:35 +08:00
parent b1b69d307f
commit 4a70f64693
29 changed files with 2565 additions and 64 deletions

651
base/check_cfg.h Normal file
View File

@@ -0,0 +1,651 @@
#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"<<endl;\
}
#define JVALUE_TO_INT(v,j) \
{\
if(j.type() == QJsonValue::Double)\
v=j.toInt();\
else\
{\
v=0;\
qWarning()<<#j<<"json not a int value"<<endl;\
}\
}
#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"<<endl;\
}\
}
#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"<<endl;\
}\
}
#define JVALUE_TO_STR(v,j) \
{\
if(j.type() == QJsonValue::String)\
v=j.toString();\
else\
qWarning()<<#j<<"json not a string value"<<endl;\
}
#define JVALUE_IS_ARRAY(j) \
if(j.type()!=QJsonValue::Array){\
qWarning()<<#j<<"json not a array"<<endl;\
}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."<<endl;
}
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;
}
QByteArray to_byte_array()
{
QByteArray 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()."<<endl;
}
if(return_num>returns_info.size())
{
qWarning()<<"name="<<brief<<" return_num>returns_info.size()."<<endl;
}
if(ch_errcode.size()!=ranges.size())
{
qWarning()<<"name="<<brief<<" ch_errcode.size()!=ranges.size()."<<endl;
}
return t;
}
QList<check_range> get_ranges()
{
return ranges;
}
QJsonObject returns_to_json(bool ack,QByteArray 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."<<endl;
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);
QByteArray tasks_to_byte_array();
QByteArray tasksid_to_byte_array();
QByteArray 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."<<endl;
}
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字节执行结果
QByteArray returns_to_paramerr(QByteArray data);
// 返回任务执行结果的json data为原始检测数据(包含16字节执行结果)
QJsonObject returns_to_json(QByteArray data);
// 返回执行结果的json字符串
QString returns_to_jstring(QByteArray 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(QByteArray 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;
QByteArray 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