Files
checker_host/prot/prot_slave.h
ranchuan 2451c5dfc5 自研批检仪检测命令测试成功
广播方式升级从机发现卡死现象
2023-12-04 18:15:37 +08:00

268 lines
6.2 KiB
C++

#ifndef PROT_SLAVE_H
#define PROT_SLAVE_H
#include "QObject"
#include "base/base.h"
#include "QList"
#include "interface/codec.h"
#include "interface/interface.h"
#include "base/mycfg.h"
#include "QThread"
#include "QTimer"
class HandleSlave : public QObject
{
Q_OBJECT
public:
HandleSlave() {
busy = 0;
addr = 0;
cmd=0;
timer_=nullptr;
timer_retry_=nullptr;
times_retry=0;
}
virtual ~HandleSlave() {
if(timer_!=nullptr){
delete timer_;
}
if(timer_retry_!=nullptr){
delete timer_retry_;
}
}
public:
virtual int start(myarray data) = 0;
virtual int dolater(int cmd, myarray data) = 0;
virtual void timeout(){timer_->stop();}
int busy;
int addr;
int cmd;
protected:
// 发送数据到从机
int send_data(int cmd,myarray data,int times){
this->cmd=cmd;
this->data_send=data;
this->times_retry=times;
if(timer_retry_==nullptr){
timer_retry_=new QTimer();
connect(timer_retry_,&QTimer::timeout,this,&HandleSlave::timeout_retry);
}
timeout_retry();
return 0;
}
// 发送操作结束信号
int end(int ack,myarray data){
emit end_signal(addr,ack,data);
return 0;
}
// 开始超时计时器,此计时器用于整个操作的超时
void timeout_start(int ms){
if(timer_==nullptr){
timer_=new QTimer();
connect(timer_,&QTimer::timeout,this,&HandleSlave::timeout);
}
timer_->start(ms);
}
// 停止超时计时器,此方法同时停止重发计时器
void timeout_stop(){
if(timer_!=nullptr){
timer_->stop();
}
timeout_stop_retry();
}
// 停止数据回复超时重试计时器
void timeout_stop_retry(){
if(timer_retry_!=nullptr){
timer_retry_->stop();
}
times_retry=0;
}
private:
// 重试回调
void timeout_retry(){
if(times_retry>0){
times_retry--;
qDebug("send to slave:%d",addr);
emit send_data_signal(addr,cmd,data_send);
timer_retry_->start(60);
}else{
timer_retry_->stop();
}
}
private:
QTimer *timer_;
QTimer *timer_retry_;
int times_retry;
myarray data_send;
signals:
void send_data_signal(int addr, int cmd, myarray data);
void end_signal(int addr,int ack,myarray data);
};
class HandleBoardCast : public QObject
{
Q_OBJECT
public:
HandleBoardCast() {
busy = 0;
addr = 0;
cmd=0;
timer_=nullptr;
timer_retry_=nullptr;
times_retry=0;
addr_response=0;
}
virtual ~HandleBoardCast() {
if(timer_!=nullptr){
delete timer_;
}
if(timer_retry_!=nullptr){
delete timer_retry_;
}
}
public:
virtual int start(myarray data) = 0;
virtual int dolater(int cmd, myarray data) = 0;
virtual void timeout(){timer_->stop();}
int busy;
int addr;
int addr_response;
int cmd;
public:
// 判断是否所有从机都返回
bool check_response(){
return (addr^addr_response)==0?true:false;
}
// 把地址列表转化为bit
void trun_list_to_bit(QList<int> addrs){
addr=0;
foreach(int adr,addrs){
addr|=1<<(adr-1);
}
}
signals:
void timeout_stop_retry_signal();
void timeout_stop_signal();
void timeout_start_signal(int ms);
void timeout_start_retry_signal(int ms);
protected:
// 发送数据到从机
int send_data(int cmd,myarray data,int times){
this->cmd=cmd;
this->data_send=data;
this->times_retry=times;
if(timer_retry_==nullptr){
timer_retry_=new QTimer();
connect(timer_,&QTimer::timeout,this,&HandleBoardCast::timeout_retry);
connect(this,&HandleBoardCast::timeout_stop_retry_signal,timer_retry_,&QTimer::stop);
connect(this,&HandleBoardCast::timeout_start_retry_signal,this,&HandleBoardCast::timeout_start_retry_cb);
}
qDebug("handle_board:start retry");
timeout_retry();
return 0;
}
// 发送操作结束信号
int end(int ack,myarray data){
emit end_signal(0x1f,ack,data);
return 0;
}
// 开始超时计时器,此计时器用于整个操作的超时
void timeout_start(int ms){
qDebug("handle_board:start timeout");
if(timer_==nullptr){
timer_=new QTimer();
connect(timer_,&QTimer::timeout,this,&HandleBoardCast::timeout);
connect(this,&HandleBoardCast::timeout_stop_signal,timer_,&QTimer::stop);
connect(this,&HandleBoardCast::timeout_start_signal,this,&HandleBoardCast::timeout_start_cb);
}else{
emit timeout_start_signal(ms);
// timer_->start(ms);
}
}
void timeout_start_cb(int ms){
timer_->start(ms);
}
void timeout_start_retry_cb(int ms){
timer_retry_->start(ms);
}
// 停止超时计时器,此方法同时停止重发计时器
void timeout_stop(){
qDebug("handle_board:stop timeout");
emit timeout_stop_signal();
timeout_stop_retry();
}
// 停止数据回复超时重试计时器
void timeout_stop_retry(){
qDebug("handle_board:stop retry");
emit timeout_stop_retry_signal();
times_retry=0;
}
private:
// 重试回调
void timeout_retry(){
qDebug("in retry.");
if(times_retry>0){
times_retry--;
myarray s;
int addr_retry=addr^addr_response;
// 这里重发只重发没有收到回应的从机
s.append(addr_retry&0xff);
s.append((addr_retry>>8)&0xff);
s.append((addr_retry>>16)&0xff);
s.append(data_send);
emit send_data_signal(0x1f,cmd,s);
// timer_retry_->start(300);
emit timeout_start_retry_signal(300);
}else{
// timer_retry_->stop();
emit timeout_stop_retry_signal();
}
}
private:
QTimer *timer_;
QTimer *timer_retry_;
int times_retry;
myarray data_send;
signals:
void send_data_signal(int addr, int cmd, myarray data);
void end_signal(int addr,int ack,myarray data);
};
class prot_slave : public QObject
{
Q_OBJECT
public:
prot_slave()
{
if_ = nullptr;
codec_ = nullptr;
broadcast_=nullptr;
}
~prot_slave() {}
void init();
bool set_slave_handle(int addr, HandleSlave *handle);
bool set_boardcast_handle(QList<int> addrs,HandleBoardCast *handle);
protected slots:
void send_data_slot(int addr, int cmd, myarray data);
protected:
InterFace *if_;
Codec *codec_;
QList<HandleSlave *> slaves;
HandleBoardCast *broadcast_;
};
prot_slave *protSlave();
#endif // PROT_SLAVE_H