16 changed files with 702 additions and 23 deletions
-
3CMakeLists.txt
-
2app_protocols/transmit_disfection_protocol
-
2app_protocols/zscanprotocol
-
0src/app/transmit_disinfection/transmit_disinfection_can_master.cpp
-
60src/app/transmit_disinfection/transmit_disinfection_can_master.hpp
-
2src/main.cpp
-
167src/protocol/waveshare_can/waveshare_can.cpp
-
112src/protocol/waveshare_can/waveshare_can.hpp
-
226src/protocol/zscanprotocol_com/zscanprotocol_com.cpp
-
107src/protocol/zscanprotocol_com/zscanprotocol_com.hpp
-
3src/zqui/base/appbuilder.hpp
-
4src/zqui/channelmgr/channelmgr.hpp
-
18src/zqui/channelmgr/qt_serial_datachannel.cpp
-
10src/zqui/channelmgr/qt_serial_datachannel.hpp
-
4src/zqui/zqui/mainwindow.h
-
3src/zqui/zqui/zqui.hpp
@ -1 +1 @@ |
|||||
Subproject commit fe4173bbfefd7d6648fbea94717605764b4e7594 |
|
||||
|
Subproject commit 6573835a56f8b1dd2aa1311b6f6136bcc0d182bd |
@ -1 +1 @@ |
|||||
Subproject commit a72ab76f401598ef36a95107a4298292b6c36d8e |
|
||||
|
Subproject commit 5161e29f77f08d1e1bea60827b0ee937fa7943bf |
@ -0,0 +1,60 @@ |
|||||
|
#pragma once
|
||||
|
#include <fstream>
|
||||
|
#include <functional>
|
||||
|
#include <iostream>
|
||||
|
#include <list>
|
||||
|
#include <map>
|
||||
|
#include <memory>
|
||||
|
#include <mutex>
|
||||
|
#include <set>
|
||||
|
#include <sstream>
|
||||
|
#include <string>
|
||||
|
#include <thread>
|
||||
|
#include <vector>
|
||||
|
|
||||
|
//
|
||||
|
#include "protocol/zscanprotocol_com/zscanprotocol_com.hpp"
|
||||
|
#include "zqui/zqui/zqui.hpp"
|
||||
|
|
||||
|
namespace iflytop { |
||||
|
using namespace std; |
||||
|
|
||||
|
class TransmitDisinfectionCanMaster { |
||||
|
TransmitDisinfectionCanMaster() {} |
||||
|
|
||||
|
WaveshareCan *m_channel = nullptr; |
||||
|
|
||||
|
uint8_t m_rxcache[1024] = {0}; |
||||
|
int32_t m_rxlen = 0; |
||||
|
bool m_rxcache_is_full = false; |
||||
|
|
||||
|
mutex lock_; |
||||
|
|
||||
|
unique_ptr<thread> m_thread; |
||||
|
|
||||
|
RxReceiptContext m_rxReceiptContext; |
||||
|
mutex m_rxReceiptContext_lock; |
||||
|
|
||||
|
/*******************************************************************************
|
||||
|
* TX CONTEXT * |
||||
|
*******************************************************************************/ |
||||
|
mutex m_tx_lock; |
||||
|
uint8_t m_txbuf[1024] = {0}; |
||||
|
int32_t m_rxsize = 0; |
||||
|
uint8_t m_txindex = 0; |
||||
|
|
||||
|
CanPacketRxBuffer m_rxbuf[255]; |
||||
|
|
||||
|
on_raw_data_t on_rx_raw; |
||||
|
|
||||
|
uint8_t m_receipt_cache[1024]; |
||||
|
zcanbus_packet_t *m_receipt_frame = (zcanbus_packet_t *)m_receipt_cache; |
||||
|
size_t m_receipt_len = 0; |
||||
|
|
||||
|
ecode2str_t m_ecode2str; |
||||
|
|
||||
|
public: |
||||
|
void initialize(QTSerialChannel *ch); |
||||
|
}; |
||||
|
|
||||
|
} // namespace iflytop
|
@ -0,0 +1,167 @@ |
|||||
|
#include "waveshare_can.hpp"
|
||||
|
|
||||
|
using namespace iflytop; |
||||
|
using namespace std; |
||||
|
#define CANUSB_TTY_BAUD_RATE_DEFAULT 2000000
|
||||
|
|
||||
|
#define TAG "WaveshareCan"
|
||||
|
|
||||
|
static int generate_checksum(const unsigned char* data, int data_len) { |
||||
|
int i, checksum; |
||||
|
|
||||
|
checksum = 0; |
||||
|
for (i = 0; i < data_len; i++) { |
||||
|
checksum += data[i]; |
||||
|
} |
||||
|
|
||||
|
return checksum & 0xff; |
||||
|
} |
||||
|
|
||||
|
static bool isHeader(uint8_t* data) { |
||||
|
if (data[0] == 0xAA && data[1] == 0x55) { |
||||
|
return true; |
||||
|
} |
||||
|
return false; |
||||
|
} |
||||
|
|
||||
|
void WaveshareCan::initialize(QTSerialChannel* serialch) { m_ch = serialch; } |
||||
|
|
||||
|
bool WaveshareCan::regFrameCB(frame_callback_t framecb) { |
||||
|
m_frame_callback = framecb; |
||||
|
// ChannelMgr::ins()->serialCh;
|
||||
|
|
||||
|
m_ch->regRxListener([this](uint8_t* data, size_t len) { |
||||
|
{ |
||||
|
lock_guard<mutex> lock(lock_); |
||||
|
if (len + m_rxlen > sizeof(m_rxcache)) { |
||||
|
m_rxlen = 0; |
||||
|
} |
||||
|
memcpy(m_rxcache + m_rxlen, data, len); |
||||
|
m_rxlen += len; |
||||
|
} |
||||
|
}); |
||||
|
m_thread.reset(new thread([this]() { |
||||
|
while (true) { |
||||
|
this_thread::sleep_for(chrono::milliseconds(1)); |
||||
|
|
||||
|
{ |
||||
|
lock_guard<mutex> lock(lock_); |
||||
|
// 1.找头部
|
||||
|
int32_t headerpos = -1; |
||||
|
for (int32_t i = 0; i < m_rxlen - 1; i++) { |
||||
|
if (isHeader(m_rxcache + i)) { |
||||
|
headerpos = i; |
||||
|
break; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
if (headerpos == -1) { |
||||
|
continue; |
||||
|
} |
||||
|
|
||||
|
// 将包头移动到缓存头部
|
||||
|
if (headerpos != 0) { |
||||
|
memmove(m_rxcache, m_rxcache + headerpos, m_rxlen - headerpos); |
||||
|
m_rxlen = m_rxlen - headerpos; |
||||
|
continue; |
||||
|
} |
||||
|
|
||||
|
if (m_rxlen < 20) continue; |
||||
|
|
||||
|
onReceivePacket(m_rxcache, 20); |
||||
|
memmove(m_rxcache, m_rxcache + 20, m_rxlen - 20); |
||||
|
m_rxlen = m_rxlen - 20; |
||||
|
} |
||||
|
} |
||||
|
})); |
||||
|
} |
||||
|
void WaveshareCan::setCanpPrameter(CANUSB_SPEED speed, CANUSB_MODE mode, CANUSB_FRAME frame) { |
||||
|
int cmd_frame_len; |
||||
|
unsigned char cmd_frame[20]; |
||||
|
|
||||
|
cmd_frame_len = 0; |
||||
|
cmd_frame[0] = 0xaa; |
||||
|
cmd_frame[1] = 0x55; |
||||
|
cmd_frame[2] = 0x02; // 0x02:用固定20字节协议收发数据 0x12-设置用可变协议收发数据
|
||||
|
cmd_frame[3] = speed; // speed
|
||||
|
cmd_frame[4] = frame; // 帧类型
|
||||
|
cmd_frame[5] = 0; /* Filter ID not handled. */ |
||||
|
cmd_frame[6] = 0; /* Filter ID not handled. */ |
||||
|
cmd_frame[7] = 0; /* Filter ID not handled. */ |
||||
|
cmd_frame[8] = 0; /* Filter ID not handled. */ |
||||
|
cmd_frame[9] = 0; /* Mask ID not handled. */ |
||||
|
cmd_frame[10] = 0; /* Mask ID not handled. */ |
||||
|
cmd_frame[11] = 0; /* Mask ID not handled. */ |
||||
|
cmd_frame[12] = 0; /* Mask ID not handled. */ |
||||
|
cmd_frame[13] = mode; // 模式
|
||||
|
cmd_frame[14] = 0x01; // 是否自动重发
|
||||
|
cmd_frame[15] = 0; // 占位,备用
|
||||
|
cmd_frame[16] = 0; // 占位,备用
|
||||
|
cmd_frame[17] = 0; // 占位,备用
|
||||
|
cmd_frame[18] = 0; // 占位,备用
|
||||
|
cmd_frame[19] = generate_checksum(&cmd_frame[2], 17); |
||||
|
|
||||
|
if (!m_ch->isOpen()) { |
||||
|
throw zexception(ke_channel_is_close, "channel is not open"); |
||||
|
} |
||||
|
m_ch->send(cmd_frame, 20); |
||||
|
} |
||||
|
|
||||
|
bool WaveshareCan::sendframe(CANUSB_FRAME frametype, uint32_t id, unsigned char data[], int data_length_code) { |
||||
|
int data_frame_len = 0; |
||||
|
unsigned char data_frame[20] = {0x00}; |
||||
|
waveshare_can_packet_t* packet = (waveshare_can_packet_t*)data_frame; |
||||
|
|
||||
|
packet->packet_header0 = 0xaa; |
||||
|
packet->packet_header1 = 0x55; |
||||
|
packet->type = 0x01; // 数据
|
||||
|
packet->frame_type = frametype; |
||||
|
packet->frame_format = 0x01; // 数据帧
|
||||
|
packet->frame_id_data_1 = id & 0xff; |
||||
|
packet->frame_id_data_2 = (id >> 8) & 0xff; |
||||
|
packet->frame_id_data_3 = (id >> 16) & 0xff; |
||||
|
packet->frame_id_data_4 = (id >> 24) & 0xff; |
||||
|
packet->frame_data_length = data_length_code; |
||||
|
packet->frame_data_1 = data[0]; |
||||
|
packet->frame_data_2 = data[1]; |
||||
|
packet->frame_data_3 = data[2]; |
||||
|
packet->frame_data_4 = data[3]; |
||||
|
packet->frame_data_5 = data[4]; |
||||
|
packet->frame_data_6 = data[5]; |
||||
|
packet->frame_data_7 = data[6]; |
||||
|
packet->frame_data_8 = data[7]; |
||||
|
packet->reserve = 0; |
||||
|
packet->check_code = generate_checksum(&data_frame[2], 17); |
||||
|
|
||||
|
QTSerialChannel* ch = &ChannelMgr::ins()->serialCh; |
||||
|
|
||||
|
if (!ch->isOpen()) { |
||||
|
throw zexception(ke_channel_is_close, "channel is not open"); |
||||
|
} |
||||
|
|
||||
|
ZLOGI(TAG, "tx 0x%08x, %s", id, zhex2str(data, data_length_code).c_str()); |
||||
|
ch->send(data_frame, 20); |
||||
|
|
||||
|
return true; |
||||
|
} |
||||
|
|
||||
|
int WaveshareCan::onReceivePacket(uint8_t* data, size_t len) { |
||||
|
waveshare_can_packet_t* rxpacket = (waveshare_can_packet_t*)data; |
||||
|
|
||||
|
can_rx_frame_t canframe; |
||||
|
canframe.dlc = rxpacket->frame_data_length; |
||||
|
canframe.id = rxpacket->frame_id_data_1 | ((uint32_t)rxpacket->frame_id_data_2 << 8) | ((uint32_t)rxpacket->frame_id_data_3 << 16) | ((uint32_t)rxpacket->frame_id_data_4 << 24); |
||||
|
|
||||
|
canframe.data[0] = rxpacket->frame_data_1; |
||||
|
canframe.data[1] = rxpacket->frame_data_2; |
||||
|
canframe.data[2] = rxpacket->frame_data_3; |
||||
|
canframe.data[3] = rxpacket->frame_data_4; |
||||
|
canframe.data[4] = rxpacket->frame_data_5; |
||||
|
canframe.data[5] = rxpacket->frame_data_6; |
||||
|
canframe.data[6] = rxpacket->frame_data_7; |
||||
|
canframe.data[7] = rxpacket->frame_data_8; |
||||
|
|
||||
|
if (m_frame_callback) { |
||||
|
m_frame_callback(&canframe); |
||||
|
} |
||||
|
} |
@ -0,0 +1,112 @@ |
|||||
|
#pragma once
|
||||
|
|
||||
|
#include <stdint.h>
|
||||
|
#include <stdio.h>
|
||||
|
#include <windows.h>
|
||||
|
|
||||
|
#include <fstream>
|
||||
|
#include <functional>
|
||||
|
#include <iostream>
|
||||
|
#include <list>
|
||||
|
#include <map>
|
||||
|
#include <memory>
|
||||
|
#include <set>
|
||||
|
#include <sstream>
|
||||
|
#include <string>
|
||||
|
#include <thread>
|
||||
|
#include <vector>
|
||||
|
|
||||
|
#include "zqui/zqui/zqui.hpp"
|
||||
|
namespace iflytop { |
||||
|
#define CANUSB_TTY_BAUD_RATE_DEFAULT 2000000
|
||||
|
|
||||
|
typedef enum { |
||||
|
CANUSB_SPEED_1000000 = 0x01, |
||||
|
CANUSB_SPEED_800000 = 0x02, |
||||
|
CANUSB_SPEED_500000 = 0x03, |
||||
|
CANUSB_SPEED_400000 = 0x04, |
||||
|
CANUSB_SPEED_250000 = 0x05, |
||||
|
CANUSB_SPEED_200000 = 0x06, |
||||
|
CANUSB_SPEED_125000 = 0x07, |
||||
|
CANUSB_SPEED_100000 = 0x08, |
||||
|
CANUSB_SPEED_50000 = 0x09, |
||||
|
CANUSB_SPEED_20000 = 0x0a, |
||||
|
CANUSB_SPEED_10000 = 0x0b, |
||||
|
CANUSB_SPEED_5000 = 0x0c, |
||||
|
} CANUSB_SPEED; |
||||
|
|
||||
|
typedef enum { |
||||
|
CANUSB_MODE_NORMAL = 0x00, |
||||
|
CANUSB_MODE_LOOPBACK = 0x01, |
||||
|
CANUSB_MODE_SILENT = 0x02, |
||||
|
CANUSB_MODE_LOOPBACK_SILENT = 0x03, |
||||
|
} CANUSB_MODE; |
||||
|
|
||||
|
typedef enum { |
||||
|
CANUSB_FRAME_STANDARD = 0x01, |
||||
|
CANUSB_FRAME_EXTENDED = 0x02, |
||||
|
} CANUSB_FRAME; |
||||
|
|
||||
|
typedef enum { |
||||
|
CANUSB_INJECT_PAYLOAD_MODE_RANDOM = 0, |
||||
|
CANUSB_INJECT_PAYLOAD_MODE_INCREMENTAL = 1, |
||||
|
CANUSB_INJECT_PAYLOAD_MODE_FIXED = 2, |
||||
|
} CANUSB_PAYLOAD_MODE; |
||||
|
|
||||
|
typedef struct { |
||||
|
uint8_t packet_header0; |
||||
|
uint8_t packet_header1; |
||||
|
uint8_t type; |
||||
|
uint8_t frame_type; |
||||
|
uint8_t frame_format; |
||||
|
uint8_t frame_id_data_1; |
||||
|
uint8_t frame_id_data_2; |
||||
|
uint8_t frame_id_data_3; |
||||
|
uint8_t frame_id_data_4; |
||||
|
uint8_t frame_data_length; |
||||
|
uint8_t frame_data_1; |
||||
|
uint8_t frame_data_2; |
||||
|
uint8_t frame_data_3; |
||||
|
uint8_t frame_data_4; |
||||
|
uint8_t frame_data_5; |
||||
|
uint8_t frame_data_6; |
||||
|
uint8_t frame_data_7; |
||||
|
uint8_t frame_data_8; |
||||
|
uint8_t reserve; |
||||
|
uint8_t check_code; |
||||
|
} waveshare_can_packet_t; |
||||
|
|
||||
|
class WaveshareCan { |
||||
|
public: |
||||
|
typedef struct { |
||||
|
uint32_t id; |
||||
|
uint8_t dlc; |
||||
|
uint8_t data[8]; |
||||
|
} can_rx_frame_t; |
||||
|
|
||||
|
typedef function<void(can_rx_frame_t*)> frame_callback_t; |
||||
|
|
||||
|
private: |
||||
|
unique_ptr<thread> m_thread; |
||||
|
frame_callback_t m_frame_callback; |
||||
|
mutex lock_; |
||||
|
|
||||
|
uint8_t m_rxcache[1024] = {0}; |
||||
|
uint8_t m_rxlen = 0; |
||||
|
|
||||
|
QTSerialChannel* m_ch; |
||||
|
|
||||
|
public: |
||||
|
void initialize(QTSerialChannel* ch); |
||||
|
bool regFrameCB(frame_callback_t framecb); |
||||
|
|
||||
|
void setCanpPrameter(CANUSB_SPEED speed, CANUSB_MODE mode, CANUSB_FRAME frame); |
||||
|
bool sendStdframe(uint32_t id, unsigned char data[], int data_length_code) { return sendframe(CANUSB_FRAME_STANDARD, id, data, data_length_code); } |
||||
|
bool sendExtframe(uint32_t id, unsigned char data[], int data_length_code) { return sendframe(CANUSB_FRAME_EXTENDED, id, data, data_length_code); } |
||||
|
bool sendframe(CANUSB_FRAME frame, uint32_t id, unsigned char data[], int data_length_code); |
||||
|
|
||||
|
private: |
||||
|
int onReceivePacket(uint8_t* data, size_t len); |
||||
|
}; |
||||
|
|
||||
|
} // namespace iflytop
|
@ -0,0 +1,226 @@ |
|||||
|
#include "zscanprotocol_com.hpp"
|
||||
|
|
||||
|
#include <stdarg.h>
|
||||
|
|
||||
|
using namespace iflytop; |
||||
|
#define TAG "ZScanProtocolCom"
|
||||
|
|
||||
|
#define DEFUALT_OVERTIME 30
|
||||
|
|
||||
|
void ZScanProtocolCom::updateChannelConfig() { m_channel->setCanpPrameter(CANUSB_SPEED_500000, CANUSB_MODE_NORMAL, CANUSB_FRAME_EXTENDED); } |
||||
|
|
||||
|
void ZScanProtocolCom::initialize(QTSerialChannel *serialCh) { //
|
||||
|
m_channel = new WaveshareCan(); |
||||
|
m_channel->initialize(serialCh); |
||||
|
|
||||
|
m_channel->regFrameCB([this](WaveshareCan::can_rx_frame_t *canframe) { //
|
||||
|
ZLOGI(TAG, "can rx: 0x%08x %d %s", canframe->id, canframe->dlc, zhex2str(canframe->data, canframe->dlc).c_str()); |
||||
|
|
||||
|
/**
|
||||
|
* @brief 消息格式 |
||||
|
* |
||||
|
* [2] [3bit] [8bit] [8bit] [8bit] |
||||
|
* , from frameNum frameId |
||||
|
*/ |
||||
|
|
||||
|
zcanid_t *canid = (zcanid_t *)&canframe->id; |
||||
|
|
||||
|
uint8_t from = canid->from; |
||||
|
uint8_t to = canid->to; |
||||
|
uint8_t nframe = (canid->frameNumAndFrameId & 0xf0) >> 4; |
||||
|
uint8_t frameId = canid->frameNumAndFrameId & 0x0f; |
||||
|
CanPacketRxBuffer *rxbuf = nullptr; |
||||
|
|
||||
|
// ZLOGI(TAG, "from:%d to:%d frameNum:%d ", canid->from, canid->to, canid->frameNumAndFrameId);
|
||||
|
|
||||
|
rxbuf = findRxBuff(from); |
||||
|
if (!rxbuf) { |
||||
|
ZLOGE(TAG, "board[%d] packetId[%d] find rx buff fail", from, frameId); |
||||
|
return; |
||||
|
} |
||||
|
|
||||
|
if (frameId == 0) { |
||||
|
rxbuf->rxdataSize = 0; |
||||
|
rxbuf->rxPacketNum = 0; |
||||
|
rxbuf->from = from; |
||||
|
rxbuf->to = to; |
||||
|
} |
||||
|
// ZLOGI(TAG, "rx packet %d %d /%d", rxbuf->rxPacketNum, frameId,nframe);
|
||||
|
|
||||
|
if (rxbuf->rxPacketNum != frameId) { |
||||
|
ZLOGE(TAG, "lost subpacket from %d", from); |
||||
|
rxbuf->rxPacketNum = 0; |
||||
|
rxbuf->rxdataSize = 0; |
||||
|
return; |
||||
|
} |
||||
|
|
||||
|
memcpy(rxbuf->rxdata + rxbuf->rxdataSize, canframe->data, canframe->dlc); |
||||
|
rxbuf->rxdataSize += canframe->dlc; |
||||
|
rxbuf->rxPacketNum++; |
||||
|
|
||||
|
if (nframe == frameId + 1) { |
||||
|
processRxPacket(from, to, rxbuf->rxdata, rxbuf->rxdataSize); |
||||
|
} |
||||
|
|
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
void ZScanProtocolCom::sendframe(int32_t from, int32_t to, uint8_t *frame, size_t len) { |
||||
|
if (on_rx_raw) on_rx_raw(kcmd, from, to, (uint8_t *)frame, len); |
||||
|
|
||||
|
uint8_t *packet = (uint8_t *)frame; |
||||
|
|
||||
|
int npacket = len / 8 + (len % 8 == 0 ? 0 : 1); |
||||
|
if (npacket > 255) { |
||||
|
throw zexception(ke_invalid_packet_format, "channel is not open"); |
||||
|
return; |
||||
|
} |
||||
|
int finalpacketlen = len % 8 == 0 ? 8 : len % 8; |
||||
|
|
||||
|
for (uint8_t i = 0; i < npacket; i++) { |
||||
|
if (i == npacket - 1) { |
||||
|
sendsubframe(from, to, npacket, i, packet + i * 8, finalpacketlen); |
||||
|
} else { |
||||
|
sendsubframe(from, to, npacket, i, packet + i * 8, 8); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
void ZScanProtocolCom::sendsubframe(int32_t from, int32_t to, int npacket, int packetIndex, uint8_t *packet, size_t len) { |
||||
|
uint32_t canid; |
||||
|
uint8_t candata[8]; |
||||
|
uint8_t cantxlen; |
||||
|
|
||||
|
zcanid_t *zcanid = (zcanid_t *)&canid; |
||||
|
zcanid->from = from; |
||||
|
zcanid->to = to; |
||||
|
zcanid->frameNumAndFrameId = (npacket << 4) | packetIndex; |
||||
|
|
||||
|
memcpy(candata, packet, len); |
||||
|
cantxlen = len; |
||||
|
|
||||
|
m_channel->sendExtframe(canid, candata, cantxlen); |
||||
|
} |
||||
|
void ZScanProtocolCom::processRxPacket(int32_t from, int32_t to, uint8_t *data, size_t len) { |
||||
|
zcanbus_packet_t *frame = (zcanbus_packet_t *)data; |
||||
|
|
||||
|
if (frame->ptype == kreceipt || frame->ptype == kerror_receipt) { |
||||
|
if (on_rx_raw) on_rx_raw((packet_type_t)frame->ptype, from, to, (uint8_t *)frame, len); |
||||
|
if (frame->index == m_rxReceiptContext.waittingIndex) { |
||||
|
lock_guard<mutex> lock(m_rxReceiptContext_lock); |
||||
|
m_rxReceiptContext.receiptIsReady = true; |
||||
|
m_rxReceiptContext.receiptLen = len; |
||||
|
memcpy(m_rxReceiptContext.receipt, frame, len); |
||||
|
} else { |
||||
|
return; |
||||
|
} |
||||
|
|
||||
|
} else if (frame->ptype == kcmd) { |
||||
|
if (on_rx_raw) on_rx_raw((packet_type_t)frame->ptype, from, to, (uint8_t *)frame, len); |
||||
|
} else if (frame->ptype == kreport) { |
||||
|
if (on_rx_raw) on_rx_raw((packet_type_t)frame->ptype, from, to, (uint8_t *)frame, len); |
||||
|
} else { |
||||
|
ZLOGE(TAG, "unknow packet type %d", frame->ptype); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
CanPacketRxBuffer *ZScanProtocolCom::findRxBuff(int deviceId) { |
||||
|
for (uint32_t i = 0; i < ZARRAY_SIZE(m_rxbuf); i++) { |
||||
|
if (m_rxbuf[i].id == deviceId) { |
||||
|
return &m_rxbuf[i]; |
||||
|
} |
||||
|
|
||||
|
if (m_rxbuf[i].id == 0) { |
||||
|
m_rxbuf[i].id = deviceId; |
||||
|
return &m_rxbuf[i]; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
ZASSERT(0); |
||||
|
return nullptr; |
||||
|
} |
||||
|
|
||||
|
void ZScanProtocolCom::callcmd(int32_t to, int32_t cmdid, uint8_t *param, int32_t paramLen, int32_t overtime) { |
||||
|
m_txindex++; |
||||
|
if (m_txindex < 200) m_txindex = 200; |
||||
|
|
||||
|
zcanbus_packet_t *frame = (zcanbus_packet_t *)m_txbuf; |
||||
|
frame->ptype = kcmd; |
||||
|
frame->index = m_txindex; |
||||
|
frame->function_id = cmdid; |
||||
|
|
||||
|
if (paramLen != 0) memcpy(frame->params, param, paramLen); |
||||
|
|
||||
|
{ |
||||
|
lock_guard<mutex> lock(m_rxReceiptContext_lock); |
||||
|
m_rxReceiptContext.waittingIndex = m_txindex; |
||||
|
m_rxReceiptContext.waittingForReceipt = true; |
||||
|
m_rxReceiptContext.receiptIsReady = false; |
||||
|
m_rxReceiptContext.receiptLen = 0; |
||||
|
} |
||||
|
|
||||
|
sendframe(1, to, (uint8_t *)frame, paramLen + sizeof(zcanbus_packet_t)); |
||||
|
bool rxreceipt = false; |
||||
|
|
||||
|
for (int32_t i = 0; i < overtime; i++) { |
||||
|
{ |
||||
|
lock_guard<mutex> lock(m_rxReceiptContext_lock); |
||||
|
/**
|
||||
|
* @brief 接收到回执 |
||||
|
*/ |
||||
|
if (m_rxReceiptContext.receiptIsReady) { |
||||
|
memcpy(m_receipt_cache, m_rxReceiptContext.receipt, m_rxReceiptContext.receiptLen); |
||||
|
m_receipt_len = m_rxReceiptContext.receiptLen; |
||||
|
rxreceipt = true; |
||||
|
// if (m_on_raw_data_cb) m_on_raw_data_cb(kcmd_receipt, (uint8_t *)rx, *rxlen);
|
||||
|
break; |
||||
|
} |
||||
|
} |
||||
|
this_thread::sleep_for(chrono::milliseconds(1)); |
||||
|
} |
||||
|
|
||||
|
if (!rxreceipt) { |
||||
|
throw zexception(kerr_overtime, "overtime"); |
||||
|
} |
||||
|
|
||||
|
if (m_receipt_frame->ptype == kerror_receipt) { |
||||
|
int32_t ecode = *(int32_t *)m_receipt_frame->params; |
||||
|
throw zexception(ecode, ecode2str(ecode)); |
||||
|
} |
||||
|
return; |
||||
|
} |
||||
|
void ZScanProtocolCom::callcmd0(int32_t to, int32_t cmdid, int32_t overtime) { callcmd(to, cmdid, nullptr, 0, overtime); } |
||||
|
void ZScanProtocolCom::callcmd1(int32_t device_id, int32_t cmdid, int32_t param0, int32_t overtime) { |
||||
|
int32_t param[4]; |
||||
|
param[0] = param0; |
||||
|
callcmd(device_id, cmdid, (uint8_t *)param, 4, overtime); |
||||
|
} |
||||
|
void ZScanProtocolCom::callcmd2(int32_t device_id, int32_t cmdid, int32_t param0, int32_t param1, int32_t overtime) { |
||||
|
int32_t param[4]; |
||||
|
param[0] = param0; |
||||
|
param[1] = param1; |
||||
|
callcmd(device_id, cmdid, (uint8_t *)param, 8, overtime); |
||||
|
} |
||||
|
void ZScanProtocolCom::callcmd3(int32_t device_id, int32_t cmdid, int32_t param0, int32_t param1, int32_t param2, int32_t overtime) { |
||||
|
int32_t param[4]; |
||||
|
param[0] = param0; |
||||
|
param[1] = param1; |
||||
|
param[2] = param2; |
||||
|
callcmd(device_id, cmdid, (uint8_t *)param, 12, overtime); |
||||
|
} |
||||
|
void ZScanProtocolCom::callcmd4(int32_t to, int32_t cmdid, int32_t param0, int32_t param1, int32_t param2, int32_t param3, int32_t overtime) { |
||||
|
int32_t param[4]; |
||||
|
param[0] = param0; |
||||
|
param[1] = param1; |
||||
|
param[2] = param2; |
||||
|
param[3] = param3; |
||||
|
callcmd(to, cmdid, (uint8_t *)param, 16, overtime); |
||||
|
} |
||||
|
|
||||
|
void ZScanProtocolCom::sendraw(int32_t from, int32_t to, uint8_t *data, size_t len) { sendframe(from, to, data, len); } |
||||
|
|
||||
|
string ZScanProtocolCom::ecode2str(int ecode) { |
||||
|
if (m_ecode2str) { |
||||
|
return m_ecode2str(ecode); |
||||
|
} |
||||
|
return "Ecode(" + to_string(ecode) + ")"; |
||||
|
} |
@ -0,0 +1,107 @@ |
|||||
|
#pragma once
|
||||
|
#include <fstream>
|
||||
|
#include <functional>
|
||||
|
#include <iostream>
|
||||
|
#include <list>
|
||||
|
#include <map>
|
||||
|
#include <memory>
|
||||
|
#include <mutex>
|
||||
|
#include <set>
|
||||
|
#include <sstream>
|
||||
|
#include <string>
|
||||
|
#include <thread>
|
||||
|
#include <vector>
|
||||
|
|
||||
|
//
|
||||
|
#include "app_protocols/zscanprotocol/zscanprotocol.hpp"
|
||||
|
#include "protocol/waveshare_can/waveshare_can.hpp"
|
||||
|
#include "zqui/zqui/zqui.hpp"
|
||||
|
|
||||
|
namespace iflytop { |
||||
|
using namespace std; |
||||
|
|
||||
|
typedef function<void(packet_type_t type, uint8_t from, uint8_t to, uint8_t *hex, uint32_t hexlen)> on_raw_data_t; |
||||
|
|
||||
|
typedef function<string(int ecode)> ecode2str_t; |
||||
|
|
||||
|
class RxReceiptContext { |
||||
|
public: |
||||
|
bool waittingForReceipt; |
||||
|
bool receiptIsReady; |
||||
|
uint8_t waittingIndex; |
||||
|
uint8_t receipt[1024]; |
||||
|
size_t receiptLen; |
||||
|
}; |
||||
|
|
||||
|
class CanPacketRxBuffer { |
||||
|
public: |
||||
|
int32_t id = 0; |
||||
|
uint8_t from = 0; |
||||
|
uint8_t to = 0; |
||||
|
|
||||
|
uint8_t rxdata[2048] = {0}; |
||||
|
int rxdataSize = 0; |
||||
|
|
||||
|
int rxPacketNum = 0; |
||||
|
}; |
||||
|
|
||||
|
class ZScanProtocolCom { |
||||
|
ZScanProtocolCom() {} |
||||
|
|
||||
|
WaveshareCan *m_channel = nullptr; |
||||
|
|
||||
|
uint8_t m_rxcache[1024] = {0}; |
||||
|
int32_t m_rxlen = 0; |
||||
|
bool m_rxcache_is_full = false; |
||||
|
|
||||
|
mutex lock_; |
||||
|
|
||||
|
unique_ptr<thread> m_thread; |
||||
|
|
||||
|
RxReceiptContext m_rxReceiptContext; |
||||
|
mutex m_rxReceiptContext_lock; |
||||
|
|
||||
|
/*******************************************************************************
|
||||
|
* TX CONTEXT * |
||||
|
*******************************************************************************/ |
||||
|
mutex m_tx_lock; |
||||
|
uint8_t m_txbuf[1024] = {0}; |
||||
|
int32_t m_rxsize = 0; |
||||
|
uint8_t m_txindex = 0; |
||||
|
|
||||
|
CanPacketRxBuffer m_rxbuf[255]; |
||||
|
|
||||
|
on_raw_data_t on_rx_raw; |
||||
|
|
||||
|
uint8_t m_receipt_cache[1024]; |
||||
|
zcanbus_packet_t *m_receipt_frame = (zcanbus_packet_t *)m_receipt_cache; |
||||
|
size_t m_receipt_len = 0; |
||||
|
|
||||
|
ecode2str_t m_ecode2str; |
||||
|
|
||||
|
public: |
||||
|
void initialize(QTSerialChannel *ch); |
||||
|
void regOnRawData(on_raw_data_t cb) { on_rx_raw = cb; } |
||||
|
void regEcdoe2Str(ecode2str_t cb) { m_ecode2str = cb; } |
||||
|
void updateChannelConfig(); |
||||
|
|
||||
|
void callcmd(int32_t to, int32_t cmdid, uint8_t *param, int32_t paramLen, int32_t overtime = 100); |
||||
|
void callcmd0(int32_t to, int32_t cmdid, int32_t overtime = 100); |
||||
|
void callcmd1(int32_t to, int32_t cmdid, int32_t param0, int32_t overtime = 100); |
||||
|
void callcmd2(int32_t to, int32_t cmdid, int32_t param0, int32_t param1, int32_t overtime = 100); |
||||
|
void callcmd3(int32_t to, int32_t cmdid, int32_t param0, int32_t param1, int32_t param2, int32_t overtime = 100); |
||||
|
void callcmd4(int32_t to, int32_t cmdid, int32_t param0, int32_t param1, int32_t param2, int32_t param3, int32_t overtime = 100); |
||||
|
|
||||
|
void sendraw(int32_t from, int32_t to, uint8_t *data, size_t len); |
||||
|
|
||||
|
private: |
||||
|
void sendframe(int32_t from, int32_t to, uint8_t *frame, size_t len); |
||||
|
void sendsubframe(int32_t from, int32_t to, int npacket, int packetIndex, uint8_t *packet, size_t len); |
||||
|
void processRxPacket(int32_t from, int32_t to, uint8_t *data, size_t len); |
||||
|
|
||||
|
private: |
||||
|
CanPacketRxBuffer *findRxBuff(int deviceId); |
||||
|
string ecode2str(int ecode); |
||||
|
}; |
||||
|
|
||||
|
} // namespace iflytop
|
Write
Preview
Loading…
Cancel
Save
Reference in new issue