Browse Source

v1.0 | 实现tdcan

master
zhaohe 1 month ago
parent
commit
ceaafd7250
  1. 2
      CMakeLists.txt
  2. 6
      resources/iflytoptdcan.service
  3. 2
      resources/install_service.sh
  4. 19
      src/app.cpp
  5. 6
      src/app.hpp
  6. 3
      src/components/linuxsocket/unix_socket.hpp
  7. 38
      src/components/zcanreceiver/tdcan_protocol.hpp
  8. 151
      src/components/zcanreceiver/tdcanreceiverhost.cpp
  9. 21
      src/components/zcanreceiver/tdcanreceiverhost.hpp
  10. 127
      src/components/zcanreceiver/zcanreceiverhost.cpp
  11. 2
      src/configs/version.hpp
  12. 4
      src/main.cpp
  13. 30
      test/config.ini
  14. 2
      tools/build.sh
  15. 14
      tools/deply.sh
  16. 8
      tools/packet.sh

2
CMakeLists.txt

@ -51,7 +51,7 @@ file(GLOB_RECURSE VAR_APP_SOURCE #
message("VAR_APP_SOURCE: ${VAR_APP_SOURCE}")
zadd_executable(
TARGET
iflytopzexcand #
iflytoptdcan #
INSTALL
./app/
#

6
resources/iflytopzexcand.service → resources/iflytoptdcan.service

@ -1,15 +1,15 @@
[Unit]
# 服务名称,可自定义
Description = iflytopzexcand
Description = iflytoptdcan
After = network.target
Wants = network.target
[Service]
Type = simple
ExecStart = /iflytopd/iflytopzexcand/iflytopzexcand
ExecStart = /iflytopd/iflytoptdcan/iflytoptdcan
Restart=always
RestartSec=0
WorkingDirectory=/iflytopd/iflytopzexcand/
WorkingDirectory=/iflytopd/iflytoptdcan/
[Install]
WantedBy = multi-user.target

2
resources/install_service.sh

@ -0,0 +1,2 @@
#/!/bin/bash
cp iflytoptdcan.service /usr/lib/systemd/system/

19
src/app.cpp

@ -14,28 +14,23 @@ void App::initialize() {
string ifname = config["basic"]["ifname"].value_or("can0");
int baudrate = config["basic"]["baudrate"].value_or(500000);
m_zcanreceiverhost.reset(new ZCanReceiverHost());
m_zcanreceiverhost->initialize(ifname, baudrate);
m_tdcanreceiverhost.reset(new TDCanReceiverHost());
m_tdcanreceiverhost->initialize(ifname, baudrate);
} catch (const toml::parse_error& err) {
logger->error("parse config error, {}", err);
exit(1);
}
m_unixsocket.reset(new UnixScoket(UnixScoket::Server, "zexcan"));
m_unixsocket.reset(new UnixScoket(UnixScoket::Server, "tdcan"));
m_unixsocket->start();
m_zcanreceiverhost->registerListener([this](uint8_t fromboardid, uint8_t* packet, size_t packetlen) {
string hexStr = StringUtils().bytesToString((uint8_t*)packet, packetlen);
logger->info("RX_FROM_CAN:<- {}({})", hexStr, hexStr.size());
// Tx to Unix socket
m_tdcanreceiverhost->registerListener([this](uint8_t* packet, size_t packetlen) {
logger->info("tx");
m_unixsocket->sendPacket(packet, packetlen);
});
m_unixsocket->onPacket.connect([this](const uint8_t* packet, size_t packetlen) {
logger->info("RX_FROM_UNIX_SOCKET:-> {}", StringUtils().bytesToString((uint8_t*)packet, packetlen));
// Tx to CAN
m_zcanreceiverhost->sendPacket((uint8_t*)packet, packetlen);
logger->info("rx");
m_tdcanreceiverhost->sendPacket((uint8_t*)packet, packetlen);
});
}

6
src/app.hpp

@ -8,7 +8,7 @@
#include "components/linuxsocket//unix_socket.hpp"
#include "components/thread/thread.hpp"
#include "components/zcanreceiver/zcanreceiverhost.hpp"
#include "components/zcanreceiver/tdcanreceiverhost.hpp"
#include "thirdlib/nod/nod.hpp"
#include "thirdlib/spdlogfactory/logger_factory.hpp"
@ -21,8 +21,8 @@ class App {
ENABLE_LOGGER(App);
private:
unique_ptr<ZCanReceiverHost> m_zcanreceiverhost;
unique_ptr<UnixScoket> m_unixsocket;
unique_ptr<TDCanReceiverHost> m_tdcanreceiverhost;
unique_ptr<UnixScoket> m_unixsocket;
public:
App() {}

3
src/components/linuxsocket/unix_socket.hpp

@ -59,11 +59,10 @@ class UnixScoket {
memset(&tx_addr, 0, sizeof(tx_addr));
tx_addr.sun_family = AF_UNIX;
strncpy(tx_addr.sun_path, m_opposite_path.c_str(), sizeof(tx_addr.sun_path) - 1);
}
void start();
void sendPacket(uint8_t* data, size_t len);
int initRxSocket();
int initRxSocket();
};
} // namespace iflytop

38
src/components/zcanreceiver/tdcan_protocol.hpp

@ -0,0 +1,38 @@
#pragma once
#include <fstream>
#include <functional>
#include <iostream>
#include <list>
#include <map>
#include <memory>
#include <set>
#include <sstream>
#include <string>
#include <vector>
namespace iflytop {
using namespace std;
typedef struct {
struct {
uint8_t fid : 4; // frame ID
uint8_t fnum : 4; // frame number
} frameinfo;
uint8_t to;
uint8_t from;
uint8_t pad;
} tdcan_id_t;
typedef struct {
uint8_t from;
uint8_t to;
uint8_t ptype;
uint8_t index;
uint16_t fnid;
uint8_t params[]; // parameters
} tdcan_frame_t;
} // namespace iflytop

151
src/components/zcanreceiver/tdcanreceiverhost.cpp

@ -0,0 +1,151 @@
#include "tdcanreceiverhost.hpp"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "utils/stringutils.hpp"
using namespace iflytop;
#define TAG "TDCanReceiverHost"
#define OVER_TIME_MS 20
#define ZARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
using namespace iflytop;
TDCanReceiverHost::TDCanReceiverHost() {}
void TDCanReceiverHost::initialize(string can_if_name, int baudrate) {
// m_iflytopCanProtocolStack.reset(new IflytopCanProtocolStack());
m_can_if_name = can_if_name;
m_baudrate = baudrate;
m_enablLoopback = false;
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->onSocketCanFrame.connect([this](shared_ptr<SocketCanFrame> canframe) { //
static_assert(sizeof(tdcan_id_t) == 4, "tdcan_id_t must be 4 bytes");
int32_t canid = canframe->getId();
tdcan_id_t id = *((tdcan_id_t *)(&(canid)));
// id 1 是本机发出去的消息,理论上会被过滤掉不上报
if (id.from == 1) {
logger->info("|-->TX RAW: {} SUC", canframe->toString());
return;
}
processRx(canframe);
});
}
void TDCanReceiverHost::registerListener(onpacket_t onpacket) { m_onpacket = onpacket; }
void TDCanReceiverHost::sendPacket(uint8_t *packet, size_t len) {
tdcan_frame_t *tdcan_frame = (tdcan_frame_t *)packet;
uint8_t *data = &(tdcan_frame->ptype);
int32_t datalen = len - sizeof(tdcan_frame->from) - sizeof(tdcan_frame->to);
int32_t paramlen = len - sizeof(*tdcan_frame);
tdcan_id_t id;
id.from = tdcan_frame->from;
id.to = tdcan_frame->to;
id.frameinfo.fid = 0;
id.frameinfo.fnum = datalen / 8 + (datalen % 8 == 0 ? 0 : 1);
id.pad = 0;
int finalpacketlen = datalen % 8 == 0 ? 8 : datalen % 8;
logger->info("|TX:[index:{},to:{},fnid:{},params:{}({})]", tdcan_frame->index, tdcan_frame->to, tdcan_frame->fnid,
StringUtils().bytesToString(tdcan_frame->params, paramlen), paramlen);
for (uint8_t i = 0; i < id.frameinfo.fnum; i++) {
id.frameinfo.fid = i;
int32_t canid = *((int32_t *)(&id));
if (i == id.frameinfo.fnum - 1) {
sendPacketSub(canid, data + i * 8, finalpacketlen);
} else {
sendPacketSub(canid, data + i * 8, 8);
}
}
logger->info("-");
}
bool TDCanReceiverHost::sendPacketSub(int32_t canid, uint8_t *packet, size_t len) {
shared_ptr<SocketCanFrame> frame = SocketCanFrame::createExtDataFrame(canid, packet, len);
logger->info("|-->TX RAW :{}", frame->toString());
m_socketCan->sendFrame(frame, 0);
return true;
}
void TDCanReceiverHost::processRx(shared_ptr<SocketCanFrame> canframe) {
// uint8_t from = (frame->getId() >> 16 & 0xFF);
// uint8_t nframe = (frame->getId() & 0xFF00) >> 8;
// uint8_t frameId = (frame->getId() & 0x00FF);
/**
* @brief
*
* [2] [3bit] [8bit] [8bit] [8bit]
* , from frameNum frameId
*/
int32_t rawcanid = canframe->getId();
tdcan_id_t *canid = (tdcan_id_t *)&rawcanid;
uint8_t from = canid->from;
uint8_t to = canid->to;
uint8_t nframe = canid->frameinfo.fnum;
uint8_t frameId = canid->frameinfo.fid;
logger->info("|RX [from:{} fram:{}/{}] {}", canid->from, frameId + 1, nframe, canframe->toString());
if (from == 0 || from >= 255) {
logger->error("Invalid from board id: {}", from);
return;
}
static_assert(ZARRAY_SIZE(m_canPacketRxBuffer) >= 255);
CanPacketRxBuffer *rxbuf = &m_canPacketRxBuffer[from];
if (frameId == 0) {
rxbuf->m_canPacketNum = 0;
rxbuf->from = from;
rxbuf->to = to;
rxbuf->m_rxdata[0] = from;
rxbuf->m_rxdata[1] = to;
rxbuf->m_rxdataLen = 2;
}
if (rxbuf->m_canPacketNum != frameId) {
logger->error("|lost subpacket from {}", from);
rxbuf->m_rxdataLen = 0;
rxbuf->m_canPacketNum = 0;
return;
}
memcpy(rxbuf->m_rxdata + rxbuf->m_rxdataLen, canframe->getData(), canframe->getDlc());
rxbuf->m_rxdataLen += canframe->getDlc();
rxbuf->m_canPacketNum++;
if (nframe == frameId + 1) {
tdcan_frame_t *tdcan_frame = (tdcan_frame_t *)rxbuf->m_rxdata;
int32_t paramLen = rxbuf->m_rxdataLen - sizeof(tdcan_frame_t);
logger->info("|-->RX:[index:{},to:{},fnid:{},params:{}({})]", tdcan_frame->index, tdcan_frame->to, tdcan_frame->fnid,
StringUtils().bytesToString(tdcan_frame->params, paramLen), paramLen);
logger->info("-");
if (m_onpacket) {
m_onpacket(rxbuf->m_rxdata, rxbuf->m_rxdataLen);
}
}
}
void TDCanReceiverHost::restartCanInterface() { m_socketCan->reStartCanInterface(); }

21
src/components/zcanreceiver/zcanreceiverhost.hpp → src/components/zcanreceiver/tdcanreceiverhost.hpp

@ -6,6 +6,7 @@
#include <mutex>
#include "socket_can/socket_can.hpp"
#include "tdcan_protocol.hpp"
//
#include "thirdlib/spdlogfactory/logger_factory.hpp"
@ -14,8 +15,8 @@ namespace iflytop {
using namespace std;
using namespace core;
class ZCanReceiverHost {
ENABLE_LOGGER(ZCanReceiverHost);
class TDCanReceiverHost {
ENABLE_LOGGER(TDCanReceiverHost);
public:
class CanPacketRxBuffer {
@ -25,9 +26,11 @@ class ZCanReceiverHost {
uint8_t m_rxdata[255 * 8];
uint8_t m_canPacketNum = 0;
uint8_t m_rxdataLen = 0;
uint8_t to = 0; // 接收数据的目标ID
uint8_t from = 0; // 接收数据的来源ID
};
typedef function<void(uint8_t fromboardid, uint8_t *packet, size_t len)> onpacket_t;
typedef function<void(uint8_t *packet, size_t len)> onpacket_t;
public:
uint8_t m_hostId = 0;
@ -36,22 +39,22 @@ class ZCanReceiverHost {
shared_ptr<SocketCan> m_socketCan;
string m_can_if_name;
int m_baudrate;
bool m_enablLoopback;
string m_can_if_name;
int m_baudrate;
bool m_enablLoopback;
int32_t hostid = -1;
public:
ZCanReceiverHost();
TDCanReceiverHost();
void initialize(string can_if_name, int baudrate);
void sendPacket(uint8_t *packet, size_t len);
void registerListener(onpacket_t onpacket);
void restartCanInterface();
private:
bool sendPacketSub(int npacket, int packetIndex, uint8_t *packet, size_t len, int overtimems);
bool sendPacketSub(int32_t canid, uint8_t *packet, size_t len);
void processRx(shared_ptr<SocketCanFrame> frame);
void processOnePacket(CanPacketRxBuffer *rxbuf, uint8_t *packet, size_t len);
void sendcmd(uint16_t packetindex, uint16_t cmdid, uint8_t subcmdid, uint8_t *data, size_t len);
};

127
src/components/zcanreceiver/zcanreceiverhost.cpp

@ -1,127 +0,0 @@
#include "zcanreceiverhost.hpp"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "utils/stringutils.hpp"
using namespace iflytop;
#define TAG "ZCanReceiver"
#define OVER_TIME_MS 20
using namespace iflytop;
ZCanReceiverHost::ZCanReceiverHost() {}
void ZCanReceiverHost::initialize(string can_if_name, int baudrate) {
// m_iflytopCanProtocolStack.reset(new IflytopCanProtocolStack());
m_can_if_name = can_if_name;
m_baudrate = baudrate;
m_enablLoopback = false;
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->onSocketCanFrame.connect([this](shared_ptr<SocketCanFrame> canframe) { //
if (canframe->getId() == m_hostId) {
logger->info("TX RAW: {} SUC", canframe->toString());
return;
}
logger->info("RX RAW: {}", canframe->toString());
processRx(canframe);
});
}
void ZCanReceiverHost::registerListener(onpacket_t onpacket) { m_onpacket = onpacket; }
void ZCanReceiverHost::sendPacket(uint8_t *packet, size_t len) {
logger->info("TX: {}", StringUtils().bytesToString(packet, len));
int npacket = len / 7 + (len % 7 == 0 ? 0 : 1);
if (npacket > 255) {
return;
}
int finalpacketlen = len % 7 == 0 ? 7 : len % 7;
for (uint8_t i = 0; i < npacket; i++) {
bool suc = false;
if (i == npacket - 1) {
suc = sendPacketSub(npacket, i, packet + i * 7, finalpacketlen, OVER_TIME_MS);
} else {
suc = sendPacketSub(npacket, i, packet + i * 7, 7, OVER_TIME_MS);
}
if (!suc) {
logger->warn("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_hostId;
uint8_t txdata[8] = {0};
txdata[0] = npacket << 4 | packetIndex;
memcpy(txdata + 1, packet, len);
// m_comcan.sendframe(CANUSB_FRAME_EXTENDED, id, packet, len);
// printf("sendPacketSub(%d:%d) ", npacket, packetIndex);
// for (size_t i = 0; i < len; i++) {
// printf("%02x ", packet[i]);
// }
// printf("\n");
shared_ptr<SocketCanFrame> frame = SocketCanFrame::createStdDataFrame(id, txdata, len + 1);
logger->info("TX RAW :{}", frame->toString());
m_socketCan->sendFrame(frame, overtimems);
return true;
}
void ZCanReceiverHost::processOnePacket(CanPacketRxBuffer *rxbuf, uint8_t *packet, size_t len) { //
if (m_onpacket) m_onpacket(rxbuf->id, packet, len);
}
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);
uint8_t from = (frame->getId() & 0xFF);
uint8_t nframe = ((frame->getData()[0] >> 4) & 0x0F);
uint8_t frameId = (frame->getData()[0] & 0x0F);
CanPacketRxBuffer *rxbuf = &m_canPacketRxBuffer[from];
rxbuf->id = from;
if (frameId == 0) {
rxbuf->m_canPacketNum = 0;
rxbuf->m_rxdataLen = 0;
}
if (frameId != rxbuf->m_canPacketNum) {
rxbuf->m_canPacketNum = 0;
rxbuf->m_rxdataLen = 0;
return;
}
if (rxbuf->m_canPacketNum < 255) {
rxbuf->m_canPacket[rxbuf->m_canPacketNum] = frame;
rxbuf->m_canPacketNum++;
memcpy(rxbuf->m_rxdata + rxbuf->m_rxdataLen, frame->getData() + 1, frame->getDlc() - 1);
rxbuf->m_rxdataLen += frame->getDlc() - 1;
}
if (nframe == frameId + 1) {
/**
* @brief
*/
logger->info("RX: {}", StringUtils().bytesToString(rxbuf->m_rxdata, rxbuf->m_rxdataLen));
processOnePacket(rxbuf, rxbuf->m_rxdata, rxbuf->m_rxdataLen);
}
}
void ZCanReceiverHost::restartCanInterface() { m_socketCan->reStartCanInterface(); }

2
src/configs/version.hpp

@ -1,2 +1,2 @@
#pragma once
#define VERSION "1.4"
#define VERSION "1.0"

4
src/main.cpp

@ -35,7 +35,7 @@ int main(int argc, char* argv[]) {
}
// unique_ptr<UnixScoket> server;
// server.reset(new UnixScoket(UnixScoket::Server, "zexcan"));
// server.reset(new UnixScoket(UnixScoket::Server, "tdcan"));
// server->start();
// server->onPacket.connect([mainLogger](uint8_t* data, size_t len) {
// if (len > 0) {
@ -44,7 +44,7 @@ int main(int argc, char* argv[]) {
// });
// unique_ptr<UnixScoket> client;
// client.reset(new UnixScoket(UnixScoket::Client, "zexcan"));
// client.reset(new UnixScoket(UnixScoket::Client, "tdcan"));
// client->start();
// while (true) {

30
test/config.ini

@ -1,30 +0,0 @@
[server]
cmdport=19004
wsport=19005
[[channels]]
type="zexcan"
name="zcan"
ifname="can0"
baudrate=500000
enable=true
[[channels]]
type="uart"
name="printer"
ifname="/dev/ttyS1"
baudrate=115200
enable=true
[[channels]]
type="inputkey"
name="emergency-key"
pinnum="GPIO2-A3"
enable=true
[[channels]]
type="uart"
name="lis"
ifname="/dev/ttyS2"
baudrate=115200
enable=true

2
tools/build.sh

@ -6,4 +6,4 @@ cmake .. \
make -j8
make install
aarch64-linux-gnu-strip ./build/app/iflytopzexcand
aarch64-linux-gnu-strip ./app/iflytoptdcan

14
tools/deply.sh

@ -8,10 +8,10 @@ if [ $# -ne 1 ]; then
fi
server=$1
ssh $server 'mkdir -p /iflytopd/iflytopzexcand/'
ssh $server 'systemctl stop iflytopzexcand'
scp ./build/app/iflytopzexcand $server:/iflytopd/iflytopzexcand/
# scp ./resources/iflytopzexcand.service $server:/lib/systemd/system/
# scp ./resources/config.ini $server:/iflytopd/iflytopzexcand/
scp ./resources/spd_logger_cfg.json $server:/iflytopd/iflytopzexcand/
ssh $server 'systemctl start iflytopzexcand'
ssh $server 'mkdir -p /iflytopd/iflytoptdcan/'
ssh $server 'systemctl stop iflytoptdcan'
scp ./build/app/iflytoptdcan $server:/iflytopd/iflytoptdcan/
# scp ./resources/iflytoptdcan.service $server:/lib/systemd/system/
# scp ./resources/config.ini $server:/iflytopd/iflytoptdcan/
scp ./resources/spd_logger_cfg.json $server:/iflytopd/iflytoptdcan/
ssh $server 'systemctl start iflytoptdcan'

8
tools/packet.sh

@ -10,18 +10,18 @@ if [ $# -ne 1 ]; then
fi
version=$1
packetname=iflytopzexcand
packetname=iflytoptdcan
workdir=$(pwd)
echo "workdir: $workdir"
mkdir -p /tmp/$packetname
aarch64-linux-gnu-strip ./build/app/iflytopzexcand
cp -r ./build/app/iflytopzexcand /tmp/$packetname/
aarch64-linux-gnu-strip ./build/app/iflytoptdcan
cp -r ./build/app/iflytoptdcan /tmp/$packetname/
cp -r ./resources/spd_logger_cfg.json /tmp/$packetname/
cp -r ./resources/*.ini /tmp/$packetname/
cp -r ./resources/iflytopzexcand.service /tmp/$packetname/
cp -r ./resources/iflytoptdcan.service /tmp/$packetname/
echo "Version: $version" > /tmp/$packetname/version

Loading…
Cancel
Save