UniversalCanCore/Src/SocketApiProtocol.cpp
2025-12-24 17:18:34 +08:00

214 lines
7.4 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include <time.h>
#include "SocketApiProtocol.h"
#define RECV_BUFFER_SIZE 82 //接收缓冲区大小
#define PKG_CORE_STATUS 0x00 //读取核心状态
#define PKG_CAN_STATUS 0x01 //CAN盒子状态
#define PKG_TRANS_CAN 0x02 //收发CAN包
#define PKG_CTRL_GET 0xFF //取得控制权限
#define LOG_LEN 512 //日志长度
static asio::io_context io_ctx; //udp上下文
static std::unique_ptr<asio::ip::udp::socket> udp_socket; //socket
asio::ip::udp::endpoint remote_endpoint; //socket remote
std::string RemoteIpStr; //socket remote ip str
uint8_t recv_buffer[RECV_BUFFER_SIZE] = {0x00}; //接收缓冲区
uint8_t send_buffer[RECV_BUFFER_SIZE] = {0x00}; //发送缓冲区
char TimeBuff[64] = {0x00}; //时间缓冲区
char StatusLogBuff[LOG_LEN] = {0x00}; //状态日志缓冲区
char SendLogBuff[LOG_LEN] = {0x00}; //发包日志缓冲区
time_t now; //当前时间戳
struct tm* t; //当前时间
void SocketApiProtocolRun(void);
void start_receive(void);
void UdpAnalysis(uint8_t* RxData);
int UdpSendData(const char* ip, uint16_t port, const uint8_t* data, size_t len);
void CallBackCoreStatus(uint8_t* RxData,uint8_t* TxData);
void SocketApiProtocolInit(uint32_t SocketPort)
{
udp_socket = std::make_unique<asio::ip::udp::socket>(
io_ctx,
asio::ip::udp::endpoint(asio::ip::udp::v4(), SocketPort)
);
if(udp_socket && udp_socket->is_open())
{
std::cout << "[UDP] Listening successfully" << std::endl;
}
else
{
std::cerr << "[UDP] Socket not open" << std::endl;
}
std::thread UdpReceiveTask(SocketApiProtocolRun);
UdpReceiveTask.detach();
start_receive(); // 注册第一次接收
std::cout << "[UDP] Listening on port " << SocketPort << std::endl;
}
void start_receive(void)
{
udp_socket->async_receive_from(
asio::buffer(recv_buffer, RECV_BUFFER_SIZE),
remote_endpoint,
[](const asio::error_code& ec, std::size_t bytes_recvd)
{
if(!ec && bytes_recvd == RECV_BUFFER_SIZE && recv_buffer[0] == 0x55 && recv_buffer[RECV_BUFFER_SIZE - 1] == 0xAA)
{
RemoteIpStr = remote_endpoint.address().to_string();
UdpAnalysis(recv_buffer);
}
// 再次注册接收,保持持续监听
start_receive();
}
);
}
void transTimeToData(uint8_t* TxData, struct tm* t)
{
uint8_t data[7] = {0x00};
data[0] = t->tm_year & 0xFF;
data[1] = (t->tm_year >> 8) & 0xFF;
data[2] = t->tm_mon;
data[3] = t->tm_wday;
data[4] = t->tm_hour;
data[5] = t->tm_min;
data[6] = t->tm_sec;
memcpy(TxData,data,7);
}
void UdpAnalysis(uint8_t* RxData)
{
int command = RxData[1];
if (SystemCall.logEn == ENABLE)
{
now = time(NULL); // 获取当前时间戳从1970-01-01秒数
t = localtime(&now); // 转成本地时间
t->tm_year+=1900;
sprintf(TimeBuff,"%d-%d-%d.log",t->tm_year,t->tm_mon,t->tm_wday);
}
memset(send_buffer,0x00,RECV_BUFFER_SIZE);
/* 添加报文头尾 */
send_buffer[0] = 0x55;
send_buffer[RECV_BUFFER_SIZE - 1] = 0xAA;
switch(command)
{
case PKG_CORE_STATUS:
if (SystemCall.logEn == ENABLE)
{
memset(StatusLogBuff,0x00,LOG_LEN);
sprintf(StatusLogBuff,"[%04d-%02d-%02d-%02d-%02d-%02d]:Get Core Status",t->tm_year
,t->tm_mon
,t->tm_wday
,t->tm_hour
,t->tm_min
,t->tm_sec);
logAdd(TimeBuff,StatusLogBuff);
}
CallBackCoreStatus(RxData, send_buffer);
break;
case PKG_CAN_STATUS:
break;
case PKG_TRANS_CAN:
break;
case PKG_CTRL_GET:
//获取控制权限收到哪个ip的包哪个ip就属于主控主控接收所有Core发送的报文
if (SystemCall.logEn == ENABLE)
{
memset(StatusLogBuff,0x00,LOG_LEN);
sprintf(StatusLogBuff,"[%04d-%02d-%02d-%02d-%02d-%02d]:Get Ctrl Access %s",t->tm_year
,t->tm_mon
,t->tm_wday
,t->tm_hour
,t->tm_min
,t->tm_sec
,RemoteIpStr.c_str());
//还需要把ip加上
logAdd(TimeBuff,StatusLogBuff);
}
memcpy(send_buffer,RxData,RECV_BUFFER_SIZE);
break;
}
//如果调试使能,则回包加入时间
if (SystemCall.logEn == ENABLE)
{
transTimeToData(&send_buffer[2],t);
}
//回包
UdpSendData(RemoteIpStr.c_str(), 12346, send_buffer, RECV_BUFFER_SIZE);
//调试使能就记录一下,记录使用队列保证不影响收发
if (SystemCall.logEn == ENABLE)
{
memset(SendLogBuff,0x00,LOG_LEN);
sprintf(SendLogBuff,"[%04d-%02d-%02d-%02d-%02d-%02d]:Send Pkg ",t->tm_year
,t->tm_mon
,t->tm_wday
,t->tm_hour
,t->tm_min
,t->tm_sec);
char *p = &SendLogBuff[31];
for (int i = 0; i < RECV_BUFFER_SIZE; i++) {
p += sprintf(p, "0x%02X ", send_buffer[i]); // ← 关键在这里
}
if (SystemCall.logEn == ENABLE)
{
logAdd(TimeBuff,SendLogBuff);
}
}
}
void CallBackCoreStatus(uint8_t* RxData, uint8_t* TxData)
{
uint8_t data[4] = {0x00};
data[0] = SystemCall.ProductInfo; //产品信息
data[1] = SystemCall.CanOpenStatus[0]; //通道0打开状态
data[2] = SystemCall.CanOpenStatus[1]; //通道1打开状态
data[3] = SystemCall.logEn; //日志启用状态
memcpy(&TxData[9],data,4);
}
int UdpSendData(const char* ip, uint16_t port, const uint8_t* data, size_t len)
{
if(!udp_socket) return 0;
asio::error_code ec;
asio::ip::udp::endpoint remote(asio::ip::make_address(ip), port);
size_t sent = udp_socket->send_to(asio::buffer(data, len), remote, 0, ec);
if(ec)
{
if (SystemCall.logEn == ENABLE)
{
printf("[UDP] Send failed: %s\n", ec.message().c_str());
}
return 0;
}
return 1;
}
// 让你的系统循环运行 ASIO
void SocketApiProtocolRun(void)
{
io_ctx.run();
}