#include "ModbusRTUMaster.h" #include "VrLog.h" #include #include 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 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& callback) { std::lock_guard lock(m_mutex); m_temperatureCallback = callback; LOG_DEBUG("Temperature callback set for ModbusRTUMaster\n"); }