11 changed files with 1194 additions and 1037 deletions
-
2a8000_protocol
-
893src/components/zcanreceiver/socket_can/socket_can.cpp
-
347src/components/zcanreceiver/socket_can/socket_can.hpp
-
158src/components/zcanreceiver/socket_can/socket_can_frame.cpp
-
128src/components/zcanreceiver/socket_can/socket_can_frame.hpp
-
224src/components/zcanreceiver/zcanreceiverhost.cpp
-
121src/components/zcanreceiver/zcanreceiverhost.hpp
-
62src/extapi_service.cpp
-
3src/extapi_service.hpp
-
215src/utils/stringutils.cpp
-
78test_src/testsqldb.cpp
@ -1 +1 @@ |
|||
Subproject commit 35b8b7a4c579bbfae432bc2c789c8564b16aa958 |
|||
Subproject commit e17619d6204aa72069968f4763ba5d2238bb645e |
@ -1,445 +1,448 @@ |
|||
// #include "socket_can.hpp"
|
|||
|
|||
// #include <linux/can/error.h>
|
|||
|
|||
// #include "iflytop/core/components/stringutils.hpp"
|
|||
// using namespace iflytop;
|
|||
// #define DO(exptr) \ |
|||
// do { \ |
|||
// if ((exptr) != 0) { \ |
|||
// logger->error("do {} failed,{}", #exptr, strerror(errno)); \ |
|||
// goto error; \ |
|||
// } \ |
|||
// } while (0)
|
|||
|
|||
// SocketCan::SocketCanError_t SocketCan::sendFrame(shared_ptr<SocketCanFrame> frame) {
|
|||
// if (!m_canBusIsReady) {
|
|||
// return kDeviceBusy;
|
|||
// }
|
|||
|
|||
// if (frame == nullptr) {
|
|||
// logger->error("frame is null");
|
|||
// return kParamError;
|
|||
// }
|
|||
|
|||
// if (isTxing()) {
|
|||
// logger->error("txing, can't send frame");
|
|||
// return kDeviceBusy;
|
|||
// }
|
|||
|
|||
// canfd_frame_t canframe = frame->getCanFrame();
|
|||
// return writeFrame(canframe);
|
|||
// }
|
|||
// SocketCan::SocketCanError_t SocketCan::writeFrame(const canfd_frame_t &_frame) {
|
|||
// if (!m_canBusIsReady) {
|
|||
// return kDeviceBusy;
|
|||
// }
|
|||
|
|||
// canfd_frame_t txframe = _frame;
|
|||
// txframe.can_id |= 0x10000000;
|
|||
// setTxStateToTxing(txframe);
|
|||
|
|||
// int ret = write(m_socketCanFd, &txframe, 16);
|
|||
// if (ret != (16)) {
|
|||
// logger->error("write fail,{}", strerror(errno));
|
|||
// unsetTxStateToTxing();
|
|||
// return kWriteError;
|
|||
// }
|
|||
// return kSuccess;
|
|||
// }
|
|||
|
|||
// SocketCan::SocketCanError_t SocketCan::sendFrame(shared_ptr<SocketCanFrame> frame, int overtime) {
|
|||
// tp_steady start = tu_steady().now();
|
|||
|
|||
// while (tu_steady().elapsedTimeMs(start) < overtime && !m_canBusIsReady) {
|
|||
// usleep(100);
|
|||
// }
|
|||
|
|||
// if (!m_canBusIsReady) {
|
|||
// return kOvertime;
|
|||
// }
|
|||
|
|||
// while (tu_steady().elapsedTimeMs(start) < overtime && isTxing()) {
|
|||
// usleep(100);
|
|||
// }
|
|||
|
|||
// if (isTxing()) {
|
|||
// logger->error("send frame overtime");
|
|||
// return kOvertime;
|
|||
// }
|
|||
// return sendFrame(frame);
|
|||
// }
|
|||
|
|||
// bool SocketCan::isTxing() { return m_txState.txState == kTxing; }
|
|||
|
|||
// bool SocketCan::isTxFrame(const canfd_frame_t &frame) {
|
|||
// lock_guard<recursive_mutex> lock(m_txState.lock);
|
|||
// if (m_txState.txbuf.can_id == frame.can_id && m_txState.txbuf.len == frame.len && memcmp(m_txState.txbuf.data, frame.data, frame.len) == 0) {
|
|||
// return true;
|
|||
// }
|
|||
// return false;
|
|||
// }
|
|||
|
|||
// void SocketCan::initialize(shared_ptr<SocketCanConfig> socketCanConfig) { //
|
|||
// ZCHECK(socketCanConfig, "socketCanConfig is null");
|
|||
// m_socketCanConfig = socketCanConfig;
|
|||
|
|||
// socketcanInitialize();
|
|||
// }
|
|||
// SocketCan::~SocketCan() {
|
|||
// if (m_thread) {
|
|||
// endListenThread();
|
|||
// }
|
|||
// if (m_socketCanFd > 0) {
|
|||
// close(m_socketCanFd);
|
|||
// m_socketCanFd = -1;
|
|||
// }
|
|||
// }
|
|||
|
|||
// void SocketCan::startListen() { startListenThread(); }
|
|||
|
|||
// void SocketCan::socketcanReInitialize() {}
|
|||
|
|||
// void SocketCan::startListenThread() {
|
|||
// if (m_thread) {
|
|||
// endListenThread();
|
|||
// return;
|
|||
// }
|
|||
// logger->info("startListenThread");
|
|||
|
|||
// m_thread.reset(new Thread("SocketCanThread", [this]() {
|
|||
// /**
|
|||
// * @brief call socketCanReadThreadLoop
|
|||
// */
|
|||
// socketCanReadThreadLoop();
|
|||
// }));
|
|||
// m_canBusIsReady = true;
|
|||
|
|||
// m_autoRestartThread.reset(new Thread("SocketCanAutoRestartThread", [this]() { monitorLoop(); }));
|
|||
// }
|
|||
// void SocketCan::endListenThread() {
|
|||
// logger->info("endListenThread");
|
|||
// if (m_thread) {
|
|||
// m_thread->join();
|
|||
// m_thread = nullptr;
|
|||
// }
|
|||
// }
|
|||
|
|||
// void SocketCan::socketcanInitialize() {
|
|||
// // setCanBitrate(canName, bitrate);
|
|||
|
|||
// struct ifreq ifr = {0};
|
|||
// struct sockaddr_can addr = {0};
|
|||
// can_filter_t zerofilter = {0};
|
|||
// int recv_own_msgs = 0; /* 0 = disabled (default), 1 = enabled */
|
|||
// int localloop = 0;
|
|||
// vector<can_filter_t> filters = m_socketCanConfig->m_canfilters;
|
|||
// can_err_mask_t err_mask = 0;
|
|||
|
|||
// if (!findCan(m_socketCanConfig->m_canName)) {
|
|||
// logger->error("can:{} not found", m_socketCanConfig->m_canName);
|
|||
// return;
|
|||
// }
|
|||
|
|||
// if (m_thread) endListenThread();
|
|||
// if (m_socketCanFd > 0) socketcanDeInitialize();
|
|||
|
|||
// logger->info("socketcanInitialize,canName:{},canBaudrate:{}", m_socketCanConfig->m_canName, m_socketCanConfig->m_canBaudrate);
|
|||
|
|||
// // 配置socketCan波特率,注意该方法必须放在socket之前
|
|||
// setCanBitrate(m_socketCanConfig->m_canName, m_socketCanConfig->m_canBaudrate);
|
|||
|
|||
// // SOCKET
|
|||
// m_socketCanFd = socket(PF_CAN, SOCK_RAW, CAN_RAW);
|
|||
// if (m_socketCanFd < 0) {
|
|||
// logger->error("socket failed,{}", strerror(errno));
|
|||
// goto error;
|
|||
// }
|
|||
|
|||
// // 设置依靠名字绑定CAN设备
|
|||
// strcpy(ifr.ifr_name, m_socketCanConfig->m_canName.c_str());
|
|||
// DO(ioctl(m_socketCanFd, SIOCGIFINDEX, &ifr));
|
|||
|
|||
// // BIND
|
|||
// addr.can_family = AF_CAN;
|
|||
// addr.can_ifindex = ifr.ifr_ifindex;
|
|||
// DO(bind(m_socketCanFd, (struct sockaddr *)&addr, sizeof(addr)));
|
|||
|
|||
// // 设置过滤器,默认不过滤
|
|||
// DO(setsockopt(m_socketCanFd, SOL_CAN_RAW, CAN_RAW_FILTER, &zerofilter, sizeof(zerofilter)));
|
|||
|
|||
// if (m_socketCanConfig->enablLoopback) {
|
|||
// localloop = 1; /* 0 = disabled (default), 1 = enabled */
|
|||
// DO(setsockopt(m_socketCanFd, SOL_CAN_RAW, CAN_RAW_LOOPBACK, &localloop, sizeof(localloop)));
|
|||
|
|||
// recv_own_msgs = 1; /* 0 = disabled (default), 1 = enabled */
|
|||
// DO(setsockopt(m_socketCanFd, SOL_CAN_RAW, CAN_RAW_RECV_OWN_MSGS, &recv_own_msgs, sizeof(recv_own_msgs)));
|
|||
// } else {
|
|||
// localloop = 0; /* 0 = disabled (default), 1 = enabled */
|
|||
// DO(setsockopt(m_socketCanFd, SOL_CAN_RAW, CAN_RAW_LOOPBACK, &localloop, sizeof(localloop)));
|
|||
|
|||
// recv_own_msgs = 0; /* 0 = disabled (default), 1 = enabled */
|
|||
// DO(setsockopt(m_socketCanFd, SOL_CAN_RAW, CAN_RAW_RECV_OWN_MSGS, &recv_own_msgs, sizeof(recv_own_msgs)));
|
|||
// }
|
|||
|
|||
// err_mask = CAN_ERR_TX_TIMEOUT | //
|
|||
// CAN_ERR_LOSTARB | //
|
|||
// CAN_ERR_CRTL | //
|
|||
// CAN_ERR_PROT | //
|
|||
// CAN_ERR_TRX | //
|
|||
// CAN_ERR_ACK | //
|
|||
// CAN_ERR_BUSOFF | //
|
|||
// CAN_ERR_BUSERROR | //
|
|||
// CAN_ERR_RESTARTED;
|
|||
|
|||
// setsockopt(m_socketCanFd, SOL_CAN_RAW, CAN_RAW_ERR_FILTER, &err_mask, sizeof(err_mask));
|
|||
// logger->info("socketcan init success");
|
|||
|
|||
// return;
|
|||
// error:
|
|||
// logger->error("socketcan init failed");
|
|||
// if (m_socketCanFd > 0) {
|
|||
// close(m_socketCanFd);
|
|||
// m_socketCanFd = -1;
|
|||
// }
|
|||
// return;
|
|||
// }
|
|||
// void SocketCan::socketcanDeInitialize() {}
|
|||
|
|||
// void SocketCan::canReadThread() {}
|
|||
|
|||
// void SocketCan::setCanBitrate(string canName, int bitrate) {
|
|||
// logger->info("set can:{} bitrate:{}", canName, bitrate);
|
|||
// dosystem(fmt::format("ip link set {} down", canName));
|
|||
// dosystem(fmt::format("ip link set {} type can bitrate {}", canName, bitrate));
|
|||
// dosystem(fmt::format("ip link set {} up", canName));
|
|||
// }
|
|||
// bool SocketCan::findCan(string canName) { return access(fmt::format("/sys/class/net/{}", canName).c_str(), F_OK) == 0; }
|
|||
|
|||
// void SocketCan::dosystem(string cmd) {
|
|||
// logger->info("do cmd:{}", cmd);
|
|||
// system(cmd.c_str());
|
|||
// }
|
|||
// bool SocketCan::tryUpdateTxState(canfd_frame_t &rxloopmsg) {
|
|||
// lock_guard<recursive_mutex> lock(m_txState.lock);
|
|||
// if (m_txState.txState == kTxing && isTxFrame(rxloopmsg)) {
|
|||
// unsetTxStateToTxing();
|
|||
// return true;
|
|||
// }
|
|||
// return false;
|
|||
// }
|
|||
|
|||
// void SocketCan::setTxStateToTxing(const canfd_frame_t &txpacket) {
|
|||
// lock_guard<recursive_mutex> lock(m_txState.lock);
|
|||
// m_txState.txState = kTxing;
|
|||
// m_txState.txbuf = txpacket;
|
|||
// }
|
|||
// void SocketCan::unsetTxStateToTxing() {
|
|||
// lock_guard<recursive_mutex> lock(m_txState.lock);
|
|||
// m_txState.txState = kTxIdle;
|
|||
// }
|
|||
|
|||
// #define TEST_CANDRIVER_DO(exptr) \ |
|||
// do { \ |
|||
// if ((exptr) != 0) { \ |
|||
// logger->error("do {} failed,{}", #exptr, strerror(errno)); \ |
|||
// if (socketId > 0) { \ |
|||
// close(socketId); \ |
|||
// socketId = -1; \ |
|||
// return -1; \ |
|||
// } \ |
|||
// } \ |
|||
// } while (0)
|
|||
|
|||
// int SocketCan::dumpCanDriverInfo(string canDevice, int baudrate) {
|
|||
// int socketId = -1;
|
|||
// struct ifreq ifr = {0};
|
|||
// struct sockaddr_can addr = {0};
|
|||
// can_filter_t zerofilter = {0};
|
|||
// int recv_own_msgs = 0; /* 0 = disabled (default), 1 = enabled */
|
|||
// int localloop = 0;
|
|||
// int ret = 0;
|
|||
// fd_set readfds, readFileDescriptors;
|
|||
// timeval waitTime;
|
|||
// int loopTime = 0;
|
|||
// logger_t logger = GET_LOGGER(SocketCan);
|
|||
|
|||
// if (!findCan(canDevice)) {
|
|||
// logger->error("can:{} not found", canDevice);
|
|||
// return -1;
|
|||
// }
|
|||
|
|||
// // set bitrate
|
|||
// system(fmt::format("ip link set {} down", canDevice).c_str());
|
|||
// system(fmt::format("ip link set {} type can bitrate {}", canDevice, baudrate).c_str());
|
|||
// system(fmt::format("ip link set {} up", canDevice).c_str());
|
|||
|
|||
// socketId = socket(PF_CAN, SOCK_RAW, CAN_RAW);
|
|||
// if (socketId < 0) {
|
|||
// logger->error("socket failed,{}", strerror(errno));
|
|||
// return -1;
|
|||
// }
|
|||
|
|||
// // 设置依靠名字绑定CAN设备
|
|||
// strcpy(ifr.ifr_name, canDevice.c_str());
|
|||
// TEST_CANDRIVER_DO(ioctl(socketId, SIOCGIFINDEX, &ifr));
|
|||
|
|||
// // BIND
|
|||
// addr.can_family = AF_CAN;
|
|||
// addr.can_ifindex = ifr.ifr_ifindex;
|
|||
// TEST_CANDRIVER_DO(bind(socketId, (struct sockaddr *)&addr, sizeof(addr)));
|
|||
|
|||
// // 设置过滤器
|
|||
// TEST_CANDRIVER_DO(setsockopt(socketId, SOL_CAN_RAW, CAN_RAW_FILTER, &zerofilter, sizeof(zerofilter)));
|
|||
|
|||
// // 打开回环
|
|||
// localloop = 1; /* 0 = disabled (default), 1 = enabled */
|
|||
// TEST_CANDRIVER_DO(setsockopt(socketId, SOL_CAN_RAW, CAN_RAW_LOOPBACK, &localloop, sizeof(localloop)));
|
|||
|
|||
// recv_own_msgs = 1; /* 0 = disabled (default), 1 = enabled */
|
|||
// TEST_CANDRIVER_DO(setsockopt(socketId, SOL_CAN_RAW, CAN_RAW_RECV_OWN_MSGS, &recv_own_msgs, sizeof(recv_own_msgs)));
|
|||
|
|||
// // 发送一条消息
|
|||
// canfd_frame_t txframe = {0};
|
|||
// canfd_frame_t rxcanframe = {0};
|
|||
|
|||
// int rxloopcount = 0;
|
|||
// txframe.can_id = 0x12;
|
|||
// txframe.len = 8;
|
|||
// txframe.data[0] = 0x01;
|
|||
|
|||
// logger->info("write one frame");
|
|||
// ret = write(socketId, &txframe, txframe.len + 8);
|
|||
// if (ret < 0) {
|
|||
// logger->error("write failed,{}", strerror(errno));
|
|||
// close(socketId);
|
|||
// return -1;
|
|||
// }
|
|||
|
|||
// FD_ZERO(&readFileDescriptors);
|
|||
// FD_SET(socketId, &readFileDescriptors);
|
|||
// while (loopTime < 10) {
|
|||
// loopTime++;
|
|||
// waitTime.tv_sec = 0;
|
|||
// waitTime.tv_usec = 100000; // 100ms
|
|||
// readfds = readFileDescriptors;
|
|||
|
|||
// int n = select(socketId + 1, &readfds, 0, 0, &waitTime);
|
|||
// if (n <= 0) continue;
|
|||
|
|||
// int readsize = read(socketId, &rxcanframe, sizeof(rxcanframe));
|
|||
// if (readsize < 0) {
|
|||
// logger->error("read failed,{}", strerror(errno));
|
|||
// close(socketId);
|
|||
// return -1;
|
|||
// }
|
|||
|
|||
// if (rxcanframe.can_id == txframe.can_id && //
|
|||
// rxcanframe.data[0] == txframe.data[0] && //
|
|||
// rxcanframe.len == txframe.len) {
|
|||
// rxloopcount++;
|
|||
// logger->info("rx loop frame {}", rxloopcount);
|
|||
// }
|
|||
// }
|
|||
|
|||
// logger->info("Test Can Driver OK!");
|
|||
// logger->info("=================Can Driver Info =================");
|
|||
// logger->info("canDevice :{}", canDevice);
|
|||
// logger->info("baudrate :{}", baudrate);
|
|||
// logger->info("loop count :{}", rxloopcount);
|
|||
// logger->info("shouldEnableLoop:{}", rxloopcount == 1);
|
|||
// logger->info("==================================================");
|
|||
|
|||
// close(socketId);
|
|||
|
|||
// return 0;
|
|||
// }
|
|||
|
|||
// void SocketCan::socketCanReadThreadLoop() {
|
|||
// ThisThread thisThread;
|
|||
|
|||
// fd_set readfds, readFileDescriptors;
|
|||
// FD_ZERO(&readFileDescriptors);
|
|||
// FD_SET(m_socketCanFd, &readFileDescriptors);
|
|||
|
|||
// while (!thisThread.getExitFlag()) {
|
|||
// canfd_frame_t canframe;
|
|||
|
|||
// timeval waitTime;
|
|||
// waitTime.tv_sec = 0;
|
|||
// waitTime.tv_usec = 100000; // 100ms
|
|||
|
|||
// readfds = readFileDescriptors;
|
|||
|
|||
// int n = select(m_socketCanFd + 1, &readfds, 0, 0, &waitTime);
|
|||
// if (n <= 0) continue;
|
|||
|
|||
// memset(&canframe, 0x00, sizeof(canframe));
|
|||
// int ret = read(m_socketCanFd, &canframe, sizeof(canframe));
|
|||
// if (ret < 0) {
|
|||
// logger->error("read failed,{}", strerror(errno));
|
|||
// continue;
|
|||
// }
|
|||
|
|||
// if (canframe.can_id & CAN_ERR_FLAG) {
|
|||
// // /usr/include/linux/can/error.h
|
|||
// // x can-bus error event 20000004,0004000000000086
|
|||
// logger->error("rx can-bus error event {:x},{}", canframe.can_id, StringUtils().bytesToString(canframe.data, canframe.len));
|
|||
|
|||
// unsetTxStateToTxing();
|
|||
// // exit(-1);
|
|||
// break;
|
|||
// } else {
|
|||
// // logger->info("TX:{} {} {}", canframe.can_id, canframe.__res0, canframe.__res1);
|
|||
// if (!tryUpdateTxState(canframe)) {
|
|||
// shared_ptr<SocketCanFrame> socketCanFrame = SocketCanFrame::createFrame(canframe);
|
|||
// logger->debug("RX:{}", socketCanFrame->toString());
|
|||
// onSocketCanFrame(socketCanFrame);
|
|||
// }
|
|||
// }
|
|||
// }
|
|||
|
|||
// m_canTriggerError = true;
|
|||
// m_canBusIsReady = false;
|
|||
// }
|
|||
|
|||
// void SocketCan::monitorLoop() {
|
|||
// ThisThread thisThread;
|
|||
// while (!thisThread.getExitFlag()) {
|
|||
// if (m_canTriggerError) {
|
|||
// // 尝试恢复CAN总线
|
|||
// logger->warn("try to recover can bus............................................");
|
|||
// if (m_thread) {
|
|||
// m_thread->join();
|
|||
// m_thread = nullptr;
|
|||
// }
|
|||
// logger->warn("close can bus fd:{}", m_socketCanFd);
|
|||
|
|||
// close(m_socketCanFd);
|
|||
// m_socketCanFd = -1;
|
|||
|
|||
// {
|
|||
// lock_guard<recursive_mutex> lock(m_txState.lock);
|
|||
// memset(&m_txState.txbuf, 0x00, sizeof(m_txState.txbuf));
|
|||
// m_txState.txState = TxState_t::kTxIdle;
|
|||
// m_txState.txAckCount = 0;
|
|||
// m_txState.txLoopMessageRxTicket = zsteady_clock().now();
|
|||
// }
|
|||
|
|||
// logger->warn("re init can bus");
|
|||
// socketcanInitialize();
|
|||
|
|||
// m_thread.reset(new Thread("SocketCanThread", [this]() {
|
|||
// usleep(10 * 1000);
|
|||
// socketCanReadThreadLoop();
|
|||
// }));
|
|||
|
|||
// m_canTriggerError = false;
|
|||
// m_canBusIsReady = true;
|
|||
|
|||
// logger->warn("recover can bus ok............................................");
|
|||
// }
|
|||
|
|||
// thisThread.sleepForMs(30);
|
|||
// }
|
|||
// }
|
|||
#include "socket_can.hpp"
|
|||
|
|||
#include <linux/can/error.h>
|
|||
|
|||
#include "components/thread/thread.hpp"
|
|||
#include "utils/stringutils.hpp"
|
|||
#include "utils/timeutils.hpp"
|
|||
//
|
|||
using namespace iflytop; |
|||
#define DO(exptr) \
|
|||
do { \ |
|||
if ((exptr) != 0) { \ |
|||
logger->error("do {} failed,{}", #exptr, strerror(errno)); \ |
|||
goto error; \ |
|||
} \ |
|||
} while (0) |
|||
|
|||
SocketCan::SocketCanError_t SocketCan::sendFrame(shared_ptr<SocketCanFrame> frame) { |
|||
if (!m_canBusIsReady) { |
|||
return kDeviceBusy; |
|||
} |
|||
|
|||
if (frame == nullptr) { |
|||
logger->error("frame is null"); |
|||
return kParamError; |
|||
} |
|||
|
|||
if (isTxing()) { |
|||
logger->error("txing, can't send frame"); |
|||
return kDeviceBusy; |
|||
} |
|||
|
|||
canfd_frame_t canframe = frame->getCanFrame(); |
|||
return writeFrame(canframe); |
|||
} |
|||
SocketCan::SocketCanError_t SocketCan::writeFrame(const canfd_frame_t &_frame) { |
|||
if (!m_canBusIsReady) { |
|||
return kDeviceBusy; |
|||
} |
|||
|
|||
canfd_frame_t txframe = _frame; |
|||
txframe.can_id |= 0x10000000; |
|||
setTxStateToTxing(txframe); |
|||
|
|||
int ret = write(m_socketCanFd, &txframe, 16); |
|||
if (ret != (16)) { |
|||
logger->error("write fail,{}", strerror(errno)); |
|||
unsetTxStateToTxing(); |
|||
return kWriteError; |
|||
} |
|||
return kSuccess; |
|||
} |
|||
|
|||
SocketCan::SocketCanError_t SocketCan::sendFrame(shared_ptr<SocketCanFrame> frame, int overtime) { |
|||
tp_steady start = tu_steady().now(); |
|||
|
|||
while (tu_steady().elapsedTimeMs(start) < overtime && !m_canBusIsReady) { |
|||
usleep(100); |
|||
} |
|||
|
|||
if (!m_canBusIsReady) { |
|||
return kOvertime; |
|||
} |
|||
|
|||
while (tu_steady().elapsedTimeMs(start) < overtime && isTxing()) { |
|||
usleep(100); |
|||
} |
|||
|
|||
if (isTxing()) { |
|||
logger->error("send frame overtime"); |
|||
return kOvertime; |
|||
} |
|||
return sendFrame(frame); |
|||
} |
|||
|
|||
bool SocketCan::isTxing() { return m_txState.txState == kTxing; } |
|||
|
|||
bool SocketCan::isTxFrame(const canfd_frame_t &frame) { |
|||
lock_guard<recursive_mutex> lock(m_txState.lock); |
|||
if (m_txState.txbuf.can_id == frame.can_id && m_txState.txbuf.len == frame.len && memcmp(m_txState.txbuf.data, frame.data, frame.len) == 0) { |
|||
return true; |
|||
} |
|||
return false; |
|||
} |
|||
|
|||
void SocketCan::initialize(shared_ptr<SocketCanConfig> socketCanConfig) { //
|
|||
ZCHECK(socketCanConfig, "socketCanConfig is null"); |
|||
m_socketCanConfig = socketCanConfig; |
|||
|
|||
socketcanInitialize(); |
|||
} |
|||
SocketCan::~SocketCan() { |
|||
if (m_thread) { |
|||
endListenThread(); |
|||
} |
|||
if (m_socketCanFd > 0) { |
|||
close(m_socketCanFd); |
|||
m_socketCanFd = -1; |
|||
} |
|||
} |
|||
|
|||
void SocketCan::startListen() { startListenThread(); } |
|||
|
|||
void SocketCan::socketcanReInitialize() {} |
|||
|
|||
void SocketCan::startListenThread() { |
|||
if (m_thread) { |
|||
endListenThread(); |
|||
return; |
|||
} |
|||
logger->info("startListenThread"); |
|||
|
|||
m_thread.reset(new Thread("SocketCanThread", [this]() { |
|||
/**
|
|||
* @brief call socketCanReadThreadLoop |
|||
*/ |
|||
socketCanReadThreadLoop(); |
|||
})); |
|||
m_canBusIsReady = true; |
|||
|
|||
m_autoRestartThread.reset(new Thread("SocketCanAutoRestartThread", [this]() { monitorLoop(); })); |
|||
} |
|||
void SocketCan::endListenThread() { |
|||
logger->info("endListenThread"); |
|||
if (m_thread) { |
|||
m_thread->join(); |
|||
m_thread = nullptr; |
|||
} |
|||
} |
|||
|
|||
void SocketCan::socketcanInitialize() { |
|||
// setCanBitrate(canName, bitrate);
|
|||
|
|||
struct ifreq ifr = {0}; |
|||
struct sockaddr_can addr = {0}; |
|||
can_filter_t zerofilter = {0}; |
|||
int recv_own_msgs = 0; /* 0 = disabled (default), 1 = enabled */ |
|||
int localloop = 0; |
|||
vector<can_filter_t> filters = m_socketCanConfig->m_canfilters; |
|||
can_err_mask_t err_mask = 0; |
|||
|
|||
if (!findCan(m_socketCanConfig->m_canName)) { |
|||
logger->error("can:{} not found", m_socketCanConfig->m_canName); |
|||
return; |
|||
} |
|||
|
|||
if (m_thread) endListenThread(); |
|||
if (m_socketCanFd > 0) socketcanDeInitialize(); |
|||
|
|||
logger->info("socketcanInitialize,canName:{},canBaudrate:{}", m_socketCanConfig->m_canName, m_socketCanConfig->m_canBaudrate); |
|||
|
|||
// 配置socketCan波特率,注意该方法必须放在socket之前
|
|||
setCanBitrate(m_socketCanConfig->m_canName, m_socketCanConfig->m_canBaudrate); |
|||
|
|||
// SOCKET
|
|||
m_socketCanFd = socket(PF_CAN, SOCK_RAW, CAN_RAW); |
|||
if (m_socketCanFd < 0) { |
|||
logger->error("socket failed,{}", strerror(errno)); |
|||
goto error; |
|||
} |
|||
|
|||
// 设置依靠名字绑定CAN设备
|
|||
strcpy(ifr.ifr_name, m_socketCanConfig->m_canName.c_str()); |
|||
DO(ioctl(m_socketCanFd, SIOCGIFINDEX, &ifr)); |
|||
|
|||
// BIND
|
|||
addr.can_family = AF_CAN; |
|||
addr.can_ifindex = ifr.ifr_ifindex; |
|||
DO(bind(m_socketCanFd, (struct sockaddr *)&addr, sizeof(addr))); |
|||
|
|||
// 设置过滤器,默认不过滤
|
|||
DO(setsockopt(m_socketCanFd, SOL_CAN_RAW, CAN_RAW_FILTER, &zerofilter, sizeof(zerofilter))); |
|||
|
|||
if (m_socketCanConfig->enablLoopback) { |
|||
localloop = 1; /* 0 = disabled (default), 1 = enabled */ |
|||
DO(setsockopt(m_socketCanFd, SOL_CAN_RAW, CAN_RAW_LOOPBACK, &localloop, sizeof(localloop))); |
|||
|
|||
recv_own_msgs = 1; /* 0 = disabled (default), 1 = enabled */ |
|||
DO(setsockopt(m_socketCanFd, SOL_CAN_RAW, CAN_RAW_RECV_OWN_MSGS, &recv_own_msgs, sizeof(recv_own_msgs))); |
|||
} else { |
|||
localloop = 0; /* 0 = disabled (default), 1 = enabled */ |
|||
DO(setsockopt(m_socketCanFd, SOL_CAN_RAW, CAN_RAW_LOOPBACK, &localloop, sizeof(localloop))); |
|||
|
|||
recv_own_msgs = 0; /* 0 = disabled (default), 1 = enabled */ |
|||
DO(setsockopt(m_socketCanFd, SOL_CAN_RAW, CAN_RAW_RECV_OWN_MSGS, &recv_own_msgs, sizeof(recv_own_msgs))); |
|||
} |
|||
|
|||
err_mask = CAN_ERR_TX_TIMEOUT | //
|
|||
CAN_ERR_LOSTARB | //
|
|||
CAN_ERR_CRTL | //
|
|||
CAN_ERR_PROT | //
|
|||
CAN_ERR_TRX | //
|
|||
CAN_ERR_ACK | //
|
|||
CAN_ERR_BUSOFF | //
|
|||
CAN_ERR_BUSERROR | //
|
|||
CAN_ERR_RESTARTED; |
|||
|
|||
setsockopt(m_socketCanFd, SOL_CAN_RAW, CAN_RAW_ERR_FILTER, &err_mask, sizeof(err_mask)); |
|||
logger->info("socketcan init success"); |
|||
|
|||
return; |
|||
error: |
|||
logger->error("socketcan init failed"); |
|||
if (m_socketCanFd > 0) { |
|||
close(m_socketCanFd); |
|||
m_socketCanFd = -1; |
|||
} |
|||
return; |
|||
} |
|||
void SocketCan::socketcanDeInitialize() {} |
|||
|
|||
void SocketCan::canReadThread() {} |
|||
|
|||
void SocketCan::setCanBitrate(string canName, int bitrate) { |
|||
logger->info("set can:{} bitrate:{}", canName, bitrate); |
|||
dosystem(fmt::format("ip link set {} down", canName)); |
|||
dosystem(fmt::format("ip link set {} type can bitrate {}", canName, bitrate)); |
|||
dosystem(fmt::format("ip link set {} up", canName)); |
|||
} |
|||
bool SocketCan::findCan(string canName) { return access(fmt::format("/sys/class/net/{}", canName).c_str(), F_OK) == 0; } |
|||
|
|||
void SocketCan::dosystem(string cmd) { |
|||
logger->info("do cmd:{}", cmd); |
|||
system(cmd.c_str()); |
|||
} |
|||
bool SocketCan::tryUpdateTxState(canfd_frame_t &rxloopmsg) { |
|||
lock_guard<recursive_mutex> lock(m_txState.lock); |
|||
if (m_txState.txState == kTxing && isTxFrame(rxloopmsg)) { |
|||
unsetTxStateToTxing(); |
|||
return true; |
|||
} |
|||
return false; |
|||
} |
|||
|
|||
void SocketCan::setTxStateToTxing(const canfd_frame_t &txpacket) { |
|||
lock_guard<recursive_mutex> lock(m_txState.lock); |
|||
m_txState.txState = kTxing; |
|||
m_txState.txbuf = txpacket; |
|||
} |
|||
void SocketCan::unsetTxStateToTxing() { |
|||
lock_guard<recursive_mutex> lock(m_txState.lock); |
|||
m_txState.txState = kTxIdle; |
|||
} |
|||
|
|||
#define TEST_CANDRIVER_DO(exptr) \
|
|||
do { \ |
|||
if ((exptr) != 0) { \ |
|||
logger->error("do {} failed,{}", #exptr, strerror(errno)); \ |
|||
if (socketId > 0) { \ |
|||
close(socketId); \ |
|||
socketId = -1; \ |
|||
return -1; \ |
|||
} \ |
|||
} \ |
|||
} while (0) |
|||
|
|||
int SocketCan::dumpCanDriverInfo(string canDevice, int baudrate) { |
|||
int socketId = -1; |
|||
struct ifreq ifr = {0}; |
|||
struct sockaddr_can addr = {0}; |
|||
can_filter_t zerofilter = {0}; |
|||
int recv_own_msgs = 0; /* 0 = disabled (default), 1 = enabled */ |
|||
int localloop = 0; |
|||
int ret = 0; |
|||
fd_set readfds, readFileDescriptors; |
|||
timeval waitTime; |
|||
int loopTime = 0; |
|||
logger_t logger = GET_LOGGER(SocketCan); |
|||
|
|||
if (!findCan(canDevice)) { |
|||
logger->error("can:{} not found", canDevice); |
|||
return -1; |
|||
} |
|||
|
|||
// set bitrate
|
|||
system(fmt::format("ip link set {} down", canDevice).c_str()); |
|||
system(fmt::format("ip link set {} type can bitrate {}", canDevice, baudrate).c_str()); |
|||
system(fmt::format("ip link set {} up", canDevice).c_str()); |
|||
|
|||
socketId = socket(PF_CAN, SOCK_RAW, CAN_RAW); |
|||
if (socketId < 0) { |
|||
logger->error("socket failed,{}", strerror(errno)); |
|||
return -1; |
|||
} |
|||
|
|||
// 设置依靠名字绑定CAN设备
|
|||
strcpy(ifr.ifr_name, canDevice.c_str()); |
|||
TEST_CANDRIVER_DO(ioctl(socketId, SIOCGIFINDEX, &ifr)); |
|||
|
|||
// BIND
|
|||
addr.can_family = AF_CAN; |
|||
addr.can_ifindex = ifr.ifr_ifindex; |
|||
TEST_CANDRIVER_DO(bind(socketId, (struct sockaddr *)&addr, sizeof(addr))); |
|||
|
|||
// 设置过滤器
|
|||
TEST_CANDRIVER_DO(setsockopt(socketId, SOL_CAN_RAW, CAN_RAW_FILTER, &zerofilter, sizeof(zerofilter))); |
|||
|
|||
// 打开回环
|
|||
localloop = 1; /* 0 = disabled (default), 1 = enabled */ |
|||
TEST_CANDRIVER_DO(setsockopt(socketId, SOL_CAN_RAW, CAN_RAW_LOOPBACK, &localloop, sizeof(localloop))); |
|||
|
|||
recv_own_msgs = 1; /* 0 = disabled (default), 1 = enabled */ |
|||
TEST_CANDRIVER_DO(setsockopt(socketId, SOL_CAN_RAW, CAN_RAW_RECV_OWN_MSGS, &recv_own_msgs, sizeof(recv_own_msgs))); |
|||
|
|||
// 发送一条消息
|
|||
canfd_frame_t txframe = {0}; |
|||
canfd_frame_t rxcanframe = {0}; |
|||
|
|||
int rxloopcount = 0; |
|||
txframe.can_id = 0x12; |
|||
txframe.len = 8; |
|||
txframe.data[0] = 0x01; |
|||
|
|||
logger->info("write one frame"); |
|||
ret = write(socketId, &txframe, txframe.len + 8); |
|||
if (ret < 0) { |
|||
logger->error("write failed,{}", strerror(errno)); |
|||
close(socketId); |
|||
return -1; |
|||
} |
|||
|
|||
FD_ZERO(&readFileDescriptors); |
|||
FD_SET(socketId, &readFileDescriptors); |
|||
while (loopTime < 10) { |
|||
loopTime++; |
|||
waitTime.tv_sec = 0; |
|||
waitTime.tv_usec = 100000; // 100ms
|
|||
readfds = readFileDescriptors; |
|||
|
|||
int n = select(socketId + 1, &readfds, 0, 0, &waitTime); |
|||
if (n <= 0) continue; |
|||
|
|||
int readsize = read(socketId, &rxcanframe, sizeof(rxcanframe)); |
|||
if (readsize < 0) { |
|||
logger->error("read failed,{}", strerror(errno)); |
|||
close(socketId); |
|||
return -1; |
|||
} |
|||
|
|||
if (rxcanframe.can_id == txframe.can_id && //
|
|||
rxcanframe.data[0] == txframe.data[0] && //
|
|||
rxcanframe.len == txframe.len) { |
|||
rxloopcount++; |
|||
logger->info("rx loop frame {}", rxloopcount); |
|||
} |
|||
} |
|||
|
|||
logger->info("Test Can Driver OK!"); |
|||
logger->info("=================Can Driver Info ================="); |
|||
logger->info("canDevice :{}", canDevice); |
|||
logger->info("baudrate :{}", baudrate); |
|||
logger->info("loop count :{}", rxloopcount); |
|||
logger->info("shouldEnableLoop:{}", rxloopcount == 1); |
|||
logger->info("=================================================="); |
|||
|
|||
close(socketId); |
|||
|
|||
return 0; |
|||
} |
|||
|
|||
void SocketCan::socketCanReadThreadLoop() { |
|||
ThisThread thisThread; |
|||
|
|||
fd_set readfds, readFileDescriptors; |
|||
FD_ZERO(&readFileDescriptors); |
|||
FD_SET(m_socketCanFd, &readFileDescriptors); |
|||
|
|||
while (!thisThread.getExitFlag()) { |
|||
canfd_frame_t canframe; |
|||
|
|||
timeval waitTime; |
|||
waitTime.tv_sec = 0; |
|||
waitTime.tv_usec = 100000; // 100ms
|
|||
|
|||
readfds = readFileDescriptors; |
|||
|
|||
int n = select(m_socketCanFd + 1, &readfds, 0, 0, &waitTime); |
|||
if (n <= 0) continue; |
|||
|
|||
memset(&canframe, 0x00, sizeof(canframe)); |
|||
int ret = read(m_socketCanFd, &canframe, sizeof(canframe)); |
|||
if (ret < 0) { |
|||
logger->error("read failed,{}", strerror(errno)); |
|||
continue; |
|||
} |
|||
|
|||
if (canframe.can_id & CAN_ERR_FLAG) { |
|||
// /usr/include/linux/can/error.h
|
|||
// x can-bus error event 20000004,0004000000000086
|
|||
logger->error("rx can-bus error event {:x},{}", canframe.can_id, StringUtils().bytesToString(canframe.data, canframe.len)); |
|||
|
|||
unsetTxStateToTxing(); |
|||
// exit(-1);
|
|||
break; |
|||
} else { |
|||
// logger->info("TX:{} {} {}", canframe.can_id, canframe.__res0, canframe.__res1);
|
|||
if (!tryUpdateTxState(canframe)) { |
|||
shared_ptr<SocketCanFrame> socketCanFrame = SocketCanFrame::createFrame(canframe); |
|||
logger->debug("RX:{}", socketCanFrame->toString()); |
|||
onSocketCanFrame(socketCanFrame); |
|||
} |
|||
} |
|||
} |
|||
|
|||
m_canTriggerError = true; |
|||
m_canBusIsReady = false; |
|||
} |
|||
|
|||
void SocketCan::monitorLoop() { |
|||
ThisThread thisThread; |
|||
while (!thisThread.getExitFlag()) { |
|||
if (m_canTriggerError) { |
|||
// 尝试恢复CAN总线
|
|||
logger->warn("try to recover can bus............................................"); |
|||
if (m_thread) { |
|||
m_thread->join(); |
|||
m_thread = nullptr; |
|||
} |
|||
logger->warn("close can bus fd:{}", m_socketCanFd); |
|||
|
|||
close(m_socketCanFd); |
|||
m_socketCanFd = -1; |
|||
|
|||
{ |
|||
lock_guard<recursive_mutex> lock(m_txState.lock); |
|||
memset(&m_txState.txbuf, 0x00, sizeof(m_txState.txbuf)); |
|||
m_txState.txState = TxState_t::kTxIdle; |
|||
m_txState.txAckCount = 0; |
|||
m_txState.txLoopMessageRxTicket = zsteady_clock().now(); |
|||
} |
|||
|
|||
logger->warn("re init can bus"); |
|||
socketcanInitialize(); |
|||
|
|||
m_thread.reset(new Thread("SocketCanThread", [this]() { |
|||
usleep(10 * 1000); |
|||
socketCanReadThreadLoop(); |
|||
})); |
|||
|
|||
m_canTriggerError = false; |
|||
m_canBusIsReady = true; |
|||
|
|||
logger->warn("recover can bus ok............................................"); |
|||
} |
|||
|
|||
thisThread.sleepForMs(30); |
|||
} |
|||
} |
@ -1,172 +1,175 @@ |
|||
// //
|
|||
// // Created by zwsd
|
|||
// //
|
|||
|
|||
// #pragma once
|
|||
// #include <fstream>
|
|||
// #include <iostream>
|
|||
// #include <list>
|
|||
// #include <map>
|
|||
// #include <memory>
|
|||
// #include <mutex>
|
|||
// #include <queue>
|
|||
// #include <set>
|
|||
// #include <sstream>
|
|||
// #include <string>
|
|||
// #include <vector>
|
|||
|
|||
// #include "iflytop/core/basic/concurrentqueue/concurrentqueue.h"
|
|||
// #include "iflytop/core/components/timeutils.hpp"
|
|||
// #include "iflytop/core/spdlogfactory/logger.hpp"
|
|||
// #include "iflytop/core/thread/thread.hpp"
|
|||
// #include "socket_can_frame.hpp"
|
|||
|
|||
// /**
|
|||
// * @brief
|
|||
// *
|
|||
// * service: SocketCan
|
|||
// *
|
|||
// * 监听事件:
|
|||
// * 依赖状态:
|
|||
// * 依赖服务:
|
|||
// * 作用:
|
|||
// *
|
|||
// */
|
|||
|
|||
// namespace iflytop {
|
|||
// using namespace std;
|
|||
// using namespace core;
|
|||
// using namespace moodycamel;
|
|||
|
|||
// class SocketCanConfig {
|
|||
// public:
|
|||
// string m_canName;
|
|||
// int m_canBaudrate;
|
|||
|
|||
// /**
|
|||
// * @brief
|
|||
// * SocketCan服务依赖于loopback功能,一般来说是需要使能的。
|
|||
// * 但有些can驱动自动开启了这个功能,这时候就需要禁用,否则就会收到两个相同的帧。
|
|||
// * 通过testCanDriver可以测试是否需要禁用loopback功能。
|
|||
// */
|
|||
// bool enablLoopback = false;
|
|||
|
|||
// vector<can_filter_t> m_canfilters; // 应用层过滤,这里不要配置
|
|||
// };
|
|||
|
|||
// class SocketCan : public enable_shared_from_this<SocketCan> {
|
|||
// ENABLE_LOGGER(SocketCan);
|
|||
|
|||
// public:
|
|||
// typedef enum {
|
|||
// kTxIdle,
|
|||
// kTxing,
|
|||
// } TxState_t;
|
|||
|
|||
// class TxState {
|
|||
// public:
|
|||
// canfd_frame_t txbuf;
|
|||
// TxState_t txState = kTxIdle;
|
|||
// int txAckCount = 0;
|
|||
// zsteady_tp txLoopMessageRxTicket;
|
|||
// recursive_mutex lock;
|
|||
// };
|
|||
|
|||
// private:
|
|||
// unique_ptr<Thread> m_thread;
|
|||
// unique_ptr<Thread> m_autoRestartThread;
|
|||
// int m_socketCanFd = -1;
|
|||
// bool m_startListen = false;
|
|||
|
|||
// shared_ptr<SocketCanConfig> m_socketCanConfig;
|
|||
|
|||
// TxState m_txState;
|
|||
// bool m_canTriggerError = false;
|
|||
// bool m_canBusIsReady = false;
|
|||
|
|||
// public:
|
|||
// typedef enum {
|
|||
// kSuccess,
|
|||
// // Wrong CANFrame format!
|
|||
// kErrorFrameFormat,
|
|||
// // CAN-FD frames not supported!
|
|||
// kCANFDNotSupported,
|
|||
// kWriteError,
|
|||
// kParamError,
|
|||
// kDeviceBusy,
|
|||
// kOvertime,
|
|||
// } SocketCanError_t;
|
|||
|
|||
// static string SocketCanError_t2Str(SocketCanError_t error) {
|
|||
// switch (error) {
|
|||
// case kSuccess:
|
|||
// return "kSuccess";
|
|||
// case kErrorFrameFormat:
|
|||
// return "kErrorFrameFormat";
|
|||
// case kCANFDNotSupported:
|
|||
// return "kCANFDNotSupported";
|
|||
// case kWriteError:
|
|||
// return "kWriteError";
|
|||
// case kParamError:
|
|||
// return "kParamError";
|
|||
// case kDeviceBusy:
|
|||
// return "kDeviceBusy";
|
|||
// case kOvertime:
|
|||
// return "kOvertime";
|
|||
// default:
|
|||
// return "Unknown";
|
|||
// }
|
|||
// }
|
|||
|
|||
// public:
|
|||
// nod::signal<void(shared_ptr<SocketCanFrame>)> onSocketCanFrame;
|
|||
|
|||
// SocketCan(){};
|
|||
// ~SocketCan();
|
|||
|
|||
// void initialize(shared_ptr<SocketCanConfig> socketCanConfig);
|
|||
// bool isError() { return false; }
|
|||
|
|||
// void startListen();
|
|||
|
|||
// SocketCanError_t sendFrame(shared_ptr<SocketCanFrame> frame, int overtime);
|
|||
// SocketCanError_t sendFrame(shared_ptr<SocketCanFrame> frame);
|
|||
// /**
|
|||
// * @brief 使用这个方法测试目标设备CAN驱动的行为,需要CAN总线上,除了目标设备外,至少有一个正常工作的节点。
|
|||
// *
|
|||
// * @param canDevice
|
|||
// * @param baudrate
|
|||
// * @return int
|
|||
// */
|
|||
// static int dumpCanDriverInfo(string canDevice, int baudrate);
|
|||
// bool isTxing();
|
|||
|
|||
// private:
|
|||
// void socketcanInitialize();
|
|||
// void socketcanDeInitialize();
|
|||
// void socketcanReInitialize();
|
|||
|
|||
// void startListenThread();
|
|||
// void endListenThread();
|
|||
// void socketCanReadThreadLoop();
|
|||
|
|||
// void monitorLoop();
|
|||
|
|||
|
|||
// private:
|
|||
// void dosystem(string cmd);
|
|||
// void setCanBitrate(string canName, int bitrate);
|
|||
// static bool findCan(string canName);
|
|||
|
|||
// SocketCanError_t writeFrame(const canfd_frame_t &frame);
|
|||
|
|||
// private:
|
|||
// void canReadThread();
|
|||
|
|||
// bool tryUpdateTxState(canfd_frame_t &rxloopmsg);
|
|||
// void setTxStateToTxing(const canfd_frame_t &txpacket);
|
|||
// void unsetTxStateToTxing();
|
|||
|
|||
// bool isTxFrame(const canfd_frame_t &frame);
|
|||
// };
|
|||
// } // namespace iflytop
|
|||
//
|
|||
// Created by zwsd
|
|||
//
|
|||
|
|||
#pragma once
|
|||
#include <fstream>
|
|||
#include <iostream>
|
|||
#include <list>
|
|||
#include <map>
|
|||
#include <memory>
|
|||
#include <mutex>
|
|||
#include <queue>
|
|||
#include <set>
|
|||
#include <sstream>
|
|||
#include <string>
|
|||
#include <vector>
|
|||
|
|||
|
|||
#include "socket_can_frame.hpp"
|
|||
#include "spdlogfactory/logger.hpp"
|
|||
#include "nlohmann/json.hpp"
|
|||
#include "concurrentqueue/blockingconcurrentqueue.h"
|
|||
#include "utils/timeutils.hpp"
|
|||
#include "nod/nod.hpp"
|
|||
#include "components/thread/thread.hpp"
|
|||
|
|||
/**
|
|||
* @brief |
|||
* |
|||
* service: SocketCan |
|||
* |
|||
* 监听事件: |
|||
* 依赖状态: |
|||
* 依赖服务: |
|||
* 作用: |
|||
* |
|||
*/ |
|||
|
|||
namespace iflytop { |
|||
using namespace std; |
|||
using namespace core; |
|||
using namespace moodycamel; |
|||
|
|||
class SocketCanConfig { |
|||
public: |
|||
string m_canName; |
|||
int m_canBaudrate; |
|||
|
|||
/**
|
|||
* @brief |
|||
* SocketCan服务依赖于loopback功能,一般来说是需要使能的。 |
|||
* 但有些can驱动自动开启了这个功能,这时候就需要禁用,否则就会收到两个相同的帧。 |
|||
* 通过testCanDriver可以测试是否需要禁用loopback功能。 |
|||
*/ |
|||
bool enablLoopback = false; |
|||
|
|||
vector<can_filter_t> m_canfilters; // 应用层过滤,这里不要配置
|
|||
}; |
|||
|
|||
class SocketCan : public enable_shared_from_this<SocketCan> { |
|||
ENABLE_LOGGER(SocketCan); |
|||
|
|||
public: |
|||
typedef enum { |
|||
kTxIdle, |
|||
kTxing, |
|||
} TxState_t; |
|||
|
|||
class TxState { |
|||
public: |
|||
canfd_frame_t txbuf; |
|||
TxState_t txState = kTxIdle; |
|||
int txAckCount = 0; |
|||
zsteady_tp txLoopMessageRxTicket; |
|||
recursive_mutex lock; |
|||
}; |
|||
|
|||
private: |
|||
unique_ptr<Thread> m_thread; |
|||
unique_ptr<Thread> m_autoRestartThread; |
|||
int m_socketCanFd = -1; |
|||
bool m_startListen = false; |
|||
|
|||
shared_ptr<SocketCanConfig> m_socketCanConfig; |
|||
|
|||
TxState m_txState; |
|||
bool m_canTriggerError = false; |
|||
bool m_canBusIsReady = false; |
|||
|
|||
public: |
|||
typedef enum { |
|||
kSuccess, |
|||
// Wrong CANFrame format!
|
|||
kErrorFrameFormat, |
|||
// CAN-FD frames not supported!
|
|||
kCANFDNotSupported, |
|||
kWriteError, |
|||
kParamError, |
|||
kDeviceBusy, |
|||
kOvertime, |
|||
} SocketCanError_t; |
|||
|
|||
static string SocketCanError_t2Str(SocketCanError_t error) { |
|||
switch (error) { |
|||
case kSuccess: |
|||
return "kSuccess"; |
|||
case kErrorFrameFormat: |
|||
return "kErrorFrameFormat"; |
|||
case kCANFDNotSupported: |
|||
return "kCANFDNotSupported"; |
|||
case kWriteError: |
|||
return "kWriteError"; |
|||
case kParamError: |
|||
return "kParamError"; |
|||
case kDeviceBusy: |
|||
return "kDeviceBusy"; |
|||
case kOvertime: |
|||
return "kOvertime"; |
|||
default: |
|||
return "Unknown"; |
|||
} |
|||
} |
|||
|
|||
public: |
|||
nod::signal<void(shared_ptr<SocketCanFrame>)> onSocketCanFrame; |
|||
|
|||
SocketCan(){}; |
|||
~SocketCan(); |
|||
|
|||
void initialize(shared_ptr<SocketCanConfig> socketCanConfig); |
|||
bool isError() { return false; } |
|||
|
|||
void startListen(); |
|||
|
|||
SocketCanError_t sendFrame(shared_ptr<SocketCanFrame> frame, int overtime); |
|||
SocketCanError_t sendFrame(shared_ptr<SocketCanFrame> frame); |
|||
/**
|
|||
* @brief 使用这个方法测试目标设备CAN驱动的行为,需要CAN总线上,除了目标设备外,至少有一个正常工作的节点。 |
|||
* |
|||
* @param canDevice |
|||
* @param baudrate |
|||
* @return int |
|||
*/ |
|||
static int dumpCanDriverInfo(string canDevice, int baudrate); |
|||
bool isTxing(); |
|||
|
|||
private: |
|||
void socketcanInitialize(); |
|||
void socketcanDeInitialize(); |
|||
void socketcanReInitialize(); |
|||
|
|||
void startListenThread(); |
|||
void endListenThread(); |
|||
void socketCanReadThreadLoop(); |
|||
|
|||
void monitorLoop(); |
|||
|
|||
|
|||
private: |
|||
void dosystem(string cmd); |
|||
void setCanBitrate(string canName, int bitrate); |
|||
static bool findCan(string canName); |
|||
|
|||
SocketCanError_t writeFrame(const canfd_frame_t &frame); |
|||
|
|||
private: |
|||
void canReadThread(); |
|||
|
|||
bool tryUpdateTxState(canfd_frame_t &rxloopmsg); |
|||
void setTxStateToTxing(const canfd_frame_t &txpacket); |
|||
void unsetTxStateToTxing(); |
|||
|
|||
bool isTxFrame(const canfd_frame_t &frame); |
|||
}; |
|||
} // namespace iflytop
|
@ -1,91 +1,91 @@ |
|||
// #include "socket_can_frame.hpp"
|
|||
#include "socket_can_frame.hpp"
|
|||
|
|||
// #include "iflytop/core/components/stringutils.hpp"
|
|||
// using namespace iflytop;
|
|||
#include "utils/stringutils.hpp"
|
|||
using namespace iflytop; |
|||
|
|||
// shared_ptr<SocketCanFrame> SocketCanFrame::createExtDataFrame(uint32_t id, uint8_t *data, size_t len) {
|
|||
// shared_ptr<SocketCanFrame> canframe = make_shared<SocketCanFrame>();
|
|||
// if (len > 8) len = 8;
|
|||
// canframe->m_id = id;
|
|||
// canframe->m_canIdentifier = socketcan::kextFrame;
|
|||
// canframe->m_canFrameType = socketcan::kdataframe;
|
|||
// canframe->m_dlc = len;
|
|||
// memcpy(canframe->m_data, data, len);
|
|||
// return canframe;
|
|||
// }
|
|||
shared_ptr<SocketCanFrame> SocketCanFrame::createExtDataFrame(uint32_t id, uint8_t *data, size_t len) { |
|||
shared_ptr<SocketCanFrame> canframe = make_shared<SocketCanFrame>(); |
|||
if (len > 8) len = 8; |
|||
canframe->m_id = id; |
|||
canframe->m_canIdentifier = socketcan::kextFrame; |
|||
canframe->m_canFrameType = socketcan::kdataframe; |
|||
canframe->m_dlc = len; |
|||
memcpy(canframe->m_data, data, len); |
|||
return canframe; |
|||
} |
|||
|
|||
// shared_ptr<SocketCanFrame> SocketCanFrame::createStdDataFrame(uint32_t id, uint8_t *data, size_t len) {
|
|||
// shared_ptr<SocketCanFrame> canframe = make_shared<SocketCanFrame>();
|
|||
// if (len > 8) len = 8;
|
|||
// canframe->m_id = id;
|
|||
// canframe->m_canIdentifier = socketcan::kstdFrame;
|
|||
// canframe->m_canFrameType = socketcan::kdataframe;
|
|||
// canframe->m_dlc = len;
|
|||
// memcpy(canframe->m_data, data, len);
|
|||
// return canframe;
|
|||
// }
|
|||
shared_ptr<SocketCanFrame> SocketCanFrame::createStdDataFrame(uint32_t id, uint8_t *data, size_t len) { |
|||
shared_ptr<SocketCanFrame> canframe = make_shared<SocketCanFrame>(); |
|||
if (len > 8) len = 8; |
|||
canframe->m_id = id; |
|||
canframe->m_canIdentifier = socketcan::kstdFrame; |
|||
canframe->m_canFrameType = socketcan::kdataframe; |
|||
canframe->m_dlc = len; |
|||
memcpy(canframe->m_data, data, len); |
|||
return canframe; |
|||
} |
|||
|
|||
// shared_ptr<SocketCanFrame> SocketCanFrame::createExtRemoteFrame(uint32_t id) {
|
|||
// shared_ptr<SocketCanFrame> canframe = make_shared<SocketCanFrame>();
|
|||
// canframe->m_id = id;
|
|||
// canframe->m_canIdentifier = socketcan::kextFrame;
|
|||
// canframe->m_canFrameType = socketcan::kremoteframe;
|
|||
// canframe->m_dlc = 0;
|
|||
// return canframe;
|
|||
// }
|
|||
// shared_ptr<SocketCanFrame> SocketCanFrame::createStdRemoteFrame(uint32_t id) {
|
|||
// shared_ptr<SocketCanFrame> canframe = make_shared<SocketCanFrame>();
|
|||
// canframe->m_id = id;
|
|||
// canframe->m_canIdentifier = socketcan::kstdFrame;
|
|||
// canframe->m_canFrameType = socketcan::kremoteframe;
|
|||
// canframe->m_dlc = 0;
|
|||
// return canframe;
|
|||
// }
|
|||
// shared_ptr<SocketCanFrame> SocketCanFrame::createFrame(canfd_frame_t frame) {
|
|||
// shared_ptr<SocketCanFrame> canframe = make_shared<SocketCanFrame>();
|
|||
// canframe->m_id = frame.can_id & ~CAN_EFF_FLAG & ~CAN_RTR_FLAG & ~CAN_ERR_FLAG;
|
|||
// canframe->m_canIdentifier = frame.can_id & CAN_EFF_FLAG ? socketcan::kextFrame : socketcan::kstdFrame;
|
|||
// canframe->m_canFrameType = frame.can_id & CAN_RTR_FLAG ? socketcan::kremoteframe : socketcan::kdataframe;
|
|||
// canframe->m_dlc = frame.len;
|
|||
shared_ptr<SocketCanFrame> SocketCanFrame::createExtRemoteFrame(uint32_t id) { |
|||
shared_ptr<SocketCanFrame> canframe = make_shared<SocketCanFrame>(); |
|||
canframe->m_id = id; |
|||
canframe->m_canIdentifier = socketcan::kextFrame; |
|||
canframe->m_canFrameType = socketcan::kremoteframe; |
|||
canframe->m_dlc = 0; |
|||
return canframe; |
|||
} |
|||
shared_ptr<SocketCanFrame> SocketCanFrame::createStdRemoteFrame(uint32_t id) { |
|||
shared_ptr<SocketCanFrame> canframe = make_shared<SocketCanFrame>(); |
|||
canframe->m_id = id; |
|||
canframe->m_canIdentifier = socketcan::kstdFrame; |
|||
canframe->m_canFrameType = socketcan::kremoteframe; |
|||
canframe->m_dlc = 0; |
|||
return canframe; |
|||
} |
|||
shared_ptr<SocketCanFrame> SocketCanFrame::createFrame(canfd_frame_t frame) { |
|||
shared_ptr<SocketCanFrame> canframe = make_shared<SocketCanFrame>(); |
|||
canframe->m_id = frame.can_id & ~CAN_EFF_FLAG & ~CAN_RTR_FLAG & ~CAN_ERR_FLAG; |
|||
canframe->m_canIdentifier = frame.can_id & CAN_EFF_FLAG ? socketcan::kextFrame : socketcan::kstdFrame; |
|||
canframe->m_canFrameType = frame.can_id & CAN_RTR_FLAG ? socketcan::kremoteframe : socketcan::kdataframe; |
|||
canframe->m_dlc = frame.len; |
|||
|
|||
// memcpy(canframe->m_data, frame.data, frame.len);
|
|||
// return canframe;
|
|||
// }
|
|||
memcpy(canframe->m_data, frame.data, frame.len); |
|||
return canframe; |
|||
} |
|||
|
|||
// void SocketCanFrame::setCanIdentifier(socketcan::can_identifier_t canIdentifier) { this->m_canIdentifier = canIdentifier; }
|
|||
// void SocketCanFrame::setFanFrameType(socketcan::can_frame_type_t fanFrameType) { this->m_canFrameType = fanFrameType; }
|
|||
// void SocketCanFrame::setId(uint32_t id) { this->m_id = id; }
|
|||
void SocketCanFrame::setCanIdentifier(socketcan::can_identifier_t canIdentifier) { this->m_canIdentifier = canIdentifier; } |
|||
void SocketCanFrame::setFanFrameType(socketcan::can_frame_type_t fanFrameType) { this->m_canFrameType = fanFrameType; } |
|||
void SocketCanFrame::setId(uint32_t id) { this->m_id = id; } |
|||
|
|||
// uint32_t SocketCanFrame::getId() { return m_id; }
|
|||
// socketcan::can_identifier_t SocketCanFrame::getCanIdentifier() { return m_canIdentifier; }
|
|||
// socketcan::can_frame_type_t SocketCanFrame::getFanFrameType() { return m_canFrameType; }
|
|||
uint32_t SocketCanFrame::getId() { return m_id; } |
|||
socketcan::can_identifier_t SocketCanFrame::getCanIdentifier() { return m_canIdentifier; } |
|||
socketcan::can_frame_type_t SocketCanFrame::getFanFrameType() { return m_canFrameType; } |
|||
|
|||
// string SocketCanFrame::toString() { //
|
|||
// return fmt::format("|{:0>8x}|{:>6}|{}|{}({})|", getId(), //
|
|||
// getFanFrameType() == socketcan::kdataframe ? "data" : "remote", //
|
|||
// getCanIdentifier() == socketcan::kextFrame ? "ext" : "std", //
|
|||
// StringUtils().bytesToString(m_data, m_dlc), m_dlc);
|
|||
// }
|
|||
string SocketCanFrame::toString() { //
|
|||
return fmt::format("|{:0>8x}|{:>6}|{}|{}({})|", getId(), //
|
|||
getFanFrameType() == socketcan::kdataframe ? "data" : "remote", //
|
|||
getCanIdentifier() == socketcan::kextFrame ? "ext" : "std", //
|
|||
StringUtils().bytesToString(m_data, m_dlc), m_dlc); |
|||
} |
|||
|
|||
// uint8_t *SocketCanFrame::getData() { return m_data; }
|
|||
// uint8_t SocketCanFrame::getDlc() { return m_dlc; }
|
|||
uint8_t *SocketCanFrame::getData() { return m_data; } |
|||
uint8_t SocketCanFrame::getDlc() { return m_dlc; } |
|||
|
|||
// canfd_frame_t SocketCanFrame::getCanFrame() {
|
|||
// canfd_frame_t frame;
|
|||
// memset(&frame, 0, sizeof(frame));
|
|||
canfd_frame_t SocketCanFrame::getCanFrame() { |
|||
canfd_frame_t frame; |
|||
memset(&frame, 0, sizeof(frame)); |
|||
|
|||
// if (m_canIdentifier == socketcan::kstdFrame) {
|
|||
// frame.can_id = (m_id & CAN_SFF_MASK);
|
|||
// } else {
|
|||
// frame.can_id = (m_id & CAN_EFF_MASK) | CAN_EFF_FLAG;
|
|||
// }
|
|||
if (m_canIdentifier == socketcan::kstdFrame) { |
|||
frame.can_id = (m_id & CAN_SFF_MASK); |
|||
} else { |
|||
frame.can_id = (m_id & CAN_EFF_MASK) | CAN_EFF_FLAG; |
|||
} |
|||
|
|||
// if (m_canFrameType == socketcan::kremoteframe) {
|
|||
// frame.can_id |= CAN_RTR_FLAG;
|
|||
// frame.len = m_dlc;
|
|||
// } else {
|
|||
// frame.len = m_dlc;
|
|||
// memcpy(frame.data, m_data, m_dlc);
|
|||
// }
|
|||
// return frame;
|
|||
// }
|
|||
if (m_canFrameType == socketcan::kremoteframe) { |
|||
frame.can_id |= CAN_RTR_FLAG; |
|||
frame.len = m_dlc; |
|||
} else { |
|||
frame.len = m_dlc; |
|||
memcpy(frame.data, m_data, m_dlc); |
|||
} |
|||
return frame; |
|||
} |
@ -1,79 +1,77 @@ |
|||
// #pragma once
|
|||
// #include <linux/can.h>
|
|||
// #include <linux/can/raw.h>
|
|||
// #include <net/if.h>
|
|||
// #include <stdio.h>
|
|||
// #include <stdlib.h>
|
|||
// #include <string.h>
|
|||
// #include <sys/ioctl.h>
|
|||
// #include <sys/socket.h>
|
|||
// #include <unistd.h>
|
|||
#pragma once
|
|||
#include <linux/can.h>
|
|||
#include <linux/can/raw.h>
|
|||
#include <net/if.h>
|
|||
#include <stdio.h>
|
|||
#include <stdlib.h>
|
|||
#include <string.h>
|
|||
#include <sys/ioctl.h>
|
|||
#include <sys/socket.h>
|
|||
#include <unistd.h>
|
|||
|
|||
// #include <fstream>
|
|||
// #include <iostream>
|
|||
// #include <list>
|
|||
// #include <map>
|
|||
// #include <memory>
|
|||
// #include <set>
|
|||
// #include <sstream>
|
|||
// #include <string>
|
|||
// #include <vector>
|
|||
#include <fstream>
|
|||
#include <iostream>
|
|||
#include <list>
|
|||
#include <map>
|
|||
#include <memory>
|
|||
#include <set>
|
|||
#include <sstream>
|
|||
#include <string>
|
|||
#include <vector>
|
|||
|
|||
// #include "iflytop/core/basic/nod/nod.hpp"
|
|||
// #include "iflytop/core/spdlogfactory/logger.hpp"
|
|||
// #include "iflytop/core/thread/thread.hpp"
|
|||
#include "spdlogfactory/logger.hpp"
|
|||
|
|||
// namespace iflytop {
|
|||
// using namespace std;
|
|||
// using namespace core;
|
|||
namespace iflytop { |
|||
using namespace std; |
|||
using namespace core; |
|||
|
|||
// /*******************************************************************************
|
|||
// * CAN_FRAME *
|
|||
// *******************************************************************************/
|
|||
/*******************************************************************************
|
|||
* CAN_FRAME * |
|||
*******************************************************************************/ |
|||
|
|||
// typedef struct can_filter can_filter_t;
|
|||
// typedef struct canfd_frame canfd_frame_t;
|
|||
typedef struct can_filter can_filter_t; |
|||
typedef struct canfd_frame canfd_frame_t; |
|||
|
|||
// namespace socketcan {
|
|||
// typedef enum {
|
|||
// kstdFrame,
|
|||
// kextFrame,
|
|||
// } can_identifier_t;
|
|||
namespace socketcan { |
|||
typedef enum { |
|||
kstdFrame, |
|||
kextFrame, |
|||
} can_identifier_t; |
|||
|
|||
// typedef enum {
|
|||
// kdataframe,
|
|||
// kremoteframe,
|
|||
// } can_frame_type_t;
|
|||
// } // namespace socketcan
|
|||
typedef enum { |
|||
kdataframe, |
|||
kremoteframe, |
|||
} can_frame_type_t; |
|||
} // namespace socketcan
|
|||
|
|||
// class SocketCanFrame {
|
|||
// private:
|
|||
// uint32_t m_id = 0;
|
|||
// socketcan::can_identifier_t m_canIdentifier = socketcan::kstdFrame;
|
|||
// socketcan::can_frame_type_t m_canFrameType = socketcan::kdataframe;
|
|||
// uint8_t m_data[8] = {0};
|
|||
// uint8_t m_dlc = 0;
|
|||
class SocketCanFrame { |
|||
private: |
|||
uint32_t m_id = 0; |
|||
socketcan::can_identifier_t m_canIdentifier = socketcan::kstdFrame; |
|||
socketcan::can_frame_type_t m_canFrameType = socketcan::kdataframe; |
|||
uint8_t m_data[8] = {0}; |
|||
uint8_t m_dlc = 0; |
|||
|
|||
// public:
|
|||
// static shared_ptr<SocketCanFrame> createExtDataFrame(uint32_t id, uint8_t *data, size_t len);
|
|||
// static shared_ptr<SocketCanFrame> createStdDataFrame(uint32_t id, uint8_t *data, size_t len);
|
|||
// static shared_ptr<SocketCanFrame> createExtRemoteFrame(uint32_t id);
|
|||
// static shared_ptr<SocketCanFrame> createStdRemoteFrame(uint32_t id);
|
|||
// static shared_ptr<SocketCanFrame> createFrame(canfd_frame_t frame);
|
|||
public: |
|||
static shared_ptr<SocketCanFrame> createExtDataFrame(uint32_t id, uint8_t *data, size_t len); |
|||
static shared_ptr<SocketCanFrame> createStdDataFrame(uint32_t id, uint8_t *data, size_t len); |
|||
static shared_ptr<SocketCanFrame> createExtRemoteFrame(uint32_t id); |
|||
static shared_ptr<SocketCanFrame> createStdRemoteFrame(uint32_t id); |
|||
static shared_ptr<SocketCanFrame> createFrame(canfd_frame_t frame); |
|||
|
|||
// void setId(uint32_t id);
|
|||
// uint32_t getId();
|
|||
// socketcan::can_frame_type_t getFanFrameType();
|
|||
// void setFanFrameType(socketcan::can_frame_type_t fanFrameType);
|
|||
// socketcan::can_identifier_t getCanIdentifier();
|
|||
// void setCanIdentifier(socketcan::can_identifier_t canIdentifier);
|
|||
void setId(uint32_t id); |
|||
uint32_t getId(); |
|||
socketcan::can_frame_type_t getFanFrameType(); |
|||
void setFanFrameType(socketcan::can_frame_type_t fanFrameType); |
|||
socketcan::can_identifier_t getCanIdentifier(); |
|||
void setCanIdentifier(socketcan::can_identifier_t canIdentifier); |
|||
|
|||
// uint8_t *getData();
|
|||
// uint8_t getDlc();
|
|||
uint8_t *getData(); |
|||
uint8_t getDlc(); |
|||
|
|||
// canfd_frame_t getCanFrame();
|
|||
canfd_frame_t getCanFrame(); |
|||
|
|||
// string toString();
|
|||
// };
|
|||
string toString(); |
|||
}; |
|||
|
|||
// } // namespace iflytop
|
|||
} // namespace iflytop
|
@ -1,105 +1,119 @@ |
|||
// #include "zcanreceiverhost.hpp"
|
|||
|
|||
// #include <stdio.h>
|
|||
// #include <stdlib.h>
|
|||
// #include <string.h>
|
|||
// 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, 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; }
|
|||
|
|||
// void ZCanReceiverHost::sendPacket(uint8_t *packet, size_t len) {
|
|||
// 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) {
|
|||
// 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_deviceId << 16) | (npacket << 8) | packetIndex;
|
|||
// // 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::createExtDataFrame(id, packet, len);
|
|||
// 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);
|
|||
|
|||
// 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) { //
|
|||
// logger->debug("onSocketCanFrame {}", canframe->toString());
|
|||
// processRx(canframe);
|
|||
// });
|
|||
// }
|
|||
#include "zcanreceiverhost.hpp"
|
|||
|
|||
#include <stdio.h>
|
|||
#include <stdlib.h>
|
|||
#include <string.h>
|
|||
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, 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; } |
|||
|
|||
void ZCanReceiverHost::sendPacket(uint8_t *packet, size_t 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 = 0; |
|||
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); |
|||
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 接收到最后一包数据 |
|||
*/ |
|||
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) { //
|
|||
logger->debug("onSocketCanFrame {}", canframe->toString()); |
|||
processRx(canframe); |
|||
}); |
|||
} |
@ -1,61 +1,60 @@ |
|||
// //
|
|||
// // Created by zwsd
|
|||
// //
|
|||
|
|||
// #pragma once
|
|||
// #include <mutex>
|
|||
|
|||
// #include "socket_can/socket_can.hpp"
|
|||
// //
|
|||
// #include "thirdlib/nlohmann/json.hpp"
|
|||
// #include "a8000_protocol/protocol.hpp"
|
|||
// #include "thirdlib/spdlogfactory/logger_factory.hpp"
|
|||
|
|||
// namespace iflytop {
|
|||
|
|||
// using namespace std;
|
|||
// using namespace zcr;
|
|||
// using namespace core;
|
|||
|
|||
// 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;
|
|||
// };
|
|||
|
|||
// typedef function<void(uint8_t fromboardid, uint8_t *packet, size_t len)> onpacket_t;
|
|||
|
|||
// public:
|
|||
// uint8_t m_deviceId = 0;
|
|||
// CanPacketRxBuffer m_canPacketRxBuffer[255];
|
|||
// onpacket_t m_onpacket;
|
|||
|
|||
// shared_ptr<SocketCan> m_socketCan;
|
|||
|
|||
// string m_can_if_name;
|
|||
// int m_baudrate;
|
|||
// bool m_enablLoopback;
|
|||
|
|||
// public:
|
|||
// ZCanReceiverHost();
|
|||
// void initialize(string can_if_name, int baudrate, bool enablLoopback);
|
|||
// void sendPacket(uint8_t *packet, size_t len);
|
|||
// void registerListener(onpacket_t onpacket);
|
|||
|
|||
// private:
|
|||
// bool sendPacketSub(int npacket, int packetIndex, uint8_t *packet, size_t len, int overtimems);
|
|||
|
|||
// 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);
|
|||
// };
|
|||
|
|||
// } // namespace iflytop
|
|||
//
|
|||
// Created by zwsd
|
|||
//
|
|||
|
|||
#pragma once
|
|||
#include <mutex>
|
|||
|
|||
#include "socket_can/socket_can.hpp"
|
|||
//
|
|||
#include "a8000_protocol/protocol.hpp"
|
|||
#include "thirdlib/spdlogfactory/logger_factory.hpp"
|
|||
|
|||
namespace iflytop { |
|||
|
|||
using namespace std; |
|||
using namespace zcr; |
|||
using namespace core; |
|||
|
|||
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; |
|||
}; |
|||
|
|||
typedef function<void(uint8_t fromboardid, uint8_t *packet, size_t len)> onpacket_t; |
|||
|
|||
public: |
|||
uint8_t m_deviceId = 0; |
|||
CanPacketRxBuffer m_canPacketRxBuffer[255]; |
|||
onpacket_t m_onpacket; |
|||
|
|||
shared_ptr<SocketCan> m_socketCan; |
|||
|
|||
string m_can_if_name; |
|||
int m_baudrate; |
|||
bool m_enablLoopback; |
|||
|
|||
public: |
|||
ZCanReceiverHost(); |
|||
void initialize(string can_if_name, int baudrate, bool enablLoopback); |
|||
void sendPacket(uint8_t *packet, size_t len); |
|||
void registerListener(onpacket_t onpacket); |
|||
|
|||
private: |
|||
bool sendPacketSub(int npacket, int packetIndex, uint8_t *packet, size_t len, int overtimems); |
|||
|
|||
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); |
|||
}; |
|||
|
|||
} // namespace iflytop
|
@ -0,0 +1,215 @@ |
|||
#include "stringutils.hpp"
|
|||
using namespace iflytop; |
|||
using namespace core; |
|||
using namespace std; |
|||
|
|||
/***********************************************************************************************************************
|
|||
* ======================================================private====================================================== * |
|||
***********************************************************************************************************************/ |
|||
char StringUtils::byteToChar(uint8_t byte) { |
|||
if (byte < 10) { |
|||
return '0' + byte; |
|||
} else { |
|||
return 'A' + (byte - 10); |
|||
} |
|||
throw std::out_of_range("byteToChar out of range"); |
|||
return 'x'; |
|||
} |
|||
bool StringUtils::isLegalHex(char c) { |
|||
if (c >= '0' && c <= '9') { |
|||
return true; |
|||
} else if (c >= 'A' && c <= 'F') { |
|||
return true; |
|||
} else if (c >= 'a' && c <= 'f') { |
|||
return true; |
|||
} |
|||
return false; |
|||
} |
|||
/***********************************************************************************************************************
|
|||
* ======================================================public======================================================= * |
|||
***********************************************************************************************************************/ |
|||
|
|||
string StringUtils::upper(const string& value) { |
|||
string cpy = value; |
|||
transform(cpy.begin(), cpy.end(), cpy.begin(), ::toupper); |
|||
return cpy; |
|||
} |
|||
string StringUtils::lower(const string& value) { |
|||
string cpy = value; |
|||
transform(cpy.begin(), cpy.end(), cpy.begin(), ::tolower); |
|||
return cpy; |
|||
} |
|||
|
|||
string StringUtils::bytesToString(const uint8_t* data, size_t size) { |
|||
string ret; |
|||
for (unsigned i = 0; i < size; ++i) { |
|||
uint8_t hight4 = data[i] >> 4 & 0x0f; |
|||
uint8_t low4 = data[i] >> 0 & 0x0f; |
|||
ret += byteToChar(hight4); |
|||
ret += byteToChar(low4); |
|||
} |
|||
return ret; |
|||
} |
|||
string& StringUtils::replaceAllDistinct(string& str, const string& old_value, const string& new_value) { |
|||
for (string::size_type pos(0); pos != string::npos; pos += new_value.length()) { |
|||
if ((pos = str.find(old_value, pos)) != string::npos) { |
|||
str.replace(pos, old_value.length(), new_value); |
|||
} else { |
|||
break; |
|||
} |
|||
} |
|||
return str; |
|||
} |
|||
|
|||
bool StringUtils::hexStringToBytes(string in, string delims, vector<uint8_t>& byteTable) { |
|||
string hexTable; |
|||
byteTable.clear(); |
|||
if (!delims.empty()) { |
|||
hexTable = replaceAllDistinct(in, delims, ""); |
|||
/* code */ |
|||
} else { |
|||
hexTable = in; |
|||
} |
|||
|
|||
if (hexTable.length() % 2 != 0) { |
|||
// printf("ss\n");
|
|||
return false; |
|||
} |
|||
|
|||
try { |
|||
for (unsigned i = 0; i < hexTable.length(); i += 2) { |
|||
string hex = hexTable.substr(i, 2); |
|||
// printf("ss1 %s\n", hex.c_str());
|
|||
|
|||
if (!isLegalHex(hex.c_str()[0])) { |
|||
return false; |
|||
} |
|||
if (!isLegalHex(hex.c_str()[1])) { |
|||
return false; |
|||
} |
|||
|
|||
int value = std::stoi(hex, 0, 16); |
|||
byteTable.push_back((uint8_t)value); |
|||
} |
|||
} catch (const std::exception& e) { |
|||
// printf("ss1\n");
|
|||
return false; |
|||
} |
|||
return true; |
|||
} |
|||
|
|||
/**
|
|||
* @brief |
|||
* |
|||
* @param value |
|||
* @return string |
|||
*/ |
|||
string StringUtils::bytet2Binary(uint32_t value, int bitCount, bool remoteZero) { |
|||
string ret; |
|||
for (int i = 0; i < bitCount; ++i) { |
|||
uint32_t bit = value & 0x01; |
|||
value = value >> 1; |
|||
if (bit == 0) { |
|||
ret = "0" + ret; |
|||
} else { |
|||
ret = "1" + ret; |
|||
} |
|||
} |
|||
if (remoteZero) { |
|||
while (ret.length() > 0 && ret[0] == '0') { |
|||
ret = ret.substr(1, ret.length() - 1); |
|||
} |
|||
} |
|||
return ret; |
|||
} |
|||
|
|||
string StringUtils::bytet2BinaryHumanReadable(uint32_t value, int bitCount) { |
|||
string ret = "("; |
|||
|
|||
for (int i = 0; i < bitCount; ++i) { |
|||
uint32_t bit = value & 0x01; |
|||
value = value >> 1; |
|||
if (bit == 0) { |
|||
ret = "0" + ret; |
|||
} else { |
|||
ret = "1" + ret; |
|||
} |
|||
if ((i + 1) % 4 == 0 && i + 1 < bitCount) { |
|||
ret = " " + ret; |
|||
} |
|||
} |
|||
ret = ret + ")"; |
|||
return ret; |
|||
} |
|||
|
|||
string StringUtils::bytet2BinaryBigEnd(uint32_t value, int bitCount, bool remoteZero) { |
|||
string ret; |
|||
for (int i = 0; i < bitCount; ++i) { |
|||
uint32_t bit = value & 0x01; |
|||
value = value >> 1; |
|||
if (bit == 0) { |
|||
ret = ret + "0"; |
|||
} else { |
|||
ret = ret + "1"; |
|||
} |
|||
} |
|||
if (remoteZero) { |
|||
while (ret.length() > 0 && ret[ret.length() - 1] == '0') { |
|||
ret = ret.substr(0, ret.length() - 1); |
|||
} |
|||
} |
|||
return ret; |
|||
} |
|||
|
|||
string StringUtils::escapeSequence(const string& raw_str) { |
|||
string escaped_str; |
|||
for (const char& ch : raw_str) { |
|||
switch (ch) { |
|||
case '\n': |
|||
escaped_str.append("\\n"); |
|||
break; |
|||
case '\r': |
|||
escaped_str.append("\\r"); |
|||
break; |
|||
case '\t': |
|||
escaped_str.append("\\t"); |
|||
break; |
|||
case '\"': |
|||
escaped_str.append("\\\""); |
|||
break; |
|||
case '\\': |
|||
escaped_str.append("\\\\"); |
|||
break; |
|||
default: |
|||
escaped_str.push_back(ch); |
|||
break; |
|||
} |
|||
} |
|||
return escaped_str; |
|||
} |
|||
|
|||
int32_t StringUtils::split(const string& str, const string& delim, vector<string>& ret) { |
|||
if (str.empty()) { |
|||
return 0; |
|||
} |
|||
string tmp; |
|||
string::size_type pos_begin = str.find_first_not_of(delim); |
|||
string::size_type comma_pos = 0; |
|||
|
|||
while (pos_begin != string::npos) { |
|||
comma_pos = str.find(delim, pos_begin); |
|||
if (comma_pos != string::npos) { |
|||
tmp = str.substr(pos_begin, comma_pos - pos_begin); |
|||
pos_begin = comma_pos + delim.length(); |
|||
} else { |
|||
tmp = str.substr(pos_begin); |
|||
pos_begin = comma_pos; |
|||
} |
|||
|
|||
if (!tmp.empty()) { |
|||
ret.push_back(tmp); |
|||
tmp.clear(); |
|||
} |
|||
} |
|||
return 0; |
|||
} |
@ -1,78 +0,0 @@ |
|||
#include <signal.h>
|
|||
#include <sqlite3.h>
|
|||
#include <stdio.h>
|
|||
#include <stdlib.h>
|
|||
|
|||
#include <fstream>
|
|||
#include <functional>
|
|||
#include <iostream>
|
|||
#include <list>
|
|||
#include <map>
|
|||
#include <memory>
|
|||
#include <set>
|
|||
#include <sstream>
|
|||
#include <string>
|
|||
#include <vector>
|
|||
|
|||
#include "iflytop/components/sqlite_orm/sqlite_orm.hpp"
|
|||
using namespace sqlite_orm; |
|||
|
|||
struct User { |
|||
int id; |
|||
std::string firstName; |
|||
int lastName; |
|||
std::string birthDate; |
|||
std::unique_ptr<std::string> imageUrl; |
|||
int typeId; |
|||
}; |
|||
|
|||
struct UserType { |
|||
int id; |
|||
std::string name; |
|||
}; |
|||
|
|||
int main(int argc, char const *argv[]) { |
|||
sqlite3 *db; |
|||
char *zErrMsg = 0; |
|||
int rc; |
|||
// rc = sqlite3_open("test.db", &db);
|
|||
// if (rc) {
|
|||
// fprintf(stderr, "Can't open database: %s\n", sqlite3_errmsg(db));
|
|||
// exit(0);
|
|||
// } else {
|
|||
// fprintf(stderr, "Opened database successfully\n");
|
|||
// }
|
|||
// sqlite3_close(db);
|
|||
{ |
|||
auto storage = make_storage("./db.sqlite", //
|
|||
make_table("users", //
|
|||
make_column("id", &User::id), //
|
|||
make_column("first_name", &User::firstName), //
|
|||
make_column("last_name", &User::lastName), //
|
|||
make_column("birth_date", &User::birthDate), //
|
|||
make_column("image_url", &User::imageUrl), //
|
|||
make_column("type_id", &User::typeId)), //
|
|||
make_table("user_types", //
|
|||
make_column("id", &UserType::id, primary_key().autoincrement()), //
|
|||
make_column("name", &UserType::name, default_value("name_placeholder")))); |
|||
// storage.dump();
|
|||
// storage.sync_schema(
|
|||
storage.sync_schema(); |
|||
|
|||
storage.filename(); |
|||
std::cout << "storage.filename():" << storage.filename() << std::endl; |
|||
storage.sync_schema(); |
|||
|
|||
storage.insert(User{1, "Nicola", 2, "1856", nullptr, 0}); |
|||
storage.insert(User{-1, "Linus", 2, "1969", nullptr, 0}); |
|||
storage.insert(User{-1, "Mark", 3, "1984", nullptr, 0}); |
|||
|
|||
auto allEmployees = storage.get_all<User>(); |
|||
for (auto &employee : allEmployees) { |
|||
std::cout << employee.id << ' ' << employee.firstName << ' ' << employee.lastName << std::endl; |
|||
} |
|||
// storage.sync_schema();
|
|||
} |
|||
|
|||
return 0; |
|||
} |
Write
Preview
Loading…
Cancel
Save
Reference in new issue