GrabBag/Module/ModbusTCPServer/_Inc/ModbusTCPServer.h
2025-06-08 12:48:04 +08:00

123 lines
4.4 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#ifndef MODBUS_TCP_SERVER_H
#define MODBUS_TCP_SERVER_H
#include "IYModbusTCPServer.h"
#include <functional>
#include <vector>
#include <thread>
#include <mutex>
#include <atomic>
#include <memory>
#include <unordered_map>
// libmodbus headers
extern "C" {
#include "modbus.h"
#include "modbus-tcp.h"
}
class ModbusTCPServer : public IYModbusTCPServer {
private:
// 客户端连接结构体
struct ClientConnection {
int socket;
modbus_t* modbusCtx;
ClientConnection(int sock, modbus_t* ctx) : socket(sock), modbusCtx(ctx) {}
~ClientConnection() {
if (modbusCtx) {
modbus_free(modbusCtx);
}
#ifdef _WIN32
if (socket != -1) {
closesocket(socket);
}
#else
if (socket != -1) {
close(socket);
}
#endif
}
};
public:
ModbusTCPServer();
virtual ~ModbusTCPServer() override;
// 实现IYModbusTCPServer接口
// 启动/停止服务器
virtual bool start(int port = 502, int maxConnections = 10) override;
virtual void stop() override;
bool isRunning() const { return m_isRunning.load(); }
// 设置回调函数
virtual void setWriteCoilsCallback(WriteCoilsCallback callback) override { m_writeCoilsCallback = callback; }
virtual void setWriteRegistersCallback(WriteRegistersCallback callback) override { m_writeRegistersCallback = callback; }
// 数据更新接口 - 线程安全
virtual void updateCoil(uint16_t address, bool value) override;
virtual void updateCoils(uint16_t startAddress, const std::vector<bool>& values) override;
virtual void updateDiscreteInput(uint16_t address, bool value) override;
virtual void updateDiscreteInputs(uint16_t startAddress, const std::vector<bool>& values) override;
virtual void updateHoldingRegister(uint16_t address, uint16_t value) override;
virtual void updateHoldingRegisters(uint16_t startAddress, const std::vector<uint16_t>& values) override;
virtual void updateInputRegister(uint16_t address, uint16_t value) override;
virtual void updateInputRegisters(uint16_t startAddress, const std::vector<uint16_t>& values) override;
// 获取错误信息
std::string getLastError() const;
private:
// 服务器主循环
void serverLoop();
// 客户端连接管理
void handleNewConnection();
void handleClientData(std::shared_ptr<ClientConnection> client);
void removeClient(int socket);
void processModbusRequest(std::shared_ptr<ClientConnection> client, const uint8_t* query, int queryLength);
// 数据读取处理器libmodbus内部调用
static int readCoilsHandler(modbus_t *ctx, int function_code, int addr, int nb, uint8_t *rsp, int *rsp_length, void *user_data);
static int readDiscreteInputsHandler(modbus_t *ctx, int function_code, int addr, int nb, uint8_t *rsp, int *rsp_length, void *user_data);
static int readHoldingRegistersHandler(modbus_t *ctx, int function_code, int addr, int nb, uint8_t *rsp, int *rsp_length, void *user_data);
static int readInputRegistersHandler(modbus_t *ctx, int function_code, int addr, int nb, uint8_t *rsp, int *rsp_length, void *user_data);
// 数据写入函数libmodbus内部调用
static int writeCoilsHandler(modbus_t *ctx, int function_code, int addr, int nb, const uint8_t *req, int req_length, void *user_data);
static int writeRegistersHandler(modbus_t *ctx, int function_code, int addr, int nb, const uint8_t *req, int req_length, void *user_data);
private:
// libmodbus context
modbus_t* m_modbusCtx;
modbus_mapping_t* m_mapping;
// 服务器状态
std::atomic<bool> m_isRunning;
std::atomic<bool> m_shouldStop;
std::unique_ptr<std::thread> m_serverThread;
int m_serverSocket;
int m_port;
int m_maxConnections;
// 客户端连接管理
std::unordered_map<int, std::shared_ptr<ClientConnection>> m_clients;
std::mutex m_clientsMutex;
// 数据存储 - 使用libmodbus的mapping结构
std::mutex m_dataMutex;
// 回调函数
WriteCoilsCallback m_writeCoilsCallback;
WriteRegistersCallback m_writeRegistersCallback;
// 错误信息
mutable std::mutex m_errorMutex;
std::string m_lastError;
// 设置错误信息
void setLastError(const std::string& error);
};
#endif // MODBUS_TCP_SERVER_H