终端一体化运控平台
Nie możesz wybrać więcej, niż 25 tematów Tematy muszą się zaczynać od litery lub cyfry, mogą zawierać myślniki ('-') i mogą mieć do 35 znaków.

DeviceInquire.cs 20 KiB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444
  1. using BPA.Communication;
  2. using BPASmartClient.CustomResource.Pages.Model;
  3. using BPASmartClient.FoodStationTest.ViewModel;
  4. using BPASmartClient.Helper;
  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.FoodStationTest.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. //代码片段。
  22. string IPSegment = "107.107.2.";
  23. ConcurrentDictionary<string, DeviceStatus> DeviceLists = new ConcurrentDictionary<string, DeviceStatus>();
  24. List<string> InvalidIP = new List<string>();//无效 IP 集合
  25. List<string> IPLists = new List<string>();//启动 Ping 任务IP集合
  26. ConcurrentQueue<string> IPQueues = new ConcurrentQueue<string>();//pincomplete 完成队列
  27. public ObservableCollection<DeviceCurrentStatus> TopDeviceCurrentStatuses { get; set; } = new ObservableCollection<DeviceCurrentStatus>();
  28. public ObservableCollection<DeviceCurrentStatus> BottomDeviceCurrentStatuses { get; set; } = new ObservableCollection<DeviceCurrentStatus>();
  29. public ObservableCollection<Devices> devices { get; set; } = new ObservableCollection<Devices>();
  30. private void DeviceDataInit()
  31. {
  32. ThreadManage.GetInstance().StartLong(new Action(() =>
  33. {
  34. for (int i = 0; i < DeviceLists.Count; i++)
  35. {
  36. string deviceName = DeviceLists.ElementAt(i).Value.DeviceName;
  37. int TopIndex = Array.FindIndex(TopDeviceCurrentStatuses.ToArray(), p => p.DeviceName == deviceName);
  38. int BottomIndex = Array.FindIndex(BottomDeviceCurrentStatuses.ToArray(), p => p.DeviceName == deviceName);
  39. if (TopIndex >= 0 && TopIndex < TopDeviceCurrentStatuses.Count)
  40. {
  41. TopDeviceCurrentStatuses.ElementAt(TopIndex).Weight = DeviceLists.ElementAt(i).Value.deviceStatus.WeightFeedback;
  42. TopDeviceCurrentStatuses.ElementAt(TopIndex).DeviceNum = DeviceLists.ElementAt(i).Value.deviceStatus.DeviceNum;
  43. TopDeviceCurrentStatuses.ElementAt(TopIndex).RunStatus = DeviceLists.ElementAt(i).Value.deviceStatus.RunStatus;
  44. }
  45. if (BottomIndex >= 0 && BottomIndex < BottomDeviceCurrentStatuses.Count)
  46. {
  47. BottomDeviceCurrentStatuses.ElementAt(BottomIndex).Weight = DeviceLists.ElementAt(i).Value.deviceStatus.WeightFeedback;
  48. BottomDeviceCurrentStatuses.ElementAt(BottomIndex).DeviceNum = DeviceLists.ElementAt(i).Value.deviceStatus.DeviceNum;
  49. BottomDeviceCurrentStatuses.ElementAt(BottomIndex).RunStatus = DeviceLists.ElementAt(i).Value.deviceStatus.RunStatus;
  50. }
  51. int deviceIndex = Array.FindIndex(devices.ToArray(), p => p.IpAddress == DeviceLists.ElementAt(i).Key && p.DeviceName != DeviceLists.ElementAt(i).Value.DeviceName);
  52. if (deviceIndex >= 0 && deviceIndex < devices.Count)
  53. {
  54. devices.ElementAt(deviceIndex).DeviceName = DeviceLists.ElementAt(i).Value.DeviceName;
  55. }
  56. if (!ThreadManage.GetInstance().IsContainsKey($"{deviceName} 开始监听"))
  57. {
  58. DeviceLists[DeviceLists.ElementAt(i).Key].Init(deviceName);
  59. }
  60. }
  61. Thread.Sleep(200);
  62. }), "设备状态监听", true);
  63. }
  64. private void TestData()
  65. {
  66. for (int i = 0; i < 8; i++)
  67. {
  68. TopDeviceCurrentStatuses.Add(new DeviceCurrentStatus()
  69. {
  70. DeviceName = $"测试设备{i + 1}",
  71. DeviceNum = i + 1,
  72. RunStatus = 1,
  73. Weight = new Random().Next(100, 10000) / 100.0
  74. });
  75. devices.Add(new Devices()
  76. {
  77. DeviceName = $"测试设备{i + 1}",
  78. IpAddress = $"192.168.1.{i + 1}",
  79. });
  80. }
  81. for (int i = 8; i < 16; i++)
  82. {
  83. BottomDeviceCurrentStatuses.Add(new DeviceCurrentStatus()
  84. {
  85. DeviceName = $"测试设备{i + 1}",
  86. DeviceNum = i + 1,
  87. RunStatus = 1,
  88. Weight = new Random().Next(100, 10000) / 100.0
  89. });
  90. devices.Add(new Devices()
  91. {
  92. DeviceName = $"测试设备{i + 1}",
  93. IpAddress = $"192.168.1.{i + 1}",
  94. });
  95. }
  96. }
  97. public void Init()
  98. {
  99. //AlarmHelper<AlarmInfo>.Init();
  100. //AlarmHelper<AlarmInfo>.Alarm.EStop1 = true;
  101. //IPSegment = ConfigurationManager.AppSettings["RawMaterial_IP"];
  102. //TestData();
  103. IpAddressLines();
  104. DeviceDataInit();
  105. ThreadManage.GetInstance().StartLong(new Action(() =>
  106. {
  107. if (IPQueues.Count >= IPLists.Count)
  108. IpAddressLines();
  109. Thread.Sleep(5000);
  110. }), "配料机设备上线监听", true);
  111. }
  112. public void Rescan()
  113. {
  114. InvalidIP.Clear();
  115. }
  116. public DeviceStatus GetDevice(string ip)
  117. {
  118. if (ip != null)
  119. {
  120. var res = DeviceLists.Values.FirstOrDefault(p => p.IpAddress == ip);
  121. if (res != null)
  122. return res;
  123. }
  124. return new DeviceStatus();
  125. }
  126. public DeviceStatus GetDevice(int location)
  127. {
  128. if (location > 0 && location < 16)
  129. {
  130. var res = DeviceLists.Values.FirstOrDefault(p => p.deviceStatus.DeviceNum == location);
  131. if (res != null)
  132. return res;
  133. }
  134. return new DeviceStatus();
  135. }
  136. public List<DeviceStatus> GetDevice()
  137. {
  138. List<DeviceStatus> deviceStatuses = new List<DeviceStatus>();
  139. foreach (var device in DeviceLists)
  140. {
  141. deviceStatuses.Add(device.Value);
  142. }
  143. return deviceStatuses;
  144. }
  145. private void IpAddressLines()
  146. {
  147. IPLists.Clear();
  148. IPQueues.Clear();
  149. for (int i = 0; i < Json<LocalPar>.Data.RawMaterialDeviceNum; i++)
  150. {
  151. //这里“69”是味魔方起始地址。
  152. //TODO:修改起始地址。
  153. IPLists.Add($"{IPSegment}{i + 69}");
  154. }
  155. IPLists.ForEach((item) =>
  156. {
  157. Ping myPing = new Ping();
  158. myPing.PingCompleted += new PingCompletedEventHandler(_myPing_PingCompleted);
  159. myPing.SendAsync(item, 1000, null);
  160. });
  161. }
  162. private void _myPing_PingCompleted(object sender, PingCompletedEventArgs e)
  163. {
  164. if (e.Reply != null && e.Reply.Status == IPStatus.Success)
  165. {
  166. string ip = e.Reply.Address.ToString();
  167. if (!DeviceLists.ContainsKey(ip))
  168. {
  169. DeviceStatus DS = new DeviceStatus();
  170. DS.modbusTcp.IsReconnect = false;
  171. DS.modbusTcp.ConnectOk = new Action(() =>
  172. {
  173. string DeviceName = DS.modbusTcp.Read<string>(DeviceAddress.DeviceName, 20).Content.Trim()?.Replace(" ", "");//读取设备名称
  174. if (DeviceName.Length > 0)
  175. {
  176. DeviceLists.TryAdd(ip, DS);
  177. DeviceLists[ip].Init(DeviceName);
  178. DeviceLists[ip].modbusTcp.IsReconnect = false;
  179. App.Current.Dispatcher.Invoke(new Action(() =>
  180. {
  181. //DeviceListViewModel.devices.Add(new Devices()
  182. //{
  183. // DeviceName = DeviceName,
  184. // IpAddress = ip
  185. //});//加入连接的(有名称的)设备列表
  186. devices.Add(new Devices() { DeviceName = DeviceName, IpAddress = ip });
  187. if (TopDeviceCurrentStatuses.Count <= 7)
  188. TopDeviceCurrentStatuses.Add(new DeviceCurrentStatus() { DeviceName = DeviceName });
  189. else
  190. BottomDeviceCurrentStatuses.Add(new DeviceCurrentStatus() { DeviceName = DeviceName });
  191. for (int i = 0; i < Json<LocalPar>.Data.Recipes.Count; i++)
  192. {
  193. for (int m = 0; m < Json<LocalPar>.Data.Recipes.ElementAt(i).RawMaterials.Count; m++)
  194. {
  195. if (Json<LocalPar>.Data.Recipes.ElementAt(i).RawMaterials.ElementAt(m).DeviceIp == ip)
  196. {
  197. Json<LocalPar>.Data.Recipes.ElementAt(i).RawMaterials.ElementAt(m).RawMaterialName = DeviceName;
  198. }
  199. }
  200. }
  201. if (Global.DeviceRawMaterials.Count > 0)
  202. {
  203. if (Global.DeviceRawMaterials.FirstOrDefault(p => p.RawMaterialName == DeviceName) == null)
  204. {
  205. Global.DeviceRawMaterials.Add(new RawMaterialModel() { RawMaterialName = DeviceName, DeviceIp = ip, RawMaterialSource = 1 });
  206. }
  207. }
  208. else
  209. {
  210. Global.DeviceRawMaterials.Add(new RawMaterialModel() { RawMaterialName = DeviceName, DeviceIp = ip, RawMaterialSource = 1 });
  211. }
  212. }));
  213. }
  214. else
  215. {
  216. //if (!InvalidIP.Contains(ip)) InvalidIP.Add(ip);
  217. if (DeviceLists.ContainsKey(ip))
  218. {
  219. DeviceLists[ip].Dispose();
  220. var res11 = DeviceLists[ip];
  221. DeviceLists.TryRemove(ip, out res11);
  222. }
  223. }
  224. });
  225. DS.modbusTcp.ConnectFail = new Action(() =>
  226. {
  227. //if (!InvalidIP.Contains(ip)) InvalidIP.Add(ip);
  228. //MessageLog.GetInstance.ShowAlarmLog($"设备{ip}连接失败");
  229. if (DeviceLists.ContainsKey(ip))
  230. {
  231. DeviceLists[ip].Dispose();
  232. var res11 = DeviceLists[ip];
  233. DeviceLists.TryRemove(ip, out res11);
  234. }
  235. });
  236. DS.modbusTcp.Disconnect = new Action(() =>
  237. {
  238. if (InvalidIP.Contains(ip))
  239. InvalidIP.Remove(ip);
  240. var res = devices.FirstOrDefault(P => P.IpAddress == ip);
  241. if (res != null && devices.Contains(res))
  242. {
  243. App.Current.Dispatcher.Invoke(new Action(() =>
  244. {
  245. devices.Remove(res);
  246. var item = Global.DeviceRawMaterials.FirstOrDefault(P => P.RawMaterialName == res.DeviceName);
  247. if (item != null)
  248. Global.DeviceRawMaterials.Remove(item);
  249. var topRes = TopDeviceCurrentStatuses.FirstOrDefault(p => p.DeviceName == res.DeviceName);
  250. var bottomRes = BottomDeviceCurrentStatuses.FirstOrDefault(p => p.DeviceName == res.DeviceName);
  251. if (topRes != null)
  252. TopDeviceCurrentStatuses.Remove(topRes);
  253. if (bottomRes != null)
  254. BottomDeviceCurrentStatuses.Remove(bottomRes);
  255. }));
  256. }
  257. if (DeviceLists.ContainsKey(ip))
  258. {
  259. DeviceLists[ip].Dispose();
  260. var res11 = DeviceLists[ip];
  261. DeviceLists.TryRemove(ip, out res11);
  262. }
  263. });
  264. Task.Run(new Action(() =>
  265. {
  266. DS.modbusTcp.Connect(new BPA.Communication.Base.ConfigurationOptions() { IpAddress = ip, Port = 502 });//PLC连接
  267. IPQueues.Enqueue(e.Reply.Address.ToString());
  268. }));
  269. }
  270. else
  271. {
  272. IPQueues.Enqueue(e.Reply.Address.ToString());
  273. }
  274. }
  275. else
  276. {
  277. if (e.Reply != null)
  278. IPQueues.Enqueue(e.Reply.Address.ToString());
  279. }
  280. }
  281. }
  282. public class DeviceStatus
  283. {
  284. #region 对象属性声明
  285. public string DeviceName = String.Empty;
  286. /// <summary>
  287. /// ModbusTcp的地址。
  288. /// </summary>
  289. public string IpAddress=> modbusTcp.GetConfigPar().IpAddress;
  290. /// <summary>
  291. /// 设备状态
  292. /// </summary>
  293. public RawMaterialDeviceStatus deviceStatus { get; set; } = new RawMaterialDeviceStatus();
  294. public ModbusTcp modbusTcp = new ModbusTcp();
  295. public bool IsConnected => modbusTcp.IsConnected();
  296. #endregion
  297. public void Init(string DeviceName)
  298. {
  299. this.DeviceName = DeviceName;
  300. //AlarmHelper<AlarmInfo>.Init();
  301. if (modbusTcp.IsConnected())
  302. {
  303. ThreadManage.GetInstance().StartLong(new Action(() =>
  304. {
  305. if (modbusTcp.IsConnected())
  306. {
  307. deviceStatus.RunStatus = (ushort)this.modbusTcp.Read<ushort>(DeviceAddress.RunStatus).Content; //获取设备运行状态
  308. deviceStatus.WeightFeedback = this.modbusTcp.Read<float>(DeviceAddress.WeightFeedback).Content;//获取设备料仓剩余重量
  309. deviceStatus.NowWeightFeedback = this.modbusTcp.Read<float>(DeviceAddress.CutWeightFeedback).Content;//获取下料重量
  310. deviceStatus.DeviceNum = (ushort)this.modbusTcp.Read<ushort>(DeviceAddress.DeviceNum).Content;//获取设备编号
  311. deviceStatus.DeviceAlarmCode = (ushort)this.modbusTcp.Read<ushort>(DeviceAddress.DeviceAlarmCode).Content;//获取设备故障编码
  312. AlarmHelper<AlarmInfo>.GetInstance(DeviceName).EStop1 = deviceStatus.DeviceAlarmCode.Get16bitValue(1);
  313. AlarmHelper<AlarmInfo>.GetInstance(DeviceName).Servo = deviceStatus.DeviceAlarmCode.Get16bitValue(2);
  314. AlarmHelper<AlarmInfo>.GetInstance(DeviceName).Inverter = deviceStatus.DeviceAlarmCode.Get16bitValue(3);
  315. AlarmHelper<AlarmInfo>.GetInstance(DeviceName).EStop2 = deviceStatus.DeviceAlarmCode.Get16bitValue(7);
  316. AlarmHelper<AlarmInfo>.GetInstance(DeviceName).SiloUpperLimit = deviceStatus.DeviceAlarmCode.Get16bitValue(8);
  317. AlarmHelper<AlarmInfo>.GetInstance(DeviceName).SiloLowerLimit = deviceStatus.DeviceAlarmCode.Get16bitValue(9);
  318. //允许配料即产线气缸抬起,发送给味魔方
  319. if (deviceStatus.DeviceNum >= 1 && deviceStatus.DeviceNum <= 15)
  320. {
  321. if (GVL_SmallStation.GetInstance.plcReadDataDB3.StockBinAllowIssue[deviceStatus.DeviceNum - 1])
  322. {
  323. this.modbusTcp.Write("LW41", (ushort)1);
  324. GVL_SmallStation.GetInstance.StockBinCylinderStatus.SetBitValue((byte)(deviceStatus.DeviceNum), true);
  325. }
  326. else
  327. {
  328. this.modbusTcp.Write("LW41", (ushort)0);
  329. GVL_SmallStation.GetInstance.StockBinCylinderStatus.SetBitValue((byte)(deviceStatus.DeviceNum), false);
  330. }
  331. }
  332. Thread.Sleep(10);
  333. }
  334. }), $"{DeviceName} 开始监听", true);
  335. }
  336. }
  337. public void SetDeviceName(string name)
  338. {
  339. this.modbusTcp.Write(DeviceAddress.DeviceName, new ushort[20]);
  340. this.modbusTcp.Write<string>(DeviceAddress.DeviceName, name);
  341. }
  342. /// <summary>
  343. /// 开盖
  344. /// </summary>
  345. public void OpenLid()
  346. {
  347. //modbusTcp.Write(DeviceAddress.OpenLid, (ushort)1);
  348. }
  349. /// <summary>
  350. /// 关盖
  351. /// </summary>
  352. public void CloseLid()
  353. {
  354. //modbusTcp.Write(DeviceAddress.CloseLid, (ushort)1);
  355. }
  356. public bool StatusReset()
  357. {
  358. return this.modbusTcp.Write(DeviceAddress.FinfishStatus, (ushort)1).IsSuccess;
  359. //var res = modbusTcp.Read(DeviceAddress.RunStatus);
  360. }
  361. public void Dispose()
  362. {
  363. ThreadManage.GetInstance().StopTask($"{DeviceName} 开始监听");
  364. }
  365. /// <summary>
  366. /// 写入重量数据,开始配料。
  367. /// </summary>
  368. /// <param name="Value">配料重量。</param>
  369. public void Start(float Value)
  370. {
  371. if (modbusTcp.IsConnected())
  372. {
  373. var res = Json<DevicePar>.Data.deviceParModels.FirstOrDefault(p => p.MaterialName == DeviceName);
  374. if (res != null)
  375. {
  376. modbusTcp.Write<float>(DeviceAddress.SlowlyAddWeight, res.SlowlyAddWeight);
  377. modbusTcp.Write<float>(DeviceAddress.PreCloseValveWeight, res.PreCloseValveWeight);
  378. modbusTcp.Write<uint>(DeviceAddress.RapidAcceleration, (uint)res.RapidAcceleration);
  379. modbusTcp.Write<uint>(DeviceAddress.SlowAcceleration, (uint)res.SlowAcceleration);
  380. modbusTcp.Write<uint>(DeviceAddress.ServoManualSpeed, (uint)res.ServoManualSpeed);
  381. modbusTcp.Write<uint>(DeviceAddress.SiloUpperLimitWeight, (uint)res.SiloUpperLimitWeight);
  382. modbusTcp.Write<uint>(DeviceAddress.LowerLimitWeightOfSilo, (uint)res.LowerLimitWeightOfSilo);
  383. modbusTcp.Write<uint>(DeviceAddress.StirringSpeed, (uint)res.StirringSpeed * 100);
  384. MessageNotify.GetInstance.ShowRunLog($"{res.MaterialName},参数下发完成");
  385. }
  386. modbusTcp.Write<float>(DeviceAddress.WeightSet, Value);//写入原料重量
  387. if (!modbusTcp.Write(DeviceAddress.Start, (ushort)1).IsSuccess)//设备启动写入
  388. {
  389. MessageNotify.GetInstance.ShowRunLog($"{DeviceName},设置重量:{Value},启动信号写入失败");
  390. }
  391. MessageNotify.GetInstance.ShowRunLog($"{DeviceName},设置重量:{Value},柔性味魔方开始配料");
  392. }
  393. }
  394. }
  395. }