终端一体化运控平台
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

385 lines
18 KiB

  1. using BPASmartClient.CustomResource.Pages.Model;
  2. using BPASmartClient.JXJFoodSmallStation.ViewModel;
  3. using BPASmartClient.Helper;
  4. using BPASmartClient.Modbus;
  5. using BPASmartClient.Model;
  6. using System;
  7. using System.Collections.Concurrent;
  8. using System.Collections.Generic;
  9. using System.Collections.ObjectModel;
  10. using System.Linq;
  11. using System.Net.NetworkInformation;
  12. using System.Threading;
  13. using System.Threading.Tasks;
  14. namespace BPASmartClient.JXJFoodSmallStation.Model
  15. {
  16. public class DeviceInquire
  17. {
  18. private volatile static DeviceInquire _Instance;
  19. public static DeviceInquire GetInstance => _Instance ?? (_Instance = new DeviceInquire());
  20. private DeviceInquire() { }
  21. string IPSegment = "192.168.0.";
  22. ConcurrentDictionary<string, DeviceStatus> DeviceLists = new ConcurrentDictionary<string, DeviceStatus>();
  23. List<string> InvalidIP = new List<string>();//无效 IP 集合
  24. List<string> IPLists = new List<string>();//启动 Ping 任务IP集合
  25. ConcurrentQueue<string> IPQueues = new ConcurrentQueue<string>();//pincomplete 完成队列
  26. public ObservableCollection<DeviceCurrentStatus> TopDeviceCurrentStatuses { get; set; } = new ObservableCollection<DeviceCurrentStatus>();
  27. public ObservableCollection<DeviceCurrentStatus> BottomDeviceCurrentStatuses { get; set; } = new ObservableCollection<DeviceCurrentStatus>();
  28. public ObservableCollection<Devices> devices { get; set; } = new ObservableCollection<Devices>();
  29. private void DeviceDataInit()
  30. {
  31. ThreadManage.GetInstance().StartLong(new Action(() =>
  32. {
  33. for (int i = 0; i < DeviceLists.Count; i++)
  34. {
  35. string deviceName = DeviceLists.ElementAt(i).Value.DeviceName;
  36. int TopIndex = Array.FindIndex(TopDeviceCurrentStatuses.ToArray(), p => p.DeviceName == deviceName);
  37. int BottomIndex = Array.FindIndex(BottomDeviceCurrentStatuses.ToArray(), p => p.DeviceName == deviceName);
  38. if (TopIndex >= 0 && TopIndex < TopDeviceCurrentStatuses.Count)
  39. {
  40. TopDeviceCurrentStatuses.ElementAt(TopIndex).Weight = DeviceLists.ElementAt(i).Value.deviceStatus.WeightFeedback;
  41. TopDeviceCurrentStatuses.ElementAt(TopIndex).DeviceNum = DeviceLists.ElementAt(i).Value.deviceStatus.DeviceNum;
  42. TopDeviceCurrentStatuses.ElementAt(TopIndex).RunStatus = DeviceLists.ElementAt(i).Value.deviceStatus.RunStatus;
  43. }
  44. if (BottomIndex >= 0 && BottomIndex < BottomDeviceCurrentStatuses.Count)
  45. {
  46. BottomDeviceCurrentStatuses.ElementAt(BottomIndex).Weight = DeviceLists.ElementAt(i).Value.deviceStatus.WeightFeedback;
  47. BottomDeviceCurrentStatuses.ElementAt(BottomIndex).DeviceNum = DeviceLists.ElementAt(i).Value.deviceStatus.DeviceNum;
  48. BottomDeviceCurrentStatuses.ElementAt(BottomIndex).RunStatus = DeviceLists.ElementAt(i).Value.deviceStatus.RunStatus;
  49. }
  50. int deviceIndex = Array.FindIndex(devices.ToArray(), p => p.IpAddress == DeviceLists.ElementAt(i).Key && p.DeviceName != DeviceLists.ElementAt(i).Value.DeviceName);
  51. if (deviceIndex >= 0 && deviceIndex < devices.Count)
  52. {
  53. devices.ElementAt(deviceIndex).DeviceName = DeviceLists.ElementAt(i).Value.DeviceName;
  54. }
  55. }
  56. Thread.Sleep(200);
  57. }), "设备状态监听");
  58. }
  59. private void TestData()
  60. {
  61. for (int i = 0; i < 8; i++)
  62. {
  63. TopDeviceCurrentStatuses.Add(new DeviceCurrentStatus()
  64. {
  65. DeviceName = $"测试设备{i + 1}",
  66. DeviceNum = i + 1,
  67. RunStatus = 1,
  68. Weight = new Random().Next(100, 10000) / 100.0
  69. });
  70. devices.Add(new Devices()
  71. {
  72. DeviceName = $"测试设备{i + 1}",
  73. IpAddress = $"192.168.1.{i + 1}",
  74. });
  75. }
  76. for (int i = 8; i < 16; i++)
  77. {
  78. BottomDeviceCurrentStatuses.Add(new DeviceCurrentStatus()
  79. {
  80. DeviceName = $"测试设备{i + 1}",
  81. DeviceNum = i + 1,
  82. RunStatus = 1,
  83. Weight = new Random().Next(100, 10000) / 100.0
  84. });
  85. devices.Add(new Devices()
  86. {
  87. DeviceName = $"测试设备{i + 1}",
  88. IpAddress = $"192.168.1.{i + 1}",
  89. });
  90. }
  91. }
  92. public void Init()
  93. {
  94. //AlarmHelper<AlarmInfo>.Init();
  95. //AlarmHelper<AlarmInfo>.Alarm.EStop1 = true;
  96. //TestData();
  97. IpAddressLines();
  98. DeviceDataInit();
  99. ThreadManage.GetInstance().StartLong(new Action(() =>
  100. {
  101. if (IPQueues.Count >= IPLists.Count)
  102. IpAddressLines();
  103. Thread.Sleep(5000);
  104. }), "配料机设备上线监听", true);
  105. }
  106. public void Rescan()
  107. {
  108. InvalidIP.Clear();
  109. }
  110. public DeviceStatus GetDevice(string ip)
  111. {
  112. if (ip != null)
  113. {
  114. var res = DeviceLists.Values.FirstOrDefault(p => p.IpAddress == ip);
  115. if (res != null) return res;
  116. }
  117. return new DeviceStatus();
  118. }
  119. public DeviceStatus GetDevice(int location)
  120. {
  121. if (location > 0 && location < 16)
  122. {
  123. var res = DeviceLists.Values.FirstOrDefault(p => p.deviceStatus.DeviceNum == location);
  124. if (res != null) return res;
  125. }
  126. return new DeviceStatus();
  127. }
  128. public List<DeviceStatus> GetDevice()
  129. {
  130. List<DeviceStatus> deviceStatuses = new List<DeviceStatus>();
  131. foreach (var device in DeviceLists)
  132. {
  133. deviceStatuses.Add(device.Value);
  134. }
  135. return deviceStatuses;
  136. }
  137. private void IpAddressLines()
  138. {
  139. IPLists.Clear();
  140. IPQueues.Clear();
  141. for (int i = 1; i <= 255; i++)
  142. {
  143. if (!InvalidIP.Contains($"{IPSegment}{i}") && !DeviceLists.ContainsKey($"{IPSegment}{i}"))
  144. {
  145. IPLists.Add($"{IPSegment}{i}");
  146. }
  147. }
  148. IPLists.ForEach((item) =>
  149. {
  150. Ping myPing = new Ping();
  151. myPing.PingCompleted += new PingCompletedEventHandler(_myPing_PingCompleted);
  152. myPing.SendAsync(item, 1000, null);
  153. });
  154. }
  155. private void _myPing_PingCompleted(object sender, PingCompletedEventArgs e)
  156. {
  157. if (e.Reply.Status == IPStatus.Success)
  158. {
  159. string ip = e.Reply.Address.ToString();
  160. if (!DeviceLists.ContainsKey(ip))
  161. {
  162. DeviceStatus DS = new DeviceStatus();
  163. DS.modbusTcp.IsReconnect = false;
  164. DS.modbusTcp.ConnectOk = new Action(() =>
  165. {
  166. string DeviceName = DS.modbusTcp.GetString(DeviceAddress.DeviceName, 20).Trim()?.Replace(" ", "");//读取设备名称
  167. if (DeviceName.Length > 0)
  168. {
  169. DeviceLists.TryAdd(ip, DS);
  170. DeviceLists[ip].Init(DeviceName);
  171. DeviceLists[ip].modbusTcp.IsReconnect = false;
  172. App.Current.Dispatcher.Invoke(new Action(() =>
  173. {
  174. //DeviceListViewModel.devices.Add(new Devices()
  175. //{
  176. // DeviceName = DeviceName,
  177. // IpAddress = ip
  178. //});//加入连接的(有名称的)设备列表
  179. devices.Add(new Devices() { DeviceName = DeviceName, IpAddress = ip });
  180. if (TopDeviceCurrentStatuses.Count <= 7)
  181. TopDeviceCurrentStatuses.Add(new DeviceCurrentStatus() { DeviceName = DeviceName });
  182. else
  183. BottomDeviceCurrentStatuses.Add(new DeviceCurrentStatus() { DeviceName = DeviceName });
  184. for (int i = 0; i < Json<LocaPar>.Data.Recipes.Count; i++)
  185. {
  186. for (int m = 0; m < Json<LocaPar>.Data.Recipes.ElementAt(i).RawMaterials.Count; m++)
  187. {
  188. if (Json<LocaPar>.Data.Recipes.ElementAt(i).RawMaterials.ElementAt(m).DeviceIp == ip)
  189. {
  190. Json<LocaPar>.Data.Recipes.ElementAt(i).RawMaterials.ElementAt(m).RawMaterialName = DeviceName;
  191. }
  192. }
  193. }
  194. if (Global.DeviceRawMaterials.Count > 0)
  195. {
  196. if (Global.DeviceRawMaterials.FirstOrDefault(p => p.RawMaterialName == DeviceName) == null)
  197. {
  198. Global.DeviceRawMaterials.Add(new RawMaterialModel() { RawMaterialName = DeviceName, DeviceIp = ip, RawMaterialSource = 1 });
  199. }
  200. }
  201. else
  202. {
  203. Global.DeviceRawMaterials.Add(new RawMaterialModel() { RawMaterialName = DeviceName, DeviceIp = ip, RawMaterialSource = 1 });
  204. }
  205. }));
  206. }
  207. else
  208. {
  209. if (!InvalidIP.Contains(ip)) InvalidIP.Add(ip);
  210. }
  211. });
  212. DS.modbusTcp.ConnectFail = new Action(() =>
  213. {
  214. if (!InvalidIP.Contains(ip)) InvalidIP.Add(ip);
  215. //MessageLog.GetInstance.ShowAlarmLog($"设备{ip}连接失败");
  216. });
  217. DS.modbusTcp.Disconnect = new Action(() =>
  218. {
  219. if (InvalidIP.Contains(ip)) InvalidIP.Remove(ip);
  220. //var res = DeviceListViewModel.devices.FirstOrDefault(P => P.IpAddress == ip);
  221. var res = devices.FirstOrDefault(P => P.IpAddress == ip);
  222. //if (res != null && DeviceListViewModel.devices.Contains(res))
  223. if (res != null && devices.Contains(res))
  224. {
  225. App.Current.Dispatcher.Invoke(new Action(() =>
  226. {
  227. //DeviceListViewModel.devices.Remove(res);
  228. devices.Remove(res);
  229. var item = Global.DeviceRawMaterials.FirstOrDefault(P => P.RawMaterialName == res.DeviceName);
  230. if (item != null) Global.DeviceRawMaterials.Remove(item);
  231. var topRes = TopDeviceCurrentStatuses.FirstOrDefault(p => p.DeviceName == res.DeviceName);
  232. var bottomRes = BottomDeviceCurrentStatuses.FirstOrDefault(p => p.DeviceName == res.DeviceName);
  233. if (topRes != null) TopDeviceCurrentStatuses.Remove(topRes);
  234. if (bottomRes != null) BottomDeviceCurrentStatuses.Remove(bottomRes);
  235. }));
  236. }
  237. if (DeviceLists.ContainsKey(ip)) DeviceLists[ip].Dispose();
  238. });
  239. Task.Run(new Action(() =>
  240. {
  241. DS.modbusTcp.ModbusTcpConnect(ip, 502);//PLC连接
  242. IPQueues.Enqueue(e.Reply.Address.ToString());
  243. }));
  244. }
  245. else IPQueues.Enqueue(e.Reply.Address.ToString());
  246. }
  247. else IPQueues.Enqueue(e.Reply.Address.ToString());
  248. }
  249. }
  250. public class DeviceStatus
  251. {
  252. #region 对象属性声明
  253. public string DeviceName = String.Empty;
  254. public string IpAddress => modbusTcp.IPAdress;
  255. /// <summary>
  256. /// 设备状态
  257. /// </summary>
  258. public RawMaterialDeviceStatus deviceStatus { get; set; } = new RawMaterialDeviceStatus();
  259. public ModbusTcp modbusTcp = new ModbusTcp();
  260. public bool IsConnected => modbusTcp.Connected;
  261. #endregion
  262. public void Init(string DeviceName)
  263. {
  264. modbusTcp.Show += new Action<string>((s) =>
  265. {
  266. if (s != null) MessageNotify.GetInstance.ShowRunLog(s);
  267. });
  268. modbusTcp.ShowEx += new Action<string>((s) =>
  269. {
  270. if (s != null) MessageNotify.GetInstance.ShowRunLog(s);
  271. });
  272. this.DeviceName = DeviceName;
  273. AlarmHelper<AlarmInfo>.Init();
  274. if (modbusTcp.Connected)
  275. {
  276. ThreadManage.GetInstance().StartLong(new Action(() =>
  277. {
  278. //获取设备运行状态
  279. //var res = this.modbusTcp.Read(DeviceAddress.RunStatus);
  280. //if (res != null && res is ushort[] ushortValue)
  281. //{
  282. // if (ushortValue.Length >= 1) deviceStatus.RunStatus = ushortValue[0];
  283. //}
  284. deviceStatus.RunStatus = (ushort)this.modbusTcp.ReadShort(DeviceAddress.RunStatus); //获取设备运行状态
  285. deviceStatus.WeightFeedback = (Int16)this.modbusTcp.GetUint(DeviceAddress.WeightFeedback);//获取设备料仓剩余重量
  286. deviceStatus.NowWeightFeedback = (float)this.modbusTcp.GetUint(DeviceAddress.CutWeightFeedback);//获取下料重量
  287. deviceStatus.DeviceNum = (ushort)this.modbusTcp.ReadShort(DeviceAddress.DeviceNum);//获取设备编号
  288. deviceStatus.DeviceAlarmCode = (ushort)this.modbusTcp.ReadShort(DeviceAddress.DeviceAlarmCode);//获取设备故障编码
  289. AlarmHelper<AlarmInfo>.GetInstance(DeviceName).EStop1 = deviceStatus.DeviceAlarmCode.Get16bitValue(1);
  290. AlarmHelper<AlarmInfo>.GetInstance(DeviceName).Servo = deviceStatus.DeviceAlarmCode.Get16bitValue(2);
  291. AlarmHelper<AlarmInfo>.GetInstance(DeviceName).Inverter = deviceStatus.DeviceAlarmCode.Get16bitValue(3);
  292. AlarmHelper<AlarmInfo>.GetInstance(DeviceName).EStop2 = deviceStatus.DeviceAlarmCode.Get16bitValue(7);
  293. AlarmHelper<AlarmInfo>.GetInstance(DeviceName).SiloUpperLimit = deviceStatus.DeviceAlarmCode.Get16bitValue(8);
  294. AlarmHelper<AlarmInfo>.GetInstance(DeviceName).SiloLowerLimit = deviceStatus.DeviceAlarmCode.Get16bitValue(9);
  295. Thread.Sleep(10);
  296. }), $"{DeviceName} 开始监听", true);
  297. }
  298. }
  299. public void SetDeviceName(string name)
  300. {
  301. this.modbusTcp.Write(DeviceAddress.DeviceName, new ushort[20]);
  302. this.modbusTcp.SetString(DeviceAddress.DeviceName, name);
  303. }
  304. public bool StatusReset()
  305. {
  306. return this.modbusTcp.Write(DeviceAddress.FinfishStatus, (ushort)1);
  307. //var res = modbusTcp.Read(DeviceAddress.RunStatus);
  308. }
  309. public void Dispose()
  310. {
  311. ThreadManage.GetInstance().StopTask($"{DeviceName} 开始监听");
  312. }
  313. public void Start(float Value)
  314. {
  315. if (modbusTcp.Connected)
  316. {
  317. modbusTcp.SetReal(DeviceAddress.WeightSet, Value);//写入配方量
  318. bool returnValue = modbusTcp.Write(DeviceAddress.Start, (ushort)1);//设备启动写入
  319. if (returnValue)
  320. {
  321. MessageNotify.GetInstance.ShowRunLog($"发送成功" + DeviceAddress.Start);
  322. }
  323. else
  324. {
  325. MessageNotify.GetInstance.ShowRunLog($"发送失败" + DeviceAddress.Start);
  326. }
  327. //配料设备参数写入
  328. var res = Json<DevicePar>.Data.deviceParModels.FirstOrDefault(p => p.MaterialName == DeviceName);
  329. if (res != null)
  330. {
  331. modbusTcp.SetReal(DeviceAddress.SlowlyAddWeight, res.SlowlyAddWeight);
  332. modbusTcp.SetReal(DeviceAddress.PreCloseValveWeight, res.PreCloseValveWeight);
  333. modbusTcp.SetUint(DeviceAddress.RapidAcceleration, (uint)res.RapidAcceleration);
  334. modbusTcp.SetUint(DeviceAddress.SlowAcceleration, (uint)res.SlowAcceleration);
  335. modbusTcp.SetUint(DeviceAddress.ServoManualSpeed, (uint)res.ServoManualSpeed);
  336. modbusTcp.SetUint(DeviceAddress.SiloUpperLimitWeight, (uint)res.SiloUpperLimitWeight);
  337. modbusTcp.SetUint(DeviceAddress.LowerLimitWeightOfSilo, (uint)res.LowerLimitWeightOfSilo);
  338. modbusTcp.SetUint(DeviceAddress.StirringSpeed, (uint)res.StirringSpeed * 100);
  339. MessageNotify.GetInstance.ShowRunLog($"{res.MaterialName},参数下发完成");
  340. }
  341. }
  342. }
  343. }
  344. }