261 lines
8.6 KiB
C++
Raw Normal View History

2025-09-29 00:56:53 +08:00
#include "RobotProtocol.h"
#include "VrLog.h"
#include "VrError.h"
#include "IYModbusTCPServer.h"
#include <cstring>
#include <algorithm>
RobotProtocol::RobotProtocol()
: m_pModbusServer(nullptr)
, m_bServerRunning(false)
, m_nPort(502)
, m_robotStatus(STATUS_DISCONNECTED)
{
}
RobotProtocol::~RobotProtocol()
{
Deinitialize();
}
int RobotProtocol::Initialize(uint16_t port)
{
if (m_bServerRunning) {
LOG_WARNING("Server is already running\n");
return SUCCESS;
}
m_nPort = port;
// 创建ModbusTCP服务器实例
bool bRet = IYModbusTCPServer::CreateInstance(&m_pModbusServer);
LOG_DEBUG("Create ModbusTCP server %s \n", bRet ? "success" : "failed");
m_bServerRunning = bRet;
// 设置ModbusTCP回调函数
if (m_pModbusServer) {
// 设置写线圈回调
m_pModbusServer->setWriteCoilsCallback([this](uint8_t unitId, uint16_t startAddress, uint16_t quantity, const uint8_t* values) {
return this->OnWriteCoils(unitId, startAddress, quantity, values);
});
// 设置写寄存器回调
m_pModbusServer->setWriteRegistersCallback([this](uint8_t unitId, uint16_t startAddress, uint16_t quantity, const uint16_t* values) {
return this->OnWriteRegisters(unitId, startAddress, quantity, values);
});
// 设置连接状态回调
m_pModbusServer->setConnectionStatusCallback([this](bool connected) {
this->OnModbusTCPConnectionChanged(connected);
});
}
int nRet = m_pModbusServer->start(m_nPort);
ERR_CODE_RETURN(nRet);
// 设置初始状态
m_robotStatus = STATUS_CONNECTED;
// 设置初始工作状态为空闲
SetWorkStatus(WORK_STATUS_IDLE);
LOG_INFO("ModbusTCP service initialization completed\n");
return SUCCESS;
}
void RobotProtocol::Deinitialize()
{
LOG_DEBUG("Stop ModbusTCP service\n");
// 停止ModbusTCP服务器
StopModbusTCPServer();
// 重置状态
m_robotStatus = STATUS_DISCONNECTED;
m_bServerRunning = false;
LOG_INFO("ModbusTCP service stopped\n");
}
int RobotProtocol::SetMultiTargetData(const MultiTargetData& multiTargetData)
{
// 数据格式: count + 每个目标的{id,status,width,depth}数据每个数据占2个寄存器
std::vector<uint16_t> data;
// 限制最大目标数量
size_t actualCount = multiTargetData.targets.size() > 5 ? 5 : multiTargetData.targets.size();
data.resize(actualCount * 16);
memset(data.data(), 0, data.size() * sizeof(uint16_t));
// 定义一个辅助函数来转换uint32_t到ModbusTCP寄存器顺序大端格式
auto uint32ToBigEndian = [&](uint16_t addr, uint32_t value) {
// ModbusTCP寄存器顺序大端高16位寄存器在前低16位寄存器在后
data[addr] = (value >> 16) & 0xFFFF; // 高16位寄存器
data[addr+1] = value & 0xFFFF; // 低16位寄存器
};
// 定义一个辅助函数来转换float到ModbusTCP寄存器顺序大端格式
auto floatToBigEndian = [&](uint16_t addr, float value) {
uint32_t intValue;
memcpy(&intValue, &value, sizeof(float));
// ModbusTCP寄存器顺序大端高16位寄存器在前低16位寄存器在后
data[addr] = (intValue >> 16) & 0xFFFF; // 高16位寄存器
data[addr+1] = intValue & 0xFFFF; // 低16位寄存器
};
// 定义一个辅助函数来转换uint16_t到ModbusTCP寄存器
auto uint16ToBigEndian = [&](uint16_t addr, uint16_t value) {
data[addr] = value; // uint16_t直接存储
};
// 从第二个寄存器开始存储目标数据 count [{id,status,width,depth}, {id,status,width,depth}]
for (size_t i = 0; i < actualCount; i++) {
uint16_t addr = i * RESULT_OFFSET_ADDR;
const TargetResult& target = multiTargetData.targets[i];
// 按照 id, status, width, depth 的顺序存储每个目标的数据
uint32ToBigEndian(addr, target.id); // ID (2个寄存器)
uint16ToBigEndian(addr+2, target.status); // Status (1个寄存器)
floatToBigEndian(addr+3, target.width); // Width (2个寄存器)
floatToBigEndian(addr+5, target.depth); // Depth (2个寄存器)
}
m_pModbusServer->updateHoldingRegisters(DETECT_RESULT_ADDR, data);
2025-11-26 22:44:38 +08:00
return SUCCESS;
2025-09-29 00:56:53 +08:00
}
RobotProtocol::RobotStatus RobotProtocol::GetDetectionStatus() const
{
return m_robotStatus;
}
void RobotProtocol::SetConnectionCallback(const ConnectionCallback& callback)
{
m_connectionCallback = callback;
}
void RobotProtocol::SetWorkSignalCallback(const WorkSignalCallback& callback)
{
m_workSignalCallback = callback;
}
void RobotProtocol::SetSystemControlCallback(const std::function<void(uint16_t)>& callback)
{
m_systemControlCallback = callback;
}
2025-09-29 00:56:53 +08:00
bool RobotProtocol::IsRunning() const
{
return m_bServerRunning;
}
int RobotProtocol::SetWorkStatus(uint16_t status)
{
LOG_DEBUG("Set work status to: %d\n", status);
2025-09-29 00:56:53 +08:00
if (!m_pModbusServer) {
LOG_ERROR("ModbusTCP server not initialized\n");
2025-11-26 22:44:38 +08:00
return ERR_CODE(DEV_NO_OPEN);
2025-09-29 00:56:53 +08:00
}
2025-09-29 00:56:53 +08:00
// 更新STATUS_ADDR地址的寄存器值
std::vector<uint16_t> statusData;
statusData.push_back(status);
2025-09-29 00:56:53 +08:00
m_pModbusServer->updateHoldingRegisters(STATUS_ADDR, statusData);
2025-09-29 00:56:53 +08:00
const char* statusStr = "";
switch(status) {
case WORK_STATUS_IDLE: statusStr = "空闲"; break;
case WORK_STATUS_WORKING: statusStr = "工作中"; break;
case WORK_STATUS_BUSY: statusStr = "忙碌"; break;
default: statusStr = "未知状态"; break;
}
2025-09-29 00:56:53 +08:00
LOG_INFO("Work status updated to: %d (%s)\n", status, statusStr);
2025-11-26 22:44:38 +08:00
return SUCCESS;
2025-09-29 00:56:53 +08:00
}
int RobotProtocol::ClearDetectionData()
{
LOG_INFO("Clearing detection result data in Modbus registers\n");
if (!m_pModbusServer) {
LOG_ERROR("ModbusTCP server not initialized\n");
2025-11-26 22:44:38 +08:00
return ERR_CODE(DEV_NO_OPEN);
}
// 清空检测结果数据区域地址1-80共5个撕裂信息每个16个寄存器
// 总共需要清空 5 * 16 = 80 个寄存器
std::vector<uint16_t> clearData(80, 0); // 创建80个值为0的寄存器
m_pModbusServer->updateHoldingRegisters(DETECT_RESULT_ADDR, clearData);
LOG_INFO("Detection result data cleared (registers 1-80)\n");
2025-11-26 22:44:38 +08:00
return SUCCESS;
}
2025-09-29 00:56:53 +08:00
void RobotProtocol::StopModbusTCPServer()
{
LOG_DEBUG("Stop ModbusTCP server\n");
if (m_pModbusServer) {
// 释放资源
delete m_pModbusServer;
m_pModbusServer = nullptr;
}
m_bServerRunning = false;
LOG_INFO("ModbusTCP server stopped\n");
}
IYModbusTCPServer::ErrorCode RobotProtocol::OnWriteCoils(uint8_t unitId, uint16_t startAddress, uint16_t quantity, const uint8_t* values)
{
return IYModbusTCPServer::ErrorCode::ILLEGAL_FUNCTION;
}
IYModbusTCPServer::ErrorCode RobotProtocol::OnWriteRegisters(uint8_t unitId, uint16_t startAddress, uint16_t quantity, const uint16_t* values)
{
// 只允许写入地址0系统状态寄存器
if (startAddress != STATUS_ADDR) {
LOG_WARNING("Attempt to write to read-only address: %d\n", startAddress);
return IYModbusTCPServer::ErrorCode::ILLEGAL_DATA_ADDRESS;
}
// 只允许写入单个寄存器
if (quantity != 1) {
LOG_WARNING("Invalid quantity for status register write: %d\n", quantity);
return IYModbusTCPServer::ErrorCode::ILLEGAL_DATA_VALUE;
}
if (!values) {
LOG_ERROR("Null values pointer in write registers\n");
return IYModbusTCPServer::ErrorCode::SERVER_FAILURE;
}
uint16_t command = values[0];
// 验证命令值是否有效0-停止, 1-开始, 2-复位)
if (command > 2) {
LOG_WARNING("Invalid system control command: %d\n", command);
return IYModbusTCPServer::ErrorCode::ILLEGAL_DATA_VALUE;
}
LOG_INFO("Received system control command via ModbusTCP: %d\n", command);
// 调用系统控制回调
if (m_systemControlCallback) {
m_systemControlCallback(command);
LOG_DEBUG("System control callback executed for command: %d\n", command);
} else {
LOG_WARNING("System control callback not set\n");
}
return IYModbusTCPServer::ErrorCode::SUCCESS;
2025-09-29 00:56:53 +08:00
}
void RobotProtocol::OnModbusTCPConnectionChanged(bool connected)
{
}