using System; using System.Text.RegularExpressions; using IoTClient.Clients.PLC; using IoTClient.Common.Enums; namespace StandardScene.Signal.Plc { /// 西门子 S7 长连接。地址兼容 Hsl 的 DB1.0 与 IoTClient 的 DB1.DBB0。 public sealed class SiemensPlcSession : IDisposable { private static readonly Regex BareDbByte = new Regex(@"^DB(\d+)\.(\d+)$", RegexOptions.IgnoreCase | RegexOptions.Compiled); private readonly SiemensVersion _version; private readonly string _ip; private readonly int _port; private readonly byte _slot; private SiemensClient _client; private readonly object _sync = new object(); public SiemensPlcSession(string version, string ip, int port, int slot) { _version = ParseVersion(version); _ip = ip ?? ""; _port = port > 0 ? port : 102; _slot = (byte)Math.Max(0, slot); } public bool Connected { get { lock (_sync) return _client?.Connected == true; } } public bool EnsureOpen() { lock (_sync) { try { if (_client == null) _client = new SiemensClient(_version, _ip, _port, _slot); if (_client.Connected) return true; var r = _client.Open(); return r != null && r.IsSucceed; } catch { return false; } } } public bool TryReadByte(string address, out byte value) { value = 0; if (string.IsNullOrWhiteSpace(address) || !EnsureOpen()) return false; try { var r = _client.ReadByte(NormalizeByteAddress(address)); if (r == null || !r.IsSucceed) return false; value = r.Value; return true; } catch { return false; } } public bool TryWriteByte(string address, byte value) { if (string.IsNullOrWhiteSpace(address) || !EnsureOpen()) return false; try { var r = _client.Write(NormalizeByteAddress(address), value); return r != null && r.IsSucceed; } catch { return false; } } public bool TryReadBool(string address, out bool value) { value = false; if (string.IsNullOrWhiteSpace(address) || !EnsureOpen()) return false; try { var r = _client.ReadBoolean(address.Trim()); if (r == null || !r.IsSucceed) return false; value = r.Value; return true; } catch { return false; } } public bool TryWriteBool(string address, bool value) { if (string.IsNullOrWhiteSpace(address) || !EnsureOpen()) return false; try { var r = _client.Write(address.Trim(), value); return r != null && r.IsSucceed; } catch { return false; } } public void Close() { lock (_sync) { try { _client?.Close(); } catch { } _client = null; } } public void Dispose() => Close(); internal static string NormalizeByteAddress(string address) { var addr = address.Trim(); var m = BareDbByte.Match(addr); return m.Success ? $"DB{m.Groups[1].Value}.DBB{m.Groups[2].Value}" : addr; } internal static SiemensVersion ParseVersion(string version) { if (string.IsNullOrWhiteSpace(version)) return SiemensVersion.S7_1500; return Enum.TryParse(version.Replace("-", "_"), true, out SiemensVersion parsed) ? parsed : SiemensVersion.S7_1500; } } }