#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 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 addrs,HandleBoardCast *handle); protected slots: void send_data_slot(int addr, int cmd, myarray data); protected: InterFace *if_; Codec *codec_; QList slaves; HandleBoardCast *broadcast_; }; prot_slave *protSlave(); #endif // PROT_SLAVE_H