diff --git a/ReadMe.txt b/ReadMe.txt index 8319dc9..841f216 100644 --- a/ReadMe.txt +++ b/ReadMe.txt @@ -37,7 +37,9 @@ 解决找不到槽任务返回值的bug 从机返回数据按地址排序 解决从机无返回时报错异常通道与实际不符的bug - +2023.12.27 + 添加tcp心跳 + 添加升级小板程序、方案、jwt文件的进度条命令 diff --git a/checker_host.pro b/checker_host.pro index dee4aa4..ff846f1 100644 --- a/checker_host.pro +++ b/checker_host.pro @@ -50,7 +50,8 @@ SOURCES += \ prot_cmd/cmd_coder.cpp \ prot_cmd/cmd_m4.cpp \ prot_cmd/cmd_pc.cpp \ - prot_cmd/cmd_slave.cpp + prot_cmd/cmd_slave.cpp \ + prot_cmd/keep_live.cpp HEADERS += \ base/base.h \ @@ -83,7 +84,8 @@ HEADERS += \ prot_cmd/cmd_coder.h \ prot_cmd/cmd_m4.h \ prot_cmd/cmd_pc.h \ - prot_cmd/cmd_slave.h + prot_cmd/cmd_slave.h \ + prot_cmd/keep_live.h FORMS += \ mainwindow.ui diff --git a/complier_info.h b/complier_info.h index 9067bf8..0c2647e 100644 --- a/complier_info.h +++ b/complier_info.h @@ -6,7 +6,7 @@ -#define BUILD_DATE "2023-12-26 17:53:34" +#define BUILD_DATE "2023-12-27 11:25:22" diff --git a/info.json b/info.json index 1ea43ac..f2434c7 100644 --- a/info.json +++ b/info.json @@ -1,5 +1,5 @@ { - "build_date": "2023-12-26 17:53:34", + "build_date": "2023-12-27 11:25:22", "hard_version": "MHPZ2_V1.00", "private": [ "info.json", diff --git a/interface/if_tcp.cpp b/interface/if_tcp.cpp index 73112b3..d03e766 100644 --- a/interface/if_tcp.cpp +++ b/interface/if_tcp.cpp @@ -2,12 +2,67 @@ #include "QNetworkConfigurationManager" #include "QThread" + + + + +const int keepalive = 1; // 开启keepalive属性 +const int keepidle = 5; // 如果连接在5秒内没有任何数据来往则进行探测 +const int keepinterval = 3; // 探测时发包的时间间隔为3秒 +const int keepcount = 3; // 尝试探测的次数, 如果第一次探测包就收到响应,则不在继续探测 + +#if 1 +#include +#include +#include +#include + +// 开启TCP心跳检测机制 +int enableKeepalive(int fd) { + if (setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, &keepalive, sizeof(keepalive)) < 0) return -1; + if (setsockopt(fd, SOL_TCP, TCP_KEEPIDLE, &keepidle, sizeof(keepidle)) < 0) return -1; + if (setsockopt(fd, SOL_TCP, TCP_KEEPINTVL, &keepinterval, sizeof(keepinterval)) < 0) return -1; + if (setsockopt(fd, SOL_TCP, TCP_KEEPCNT, &keepcount, sizeof(keepcount)) < 0) return -1; + return 0; +} +#else + +int enableKeepalive(int fd) +{ + return -1; +} +#endif + + + +static bool CheckNetInfo() +{ + QNetworkInterface net= QNetworkInterface::interfaceFromName("eth0"); + if(net.flags().testFlag(QNetworkInterface::IsUp) + && net.flags().testFlag(QNetworkInterface::IsRunning) + && !net.flags().testFlag(QNetworkInterface::IsLoopBack) + && (net.name() == "eth0")) + { + // qDebug() << "eth0 is Connected" << endl; + return true; + } + else + { + // qDebug() << "eth0 is Not Connected"; + return false; + } +} + + + + + if_tcp::if_tcp() { this->connect_state = false; this->timer_reconnect_ = nullptr; this->tcp_socket_ = nullptr; - this->reconnect_timeout_ms = 10000; + this->reconnect_timeout_ms = 3000; this->cfg_ = syscfg(); this->timer_recv_end_ = nullptr; @@ -33,11 +88,9 @@ void if_tcp::init() if (nullptr == timer_reconnect_) { timer_reconnect_ = new QTimer(this); - connect(timer_reconnect_, &QTimer::timeout, this, &if_tcp::reconnect_cb); } timer_reconnect_->start(reconnect_timeout_ms); - if (nullptr == tcp_socket_) { tcp_socket_ = new QTcpSocket(this); @@ -49,8 +102,10 @@ void if_tcp::init() tcp_socket_->setSocketOption(QAbstractSocket::LowDelayOption, 1); // 禁用Nagle算法. tcp_socket_->setSocketOption(QAbstractSocket::KeepAliveOption, 1); - if (cfg_->tcp_enable) + if (cfg_->tcp_enable){ tcp_socket_->connectToHost(QHostAddress(cfg_->server_ip), cfg_->server_port); + enableKeepalive(tcp_socket_->socketDescriptor()); + } } } @@ -78,39 +133,25 @@ QString if_tcp::get_local_ip() void if_tcp::reconnect_cb() { - if (connect_state != true) - { - QNetworkConfigurationManager mgr; - if (mgr.isOnline() == true) + // 网线拔出之后自动断开连接 + if(CheckNetInfo()==false){ + if(connect_state!=false){ + connect_state=false; + tcp_socket_->close(); + } + }else{ + if (connect_state != true) { if (cfg_->tcp_enable) { - qDebug("network is online."); tcp_socket_->connectToHost(QHostAddress(cfg_->server_ip), cfg_->server_port); } } - else - { - if (cfg_->tcp_enable) - { - qDebug("network is not online."); - } - } - // 设置为配置的ip地址 - // if (get_local_ip().isEmpty()) - // { - // qDebug("modify local ip addr."); - // QString str = "ifconfig eth0 %1"; - // system(str.arg(cfg_->local_ip).toLocal8Bit().data()); - // str = "route add default gw %1"; - // system(str.arg(cfg_->gateway_ip).toLocal8Bit().data()); - // } } } void if_tcp::connected_cb() { - timer_reconnect_->start(); connect_state = true; emit tcp_connected_signal(); qInfo("connected"); @@ -124,43 +165,41 @@ void if_tcp::disconnected_cb() void if_tcp::state_changed_cb(QAbstractSocket::SocketState nSocketState) { - qInfo("state changed:%d", nSocketState); + // qInfo("state changed:%d", nSocketState); } void if_tcp::on_error_cb(QAbstractSocket::SocketError nErrCode) { connect_state = false; - qWarning("on error:%d", nErrCode); + // qWarning("on error:%d", nErrCode); } void if_tcp::ready_read_cb() { QByteArray data = tcp_socket_->readAll(); - timer_reconnect_->start(); if (irq_fun) { irq_fun(myarray(data)); } - // qInfo()<< "recv data from tcp:"<write(data); if (!tcp_socket_->flush()) { - // connect_state=false; qWarning("write fial:[%s]", data.toHex(' ').data()); } else { - timer_reconnect_->start(); } return wb; } diff --git a/interface/if_tcp.h b/interface/if_tcp.h index 008de2f..d966191 100644 --- a/interface/if_tcp.h +++ b/interface/if_tcp.h @@ -33,6 +33,8 @@ protected slots: void ready_read_cb(); signals: void tcp_connected_signal(); + void tcp_recv_signal(); + void tcp_send_signal(); protected: mycfg *cfg_; @@ -45,4 +47,8 @@ protected: int recv_end_timeout_ms; }; + + +InterFace *if_tcp_get(); + #endif // IF_TCP_H diff --git a/main.cpp b/main.cpp index b01400d..815503b 100644 --- a/main.cpp +++ b/main.cpp @@ -14,7 +14,7 @@ #include "base/debug.h" #include "prot_cmd/cmd_m4.h" #include "base/beep.h" - +#include "prot_cmd/keep_live.h" @@ -38,6 +38,8 @@ int main(int argc, char *argv[]) protSlave(); command_start(); cmd_m4_init(); + KeepLive(); + // 注册信号数据类型 qRegisterMetaType("myarray"); diff --git a/prot/prot_cmdline.cpp b/prot/prot_cmdline.cpp index 4abbcca..3cda443 100644 --- a/prot/prot_cmdline.cpp +++ b/prot/prot_cmdline.cpp @@ -47,7 +47,7 @@ static QString get_local_ip() } -bool CheckNetInfo() +static bool CheckNetInfo() { QNetworkInterface net= QNetworkInterface::interfaceFromName("eth0"); if(net.flags().testFlag(QNetworkInterface::IsUp) diff --git a/prot/prot_pc.h b/prot/prot_pc.h index 82cc75a..d17e50e 100644 --- a/prot/prot_pc.h +++ b/prot/prot_pc.h @@ -27,7 +27,7 @@ public: } } virtual int dolater(int cmd, myarray data) = 0; - virtual void timeout()=0; + virtual void timeout(){busy=0;} int busy; protected: void timeout_start(int ms){ @@ -48,6 +48,40 @@ signals: void send_data_signal(int cmd, myarray data); }; + +/* + +HandlePc 重载示例 +class ChildPc:public HandlePc +{ + // 重载此函数用于接收上位机命令 + int dolater(int cmd, myarray data); + // (可选)重载此函数处理超时的情况 + void timeout(); + // 此变量不为0则忙 + int busy; + // 调用此函数开始超时计时 + void timeout_start(int ms); + // 调用此函数停止超时计时 + void timeout_stop(); + // 调用此函数给上位机发送数据 + void send_data_signal(int cmd, myarray data); +} + +// .cpp 文件中做以下声明以启用 +static HandlePc *get_ChidlPc(){ + return new ChildPc();} +protpc_export(0x30, get_ChidlPc); + + +*/ + + + + + + + class ProtPc : public QObject { Q_OBJECT @@ -61,6 +95,7 @@ public: ~ProtPc() {} void init(); bool docmd(int cmd,myarray data); + bool busy(){return ((handle_!=nullptr)&&(handle_->busy!=0));} public slots: void send_data_slot(int cmd, myarray data); diff --git a/prot/prot_slave.h b/prot/prot_slave.h index 22d5245..ede86ba 100644 --- a/prot/prot_slave.h +++ b/prot/prot_slave.h @@ -50,7 +50,7 @@ protected: timeout_retry(); return 0; } - // 发送操作结束信号 + // 发送操作结束信号,ack=0成功,1失败 int end(int ack,myarray data){ emit end_signal(addr,ack,data); return 0; @@ -228,7 +228,7 @@ protected: 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){ diff --git a/prot_cmd/cmd_pc.cpp b/prot_cmd/cmd_pc.cpp index 4f33edd..c4b78f1 100644 --- a/prot_cmd/cmd_pc.cpp +++ b/prot_cmd/cmd_pc.cpp @@ -7,6 +7,7 @@ #include "base/check_cfg.h" #include "QDebug" #include "elec/elec_judge.h" +#include "QDateTime" typedef struct { @@ -349,7 +350,6 @@ int selfdev_slaveupdate::dolater(int cmd, myarray data) emit send_data_signal(0xfe,myarray(1,char(0))); // 自动给小板升级 - // start_updata_mcu(cfg_->config_path+name,slave_addrs); HandleBoardCast *b=new boardcast_updata(); bool ack=slave->set_boardcast_handle(cfg_->calc_slave_addrs(),b); if(ack==false){ @@ -357,6 +357,8 @@ int selfdev_slaveupdate::dolater(int cmd, myarray data) busy=0; }else{ connect(b,&HandleBoardCast::end_signal,this,&selfdev_slaveupdate::slave_end_slot); + connect(b,&HandleBoardCast::rate_signal,this,&selfdev_slaveupdate::rate_slot); + handle_start_time=QDateTime::currentDateTime().toTime_t(); b->start(data); } @@ -368,6 +370,18 @@ void selfdev_slaveupdate::timeout(){ qDebug("slave update timeout"); } +void selfdev_slaveupdate::rate_slot(int rate, mystring str) +{ + qint64 now_time=QDateTime::currentDateTime().toTime_t(); + now_time=now_time-handle_start_time; + myarray data; + data.append(char(rate&0xff)); + data.append(uint8_t(now_time&0xff)); + data.append(uint8_t((now_time>>8)&0xff)); + data.append(str.toLocal8Bit()); + emit send_data_signal(0x46,data); +} + void selfdev_slaveupdate::slave_end_slot(int addr,int ack, slave_data data) { qDebug("slave update end,ack=%s",ack?"failed":"success"); @@ -414,11 +428,6 @@ int selfdev_update_scheme::dolater(int cmd, myarray data) r.append(ack?char(0):char(1)); r.append(rw); if(ack){ - // 检测数据保存 -// if(comm_f_!=nullptr){ -// delete comm_f_; -// comm_f_=nullptr; -// } // 自动给小板升级 HandleBoardCast *b=new boardcast_updata_scheme(); bool ack=slave->set_boardcast_handle(cfg_->calc_slave_addrs(),b); @@ -427,6 +436,8 @@ int selfdev_update_scheme::dolater(int cmd, myarray data) busy=0; }else{ connect(b,&HandleBoardCast::end_signal,this,&selfdev_update_scheme::slave_end_slot); + connect(b,&HandleBoardCast::rate_signal,this,&selfdev_update_scheme::rate_slot); + handle_start_time=QDateTime::currentDateTime().toTime_t(); myarray scheme=myarray((const char *)ccfg_->check_scheme(),ccfg_->check_scheme_size()); b->start(scheme); } @@ -444,6 +455,17 @@ void selfdev_update_scheme::timeout(){ busy=0; qDebug("slave update timeout"); } +void selfdev_update_scheme::rate_slot(int rate, mystring str) +{ + qint64 now_time=QDateTime::currentDateTime().toTime_t(); + now_time=now_time-handle_start_time; + myarray data; + data.append(char(rate&0xff)); + data.append(uint8_t(now_time&0xff)); + data.append(uint8_t((now_time>>8)&0xff)); + data.append(str.toLocal8Bit()); + emit send_data_signal(0x46,data); +} void selfdev_update_scheme::slave_end_slot(int addr,int ack, slave_data data) { @@ -523,6 +545,8 @@ int selfdev_jwtupdate::dolater(int cmd, myarray data) busy=0; }else{ connect(b,&HandleBoardCast::end_signal,this,&selfdev_slaveupdate::slave_end_slot); + connect(b,&HandleBoardCast::rate_signal,this,&selfdev_slaveupdate::rate_slot); + handle_start_time=QDateTime::currentDateTime().toTime_t(); b->start(data); } diff --git a/prot_cmd/cmd_pc.h b/prot_cmd/cmd_pc.h index 546eba3..81b729a 100644 --- a/prot_cmd/cmd_pc.h +++ b/prot_cmd/cmd_pc.h @@ -116,14 +116,19 @@ class selfdev_slaveupdate : public HandlePc { Q_OBJECT public: - selfdev_slaveupdate() : HandlePc() {} + selfdev_slaveupdate() : HandlePc() { + handle_start_time=0; + } ~selfdev_slaveupdate() {} int dolater(int cmd, myarray data); void timeout(); public slots: void slave_end_slot(int addr,int ack, slave_data data); + void rate_slot(int rate, mystring str); signals: void send_to_m4_signal(myarray data); +protected: + qint64 handle_start_time; }; @@ -142,8 +147,11 @@ public: void timeout(); public slots: void slave_end_slot(int addr,int ack, slave_data data); + void rate_slot(int rate, mystring str); signals: void send_to_m4_signal(myarray data); +protected: + qint64 handle_start_time; }; @@ -277,7 +285,7 @@ public: // pc指令生成从机列表 virtual QList cmd_pc_to_addrs(myarray data)=0; // 从机发起命令 - virtual int cmd_slave()=0; + virtual int cmd_slave(){return 0x20;} // pc收到回复,返回0不回复 virtual int cmd_pc_recv()=0; // 生成接收回复到pc @@ -299,7 +307,30 @@ signals: }; +/* +selfdev_runtask 重载示例 +class selfdef_custom:public selfdev_runtask +{ + // 重载此函数把pc的指令格式转化为从机能识别的格式 + myarray cmd_pc_to_slave(myarray data); + // 重载此函数根据pc指令生成要执行命令的从机列表 + QList cmd_pc_to_addrs(myarray data); + // (可选)重载此函数设置从机要执行的命令,不重载则使用命令0x20 + int cmd_slave(); + // 重载此函数指定收到数据回复的命令字 + int cmd_pc_recv(); + // 重载此函数生成接收到数据回复的数据 + myarray cmd_pc_recv_to_pc(); + // 重载此函数指定操作结束回复的命令字 + int cmd_pc_ret(); + // 重载此函数把从机的数据格式转化为pc能识别的格式 + myarray ret_slave_to_pc(QList data); +} + + + +*/ // 赋码仪配置参数 diff --git a/prot_cmd/cmd_slave.cpp b/prot_cmd/cmd_slave.cpp index ec35b8d..cc7fbe5 100644 --- a/prot_cmd/cmd_slave.cpp +++ b/prot_cmd/cmd_slave.cpp @@ -380,6 +380,16 @@ int boardcast_updata_scheme::start(myarray data) int boardcast_updata_scheme::dolater(int cmd, myarray data) { + for(int i=0;iget_check_time_out()*1000; } - qDebug("addr %d start ,timeout=%d",addr,timeout); + // 这里addr是bit数,用16进制打印 + qDebug("addr 0x%06X start ,timeout=%d",addr,timeout); this->data=data; send_pack_num=0; send_bytes=0; @@ -534,7 +545,8 @@ bool slave_cmd::send_next() void slave_cmd::timeout() { timeout_stop(); - qWarning("addr %d timeout.",addr); + int addr_timeout=addr^addr_response; + qWarning("addr 0x%06X timeout",addr_timeout); end(1,ret_data); busy=0; } @@ -571,7 +583,8 @@ int slave_cmd2::start(myarray data) { int timeout=5000; busy=1; - qDebug("addr %d start ,timeout=%d",addr,timeout); + // 这里addr是bit数,用16进制打印 + qDebug("addr 0x%06X start ,timeout=%d",addr,timeout); send_data(cmd,data,3); timeout_start(timeout); return 0; @@ -580,7 +593,8 @@ int slave_cmd2::start(myarray data) void slave_cmd2::timeout() { timeout_stop(); - qWarning("addr %d timeout.",addr); + int addr_timeout=addr^addr_response; + qWarning("addr 0x%06X timeout",addr_timeout); end(1,ret_data); busy=0; } diff --git a/prot_cmd/cmd_slave.h b/prot_cmd/cmd_slave.h index df0fb9f..2ea58c6 100644 --- a/prot_cmd/cmd_slave.h +++ b/prot_cmd/cmd_slave.h @@ -147,6 +147,7 @@ public: // 获取命令数据,使用前先设置cmd +// 自动加入包信息,可以发送长数据 class slave_cmd:public HandleBoardCast { public: @@ -169,6 +170,7 @@ protected: // 获取命令数据,使用前先设置cmd +// 不加入分包信息,不可发送长数据 class slave_cmd2:public HandleBoardCast { public: diff --git a/prot_cmd/keep_live.cpp b/prot_cmd/keep_live.cpp new file mode 100644 index 0000000..476cb27 --- /dev/null +++ b/prot_cmd/keep_live.cpp @@ -0,0 +1,113 @@ +#include "keep_live.h" +#include "interface/if_tcp.h" +#include "base/mycfg.h" +#include "interface/if_tcp.h" +#include "prot/prot_pc.h" +#include "QDateTime" + + +int keep_live_checker::dolater(int cmd,myarray data) +{ + data.remove(0,1); + QDateTime t=QDateTime::currentDateTime(); + if(t.toString("yyyy-MM-dd hh:mm:ss")!=QString(data)) + { + // 时间不相等则设置 + //qInfo()<<"set time="<(if_tcp_get()); + if(cfg_->tcp_enable!=true){ + return; + } + if(timer_==nullptr){ + timer_=new QTimer(); + connect(timer_,&QTimer::timeout,this,&keep_live::timeout_slot); + timer_->setInterval(1000); + timer_->start(); + connect(tcp,&if_tcp::tcp_connected_signal,this,&keep_live::connected_slot); + connect(tcp,&if_tcp::tcp_recv_signal,this,&keep_live::recv_slot); + } +} + + +void keep_live::connected_slot() +{ + if(timer_!=nullptr){ + timer_->setInterval(30*1000); + timer_->start(); + } +} + +void keep_live::recv_slot() +{ + if(timer_!=nullptr){ + timer_->start(); + } +} + + + + +// state 0idle,1,busy,2,failt +void keep_checker::timeout_slot(){ + myarray data; + mycfg *cfg_=syscfg(); + ProtPc *pc_=protPc(); + data.append(uint8_t(cfg_->local_id)); + data.append(uint8_t(pc_->busy())); + data.append(myarray("正常")); + pc_->send_data_slot(uint8_t(0x23),data); +} + + + + +void keep_coder::timeout_slot(){ + myarray data; + mycfg *cfg_=syscfg(); + ProtPc *pc_=protPc(); + data.append(uint8_t(0)); + data.append(uint8_t(0xff)); + data.append(uint8_t(0x03)); + data.append(uint8_t(cfg_->local_id)); + data.append(uint8_t(0xff)); + data.append(uint8_t(0x03)); + pc_->send_data_slot(uint8_t(0x8a),data); +} + + +keep_live *KeepLive() +{ + static keep_live *kp=nullptr; + mycfg *cfg_=syscfg(); + if(kp!=nullptr){ + return kp; + } + if(cfg_->tcp_enable){ + if(cfg_->device_type=="checker"){ + kp=new keep_checker(); + }else if(cfg_->device_type.contains("coder",Qt::CaseInsensitive)==true){ + kp=new keep_coder(); + } + } + return kp; +} + diff --git a/prot_cmd/keep_live.h b/prot_cmd/keep_live.h new file mode 100644 index 0000000..67ebccc --- /dev/null +++ b/prot_cmd/keep_live.h @@ -0,0 +1,64 @@ +#ifndef KEEP_LIVE_H +#define KEEP_LIVE_H + +#include +#include "prot/prot_pc.h" +#include "QTimer" + +class keep_live_checker : public HandlePc +{ + Q_OBJECT +public: + keep_live_checker():HandlePc(){ + + } + int dolater(int cmd,myarray data); +}; + + + +class keep_live:public QObject +{ + Q_OBJECT +public: + keep_live():QObject(){ + timer_=nullptr; + } + void init(); +public slots: + virtual void timeout_slot()=0; + void connected_slot(); + void recv_slot(); +protected: + QTimer *timer_; +}; + + + +class keep_checker:public keep_live +{ + Q_OBJECT +public: + keep_checker():keep_live(){ + } + void timeout_slot(); +}; + + +class keep_coder:public keep_live +{ + Q_OBJECT +public: + keep_coder():keep_live(){ + } + void timeout_slot(); +}; + + +keep_live *KeepLive(); + + +#endif // KEEP_LIVE_H + + +