Browse Source

udpate iflytopcpp

master
zhaohe 2 years ago
parent
commit
9ee71b6718
  1. 7
      .project/cmake/target.cmake
  2. 2
      dep/iflytopcpp
  3. 49
      src/test/dump_can_driver_info.cpp
  4. 387
      src/test/socketcan.cpp
  5. 129
      src/test/socketcan.hpp
  6. 39
      src/test/test_can.cpp

7
.project/cmake/target.cmake

@ -11,12 +11,13 @@ zadd_executable_simple(
app.out app.out
SRC SRC
src/main.cpp # src/main.cpp #
src/test/socketcan.cpp
# src/test/socketcan.cpp
src/service/main_control_service.cpp # src/service/main_control_service.cpp #
src/service/iflytop_hardware_ws_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_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)

2
dep/iflytopcpp

@ -1 +1 @@
Subproject commit 5199d0a9ee175f8254d13ec9436be0f9f67e83d5
Subproject commit f186de7700bf4550ce2420d1cd87d43a5a1bfc39

49
src/test/dump_can_driver_info.cpp

@ -0,0 +1,49 @@
#include <stdio.h>
#include "zlinuxcomponents/zmainhelper.hpp"
//
#include "iflytopcpp/core/spdlogfactory/logger.hpp"
#include "iflytopcpp/core/thread/thread.hpp"
#include "spdlog/spdlog.h"
//
#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 "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> thread;
shared_ptr<SocketCan> 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();

387
src/test/socketcan.cpp

@ -1,387 +0,0 @@
#include "socketcan.hpp"
#include <linux/can.h>
#include <linux/can/raw.h>
#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> CanFrame::createExtDataFrame(uint32_t id, uint8_t *data, size_t len) {
shared_ptr<CanFrame> canframe = make_shared<CanFrame>();
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> CanFrame::createStdDataFrame(uint32_t id, uint8_t *data, size_t len) {
shared_ptr<CanFrame> canframe = make_shared<CanFrame>();
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> CanFrame::createExtRemoteFrame(uint32_t id) {
shared_ptr<CanFrame> canframe = make_shared<CanFrame>();
canframe->m_id = id;
canframe->m_canIdentifier = kextFrame;
canframe->m_canFrameType = kremoteframe;
canframe->m_dlc = 0;
return canframe;
}
shared_ptr<CanFrame> CanFrame::createStdRemoteFrame(uint32_t id) {
shared_ptr<CanFrame> canframe = make_shared<CanFrame>();
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<can_filter_t> 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<CanFrame> 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 <canid>##<flags><data>* */
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));
}

129
src/test/socketcan.hpp

@ -1,129 +0,0 @@
//
// Created by zwsd
//
#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 "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<CanFrame> createExtDataFrame(uint32_t id, uint8_t *data, size_t len);
static shared_ptr<CanFrame> createStdDataFrame(uint32_t id, uint8_t *data, size_t len);
static shared_ptr<CanFrame> createExtRemoteFrame(uint32_t id);
static shared_ptr<CanFrame> 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<can_filter_t> m_canfilters;
unique_ptr<Thread> m_thread;
public:
nod::signal<void(shared_ptr<CanFrame> canframe)> signalOnFrame;
public:
SocketCan(){};
bool initialize(string canName, int bitrate, vector<can_filter_t> filters);
int sendFrame(shared_ptr<CanFrame> 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

39
src/test/test_can.cpp

@ -2,7 +2,6 @@
#include "zlinuxcomponents/zmainhelper.hpp" #include "zlinuxcomponents/zmainhelper.hpp"
// //
#include "iflytopcpp/core/driver/sockcanpp/CanDriver.hpp"
#include "iflytopcpp/core/spdlogfactory/logger.hpp" #include "iflytopcpp/core/spdlogfactory/logger.hpp"
#include "iflytopcpp/core/thread/thread.hpp" #include "iflytopcpp/core/thread/thread.hpp"
#include "spdlog/spdlog.h" #include "spdlog/spdlog.h"
@ -18,18 +17,12 @@
#include <sys/socket.h> #include <sys/socket.h>
#include <unistd.h> #include <unistd.h>
// #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 iflytop;
using namespace core; using namespace core;
using namespace std; using namespace std;
using namespace clipp; using namespace clipp;
using namespace sockcanpp;
// using sockcanpp::CanDriver; // using sockcanpp::CanDriver;
// using sockcanpp::CanId; // using sockcanpp::CanId;
@ -57,35 +50,25 @@ class Main {
} }
void onSIGINT() { exit(0); } void onSIGINT() { exit(0); }
int main(int argCount, char* argValues[]) { int main(int argCount, char* argValues[]) {
socketCan.reset(new SocketCan()); socketCan.reset(new SocketCan());
socketCan->initialize("can0", 500000, {});
shared_ptr<SocketCanConfig> socketCanConfig = make_shared<SocketCanConfig>();
socketCanConfig->m_canName = "can0";
socketCanConfig->m_canBaudrate = 500000;
socketCanConfig->enablLoopback = false;
socketCan->initialize(socketCanConfig);
socketCan->startListen(); socketCan->startListen();
socketCan->signalOnFrame.connect([this](shared_ptr<CanFrame> canframe) {
if (canframe) {
// logger->info("Rx: {}", canframe->toString());
logger->info("RX Frame");
}
});
socketCan->onSocketCanFrame.connect([this](shared_ptr<SocketCanFrame> frame) { logger->info("RX:{}", frame->toString()); });
ThisThread thisThread; ThisThread thisThread;
int i = 0; int i = 0;
while (!thisThread.getExitFlag()) { while (!thisThread.getExitFlag()) {
thisThread.sleepForMs(10);
uint8_t data[8] = {1, 2, 3, 4, 5, 6, 7, 8};
shared_ptr<CanFrame> canframe = CanFrame::createExtDataFrame(0x11223344, data, 8);
uint8_t data[8] = {1, 2, 3, 4, 5, 6, 7, 8};
shared_ptr<SocketCanFrame> canframe = SocketCanFrame::createExtDataFrame(0x11223344, data, 8);
logger->info("TX Frame {}", i); logger->info("TX Frame {}", i);
socketCan->sendFrame(canframe);
socketCan->sendFrame(canframe, 5);
i++; i++;
if (i == 30) {
break;
}
#if 0
socketCan->sendFrame("11111111#1122334455667788");
logger->info("TX Frame");
#endif
} }
while (true) { while (true) {
sleep(1000); sleep(1000);

Loading…
Cancel
Save