| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135 |
- using System;
- using System.ComponentModel;
- using System.Threading.Tasks;
- using HslCommunication;
- using HslCommunication.Profinet.Melsec;
- using Newtonsoft.Json;
- using TeamAAS.Communication.Attributes;
- using TeamAAS.Communication.Base;
- using TeamAAS.Communication.Interfaces;
- namespace TeamAAS.Communication.PLCs
- {
- [Communication("三菱 PLC", "PLC", "HslCommunication MC协议 TCP")]
- public class MitsubishiPlc : PlcCommunicationBase
- {
- [JsonIgnore] private MelsecMcNet _mc;
- [JsonIgnore] private bool _connected;
- public override string PlcVendor => "三菱 MC";
- 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 = 6000;
- [Category("II.连接配置"), DisplayName("端口"), Description("PLC 端口(默认 6000)")]
- public int Port { get { return _port; } set { if (SetProperty(ref _port, value)) Notify(nameof(EndpointUrl)); } }
- 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<object, bool> ConnectChangedEvent;
- public override event Action<object, string> DataReceivedEvent;
- public MitsubishiPlc() { }
- public override void Connect()
- {
- if (string.IsNullOrWhiteSpace(IpAddress))
- throw new InvalidOperationException("三菱 PLC IP 不能为空。");
- if (Port <= 0)
- throw new InvalidOperationException("三菱 PLC 端口必须大于 0。");
- Disconnect();
- _mc = new MelsecMcNet { IpAddress = IpAddress, Port = Port, ConnectTimeOut = 2000 };
- var result = _mc.ConnectServer();
- if (!result.IsSuccess)
- {
- _mc = null;
- throw new InvalidOperationException("三菱 PLC 连接失败: " + result.Message);
- }
- Driver = _mc;
- _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 (_mc != null)
- {
- try { _mc.ConnectClose(); } catch { }
- _mc = null;
- }
- ConnectChangedEvent?.Invoke(this, false);
- Notify(nameof(IsConnected));
- }
- public override void Dispose() => Disconnect();
- private static string GetPrefix(string address)
- {
- var t = address.Trim().ToUpperInvariant();
- int i = 0;
- while (i < t.Length && char.IsLetter(t[i])) i++;
- if (i == 0) throw new FormatException($"无效的三菱地址: {address}");
- return t.Substring(0, i);
- }
- private static bool IsBitDevice(string address)
- {
- switch (GetPrefix(address))
- {
- case "M": case "X": case "Y": case "B": case "F": case "T": case "C": case "SM": case "L": case "S":
- return true;
- default:
- return false;
- }
- }
- public override object ReadValue(string address, DebugDataType type, ushort length = 1)
- {
- if (Driver == null) throw new InvalidOperationException("三菱 PLC 尚未连接。");
- bool isBit = IsBitDevice(address);
- if (isBit && type != DebugDataType.Bool)
- throw new InvalidOperationException($"{address} 是位设备({GetPrefix(address)}),只支持 Bool 类型读取");
- if (!isBit && type == DebugDataType.Bool)
- throw new InvalidOperationException($"{address} 是字设备({GetPrefix(address)}),不支持 Bool 类型读取");
- return base.ReadValue(address, type, length);
- }
- public override void WriteValue(string address, object value, DebugDataType type, ushort length = 1)
- {
- if (Driver == null) throw new InvalidOperationException("三菱 PLC 尚未连接。");
- bool isBit = IsBitDevice(address);
- if (isBit && type != DebugDataType.Bool)
- throw new InvalidOperationException($"{address} 是位设备({GetPrefix(address)}),只支持 Bool 类型写入");
- if (!isBit && type == DebugDataType.Bool)
- throw new InvalidOperationException($"{address} 是字设备({GetPrefix(address)}),不支持 Bool 类型写入");
- base.WriteValue(address, value, type, length);
- }
- }
- }
|