#include #include #include "toml.hpp" #include #include #include #include #include "SerialPort.h" #include "LedCommand.h" #include "LedMqttSubscriber.h" using namespace toml; // 声明全局变量 int led_num = 0; std::atomic running(true); // 信号处理器 void signalHandler(int signum) { std::cout << "\n收到中断信号 (" << signum << "),准备退出..." << std::endl; running = false; } class BreathingLight { public: BreathingLight() : brightness(0), step(15), increasing(true) {} void update(SerialPort &serial) { LedCommand cmd; cmd.setColor(brightness, brightness, 0); // 黄色 cmd.setExtCount(led_num); auto packet = cmd.serialize(); if (!serial.writeData(packet.data(), packet.size())) { std::cerr << "发送数据失败" << std::endl; } if (increasing) { brightness += step; if (brightness >= 255) { brightness = 255; increasing = false; } } else { brightness -= step; if (brightness <= 0) { brightness = 0; increasing = true; } } } private: int brightness; int step; bool increasing; }; // 常红灯 void alwaysRed(SerialPort &serial) { LedCommand cmd; cmd.setColor(255, 0, 0); // 红色 cmd.setExtCount(led_num); auto packet = cmd.serialize(); std::cout << "发送常红数据包:"; for (auto b : packet) printf(" %02X", b); std::cout << std::endl; if (!serial.writeData(packet.data(), packet.size())) std::cerr << "发送数据失败" << std::endl; } // 常绿灯 void alwaysGreen(SerialPort &serial) { LedCommand cmd; cmd.setColor(0, 255, 0); cmd.setExtCount(led_num); auto packet = cmd.serialize(); std::cout << "发送常绿数据包:"; for (auto b : packet) printf(" %02X", b); std::cout << std::endl; if (!serial.writeData(packet.data(), packet.size())) std::cerr << "发送数据失败" << std::endl; } // 关灯 void CloseLed(SerialPort &serial) { LedCommand cmd; cmd.setColor(0, 0, 0); cmd.setExtCount(led_num); auto packet = cmd.serialize(); std::cout << "发送关闭数据包:"; for (auto b : packet) printf(" %02X", b); std::cout << std::endl; if (!serial.writeData(packet.data(), packet.size())) std::cerr << "发送数据失败" << std::endl; } int main() { // 注册信号处理函数 std::signal(SIGINT, signalHandler); std::signal(SIGTERM, signalHandler); std::string port = "/dev/ttyS0"; int baudrate = 115200; std::ifstream ifs("../config/config.toml"); if (ifs) { try { auto data = toml::parse(ifs); if (auto serial = toml::find(data, "serial"); !serial.is_table()) { std::cerr << "serial 部分不存在或格式错误" << std::endl; return 1; } port = toml::find(data, "serial", "port"); baudrate = toml::find(data, "serial", "baudrate"); led_num = toml::find(data, "led", "num"); } catch (const std::exception &e) { std::cerr << "解析 config.toml 失败: " << e.what() << std::endl; return 1; } } else { std::cerr << "无法打开 config.toml 文件,使用默认参数。" << std::endl; } std::cout << "串口号: " << port << "\n波特率: " << baudrate << std::endl; MqttClient mqtt("../config/config.toml"); if (!mqtt.start()) { std::cerr << "MQTT 启动失败" << std::endl; return 1; } std::cout << "MQTT 连接成功,开始循环处理..." << std::endl; SerialPort serial; if (!serial.openPort(port, baudrate)) { return 1; } BreathingLight breathingLight; while (running) { mqtt.checkTimeout(std::chrono::seconds(3)); // 没消息则重置数据 int gear = mqtt.getGear(); double speed = mqtt.getSpeed(); // 根据 gear 和 speed 控制 LED LedCommand cmd; if (gear == 3) { alwaysRed(serial); } else { if (speed > 0) { breathingLight.update(serial); } else { alwaysGreen(serial); } } std::this_thread::sleep_for(std::chrono::milliseconds(100)); } CloseLed(); serial.closePort(); mqtt.disconnect(); std::cout << "程序已退出。" << std::endl; return 0; }