重新构建的批检仪主板程序

This commit is contained in:
andy
2023-11-26 23:05:35 +08:00
parent b1b69d307f
commit 4a70f64693
29 changed files with 2565 additions and 64 deletions

View File

@@ -0,0 +1,34 @@
#include "interface/codec.h"
Codec *codecFind(const char *name)
{
extern const int __start_codecdef;
extern const int __stop_codecdef;
codec_def *start=(codec_def *)&__start_codecdef;
codec_def *end=(codec_def *)&__stop_codecdef;
codec_def *item = 0;
for (item=start;item<end;item++)
{
if (item != nullptr)
{
if (strcmp(name, item->name) == 0)
return item->codec_get_fun();
}
}
qWarning("can not find codec named '%s'", name);
return nullptr;
}

View File

@@ -13,9 +13,16 @@ public:
fullFrame = false;
}
virtual ~Codec() {}
virtual myarray encode(int srcAddr, int dstAddr, int cmd, myarray data) = 0;
virtual myarray decode(int &srcAddr, int &dstAddr, int &cmd, myarray data) = 0;
virtual myarray decode(int &srcAddr, int &dstAddr, int &cmd)
// 返回true,则是一个完整的帧
// virtual bool packCheck(myarray data){return false;}
// virtual bool recvByte(int byte){return false;}
// virtual myarray encode(int srcAddr, int dstAddr, int cmd, myarray data){return myarray();}
// virtual myarray decode(int &srcAddr, int &dstAddr, int &cmd, myarray data){return myarray();}
virtual bool packCheck(myarray data)=0;
virtual bool recvByte(int byte)=0;
virtual myarray encode(int srcAddr, int dstAddr, int cmd, myarray data)=0;
virtual myarray decode(int &srcAddr, int &dstAddr, int &cmd, myarray data)=0;
myarray decode(int &srcAddr, int &dstAddr, int &cmd)
{
if (fullFrame == true)
{
@@ -24,11 +31,37 @@ public:
}
return myarray();
}
virtual bool recvByte(int byte) = 0;
protected:
bool fullFrame;
myarray data;
};
Codec *codecFind(const char *name);
typedef struct{
const char *name;
Codec *(*codec_get_fun)();
}codec_def;
#define codec_export(name_,fun_) \
const static char __codec_##name_##_name[] __attribute__((section(".rodata.codecstr"))) = #name_; \
__attribute__((used)) static codec_def _codec_##name_ __attribute__((section("codecdef")))={\
.name=__codec_##name_##_name,\
.codec_get_fun=fun_,\
}
#endif // CODEC_H

91
interface/codec_m4.cpp Normal file
View File

@@ -0,0 +1,91 @@
#include "codec_m4.h"
#include "QDebug"
bool codec_m4::recvByte(int byte)
{
bool ack = false;
if (fullFrame == true)
{
return fullFrame;
}
data.append(byte);
switch (data.size()) {
case 1:
if(uint8_t(data[0])==0xff)
{
num_to_read=2;
}
else
{
data.remove(0,1);
num_to_read=0;
}
break;
case 2:
{
int len=data[1];
num_to_read=len+2;
}
break;
default:
break;
}
// 此时一帧数据已完成
if(num_to_read>0&&num_to_read==data.size())
{
data.remove(0,2);
qDebug()<<"recv_m4:"<<QString(data)<<endl;
ack=true;
num_to_read=0;
}
fullFrame=ack;
return fullFrame;
}
bool codec_m4::packCheck(myarray data)
{
if(data[0]!=0xff){
return false;
}
if(data.size()>=2&&(data.size()==(data[1]+2))){
return true;
}
return false;
}
myarray codec_m4::encode(int srcAddr, int dstAddr, int cmd, myarray data)
{
myarray r;
r.append(0xff);
r.append(char(data.size()));
r.append(data);
return r;
}
myarray codec_m4::decode(int &srcAddr, int &dstAddr, int &cmd, myarray data)
{
if(packCheck(data)){
return myarray(data.mid(2));
}
}
Codec *codec_get()
{
static Codec *codec_=nullptr;
if(codec_==nullptr){
codec_=new codec_m4();
}
return codec_;
}
codec_export(codec_m4,codec_get);

18
interface/codec_m4.h Normal file
View File

@@ -0,0 +1,18 @@
#ifndef CODEC_M4_H
#define CODEC_M4_H
#include "interface/codec.h"
class codec_m4:public Codec
{
public:
codec_m4(){num_to_read=0;}
virtual bool packCheck(myarray data);
virtual bool recvByte(int byte);
virtual myarray encode(int srcAddr, int dstAddr, int cmd, myarray data);
virtual myarray decode(int &srcAddr, int &dstAddr, int &cmd, myarray data);
protected:
int num_to_read;
};
#endif // CODEC_M4_H

86
interface/codec_slave.cpp Normal file
View File

@@ -0,0 +1,86 @@
#include "codec_slave.h"
#include "base/crc.h"
myarray codec_slave::encode(int srcAddr, int dstAddr, int cmd, myarray data)
{
Q_UNUSED(srcAddr);
myarray t;
uint16_t len=data.size()+10;
cmd_no++;
t.append('Y');
t.append('e');
t.append(len&0xff);
t.append(len>>8);
t.append(char(0));// 源地址
t.append(char(dstAddr&0xff));// 目标地址
t.append(cmd);// 命令码
t.append(cmd_no&0xff);
t.append(cmd_no>>8);
t.append(data);
t.append(crc::crc8((uint8_t *)t.data(),t.size()));
return t;
}
myarray codec_slave::decode(int &srcAddr, int &dstAddr, int &cmd, myarray data)
{
myarray r;
QString str_err="ok";
if(data.size()<10)
{
// 一帧数据至少10字节
qWarning("recv data len too less");
str_err="recv data len too less.";
return r;
}
uint16_t len=data[2]|(data[3]<<8);
uint8_t crc=crc::crc8((uint8_t *)data.data(),data.size()-1);
if(len!=data.size())
{
// 如果长度不相等则产生了数据丢失
qWarning("recv data have lossed");
str_err="recv data have lossed.";
return r;
}
srcAddr=data[4];
dstAddr=data[5];
uint16_t no=data[7]|(data[8]<<8);
uint16_t h_no=cmd_no;
if(no!=h_no)
{
// 发送一条指令应等待其返回,此时流水号应相同
//qWarning()<<"alave_addr="<<src_addr<<" cmd_no error:host="<<h_no<<",slave="<<no<<endl;
//return r;
//str_err="cmd no err.";
}
if(crc!=uint8_t(data[len-1]))
{
// crc校验不对
qWarning("recv data crc check error:%02x,%02x",crc,uint8_t(data[len-1]));
qWarning("data=%s",data.toHex(' ').data());
str_err="crc check err.";
}
cmd=data[6];
r=data.mid(9,len-10);
return r;
}
Codec *codec_slave_get()
{
static Codec *codec_=nullptr;
if(codec_==nullptr){
codec_=new codec_slave();
}
return codec_;
}
codec_export(codec_slave,codec_slave_get);

21
interface/codec_slave.h Normal file
View File

@@ -0,0 +1,21 @@
#ifndef CODEC_SLAVE_H
#define CODEC_SLAVE_H
#include "interface/codec.h"
class codec_slave: public Codec
{
public:
codec_slave(): Codec(){
}
virtual bool packCheck(myarray data){return false;}
virtual bool recvByte(int byte){return false;}
virtual myarray encode(int srcAddr, int dstAddr, int cmd, myarray data);
virtual myarray decode(int &srcAddr, int &dstAddr, int &cmd, myarray data);
protected:
uint16_t cmd_no;
};
#endif // CODEC_SLAVE_H

View File

@@ -1,18 +1,10 @@
#include "codec.h"
#include "base/crc.h"
#include "interface/codec_ym.h"
class CodecYm : public Codec
{
Q_OBJECT
public:
CodecYm() : Codec()
{
is_big_data = false;
num_to_read = 0;
}
~CodecYm() {}
// 重载接收字节函数
bool recvByte(int byte)
bool CodecYm::recvByte(int byte)
{
bool ack = false;
if (fullFrame == true)
@@ -74,26 +66,38 @@ public:
return fullFrame;
}
// 重载解码函数
QByteArray decode(int &srcAddr, int &dstAddr, int &cmd, QByteArray data)
myarray CodecYm::decode(int &srcAddr, int &dstAddr, int &cmd, myarray data)
{
Q_UNUSED(srcAddr);
Q_UNUSED(dstAddr);
QByteArray r;
myarray r;
if(packCheck(data)==true){
cmd=this->cmd;
if (is_big_data == false)
r = data.mid(7, len - 3);
else
r = data.mid(11, len - 7);
}
return r;
}
bool CodecYm::packCheck(myarray data)
{
bool ack=false;
if (data.size() < 9)
{
// 主机一帧数据至少9字节
qWarning("recv data len too less");
return r;
return ack;
}
if ((uint8_t(data[0]) != 0x59u) || (uint8_t(data[1]) != 0x6du))
{
// 帧头不对
qWarning("frame head not 0x59 0x6d");
return r;
return ack;
}
int len = (data[2] | (data[3] << 8));
len = (data[2] | (data[3] << 8));
if (len == 65535)
{
// 重新设置数据长度
@@ -108,10 +112,10 @@ public:
{
// 如果长度不相等则产生了数据丢失
qWarning("recv data have lossed");
return r;
return ack;
}
uint8_t chk_a = 0, chk_b = 0;
// crc::crc16((uint8_t *)data.data(),2,len+4,&chk_a,&chk_b);
crc::crc16((uint8_t *)data.data(),2,len+4,&chk_a,&chk_b);
if (chk_a != uint8_t(data[data.size() - 2]) || chk_b != uint8_t(data[data.size() - 1]))
{
// crc校验不对
@@ -122,15 +126,58 @@ public:
cmd_no = data[5] | (data[6] << 8);
cmd = data[4];
// 数据负载
if (is_big_data == false)
r = data.mid(7, len - 3);
else
r = data.mid(11, len - 7);
return r;
return true;
}
myarray CodecYm::encode(int srcAddr, int dstAddr, int cmd, myarray data)
{
Q_UNUSED(srcAddr);
Q_UNUSED(dstAddr);
myarray t;
uint32_t len=data.size()+3;
t.append(0x59u);
t.append(0x6du);
t.append(0x43u);
if(len<65535)
{
t.append((len)&0xff);
t.append((len)>>8);
t.append(cmd);
t.append(cmd_no&0xff);
t.append(cmd_no>>8);
}else{
len+=4;
t.append(0xff);
t.append(0xff);
t.append(cmd);
t.append(cmd_no&0xff);
t.append(cmd_no>>8);
t.append(len&0xff);
t.append((len>>8)&0xff);
t.append((len>>16)&0xff);
t.append((len>>24)&0xff);
}
t.append(data);
uint8_t chk_a,chk_b;
crc::crc16((uint8_t *)t.data(),3,len+5,&chk_a,&chk_b);
t.append(chk_a);
t.append(chk_b);
return t;
}
private:
bool is_big_data;
int num_to_read;
int cmd_no;
};
Codec *codec_ym_get()
{
static Codec *codec_=nullptr;
if(codec_==nullptr){
codec_=new CodecYm();
}
return codec_;
}
codec_export(codec_ym,codec_ym_get);

39
interface/codec_ym.h Normal file
View File

@@ -0,0 +1,39 @@
#ifndef CODEC_YM_H
#define CODEC_YM_H
#include "interface/codec.h"
class CodecYm : public Codec
{
Q_OBJECT
public:
CodecYm() : Codec()
{
is_big_data = false;
num_to_read = 0;
}
~CodecYm() {}
// 重载接收字节函数
bool recvByte(int byte);
// 重载解码函数
myarray decode(int &srcAddr, int &dstAddr, int &cmd, myarray data);
bool packCheck(myarray data);
myarray encode(int srcAddr, int dstAddr, int cmd, myarray data);
private:
bool is_big_data;
int num_to_read;
int cmd_no;
int cmd;
int len;
};
#endif // CODEC_YM_H

View File

@@ -1,11 +1,186 @@
#include "if_tcp.h"
#include "QNetworkConfigurationManager"
#include "QThread"
if_tcp::if_tcp()
{
this->connect_state=false;
this->timer_reconnect_=nullptr;
this->tcp_socket_=nullptr;
this->reconnect_timeout_ms=10000;
this->cfg_=syscfg();
this->timer_recv_end_=nullptr;
this->recv_end_timeout_ms=100;
qDebug("tcp created.");
}
if_tcp::~if_tcp()
{
}
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);
connect(tcp_socket_, SIGNAL(connected()), this, SLOT(connected_cb()));
connect(tcp_socket_, SIGNAL(disconnected()), this, SLOT(disconnected_cb()));
connect(tcp_socket_, SIGNAL(stateChanged(QAbstractSocket::SocketState)), this, SLOT(state_changed_cb(QAbstractSocket::SocketState)));
connect(tcp_socket_, SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(on_error_cb(QAbstractSocket::SocketError)));
connect(tcp_socket_, SIGNAL(readyRead()), this, SLOT(ready_read_cb()));
tcp_socket_->setSocketOption(QAbstractSocket::LowDelayOption, 1);// 禁用Nagle算法.
tcp_socket_->setSocketOption(QAbstractSocket::KeepAliveOption, 1);
if(cfg_->tcp_enable)
tcp_socket_->connectToHost(QHostAddress(cfg_->server_ip), cfg_->server_port);
}
}
// 获取本机地址
QString if_tcp::get_local_ip()
{
QList<QNetworkInterface> network =QNetworkInterface::allInterfaces();
foreach (QNetworkInterface net, network)
{
QString netName=net.humanReadableName();
if(netName=="eth0")
{
QList<QNetworkAddressEntry> list=net.addressEntries(); // 获取IP地址与子掩码等
foreach(QNetworkAddressEntry address,list)
{
if(address.ip().protocol()==QAbstractSocket::IPv4Protocol) // 获取IPv4的地址
{
return address.ip().toString();
}
}
}
}
return QString();
}
void if_tcp::reconnect_cb()
{
if(connect_state!=true)
{
QNetworkConfigurationManager mgr;
if(mgr.isOnline()==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(QHostAddress(get_local_ip())!=QHostAddress(local_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");
}
void if_tcp::disconnected_cb()
{
connect_state=false;
qInfo("disconnected");
}
void if_tcp::state_changed_cb(QAbstractSocket::SocketState nSocketState)
{
qInfo("state changed:%d",nSocketState);
}
void if_tcp::on_error_cb(QAbstractSocket::SocketError nErrCode)
{
connect_state=false;
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:"<<crc::byte_array_to_string(recv)<<endl;
}
int if_tcp::write(myarray data)
{
if(nullptr == tcp_socket_ || false == connect_state)
{
//qWarning() << "Cant send data , TcpClient socket not connect.";
return 0;
}
int wb = tcp_socket_->write(data);
if(!tcp_socket_->flush())
{
//connect_state=false;
qWarning("write fial:[%s]",data.toHex(' ').data());
}
else
{
timer_reconnect_->start();
}
return wb;
}
InterFace *if_tcp_get()
{
static InterFace *if_=nullptr;
if(if_==nullptr){
if_=new if_tcp();
QTimer::singleShot(0,if_,&if_->init);
}
return if_;
}
if_export(tcp,if_tcp_get);

View File

@@ -3,6 +3,14 @@
#include <QObject>
#include <interface/interface.h>
#include "QTimer"
#include <QNetworkInterface>
#include <QTcpSocket>
#include <QObject>
#include <QThread>
#include <QTimer>
#include "QByteArray"
#include "base/mycfg.h"
class if_tcp : public InterFace
{
@@ -10,8 +18,31 @@ class if_tcp : public InterFace
public:
if_tcp();
virtual ~if_tcp();
void init();
int write(myarray data);
protected:
QString get_local_ip();
protected slots:
void reconnect_cb();
void connected_cb();
void disconnected_cb();
void state_changed_cb(QAbstractSocket::SocketState nSocketState);
void on_error_cb(QAbstractSocket::SocketError nErrCode);
void ready_read_cb();
signals:
void tcp_connected_signal();
protected:
mycfg *cfg_;
QTimer *timer_reconnect_;
int reconnect_timeout_ms;
QTcpSocket *tcp_socket_;
bool connect_state;
QTimer *timer_recv_end_;
int recv_end_timeout_ms;
};
#endif // IF_TCP_H

View File

@@ -3,30 +3,30 @@
#include "string.h"
#include "QDebug"
typedef struct
{
InterFace *interface;
const char *name;
} self_table_def;
static self_table_def g_self_table[] =
{
{.interface = 0, .name = "default"},
};
InterFace *interFaceFind(const char *name)
{
int num = sizeof(g_self_table) / sizeof(g_self_table[0]);
self_table_def *item = 0;
for (int i = 0; i < num; i++)
extern const int __start_ifdef;
extern const int __stop_ifdef;
if_def *start=(if_def *)&__start_ifdef;
if_def *end=(if_def *)&__stop_ifdef;
if_def *item = 0;
for (item=start;item<end;item++)
{
item = &g_self_table[i];
if (item != nullptr)
{
if (strcmp(name, item->name) == 0)
return item->interface;
return item->if_get_fun();
}
}
qWarning("can not find interface named '%s'", name);
return nullptr;
}

View File

@@ -3,23 +3,45 @@
#include <QObject>
#include "base/base.h"
#include "interface/codec.h"
using namespace std;
using namespace std::placeholders;
typedef std::function<void(void)> irq_cb;
typedef std::function<void(myarray data)> irq_cb;
class InterFace : public QObject
{
Q_OBJECT
public:
InterFace() {}
InterFace() {irq_fun=nullptr;}
virtual ~InterFace() {}
virtual void init() = 0;
virtual int write(myarray data) = 0;
virtual void set_irq(irq_cb fun, myarray &data) = 0;
virtual void set_irq(irq_cb fun){
this->irq_fun=fun;
}
protected:
irq_cb irq_fun;
};
InterFace *interFaceFind(const char *name);
typedef struct{
const char *name;
InterFace *(*if_get_fun)();
}if_def;
#define if_export(name_,fun_) \
const static char __if_##name_##_name[] __attribute__((section(".rodata.ifstr"))) = #name_; \
__attribute__((used)) static if_def _if_##name_ __attribute__((section("ifdef")))={\
.name=__if_##name_##_name,\
.if_get_fun=fun_,\
}
#endif // INTERFACE_H