using BPASmartClient.CustomResource.Pages.Model; using BPASmartClient.DosingSystem.ViewModel; using BPASmartClient.Modbus; using BPASmartClient.Model; using System; using System.Collections.Concurrent; using System.Collections.Generic; using System.Collections.ObjectModel; using System.Linq; using System.Net.NetworkInformation; using System.Threading; using System.Threading.Tasks; using BPA.Helper; using System.Text.RegularExpressions; namespace BPASmartClient.DosingSystem { public class DeviceInquire { private volatile static DeviceInquire _Instance; public static DeviceInquire GetInstance => _Instance ?? (_Instance = new DeviceInquire()); private DeviceInquire() { } string IPSegment = "192.168.0."; ConcurrentDictionary DeviceLists = new ConcurrentDictionary(); List InvalidIP = new List();//无效 IP 集合 List IPLists = new List();//启动 Ping 任务IP集合 ConcurrentQueue IPQueues = new ConcurrentQueue();//pincomplete 完成队列 public ObservableCollection TopDeviceCurrentStatuses { get; set; } = new ObservableCollection(); public ObservableCollection BottomDeviceCurrentStatuses { get; set; } = new ObservableCollection(); public ObservableCollection devices { get; set; } = new ObservableCollection(); private void DeviceDataInit() { ThreadManage.GetInstance().StartLong(new Action(() => { for (int i = 0; i < DeviceLists.Count; i++) { string deviceName = DeviceLists.ElementAt(i).Value.DeviceName; int TopIndex = Array.FindIndex(TopDeviceCurrentStatuses.ToArray(), p => p.DeviceName == deviceName); int BottomIndex = Array.FindIndex(BottomDeviceCurrentStatuses.ToArray(), p => p.DeviceName == deviceName); if (TopIndex >= 0 && TopIndex < TopDeviceCurrentStatuses.Count) { TopDeviceCurrentStatuses.ElementAt(TopIndex).Weight = DeviceLists.ElementAt(i).Value.deviceStatus.WeightFeedback; TopDeviceCurrentStatuses.ElementAt(TopIndex).DeviceNum = DeviceLists.ElementAt(i).Value.deviceStatus.DeviceNum; } if (BottomIndex >= 0 && BottomIndex < BottomDeviceCurrentStatuses.Count) { BottomDeviceCurrentStatuses.ElementAt(BottomIndex).Weight = DeviceLists.ElementAt(i).Value.deviceStatus.WeightFeedback; BottomDeviceCurrentStatuses.ElementAt(BottomIndex).DeviceNum = DeviceLists.ElementAt(i).Value.deviceStatus.DeviceNum; } int deviceIndex = Array.FindIndex(devices.ToArray(), p => p.IpAddress == DeviceLists.ElementAt(i).Key/* && p.DeviceName != DeviceLists.ElementAt(i).Value.DeviceName && p.DeviceNum != DeviceLists.ElementAt(i).Value.deviceStatus.DeviceNum*/); if (deviceIndex >= 0 && deviceIndex < devices.Count) { devices.ElementAt(deviceIndex).DeviceName = DeviceLists.ElementAt(i).Value.DeviceName; devices.ElementAt(deviceIndex).DeviceNum = DeviceLists.ElementAt(i).Value.deviceStatus.DeviceNum; } } Thread.Sleep(200); }), "设备状态监听", true); } private void aa(int num, string name) { DeviceLists.TryAdd($"192.168.1.{num}", new DeviceStatus() { DeviceName = $"{name}" }); TopDeviceCurrentStatuses.Add(new DeviceCurrentStatus() { DeviceName = $"{name}", DeviceNum = num, Weight = new Random().Next(100, 10000) / 100.0 }); Global.DeviceRawMaterials.Add(new RawMaterialModel() { DeviceIp = $"192.168.1.{num}", RawMaterialName = $"{name}", }); devices.Add(new Devices() { DeviceName = $"{name}", DeviceNum = num, IpAddress = $"192.168.1.{num}", }); } private void TestData() { aa(1, "盐"); aa(2, "郫县豆瓣"); aa(3, "芥菜"); aa(4, "调味剂"); aa(5, "香料"); aa(6, "鸡精"); aa(7, "味精"); for (int i = 0; i < 8; i++) { DeviceLists.TryAdd($"192.168.1.{i + 1}", new DeviceStatus() { DeviceName = $"测试设备{i + 1}" }); TopDeviceCurrentStatuses.Add(new DeviceCurrentStatus() { DeviceName = $"测试设备{i + 1}", DeviceNum = i + 1, Weight = new Random().Next(100, 10000) / 100.0 }); Global.DeviceRawMaterials.Add(new RawMaterialModel() { DeviceIp = $"192.168.1.{i + 1}", RawMaterialName = $"测试设备{i + 1}", }); devices.Add(new Devices() { DeviceName = $"测试设备{i + 1}", DeviceNum = i + 1, IpAddress = $"192.168.1.{i + 1}", }); } for (int i = 8; i < 16; i++) { DeviceLists.TryAdd($"192.168.1.{i + 1}", new DeviceStatus() { DeviceName = $"测试设备{i + 1}" }); BottomDeviceCurrentStatuses.Add(new DeviceCurrentStatus() { DeviceName = $"测试设备{i + 1}", DeviceNum = i + 1, Weight = new Random().Next(100, 10000) / 100.0 }); Global.DeviceRawMaterials.Add(new RawMaterialModel() { DeviceIp = $"192.168.1.{i + 1}", RawMaterialName = $"测试设备{i + 1}", }); devices.Add(new Devices() { DeviceName = $"测试设备{i + 1}", DeviceNum = i + 1, IpAddress = $"192.168.1.{i + 1}", }); } } public void Init() { if (!string.IsNullOrEmpty(Json.Data.BaseParModel.NetworkSegAddress)) IPSegment = Json.Data.BaseParModel.NetworkSegAddress; else Json.Data.BaseParModel.NetworkSegAddress = IPSegment; TestData(); IpAddressLines(); SiemensDevice.GetInstance.Connect(Json.Data.BaseParModel.DeviceAddress); DeviceDataInit(); ThreadManage.GetInstance().StartLong(new Action(() => { if (IPQueues.Count >= IPLists.Count) IpAddressLines(); Thread.Sleep(5000); }), "配料机设备上线监听", true); } public void Rescan() { InvalidIP.Clear(); } public DeviceStatus GetDevice(string ip) { if (ip != null) { if (DeviceLists.ContainsKey(ip)) return DeviceLists[ip]; else return new DeviceStatus(); //var res = DeviceLists.Values.FirstOrDefault(p => p.IpAddress == ip); //if (res != null) return res; } return new DeviceStatus(); } public List GetDevice() { List deviceStatuses = new List(); foreach (var device in DeviceLists) { deviceStatuses.Add(device.Value); } return deviceStatuses; } private void IpAddressLines() { IPLists.Clear(); IPQueues.Clear(); /*for (int i = 1; i <= 255; i++) { if (!InvalidIP.Contains($"{IPSegment}{i}") && !DeviceLists.ContainsKey($"{IPSegment}{i}")) { string pattern = @"^(([1-9]\d?)|(1\d{2})|(2[01]\d)|(22[0-3]))(\.((1?\d\d?)|(2[04]/d)|(25[0-5]))){3}$"; if (Regex.IsMatch($"{IPSegment}{i}", pattern)) { IPLists.Add($"{IPSegment}{i}"); } } }*/ for (int i = 0; i < 15; i++) { IPLists.Add($"{IPSegment}{(i + 1) * 10}"); } IPLists.ForEach((item) => { Ping myPing = new Ping(); myPing.PingCompleted += new PingCompletedEventHandler(_myPing_PingCompleted); myPing.SendAsync(item, 1000, null); }); } private void _myPing_PingCompleted(object sender, PingCompletedEventArgs e) { if (e.Reply != null && e.Reply.Status == IPStatus.Success) { string ip = e.Reply.Address.ToString(); if (!DeviceLists.ContainsKey(ip)) { DeviceStatus DS = new DeviceStatus(); DS.modbusTcp.IsReconnect = false; DS.modbusTcp.ConnectOk = new Action(() => { string DeviceName = DS.modbusTcp.GetString(DeviceAddress.DeviceName, 20).Trim()?.Replace(" ", "");//读取设备名称 if (DeviceName.Length > 0) { DeviceLists.TryAdd(ip, DS); DeviceLists[ip].Init(DeviceName); DeviceLists[ip].modbusTcp.IsReconnect = false; App.Current.Dispatcher.Invoke(new Action(() => { devices.Add(new Devices() { DeviceName = DeviceName, IpAddress = ip }); if (TopDeviceCurrentStatuses.Count <= 7) TopDeviceCurrentStatuses.Add(new DeviceCurrentStatus() { DeviceName = DeviceName }); else BottomDeviceCurrentStatuses.Add(new DeviceCurrentStatus() { DeviceName = DeviceName }); for (int i = 0; i < Json.Data.Recipes.Count; i++) { for (int m = 0; m < Json.Data.Recipes.ElementAt(i).RawMaterials.Count; m++) { if (Json.Data.Recipes.ElementAt(i).RawMaterials.ElementAt(m).DeviceIp == ip) { Json.Data.Recipes.ElementAt(i).RawMaterials.ElementAt(m).RawMaterialName = DeviceName; } } } if (Global.DeviceRawMaterials.Count > 0) { if (Global.DeviceRawMaterials.FirstOrDefault(p => p.RawMaterialName == DeviceName) == null) { Global.DeviceRawMaterials.Add(new RawMaterialModel() { RawMaterialName = DeviceName, DeviceIp = ip, RawMaterialSource = 1 }); } } else { Global.DeviceRawMaterials.Add(new RawMaterialModel() { RawMaterialName = DeviceName, DeviceIp = ip, RawMaterialSource = 1 }); } })); } else { //if (!InvalidIP.Contains(ip)) InvalidIP.Add(ip); } }); DS.modbusTcp.ConnectFail = new Action(() => { //if (!InvalidIP.Contains(ip)) InvalidIP.Add(ip); }); DS.modbusTcp.Disconnect = new Action(() => { if (InvalidIP.Contains(ip)) InvalidIP.Remove(ip); var res = devices.FirstOrDefault(P => P.IpAddress == ip); if (res != null && devices.Contains(res)) { App.Current.Dispatcher.Invoke(new Action(() => { devices.Remove(res); var item = Global.DeviceRawMaterials.FirstOrDefault(P => P.RawMaterialName == res.DeviceName); if (item != null) Global.DeviceRawMaterials.Remove(item); var topRes = TopDeviceCurrentStatuses.FirstOrDefault(p => p.DeviceName == res.DeviceName); var bottomRes = BottomDeviceCurrentStatuses.FirstOrDefault(p => p.DeviceName == res.DeviceName); if (topRes != null) TopDeviceCurrentStatuses.Remove(topRes); if (bottomRes != null) BottomDeviceCurrentStatuses.Remove(bottomRes); })); } if (DeviceLists.ContainsKey(ip)) { DeviceLists[ip].Dispose(); var res11 = DeviceLists[ip]; DeviceLists.TryRemove(ip, out res11); } }); Task.Run(new Action(() => { DS.modbusTcp.ModbusTcpConnect(ip, 502);//PLC连接 IPQueues.Enqueue(e.Reply.Address.ToString()); })); } else IPQueues.Enqueue(e.Reply.Address.ToString()); } else { if (e.Reply != null) IPQueues.Enqueue(e.Reply.Address.ToString()); } } } public class DeviceStatus { #region 对象属性声明 public string DeviceName = String.Empty; public string IpAddress => modbusTcp.IPAdress; /// /// 设备状态 /// public RawMaterialDeviceStatus deviceStatus { get; set; } = new RawMaterialDeviceStatus(); public ModbusTcp modbusTcp = new ModbusTcp(); public bool IsConnected => modbusTcp.Connected; #endregion public void Init(string DeviceName) { modbusTcp.Show = new Action((s) => { MessageNotify.GetInstance.ShowRunLog(s); }); modbusTcp.ShowEx = new Action((s) => { MessageNotify.GetInstance.ShowRunLog(s); }); this.DeviceName = DeviceName; AlarmHelper.Init(); if (modbusTcp.Connected) { ThreadManage.GetInstance().StartLong(new Action(() => { this.DeviceName = modbusTcp.GetString(DeviceAddress.DeviceName, 20)?.Trim()?.Replace(" ", ""); deviceStatus.RunStatus = (ushort)this.modbusTcp.ReadShort(DeviceAddress.RunStatus); //获取设备运行状态 deviceStatus.WeightFeedback = (float)this.modbusTcp.GetUint(DeviceAddress.WeightFeedback);//获取设备料仓剩余重量 deviceStatus.NowWeightFeedback = this.modbusTcp.GetReal(DeviceAddress.CutWeightFeedback);//获取下料重量 deviceStatus.DeviceNum = (ushort)this.modbusTcp.ReadShort(DeviceAddress.DeviceNum);//获取设备编号 deviceStatus.DeviceAlarmCode = (ushort)this.modbusTcp.ReadShort(DeviceAddress.DeviceAlarmCode);//获取设备故障编码 AlarmHelper.GetInstance(DeviceName).EStop1 = deviceStatus.DeviceAlarmCode.GetBitValue(1); AlarmHelper.GetInstance(DeviceName).Servo = deviceStatus.DeviceAlarmCode.GetBitValue(2); AlarmHelper.GetInstance(DeviceName).Inverter = deviceStatus.DeviceAlarmCode.GetBitValue(3); AlarmHelper.GetInstance(DeviceName).EStop2 = deviceStatus.DeviceAlarmCode.GetBitValue(7); AlarmHelper.GetInstance(DeviceName).SiloUpperLimit = deviceStatus.DeviceAlarmCode.GetBitValue(8); AlarmHelper.GetInstance(DeviceName).SiloLowerLimit = deviceStatus.DeviceAlarmCode.GetBitValue(9); Thread.Sleep(10); }), $"{DeviceName} 开始监听", true); } } public void SetDeviceName(string name) { this.modbusTcp.Write(DeviceAddress.DeviceName, new ushort[20]); this.modbusTcp.SetString(DeviceAddress.DeviceName, name); } public void StatusReset() { this.modbusTcp.Write(DeviceAddress.FinfishStatus, (ushort)1); //var res = modbusTcp.Read(DeviceAddress.RunStatus); } public void Dispose() { ThreadManage.GetInstance().StopTask($"{DeviceName} 开始监听"); } public void Start(float Value) { if (modbusTcp.Connected) { var res = Json.Data.deviceParModels.FirstOrDefault(p => p.MaterialName == DeviceName); if (res != null) { prop1: modbusTcp.SetReal(DeviceAddress.SlowlyAddWeight, res.SlowlyAddWeight); var Value1 = (float)this.modbusTcp.GetReal(DeviceAddress.SlowlyAddWeight); if (Value1 != null && Value1.ToString() != res.SlowlyAddWeight.ToString()) goto prop1; prop2: modbusTcp.SetReal(DeviceAddress.PreCloseValveWeight, res.PreCloseValveWeight); var Value2 = (float)this.modbusTcp.GetReal(DeviceAddress.PreCloseValveWeight); if (Value2 != null && Value2.ToString() != res.PreCloseValveWeight.ToString()) goto prop2; prop3: modbusTcp.SetUint(DeviceAddress.RapidAcceleration, (uint)res.RapidAcceleration); var Value3 = this.modbusTcp.GetUint(DeviceAddress.RapidAcceleration); if (Value3 != null && Value3.ToString() != res.RapidAcceleration.ToString()) goto prop3; prop4: modbusTcp.SetUint(DeviceAddress.SlowAcceleration, (uint)res.SlowAcceleration); var Value4 = this.modbusTcp.GetUint(DeviceAddress.SlowAcceleration); if (Value4 != null && Value4.ToString() != res.SlowAcceleration.ToString()) goto prop4; prop5: modbusTcp.SetUint(DeviceAddress.ServoManualSpeed, (uint)res.ServoManualSpeed); var Value5 = this.modbusTcp.GetUint(DeviceAddress.ServoManualSpeed); if (Value5 != null && Value5.ToString() != res.ServoManualSpeed.ToString()) goto prop5; prop6: modbusTcp.SetUint(DeviceAddress.SiloUpperLimitWeight, (uint)res.SiloUpperLimitWeight); var Value6 = this.modbusTcp.GetUint(DeviceAddress.SiloUpperLimitWeight); if (Value6 != null && Value6.ToString() != res.SiloUpperLimitWeight.ToString()) goto prop6; prop7: modbusTcp.SetUint(DeviceAddress.LowerLimitWeightOfSilo, (uint)res.LowerLimitWeightOfSilo); var Value7 = this.modbusTcp.GetUint(DeviceAddress.LowerLimitWeightOfSilo); if (Value7 != null && Value7.ToString() != res.LowerLimitWeightOfSilo.ToString()) goto prop7; prop8: modbusTcp.SetUint(DeviceAddress.StirringSpeed, (uint)res.StirringSpeed); var Value8 = this.modbusTcp.GetUint(DeviceAddress.StirringSpeed); if (Value8 != null && Value8.ToString() != res.StirringSpeed.ToString()) goto prop8; MessageNotify.GetInstance.ShowRunLog($"{res.MaterialName},配料参数下发完成"); } //prop9: // modbusTcp.SetReal(DeviceAddress.WeightSet, Value);//写入配方重量 // var Value9 = this.modbusTcp.GetReal(DeviceAddress.WeightSet); // if (Value9 != null && Value9.ToString() != Value.ToString()) goto prop9; //prop10: // modbusTcp.Write(DeviceAddress.Start, (ushort)1);//设备启动写入 // var Value10 = (short[])this.modbusTcp.Read(DeviceAddress.Start); // if (Value10 != null && Value10[0] != 1) goto prop10; modbusTcp.SetReal(DeviceAddress.WeightSet, Value);//写入配方重量 modbusTcp.Write(DeviceAddress.Start, (ushort)1);//设备启动写入 MessageNotify.GetInstance.ShowRunLog($"{DeviceName},设置重量:{Value},味魔方启动配料"); } } } }