#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 prots_end_cbfun; typedef std::function prots_rate_cbfun; typedef struct{ int addr; myarray data; }slave_ret; // 定义保存从机数据的类 class slave_data{ public: QList data; // 重载括号操作符,index为地址-1 myarray &operator [](int index){ for(int i=0;istop();} 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 addrs){ addr=0; foreach(int adr,addrs){ addr|=1<<(adr-1); } return addr; } // 把bit转化为地址列表 QList trun_bit_to_list(int addrs){ QList l; for(int i=0;i<32;i++){ if(addrs&(1<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 addrs,HandleBoardCast *handle); protected slots: void send_data_slot(int addr, int cmd, myarray data); protected: InterFace *if_; Codec *codec_; QList 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