737 lines
22 KiB
C++
737 lines
22 KiB
C++
/*******************************************************************************
|
||
* hook_rs422.cpp
|
||
*
|
||
* FPGA扩展RS422串口外挂程序
|
||
* 功能:监听/dev/pts/25串口,处理数据并执行相应操作
|
||
*
|
||
* 1. 将产生的虚拟遥测写入/dev/pts/12串口
|
||
* 2. 将收到的上行指令写入/dev/pts/12串口
|
||
* 3. 将从串口得到的数据通过DDS接口发送出去
|
||
*
|
||
* 使用方式: ./Com_kk <发送串口> <接收串口>
|
||
* 示例: ./Com_kk /dev/pts/12 /dev/pts/25
|
||
******************************************************************************/
|
||
|
||
#include "hook-rs422_kk.h"
|
||
#include "SimMsg.h"
|
||
|
||
#include <iostream>
|
||
#include <cstring>
|
||
#include <vector>
|
||
#include <thread>
|
||
#include <mutex>
|
||
#include <atomic>
|
||
#include <fcntl.h>
|
||
#include <unistd.h>
|
||
#include <termios.h>
|
||
#include <errno.h>
|
||
#include <poll.h>
|
||
#include <signal.h>
|
||
#include <time.h>
|
||
|
||
using namespace std;
|
||
|
||
// 全局变量定义
|
||
volatile int keep_running = 1;
|
||
uint8_t scomm_enable = 1;
|
||
|
||
// DDS相关全局变量
|
||
SimMsg* simMsg = nullptr;
|
||
string pkgname = "";
|
||
string topic_name_o2_can = "o2-can";
|
||
string topic_name_o1_can = "o1-can";
|
||
string topic_name_kk = "comu-kk";
|
||
|
||
// 互斥锁保护共享数据
|
||
std::mutex g_data_mutex;
|
||
|
||
// 本地参数声明
|
||
uint8_t tm_buffer[256] = { 0 };
|
||
S_Comm_telemetry_data_t s_tele = { 0 };
|
||
|
||
uint8_t isReceiveCmder = 0;
|
||
uint8_t rec_cmder_fromdds[255] = { 0 };
|
||
uint16_t rec_len_fromdds = 0;
|
||
|
||
string Msgfrom = "O2-A";
|
||
|
||
//====================================== 串口管理 ======================================//
|
||
|
||
// Socat虚拟串口结构
|
||
typedef struct {
|
||
int fd; // 文件描述符
|
||
bool enabled; // 使能标志
|
||
char device_path[256]; // 串口设备路径
|
||
const char* port_name; // 串口名称(用于日志标识)
|
||
const char* port_role; // 串口角色
|
||
} SocatPort;
|
||
|
||
// 串口枚举定义
|
||
enum SocatPortId {
|
||
PORT_TX = 0, // 发送串口 (argv[1])
|
||
PORT_RX = 1 // 接收串口 (argv[2])
|
||
};
|
||
|
||
// 串口实例
|
||
static SocatPort socat_ports[2] = {
|
||
{ -1, false, "", "发送串口", "发送" },
|
||
{ -1, false, "", "接收串口", "接收" }
|
||
};
|
||
|
||
// 线程相关
|
||
static pthread_t listen_thread;
|
||
|
||
//====================================== 函数声明 ======================================//
|
||
|
||
// 日志函数
|
||
void WriteLog(const string &msg);
|
||
|
||
// DDS接口函数
|
||
void pkginit(uint8_t domainid, string appname, string pkgname_);
|
||
void PkgToO2_AkkDataPub(uint8_t* o2_kk_data, uint16_t len);
|
||
void PkgToO_1kkDataPub(uint8_t* o1_kk_data, uint16_t len);
|
||
void pkgSubO_1KKData(message_func_t MessageCallback);
|
||
void PkgSubO2_AKkData(message_func_t MessageCallback);
|
||
|
||
// 数据处理函数
|
||
void cjb_rs422_kk_receive(string src, string dest, string type, string reserve1,
|
||
string reserve2, vector<uint8_t>& data);
|
||
void process_tm_buffer(uint8_t* buffer, uint16_t length);
|
||
void generate_s_tele(uint8_t* tele);
|
||
uint8_t generate_cmder(uint8_t* tele);
|
||
|
||
// 串口管理函数
|
||
int init_socat_serial(SocatPortId port_id, const char* device_path);
|
||
int read_from_serial(SocatPortId port_id, uint8_t* buffer, uint16_t buffer_size);
|
||
void forward_to_socat(uint8_t* data, uint16_t len, SocatPortId port_id);
|
||
void cleanup_socat_serial(SocatPortId port_id);
|
||
void cleanup_all_socat_serial();
|
||
|
||
// 线程函数
|
||
void* listen_serial_thread(void* arg);
|
||
int start_listen_thread();
|
||
void stop_listen_thread();
|
||
|
||
// 主程序接口
|
||
void hook_rs422_kk(const char* tx_port, const char* rx_port);
|
||
void set_scomm_enable(uint8_t s_en);
|
||
void cleanup_hook_rs422();
|
||
|
||
// 信号处理
|
||
void signal_handler(int signum);
|
||
|
||
//====================================== 日志函数 ======================================//
|
||
|
||
void WriteLog(const string &msg) {
|
||
time_t now = time(0);
|
||
char buf[80];
|
||
strftime(buf, sizeof(buf), "%Y-%m-%d %H:%M:%S", localtime(&now));
|
||
cout << "[" << buf << "] " << msg << endl;
|
||
}
|
||
|
||
//====================================== FastDDS函数 ======================================//
|
||
|
||
void pkginit(uint8_t domainid, string appname, string pkgname_) {
|
||
if (simMsg == nullptr) {
|
||
WriteLog("初始化FastDDS通信...");
|
||
simMsg = new SimMsg(domainid, 3000, appname, WriteLog);
|
||
simMsg->create_pub(topic_name_o2_can);
|
||
simMsg->create_pub(topic_name_o1_can);
|
||
simMsg->create_pub(topic_name_kk);
|
||
pkgname = pkgname_;
|
||
WriteLog("FastDDS初始化完成: domainid=" + to_string(domainid) +
|
||
", appname=" + appname + ", pkgname=" + pkgname_);
|
||
}
|
||
}
|
||
|
||
void PkgToO2_AkkDataPub(uint8_t* o2_kk_data, uint16_t len) {
|
||
if (!simMsg || !scomm_enable) return;
|
||
|
||
simMsg->publish(topic_name_kk, pkgname, "O2-A", "", o2_kk_data, len);
|
||
|
||
string hex_str = "发送到O2-A DDS(" + to_string(len) + "字节): ";
|
||
for (int i = 0; i < (len < 10 ? len : 10); i++) {
|
||
char buf[4];
|
||
snprintf(buf, sizeof(buf), "%02X ", o2_kk_data[i]);
|
||
hex_str += buf;
|
||
}
|
||
if (len > 10) hex_str += "...";
|
||
WriteLog(hex_str);
|
||
}
|
||
|
||
void PkgToO_1kkDataPub(uint8_t* o1_kk_data, uint16_t len) {
|
||
if (!simMsg || !scomm_enable) return;
|
||
|
||
simMsg->publish(topic_name_kk, pkgname, "O-1", "", o1_kk_data, len);
|
||
|
||
string hex_str = "发送到O-1 DDS(" + to_string(len) + "字节): ";
|
||
for (int i = 0; i < (len < 10 ? len : 10); i++) {
|
||
char buf[4];
|
||
snprintf(buf, sizeof(buf), "%02X ", o1_kk_data[i]);
|
||
hex_str += buf;
|
||
}
|
||
if (len > 10) hex_str += "...";
|
||
WriteLog(hex_str);
|
||
}
|
||
|
||
void pkgSubO_1KKData(message_func_t MessageCallback) {
|
||
if (!simMsg) return;
|
||
|
||
vector<string> parameters;
|
||
string expression = "src = 'O-1'";
|
||
simMsg->create_sub(topic_name_kk,
|
||
static_cast<message_func_t>(MessageCallback),
|
||
expression, parameters);
|
||
WriteLog("订阅O-1数据成功");
|
||
}
|
||
|
||
void PkgSubO2_AKkData(message_func_t MessageCallback) {
|
||
if (!simMsg) return;
|
||
|
||
vector<string> parameters;
|
||
string expression = "src = 'O2-A'";
|
||
simMsg->create_sub(topic_name_kk,
|
||
static_cast<message_func_t>(MessageCallback),
|
||
expression, parameters);
|
||
WriteLog("订阅O2-A数据成功");
|
||
}
|
||
|
||
//====================================== DDS接收回调 ======================================//
|
||
|
||
void cjb_rs422_kk_receive(string src, string dest, string type, string reserve1,
|
||
string reserve2, vector<uint8_t>& data) {
|
||
if (data.empty()) {
|
||
WriteLog("警告:收到空数据");
|
||
return;
|
||
}
|
||
|
||
WriteLog("收到来自 " + src + " 的数据,大小: " + to_string(data.size()) + " 字节");
|
||
|
||
if (dest == "CJ") {
|
||
lock_guard<mutex> lock(g_data_mutex);
|
||
|
||
Msgfrom = src;
|
||
uint8_t checksum = 0;
|
||
uint16_t frameLen = 0;
|
||
|
||
// 安全复制数据
|
||
uint16_t copy_size = (data.size() < sizeof(rec_cmder_fromdds)) ?
|
||
data.size() : sizeof(rec_cmder_fromdds) - 1;
|
||
|
||
for (size_t kc = 0; kc < copy_size; kc++) {
|
||
if (kc == 5 || kc == 6) continue;
|
||
|
||
if (frameLen < sizeof(rec_cmder_fromdds)) {
|
||
rec_cmder_fromdds[frameLen++] = data[kc];
|
||
}
|
||
}
|
||
|
||
rec_len_fromdds = frameLen;
|
||
|
||
// 更新指令ID为遥控指令查询ID 0x4B
|
||
if (rec_len_fromdds > 2) {
|
||
rec_cmder_fromdds[2] = 0xB4;
|
||
}
|
||
|
||
// 调整长度字段
|
||
if (rec_len_fromdds > 4) {
|
||
if (rec_cmder_fromdds[4] >= 0x02) {
|
||
rec_cmder_fromdds[4] -= 0x02;
|
||
} else {
|
||
rec_cmder_fromdds[4] = 0;
|
||
}
|
||
}
|
||
|
||
// 重新计算校验和
|
||
for (int kc = 2; kc < rec_len_fromdds - 1; kc++) {
|
||
checksum += rec_cmder_fromdds[kc];
|
||
}
|
||
|
||
if (rec_len_fromdds > 0) {
|
||
rec_cmder_fromdds[rec_len_fromdds - 1] = checksum;
|
||
}
|
||
|
||
isReceiveCmder = 1;
|
||
WriteLog("已存储空空遥控指令,长度: " + to_string(rec_len_fromdds) + " 字节");
|
||
|
||
// 打印指令内容
|
||
string hex_str = "指令内容: ";
|
||
int print_len = (rec_len_fromdds < 20 ? rec_len_fromdds : 20);
|
||
for (int i = 0; i < print_len; i++) {
|
||
char buf[4];
|
||
snprintf(buf, sizeof(buf), "%02X ", rec_cmder_fromdds[i]);
|
||
hex_str += buf;
|
||
}
|
||
if (rec_len_fromdds > 20) hex_str += "...";
|
||
WriteLog(hex_str);
|
||
} else {
|
||
WriteLog("非CJ目标的数据,忽略");
|
||
}
|
||
}
|
||
|
||
//====================================== 串口管理 ======================================//
|
||
|
||
int init_socat_serial(SocatPortId port_id, const char* device_path) {
|
||
if (port_id < 0 || port_id >= 2) {
|
||
WriteLog("错误:无效的串口ID");
|
||
return -1;
|
||
}
|
||
|
||
SocatPort* port = &socat_ports[port_id];
|
||
|
||
// 更新设备路径
|
||
if (device_path && strlen(device_path) > 0) {
|
||
strncpy(port->device_path, device_path, sizeof(port->device_path) - 1);
|
||
port->device_path[sizeof(port->device_path) - 1] = '\0';
|
||
}
|
||
|
||
if (strlen(port->device_path) == 0) {
|
||
WriteLog("错误:串口" + string(port->port_role) + "路径为空");
|
||
return -1;
|
||
}
|
||
|
||
// 打开串口
|
||
port->fd = open(port->device_path, O_RDWR | O_NOCTTY);
|
||
if (port->fd < 0) {
|
||
WriteLog("错误:无法打开" + string(port->port_role) + " " +
|
||
string(port->device_path) + " (错误: " + strerror(errno) + ")");
|
||
port->enabled = false;
|
||
return -1;
|
||
}
|
||
|
||
// 配置串口参数
|
||
struct termios tty;
|
||
memset(&tty, 0, sizeof(tty));
|
||
|
||
if (tcgetattr(port->fd, &tty) != 0) {
|
||
WriteLog("错误:无法获取" + string(port->port_role) + "属性");
|
||
close(port->fd);
|
||
port->fd = -1;
|
||
port->enabled = false;
|
||
return -1;
|
||
}
|
||
|
||
// 设置波特率 115200
|
||
cfsetospeed(&tty, B115200);
|
||
cfsetispeed(&tty, B115200);
|
||
|
||
// 8N1配置
|
||
tty.c_cflag &= ~PARENB; // 无奇偶校验
|
||
tty.c_cflag &= ~CSTOPB; // 1位停止位
|
||
tty.c_cflag &= ~CSIZE;
|
||
tty.c_cflag |= CS8; // 8位数据位
|
||
tty.c_cflag |= CREAD | CLOCAL; // 启用接收,忽略调制解调器状态
|
||
|
||
// 关闭硬件流控
|
||
tty.c_cflag &= ~CRTSCTS;
|
||
|
||
// 输入模式
|
||
tty.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG); // 非规范模式
|
||
tty.c_iflag &= ~(IXON | IXOFF | IXANY); // 关闭软件流控
|
||
tty.c_iflag &= ~(INLCR | ICRNL | IGNCR);
|
||
|
||
// 输出模式
|
||
tty.c_oflag &= ~OPOST; // 原始输出
|
||
tty.c_oflag &= ~ONLCR;
|
||
|
||
// 超时设置
|
||
if (port_id == PORT_RX) {
|
||
tty.c_cc[VMIN] = 1; // 至少读取1个字节
|
||
tty.c_cc[VTIME] = 10; // 1秒超时
|
||
} else {
|
||
tty.c_cc[VMIN] = 0; // 非阻塞
|
||
tty.c_cc[VTIME] = 5; // 0.5秒超时
|
||
}
|
||
|
||
if (tcsetattr(port->fd, TCSANOW, &tty) != 0) {
|
||
WriteLog("错误:无法设置" + string(port->port_role) + "属性");
|
||
close(port->fd);
|
||
port->fd = -1;
|
||
port->enabled = false;
|
||
return -1;
|
||
}
|
||
|
||
// 清空缓冲区
|
||
tcflush(port->fd, TCIOFLUSH);
|
||
|
||
port->enabled = true;
|
||
WriteLog("成功初始化" + string(port->port_role) + ":" +
|
||
string(port->device_path) + " (" + string(port->port_name) + ")");
|
||
return 0;
|
||
}
|
||
|
||
int read_from_serial(SocatPortId port_id, uint8_t* buffer, uint16_t buffer_size) {
|
||
if (port_id < 0 || port_id >= 2 || buffer == nullptr || buffer_size == 0) {
|
||
return -1;
|
||
}
|
||
|
||
SocatPort* port = &socat_ports[port_id];
|
||
|
||
if (!port->enabled || port->fd < 0) {
|
||
return -1;
|
||
}
|
||
|
||
// 使用poll检查是否有数据可读
|
||
struct pollfd fds[1];
|
||
fds[0].fd = port->fd;
|
||
fds[0].events = POLLIN;
|
||
|
||
int ret = poll(fds, 1, 100); // 100ms超时
|
||
|
||
if (ret > 0 && (fds[0].revents & POLLIN)) {
|
||
ssize_t bytes_read = read(port->fd, buffer, buffer_size);
|
||
if (bytes_read > 0) {
|
||
string hex_str = "从" + string(port->port_role) + "(" +
|
||
string(port->device_path) + ")收到数据(" +
|
||
to_string(bytes_read) + "字节): ";
|
||
for (int i = 0; i < (bytes_read < 8 ? bytes_read : 8); i++) {
|
||
char buf[4];
|
||
snprintf(buf, sizeof(buf), "%02X ", buffer[i]);
|
||
hex_str += buf;
|
||
}
|
||
if (bytes_read > 8) hex_str += "...";
|
||
WriteLog(hex_str);
|
||
return bytes_read;
|
||
} else if (bytes_read == 0) {
|
||
return 0;
|
||
} else {
|
||
if (errno != EAGAIN && errno != EWOULDBLOCK) {
|
||
WriteLog("错误:读取" + string(port->port_role) + "数据失败: " +
|
||
string(strerror(errno)));
|
||
}
|
||
return -1;
|
||
}
|
||
}
|
||
|
||
return 0; // 没有数据可读
|
||
}
|
||
|
||
void forward_to_socat(uint8_t* data, uint16_t len, SocatPortId port_id) {
|
||
if (port_id < 0 || port_id >= 2) return;
|
||
|
||
SocatPort* port = &socat_ports[port_id];
|
||
|
||
if (!port->enabled || port->fd < 0 || len == 0) return;
|
||
|
||
// 打印发送的数据
|
||
string hex_str = "向" + string(port->port_role) + "(" +
|
||
string(port->device_path) + ")发送数据(" +
|
||
to_string(len) + "字节): ";
|
||
for (int i = 0; i < (len < 8 ? len : 8); i++) {
|
||
char buf[4];
|
||
snprintf(buf, sizeof(buf), "%02X ", data[i]);
|
||
hex_str += buf;
|
||
}
|
||
if (len > 8) hex_str += "...";
|
||
WriteLog(hex_str);
|
||
|
||
// 写入数据
|
||
ssize_t written = write(port->fd, data, len);
|
||
|
||
if (written != len) {
|
||
WriteLog("警告:未能完全写入所有数据到" + string(port->port_role) +
|
||
" (期望" + to_string(len) + "字节,实际" + to_string(written) + "字节)");
|
||
}
|
||
|
||
// 确保数据发送完成
|
||
tcdrain(port->fd);
|
||
}
|
||
|
||
void cleanup_socat_serial(SocatPortId port_id) {
|
||
if (port_id < 0 || port_id >= 2) return;
|
||
|
||
SocatPort* port = &socat_ports[port_id];
|
||
port->enabled = false;
|
||
|
||
if (port->fd >= 0) {
|
||
close(port->fd);
|
||
port->fd = -1;
|
||
WriteLog("清理" + string(port->port_role) + ":" + string(port->device_path));
|
||
}
|
||
}
|
||
|
||
void cleanup_all_socat_serial() {
|
||
for (int i = 0; i < 2; i++) {
|
||
cleanup_socat_serial(static_cast<SocatPortId>(i));
|
||
}
|
||
}
|
||
|
||
//====================================== 数据处理 ======================================//
|
||
|
||
void process_tm_buffer(uint8_t* buffer, uint16_t length) {
|
||
if (length < 3) {
|
||
WriteLog("警告:接收数据长度不足");
|
||
return;
|
||
}
|
||
|
||
char type_str[10];
|
||
snprintf(type_str, sizeof(type_str), "0x%02X", buffer[2]);
|
||
WriteLog("处理指令类型: " + string(type_str));
|
||
|
||
uint8_t scomm[56];
|
||
uint8_t cmder[255];
|
||
uint8_t cmder_len;
|
||
|
||
switch (buffer[2]) {
|
||
case 0x0F: // 取常规遥测数据
|
||
WriteLog("指令0x0F: 取常规遥测数据");
|
||
generate_s_tele(scomm);
|
||
WriteLog("发送常规遥测数据到发送串口");
|
||
forward_to_socat(scomm, 56, PORT_TX);
|
||
break;
|
||
|
||
case 0x1E: // 遥控指令
|
||
WriteLog("指令0x1E: 遥控指令(本地处理)");
|
||
break;
|
||
|
||
case 0x4B: // 取主星空空的遥控指令
|
||
WriteLog("指令0x4B: 请求空空遥控指令");
|
||
|
||
{
|
||
lock_guard<mutex> lock(g_data_mutex);
|
||
cmder_len = generate_cmder(cmder);
|
||
}
|
||
|
||
if (cmder_len != 0) {
|
||
WriteLog("发送空空遥控指令到发送串口");
|
||
forward_to_socat(cmder, cmder_len, PORT_TX);
|
||
} else {
|
||
WriteLog("没有可用的空空遥控指令,返回默认响应");
|
||
forward_to_socat(cmder, 6, PORT_TX);
|
||
}
|
||
break;
|
||
|
||
case 0x5A: // 发送下行遥测
|
||
WriteLog("指令0x5A: 发送下行遥测到DDS");
|
||
|
||
if (Msgfrom == "O2-A") {
|
||
if (scomm_enable) {
|
||
PkgToO2_AkkDataPub(buffer, length);
|
||
WriteLog("发送到O2-A DDS");
|
||
}
|
||
} else if (Msgfrom == "O-1") {
|
||
if (scomm_enable) {
|
||
PkgToO_1kkDataPub(buffer, length);
|
||
WriteLog("发送到O-1 DDS");
|
||
}
|
||
} else {
|
||
if (scomm_enable) {
|
||
PkgToO2_AkkDataPub(buffer, length);
|
||
WriteLog("发送到默认O2-A DDS");
|
||
}
|
||
}
|
||
break;
|
||
|
||
default:
|
||
char unknown_str[10];
|
||
snprintf(unknown_str, sizeof(unknown_str), "0x%02X", buffer[2]);
|
||
WriteLog("未知指令类型: " + string(unknown_str));
|
||
WriteLog("数据将转发到发送串口");
|
||
forward_to_socat(buffer, length, PORT_TX);
|
||
break;
|
||
}
|
||
}
|
||
|
||
void generate_s_tele(uint8_t* tele) {
|
||
static uint8_t packet_cnt = 0;
|
||
uint8_t checksum = 0;
|
||
|
||
s_tele.packet_cnt_1 = packet_cnt++;
|
||
s_tele.para2.trans = 1;
|
||
|
||
// 填充示例数据
|
||
s_tele.snrInfoChannel = 80;
|
||
s_tele.receive_RSSI = 60;
|
||
|
||
tele[0] = 0xEB; tele[1] = 0x90; tele[2] = 0xF0;
|
||
tele[3] = 0x00; tele[4] = 0x32;
|
||
tele[5] = 0x00; tele[6] = 0x30; tele[7] = 0x01;
|
||
tele[8] = 0xA6; tele[9] = 0xC0;
|
||
tele[10] = packet_cnt; tele[11] = 0x00; tele[12] = 0x29;
|
||
|
||
memcpy(&tele[13], &s_tele, sizeof(S_Comm_telemetry_data_t));
|
||
|
||
for (int kc = 2; kc < 55; kc++)
|
||
checksum += tele[kc];
|
||
|
||
tele[55] = checksum;
|
||
|
||
WriteLog("生成遥测数据包,包计数: " + to_string(packet_cnt));
|
||
}
|
||
|
||
uint8_t generate_cmder(uint8_t* tele) {
|
||
if (isReceiveCmder) {
|
||
memcpy(tele, rec_cmder_fromdds, rec_len_fromdds);
|
||
isReceiveCmder = 0;
|
||
memset(rec_cmder_fromdds, 0, 255);
|
||
return rec_len_fromdds;
|
||
} else {
|
||
tele[0] = 0xEB; tele[1] = 0x90; tele[2] = 0xB4;
|
||
tele[3] = 0x00; tele[4] = 0x00; tele[5] = 0xB4;
|
||
return 6;
|
||
}
|
||
}
|
||
|
||
//====================================== 监听线程 ======================================//
|
||
|
||
void* listen_serial_thread(void* arg) {
|
||
WriteLog("串口监听线程启动,监听接收串口");
|
||
|
||
uint8_t read_buffer[256];
|
||
|
||
while (keep_running) {
|
||
int bytes_read = read_from_serial(PORT_RX, read_buffer, sizeof(read_buffer));
|
||
|
||
if (bytes_read > 0) {
|
||
process_tm_buffer(read_buffer, bytes_read);
|
||
} else if (bytes_read < 0) {
|
||
usleep(100000); // 100ms
|
||
} else {
|
||
usleep(10000); // 10ms
|
||
}
|
||
}
|
||
|
||
WriteLog("串口监听线程停止");
|
||
return NULL;
|
||
}
|
||
|
||
int start_listen_thread() {
|
||
if (socat_ports[PORT_RX].fd < 0) {
|
||
WriteLog("错误:接收串口未初始化");
|
||
return -1;
|
||
}
|
||
|
||
keep_running = 1;
|
||
int ret = pthread_create(&listen_thread, NULL, listen_serial_thread, NULL);
|
||
if (ret != 0) {
|
||
WriteLog("错误:无法创建监听线程");
|
||
return -1;
|
||
}
|
||
|
||
return 0;
|
||
}
|
||
|
||
void stop_listen_thread() {
|
||
keep_running = 0;
|
||
if (listen_thread) {
|
||
pthread_join(listen_thread, NULL);
|
||
listen_thread = 0;
|
||
}
|
||
}
|
||
|
||
//====================================== 主程序接口 ======================================//
|
||
|
||
void hook_rs422_kk(const char* tx_port, const char* rx_port) {
|
||
WriteLog("初始化RS422通信模块");
|
||
WriteLog("发送串口: " + string(tx_port ? tx_port : "未指定"));
|
||
WriteLog("接收串口: " + string(rx_port ? rx_port : "未指定"));
|
||
|
||
// 初始化串口
|
||
int success_count = 0;
|
||
|
||
if (init_socat_serial(PORT_TX, tx_port) == 0) {
|
||
success_count++;
|
||
}
|
||
|
||
if (init_socat_serial(PORT_RX, rx_port) == 0) {
|
||
success_count++;
|
||
}
|
||
|
||
if (success_count >= 2) {
|
||
WriteLog("成功初始化所有串口");
|
||
} else if (success_count >= 1) {
|
||
WriteLog("警告:只初始化了 " + to_string(success_count) + " 个串口");
|
||
WriteLog("错误:无法正常工作,至少需要两个串口");
|
||
return;
|
||
} else {
|
||
WriteLog("错误:未能初始化任何串口");
|
||
return;
|
||
}
|
||
|
||
// 初始化DDS
|
||
pkginit(1, "rs422_app", "hook_rs422");
|
||
|
||
// 订阅DDS消息
|
||
PkgSubO2_AKkData(cjb_rs422_kk_receive);
|
||
pkgSubO_1KKData(cjb_rs422_kk_receive);
|
||
WriteLog("已订阅O2-A和O-1数据");
|
||
|
||
// 启动监听线程
|
||
if (start_listen_thread() == 0) {
|
||
WriteLog("串口监听线程已启动");
|
||
} else {
|
||
WriteLog("错误:未能启动串口监听线程");
|
||
}
|
||
}
|
||
|
||
void set_scomm_enable(uint8_t s_en) {
|
||
scomm_enable = s_en;
|
||
WriteLog("设置通信使能: " + to_string(s_en));
|
||
}
|
||
|
||
void cleanup_hook_rs422() {
|
||
WriteLog("清理RS422通信模块资源");
|
||
|
||
stop_listen_thread();
|
||
cleanup_all_socat_serial();
|
||
|
||
if (simMsg) {
|
||
delete simMsg;
|
||
simMsg = nullptr;
|
||
WriteLog("清理DDS资源");
|
||
}
|
||
}
|
||
|
||
//====================================== 信号处理 ======================================//
|
||
|
||
void signal_handler(int signum) {
|
||
keep_running = 0;
|
||
}
|
||
|
||
//====================================== 主函数 ======================================//
|
||
|
||
int main(int argc, char* argv[]) {
|
||
WriteLog("========================================");
|
||
WriteLog("RS422通信程序启动");
|
||
WriteLog("使用方式: " + string(argv[0]) + " <发送串口> <接收串口>");
|
||
WriteLog("示例: " + string(argv[0]) + " /dev/pts/12 /dev/pts/25");
|
||
WriteLog("========================================");
|
||
|
||
// 检查参数
|
||
if (argc < 3) {
|
||
WriteLog("错误:参数不足");
|
||
WriteLog("请指定发送串口和接收串口:");
|
||
WriteLog(" " + string(argv[0]) + " /dev/pts/12 /dev/pts/25");
|
||
WriteLog("或使用默认值:");
|
||
WriteLog(" " + string(argv[0]) + " /dev/pts/12 /dev/pts/25");
|
||
return 1;
|
||
}
|
||
|
||
const char* tx_port = argv[1];
|
||
const char* rx_port = argv[2];
|
||
|
||
// 设置信号处理
|
||
signal(SIGINT, signal_handler);
|
||
signal(SIGTERM, signal_handler);
|
||
signal(SIGQUIT, signal_handler);
|
||
|
||
// 启动RS422通信模块
|
||
hook_rs422_kk(tx_port, rx_port);
|
||
|
||
// 主循环
|
||
while (keep_running) {
|
||
sleep(1);
|
||
|
||
static int counter = 0;
|
||
if (counter++ % 60 == 0) {
|
||
string tx_path = socat_ports[PORT_TX].device_path;
|
||
string rx_path = socat_ports[PORT_RX].device_path;
|
||
WriteLog("程序运行中... 发送串口:" + tx_path + " 接收串口:" + rx_path);
|
||
}
|
||
}
|
||
|
||
// 清理资源
|
||
cleanup_hook_rs422();
|
||
|
||
return 0;
|
||
} |