218 lines
6.0 KiB
C++
Raw Normal View History

2025-10-24 23:19:44 +08:00
#include "ModbusRTUMaster.h"
#include "VrLog.h"
#include <cstring>
#include <QDateTime>
ModbusRTUMaster::ModbusRTUMaster(QObject *parent)
: QObject(parent)
, m_pModbusCtx(nullptr)
, m_baud(115200)
, m_parity('N')
, m_dataBit(8)
, m_stopBit(1)
, m_bInitialized(false)
, m_bRunning(false)
, m_pReadTimer(nullptr)
, m_temperatureCallback(nullptr)
{
LOG_DEBUG("ModbusRTUMaster constructor called\n");
}
ModbusRTUMaster::~ModbusRTUMaster()
{
LOG_DEBUG("ModbusRTUMaster destructor called\n");
Deinitialize();
}
int ModbusRTUMaster::Initialize(const QString& device, int baud, char parity, int dataBit, int stopBit)
{
LOG_DEBUG("Initializing ModbusRTUMaster with device: %s, baud: %d, parity: %c, dataBit: %d, stopBit: %d\n",
device.toStdString().c_str(), baud, parity, dataBit, stopBit);
// 检查是否已初始化
if (m_bInitialized) {
LOG_WARNING("ModbusRTUMaster is already initialized\n");
return 0; // 已初始化,直接返回成功
}
// 保存配置参数
m_device = device;
m_baud = baud;
m_parity = parity;
m_dataBit = dataBit;
m_stopBit = stopBit;
// 创建Modbus RTU上下文
m_pModbusCtx = modbus_new_rtu(device.toStdString().c_str(), baud, parity, dataBit, stopBit);
if (m_pModbusCtx == nullptr) {
LOG_ERROR("Failed to create modbus RTU context for device: %s\n", device.toStdString().c_str());
return -1;
}
// 设置从机地址通常为1
modbus_set_slave(m_pModbusCtx, 1);
// 设置响应超时500ms
modbus_set_response_timeout(m_pModbusCtx, 0, 500000);
// 连接设备
if (modbus_connect(m_pModbusCtx) == -1) {
LOG_ERROR("Failed to connect to modbus device: %s, error: %s\n",
device.toStdString().c_str(), modbus_strerror(errno));
modbus_free(m_pModbusCtx);
m_pModbusCtx = nullptr;
return -2;
}
// 创建读取定时器
m_pReadTimer = new QTimer(this);
connect(m_pReadTimer, &QTimer::timeout, this, &ModbusRTUMaster::OnReadTimer);
m_bInitialized = true;
LOG_INFO("ModbusRTUMaster initialized successfully with device: %s\n", device.toStdString().c_str());
return 0;
}
void ModbusRTUMaster::Deinitialize()
{
LOG_DEBUG("Deinitializing ModbusRTUMaster\n");
// 停止读取
StopReading();
// 断开连接并释放资源
if (m_pModbusCtx) {
modbus_close(m_pModbusCtx);
modbus_free(m_pModbusCtx);
m_pModbusCtx = nullptr;
}
// 删除定时器
if (m_pReadTimer) {
delete m_pReadTimer;
m_pReadTimer = nullptr;
}
m_bInitialized = false;
LOG_INFO("ModbusRTUMaster deinitialized successfully\n");
}
int ModbusRTUMaster::StartReading()
{
LOG_DEBUG("Starting ModbusRTUMaster reading\n");
// 检查是否已初始化
if (!m_bInitialized) {
LOG_ERROR("ModbusRTUMaster not initialized\n");
return -1;
}
// 检查是否已在运行
if (m_bRunning) {
LOG_WARNING("ModbusRTUMaster is already running\n");
return 0; // 已运行,直接返回成功
}
// 启动定时器每1000ms读取一次
if (m_pReadTimer) {
m_pReadTimer->start(1000);
m_bRunning = true;
LOG_INFO("ModbusRTUMaster reading started\n");
return 0;
} else {
LOG_ERROR("Read timer not initialized\n");
return -2;
}
}
void ModbusRTUMaster::StopReading()
{
LOG_DEBUG("Stopping ModbusRTUMaster reading\n");
// 停止定时器
if (m_pReadTimer && m_pReadTimer->isActive()) {
m_pReadTimer->stop();
}
m_bRunning = false;
LOG_INFO("ModbusRTUMaster reading stopped\n");
}
bool ModbusRTUMaster::IsRunning() const
{
return m_bRunning;
}
void ModbusRTUMaster::OnReadTimer()
{
// 读取温度数据
float temperature = 0.0f;
int result = ReadTemperature(temperature);
if (result == 0) {
LOG_DEBUG("Temperature read successfully: %.2f°C\n", temperature);
// 调用温度回调函数(如果已设置)
std::lock_guard<std::mutex> lock(m_mutex);
if (m_temperatureCallback) {
m_temperatureCallback(temperature);
}
} else {
LOG_ERROR("Failed to read temperature, error code: %d\n", result);
}
}
int ModbusRTUMaster::ReadTemperature(float& temperature)
{
// 检查Modbus上下文
if (!m_pModbusCtx) {
LOG_ERROR("Modbus context not initialized\n");
return -1;
}
// 读取保持寄存器
uint16_t registers[2] = {0}; // float需要2个寄存器
int rc = modbus_read_registers(m_pModbusCtx, TEMPERATURE_ADDR, TEMPERATURE_QUANTITY, registers);
if (rc == -1) {
LOG_ERROR("Failed to read registers from address 0x%02X, error: %s\n",
TEMPERATURE_ADDR, modbus_strerror(errno));
return -2;
}
// 检查读取的寄存器数量是否正确
if (rc != TEMPERATURE_QUANTITY) {
LOG_ERROR("Incorrect number of registers read. Expected: %d, Actual: %d\n",
TEMPERATURE_QUANTITY, rc);
return -3;
}
// 将寄存器数据转换为float温度值
// Modbus使用大端序存储float需要转换
uint32_t tempValue = ((uint32_t)registers[0] << 16) | registers[1];
memcpy(&temperature, &tempValue, sizeof(float));
return 0;
}
void ModbusRTUMaster::ConvertTemperatureToRegisters(float temperature, uint16_t registers[2])
{
// 将float温度值转换为Modbus寄存器格式大端序
uint32_t tempValue = 0;
memcpy(&tempValue, &temperature, sizeof(float));
// 高16位寄存器
registers[0] = (tempValue >> 16) & 0xFFFF;
// 低16位寄存器
registers[1] = tempValue & 0xFFFF;
}
void ModbusRTUMaster::SetTemperatureCallback(const std::function<void(float)>& callback)
{
std::lock_guard<std::mutex> lock(m_mutex);
m_temperatureCallback = callback;
LOG_DEBUG("Temperature callback set for ModbusRTUMaster\n");
}