|
- #pragma once
-
- #include "domain/register_address.h"
- #include "domain/project_limits.h"
-
- #include <algorithm>
- #include <cctype>
- #include <functional>
- #include <string>
- #include <vector>
-
- struct PlcSerialConfiguration
- {
- std::string portName;
- int serverAddress = 1;
- int baudRate = 9600;
- int dataBits = 8;
- int parity = 2;
- int stopBits = 1;
- int responseTimeoutMs = 1000;
- int retries = 2;
- int pollIntervalMs = 200;
- };
-
- enum class PlcConnectionState
- {
- Disconnected,
- Connecting,
- Connected,
- Recovering,
- Faulted
- };
-
- enum class PlcCommunicationError
- {
- None,
- SerialPortOpenFailed,
- PlcNotResponding,
- UsbSerialAdapterRemoved,
- SerialConnectionLost,
- CommunicationTimeout,
- ProtocolError,
- ReadFailed,
- WriteFailed,
- ConfigurationError,
- RequestAborted,
- Unknown
- };
-
- struct PlcCommunicationResult
- {
- bool succeeded = false;
- std::string message;
- };
-
- inline PlcCommunicationResult validatePlcSerialConfiguration(
- const PlcSerialConfiguration &configuration)
- {
- const bool has_port_name = std::any_of(
- configuration.portName.cbegin(), configuration.portName.cend(),
- [](unsigned char character) { return std::isspace(character) == 0; });
- if (!has_port_name)
- {
- return {false, "必须填写串口端口"};
- }
- if (configuration.serverAddress < ProjectLimits::kMinimumPlcServerAddress
- || configuration.serverAddress > ProjectLimits::kMaximumPlcServerAddress)
- {
- return {false, "PLC 站号必须在 1~247 范围内"};
- }
- if (configuration.baudRate != 9600
- && configuration.baudRate != 19200
- && configuration.baudRate != 38400
- && configuration.baudRate != 57600
- && configuration.baudRate != 115200)
- {
- return {false, "波特率只支持 9600、19200、38400、57600 或 115200"};
- }
- if (configuration.dataBits != 7 && configuration.dataBits != 8)
- {
- return {false, "数据位只支持 7 或 8"};
- }
- if (configuration.parity != 0
- && configuration.parity != 2
- && configuration.parity != 3)
- {
- return {false, "校验方式只支持无校验、偶校验或奇校验"};
- }
- if (configuration.stopBits != 1 && configuration.stopBits != 2)
- {
- return {false, "停止位只支持 1 或 2"};
- }
- if (configuration.responseTimeoutMs < ProjectLimits::kMinimumResponseTimeoutMs
- || configuration.responseTimeoutMs > ProjectLimits::kMaximumResponseTimeoutMs)
- {
- return {false, "PLC 响应超时必须在 100~30000 ms 范围内"};
- }
- if (configuration.retries < ProjectLimits::kMinimumRetries
- || configuration.retries > ProjectLimits::kMaximumRetries)
- {
- return {false, "PLC 失败重试次数必须在 0~5 范围内"};
- }
- if (configuration.pollIntervalMs < ProjectLimits::kMinimumPollIntervalMs
- || configuration.pollIntervalMs > ProjectLimits::kMaximumPollIntervalMs)
- {
- return {false, "PLC 轮询周期必须在 50~10000 ms 范围内"};
- }
- return {true, {}};
- }
-
- class PlcCommunicationGateway
- {
- public:
- virtual ~PlcCommunicationGateway() = default;
-
- virtual PlcCommunicationResult connectDevice(
- const PlcSerialConfiguration &configuration) = 0;
- virtual void disconnectDevice() = 0;
- virtual PlcCommunicationResult setPollAddresses(
- const std::vector<RegisterAddress> &addresses) = 0;
- virtual PlcConnectionState state() const = 0;
- virtual bool initialReadCompleted() const = 0;
- virtual PlcCommunicationError lastErrorType() const = 0;
- virtual const std::string &lastError() const = 0;
- virtual void setCallbacks(
- std::function<void()> state_changed,
- std::function<void(bool)> initial_read_changed,
- std::function<void()> cache_updated,
- std::function<void(const std::string &)> error_reported) = 0;
- };
|