Browse Source

update

master
zhaohe 4 months ago
parent
commit
d349df730e
  1. 2
      a8000_protocol
  2. 893
      src/components/zcanreceiver/socket_can/socket_can.cpp
  3. 347
      src/components/zcanreceiver/socket_can/socket_can.hpp
  4. 158
      src/components/zcanreceiver/socket_can/socket_can_frame.cpp
  5. 128
      src/components/zcanreceiver/socket_can/socket_can_frame.hpp
  6. 224
      src/components/zcanreceiver/zcanreceiverhost.cpp
  7. 121
      src/components/zcanreceiver/zcanreceiverhost.hpp
  8. 62
      src/extapi_service.cpp
  9. 3
      src/extapi_service.hpp
  10. 215
      src/utils/stringutils.cpp
  11. 78
      test_src/testsqldb.cpp

2
a8000_protocol

@ -1 +1 @@
Subproject commit 35b8b7a4c579bbfae432bc2c789c8564b16aa958
Subproject commit e17619d6204aa72069968f4763ba5d2238bb645e

893
src/components/zcanreceiver/socket_can/socket_can.cpp

@ -1,445 +1,448 @@
// #include "socket_can.hpp"
// #include <linux/can/error.h>
// #include "iflytop/core/components/stringutils.hpp"
// using namespace iflytop;
// #define DO(exptr) \
// do { \
// if ((exptr) != 0) { \
// logger->error("do {} failed,{}", #exptr, strerror(errno)); \
// goto error; \
// } \
// } while (0)
// SocketCan::SocketCanError_t SocketCan::sendFrame(shared_ptr<SocketCanFrame> frame) {
// if (!m_canBusIsReady) {
// return kDeviceBusy;
// }
// if (frame == nullptr) {
// logger->error("frame is null");
// return kParamError;
// }
// if (isTxing()) {
// logger->error("txing, can't send frame");
// return kDeviceBusy;
// }
// canfd_frame_t canframe = frame->getCanFrame();
// return writeFrame(canframe);
// }
// SocketCan::SocketCanError_t SocketCan::writeFrame(const canfd_frame_t &_frame) {
// if (!m_canBusIsReady) {
// return kDeviceBusy;
// }
// canfd_frame_t txframe = _frame;
// txframe.can_id |= 0x10000000;
// setTxStateToTxing(txframe);
// int ret = write(m_socketCanFd, &txframe, 16);
// if (ret != (16)) {
// logger->error("write fail,{}", strerror(errno));
// unsetTxStateToTxing();
// return kWriteError;
// }
// return kSuccess;
// }
// SocketCan::SocketCanError_t SocketCan::sendFrame(shared_ptr<SocketCanFrame> frame, int overtime) {
// tp_steady start = tu_steady().now();
// while (tu_steady().elapsedTimeMs(start) < overtime && !m_canBusIsReady) {
// usleep(100);
// }
// if (!m_canBusIsReady) {
// return kOvertime;
// }
// while (tu_steady().elapsedTimeMs(start) < overtime && isTxing()) {
// usleep(100);
// }
// if (isTxing()) {
// logger->error("send frame overtime");
// return kOvertime;
// }
// return sendFrame(frame);
// }
// bool SocketCan::isTxing() { return m_txState.txState == kTxing; }
// bool SocketCan::isTxFrame(const canfd_frame_t &frame) {
// lock_guard<recursive_mutex> lock(m_txState.lock);
// if (m_txState.txbuf.can_id == frame.can_id && m_txState.txbuf.len == frame.len && memcmp(m_txState.txbuf.data, frame.data, frame.len) == 0) {
// return true;
// }
// return false;
// }
// void SocketCan::initialize(shared_ptr<SocketCanConfig> socketCanConfig) { //
// ZCHECK(socketCanConfig, "socketCanConfig is null");
// m_socketCanConfig = socketCanConfig;
// socketcanInitialize();
// }
// SocketCan::~SocketCan() {
// if (m_thread) {
// endListenThread();
// }
// if (m_socketCanFd > 0) {
// close(m_socketCanFd);
// m_socketCanFd = -1;
// }
// }
// void SocketCan::startListen() { startListenThread(); }
// void SocketCan::socketcanReInitialize() {}
// void SocketCan::startListenThread() {
// if (m_thread) {
// endListenThread();
// return;
// }
// logger->info("startListenThread");
// m_thread.reset(new Thread("SocketCanThread", [this]() {
// /**
// * @brief call socketCanReadThreadLoop
// */
// socketCanReadThreadLoop();
// }));
// m_canBusIsReady = true;
// m_autoRestartThread.reset(new Thread("SocketCanAutoRestartThread", [this]() { monitorLoop(); }));
// }
// void SocketCan::endListenThread() {
// logger->info("endListenThread");
// if (m_thread) {
// m_thread->join();
// m_thread = nullptr;
// }
// }
// void SocketCan::socketcanInitialize() {
// // setCanBitrate(canName, bitrate);
// struct ifreq ifr = {0};
// struct sockaddr_can addr = {0};
// can_filter_t zerofilter = {0};
// int recv_own_msgs = 0; /* 0 = disabled (default), 1 = enabled */
// int localloop = 0;
// vector<can_filter_t> filters = m_socketCanConfig->m_canfilters;
// can_err_mask_t err_mask = 0;
// if (!findCan(m_socketCanConfig->m_canName)) {
// logger->error("can:{} not found", m_socketCanConfig->m_canName);
// return;
// }
// if (m_thread) endListenThread();
// if (m_socketCanFd > 0) socketcanDeInitialize();
// logger->info("socketcanInitialize,canName:{},canBaudrate:{}", m_socketCanConfig->m_canName, m_socketCanConfig->m_canBaudrate);
// // 配置socketCan波特率,注意该方法必须放在socket之前
// setCanBitrate(m_socketCanConfig->m_canName, m_socketCanConfig->m_canBaudrate);
// // SOCKET
// m_socketCanFd = socket(PF_CAN, SOCK_RAW, CAN_RAW);
// if (m_socketCanFd < 0) {
// logger->error("socket failed,{}", strerror(errno));
// goto error;
// }
// // 设置依靠名字绑定CAN设备
// strcpy(ifr.ifr_name, m_socketCanConfig->m_canName.c_str());
// DO(ioctl(m_socketCanFd, SIOCGIFINDEX, &ifr));
// // BIND
// addr.can_family = AF_CAN;
// addr.can_ifindex = ifr.ifr_ifindex;
// DO(bind(m_socketCanFd, (struct sockaddr *)&addr, sizeof(addr)));
// // 设置过滤器,默认不过滤
// DO(setsockopt(m_socketCanFd, SOL_CAN_RAW, CAN_RAW_FILTER, &zerofilter, sizeof(zerofilter)));
// if (m_socketCanConfig->enablLoopback) {
// localloop = 1; /* 0 = disabled (default), 1 = enabled */
// DO(setsockopt(m_socketCanFd, SOL_CAN_RAW, CAN_RAW_LOOPBACK, &localloop, sizeof(localloop)));
// recv_own_msgs = 1; /* 0 = disabled (default), 1 = enabled */
// DO(setsockopt(m_socketCanFd, SOL_CAN_RAW, CAN_RAW_RECV_OWN_MSGS, &recv_own_msgs, sizeof(recv_own_msgs)));
// } else {
// localloop = 0; /* 0 = disabled (default), 1 = enabled */
// DO(setsockopt(m_socketCanFd, SOL_CAN_RAW, CAN_RAW_LOOPBACK, &localloop, sizeof(localloop)));
// recv_own_msgs = 0; /* 0 = disabled (default), 1 = enabled */
// DO(setsockopt(m_socketCanFd, SOL_CAN_RAW, CAN_RAW_RECV_OWN_MSGS, &recv_own_msgs, sizeof(recv_own_msgs)));
// }
// err_mask = CAN_ERR_TX_TIMEOUT | //
// CAN_ERR_LOSTARB | //
// CAN_ERR_CRTL | //
// CAN_ERR_PROT | //
// CAN_ERR_TRX | //
// CAN_ERR_ACK | //
// CAN_ERR_BUSOFF | //
// CAN_ERR_BUSERROR | //
// CAN_ERR_RESTARTED;
// setsockopt(m_socketCanFd, SOL_CAN_RAW, CAN_RAW_ERR_FILTER, &err_mask, sizeof(err_mask));
// logger->info("socketcan init success");
// return;
// error:
// logger->error("socketcan init failed");
// if (m_socketCanFd > 0) {
// close(m_socketCanFd);
// m_socketCanFd = -1;
// }
// return;
// }
// void SocketCan::socketcanDeInitialize() {}
// void SocketCan::canReadThread() {}
// void SocketCan::setCanBitrate(string canName, int bitrate) {
// logger->info("set can:{} bitrate:{}", canName, bitrate);
// dosystem(fmt::format("ip link set {} down", canName));
// dosystem(fmt::format("ip link set {} type can bitrate {}", canName, bitrate));
// dosystem(fmt::format("ip link set {} up", canName));
// }
// bool SocketCan::findCan(string canName) { return access(fmt::format("/sys/class/net/{}", canName).c_str(), F_OK) == 0; }
// void SocketCan::dosystem(string cmd) {
// logger->info("do cmd:{}", cmd);
// system(cmd.c_str());
// }
// bool SocketCan::tryUpdateTxState(canfd_frame_t &rxloopmsg) {
// lock_guard<recursive_mutex> lock(m_txState.lock);
// if (m_txState.txState == kTxing && isTxFrame(rxloopmsg)) {
// unsetTxStateToTxing();
// return true;
// }
// return false;
// }
// void SocketCan::setTxStateToTxing(const canfd_frame_t &txpacket) {
// lock_guard<recursive_mutex> lock(m_txState.lock);
// m_txState.txState = kTxing;
// m_txState.txbuf = txpacket;
// }
// void SocketCan::unsetTxStateToTxing() {
// lock_guard<recursive_mutex> lock(m_txState.lock);
// m_txState.txState = kTxIdle;
// }
// #define TEST_CANDRIVER_DO(exptr) \
// do { \
// if ((exptr) != 0) { \
// logger->error("do {} failed,{}", #exptr, strerror(errno)); \
// if (socketId > 0) { \
// close(socketId); \
// socketId = -1; \
// return -1; \
// } \
// } \
// } while (0)
// int SocketCan::dumpCanDriverInfo(string canDevice, int baudrate) {
// int socketId = -1;
// struct ifreq ifr = {0};
// struct sockaddr_can addr = {0};
// can_filter_t zerofilter = {0};
// int recv_own_msgs = 0; /* 0 = disabled (default), 1 = enabled */
// int localloop = 0;
// int ret = 0;
// fd_set readfds, readFileDescriptors;
// timeval waitTime;
// int loopTime = 0;
// logger_t logger = GET_LOGGER(SocketCan);
// if (!findCan(canDevice)) {
// logger->error("can:{} not found", canDevice);
// return -1;
// }
// // set bitrate
// system(fmt::format("ip link set {} down", canDevice).c_str());
// system(fmt::format("ip link set {} type can bitrate {}", canDevice, baudrate).c_str());
// system(fmt::format("ip link set {} up", canDevice).c_str());
// socketId = socket(PF_CAN, SOCK_RAW, CAN_RAW);
// if (socketId < 0) {
// logger->error("socket failed,{}", strerror(errno));
// return -1;
// }
// // 设置依靠名字绑定CAN设备
// strcpy(ifr.ifr_name, canDevice.c_str());
// TEST_CANDRIVER_DO(ioctl(socketId, SIOCGIFINDEX, &ifr));
// // BIND
// addr.can_family = AF_CAN;
// addr.can_ifindex = ifr.ifr_ifindex;
// TEST_CANDRIVER_DO(bind(socketId, (struct sockaddr *)&addr, sizeof(addr)));
// // 设置过滤器
// TEST_CANDRIVER_DO(setsockopt(socketId, SOL_CAN_RAW, CAN_RAW_FILTER, &zerofilter, sizeof(zerofilter)));
// // 打开回环
// localloop = 1; /* 0 = disabled (default), 1 = enabled */
// TEST_CANDRIVER_DO(setsockopt(socketId, SOL_CAN_RAW, CAN_RAW_LOOPBACK, &localloop, sizeof(localloop)));
// recv_own_msgs = 1; /* 0 = disabled (default), 1 = enabled */
// TEST_CANDRIVER_DO(setsockopt(socketId, SOL_CAN_RAW, CAN_RAW_RECV_OWN_MSGS, &recv_own_msgs, sizeof(recv_own_msgs)));
// // 发送一条消息
// canfd_frame_t txframe = {0};
// canfd_frame_t rxcanframe = {0};
// int rxloopcount = 0;
// txframe.can_id = 0x12;
// txframe.len = 8;
// txframe.data[0] = 0x01;
// logger->info("write one frame");
// ret = write(socketId, &txframe, txframe.len + 8);
// if (ret < 0) {
// logger->error("write failed,{}", strerror(errno));
// close(socketId);
// return -1;
// }
// FD_ZERO(&readFileDescriptors);
// FD_SET(socketId, &readFileDescriptors);
// while (loopTime < 10) {
// loopTime++;
// waitTime.tv_sec = 0;
// waitTime.tv_usec = 100000; // 100ms
// readfds = readFileDescriptors;
// int n = select(socketId + 1, &readfds, 0, 0, &waitTime);
// if (n <= 0) continue;
// int readsize = read(socketId, &rxcanframe, sizeof(rxcanframe));
// if (readsize < 0) {
// logger->error("read failed,{}", strerror(errno));
// close(socketId);
// return -1;
// }
// if (rxcanframe.can_id == txframe.can_id && //
// rxcanframe.data[0] == txframe.data[0] && //
// rxcanframe.len == txframe.len) {
// rxloopcount++;
// logger->info("rx loop frame {}", rxloopcount);
// }
// }
// logger->info("Test Can Driver OK!");
// logger->info("=================Can Driver Info =================");
// logger->info("canDevice :{}", canDevice);
// logger->info("baudrate :{}", baudrate);
// logger->info("loop count :{}", rxloopcount);
// logger->info("shouldEnableLoop:{}", rxloopcount == 1);
// logger->info("==================================================");
// close(socketId);
// return 0;
// }
// void SocketCan::socketCanReadThreadLoop() {
// ThisThread thisThread;
// fd_set readfds, readFileDescriptors;
// FD_ZERO(&readFileDescriptors);
// FD_SET(m_socketCanFd, &readFileDescriptors);
// while (!thisThread.getExitFlag()) {
// canfd_frame_t canframe;
// timeval waitTime;
// waitTime.tv_sec = 0;
// waitTime.tv_usec = 100000; // 100ms
// readfds = readFileDescriptors;
// int n = select(m_socketCanFd + 1, &readfds, 0, 0, &waitTime);
// if (n <= 0) continue;
// memset(&canframe, 0x00, sizeof(canframe));
// int ret = read(m_socketCanFd, &canframe, sizeof(canframe));
// if (ret < 0) {
// logger->error("read failed,{}", strerror(errno));
// continue;
// }
// if (canframe.can_id & CAN_ERR_FLAG) {
// // /usr/include/linux/can/error.h
// // x can-bus error event 20000004,0004000000000086
// logger->error("rx can-bus error event {:x},{}", canframe.can_id, StringUtils().bytesToString(canframe.data, canframe.len));
// unsetTxStateToTxing();
// // exit(-1);
// break;
// } else {
// // logger->info("TX:{} {} {}", canframe.can_id, canframe.__res0, canframe.__res1);
// if (!tryUpdateTxState(canframe)) {
// shared_ptr<SocketCanFrame> socketCanFrame = SocketCanFrame::createFrame(canframe);
// logger->debug("RX:{}", socketCanFrame->toString());
// onSocketCanFrame(socketCanFrame);
// }
// }
// }
// m_canTriggerError = true;
// m_canBusIsReady = false;
// }
// void SocketCan::monitorLoop() {
// ThisThread thisThread;
// while (!thisThread.getExitFlag()) {
// if (m_canTriggerError) {
// // 尝试恢复CAN总线
// logger->warn("try to recover can bus............................................");
// if (m_thread) {
// m_thread->join();
// m_thread = nullptr;
// }
// logger->warn("close can bus fd:{}", m_socketCanFd);
// close(m_socketCanFd);
// m_socketCanFd = -1;
// {
// lock_guard<recursive_mutex> lock(m_txState.lock);
// memset(&m_txState.txbuf, 0x00, sizeof(m_txState.txbuf));
// m_txState.txState = TxState_t::kTxIdle;
// m_txState.txAckCount = 0;
// m_txState.txLoopMessageRxTicket = zsteady_clock().now();
// }
// logger->warn("re init can bus");
// socketcanInitialize();
// m_thread.reset(new Thread("SocketCanThread", [this]() {
// usleep(10 * 1000);
// socketCanReadThreadLoop();
// }));
// m_canTriggerError = false;
// m_canBusIsReady = true;
// logger->warn("recover can bus ok............................................");
// }
// thisThread.sleepForMs(30);
// }
// }
#include "socket_can.hpp"
#include <linux/can/error.h>
#include "components/thread/thread.hpp"
#include "utils/stringutils.hpp"
#include "utils/timeutils.hpp"
//
using namespace iflytop;
#define DO(exptr) \
do { \
if ((exptr) != 0) { \
logger->error("do {} failed,{}", #exptr, strerror(errno)); \
goto error; \
} \
} while (0)
SocketCan::SocketCanError_t SocketCan::sendFrame(shared_ptr<SocketCanFrame> frame) {
if (!m_canBusIsReady) {
return kDeviceBusy;
}
if (frame == nullptr) {
logger->error("frame is null");
return kParamError;
}
if (isTxing()) {
logger->error("txing, can't send frame");
return kDeviceBusy;
}
canfd_frame_t canframe = frame->getCanFrame();
return writeFrame(canframe);
}
SocketCan::SocketCanError_t SocketCan::writeFrame(const canfd_frame_t &_frame) {
if (!m_canBusIsReady) {
return kDeviceBusy;
}
canfd_frame_t txframe = _frame;
txframe.can_id |= 0x10000000;
setTxStateToTxing(txframe);
int ret = write(m_socketCanFd, &txframe, 16);
if (ret != (16)) {
logger->error("write fail,{}", strerror(errno));
unsetTxStateToTxing();
return kWriteError;
}
return kSuccess;
}
SocketCan::SocketCanError_t SocketCan::sendFrame(shared_ptr<SocketCanFrame> frame, int overtime) {
tp_steady start = tu_steady().now();
while (tu_steady().elapsedTimeMs(start) < overtime && !m_canBusIsReady) {
usleep(100);
}
if (!m_canBusIsReady) {
return kOvertime;
}
while (tu_steady().elapsedTimeMs(start) < overtime && isTxing()) {
usleep(100);
}
if (isTxing()) {
logger->error("send frame overtime");
return kOvertime;
}
return sendFrame(frame);
}
bool SocketCan::isTxing() { return m_txState.txState == kTxing; }
bool SocketCan::isTxFrame(const canfd_frame_t &frame) {
lock_guard<recursive_mutex> lock(m_txState.lock);
if (m_txState.txbuf.can_id == frame.can_id && m_txState.txbuf.len == frame.len && memcmp(m_txState.txbuf.data, frame.data, frame.len) == 0) {
return true;
}
return false;
}
void SocketCan::initialize(shared_ptr<SocketCanConfig> socketCanConfig) { //
ZCHECK(socketCanConfig, "socketCanConfig is null");
m_socketCanConfig = socketCanConfig;
socketcanInitialize();
}
SocketCan::~SocketCan() {
if (m_thread) {
endListenThread();
}
if (m_socketCanFd > 0) {
close(m_socketCanFd);
m_socketCanFd = -1;
}
}
void SocketCan::startListen() { startListenThread(); }
void SocketCan::socketcanReInitialize() {}
void SocketCan::startListenThread() {
if (m_thread) {
endListenThread();
return;
}
logger->info("startListenThread");
m_thread.reset(new Thread("SocketCanThread", [this]() {
/**
* @brief call socketCanReadThreadLoop
*/
socketCanReadThreadLoop();
}));
m_canBusIsReady = true;
m_autoRestartThread.reset(new Thread("SocketCanAutoRestartThread", [this]() { monitorLoop(); }));
}
void SocketCan::endListenThread() {
logger->info("endListenThread");
if (m_thread) {
m_thread->join();
m_thread = nullptr;
}
}
void SocketCan::socketcanInitialize() {
// setCanBitrate(canName, bitrate);
struct ifreq ifr = {0};
struct sockaddr_can addr = {0};
can_filter_t zerofilter = {0};
int recv_own_msgs = 0; /* 0 = disabled (default), 1 = enabled */
int localloop = 0;
vector<can_filter_t> filters = m_socketCanConfig->m_canfilters;
can_err_mask_t err_mask = 0;
if (!findCan(m_socketCanConfig->m_canName)) {
logger->error("can:{} not found", m_socketCanConfig->m_canName);
return;
}
if (m_thread) endListenThread();
if (m_socketCanFd > 0) socketcanDeInitialize();
logger->info("socketcanInitialize,canName:{},canBaudrate:{}", m_socketCanConfig->m_canName, m_socketCanConfig->m_canBaudrate);
// 配置socketCan波特率,注意该方法必须放在socket之前
setCanBitrate(m_socketCanConfig->m_canName, m_socketCanConfig->m_canBaudrate);
// SOCKET
m_socketCanFd = socket(PF_CAN, SOCK_RAW, CAN_RAW);
if (m_socketCanFd < 0) {
logger->error("socket failed,{}", strerror(errno));
goto error;
}
// 设置依靠名字绑定CAN设备
strcpy(ifr.ifr_name, m_socketCanConfig->m_canName.c_str());
DO(ioctl(m_socketCanFd, SIOCGIFINDEX, &ifr));
// BIND
addr.can_family = AF_CAN;
addr.can_ifindex = ifr.ifr_ifindex;
DO(bind(m_socketCanFd, (struct sockaddr *)&addr, sizeof(addr)));
// 设置过滤器,默认不过滤
DO(setsockopt(m_socketCanFd, SOL_CAN_RAW, CAN_RAW_FILTER, &zerofilter, sizeof(zerofilter)));
if (m_socketCanConfig->enablLoopback) {
localloop = 1; /* 0 = disabled (default), 1 = enabled */
DO(setsockopt(m_socketCanFd, SOL_CAN_RAW, CAN_RAW_LOOPBACK, &localloop, sizeof(localloop)));
recv_own_msgs = 1; /* 0 = disabled (default), 1 = enabled */
DO(setsockopt(m_socketCanFd, SOL_CAN_RAW, CAN_RAW_RECV_OWN_MSGS, &recv_own_msgs, sizeof(recv_own_msgs)));
} else {
localloop = 0; /* 0 = disabled (default), 1 = enabled */
DO(setsockopt(m_socketCanFd, SOL_CAN_RAW, CAN_RAW_LOOPBACK, &localloop, sizeof(localloop)));
recv_own_msgs = 0; /* 0 = disabled (default), 1 = enabled */
DO(setsockopt(m_socketCanFd, SOL_CAN_RAW, CAN_RAW_RECV_OWN_MSGS, &recv_own_msgs, sizeof(recv_own_msgs)));
}
err_mask = CAN_ERR_TX_TIMEOUT | //
CAN_ERR_LOSTARB | //
CAN_ERR_CRTL | //
CAN_ERR_PROT | //
CAN_ERR_TRX | //
CAN_ERR_ACK | //
CAN_ERR_BUSOFF | //
CAN_ERR_BUSERROR | //
CAN_ERR_RESTARTED;
setsockopt(m_socketCanFd, SOL_CAN_RAW, CAN_RAW_ERR_FILTER, &err_mask, sizeof(err_mask));
logger->info("socketcan init success");
return;
error:
logger->error("socketcan init failed");
if (m_socketCanFd > 0) {
close(m_socketCanFd);
m_socketCanFd = -1;
}
return;
}
void SocketCan::socketcanDeInitialize() {}
void SocketCan::canReadThread() {}
void SocketCan::setCanBitrate(string canName, int bitrate) {
logger->info("set can:{} bitrate:{}", canName, bitrate);
dosystem(fmt::format("ip link set {} down", canName));
dosystem(fmt::format("ip link set {} type can bitrate {}", canName, bitrate));
dosystem(fmt::format("ip link set {} up", canName));
}
bool SocketCan::findCan(string canName) { return access(fmt::format("/sys/class/net/{}", canName).c_str(), F_OK) == 0; }
void SocketCan::dosystem(string cmd) {
logger->info("do cmd:{}", cmd);
system(cmd.c_str());
}
bool SocketCan::tryUpdateTxState(canfd_frame_t &rxloopmsg) {
lock_guard<recursive_mutex> lock(m_txState.lock);
if (m_txState.txState == kTxing && isTxFrame(rxloopmsg)) {
unsetTxStateToTxing();
return true;
}
return false;
}
void SocketCan::setTxStateToTxing(const canfd_frame_t &txpacket) {
lock_guard<recursive_mutex> lock(m_txState.lock);
m_txState.txState = kTxing;
m_txState.txbuf = txpacket;
}
void SocketCan::unsetTxStateToTxing() {
lock_guard<recursive_mutex> lock(m_txState.lock);
m_txState.txState = kTxIdle;
}
#define TEST_CANDRIVER_DO(exptr) \
do { \
if ((exptr) != 0) { \
logger->error("do {} failed,{}", #exptr, strerror(errno)); \
if (socketId > 0) { \
close(socketId); \
socketId = -1; \
return -1; \
} \
} \
} while (0)
int SocketCan::dumpCanDriverInfo(string canDevice, int baudrate) {
int socketId = -1;
struct ifreq ifr = {0};
struct sockaddr_can addr = {0};
can_filter_t zerofilter = {0};
int recv_own_msgs = 0; /* 0 = disabled (default), 1 = enabled */
int localloop = 0;
int ret = 0;
fd_set readfds, readFileDescriptors;
timeval waitTime;
int loopTime = 0;
logger_t logger = GET_LOGGER(SocketCan);
if (!findCan(canDevice)) {
logger->error("can:{} not found", canDevice);
return -1;
}
// set bitrate
system(fmt::format("ip link set {} down", canDevice).c_str());
system(fmt::format("ip link set {} type can bitrate {}", canDevice, baudrate).c_str());
system(fmt::format("ip link set {} up", canDevice).c_str());
socketId = socket(PF_CAN, SOCK_RAW, CAN_RAW);
if (socketId < 0) {
logger->error("socket failed,{}", strerror(errno));
return -1;
}
// 设置依靠名字绑定CAN设备
strcpy(ifr.ifr_name, canDevice.c_str());
TEST_CANDRIVER_DO(ioctl(socketId, SIOCGIFINDEX, &ifr));
// BIND
addr.can_family = AF_CAN;
addr.can_ifindex = ifr.ifr_ifindex;
TEST_CANDRIVER_DO(bind(socketId, (struct sockaddr *)&addr, sizeof(addr)));
// 设置过滤器
TEST_CANDRIVER_DO(setsockopt(socketId, SOL_CAN_RAW, CAN_RAW_FILTER, &zerofilter, sizeof(zerofilter)));
// 打开回环
localloop = 1; /* 0 = disabled (default), 1 = enabled */
TEST_CANDRIVER_DO(setsockopt(socketId, SOL_CAN_RAW, CAN_RAW_LOOPBACK, &localloop, sizeof(localloop)));
recv_own_msgs = 1; /* 0 = disabled (default), 1 = enabled */
TEST_CANDRIVER_DO(setsockopt(socketId, SOL_CAN_RAW, CAN_RAW_RECV_OWN_MSGS, &recv_own_msgs, sizeof(recv_own_msgs)));
// 发送一条消息
canfd_frame_t txframe = {0};
canfd_frame_t rxcanframe = {0};
int rxloopcount = 0;
txframe.can_id = 0x12;
txframe.len = 8;
txframe.data[0] = 0x01;
logger->info("write one frame");
ret = write(socketId, &txframe, txframe.len + 8);
if (ret < 0) {
logger->error("write failed,{}", strerror(errno));
close(socketId);
return -1;
}
FD_ZERO(&readFileDescriptors);
FD_SET(socketId, &readFileDescriptors);
while (loopTime < 10) {
loopTime++;
waitTime.tv_sec = 0;
waitTime.tv_usec = 100000; // 100ms
readfds = readFileDescriptors;
int n = select(socketId + 1, &readfds, 0, 0, &waitTime);
if (n <= 0) continue;
int readsize = read(socketId, &rxcanframe, sizeof(rxcanframe));
if (readsize < 0) {
logger->error("read failed,{}", strerror(errno));
close(socketId);
return -1;
}
if (rxcanframe.can_id == txframe.can_id && //
rxcanframe.data[0] == txframe.data[0] && //
rxcanframe.len == txframe.len) {
rxloopcount++;
logger->info("rx loop frame {}", rxloopcount);
}
}
logger->info("Test Can Driver OK!");
logger->info("=================Can Driver Info =================");
logger->info("canDevice :{}", canDevice);
logger->info("baudrate :{}", baudrate);
logger->info("loop count :{}", rxloopcount);
logger->info("shouldEnableLoop:{}", rxloopcount == 1);
logger->info("==================================================");
close(socketId);
return 0;
}
void SocketCan::socketCanReadThreadLoop() {
ThisThread thisThread;
fd_set readfds, readFileDescriptors;
FD_ZERO(&readFileDescriptors);
FD_SET(m_socketCanFd, &readFileDescriptors);
while (!thisThread.getExitFlag()) {
canfd_frame_t canframe;
timeval waitTime;
waitTime.tv_sec = 0;
waitTime.tv_usec = 100000; // 100ms
readfds = readFileDescriptors;
int n = select(m_socketCanFd + 1, &readfds, 0, 0, &waitTime);
if (n <= 0) continue;
memset(&canframe, 0x00, sizeof(canframe));
int ret = read(m_socketCanFd, &canframe, sizeof(canframe));
if (ret < 0) {
logger->error("read failed,{}", strerror(errno));
continue;
}
if (canframe.can_id & CAN_ERR_FLAG) {
// /usr/include/linux/can/error.h
// x can-bus error event 20000004,0004000000000086
logger->error("rx can-bus error event {:x},{}", canframe.can_id, StringUtils().bytesToString(canframe.data, canframe.len));
unsetTxStateToTxing();
// exit(-1);
break;
} else {
// logger->info("TX:{} {} {}", canframe.can_id, canframe.__res0, canframe.__res1);
if (!tryUpdateTxState(canframe)) {
shared_ptr<SocketCanFrame> socketCanFrame = SocketCanFrame::createFrame(canframe);
logger->debug("RX:{}", socketCanFrame->toString());
onSocketCanFrame(socketCanFrame);
}
}
}
m_canTriggerError = true;
m_canBusIsReady = false;
}
void SocketCan::monitorLoop() {
ThisThread thisThread;
while (!thisThread.getExitFlag()) {
if (m_canTriggerError) {
// 尝试恢复CAN总线
logger->warn("try to recover can bus............................................");
if (m_thread) {
m_thread->join();
m_thread = nullptr;
}
logger->warn("close can bus fd:{}", m_socketCanFd);
close(m_socketCanFd);
m_socketCanFd = -1;
{
lock_guard<recursive_mutex> lock(m_txState.lock);
memset(&m_txState.txbuf, 0x00, sizeof(m_txState.txbuf));
m_txState.txState = TxState_t::kTxIdle;
m_txState.txAckCount = 0;
m_txState.txLoopMessageRxTicket = zsteady_clock().now();
}
logger->warn("re init can bus");
socketcanInitialize();
m_thread.reset(new Thread("SocketCanThread", [this]() {
usleep(10 * 1000);
socketCanReadThreadLoop();
}));
m_canTriggerError = false;
m_canBusIsReady = true;
logger->warn("recover can bus ok............................................");
}
thisThread.sleepForMs(30);
}
}

347
src/components/zcanreceiver/socket_can/socket_can.hpp

@ -1,172 +1,175 @@
// //
// // Created by zwsd
// //
// #pragma once
// #include <fstream>
// #include <iostream>
// #include <list>
// #include <map>
// #include <memory>
// #include <mutex>
// #include <queue>
// #include <set>
// #include <sstream>
// #include <string>
// #include <vector>
// #include "iflytop/core/basic/concurrentqueue/concurrentqueue.h"
// #include "iflytop/core/components/timeutils.hpp"
// #include "iflytop/core/spdlogfactory/logger.hpp"
// #include "iflytop/core/thread/thread.hpp"
// #include "socket_can_frame.hpp"
// /**
// * @brief
// *
// * service: SocketCan
// *
// * 监听事件:
// * 依赖状态:
// * 依赖服务:
// * 作用:
// *
// */
// namespace iflytop {
// using namespace std;
// using namespace core;
// using namespace moodycamel;
// class SocketCanConfig {
// public:
// string m_canName;
// int m_canBaudrate;
// /**
// * @brief
// * SocketCan服务依赖于loopback功能,一般来说是需要使能的。
// * 但有些can驱动自动开启了这个功能,这时候就需要禁用,否则就会收到两个相同的帧。
// * 通过testCanDriver可以测试是否需要禁用loopback功能。
// */
// bool enablLoopback = false;
// vector<can_filter_t> m_canfilters; // 应用层过滤,这里不要配置
// };
// class SocketCan : public enable_shared_from_this<SocketCan> {
// ENABLE_LOGGER(SocketCan);
// public:
// typedef enum {
// kTxIdle,
// kTxing,
// } TxState_t;
// class TxState {
// public:
// canfd_frame_t txbuf;
// TxState_t txState = kTxIdle;
// int txAckCount = 0;
// zsteady_tp txLoopMessageRxTicket;
// recursive_mutex lock;
// };
// private:
// unique_ptr<Thread> m_thread;
// unique_ptr<Thread> m_autoRestartThread;
// int m_socketCanFd = -1;
// bool m_startListen = false;
// shared_ptr<SocketCanConfig> m_socketCanConfig;
// TxState m_txState;
// bool m_canTriggerError = false;
// bool m_canBusIsReady = false;
// public:
// typedef enum {
// kSuccess,
// // Wrong CANFrame format!
// kErrorFrameFormat,
// // CAN-FD frames not supported!
// kCANFDNotSupported,
// kWriteError,
// kParamError,
// kDeviceBusy,
// kOvertime,
// } SocketCanError_t;
// static string SocketCanError_t2Str(SocketCanError_t error) {
// switch (error) {
// case kSuccess:
// return "kSuccess";
// case kErrorFrameFormat:
// return "kErrorFrameFormat";
// case kCANFDNotSupported:
// return "kCANFDNotSupported";
// case kWriteError:
// return "kWriteError";
// case kParamError:
// return "kParamError";
// case kDeviceBusy:
// return "kDeviceBusy";
// case kOvertime:
// return "kOvertime";
// default:
// return "Unknown";
// }
// }
// public:
// nod::signal<void(shared_ptr<SocketCanFrame>)> onSocketCanFrame;
// SocketCan(){};
// ~SocketCan();
// void initialize(shared_ptr<SocketCanConfig> socketCanConfig);
// bool isError() { return false; }
// void startListen();
// SocketCanError_t sendFrame(shared_ptr<SocketCanFrame> frame, int overtime);
// SocketCanError_t sendFrame(shared_ptr<SocketCanFrame> frame);
// /**
// * @brief 使用这个方法测试目标设备CAN驱动的行为,需要CAN总线上,除了目标设备外,至少有一个正常工作的节点。
// *
// * @param canDevice
// * @param baudrate
// * @return int
// */
// static int dumpCanDriverInfo(string canDevice, int baudrate);
// bool isTxing();
// private:
// void socketcanInitialize();
// void socketcanDeInitialize();
// void socketcanReInitialize();
// void startListenThread();
// void endListenThread();
// void socketCanReadThreadLoop();
// void monitorLoop();
// private:
// void dosystem(string cmd);
// void setCanBitrate(string canName, int bitrate);
// static bool findCan(string canName);
// SocketCanError_t writeFrame(const canfd_frame_t &frame);
// private:
// void canReadThread();
// bool tryUpdateTxState(canfd_frame_t &rxloopmsg);
// void setTxStateToTxing(const canfd_frame_t &txpacket);
// void unsetTxStateToTxing();
// bool isTxFrame(const canfd_frame_t &frame);
// };
// } // namespace iflytop
//
// Created by zwsd
//
#pragma once
#include <fstream>
#include <iostream>
#include <list>
#include <map>
#include <memory>
#include <mutex>
#include <queue>
#include <set>
#include <sstream>
#include <string>
#include <vector>
#include "socket_can_frame.hpp"
#include "spdlogfactory/logger.hpp"
#include "nlohmann/json.hpp"
#include "concurrentqueue/blockingconcurrentqueue.h"
#include "utils/timeutils.hpp"
#include "nod/nod.hpp"
#include "components/thread/thread.hpp"
/**
* @brief
*
* service: SocketCan
*
* :
* :
* :
* :
*
*/
namespace iflytop {
using namespace std;
using namespace core;
using namespace moodycamel;
class SocketCanConfig {
public:
string m_canName;
int m_canBaudrate;
/**
* @brief
* SocketCan服务依赖于loopback功能使
* can驱动自动开启了这个功能
* testCanDriver可以测试是否需要禁用loopback功能
*/
bool enablLoopback = false;
vector<can_filter_t> m_canfilters; // 应用层过滤,这里不要配置
};
class SocketCan : public enable_shared_from_this<SocketCan> {
ENABLE_LOGGER(SocketCan);
public:
typedef enum {
kTxIdle,
kTxing,
} TxState_t;
class TxState {
public:
canfd_frame_t txbuf;
TxState_t txState = kTxIdle;
int txAckCount = 0;
zsteady_tp txLoopMessageRxTicket;
recursive_mutex lock;
};
private:
unique_ptr<Thread> m_thread;
unique_ptr<Thread> m_autoRestartThread;
int m_socketCanFd = -1;
bool m_startListen = false;
shared_ptr<SocketCanConfig> m_socketCanConfig;
TxState m_txState;
bool m_canTriggerError = false;
bool m_canBusIsReady = false;
public:
typedef enum {
kSuccess,
// Wrong CANFrame format!
kErrorFrameFormat,
// CAN-FD frames not supported!
kCANFDNotSupported,
kWriteError,
kParamError,
kDeviceBusy,
kOvertime,
} SocketCanError_t;
static string SocketCanError_t2Str(SocketCanError_t error) {
switch (error) {
case kSuccess:
return "kSuccess";
case kErrorFrameFormat:
return "kErrorFrameFormat";
case kCANFDNotSupported:
return "kCANFDNotSupported";
case kWriteError:
return "kWriteError";
case kParamError:
return "kParamError";
case kDeviceBusy:
return "kDeviceBusy";
case kOvertime:
return "kOvertime";
default:
return "Unknown";
}
}
public:
nod::signal<void(shared_ptr<SocketCanFrame>)> onSocketCanFrame;
SocketCan(){};
~SocketCan();
void initialize(shared_ptr<SocketCanConfig> socketCanConfig);
bool isError() { return false; }
void startListen();
SocketCanError_t sendFrame(shared_ptr<SocketCanFrame> frame, int overtime);
SocketCanError_t sendFrame(shared_ptr<SocketCanFrame> frame);
/**
* @brief 使CAN驱动的行为CAN总线上
*
* @param canDevice
* @param baudrate
* @return int
*/
static int dumpCanDriverInfo(string canDevice, int baudrate);
bool isTxing();
private:
void socketcanInitialize();
void socketcanDeInitialize();
void socketcanReInitialize();
void startListenThread();
void endListenThread();
void socketCanReadThreadLoop();
void monitorLoop();
private:
void dosystem(string cmd);
void setCanBitrate(string canName, int bitrate);
static bool findCan(string canName);
SocketCanError_t writeFrame(const canfd_frame_t &frame);
private:
void canReadThread();
bool tryUpdateTxState(canfd_frame_t &rxloopmsg);
void setTxStateToTxing(const canfd_frame_t &txpacket);
void unsetTxStateToTxing();
bool isTxFrame(const canfd_frame_t &frame);
};
} // namespace iflytop

158
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> SocketCanFrame::createExtDataFrame(uint32_t id, uint8_t *data, size_t len) {
// shared_ptr<SocketCanFrame> canframe = make_shared<SocketCanFrame>();
// if (len > 8) len = 8;
// canframe->m_id = id;
// canframe->m_canIdentifier = socketcan::kextFrame;
// canframe->m_canFrameType = socketcan::kdataframe;
// canframe->m_dlc = len;
// memcpy(canframe->m_data, data, len);
// return canframe;
// }
shared_ptr<SocketCanFrame> SocketCanFrame::createExtDataFrame(uint32_t id, uint8_t *data, size_t len) {
shared_ptr<SocketCanFrame> canframe = make_shared<SocketCanFrame>();
if (len > 8) len = 8;
canframe->m_id = id;
canframe->m_canIdentifier = socketcan::kextFrame;
canframe->m_canFrameType = socketcan::kdataframe;
canframe->m_dlc = len;
memcpy(canframe->m_data, data, len);
return canframe;
}
// shared_ptr<SocketCanFrame> SocketCanFrame::createStdDataFrame(uint32_t id, uint8_t *data, size_t len) {
// shared_ptr<SocketCanFrame> canframe = make_shared<SocketCanFrame>();
// if (len > 8) len = 8;
// canframe->m_id = id;
// canframe->m_canIdentifier = socketcan::kstdFrame;
// canframe->m_canFrameType = socketcan::kdataframe;
// canframe->m_dlc = len;
// memcpy(canframe->m_data, data, len);
// return canframe;
// }
shared_ptr<SocketCanFrame> SocketCanFrame::createStdDataFrame(uint32_t id, uint8_t *data, size_t len) {
shared_ptr<SocketCanFrame> canframe = make_shared<SocketCanFrame>();
if (len > 8) len = 8;
canframe->m_id = id;
canframe->m_canIdentifier = socketcan::kstdFrame;
canframe->m_canFrameType = socketcan::kdataframe;
canframe->m_dlc = len;
memcpy(canframe->m_data, data, len);
return canframe;
}
// shared_ptr<SocketCanFrame> SocketCanFrame::createExtRemoteFrame(uint32_t id) {
// shared_ptr<SocketCanFrame> canframe = make_shared<SocketCanFrame>();
// canframe->m_id = id;
// canframe->m_canIdentifier = socketcan::kextFrame;
// canframe->m_canFrameType = socketcan::kremoteframe;
// canframe->m_dlc = 0;
// return canframe;
// }
// shared_ptr<SocketCanFrame> SocketCanFrame::createStdRemoteFrame(uint32_t id) {
// shared_ptr<SocketCanFrame> canframe = make_shared<SocketCanFrame>();
// canframe->m_id = id;
// canframe->m_canIdentifier = socketcan::kstdFrame;
// canframe->m_canFrameType = socketcan::kremoteframe;
// canframe->m_dlc = 0;
// return canframe;
// }
// shared_ptr<SocketCanFrame> SocketCanFrame::createFrame(canfd_frame_t frame) {
// shared_ptr<SocketCanFrame> canframe = make_shared<SocketCanFrame>();
// canframe->m_id = frame.can_id & ~CAN_EFF_FLAG & ~CAN_RTR_FLAG & ~CAN_ERR_FLAG;
// canframe->m_canIdentifier = frame.can_id & CAN_EFF_FLAG ? socketcan::kextFrame : socketcan::kstdFrame;
// canframe->m_canFrameType = frame.can_id & CAN_RTR_FLAG ? socketcan::kremoteframe : socketcan::kdataframe;
// canframe->m_dlc = frame.len;
shared_ptr<SocketCanFrame> SocketCanFrame::createExtRemoteFrame(uint32_t id) {
shared_ptr<SocketCanFrame> canframe = make_shared<SocketCanFrame>();
canframe->m_id = id;
canframe->m_canIdentifier = socketcan::kextFrame;
canframe->m_canFrameType = socketcan::kremoteframe;
canframe->m_dlc = 0;
return canframe;
}
shared_ptr<SocketCanFrame> SocketCanFrame::createStdRemoteFrame(uint32_t id) {
shared_ptr<SocketCanFrame> canframe = make_shared<SocketCanFrame>();
canframe->m_id = id;
canframe->m_canIdentifier = socketcan::kstdFrame;
canframe->m_canFrameType = socketcan::kremoteframe;
canframe->m_dlc = 0;
return canframe;
}
shared_ptr<SocketCanFrame> SocketCanFrame::createFrame(canfd_frame_t frame) {
shared_ptr<SocketCanFrame> canframe = make_shared<SocketCanFrame>();
canframe->m_id = frame.can_id & ~CAN_EFF_FLAG & ~CAN_RTR_FLAG & ~CAN_ERR_FLAG;
canframe->m_canIdentifier = frame.can_id & CAN_EFF_FLAG ? socketcan::kextFrame : socketcan::kstdFrame;
canframe->m_canFrameType = frame.can_id & CAN_RTR_FLAG ? socketcan::kremoteframe : socketcan::kdataframe;
canframe->m_dlc = frame.len;
// memcpy(canframe->m_data, frame.data, frame.len);
// return canframe;
// }
memcpy(canframe->m_data, frame.data, frame.len);
return canframe;
}
// void SocketCanFrame::setCanIdentifier(socketcan::can_identifier_t canIdentifier) { this->m_canIdentifier = canIdentifier; }
// void SocketCanFrame::setFanFrameType(socketcan::can_frame_type_t fanFrameType) { this->m_canFrameType = fanFrameType; }
// void SocketCanFrame::setId(uint32_t id) { this->m_id = id; }
void SocketCanFrame::setCanIdentifier(socketcan::can_identifier_t canIdentifier) { this->m_canIdentifier = canIdentifier; }
void SocketCanFrame::setFanFrameType(socketcan::can_frame_type_t fanFrameType) { this->m_canFrameType = fanFrameType; }
void SocketCanFrame::setId(uint32_t id) { this->m_id = id; }
// uint32_t SocketCanFrame::getId() { return m_id; }
// socketcan::can_identifier_t SocketCanFrame::getCanIdentifier() { return m_canIdentifier; }
// socketcan::can_frame_type_t SocketCanFrame::getFanFrameType() { return m_canFrameType; }
uint32_t SocketCanFrame::getId() { return m_id; }
socketcan::can_identifier_t SocketCanFrame::getCanIdentifier() { return m_canIdentifier; }
socketcan::can_frame_type_t SocketCanFrame::getFanFrameType() { return m_canFrameType; }
// string SocketCanFrame::toString() { //
// return fmt::format("|{:0>8x}|{:>6}|{}|{}({})|", getId(), //
// getFanFrameType() == socketcan::kdataframe ? "data" : "remote", //
// getCanIdentifier() == socketcan::kextFrame ? "ext" : "std", //
// StringUtils().bytesToString(m_data, m_dlc), m_dlc);
// }
string SocketCanFrame::toString() { //
return fmt::format("|{:0>8x}|{:>6}|{}|{}({})|", getId(), //
getFanFrameType() == socketcan::kdataframe ? "data" : "remote", //
getCanIdentifier() == socketcan::kextFrame ? "ext" : "std", //
StringUtils().bytesToString(m_data, m_dlc), m_dlc);
}
// uint8_t *SocketCanFrame::getData() { return m_data; }
// uint8_t SocketCanFrame::getDlc() { return m_dlc; }
uint8_t *SocketCanFrame::getData() { return m_data; }
uint8_t SocketCanFrame::getDlc() { return m_dlc; }
// canfd_frame_t SocketCanFrame::getCanFrame() {
// canfd_frame_t frame;
// memset(&frame, 0, sizeof(frame));
canfd_frame_t SocketCanFrame::getCanFrame() {
canfd_frame_t frame;
memset(&frame, 0, sizeof(frame));
// if (m_canIdentifier == socketcan::kstdFrame) {
// frame.can_id = (m_id & CAN_SFF_MASK);
// } else {
// frame.can_id = (m_id & CAN_EFF_MASK) | CAN_EFF_FLAG;
// }
if (m_canIdentifier == socketcan::kstdFrame) {
frame.can_id = (m_id & CAN_SFF_MASK);
} else {
frame.can_id = (m_id & CAN_EFF_MASK) | CAN_EFF_FLAG;
}
// if (m_canFrameType == socketcan::kremoteframe) {
// frame.can_id |= CAN_RTR_FLAG;
// frame.len = m_dlc;
// } else {
// frame.len = m_dlc;
// memcpy(frame.data, m_data, m_dlc);
// }
// return frame;
// }
if (m_canFrameType == socketcan::kremoteframe) {
frame.can_id |= CAN_RTR_FLAG;
frame.len = m_dlc;
} else {
frame.len = m_dlc;
memcpy(frame.data, m_data, m_dlc);
}
return frame;
}

128
src/components/zcanreceiver/socket_can/socket_can_frame.hpp

@ -1,79 +1,77 @@
// #pragma once
// #include <linux/can.h>
// #include <linux/can/raw.h>
// #include <net/if.h>
// #include <stdio.h>
// #include <stdlib.h>
// #include <string.h>
// #include <sys/ioctl.h>
// #include <sys/socket.h>
// #include <unistd.h>
#pragma once
#include <linux/can.h>
#include <linux/can/raw.h>
#include <net/if.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <unistd.h>
// #include <fstream>
// #include <iostream>
// #include <list>
// #include <map>
// #include <memory>
// #include <set>
// #include <sstream>
// #include <string>
// #include <vector>
#include <fstream>
#include <iostream>
#include <list>
#include <map>
#include <memory>
#include <set>
#include <sstream>
#include <string>
#include <vector>
// #include "iflytop/core/basic/nod/nod.hpp"
// #include "iflytop/core/spdlogfactory/logger.hpp"
// #include "iflytop/core/thread/thread.hpp"
#include "spdlogfactory/logger.hpp"
// namespace iflytop {
// using namespace std;
// using namespace core;
namespace iflytop {
using namespace std;
using namespace core;
// /*******************************************************************************
// * CAN_FRAME *
// *******************************************************************************/
/*******************************************************************************
* CAN_FRAME *
*******************************************************************************/
// typedef struct can_filter can_filter_t;
// typedef struct canfd_frame canfd_frame_t;
typedef struct can_filter can_filter_t;
typedef struct canfd_frame canfd_frame_t;
// namespace socketcan {
// typedef enum {
// kstdFrame,
// kextFrame,
// } can_identifier_t;
namespace socketcan {
typedef enum {
kstdFrame,
kextFrame,
} can_identifier_t;
// typedef enum {
// kdataframe,
// kremoteframe,
// } can_frame_type_t;
// } // namespace socketcan
typedef enum {
kdataframe,
kremoteframe,
} can_frame_type_t;
} // namespace socketcan
// class SocketCanFrame {
// private:
// uint32_t m_id = 0;
// socketcan::can_identifier_t m_canIdentifier = socketcan::kstdFrame;
// socketcan::can_frame_type_t m_canFrameType = socketcan::kdataframe;
// uint8_t m_data[8] = {0};
// uint8_t m_dlc = 0;
class SocketCanFrame {
private:
uint32_t m_id = 0;
socketcan::can_identifier_t m_canIdentifier = socketcan::kstdFrame;
socketcan::can_frame_type_t m_canFrameType = socketcan::kdataframe;
uint8_t m_data[8] = {0};
uint8_t m_dlc = 0;
// public:
// static shared_ptr<SocketCanFrame> createExtDataFrame(uint32_t id, uint8_t *data, size_t len);
// static shared_ptr<SocketCanFrame> createStdDataFrame(uint32_t id, uint8_t *data, size_t len);
// static shared_ptr<SocketCanFrame> createExtRemoteFrame(uint32_t id);
// static shared_ptr<SocketCanFrame> createStdRemoteFrame(uint32_t id);
// static shared_ptr<SocketCanFrame> createFrame(canfd_frame_t frame);
public:
static shared_ptr<SocketCanFrame> createExtDataFrame(uint32_t id, uint8_t *data, size_t len);
static shared_ptr<SocketCanFrame> createStdDataFrame(uint32_t id, uint8_t *data, size_t len);
static shared_ptr<SocketCanFrame> createExtRemoteFrame(uint32_t id);
static shared_ptr<SocketCanFrame> createStdRemoteFrame(uint32_t id);
static shared_ptr<SocketCanFrame> createFrame(canfd_frame_t frame);
// void setId(uint32_t id);
// uint32_t getId();
// socketcan::can_frame_type_t getFanFrameType();
// void setFanFrameType(socketcan::can_frame_type_t fanFrameType);
// socketcan::can_identifier_t getCanIdentifier();
// void setCanIdentifier(socketcan::can_identifier_t canIdentifier);
void setId(uint32_t id);
uint32_t getId();
socketcan::can_frame_type_t getFanFrameType();
void setFanFrameType(socketcan::can_frame_type_t fanFrameType);
socketcan::can_identifier_t getCanIdentifier();
void setCanIdentifier(socketcan::can_identifier_t canIdentifier);
// uint8_t *getData();
// uint8_t getDlc();
uint8_t *getData();
uint8_t getDlc();
// canfd_frame_t getCanFrame();
canfd_frame_t getCanFrame();
// string toString();
// };
string toString();
};
// } // namespace iflytop
} // namespace iflytop

224
src/components/zcanreceiver/zcanreceiverhost.cpp

@ -1,105 +1,119 @@
// #include "zcanreceiverhost.hpp"
// #include <stdio.h>
// #include <stdlib.h>
// #include <string.h>
// using namespace iflytop;
// #define TAG "ZCanReceiver"
// #define OVER_TIME_MS 20
// using namespace iflytop;
// ZCanReceiverHost::ZCanReceiverHost() {}
// void ZCanReceiverHost::initialize(string can_if_name, int baudrate, bool enablLoopback) {
// // m_iflytopCanProtocolStack.reset(new IflytopCanProtocolStack());
// m_can_if_name = can_if_name;
// m_baudrate = baudrate;
// m_enablLoopback = enablLoopback;
// resetSocketCan();
// }
// void ZCanReceiverHost::registerListener(onpacket_t onpacket) { m_onpacket = onpacket; }
// void ZCanReceiverHost::sendPacket(uint8_t *packet, size_t len) {
// int npacket = len / 8 + (len % 8 == 0 ? 0 : 1);
// if (npacket > 255) {
// return;
// }
// int finalpacketlen = len % 8 == 0 ? 8 : len % 8;
// for (uint8_t i = 0; i < npacket; i++) {
// bool suc = false;
// if (i == npacket - 1) {
// suc = sendPacketSub(npacket, i, packet + i * 8, finalpacketlen, OVER_TIME_MS);
// } else {
// suc = sendPacketSub(npacket, i, packet + i * 8, 8, OVER_TIME_MS);
// }
// if (!suc) {
// logger->warn("sendPacket fail, packet(%d:%d)\n", npacket, i);
// return;
// }
// }
// }
// bool ZCanReceiverHost::sendPacketSub(int npacket, int packetIndex, uint8_t *packet, size_t len, int overtimems) {
// uint32_t id = (m_deviceId << 16) | (npacket << 8) | packetIndex;
// // m_comcan.sendframe(CANUSB_FRAME_EXTENDED, id, packet, len);
// // printf("sendPacketSub(%d:%d) ", npacket, packetIndex);
// // for (size_t i = 0; i < len; i++) {
// // printf("%02x ", packet[i]);
// // }
// // printf("\n");
// shared_ptr<SocketCanFrame> frame = SocketCanFrame::createExtDataFrame(id, packet, len);
// m_socketCan->sendFrame(frame, overtimems);
// return true;
// }
// void ZCanReceiverHost::processOnePacket(CanPacketRxBuffer *rxbuf, uint8_t *packet, size_t len) { //
// if (m_onpacket) m_onpacket(rxbuf->id, packet, len);
// }
// void ZCanReceiverHost::processRx(shared_ptr<SocketCanFrame> frame) {
// uint8_t from = (frame->getId() >> 16 & 0xFF);
// uint8_t nframe = (frame->getId() & 0xFF00) >> 8;
// uint8_t frameId = (frame->getId() & 0x00FF);
// CanPacketRxBuffer *rxbuf = &m_canPacketRxBuffer[from];
// rxbuf->id = from;
// if (frameId == 0) {
// rxbuf->m_canPacketNum = 0;
// rxbuf->m_rxdataLen = 0;
// }
// if (rxbuf->m_canPacketNum < 255) {
// rxbuf->m_canPacket[rxbuf->m_canPacketNum] = frame;
// rxbuf->m_canPacketNum++;
// memcpy(rxbuf->m_rxdata + rxbuf->m_rxdataLen, frame->getData(), frame->getDlc());
// rxbuf->m_rxdataLen += frame->getDlc();
// }
// if (nframe == frameId + 1) {
// /**
// * @brief 接收到最后一包数据
// */
// processOnePacket(rxbuf, rxbuf->m_rxdata, rxbuf->m_rxdataLen);
// }
// }
// void ZCanReceiverHost::resetSocketCan() {
// auto socketCanConfig = make_shared<SocketCanConfig>();
// socketCanConfig->enablLoopback = m_enablLoopback; // 根据 SocketCan::dumpCanDriverInfo() 的输出,确定该标志位是false还是true
// socketCanConfig->m_canName = m_can_if_name;
// socketCanConfig->m_canBaudrate = m_baudrate;
// socketCanConfig->m_canfilters = {};
// logger->info("initialize() m_canName:{} {}", socketCanConfig->m_canName, socketCanConfig->m_canBaudrate);
// m_socketCan.reset(new SocketCan());
// m_socketCan->initialize(socketCanConfig);
// m_socketCan->startListen();
// m_socketCan->onSocketCanFrame.connect([this](shared_ptr<SocketCanFrame> canframe) { //
// logger->debug("onSocketCanFrame {}", canframe->toString());
// processRx(canframe);
// });
// }
#include "zcanreceiverhost.hpp"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
using namespace iflytop;
#define TAG "ZCanReceiver"
#define OVER_TIME_MS 20
using namespace iflytop;
ZCanReceiverHost::ZCanReceiverHost() {}
void ZCanReceiverHost::initialize(string can_if_name, int baudrate, bool enablLoopback) {
// m_iflytopCanProtocolStack.reset(new IflytopCanProtocolStack());
m_can_if_name = can_if_name;
m_baudrate = baudrate;
m_enablLoopback = enablLoopback;
resetSocketCan();
}
void ZCanReceiverHost::registerListener(onpacket_t onpacket) { m_onpacket = onpacket; }
void ZCanReceiverHost::sendPacket(uint8_t *packet, size_t len) {
int npacket = len / 7 + (len % 7 == 0 ? 0 : 1);
if (npacket > 255) {
return;
}
int finalpacketlen = len % 7 == 0 ? 7 : len % 7;
for (uint8_t i = 0; i < npacket; i++) {
bool suc = false;
if (i == npacket - 1) {
suc = sendPacketSub(npacket, i, packet + i * 7, finalpacketlen, OVER_TIME_MS);
} else {
suc = sendPacketSub(npacket, i, packet + i * 7, 7, OVER_TIME_MS);
}
if (!suc) {
logger->warn("sendPacket fail, packet(%d:%d)\n", npacket, i);
return;
}
}
}
bool ZCanReceiverHost::sendPacketSub(int npacket, int packetIndex, uint8_t *packet, size_t len, int overtimems) {
uint32_t id = 0;
uint8_t txdata[8] = {0};
txdata[0] = npacket << 4 | packetIndex;
memcpy(txdata + 1, packet, len);
// m_comcan.sendframe(CANUSB_FRAME_EXTENDED, id, packet, len);
// printf("sendPacketSub(%d:%d) ", npacket, packetIndex);
// for (size_t i = 0; i < len; i++) {
// printf("%02x ", packet[i]);
// }
// printf("\n");
shared_ptr<SocketCanFrame> frame = SocketCanFrame::createStdDataFrame(id, txdata, len + 1);
m_socketCan->sendFrame(frame, overtimems);
return true;
}
void ZCanReceiverHost::processOnePacket(CanPacketRxBuffer *rxbuf, uint8_t *packet, size_t len) { //
if (m_onpacket) m_onpacket(rxbuf->id, packet, len);
}
void ZCanReceiverHost::processRx(shared_ptr<SocketCanFrame> frame) {
// uint8_t from = (frame->getId() >> 16 & 0xFF);
// uint8_t nframe = (frame->getId() & 0xFF00) >> 8;
// uint8_t frameId = (frame->getId() & 0x00FF);
uint8_t from = (frame->getId() & 0xFF);
uint8_t nframe = ((frame->getData()[0] >> 4) & 0x0F);
uint8_t frameId = (frame->getData()[0] & 0x0F);
CanPacketRxBuffer *rxbuf = &m_canPacketRxBuffer[from];
rxbuf->id = from;
if (frameId == 0) {
rxbuf->m_canPacketNum = 0;
rxbuf->m_rxdataLen = 0;
}
if (frameId != rxbuf->m_canPacketNum) {
rxbuf->m_canPacketNum = 0;
rxbuf->m_rxdataLen = 0;
return;
}
if (rxbuf->m_canPacketNum < 255) {
rxbuf->m_canPacket[rxbuf->m_canPacketNum] = frame;
rxbuf->m_canPacketNum++;
memcpy(rxbuf->m_rxdata + rxbuf->m_rxdataLen, frame->getData() + 1, frame->getDlc() - 1);
rxbuf->m_rxdataLen += frame->getDlc() - 1;
}
if (nframe == frameId + 1) {
/**
* @brief
*/
processOnePacket(rxbuf, rxbuf->m_rxdata, rxbuf->m_rxdataLen);
}
}
void ZCanReceiverHost::resetSocketCan() {
auto socketCanConfig = make_shared<SocketCanConfig>();
socketCanConfig->enablLoopback = m_enablLoopback; // 根据 SocketCan::dumpCanDriverInfo() 的输出,确定该标志位是false还是true
socketCanConfig->m_canName = m_can_if_name;
socketCanConfig->m_canBaudrate = m_baudrate;
socketCanConfig->m_canfilters = {};
logger->info("initialize() m_canName:{} {}", socketCanConfig->m_canName, socketCanConfig->m_canBaudrate);
m_socketCan.reset(new SocketCan());
m_socketCan->initialize(socketCanConfig);
m_socketCan->startListen();
m_socketCan->onSocketCanFrame.connect([this](shared_ptr<SocketCanFrame> canframe) { //
logger->debug("onSocketCanFrame {}", canframe->toString());
processRx(canframe);
});
}

121
src/components/zcanreceiver/zcanreceiverhost.hpp

@ -1,61 +1,60 @@
// //
// // Created by zwsd
// //
// #pragma once
// #include <mutex>
// #include "socket_can/socket_can.hpp"
// //
// #include "thirdlib/nlohmann/json.hpp"
// #include "a8000_protocol/protocol.hpp"
// #include "thirdlib/spdlogfactory/logger_factory.hpp"
// namespace iflytop {
// using namespace std;
// using namespace zcr;
// using namespace core;
// class ZCanReceiverHost {
// ENABLE_LOGGER(ZCanReceiverHost);
// public:
// class CanPacketRxBuffer {
// public:
// uint16_t id;
// shared_ptr<SocketCanFrame> m_canPacket[256]; // 用于接收can消息
// uint8_t m_rxdata[255 * 8];
// uint8_t m_canPacketNum = 0;
// uint8_t m_rxdataLen = 0;
// };
// typedef function<void(uint8_t fromboardid, uint8_t *packet, size_t len)> onpacket_t;
// public:
// uint8_t m_deviceId = 0;
// CanPacketRxBuffer m_canPacketRxBuffer[255];
// onpacket_t m_onpacket;
// shared_ptr<SocketCan> m_socketCan;
// string m_can_if_name;
// int m_baudrate;
// bool m_enablLoopback;
// public:
// ZCanReceiverHost();
// void initialize(string can_if_name, int baudrate, bool enablLoopback);
// void sendPacket(uint8_t *packet, size_t len);
// void registerListener(onpacket_t onpacket);
// private:
// bool sendPacketSub(int npacket, int packetIndex, uint8_t *packet, size_t len, int overtimems);
// void processRx(shared_ptr<SocketCanFrame> frame);
// void processOnePacket(CanPacketRxBuffer *rxbuf, uint8_t *packet, size_t len);
// void resetSocketCan();
// void sendcmd(uint16_t packetindex, uint16_t cmdid, uint8_t subcmdid, uint8_t *data, size_t len);
// };
// } // namespace iflytop
//
// Created by zwsd
//
#pragma once
#include <mutex>
#include "socket_can/socket_can.hpp"
//
#include "a8000_protocol/protocol.hpp"
#include "thirdlib/spdlogfactory/logger_factory.hpp"
namespace iflytop {
using namespace std;
using namespace zcr;
using namespace core;
class ZCanReceiverHost {
ENABLE_LOGGER(ZCanReceiverHost);
public:
class CanPacketRxBuffer {
public:
uint16_t id;
shared_ptr<SocketCanFrame> m_canPacket[256]; // 用于接收can消息
uint8_t m_rxdata[255 * 8];
uint8_t m_canPacketNum = 0;
uint8_t m_rxdataLen = 0;
};
typedef function<void(uint8_t fromboardid, uint8_t *packet, size_t len)> onpacket_t;
public:
uint8_t m_deviceId = 0;
CanPacketRxBuffer m_canPacketRxBuffer[255];
onpacket_t m_onpacket;
shared_ptr<SocketCan> m_socketCan;
string m_can_if_name;
int m_baudrate;
bool m_enablLoopback;
public:
ZCanReceiverHost();
void initialize(string can_if_name, int baudrate, bool enablLoopback);
void sendPacket(uint8_t *packet, size_t len);
void registerListener(onpacket_t onpacket);
private:
bool sendPacketSub(int npacket, int packetIndex, uint8_t *packet, size_t len, int overtimems);
void processRx(shared_ptr<SocketCanFrame> frame);
void processOnePacket(CanPacketRxBuffer *rxbuf, uint8_t *packet, size_t len);
void resetSocketCan();
void sendcmd(uint16_t packetindex, uint16_t cmdid, uint8_t subcmdid, uint8_t *data, size_t len);
};
} // namespace iflytop

62
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> webSocket, shared_ptr<ConnectionState> 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<uint8_t> 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> webSocket, shared_ptr<ConnectionState> 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<uint8_t> 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();
}

3
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<GConfig> m_zconfig;
shared_ptr<ix::WebSocketServer> m_canPassthroughServer; // 19003
// shared_ptr<ZCanReceiverHost> m_zcanreceiverhost;
shared_ptr<ZCanReceiverHost> m_zcanreceiverhost;
public:
ExtAPIService() {};

215
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<uint8_t>& byteTable) {
string hexTable;
byteTable.clear();
if (!delims.empty()) {
hexTable = replaceAllDistinct(in, delims, "");
/* code */
} else {
hexTable = in;
}
if (hexTable.length() % 2 != 0) {
// printf("ss\n");
return false;
}
try {
for (unsigned i = 0; i < hexTable.length(); i += 2) {
string hex = hexTable.substr(i, 2);
// printf("ss1 %s\n", hex.c_str());
if (!isLegalHex(hex.c_str()[0])) {
return false;
}
if (!isLegalHex(hex.c_str()[1])) {
return false;
}
int value = std::stoi(hex, 0, 16);
byteTable.push_back((uint8_t)value);
}
} catch (const std::exception& e) {
// printf("ss1\n");
return false;
}
return true;
}
/**
* @brief
*
* @param value
* @return string
*/
string StringUtils::bytet2Binary(uint32_t value, int bitCount, bool remoteZero) {
string ret;
for (int i = 0; i < bitCount; ++i) {
uint32_t bit = value & 0x01;
value = value >> 1;
if (bit == 0) {
ret = "0" + ret;
} else {
ret = "1" + ret;
}
}
if (remoteZero) {
while (ret.length() > 0 && ret[0] == '0') {
ret = ret.substr(1, ret.length() - 1);
}
}
return ret;
}
string StringUtils::bytet2BinaryHumanReadable(uint32_t value, int bitCount) {
string ret = "(";
for (int i = 0; i < bitCount; ++i) {
uint32_t bit = value & 0x01;
value = value >> 1;
if (bit == 0) {
ret = "0" + ret;
} else {
ret = "1" + ret;
}
if ((i + 1) % 4 == 0 && i + 1 < bitCount) {
ret = " " + ret;
}
}
ret = ret + ")";
return ret;
}
string StringUtils::bytet2BinaryBigEnd(uint32_t value, int bitCount, bool remoteZero) {
string ret;
for (int i = 0; i < bitCount; ++i) {
uint32_t bit = value & 0x01;
value = value >> 1;
if (bit == 0) {
ret = ret + "0";
} else {
ret = ret + "1";
}
}
if (remoteZero) {
while (ret.length() > 0 && ret[ret.length() - 1] == '0') {
ret = ret.substr(0, ret.length() - 1);
}
}
return ret;
}
string StringUtils::escapeSequence(const string& raw_str) {
string escaped_str;
for (const char& ch : raw_str) {
switch (ch) {
case '\n':
escaped_str.append("\\n");
break;
case '\r':
escaped_str.append("\\r");
break;
case '\t':
escaped_str.append("\\t");
break;
case '\"':
escaped_str.append("\\\"");
break;
case '\\':
escaped_str.append("\\\\");
break;
default:
escaped_str.push_back(ch);
break;
}
}
return escaped_str;
}
int32_t StringUtils::split(const string& str, const string& delim, vector<string>& ret) {
if (str.empty()) {
return 0;
}
string tmp;
string::size_type pos_begin = str.find_first_not_of(delim);
string::size_type comma_pos = 0;
while (pos_begin != string::npos) {
comma_pos = str.find(delim, pos_begin);
if (comma_pos != string::npos) {
tmp = str.substr(pos_begin, comma_pos - pos_begin);
pos_begin = comma_pos + delim.length();
} else {
tmp = str.substr(pos_begin);
pos_begin = comma_pos;
}
if (!tmp.empty()) {
ret.push_back(tmp);
tmp.clear();
}
}
return 0;
}

78
test_src/testsqldb.cpp

@ -1,78 +0,0 @@
#include <signal.h>
#include <sqlite3.h>
#include <stdio.h>
#include <stdlib.h>
#include <fstream>
#include <functional>
#include <iostream>
#include <list>
#include <map>
#include <memory>
#include <set>
#include <sstream>
#include <string>
#include <vector>
#include "iflytop/components/sqlite_orm/sqlite_orm.hpp"
using namespace sqlite_orm;
struct User {
int id;
std::string firstName;
int lastName;
std::string birthDate;
std::unique_ptr<std::string> imageUrl;
int typeId;
};
struct UserType {
int id;
std::string name;
};
int main(int argc, char const *argv[]) {
sqlite3 *db;
char *zErrMsg = 0;
int rc;
// rc = sqlite3_open("test.db", &db);
// if (rc) {
// fprintf(stderr, "Can't open database: %s\n", sqlite3_errmsg(db));
// exit(0);
// } else {
// fprintf(stderr, "Opened database successfully\n");
// }
// sqlite3_close(db);
{
auto storage = make_storage("./db.sqlite", //
make_table("users", //
make_column("id", &User::id), //
make_column("first_name", &User::firstName), //
make_column("last_name", &User::lastName), //
make_column("birth_date", &User::birthDate), //
make_column("image_url", &User::imageUrl), //
make_column("type_id", &User::typeId)), //
make_table("user_types", //
make_column("id", &UserType::id, primary_key().autoincrement()), //
make_column("name", &UserType::name, default_value("name_placeholder"))));
// storage.dump();
// storage.sync_schema(
storage.sync_schema();
storage.filename();
std::cout << "storage.filename():" << storage.filename() << std::endl;
storage.sync_schema();
storage.insert(User{1, "Nicola", 2, "1856", nullptr, 0});
storage.insert(User{-1, "Linus", 2, "1969", nullptr, 0});
storage.insert(User{-1, "Mark", 3, "1984", nullptr, 0});
auto allEmployees = storage.get_all<User>();
for (auto &employee : allEmployees) {
std::cout << employee.id << ' ' << employee.firstName << ' ' << employee.lastName << std::endl;
}
// storage.sync_schema();
}
return 0;
}
Loading…
Cancel
Save