Files
checker_host/prot/prot_slave.h
2024-01-06 09:59:58 +08:00

349 lines
8.0 KiB
C++
Raw Permalink 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 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;
}
// 发送操作结束信号,ack=0成功,1失败
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);
};
using namespace std;
// using namespace std::placeholders;
class slave_data;
typedef std::function<void(int addr,int ack,slave_data data)> prots_end_cbfun;
typedef std::function<void(int rate,mystring data)> prots_rate_cbfun;
typedef struct{
int addr;
myarray data;
}slave_ret;
// 定义保存从机数据的类
class slave_data{
public:
QList<slave_ret> data;
// 重载括号操作符index为地址-1
myarray &operator [](int index){
for(int i=0;i<data.size();i++){
if(data[i].addr==(index+1)){
return data[i].data;
}
}
slave_ret r;
r.addr=index+1;
data.append(r);
return data.last().data;
}
// 清除
void clear(){
data.clear();
}
int size(){
return data.size();
}
slave_ret &at(int index){
return data[index];
}
};
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;
end_cb=nullptr;
rate_cb=nullptr;
}
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;
slave_data ret_data;
public:
// 判断是否所有从机都返回
bool check_response(){
return (addr^addr_response)==0?true:false;
}
// 把地址列表转化为bit
int trun_list_to_bit(QList<int> addrs){
addr=0;
foreach(int adr,addrs){
addr|=1<<(adr-1);
}
return addr;
}
// 把bit转化为地址列表
QList<int> trun_bit_to_list(int addrs){
QList<int> l;
for(int i=0;i<32;i++){
if(addrs&(1<<i)){
l.append(i+1);
}
}
return l;
}
void set_cbfun(prots_end_cbfun end_fun,prots_rate_cbfun rate_fun){
this->end_cb=end_fun;
this->rate_cb=rate_fun;
}
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;
this->addr_response=0;
this->ret_data.clear();
if(timer_retry_==nullptr){
timer_retry_=new QTimer();
connect(timer_retry_,&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);
}
// timeout_retry();
// emit timeout_start_retry_signal(5);
timeout_start_retry_cb(5);
return 0;
}
// 发送操作结束信号,ack=0成功,1失败
int end(int ack,slave_data data){
emit end_signal(0x1f,ack,data);
if(end_cb!=nullptr){
end_cb(0x1f,ack,data);
}
return 0;
}
void rate(int rate,mystring str){
emit rate_signal(rate,str);
if(rate_cb!=nullptr){
rate_cb(rate,str);
}
}
// 开始超时计时器,此计时器用于整个操作的超时
void timeout_start(int ms){
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);
}
// emit timeout_start_signal(ms);
timeout_start_cb(ms);
}
void timeout_start_cb(int ms){
// qDebug("handle_board:start timeout");
timer_->setInterval(ms);
timer_->start();
}
void timeout_start_retry_cb(int ms){
// qDebug("handle_board:start retry");
timer_retry_->setInterval(ms);
timer_retry_->start();
}
// 停止超时计时器,此方法同时停止重发计时器
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);
timeout_start_retry_cb(2000);
}else{
// timer_retry_->stop();
timeout_stop_retry();
}
}
private:
QTimer *timer_;
QTimer *timer_retry_;
int times_retry;
myarray data_send;// 发送的数据
prots_end_cbfun end_cb;
prots_rate_cbfun rate_cb;
signals:
void send_data_signal(int addr, int cmd, myarray data);
void end_signal(int addr,int ack,slave_data data);
void rate_signal(int rate,mystring str);
};
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_;
signals:
void boardcast_dolater_signal(int cmd,myarray data);
void slave_dolater_signal(int cmd,myarray data);
};
prot_slave *protSlave();
#endif // PROT_SLAVE_H