From d349df730e80568a044e0708f523d274a2586295 Mon Sep 17 00:00:00 2001 From: zhaohe Date: Sat, 22 Mar 2025 14:48:13 +0800 Subject: [PATCH] update --- a8000_protocol | 2 +- .../zcanreceiver/socket_can/socket_can.cpp | 893 +++++++++++---------- .../zcanreceiver/socket_can/socket_can.hpp | 347 ++++---- .../zcanreceiver/socket_can/socket_can_frame.cpp | 158 ++-- .../zcanreceiver/socket_can/socket_can_frame.hpp | 128 ++- src/components/zcanreceiver/zcanreceiverhost.cpp | 224 +++--- src/components/zcanreceiver/zcanreceiverhost.hpp | 121 ++- src/extapi_service.cpp | 62 +- src/extapi_service.hpp | 3 +- src/utils/stringutils.cpp | 215 +++++ test_src/testsqldb.cpp | 78 -- 11 files changed, 1194 insertions(+), 1037 deletions(-) create mode 100644 src/utils/stringutils.cpp delete mode 100644 test_src/testsqldb.cpp diff --git a/a8000_protocol b/a8000_protocol index 35b8b7a..e17619d 160000 --- a/a8000_protocol +++ b/a8000_protocol @@ -1 +1 @@ -Subproject commit 35b8b7a4c579bbfae432bc2c789c8564b16aa958 +Subproject commit e17619d6204aa72069968f4763ba5d2238bb645e diff --git a/src/components/zcanreceiver/socket_can/socket_can.cpp b/src/components/zcanreceiver/socket_can/socket_can.cpp index f9468a2..d8bdd8b 100644 --- a/src/components/zcanreceiver/socket_can/socket_can.cpp +++ b/src/components/zcanreceiver/socket_can/socket_can.cpp @@ -1,445 +1,448 @@ -// #include "socket_can.hpp" - -// #include - -// #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 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 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 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) { // -// 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 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 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 lock(m_txState.lock); -// m_txState.txState = kTxing; -// m_txState.txbuf = txpacket; -// } -// void SocketCan::unsetTxStateToTxing() { -// lock_guard 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::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 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 + +#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 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 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 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) { // + 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 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 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 lock(m_txState.lock); + m_txState.txState = kTxing; + m_txState.txbuf = txpacket; +} +void SocketCan::unsetTxStateToTxing() { + lock_guard 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::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 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); + } +} diff --git a/src/components/zcanreceiver/socket_can/socket_can.hpp b/src/components/zcanreceiver/socket_can/socket_can.hpp index a9e30b2..b7da493 100644 --- a/src/components/zcanreceiver/socket_can/socket_can.hpp +++ b/src/components/zcanreceiver/socket_can/socket_can.hpp @@ -1,172 +1,175 @@ -// // -// // Created by zwsd -// // - -// #pragma once -// #include -// #include -// #include -// #include -// #include -// #include -// #include -// #include -// #include -// #include -// #include - -// #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 m_canfilters; // 应用层过滤,这里不要配置 -// }; - -// class SocketCan : public enable_shared_from_this { -// 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 m_thread; -// unique_ptr m_autoRestartThread; -// int m_socketCanFd = -1; -// bool m_startListen = false; - -// shared_ptr 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)> onSocketCanFrame; - -// SocketCan(){}; -// ~SocketCan(); - -// void initialize(shared_ptr socketCanConfig); -// bool isError() { return false; } - -// void startListen(); - -// SocketCanError_t sendFrame(shared_ptr frame, int overtime); -// SocketCanError_t sendFrame(shared_ptr 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 \ No newline at end of file +// +// Created by zwsd +// + +#pragma once +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +#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 m_canfilters; // 应用层过滤,这里不要配置 +}; + +class SocketCan : public enable_shared_from_this { + 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 m_thread; + unique_ptr m_autoRestartThread; + int m_socketCanFd = -1; + bool m_startListen = false; + + shared_ptr 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)> onSocketCanFrame; + + SocketCan(){}; + ~SocketCan(); + + void initialize(shared_ptr socketCanConfig); + bool isError() { return false; } + + void startListen(); + + SocketCanError_t sendFrame(shared_ptr frame, int overtime); + SocketCanError_t sendFrame(shared_ptr 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 \ No newline at end of file diff --git a/src/components/zcanreceiver/socket_can/socket_can_frame.cpp b/src/components/zcanreceiver/socket_can/socket_can_frame.cpp index 48325cf..ca4feab 100644 --- a/src/components/zcanreceiver/socket_can/socket_can_frame.cpp +++ b/src/components/zcanreceiver/socket_can/socket_can_frame.cpp @@ -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::createExtDataFrame(uint32_t id, uint8_t *data, size_t len) { -// shared_ptr canframe = make_shared(); -// 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::createExtDataFrame(uint32_t id, uint8_t *data, size_t len) { + shared_ptr canframe = make_shared(); + 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::createStdDataFrame(uint32_t id, uint8_t *data, size_t len) { -// shared_ptr canframe = make_shared(); -// 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::createStdDataFrame(uint32_t id, uint8_t *data, size_t len) { + shared_ptr canframe = make_shared(); + 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::createExtRemoteFrame(uint32_t id) { -// shared_ptr canframe = make_shared(); -// canframe->m_id = id; -// canframe->m_canIdentifier = socketcan::kextFrame; -// canframe->m_canFrameType = socketcan::kremoteframe; -// canframe->m_dlc = 0; -// return canframe; -// } -// shared_ptr SocketCanFrame::createStdRemoteFrame(uint32_t id) { -// shared_ptr canframe = make_shared(); -// canframe->m_id = id; -// canframe->m_canIdentifier = socketcan::kstdFrame; -// canframe->m_canFrameType = socketcan::kremoteframe; -// canframe->m_dlc = 0; -// return canframe; -// } -// shared_ptr SocketCanFrame::createFrame(canfd_frame_t frame) { -// shared_ptr canframe = make_shared(); -// 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::createExtRemoteFrame(uint32_t id) { + shared_ptr canframe = make_shared(); + canframe->m_id = id; + canframe->m_canIdentifier = socketcan::kextFrame; + canframe->m_canFrameType = socketcan::kremoteframe; + canframe->m_dlc = 0; + return canframe; +} +shared_ptr SocketCanFrame::createStdRemoteFrame(uint32_t id) { + shared_ptr canframe = make_shared(); + canframe->m_id = id; + canframe->m_canIdentifier = socketcan::kstdFrame; + canframe->m_canFrameType = socketcan::kremoteframe; + canframe->m_dlc = 0; + return canframe; +} +shared_ptr SocketCanFrame::createFrame(canfd_frame_t frame) { + shared_ptr canframe = make_shared(); + 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; -// } \ No newline at end of file + 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; +} \ No newline at end of file diff --git a/src/components/zcanreceiver/socket_can/socket_can_frame.hpp b/src/components/zcanreceiver/socket_can/socket_can_frame.hpp index a45d14d..cdb75f5 100644 --- a/src/components/zcanreceiver/socket_can/socket_can_frame.hpp +++ b/src/components/zcanreceiver/socket_can/socket_can_frame.hpp @@ -1,79 +1,77 @@ -// #pragma once -// #include -// #include -// #include -// #include -// #include -// #include -// #include -// #include -// #include +#pragma once +#include +#include +#include +#include +#include +#include +#include +#include +#include -// #include -// #include -// #include -// #include -// #include -// #include -// #include -// #include -// #include +#include +#include +#include +#include +#include +#include +#include +#include +#include -// #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 createExtDataFrame(uint32_t id, uint8_t *data, size_t len); -// static shared_ptr createStdDataFrame(uint32_t id, uint8_t *data, size_t len); -// static shared_ptr createExtRemoteFrame(uint32_t id); -// static shared_ptr createStdRemoteFrame(uint32_t id); -// static shared_ptr createFrame(canfd_frame_t frame); + public: + static shared_ptr createExtDataFrame(uint32_t id, uint8_t *data, size_t len); + static shared_ptr createStdDataFrame(uint32_t id, uint8_t *data, size_t len); + static shared_ptr createExtRemoteFrame(uint32_t id); + static shared_ptr createStdRemoteFrame(uint32_t id); + static shared_ptr 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 diff --git a/src/components/zcanreceiver/zcanreceiverhost.cpp b/src/components/zcanreceiver/zcanreceiverhost.cpp index 8317409..1e9337e 100644 --- a/src/components/zcanreceiver/zcanreceiverhost.cpp +++ b/src/components/zcanreceiver/zcanreceiverhost.cpp @@ -1,105 +1,119 @@ -// #include "zcanreceiverhost.hpp" - -// #include -// #include -// #include -// 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 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 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->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 canframe) { // -// logger->debug("onSocketCanFrame {}", canframe->toString()); -// processRx(canframe); -// }); -// } \ No newline at end of file +#include "zcanreceiverhost.hpp" + +#include +#include +#include +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 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 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->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 canframe) { // + logger->debug("onSocketCanFrame {}", canframe->toString()); + processRx(canframe); + }); +} \ No newline at end of file diff --git a/src/components/zcanreceiver/zcanreceiverhost.hpp b/src/components/zcanreceiver/zcanreceiverhost.hpp index 60d7cbe..4bc343e 100644 --- a/src/components/zcanreceiver/zcanreceiverhost.hpp +++ b/src/components/zcanreceiver/zcanreceiverhost.hpp @@ -1,61 +1,60 @@ -// // -// // Created by zwsd -// // - -// #pragma once -// #include - -// #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 m_canPacket[256]; // 用于接收can消息 -// uint8_t m_rxdata[255 * 8]; -// uint8_t m_canPacketNum = 0; -// uint8_t m_rxdataLen = 0; -// }; - -// typedef function onpacket_t; - -// public: -// uint8_t m_deviceId = 0; -// CanPacketRxBuffer m_canPacketRxBuffer[255]; -// onpacket_t m_onpacket; - -// shared_ptr 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 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 \ No newline at end of file +// +// Created by zwsd +// + +#pragma once +#include + +#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 m_canPacket[256]; // 用于接收can消息 + uint8_t m_rxdata[255 * 8]; + uint8_t m_canPacketNum = 0; + uint8_t m_rxdataLen = 0; + }; + + typedef function onpacket_t; + + public: + uint8_t m_deviceId = 0; + CanPacketRxBuffer m_canPacketRxBuffer[255]; + onpacket_t m_onpacket; + + shared_ptr 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 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 \ No newline at end of file diff --git a/src/extapi_service.cpp b/src/extapi_service.cpp index 5328120..6cdb097 100644 --- a/src/extapi_service.cpp +++ b/src/extapi_service.cpp @@ -2,25 +2,27 @@ #include "configs/project_setting.hpp" #include "configs/version.hpp" +#include "ixwebsocket/IXWebSocketServer.h" +#include "utils/stringutils.hpp" // #include "iflytop/components/zcanreceiver/zcanreceiverhost.hpp" // #include "iflytop/core/components/stringutils.hpp" // #include "iflytop/core/core.hpp" - - using namespace iflytop; using namespace core; using namespace std; using namespace nlohmann; +using namespace ix; + #define BIND namespace iflytop {}; void ExtAPIService::initialize(string can_if_name, int baudrate, bool enablLoopback) { GET_TO_SERVICE(m_zconfig); - // m_zcanreceiverhost.reset(new ZCanReceiverHost()); - // m_zcanreceiverhost->initialize(can_if_name, baudrate, enablLoopback); + m_zcanreceiverhost.reset(new ZCanReceiverHost()); + m_zcanreceiverhost->initialize(can_if_name, baudrate, enablLoopback); initCanPassthroughServer(); }; @@ -33,30 +35,30 @@ void ExtAPIService::initCanPassthroughServer() { * descript: 直接透传CAN数据,不做任何处理 * */ - // m_canPassthroughServer.reset(new WebSocketServer(19005, "0.0.0.0")); - // m_canPassthroughServer->setOnConnectionCallback([this](weak_ptr webSocket, shared_ptr connectionState) { - // logger->info("m_canPassthroughServer on connect remote ip: {}", connectionState->getRemoteIp()); - // auto ws = webSocket.lock(); - // if (!ws) return; - - // ws->setOnMessageCallback([this, webSocket](const ix::WebSocketMessagePtr &msg) { - // if (msg->type == ix::WebSocketMessageType::Message) { - // logger->info("down can bin -> {}({})", msg->str, msg->wireSize); - // vector rxbyte; - // StringUtils().hexStringToBytes(msg->str, "", rxbyte); - // m_zcanreceiverhost->sendPacket(rxbyte.data(), rxbyte.size()); - // } - // }); - // }); - - // m_zcanreceiverhost->registerListener([this](uint8_t fromboardid, uint8_t *packet, size_t len) { - // string hexStr = StringUtils().bytesToString((uint8_t *)packet, len); - // logger->info("up can bin -> {}({})", hexStr, len); - // auto clients = m_canPassthroughServer->getClients(); - // for (auto &each : clients) { - // if (each) each->sendText(hexStr); - // } - // }); - - // m_canPassthroughServer->listenAndStart(); + m_canPassthroughServer.reset(new WebSocketServer(19005, "0.0.0.0")); + m_canPassthroughServer->setOnConnectionCallback([this](weak_ptr webSocket, shared_ptr connectionState) { + logger->info("m_canPassthroughServer on connect remote ip: {}", connectionState->getRemoteIp()); + auto ws = webSocket.lock(); + if (!ws) return; + + ws->setOnMessageCallback([this, webSocket](const ix::WebSocketMessagePtr &msg) { + if (msg->type == ix::WebSocketMessageType::Message) { + logger->info("down can bin -> {}({})", msg->str, msg->wireSize); + vector rxbyte; + StringUtils().hexStringToBytes(msg->str, "", rxbyte); + m_zcanreceiverhost->sendPacket(rxbyte.data(), rxbyte.size()); + } + }); + }); + + m_zcanreceiverhost->registerListener([this](uint8_t fromboardid, uint8_t *packet, size_t len) { + string hexStr = StringUtils().bytesToString((uint8_t *)packet, len); + logger->info("up can bin -> {}({})", hexStr, len); + auto clients = m_canPassthroughServer->getClients(); + for (auto &each : clients) { + if (each) each->sendText(hexStr); + } + }); + + m_canPassthroughServer->listenAndStart(); } diff --git a/src/extapi_service.hpp b/src/extapi_service.hpp index aa0105a..1c1d43c 100644 --- a/src/extapi_service.hpp +++ b/src/extapi_service.hpp @@ -26,6 +26,7 @@ #include "configs/gconfig.hpp" #include "ixwebsocket/IXWebSocketServer.h" #include "spdlogfactory/logger.hpp" +#include "components/zcanreceiver/zcanreceiverhost.hpp" // // @@ -47,7 +48,7 @@ class ExtAPIService { shared_ptr m_zconfig; shared_ptr m_canPassthroughServer; // 19003 - // shared_ptr m_zcanreceiverhost; + shared_ptr m_zcanreceiverhost; public: ExtAPIService() {}; diff --git a/src/utils/stringutils.cpp b/src/utils/stringutils.cpp new file mode 100644 index 0000000..0940675 --- /dev/null +++ b/src/utils/stringutils.cpp @@ -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& 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& 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; +} diff --git a/test_src/testsqldb.cpp b/test_src/testsqldb.cpp deleted file mode 100644 index 681c79f..0000000 --- a/test_src/testsqldb.cpp +++ /dev/null @@ -1,78 +0,0 @@ -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#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 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(); - for (auto &employee : allEmployees) { - std::cout << employee.id << ' ' << employee.firstName << ' ' << employee.lastName << std::endl; - } - // storage.sync_schema(); - } - - return 0; -}