using System; using System.ComponentModel; using System.Threading.Tasks; using HslCommunication.Profinet.Siemens; using Newtonsoft.Json; using TeamAAS.Communication.Attributes; using TeamAAS.Communication.Base; namespace TeamAAS.Communication.PLCs { [Communication("西门子 S7", "PLC", "HslCommunication SiemensS7Net")] public class SiemensS7Plc : PlcCommunicationBase { [JsonIgnore] private SiemensS7Net _s7; [JsonIgnore] private bool _connected; public override string PlcVendor => "西门子 S7"; private string _ipAddress = "127.0.0.1"; [Category("II.连接配置"), DisplayName("IP 地址"), Description("PLC IP 地址")] public string IpAddress { get { return _ipAddress; } set { if (SetProperty(ref _ipAddress, value)) Notify(nameof(EndpointUrl)); } } private int _port = 102; [Category("II.连接配置"), DisplayName("端口"), Description("PLC 端口(默认 102)")] public int Port { get { return _port; } set { if (SetProperty(ref _port, value)) Notify(nameof(EndpointUrl)); } } private SiemensPLCS _plcType = SiemensPLCS.S1200; [Category("III.PLC 配置"), DisplayName("CPU 型号"), Description("西门子 S7 CPU 型号")] public SiemensPLCS PlcType { get { return _plcType; } set { SetProperty(ref _plcType, value); } } public override string EndpointUrl { get { return $"tcp://{IpAddress}:{Port}"; } set { if (!string.IsNullOrWhiteSpace(value) && value.StartsWith("tcp://")) { var uri = new Uri(value); IpAddress = uri.Host; Port = uri.Port; } } } [JsonIgnore, Browsable(false)] public override bool IsConnected => _connected; public override event Action ConnectChangedEvent; public override event Action DataReceivedEvent; public SiemensS7Plc() { } public override void Connect() { if (string.IsNullOrWhiteSpace(IpAddress)) throw new InvalidOperationException("西门子 PLC IP 不能为空。"); if (Port <= 0) throw new InvalidOperationException("西门子 PLC 端口必须大于 0。"); Disconnect(); _s7 = new SiemensS7Net(PlcType, IpAddress) { Port = Port, ConnectTimeOut = 2000 }; var result = _s7.ConnectServer(); if (!result.IsSuccess) { _s7 = null; throw new InvalidOperationException("西门子 PLC 连接失败: " + result.Message); } Driver = _s7; _connected = true; ConnectChangedEvent?.Invoke(this, true); Notify(nameof(IsConnected)); } public override Task ConnectAsync() => Task.Run(() => Connect()); public override void Disconnect() { _connected = false; Driver = null; if (_s7 != null) { try { _s7.ConnectClose(); } catch { } _s7 = null; } ConnectChangedEvent?.Invoke(this, false); Notify(nameof(IsConnected)); } public override void Dispose() => Disconnect(); } }