新增 scene.signal 信号交互插件,落地 PLC 握手与扫车放行。
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -0,0 +1,152 @@
|
||||
using System;
|
||||
using System.Text.RegularExpressions;
|
||||
using IoTClient.Clients.PLC;
|
||||
using IoTClient.Common.Enums;
|
||||
|
||||
namespace StandardScene.Signal.Plc
|
||||
{
|
||||
/// <summary>西门子 S7 长连接。地址兼容 Hsl 的 DB1.0 与 IoTClient 的 DB1.DBB0。</summary>
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user