3 changed files with 295 additions and 0 deletions
-
48src/iflytop/components/zcanreceiver/cmd.hpp
-
163src/iflytop/components/zcanreceiver/zcanreceiverhost.cpp
-
84src/iflytop/components/zcanreceiver/zcanreceiverhost.hpp
@ -0,0 +1,48 @@ |
|||
#pragma once
|
|||
#include <fstream>
|
|||
#include <iostream>
|
|||
#include <list>
|
|||
#include <map>
|
|||
#include <memory>
|
|||
#include <sstream>
|
|||
#include <string>
|
|||
#include <vector>
|
|||
#include <set>
|
|||
#include <functional>
|
|||
namespace iflytop { |
|||
namespace zcr { |
|||
|
|||
typedef struct { |
|||
uint16_t packetindex; |
|||
uint16_t cmdid; |
|||
uint8_t subcmdid; |
|||
uint8_t packetType; |
|||
uint8_t data[]; |
|||
} Cmdheader_t; |
|||
|
|||
typedef enum { |
|||
kpt_cmd = 0, |
|||
kpt_ack = 1, |
|||
kpt_error_ack = 2, |
|||
kpt_status_report = 3, |
|||
} PacketType_t; |
|||
|
|||
typedef enum { |
|||
kcmd_ping = 0, |
|||
kcmd_read_io = 1, |
|||
kcmd_set_io = 2, |
|||
|
|||
kcmd_m211887_operation = 1000, // 维萨拉压力传感器
|
|||
kcmd_read_presure_sensor = 1001, |
|||
kcmd_triple_warning_light_ctl = 1002, |
|||
kcmd_high_power_electrical_ctl = 1003, |
|||
kcmd_peristaltic_pump_ctl = 1004, |
|||
kcmd_read_huacheng_pressure_sensor = 1005, |
|||
} CmdID_t; |
|||
|
|||
} // namespace zcr
|
|||
} // namespace iflytop
|
|||
|
|||
/**
|
|||
* @brief |
|||
*/ |
@ -0,0 +1,163 @@ |
|||
#include "zcanreceiverhost.hpp"
|
|||
|
|||
#include <stdio.h>
|
|||
#include <stdlib.h>
|
|||
#include <string.h>
|
|||
using namespace iflytop; |
|||
|
|||
#define TAG "ZCanReceiver"
|
|||
|
|||
#define OVER_TIME_MS 5
|
|||
|
|||
using namespace iflytop; |
|||
ZCanReceiverHost::ZCanReceiverHost() {} |
|||
|
|||
void ZCanReceiverHost::initialize(string can_if_name, int baudrate, bool enablLoopback) { |
|||
// m_iflytopCanProtocolStack.reset(new IflytopCanProtocolStack());
|
|||
m_can_if_name = can_if_name; |
|||
m_baudrate = baudrate; |
|||
m_enablLoopback = enablLoopback; |
|||
resetSocketCan(); |
|||
} |
|||
void ZCanReceiverHost::registerListener(onpacket_t onpacket) { m_onpacket = onpacket; } |
|||
|
|||
shared_ptr<ZCanReceiverCMD> ZCanReceiverHost::sendcmdblock(shared_ptr<ZCanReceiverCMD> cmd, int overtime_ms) { //
|
|||
lock_guard<mutex> lock(m_txblocklock); |
|||
|
|||
{ |
|||
lock_guard<mutex> lock(m_txContextLock); |
|||
m_txContext.txcmdcache = cmd; |
|||
m_txContext.isReady = false; |
|||
} |
|||
|
|||
auto enter = zsteady_clock().now(); |
|||
sendcmd(cmd->packetindex, cmd->cmdid, cmd->subcmdid, cmd->data, cmd->len); |
|||
|
|||
while (true) { |
|||
if (m_txContext.isReady) { |
|||
break; |
|||
} |
|||
if (zsteady_clock().elapsedTimeMs(enter) > overtime_ms) { |
|||
break; |
|||
} |
|||
this_thread::sleep_for(chrono::milliseconds(1)); |
|||
} |
|||
|
|||
if (!m_txContext.isReady) { |
|||
logger->warn("sendcmdblock(index{},cmd{},subcmd{}) fail,timeout", cmd->packetindex, cmd->cmdid, cmd->subcmdid); |
|||
return nullptr; |
|||
} |
|||
return m_txContext.rx; |
|||
} |
|||
|
|||
void ZCanReceiverHost::sendcmd(uint16_t packetindex, uint16_t cmdid, uint8_t subcmdid, uint8_t *data, size_t len) { |
|||
Cmdheader_t *header = (Cmdheader_t *)m_sendbuf; |
|||
header->packetindex = packetindex; |
|||
header->cmdid = cmdid; |
|||
header->subcmdid = subcmdid; |
|||
header->packetType = 0x00; |
|||
memcpy(header->data, data, len); |
|||
sendPacket(m_sendbuf, sizeof(Cmdheader_t) + len); |
|||
} |
|||
void ZCanReceiverHost::sendPacket(uint8_t *packet, size_t len) { |
|||
/**
|
|||
* @brief |
|||
*/ |
|||
int npacket = len / 8 + (len % 8 == 0 ? 0 : 1); |
|||
if (npacket > 255) { |
|||
return; |
|||
} |
|||
int finalpacketlen = len % 8 == 0 ? 8 : len % 8; |
|||
for (uint8_t i = 0; i < npacket; i++) { |
|||
bool suc = false; |
|||
if (i == npacket - 1) { |
|||
suc = sendPacketSub(npacket, i, packet + i * 8, finalpacketlen, OVER_TIME_MS); |
|||
} else { |
|||
suc = sendPacketSub(npacket, i, packet + i * 8, 8, OVER_TIME_MS); |
|||
} |
|||
if (!suc) { |
|||
printf("sendPacket fail, packet(%d:%d)\n", npacket, i); |
|||
return; |
|||
} |
|||
} |
|||
} |
|||
|
|||
bool ZCanReceiverHost::sendPacketSub(int npacket, int packetIndex, uint8_t *packet, size_t len, int overtimems) { |
|||
uint32_t id = (m_deviceId << 16) | (npacket << 8) | packetIndex; |
|||
// m_comcan.sendframe(CANUSB_FRAME_EXTENDED, id, packet, len);
|
|||
shared_ptr<SocketCanFrame> frame = SocketCanFrame::createExtDataFrame(id, packet, len); |
|||
m_socketCan->sendFrame(frame, overtimems); |
|||
return true; |
|||
} |
|||
|
|||
void ZCanReceiverHost::processOnePacket(CanPacketRxBuffer *rxbuf, uint8_t *packet, size_t len) { //
|
|||
|
|||
Cmdheader_t *header = (Cmdheader_t *)packet; |
|||
// uint8_t from = rxbuf->id;
|
|||
|
|||
shared_ptr<ZCanReceiverCMD> rx = make_shared<ZCanReceiverCMD>(); |
|||
rx->packetindex = header->packetindex; |
|||
rx->cmdid = header->cmdid; |
|||
rx->subcmdid = header->subcmdid; |
|||
rx->len = len - sizeof(Cmdheader_t); |
|||
memcpy(rx->data, header->data, rx->len); |
|||
|
|||
/**
|
|||
* @brief 匹配下发的命令 |
|||
*/ |
|||
if (header->packetType == kpt_ack || header->packetType == kpt_error_ack) { |
|||
if (header->packetindex == m_txContext.txcmdcache->packetindex) { |
|||
lock_guard<mutex> lock(m_txContextLock); |
|||
m_txContext.rx = rx; |
|||
m_txContext.isReady = true; |
|||
} |
|||
return; |
|||
} |
|||
/**
|
|||
* @brief 处理其他类型的消息 |
|||
*/ |
|||
} |
|||
|
|||
void ZCanReceiverHost::processRx(shared_ptr<SocketCanFrame> frame) { |
|||
uint8_t from = (frame->getId() >> 16 & 0xFF); |
|||
uint8_t nframe = (frame->getId() & 0xFF00) >> 8; |
|||
uint8_t frameId = (frame->getId() & 0x00FF); |
|||
|
|||
CanPacketRxBuffer *rxbuf = &m_canPacketRxBuffer[from]; |
|||
rxbuf->id = from; |
|||
|
|||
if (frameId == 0) { |
|||
rxbuf->m_canPacketNum = 0; |
|||
rxbuf->m_rxdataLen = 0; |
|||
} |
|||
|
|||
if (rxbuf->m_canPacketNum < 255) { |
|||
rxbuf->m_canPacket[rxbuf->m_canPacketNum] = frame; |
|||
rxbuf->m_canPacketNum++; |
|||
memcpy(rxbuf->m_rxdata + rxbuf->m_rxdataLen, frame->getData(), frame->getDlc()); |
|||
rxbuf->m_rxdataLen += frame->getDlc(); |
|||
} |
|||
if (nframe == frameId + 1) { |
|||
/**
|
|||
* @brief 接收到最后一包数据 |
|||
*/ |
|||
processOnePacket(rxbuf, rxbuf->m_rxdata, rxbuf->m_rxdataLen); |
|||
} |
|||
} |
|||
|
|||
void ZCanReceiverHost::resetSocketCan() { |
|||
auto socketCanConfig = make_shared<SocketCanConfig>(); |
|||
socketCanConfig->enablLoopback = m_enablLoopback; // 根据 SocketCan::dumpCanDriverInfo() 的输出,确定该标志位是false还是true
|
|||
socketCanConfig->m_canName = m_can_if_name; |
|||
socketCanConfig->m_canBaudrate = m_baudrate; |
|||
socketCanConfig->m_canfilters = {}; |
|||
|
|||
logger->info("initialize() m_canName:{} {}", socketCanConfig->m_canName, socketCanConfig->m_canBaudrate); |
|||
|
|||
m_socketCan.reset(new SocketCan()); |
|||
m_socketCan->initialize(socketCanConfig); |
|||
m_socketCan->startListen(); |
|||
m_socketCan->onSocketCanFrame.connect([this](shared_ptr<SocketCanFrame> canframe) { //
|
|||
// processRx(canframe);
|
|||
}); |
|||
} |
@ -0,0 +1,84 @@ |
|||
//
|
|||
// Created by zwsd
|
|||
//
|
|||
|
|||
#pragma once
|
|||
#include <mutex>
|
|||
|
|||
#include "cmd.hpp"
|
|||
#include "iflytop/core/basic/nlohmann/json.hpp"
|
|||
#include "iflytop/core/core.hpp"
|
|||
#include "iflytop/core/driver/socketcan/socket_can.hpp"
|
|||
#include "iflytop/core/spdlogfactory/logger.hpp"
|
|||
#include "zservice_container/zservice_container.hpp"
|
|||
|
|||
namespace iflytop { |
|||
|
|||
using namespace std; |
|||
using namespace zcr; |
|||
|
|||
class ZCanReceiverCMD { |
|||
public: |
|||
uint16_t packetindex; |
|||
uint16_t cmdid; |
|||
uint8_t subcmdid; |
|||
uint8_t data[255 * 8]; |
|||
size_t len; |
|||
}; |
|||
|
|||
class ZCanReceiverHost { |
|||
ENABLE_LOGGER(ZCanReceiverHost); |
|||
|
|||
public: |
|||
class CanPacketRxBuffer { |
|||
public: |
|||
uint16_t id; |
|||
shared_ptr<SocketCanFrame> m_canPacket[256]; // 用于接收can消息
|
|||
uint8_t m_rxdata[255 * 8]; |
|||
uint8_t m_canPacketNum = 0; |
|||
uint8_t m_rxdataLen = 0; |
|||
}; |
|||
|
|||
class TxContext { |
|||
public: |
|||
shared_ptr<ZCanReceiverCMD> txcmdcache; |
|||
shared_ptr<ZCanReceiverCMD> rx; |
|||
bool isReady; |
|||
}; |
|||
|
|||
typedef function<void(CanPacketRxBuffer *rxbuf, uint8_t *packet, size_t len)> onpacket_t; |
|||
|
|||
public: |
|||
uint8_t m_sendbuf[1000]; |
|||
CanPacketRxBuffer m_canPacketRxBuffer[255]; |
|||
onpacket_t m_onpacket; |
|||
uint8_t m_deviceId = 1; |
|||
|
|||
shared_ptr<SocketCan> m_socketCan; |
|||
|
|||
mutex m_txblocklock; |
|||
mutex m_txContextLock; |
|||
TxContext m_txContext; |
|||
|
|||
string m_can_if_name; |
|||
int m_baudrate; |
|||
bool m_enablLoopback; |
|||
|
|||
public: |
|||
ZCanReceiverHost(); |
|||
|
|||
void initialize(string can_if_name, int baudrate, bool enablLoopback); |
|||
void registerListener(onpacket_t onpacket); |
|||
|
|||
shared_ptr<ZCanReceiverCMD> sendcmdblock(shared_ptr<ZCanReceiverCMD> cmd, int overtime_ms); |
|||
|
|||
private: |
|||
void processRx(shared_ptr<SocketCanFrame> frame); |
|||
void processOnePacket(CanPacketRxBuffer *rxbuf, uint8_t *packet, size_t len); |
|||
void resetSocketCan(); |
|||
void sendcmd(uint16_t packetindex, uint16_t cmdid, uint8_t subcmdid, uint8_t *data, size_t len); |
|||
void sendPacket(uint8_t *packet, size_t len); |
|||
bool sendPacketSub(int npacket, int packetIndex, uint8_t *packet, size_t len, int overtimems); |
|||
}; |
|||
|
|||
} // namespace iflytop
|
Write
Preview
Loading…
Cancel
Save
Reference in new issue