2023-11-26 23:05:35 +08:00
|
|
|
|
#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"
|
2023-11-27 14:31:00 +08:00
|
|
|
|
#include "QTimer"
|
2023-11-26 23:05:35 +08:00
|
|
|
|
|
2023-11-27 14:31:00 +08:00
|
|
|
|
class HandleSlave : public QObject
|
|
|
|
|
{
|
|
|
|
|
Q_OBJECT
|
|
|
|
|
public:
|
|
|
|
|
HandleSlave() {
|
|
|
|
|
busy = 0;
|
|
|
|
|
addr = 0;
|
|
|
|
|
cmd=0;
|
|
|
|
|
timer_=nullptr;
|
2023-11-29 15:36:45 +08:00
|
|
|
|
timer_retry_=nullptr;
|
|
|
|
|
times_retry=0;
|
2023-11-27 14:31:00 +08:00
|
|
|
|
}
|
|
|
|
|
virtual ~HandleSlave() {
|
|
|
|
|
if(timer_!=nullptr){
|
|
|
|
|
delete timer_;
|
|
|
|
|
}
|
2023-11-29 15:36:45 +08:00
|
|
|
|
if(timer_retry_!=nullptr){
|
|
|
|
|
delete timer_retry_;
|
|
|
|
|
}
|
2023-11-27 14:31:00 +08:00
|
|
|
|
}
|
|
|
|
|
public:
|
|
|
|
|
virtual int start(myarray data) = 0;
|
|
|
|
|
virtual int dolater(int cmd, myarray data) = 0;
|
2023-12-04 18:15:37 +08:00
|
|
|
|
virtual void timeout(){timer_->stop();}
|
2023-11-27 14:31:00 +08:00
|
|
|
|
int busy;
|
|
|
|
|
int addr;
|
|
|
|
|
int cmd;
|
2023-11-29 15:36:45 +08:00
|
|
|
|
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();
|
2023-12-04 18:15:37 +08:00
|
|
|
|
connect(timer_retry_,&QTimer::timeout,this,&HandleSlave::timeout_retry);
|
2023-11-29 15:36:45 +08:00
|
|
|
|
}
|
2023-12-04 18:15:37 +08:00
|
|
|
|
timeout_retry();
|
2023-11-27 14:31:00 +08:00
|
|
|
|
return 0;
|
|
|
|
|
}
|
2023-11-29 15:36:45 +08:00
|
|
|
|
// 发送操作结束信号
|
2023-11-27 14:31:00 +08:00
|
|
|
|
int end(int ack,myarray data){
|
|
|
|
|
emit end_signal(addr,ack,data);
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
2023-11-29 15:36:45 +08:00
|
|
|
|
// 开始超时计时器,此计时器用于整个操作的超时
|
2023-11-27 14:31:00 +08:00
|
|
|
|
void timeout_start(int ms){
|
|
|
|
|
if(timer_==nullptr){
|
|
|
|
|
timer_=new QTimer();
|
|
|
|
|
connect(timer_,&QTimer::timeout,this,&HandleSlave::timeout);
|
|
|
|
|
}
|
|
|
|
|
timer_->start(ms);
|
|
|
|
|
}
|
2023-11-29 15:36:45 +08:00
|
|
|
|
// 停止超时计时器,此方法同时停止重发计时器
|
2023-11-27 14:31:00 +08:00
|
|
|
|
void timeout_stop(){
|
|
|
|
|
if(timer_!=nullptr){
|
|
|
|
|
timer_->stop();
|
|
|
|
|
}
|
2023-11-29 15:36:45 +08:00
|
|
|
|
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--;
|
2023-12-04 18:15:37 +08:00
|
|
|
|
qDebug("send to slave:%d",addr);
|
2023-11-29 15:36:45 +08:00
|
|
|
|
emit send_data_signal(addr,cmd,data_send);
|
2023-12-04 18:15:37 +08:00
|
|
|
|
timer_retry_->start(60);
|
2023-11-29 15:36:45 +08:00
|
|
|
|
}else{
|
|
|
|
|
timer_retry_->stop();
|
|
|
|
|
}
|
2023-11-27 14:31:00 +08:00
|
|
|
|
}
|
|
|
|
|
private:
|
|
|
|
|
QTimer *timer_;
|
2023-11-29 15:36:45 +08:00
|
|
|
|
QTimer *timer_retry_;
|
|
|
|
|
int times_retry;
|
|
|
|
|
myarray data_send;
|
2023-11-27 14:31:00 +08:00
|
|
|
|
signals:
|
|
|
|
|
void send_data_signal(int addr, int cmd, myarray data);
|
|
|
|
|
void end_signal(int addr,int ack,myarray data);
|
2023-11-26 23:05:35 +08:00
|
|
|
|
};
|
|
|
|
|
|
2023-11-29 15:36:45 +08:00
|
|
|
|
|
2023-12-05 18:37:40 +08:00
|
|
|
|
using namespace std;
|
|
|
|
|
// using namespace std::placeholders;
|
2023-12-09 10:37:48 +08:00
|
|
|
|
class slave_data;
|
|
|
|
|
typedef std::function<void(int addr,int ack,slave_data data)> prots_end_cbfun;
|
2023-12-05 18:37:40 +08:00
|
|
|
|
typedef std::function<void(int rate,mystring data)> prots_rate_cbfun;
|
2023-11-29 15:36:45 +08:00
|
|
|
|
|
|
|
|
|
|
2023-12-09 10:37:48 +08:00
|
|
|
|
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];
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2023-11-29 15:36:45 +08:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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;
|
2023-12-05 18:37:40 +08:00
|
|
|
|
end_cb=nullptr;
|
|
|
|
|
rate_cb=nullptr;
|
2023-11-29 15:36:45 +08:00
|
|
|
|
}
|
|
|
|
|
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;
|
2023-12-04 18:15:37 +08:00
|
|
|
|
virtual void timeout(){timer_->stop();}
|
2023-11-29 15:36:45 +08:00
|
|
|
|
int busy;
|
|
|
|
|
int addr;
|
|
|
|
|
int addr_response;
|
|
|
|
|
int cmd;
|
2023-12-09 10:37:48 +08:00
|
|
|
|
slave_data ret_data;
|
2023-11-29 15:36:45 +08:00
|
|
|
|
public:
|
|
|
|
|
// 判断是否所有从机都返回
|
|
|
|
|
bool check_response(){
|
|
|
|
|
return (addr^addr_response)==0?true:false;
|
|
|
|
|
}
|
|
|
|
|
// 把地址列表转化为bit
|
2023-12-09 10:37:48 +08:00
|
|
|
|
int trun_list_to_bit(QList<int> addrs){
|
2023-11-29 15:36:45 +08:00
|
|
|
|
addr=0;
|
|
|
|
|
foreach(int adr,addrs){
|
|
|
|
|
addr|=1<<(adr-1);
|
|
|
|
|
}
|
2023-12-09 10:37:48 +08:00
|
|
|
|
return addr;
|
2023-11-29 15:36:45 +08:00
|
|
|
|
}
|
2023-12-09 10:37:48 +08:00
|
|
|
|
// 把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;
|
|
|
|
|
}
|
|
|
|
|
|
2023-12-05 18:37:40 +08:00
|
|
|
|
void set_cbfun(prots_end_cbfun end_fun,prots_rate_cbfun rate_fun){
|
|
|
|
|
this->end_cb=end_fun;
|
|
|
|
|
this->rate_cb=rate_fun;
|
|
|
|
|
}
|
2023-12-04 18:15:37 +08:00
|
|
|
|
signals:
|
|
|
|
|
void timeout_stop_retry_signal();
|
|
|
|
|
void timeout_stop_signal();
|
|
|
|
|
void timeout_start_signal(int ms);
|
|
|
|
|
void timeout_start_retry_signal(int ms);
|
2023-11-29 15:36:45 +08:00
|
|
|
|
protected:
|
|
|
|
|
// 发送数据到从机
|
|
|
|
|
int send_data(int cmd,myarray data,int times){
|
|
|
|
|
this->cmd=cmd;
|
|
|
|
|
this->data_send=data;
|
|
|
|
|
this->times_retry=times;
|
2023-12-05 18:37:40 +08:00
|
|
|
|
this->addr_response=0;
|
2023-12-09 10:37:48 +08:00
|
|
|
|
this->ret_data.clear();
|
2023-11-29 15:36:45 +08:00
|
|
|
|
if(timer_retry_==nullptr){
|
|
|
|
|
timer_retry_=new QTimer();
|
2023-12-05 18:37:40 +08:00
|
|
|
|
connect(timer_retry_,&QTimer::timeout,this,&HandleBoardCast::timeout_retry);
|
2023-12-04 18:15:37 +08:00
|
|
|
|
connect(this,&HandleBoardCast::timeout_stop_retry_signal,timer_retry_,&QTimer::stop);
|
|
|
|
|
connect(this,&HandleBoardCast::timeout_start_retry_signal,this,&HandleBoardCast::timeout_start_retry_cb);
|
2023-11-29 15:36:45 +08:00
|
|
|
|
}
|
2023-12-05 18:37:40 +08:00
|
|
|
|
// timeout_retry();
|
|
|
|
|
// emit timeout_start_retry_signal(5);
|
|
|
|
|
timeout_start_retry_cb(5);
|
2023-11-29 15:36:45 +08:00
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
// 发送操作结束信号
|
2023-12-09 10:37:48 +08:00
|
|
|
|
int end(int ack,slave_data data){
|
2023-11-29 15:36:45 +08:00
|
|
|
|
emit end_signal(0x1f,ack,data);
|
2023-12-05 18:37:40 +08:00
|
|
|
|
if(end_cb!=nullptr){
|
|
|
|
|
end_cb(0x1f,ack,data);
|
|
|
|
|
}
|
2023-11-29 15:36:45 +08:00
|
|
|
|
return 0;
|
|
|
|
|
}
|
2023-12-05 18:37:40 +08:00
|
|
|
|
void rate(int rate,mystring str){
|
|
|
|
|
emit rate_signal(rate,str);
|
|
|
|
|
if(rate_cb!=nullptr){
|
|
|
|
|
rate_cb(rate,str);
|
|
|
|
|
}
|
|
|
|
|
}
|
2023-11-29 15:36:45 +08:00
|
|
|
|
// 开始超时计时器,此计时器用于整个操作的超时
|
|
|
|
|
void timeout_start(int ms){
|
|
|
|
|
if(timer_==nullptr){
|
|
|
|
|
timer_=new QTimer();
|
|
|
|
|
connect(timer_,&QTimer::timeout,this,&HandleBoardCast::timeout);
|
2023-12-04 18:15:37 +08:00
|
|
|
|
connect(this,&HandleBoardCast::timeout_stop_signal,timer_,&QTimer::stop);
|
|
|
|
|
connect(this,&HandleBoardCast::timeout_start_signal,this,&HandleBoardCast::timeout_start_cb);
|
2023-11-29 15:36:45 +08:00
|
|
|
|
}
|
2023-12-05 18:37:40 +08:00
|
|
|
|
// emit timeout_start_signal(ms);
|
|
|
|
|
timeout_start_cb(ms);
|
2023-12-04 18:15:37 +08:00
|
|
|
|
}
|
|
|
|
|
void timeout_start_cb(int ms){
|
2023-12-05 18:37:40 +08:00
|
|
|
|
qDebug("handle_board:start timeout");
|
|
|
|
|
timer_->setInterval(ms);
|
|
|
|
|
timer_->start();
|
2023-11-29 15:36:45 +08:00
|
|
|
|
}
|
2023-12-04 18:15:37 +08:00
|
|
|
|
void timeout_start_retry_cb(int ms){
|
2023-12-05 18:37:40 +08:00
|
|
|
|
qDebug("handle_board:start retry");
|
|
|
|
|
timer_retry_->setInterval(ms);
|
|
|
|
|
timer_retry_->start();
|
2023-12-04 18:15:37 +08:00
|
|
|
|
}
|
2023-11-29 15:36:45 +08:00
|
|
|
|
// 停止超时计时器,此方法同时停止重发计时器
|
|
|
|
|
void timeout_stop(){
|
2023-12-04 18:15:37 +08:00
|
|
|
|
qDebug("handle_board:stop timeout");
|
|
|
|
|
emit timeout_stop_signal();
|
2023-11-29 15:36:45 +08:00
|
|
|
|
timeout_stop_retry();
|
|
|
|
|
}
|
|
|
|
|
// 停止数据回复超时重试计时器
|
|
|
|
|
void timeout_stop_retry(){
|
2023-12-04 18:15:37 +08:00
|
|
|
|
qDebug("handle_board:stop retry");
|
|
|
|
|
emit timeout_stop_retry_signal();
|
2023-11-29 15:36:45 +08:00
|
|
|
|
times_retry=0;
|
|
|
|
|
}
|
|
|
|
|
private:
|
|
|
|
|
// 重试回调
|
|
|
|
|
void timeout_retry(){
|
2023-12-04 18:15:37 +08:00
|
|
|
|
qDebug("in retry.");
|
2023-11-29 15:36:45 +08:00
|
|
|
|
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);
|
2023-12-04 18:15:37 +08:00
|
|
|
|
// timer_retry_->start(300);
|
2023-12-05 18:37:40 +08:00
|
|
|
|
//emit timeout_start_retry_signal(300);
|
|
|
|
|
timeout_start_retry_cb(1000);
|
2023-11-29 15:36:45 +08:00
|
|
|
|
}else{
|
2023-12-04 18:15:37 +08:00
|
|
|
|
// timer_retry_->stop();
|
2023-12-05 18:37:40 +08:00
|
|
|
|
timeout_stop_retry();
|
2023-11-29 15:36:45 +08:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
private:
|
|
|
|
|
QTimer *timer_;
|
|
|
|
|
QTimer *timer_retry_;
|
|
|
|
|
int times_retry;
|
2023-12-09 10:37:48 +08:00
|
|
|
|
myarray data_send;// 发送的数据
|
2023-12-05 18:37:40 +08:00
|
|
|
|
prots_end_cbfun end_cb;
|
|
|
|
|
prots_rate_cbfun rate_cb;
|
2023-11-29 15:36:45 +08:00
|
|
|
|
signals:
|
|
|
|
|
void send_data_signal(int addr, int cmd, myarray data);
|
2023-12-09 10:37:48 +08:00
|
|
|
|
void end_signal(int addr,int ack,slave_data data);
|
2023-12-05 18:37:40 +08:00
|
|
|
|
void rate_signal(int rate,mystring str);
|
2023-11-29 15:36:45 +08:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2023-11-27 14:31:00 +08:00
|
|
|
|
class prot_slave : public QObject
|
2023-11-26 23:05:35 +08:00
|
|
|
|
{
|
2023-11-27 14:31:00 +08:00
|
|
|
|
Q_OBJECT
|
2023-11-26 23:05:35 +08:00
|
|
|
|
public:
|
2023-11-27 14:31:00 +08:00
|
|
|
|
prot_slave()
|
|
|
|
|
{
|
|
|
|
|
if_ = nullptr;
|
|
|
|
|
codec_ = nullptr;
|
2023-11-29 15:36:45 +08:00
|
|
|
|
broadcast_=nullptr;
|
2023-11-27 14:31:00 +08:00
|
|
|
|
}
|
|
|
|
|
~prot_slave() {}
|
|
|
|
|
void init();
|
|
|
|
|
bool set_slave_handle(int addr, HandleSlave *handle);
|
2023-11-29 15:36:45 +08:00
|
|
|
|
bool set_boardcast_handle(QList<int> addrs,HandleBoardCast *handle);
|
2023-11-26 23:05:35 +08:00
|
|
|
|
protected slots:
|
2023-11-27 14:31:00 +08:00
|
|
|
|
void send_data_slot(int addr, int cmd, myarray data);
|
|
|
|
|
|
2023-11-26 23:05:35 +08:00
|
|
|
|
protected:
|
2023-11-27 14:31:00 +08:00
|
|
|
|
InterFace *if_;
|
|
|
|
|
Codec *codec_;
|
|
|
|
|
QList<HandleSlave *> slaves;
|
2023-11-29 15:36:45 +08:00
|
|
|
|
HandleBoardCast *broadcast_;
|
2023-12-05 18:37:40 +08:00
|
|
|
|
signals:
|
|
|
|
|
void boardcast_dolater_signal(int cmd,myarray data);
|
|
|
|
|
void slave_dolater_signal(int cmd,myarray data);
|
|
|
|
|
|
2023-11-26 23:05:35 +08:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
prot_slave *protSlave();
|
|
|
|
|
|
|
|
|
|
#endif // PROT_SLAVE_H
|