led_ctrl/src/main.cpp
2025-06-05 11:04:06 +08:00

205 lines
4.9 KiB
C++

#include <iostream>
#include <fstream>
#include "toml.hpp"
#include <chrono>
#include <thread>
#include <csignal>
#include <atomic>
#include "SerialPort.h"
#include "LedCommand.h"
#include "LedMqttSubscriber.h"
using namespace toml;
// 声明全局变量
int led_num = 0;
std::atomic<bool> 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<std::string>(data, "serial", "port");
baudrate = toml::find<int>(data, "serial", "baudrate");
led_num = toml::find<int>(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;
}