using BPA.Communication; using BPASmartClient.CustomResource.Pages.Model; using BPASmartClient.FoodStationTest.ViewModel; using BPASmartClient.Helper; 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; namespace BPASmartClient.FoodStationTest.Model { public class DeviceInquire { private volatile static DeviceInquire _Instance; public static DeviceInquire GetInstance => _Instance ?? (_Instance = new DeviceInquire()); private DeviceInquire() { } //代码片段。 string IPSegment = "107.107.2."; 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; TopDeviceCurrentStatuses.ElementAt(TopIndex).RunStatus = DeviceLists.ElementAt(i).Value.deviceStatus.RunStatus; } 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; BottomDeviceCurrentStatuses.ElementAt(BottomIndex).RunStatus = DeviceLists.ElementAt(i).Value.deviceStatus.RunStatus; } int deviceIndex = Array.FindIndex(devices.ToArray(), p => p.IpAddress == DeviceLists.ElementAt(i).Key && p.DeviceName != DeviceLists.ElementAt(i).Value.DeviceName); if (deviceIndex >= 0 && deviceIndex < devices.Count) { devices.ElementAt(deviceIndex).DeviceName = DeviceLists.ElementAt(i).Value.DeviceName; } if (!ThreadManage.GetInstance().IsContainsKey($"{deviceName} 开始监听")) { DeviceLists[DeviceLists.ElementAt(i).Key].Init(deviceName); } } Thread.Sleep(200); }), "设备状态监听", true); } private void TestData() { for (int i = 0; i < 8; i++) { TopDeviceCurrentStatuses.Add(new DeviceCurrentStatus() { DeviceName = $"测试设备{i + 1}", DeviceNum = i + 1, RunStatus = 1, Weight = new Random().Next(100, 10000) / 100.0 }); devices.Add(new Devices() { DeviceName = $"测试设备{i + 1}", IpAddress = $"192.168.1.{i + 1}", }); } for (int i = 8; i < 16; i++) { BottomDeviceCurrentStatuses.Add(new DeviceCurrentStatus() { DeviceName = $"测试设备{i + 1}", DeviceNum = i + 1, RunStatus = 1, Weight = new Random().Next(100, 10000) / 100.0 }); devices.Add(new Devices() { DeviceName = $"测试设备{i + 1}", IpAddress = $"192.168.1.{i + 1}", }); } } public void Init() { //AlarmHelper.Init(); //AlarmHelper.Alarm.EStop1 = true; //IPSegment = ConfigurationManager.AppSettings["RawMaterial_IP"]; //TestData(); IpAddressLines(); 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) { var res = DeviceLists.Values.FirstOrDefault(p => p.IpAddress == ip); if (res != null) return res; } return new DeviceStatus(); } public DeviceStatus GetDevice(int location) { if (location > 0 && location < 16) { var res = DeviceLists.Values.FirstOrDefault(p => p.deviceStatus.DeviceNum == location); 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 = 0; i < Json.Data.RawMaterialDeviceNum; i++) { //这里“69”是味魔方起始地址。 //TODO:修改起始地址。 IPLists.Add($"{IPSegment}{i + 69}"); } 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.Read(DeviceAddress.DeviceName, 20).Content.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(() => { //DeviceListViewModel.devices.Add(new Devices() //{ // DeviceName = DeviceName, // IpAddress = ip //});//加入连接的(有名称的)设备列表 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); if (DeviceLists.ContainsKey(ip)) { DeviceLists[ip].Dispose(); var res11 = DeviceLists[ip]; DeviceLists.TryRemove(ip, out res11); } } }); DS.modbusTcp.ConnectFail = new Action(() => { //if (!InvalidIP.Contains(ip)) InvalidIP.Add(ip); //MessageLog.GetInstance.ShowAlarmLog($"设备{ip}连接失败"); if (DeviceLists.ContainsKey(ip)) { DeviceLists[ip].Dispose(); var res11 = DeviceLists[ip]; DeviceLists.TryRemove(ip, out res11); } }); 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.Connect(new BPA.Communication.Base.ConfigurationOptions() { IpAddress = ip, Port = 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; /// /// ModbusTcp的地址。 /// public string IpAddress=> modbusTcp.GetConfigPar().IpAddress; /// /// 设备状态 /// public RawMaterialDeviceStatus deviceStatus { get; set; } = new RawMaterialDeviceStatus(); public ModbusTcp modbusTcp = new ModbusTcp(); public bool IsConnected => modbusTcp.IsConnected(); #endregion public void Init(string DeviceName) { this.DeviceName = DeviceName; //AlarmHelper.Init(); if (modbusTcp.IsConnected()) { ThreadManage.GetInstance().StartLong(new Action(() => { if (modbusTcp.IsConnected()) { deviceStatus.RunStatus = (ushort)this.modbusTcp.Read(DeviceAddress.RunStatus).Content; //获取设备运行状态 deviceStatus.WeightFeedback = this.modbusTcp.Read(DeviceAddress.WeightFeedback).Content;//获取设备料仓剩余重量 deviceStatus.NowWeightFeedback = this.modbusTcp.Read(DeviceAddress.CutWeightFeedback).Content;//获取下料重量 deviceStatus.DeviceNum = (ushort)this.modbusTcp.Read(DeviceAddress.DeviceNum).Content;//获取设备编号 deviceStatus.DeviceAlarmCode = (ushort)this.modbusTcp.Read(DeviceAddress.DeviceAlarmCode).Content;//获取设备故障编码 AlarmHelper.GetInstance(DeviceName).EStop1 = deviceStatus.DeviceAlarmCode.Get16bitValue(1); AlarmHelper.GetInstance(DeviceName).Servo = deviceStatus.DeviceAlarmCode.Get16bitValue(2); AlarmHelper.GetInstance(DeviceName).Inverter = deviceStatus.DeviceAlarmCode.Get16bitValue(3); AlarmHelper.GetInstance(DeviceName).EStop2 = deviceStatus.DeviceAlarmCode.Get16bitValue(7); AlarmHelper.GetInstance(DeviceName).SiloUpperLimit = deviceStatus.DeviceAlarmCode.Get16bitValue(8); AlarmHelper.GetInstance(DeviceName).SiloLowerLimit = deviceStatus.DeviceAlarmCode.Get16bitValue(9); //允许配料即产线气缸抬起,发送给味魔方 if (deviceStatus.DeviceNum >= 1 && deviceStatus.DeviceNum <= 15) { if (GVL_SmallStation.GetInstance.plcReadDataDB3.StockBinAllowIssue[deviceStatus.DeviceNum - 1]) { this.modbusTcp.Write("LW41", (ushort)1); GVL_SmallStation.GetInstance.StockBinCylinderStatus.SetBitValue((byte)(deviceStatus.DeviceNum), true); } else { this.modbusTcp.Write("LW41", (ushort)0); GVL_SmallStation.GetInstance.StockBinCylinderStatus.SetBitValue((byte)(deviceStatus.DeviceNum), false); } } Thread.Sleep(10); } }), $"{DeviceName} 开始监听", true); } } public void SetDeviceName(string name) { this.modbusTcp.Write(DeviceAddress.DeviceName, new ushort[20]); this.modbusTcp.Write(DeviceAddress.DeviceName, name); } /// /// 开盖 /// public void OpenLid() { //modbusTcp.Write(DeviceAddress.OpenLid, (ushort)1); } /// /// 关盖 /// public void CloseLid() { //modbusTcp.Write(DeviceAddress.CloseLid, (ushort)1); } public bool StatusReset() { return this.modbusTcp.Write(DeviceAddress.FinfishStatus, (ushort)1).IsSuccess; //var res = modbusTcp.Read(DeviceAddress.RunStatus); } public void Dispose() { ThreadManage.GetInstance().StopTask($"{DeviceName} 开始监听"); } /// /// 写入重量数据,开始配料。 /// /// 配料重量。 public void Start(float Value) { if (modbusTcp.IsConnected()) { var res = Json.Data.deviceParModels.FirstOrDefault(p => p.MaterialName == DeviceName); if (res != null) { modbusTcp.Write(DeviceAddress.SlowlyAddWeight, res.SlowlyAddWeight); modbusTcp.Write(DeviceAddress.PreCloseValveWeight, res.PreCloseValveWeight); modbusTcp.Write(DeviceAddress.RapidAcceleration, (uint)res.RapidAcceleration); modbusTcp.Write(DeviceAddress.SlowAcceleration, (uint)res.SlowAcceleration); modbusTcp.Write(DeviceAddress.ServoManualSpeed, (uint)res.ServoManualSpeed); modbusTcp.Write(DeviceAddress.SiloUpperLimitWeight, (uint)res.SiloUpperLimitWeight); modbusTcp.Write(DeviceAddress.LowerLimitWeightOfSilo, (uint)res.LowerLimitWeightOfSilo); modbusTcp.Write(DeviceAddress.StirringSpeed, (uint)res.StirringSpeed * 100); MessageNotify.GetInstance.ShowRunLog($"{res.MaterialName},参数下发完成"); } modbusTcp.Write(DeviceAddress.WeightSet, Value);//写入原料重量 if (!modbusTcp.Write(DeviceAddress.Start, (ushort)1).IsSuccess)//设备启动写入 { MessageNotify.GetInstance.ShowRunLog($"{DeviceName},设置重量:{Value},启动信号写入失败"); } MessageNotify.GetInstance.ShowRunLog($"{DeviceName},设置重量:{Value},柔性味魔方开始配料"); } } } }