first commit
This commit is contained in:
28
Src/CanReceiveTask.cpp
Normal file
28
Src/CanReceiveTask.cpp
Normal file
@@ -0,0 +1,28 @@
|
||||
#include "CanReceiveTask.h"
|
||||
|
||||
// 一个任务函数,C 风格
|
||||
void Task1(void* param) {
|
||||
while (true) {
|
||||
std::cout << "Task1 running\n";
|
||||
vTaskDelay(1000); // 延时 1000ms
|
||||
}
|
||||
}
|
||||
|
||||
// 另一个任务函数
|
||||
void Task2(void* param) {
|
||||
while (true) {
|
||||
std::cout << "Task2 running\n";
|
||||
vTaskDelay(500); // 延时 500ms
|
||||
}
|
||||
}
|
||||
|
||||
void CanRecive(void)
|
||||
{
|
||||
// 创建“任务”,用 std::thread 代替 FreeRTOS 任务
|
||||
std::thread t1(Task1, nullptr);
|
||||
std::thread t2(Task2, nullptr);
|
||||
|
||||
// 如果想模拟 FreeRTOS,通常任务一直运行,主函数也可以阻塞
|
||||
t1.join();
|
||||
t2.join();
|
||||
}
|
||||
214
Src/SocketApiProtocol.cpp
Normal file
214
Src/SocketApiProtocol.cpp
Normal file
@@ -0,0 +1,214 @@
|
||||
#include <time.h>
|
||||
#include "SocketApiProtocol.h"
|
||||
|
||||
#define RECV_BUFFER_SIZE 26 //接收缓冲区大小
|
||||
|
||||
#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();
|
||||
}
|
||||
48
Src/System.cpp
Normal file
48
Src/System.cpp
Normal file
@@ -0,0 +1,48 @@
|
||||
#include "System.h"
|
||||
|
||||
SystemConfig SystemCall;
|
||||
// 在线程池中执行文件操作
|
||||
static asio::thread_pool pool(2); // 线程专门处理文件I/O
|
||||
|
||||
void SystemCallInit(void)
|
||||
{
|
||||
SystemCall.ProductInfo = 0xFF;
|
||||
SystemCall.logEn = ENABLE;
|
||||
SystemCall.CanOpenStatus[0] = DISABLE;
|
||||
SystemCall.CanOpenStatus[1] = DISABLE;
|
||||
}
|
||||
|
||||
void logAdd(const std::string& filename, const std::string& content) {
|
||||
asio::post(pool, [filename, content]() {
|
||||
std::ofstream file;
|
||||
|
||||
try {
|
||||
// 以追加模式打开文件
|
||||
file.open(filename, std::ios::app | std::ios::out);
|
||||
if (!file.is_open()) {
|
||||
throw std::runtime_error("Cannot open file: " + filename);
|
||||
}
|
||||
|
||||
// 写入内容(追加换行符)
|
||||
file << content << std::endl;
|
||||
|
||||
if (file.fail()) {
|
||||
throw std::runtime_error("Write failed");
|
||||
}
|
||||
|
||||
//std::cout << "Successfully appended to file: " << filename << std::endl;
|
||||
}
|
||||
catch (const std::exception& e) {
|
||||
std::cerr << "Error: " << e.what() << std::endl;
|
||||
}
|
||||
});
|
||||
|
||||
// 注意:pool会在作用域结束时join
|
||||
// 如果需要保持运行,可以将pool作为成员变量
|
||||
}
|
||||
|
||||
// 模拟 FreeRTOS 的延时
|
||||
void vTaskDelay(TickType_t ms)
|
||||
{
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(ms));
|
||||
}
|
||||
62
Src/main.cpp
Normal file
62
Src/main.cpp
Normal file
@@ -0,0 +1,62 @@
|
||||
#include "CanReceiveTask.h" /* CAN接收任务 */
|
||||
#include "SocketApiProtocol.h"
|
||||
|
||||
#define LISTEN_PORT 12345 //监听端口
|
||||
|
||||
int SearchPreProcess(void);
|
||||
void KillPreProcess(void);
|
||||
|
||||
int main() {
|
||||
|
||||
//此程序必须只有一个进程在运行
|
||||
while (SearchPreProcess() == ENABLE)
|
||||
{
|
||||
//杀死上一个进程
|
||||
KillPreProcess();
|
||||
std::cout<< "Kill Pre Process" <<std::endl;
|
||||
//等待进程里面的socket和内存被释放
|
||||
Sleep(500);
|
||||
}
|
||||
|
||||
//系统参数和回调初始化
|
||||
SystemCallInit();
|
||||
|
||||
//监听SOCKET端口
|
||||
SocketApiProtocolInit(LISTEN_PORT);
|
||||
|
||||
//打印一下
|
||||
std::cout << "Program Run Success" << std::endl;
|
||||
|
||||
//阻塞一下
|
||||
getchar();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
//查找是否有本程序的进程在运行
|
||||
int SearchPreProcess(void)
|
||||
{
|
||||
char cmd[512];
|
||||
DWORD currentPID = GetCurrentProcessId();
|
||||
|
||||
// 查找同名进程,但排除自己
|
||||
snprintf(cmd, sizeof(cmd),
|
||||
"tasklist | findstr \"UniversalCanCore.exe\" | findstr /v \"%lu\" > nul",
|
||||
currentPID);
|
||||
|
||||
return system(cmd) == 0 ? ENABLE : DISABLE;
|
||||
}
|
||||
|
||||
//杀死同名进程以及上一个进程
|
||||
void KillPreProcess(void)
|
||||
{
|
||||
char cmd[256];
|
||||
DWORD currentPID = GetCurrentProcessId();
|
||||
|
||||
// 查找并杀死除了自己以外的同名进程
|
||||
snprintf(cmd, sizeof(cmd),
|
||||
"for /f \"tokens=2\" %%a in ('tasklist ^| findstr \"UniversalCanCore.exe\"') do if not %%a==%lu taskkill /F /PID %%a",
|
||||
currentPID);
|
||||
|
||||
system(cmd);
|
||||
}
|
||||
Reference in New Issue
Block a user