diff --git a/.project/cmake/target.cmake b/.project/cmake/target.cmake index aa6ec03..7d174ce 100644 --- a/.project/cmake/target.cmake +++ b/.project/cmake/target.cmake @@ -11,12 +11,13 @@ zadd_executable_simple( app.out SRC src/main.cpp # - src/test/socketcan.cpp + # src/test/socketcan.cpp src/service/main_control_service.cpp # src/service/iflytop_hardware_ws_service.cpp # ) zadd_executable_simple(TARGET test_demo.out SRC src/test/test_demo.cpp) -zadd_executable_simple(TARGET test_can.out SRC src/test/test_can.cpp - src/test/socketcan.cpp) +zadd_executable_simple(TARGET test_can.out SRC src/test/test_can.cpp) +zadd_executable_simple(TARGET dump_can_driver_info.out SRC + src/test/dump_can_driver_info.cpp) diff --git a/dep/iflytopcpp b/dep/iflytopcpp index 5199d0a..f186de7 160000 --- a/dep/iflytopcpp +++ b/dep/iflytopcpp @@ -1 +1 @@ -Subproject commit 5199d0a9ee175f8254d13ec9436be0f9f67e83d5 +Subproject commit f186de7700bf4550ce2420d1cd87d43a5a1bfc39 diff --git a/src/test/dump_can_driver_info.cpp b/src/test/dump_can_driver_info.cpp new file mode 100644 index 0000000..6efbdf9 --- /dev/null +++ b/src/test/dump_can_driver_info.cpp @@ -0,0 +1,49 @@ +#include + +#include "zlinuxcomponents/zmainhelper.hpp" +// +#include "iflytopcpp/core/spdlogfactory/logger.hpp" +#include "iflytopcpp/core/thread/thread.hpp" +#include "spdlog/spdlog.h" +// + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "iflytopcpp/core/driver/socketcan/socket_can.hpp" + +using namespace iflytop; +using namespace core; +using namespace std; +using namespace clipp; + +class Main { + ENABLE_LOGGER(Main); + unique_ptr thread; + shared_ptr socketCan; + + public: + Main(/* args */) {} + ~Main() {} + void run(int argc, char* argv[]) { + thread.reset(new Thread("main", [&]() { exit(main(argc, argv)); })); + while (true) sleep(1000); + } + void onSIGINT() { exit(0); } + int main(int argCount, char* argValues[]) { + if (argCount < 3) { + logger->info("Usage: {} canName canBaudrate", argValues[0]); + return 1; + } + SocketCan::dumpCanDriverInfo(argValues[1], atoi(argValues[2])); + return 0; + } +}; +MAIN_ENTRY(); diff --git a/src/test/socketcan.cpp b/src/test/socketcan.cpp deleted file mode 100644 index 6009cc0..0000000 --- a/src/test/socketcan.cpp +++ /dev/null @@ -1,387 +0,0 @@ -#include "socketcan.hpp" - -#include -#include - -#include "iflytopcpp/core/components/stringutils.hpp" -// -using namespace iflytop; -#define CANID_DELIM '#' -#define CC_DLC_DELIM '_' -#define DATA_SEPERATOR '.' -#define CAN_MAX_DLC 8 -#define CAN_MAX_RAW_DLC 15 -#define CAN_MAX_DLEN 8 -unsigned char asc2nibble(char c) { - if ((c >= '0') && (c <= '9')) return c - '0'; - if ((c >= 'A') && (c <= 'F')) return c - 'A' + 10; - if ((c >= 'a') && (c <= 'f')) return c - 'a' + 10; - return 16; /* error */ -} - -/******************************************************************************* - * can_frame_t * - *******************************************************************************/ - -shared_ptr CanFrame::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 = kextFrame; - canframe->m_canFrameType = kdataframe; - canframe->m_dlc = len; - memcpy(canframe->m_data, data, len); - return canframe; -} - -shared_ptr CanFrame::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 = kstdFrame; - canframe->m_canFrameType = kdataframe; - canframe->m_dlc = len; - memcpy(canframe->m_data, data, len); - return canframe; -} - -shared_ptr CanFrame::createExtRemoteFrame(uint32_t id) { - shared_ptr canframe = make_shared(); - canframe->m_id = id; - canframe->m_canIdentifier = kextFrame; - canframe->m_canFrameType = kremoteframe; - canframe->m_dlc = 0; - return canframe; -} -shared_ptr CanFrame::createStdRemoteFrame(uint32_t id) { - shared_ptr canframe = make_shared(); - canframe->m_id = id; - canframe->m_canIdentifier = kstdFrame; - canframe->m_canFrameType = kremoteframe; - canframe->m_dlc = 0; - return canframe; -} -void CanFrame::setCanIdentifier(can_identifier_t canIdentifier) { this->m_canIdentifier = canIdentifier; } -void CanFrame::setFanFrameType(can_frame_type_t fanFrameType) { this->m_canFrameType = fanFrameType; } -void CanFrame::setId(uint32_t id) { this->m_id = id; } - -uint32_t CanFrame::getId() { return m_id; } -can_identifier_t CanFrame::getCanIdentifier() { return m_canIdentifier; } -can_frame_type_t CanFrame::getFanFrameType() { return m_canFrameType; } - -/******************************************************************************* - * SocketCan * - *******************************************************************************/ -#if 0 - int s, nbytes; - struct sockaddr_can addr; - struct ifreq ifr; - struct can_frame frame[2] = {{0}}; - s = socket(PF_CAN, SOCK_RAW, CAN_RAW); - printf("send_s = %d\n", s); - strcpy(ifr.ifr_name, "can0"); - ioctl(s, SIOCGIFINDEX, &ifr); - addr.can_family = AF_CAN; - addr.can_ifindex = ifr.ifr_ifindex; - bind(s, (struct sockaddr *)&addr, sizeof(addr)); - - setsockopt(s, SOL_CAN_RAW, CAN_RAW_FILTER, NULL, 0); - - frame[0].can_id = 0x11; - frame[0].can_dlc = 1; - frame[0].data[0] = 'Y'; - frame[1].can_id = 0x410; - frame[1].can_dlc = 1; - frame[1].data[0] = 'N'; - - while (1) { - nbytes = write(s, &frame[0], sizeof(frame[0])); - if (nbytes != sizeof(frame[0])) { - printf("Send Error frame[0]!\n"); - break; - } - - sleep(1); - - nbytes = write(s, &frame[1], sizeof(frame[1])); - if (nbytes != sizeof(frame[1])) { - printf("Send Error frame[1]!\n"); - break; - } - - sleep(1); - } - - close(s); -#endif - -bool SocketCan::findCan(string canName) { return access(fmt::format("/sys/class/net/{}", canName).c_str(), F_OK) == 0; } - -bool SocketCan::initialize(string canName, int bitrate, vector filters) { - m_canName = canName; - if (findCan(canName) == false) { - logger->error("can {} not found", canName); - return false; - } - - // setCanBitrate(canName, bitrate); - - m_canfd = socket(PF_CAN, SOCK_RAW, CAN_RAW); - if (m_canfd < 0) { - logger->error("socket failed,{}", strerror(errno)); - return false; - } - - struct ifreq ifr = {0}; - strcpy(ifr.ifr_name, canName.c_str()); - ioctl(m_canfd, SIOCGIFINDEX, &ifr); - - const int bufsize = 0; - if (setsockopt(m_canfd, SOL_SOCKET, SO_SNDBUF, &bufsize, sizeof(bufsize)) != 0) { - logger->error("setsockopt SO_SNDBUF fail,{}", strerror(errno)); - return -1; - } - - struct sockaddr_can addr = {0}; - addr.can_family = AF_CAN; - addr.can_ifindex = ifr.ifr_ifindex; - if (bind(m_canfd, (struct sockaddr *)&addr, sizeof(addr)) < 0) { - logger->error("bind fail,{}", strerror(errno)); - return false; - } - - if (!filters.empty()) { - if (setsockopt(m_canfd, SOL_CAN_RAW, CAN_RAW_FILTER, filters.data(), filters.size() * sizeof(struct can_filter)) != 0) { - logger->error("set filters fail,{}", strerror(errno)); - return false; - }; - } else { - can_filter_t filter = {0}; - filter.can_id = 0; - filter.can_mask = 0; - if (setsockopt(m_canfd, SOL_CAN_RAW, CAN_RAW_FILTER, &filter, sizeof(filter)) != 0) { - logger->error("set filters fail,{}", strerror(errno)); - return false; - }; - } - - return true; -} - -int SocketCan::sendFrame(shared_ptr frame) { - if (frame == nullptr) { - logger->error("frame is null"); - return -1; - } - if (m_canfd < 0) { - logger->error("canfd is invalid"); - return -1; - } - - canfd_frame_t canframe = frame->getCanFrame(); - - int ret = write(m_canfd, &canframe, canframe.len + 8); - if (ret != (canframe.len + 8)) { - logger->error("write fail,{}", strerror(errno)); - return -1; - } - return 0; -} -#if 0 -struct canfd_frame { - canid_t can_id; /* 32 bit CAN_ID + EFF/RTR/ERR flags */ - __u8 len; /* frame payload length in byte */ - __u8 flags; /* additional flags for CAN FD */ - __u8 __res0; /* reserved / padding */ - __u8 __res1; /* reserved / padding */ - __u8 data[CANFD_MAX_DLEN] __attribute__((aligned(8))); -}; -#endif - -void SocketCan::startListen() { - m_thread.reset( // - new Thread(fmt::format("SocketCan_{}_ListenThread", m_canName), // - [this]() { - ThisThread thisThread; - fd_set readfds, readFileDescriptors; - FD_ZERO(&readFileDescriptors); - FD_SET(m_canfd, &readFileDescriptors); - - while (!thisThread.getExitFlag()) { - canfd_frame_t canframe; - struct canfd_frame frame; - - timeval waitTime; - waitTime.tv_sec = 3; - waitTime.tv_usec = 0; - - readfds = readFileDescriptors; - - int n = select(m_canfd + 1, &readfds, 0, 0, &waitTime); - logger->info("select.... {}", n); - if (n <= 0) { - continue; - } - - memset(&canframe, 0x00, sizeof(canframe)); - int ret = read(m_canfd, &canframe, sizeof(canframe)); - // if (ret != sizeof(canframe)) { - // logger->error("read fail,{}", strerror(errno)); - // continue; - // } - - logger->info("RX({}):{}", ret, StringUtils().bytesToString((uint8_t *)&canframe, ret)); - } - })); -} -canfd_frame_t CanFrame::getCanFrame() { - canfd_frame_t frame; -#if 1 - memset(&frame, 0, sizeof(frame)); - - if (m_canIdentifier == kstdFrame) { - frame.can_id = (m_id & CAN_SFF_MASK); - } else { - frame.can_id = (m_id & CAN_EFF_MASK) | CAN_EFF_FLAG; - } - - if (m_canFrameType == kremoteframe) { - frame.can_id |= CAN_RTR_FLAG; - frame.len = m_dlc; - } else { - frame.len = m_dlc; - memcpy(frame.data, m_data, m_dlc); - } -#endif - return frame; -} - -int SocketCan::parse_canframe(char *cs, struct canfd_frame *cf) { - /* documentation see lib.h */ - - int i, idx, dlen, len; - int maxdlen = CAN_MAX_DLEN; - int ret = CAN_MTU; - canid_t tmp; - - len = strlen(cs); - // printf("'%s' len %d\n", cs, len); - - memset(cf, 0, sizeof(*cf)); /* init CAN FD frame, e.g. LEN = 0 */ - - if (len < 4) return 0; - - if (cs[3] == CANID_DELIM) { /* 3 digits */ - - idx = 4; - for (i = 0; i < 3; i++) { - if ((tmp = asc2nibble(cs[i])) > 0x0F) return 0; - cf->can_id |= (tmp << (2 - i) * 4); - } - - } else if (cs[8] == CANID_DELIM) { /* 8 digits */ - - idx = 9; - for (i = 0; i < 8; i++) { - if ((tmp = asc2nibble(cs[i])) > 0x0F) return 0; - cf->can_id |= (tmp << (7 - i) * 4); - } - if (!(cf->can_id & CAN_ERR_FLAG)) /* 8 digits but no errorframe? */ - cf->can_id |= CAN_EFF_FLAG; /* then it is an extended frame */ - - } else - return 0; - - if ((cs[idx] == 'R') || (cs[idx] == 'r')) { /* RTR frame */ - cf->can_id |= CAN_RTR_FLAG; - - /* check for optional DLC value for CAN 2.0B frames */ - if (cs[++idx] && (tmp = asc2nibble(cs[idx++])) <= CAN_MAX_DLEN) { - cf->len = tmp; - - /* check for optional raw DLC value for CAN 2.0B frames */ - if ((tmp == CAN_MAX_DLEN) && (cs[idx++] == CC_DLC_DELIM)) { - tmp = asc2nibble(cs[idx]); - if ((tmp > CAN_MAX_DLEN) && (tmp <= CAN_MAX_RAW_DLC)) { - struct can_frame *ccf = (struct can_frame *)cf; - - ccf->__res1 = tmp; - } - } - } - return ret; - } - - if (cs[idx] == CANID_DELIM) { /* CAN FD frame escape char '##' */ - - maxdlen = CANFD_MAX_DLEN; - ret = CANFD_MTU; - - /* CAN FD frame ##* */ - if ((tmp = asc2nibble(cs[idx + 1])) > 0x0F) return 0; - - cf->flags = tmp; - idx += 2; - } - - for (i = 0, dlen = 0; i < maxdlen; i++) { - if (cs[idx] == DATA_SEPERATOR) /* skip (optional) separator */ - idx++; - - if (idx >= len) /* end of string => end of data */ - break; - - if ((tmp = asc2nibble(cs[idx++])) > 0x0F) return 0; - cf->data[i] = (tmp << 4); - if ((tmp = asc2nibble(cs[idx++])) > 0x0F) return 0; - cf->data[i] |= tmp; - dlen++; - } - cf->len = dlen; - - /* check for extra DLC when having a Classic CAN with 8 bytes payload */ - if ((maxdlen == CAN_MAX_DLEN) && (dlen == CAN_MAX_DLEN) && (cs[idx++] == CC_DLC_DELIM)) { - unsigned char dlc = asc2nibble(cs[idx]); - - if ((dlc > CAN_MAX_DLEN) && (dlc <= CAN_MAX_RAW_DLC)) { - struct can_frame *ccf = (struct can_frame *)cf; - - ccf->__res1 = dlc; - } - } - - return ret; -} - -int SocketCan::sendFrame(string framestr) { - struct canfd_frame frame; - int required_mtu; - required_mtu = parse_canframe((char *)framestr.c_str(), &frame); - if (!required_mtu) { - logger->error("Wrong CAN-frame format!"); - return -1; - } - - if (required_mtu > (int)CAN_MTU) { - logger->error("CAN-FD frames not supported!"); - return -1; - } - logger->info("send frame:{} {} {} {} {} {}", required_mtu, frame.can_id, frame.len, frame.flags, frame.__res0, frame.__res1); - if (write(m_canfd, &frame, required_mtu) != required_mtu) { - logger->error("CAN-FD frames not supported!"); - return -1; - } - return 0; -} - -void SocketCan::dosystem(string cmd) { - logger->info("do cmd:{}", cmd); - system(cmd.c_str()); -} - -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)); -} diff --git a/src/test/socketcan.hpp b/src/test/socketcan.hpp deleted file mode 100644 index 0198485..0000000 --- a/src/test/socketcan.hpp +++ /dev/null @@ -1,129 +0,0 @@ -// -// Created by zwsd -// - -#pragma once -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "iflytopcpp/core/basic/nod/nod.hpp" -#include "iflytopcpp/core/spdlogfactory/logger.hpp" -#include "iflytopcpp/core/thread/thread.hpp" - -/** - * @brief - * - * service: SocketCan - * - * 监听事件: - * 依赖状态: - * 依赖服务: - * 作用: - * - */ - -namespace iflytop { -using namespace std; -using namespace core; - -/******************************************************************************* - * CAN_FRAME * - *******************************************************************************/ - -typedef struct can_filter can_filter_t; -typedef struct canfd_frame canfd_frame_t; -typedef enum { - kstdFrame, - kextFrame, -} can_identifier_t; - -typedef enum { - kdataframe, - kremoteframe, -} can_frame_type_t; - -class CanFrame { - private: - uint32_t m_id = 0; - can_identifier_t m_canIdentifier = kstdFrame; - can_frame_type_t m_canFrameType = 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); - - void setId(uint32_t id); - uint32_t getId(); - can_frame_type_t getFanFrameType(); - void setFanFrameType(can_frame_type_t fanFrameType); - can_identifier_t getCanIdentifier(); - void setCanIdentifier(can_identifier_t canIdentifier); - - canfd_frame_t getCanFrame(); -}; - -/******************************************************************************* - * SocketCan * - *******************************************************************************/ - -class SocketCan { - ENABLE_LOGGER(SocketCan); - - string m_canName; - int m_canfd; - vector m_canfilters; - unique_ptr m_thread; - - public: - nod::signal canframe)> signalOnFrame; - - public: - SocketCan(){}; - bool initialize(string canName, int bitrate, vector filters); - int sendFrame(shared_ptr frame); - /** - * @brief 发送can帧 - * - * @param frame - * frame="11111111#1122334455667788" ID=0x11111111,帧类型=数据帧,帧格式=扩展帧,数据长度=8,数据=1122334455667788 - * frame="111#1122334455667788" ID=0x111, 帧类型=数据帧,帧格式=标准帧,数据长度=8,数据=1122334455667788 - * frame="111#R" ID=0x111, 帧类型=远程帧,帧格式=标准帧,数据长度=0 - * frame="11111111#R" ID=0x11111111,帧类型=远程帧,帧格式=扩展帧,数据长度=0 - * @return int - */ - int sendFrame(string frame); - void startListen(); - ~SocketCan() { - if (m_canfd > 0) { - close(m_canfd); - } - } - - private: - void dosystem(string cmd); - void setCanBitrate(string canName, int bitrate); - bool findCan(string canName); - int parse_canframe(char *cs, struct canfd_frame *cf); -}; -} // namespace iflytop \ No newline at end of file diff --git a/src/test/test_can.cpp b/src/test/test_can.cpp index d9aab42..62b3366 100644 --- a/src/test/test_can.cpp +++ b/src/test/test_can.cpp @@ -2,7 +2,6 @@ #include "zlinuxcomponents/zmainhelper.hpp" // -#include "iflytopcpp/core/driver/sockcanpp/CanDriver.hpp" #include "iflytopcpp/core/spdlogfactory/logger.hpp" #include "iflytopcpp/core/thread/thread.hpp" #include "spdlog/spdlog.h" @@ -18,18 +17,12 @@ #include #include -// #include "iflytopcpp/core/driver/sockcanpp/CanDriver.hpp" -// #include "iflytopcpp/core/driver/sockcanpp/exceptions/CanException.hpp" -// #include "iflytopcpp/core/driver/sockcanpp/exceptions/CanInitException.hpp" -// #include "iflytopcpp/core/driver/sockcanpp/exceptions/InvalidSocketException.hpp" - -#include "socketcan.hpp" +#include "iflytopcpp/core/driver/socketcan/socket_can.hpp" using namespace iflytop; using namespace core; using namespace std; using namespace clipp; -using namespace sockcanpp; // using sockcanpp::CanDriver; // using sockcanpp::CanId; @@ -57,35 +50,25 @@ class Main { } void onSIGINT() { exit(0); } int main(int argCount, char* argValues[]) { - socketCan.reset(new SocketCan()); - socketCan->initialize("can0", 500000, {}); + shared_ptr socketCanConfig = make_shared(); + socketCanConfig->m_canName = "can0"; + socketCanConfig->m_canBaudrate = 500000; + socketCanConfig->enablLoopback = false; + + socketCan->initialize(socketCanConfig); socketCan->startListen(); - socketCan->signalOnFrame.connect([this](shared_ptr canframe) { - if (canframe) { - // logger->info("Rx: {}", canframe->toString()); - logger->info("RX Frame"); - } - }); + socketCan->onSocketCanFrame.connect([this](shared_ptr frame) { logger->info("RX:{}", frame->toString()); }); ThisThread thisThread; int i = 0; while (!thisThread.getExitFlag()) { - thisThread.sleepForMs(10); - uint8_t data[8] = {1, 2, 3, 4, 5, 6, 7, 8}; - shared_ptr canframe = CanFrame::createExtDataFrame(0x11223344, data, 8); + uint8_t data[8] = {1, 2, 3, 4, 5, 6, 7, 8}; + shared_ptr canframe = SocketCanFrame::createExtDataFrame(0x11223344, data, 8); logger->info("TX Frame {}", i); - socketCan->sendFrame(canframe); + socketCan->sendFrame(canframe, 5); i++; - if (i == 30) { - break; - } - -#if 0 - socketCan->sendFrame("11111111#1122334455667788"); - logger->info("TX Frame"); -#endif } while (true) { sleep(1000);