#pragma once #include "modbus_exception.hpp" #include "itransport.hpp" #include "transport_error.hpp" #include #include #include #include class ModbusTCP : public ITransport { public: ModbusTCP(); ~ModbusTCP() override; bool connect(const char* host, std::uint16_t port) override; void disconnect() override; bool is_connected() const override; TransportState state() const override { return state_; } TransportError last_error() const override { return last_error_; } bool read_registers(std::uint16_t addr, std::uint16_t count, std::vector& out) override; bool write_registers(std::uint16_t addr, const std::vector& values) override; void poll() override; // watchdog void reset() override; private: bool reconnect(); bool recv_all(void* buf, std::size_t len); private: // socket int sock_; std::uint16_t transaction_id_{0}; // connection info std::string host_; std::uint16_t port_{0}; // state machine TransportState state_{TransportState::Disconnected}; TransportError last_error_{TransportError::None}; ModbusException exception_; // watchdog static constexpr int WATCHDOG_SEC = 5; static constexpr int MAX_RETRY = 5; static constexpr int FAULT_RESET_SEC = 30; // Fault 후 자동 리셋 대기 std::chrono::steady_clock::time_point last_ok_; std::chrono::steady_clock::time_point fault_since_; int retry_count_{0}; bool can_io() const; };