终端一体化运控平台
選択できるのは25トピックまでです。 トピックは、先頭が英数字で、英数字とダッシュ('-')を使用した35文字以内のものにしてください。
 
 
 

1371 行
77 KiB

  1. //#define Debug
  2. extern alias aliyun;
  3. using BPA.Helper;
  4. using BPASmartClient.CustomResource.Pages.Model;
  5. using BPASmartClient.CustomResource.UserControls;
  6. using BPASmartClient.CustomResource.UserControls.MessageShow;
  7. using BPASmartClient.DosingSystem.ViewModel;
  8. using BPASmartClient.Model;
  9. using System;
  10. using System.Collections.Concurrent;
  11. using System.Collections.ObjectModel;
  12. using System.Collections.Specialized;
  13. using System.Diagnostics;
  14. using System.Linq;
  15. using System.Threading;
  16. using System.Threading.Tasks;
  17. using aliyun.uPLibrary.Networking.M2Mqtt.Messages;
  18. using System.Collections.Generic;
  19. using aliyun::BPA.PahoMQ;
  20. using System.Configuration;
  21. using BPA.Communication;
  22. using Newtonsoft.Json;
  23. using System.Reflection;
  24. using System.Text;
  25. using BPASmartClient.DosingSystem.Model;
  26. using Microsoft.EntityFrameworkCore.Metadata.Internal;
  27. using System.Collections;
  28. using static Microsoft.EntityFrameworkCore.DbLoggerCategory;
  29. using System.Windows.Navigation;
  30. using System.Text.RegularExpressions;
  31. using static System.Resources.ResXFileRef;
  32. using BPASmartClient.DosingSystem.Model.Dto;
  33. using BPASmartClient.DosingSystem.Model.MQTT;
  34. namespace BPASmartClient.DosingSystem
  35. {
  36. /// <summary>
  37. /// 业务逻辑执行类
  38. /// </summary>
  39. public class ExcuteControl
  40. {
  41. private static ExcuteControl Instance;
  42. public static ExcuteControl GetInstance => Instance ??= new ExcuteControl();
  43. public ConcurrentDictionary<string, aliyun.BPA.PahoMQ.MessageHandler> mqttCollection = new ConcurrentDictionary<string, aliyun.BPA.PahoMQ.MessageHandler>();
  44. public ConcurrentDictionary<string, string> aliyun = new ConcurrentDictionary<string, string>();
  45. public ObservableCollection<RecipeModel> Recipes { get; set; } = Json<LocalRecipe>.Data.Recipes;
  46. public ObservableCollection<StockStatusModel> StockStatus = new ObservableCollection<StockStatusModel>();
  47. public string CurrentRecipeName { get; set; }
  48. /// <summary>
  49. /// 当前正在制作的配方
  50. /// </summary>
  51. public ObservableCollection<RecipeModel> recipeProcesses { get; set; } = new ObservableCollection<RecipeModel>();
  52. /// <summary>
  53. /// 等待制作的配方
  54. /// </summary>
  55. public ObservableCollection<RecipeModel> UserTreeWait { get; set; } = new ObservableCollection<RecipeModel>();
  56. /// <summary>
  57. /// 已完成的配方
  58. /// </summary>
  59. public ObservableCollection<RecipeModel> UserTreeCompelete { get; set; } = new ObservableCollection<RecipeModel>();
  60. public ConcurrentQueue<string> RecipeNames = new ConcurrentQueue<string>();
  61. /// <summary>
  62. /// 配料完成计数
  63. /// </summary>
  64. int Comcount = 0;
  65. public static bool PropertySet = false;//云端属性设置回调主题订阅标志
  66. public static bool PropertyReport = false; //属性上报主题订阅标志
  67. public static bool EventReport = false; //事件上报主题订阅标志
  68. public static bool ServiceCall = false;//服务调用回调主题订阅标志
  69. public NameValueCollection produtInfo;
  70. public NameValueCollection mqttInfo;
  71. public NameValueCollection ConveyerInfo;
  72. public NameValueCollection ServicesInfo;
  73. public bool AliyunIsConnect = false;
  74. public ExcuteControl()
  75. {
  76. ActionManage.GetInstance.Register<object>(new Action<object>((o) =>
  77. {
  78. if (o != null && o is string recipeName)
  79. {
  80. RecipeSend(recipeName);
  81. }
  82. }), "配方下发");
  83. ActionManage.GetInstance.Register<object>(new Action<object>((ob) =>
  84. {
  85. if (ob != null && ob is string recipeName)
  86. {
  87. CancelRecipe(recipeName);
  88. }
  89. }), "取消配方");
  90. AliYunInit();
  91. RecipeRun();
  92. BusinessExcute();
  93. ConveyerPropertyReport();
  94. ThreadTaskInit();
  95. #if Debug
  96. Task.Run(() => {
  97. while (true)
  98. {
  99. if (AliyunIsConnect)
  100. {
  101. for (int i = 0; i < 6; i++)
  102. {
  103. AliyunEventReport($"192.168.0.{i+1}0", new AliyunStockEventReportModel { Result = "1" }, "StockJerk1StatusEvent", AliyunMaterialModelType.StockModel);
  104. AliyunEventReport($"192.168.0.{i + 1}0", new AliyunStockEventReportModel { Result = "1" }, "StockServoFalutEvent", AliyunMaterialModelType.StockModel);
  105. AliyunEventReport($"192.168.0.{i + 1}0", new AliyunStockEventReportModel { Result = "1" }, "StockJerk2StatusEvent", AliyunMaterialModelType.StockModel);
  106. AliyunEventReport($"192.168.0.{i + 1}0", new AliyunStockEventReportModel { Result = "1" }, "StockUpLimitEvent", AliyunMaterialModelType.StockModel);
  107. AliyunEventReport($"192.168.0.{i + 1}0", new AliyunStockEventReportModel { Result = "1" }, "StockDownLimitEvent", AliyunMaterialModelType.StockModel);
  108. AliyunStockPropertyReportModel model = new AliyunStockPropertyReportModel();
  109. model.StockRealWeight = 1;
  110. model.BucketRealWeight = 2;
  111. model.StockDeviceNum = 2;
  112. model.StockDeviceName = "测试";
  113. model.StockWorkModel = 0;
  114. model.StockSlowlyAddWeight = 6;
  115. model.StockPreCloseValueWeight = 7;
  116. model.StockRapidAcceleration = 46;
  117. model.StockSlowAcceleration = 24;
  118. model.StockServoManualSpeed = 35;
  119. model.StockUpperLimitWeight = 57;
  120. model.StockLowerLimitWeight = 34;
  121. model.StockStirringSpeed = 54;
  122. model.StockMaterialType = "粉体";
  123. model.StockBatchStatus = "待机";
  124. StokcPropertyReport($"192.168.0.{i + 1}0", model);
  125. }
  126. AliyunConveyerPropertyReportModel model1 = new AliyunConveyerPropertyReportModel();
  127. model1.TopBucketControlStatus = 1;
  128. model1.DownBucketControlStatus =1;
  129. model1.RunStatus = 1;
  130. model1.WorkModel = 1;
  131. model1.TopBucketSigleCheck = 1;
  132. model1.ButtonBucketSigleCheck = 1;
  133. model1.ConveyerOnlineStatus =1;
  134. var mqdeviceTestProperty = new PostPropertyParams<AliyunConveyerPropertyReportModel>();
  135. mqdeviceTestProperty.sys = new Sys { ack = 1 };
  136. mqdeviceTestProperty.method = "thing.event.property.post";
  137. mqdeviceTestProperty.version = "1.0";
  138. mqdeviceTestProperty.ModelName = $"{produtInfo.Get("Conveyer")}";
  139. mqdeviceTestProperty.Model = model1;
  140. mqdeviceTestProperty.Init();
  141. var message = JsonConvert.SerializeObject(mqdeviceTestProperty);
  142. var topic = $"/sys/{produtInfo.Get("ProductKey")}/Conveyer/thing/event/property/post";//发布主题
  143. var topicReply = $"/sys/{produtInfo.Get("ProductKey")}/Conveyer/thing/event/property/post_reply";//订阅主题
  144. if (mqttCollection.ContainsKey("Conveyer"))
  145. {
  146. try
  147. {
  148. mqttCollection["Conveyer"].Publish((op) =>
  149. {
  150. op.Message = message;
  151. op.Topic = topic;
  152. op.TopicReply = topicReply;
  153. //if (!PropertyReport)
  154. //{
  155. // op.ThresholdCallback += MqttPostProperty_MqttMsgPublishReceived; // MqttPostProperty_MqttMsgPublishReceived;
  156. // PropertyReport = true;
  157. //}
  158. });
  159. }
  160. catch (Exception)
  161. {
  162. //throw;
  163. }
  164. }
  165. SystemEventReport("ProcessRecipe", new { RecipeName = "测试5" });//正在执行配方上报
  166. if (UserTreeWait.Count > 0)
  167. {
  168. string[] recipeNames = new string[UserTreeWait.Count];
  169. for (int i = 0; i < recipeNames.Length; i++)
  170. {
  171. recipeNames[i] = UserTreeWait.ElementAt(i).RecipeName;
  172. }
  173. SystemEventReport("WaitProcessRecipe", new { RecipeNames = recipeNames });//等待执行配方上报
  174. }
  175. else
  176. {
  177. SystemEventReport("WaitProcessRecipe", new { RecipeNames = new string[] { } });//等待执行配方上报
  178. }
  179. }
  180. Thread.Sleep(5000);
  181. }
  182. });
  183. #endif
  184. }
  185. /// <summary>
  186. /// 阿里云连接检查
  187. /// </summary>
  188. private void AliyunMqConnectCheck()
  189. {
  190. }
  191. public void MqttDisConnect()
  192. {
  193. ThreadManage.GetInstance.Dispose();
  194. foreach (var item in mqttCollection)
  195. {
  196. item.Value._mqttClient?.Disconnect();
  197. }
  198. }
  199. /// <summary>
  200. /// 连接阿里云Iot物联网平台
  201. /// </summary>
  202. /// <exception cref="NotImplementedException"></exception>
  203. private async void AliYunInit()
  204. {
  205. produtInfo = (NameValueCollection)System.Configuration.ConfigurationManager.GetSection("FlexBatchSystem/ProductInfo");
  206. mqttInfo = (NameValueCollection)System.Configuration.ConfigurationManager.GetSection("FlexBatchSystem/MqttInfo");
  207. ConveyerInfo = (NameValueCollection)System.Configuration.ConfigurationManager.GetSection("FlexBatchSystem/ConveyerInfo");
  208. ServicesInfo = (NameValueCollection)System.Configuration.ConfigurationManager.GetSection("FlexBatchSystem/Services");
  209. int count = Json<DevicePar>.Data.BaseParModel.StockCount;//料仓数
  210. #region 料仓连接阿里云
  211. for (int i = 0; i < count; i++)
  212. {
  213. if (!mqttCollection.ContainsKey($"Stock{i + 1}")) //创建料仓设备mqtt连接
  214. {
  215. await Task.Run(() =>
  216. {
  217. try
  218. {
  219. int num = i + 1;
  220. NameValueCollection StockInfo = ((NameValueCollection)System.Configuration.ConfigurationManager.GetSection($"FlexBatchSystem/StockInfo{num}"));
  221. var mes = new aliyun.BPA.PahoMQ.MessageHandler(new aliyun.BPA.PahoMQ.PahoMQOption()
  222. {
  223. Broker = mqttInfo.Get("mqttHostUrl"),
  224. ProductKey = produtInfo.Get("ProductKey"),
  225. DeviceName = StockInfo.Get("DeviceName"),
  226. DeviceSecret = StockInfo.Get("DeviceSecret"),
  227. Port = 1883
  228. });
  229. if (mes._mqttClient.IsConnected)
  230. {
  231. MessageLog.GetInstance.Show($"阿里云--料仓{num}设备激活成功!");
  232. }
  233. else
  234. {
  235. MessageLog.GetInstance.Show($"阿里云--料仓{num}设备激活失败!");
  236. return;
  237. }
  238. mes.Subscribe((op) =>
  239. {
  240. op.TopicReply = $"/sys/{produtInfo.Get("ProductKey")}/{StockInfo.Get("DeviceName")}/thing/service/property/set";
  241. //if (!PropertySet)
  242. //{
  243. op.ThresholdCallback += StockPropertySetCallback;
  244. PropertyReport = true;
  245. //}
  246. });
  247. MessageLog.GetInstance.Show($"阿里云--料仓{num}设备属性设置订阅成功!");
  248. mqttCollection.TryAdd($"Stock{i + 1}", mes);
  249. if (!aliyun.ContainsKey($"{Json<DevicePar>.Data.BaseParModel.NetworkSegAddress}{i + 1}0"))
  250. {
  251. aliyun.TryAdd($"{Json<DevicePar>.Data.BaseParModel.NetworkSegAddress}{i + 1}0", $"Stock{i + 1}");
  252. }
  253. }
  254. catch (Exception)
  255. {
  256. MessageLog.GetInstance.Show($"阿里云--料仓{i}设备激活失败!");
  257. return;
  258. }
  259. });
  260. }
  261. }
  262. #endregion
  263. #region 输送线连接阿里云
  264. if (!mqttCollection.ContainsKey($"Conveyer"))//创建输送线Mqtt连接
  265. {
  266. await Task.Run(() =>
  267. {
  268. try
  269. {
  270. var res = new aliyun.BPA.PahoMQ.MessageHandler(new aliyun.BPA.PahoMQ.PahoMQOption()
  271. {
  272. Broker = mqttInfo.Get("mqttHostUrl"),
  273. ProductKey = produtInfo.Get("ProductKey"),
  274. DeviceName = ConveyerInfo.Get("DeviceName"),
  275. DeviceSecret = ConveyerInfo.Get("DeviceSecret"),
  276. Port = 1883
  277. });
  278. if (res._mqttClient.IsConnected)
  279. {
  280. MessageLog.GetInstance.Show($"阿里云--输送线设备激活成功!");
  281. }
  282. else
  283. {
  284. MessageLog.GetInstance.Show($"阿里云--输送线设备激活失败!");
  285. return;
  286. }
  287. //属性订阅
  288. res.Subscribe((op) =>
  289. {
  290. op.TopicReply = $"/sys/{produtInfo.Get("ProductKey")}/{ConveyerInfo.Get("DeviceName")}/thing/service/property/set";
  291. //if (!PropertySet)
  292. //{
  293. op.ThresholdCallback += ConveyerPropertySetCallback;
  294. PropertyReport = true;
  295. // }
  296. });
  297. MessageLog.GetInstance.Show($"阿里云---输送线设备属性设置订阅成功!");
  298. //服务订阅
  299. for (int j = 0; j < ServicesInfo.AllKeys.Length; j++)
  300. {
  301. res.Subscribe((op) =>
  302. {
  303. op.TopicReply = $"/sys/{produtInfo.Get("ProductKey")}/{ConveyerInfo.Get("DeviceName")}/thing/service/{ServicesInfo.Get(j)}";
  304. if (!ServiceCall)
  305. {
  306. op.ThresholdCallback += ServiceCallback;
  307. ServiceCall = true;
  308. }
  309. });
  310. MessageLog.GetInstance.Show($"阿里云--服务'{ServicesInfo.Get(j)}'订阅成功!");
  311. }
  312. mqttCollection.TryAdd($"Conveyer", res);
  313. }
  314. catch (Exception)
  315. {
  316. MessageLog.GetInstance.Show($"阿里云--输送线设备激活失败!");
  317. return;
  318. }
  319. });
  320. }
  321. if (mqttCollection.ContainsKey("Conveyer")&& mqttCollection["Conveyer"]._mqttClient.IsConnected)
  322. {
  323. AliyunSystemPropertyReportModel m1 = new AliyunSystemPropertyReportModel();
  324. m1.RecipeCollection = new string[Json<LocalRecipe>.Data.Recipes.Count];
  325. for (int i = 0; i < Json<LocalRecipe>.Data.Recipes.Count; i++)
  326. {
  327. m1.RecipeCollection[i] = Json<LocalRecipe>.Data.Recipes[i].RecipeName;
  328. }
  329. SystemPropertyReport(m1);
  330. }
  331. #endregion
  332. }
  333. /// <summary>
  334. /// 料仓属性上报
  335. /// </summary>
  336. /// <param name="ipaddres"></param>
  337. /// <param name="model"></param>
  338. public void StokcPropertyReport<T>(string ipaddres, T model)
  339. {
  340. var mqdeviceTestProperty = new PostPropertyParams<T>();
  341. mqdeviceTestProperty.sys = new Sys { ack = 1 };
  342. mqdeviceTestProperty.method = "thing.event.property.post";
  343. mqdeviceTestProperty.version = "1.0";
  344. mqdeviceTestProperty.ModelName = $"{produtInfo.Get("Stock")}";
  345. mqdeviceTestProperty.Model= model;
  346. mqdeviceTestProperty.Init();
  347. var message = JsonConvert.SerializeObject(mqdeviceTestProperty);
  348. var topic = $"/sys/{produtInfo.Get("ProductKey")}/{aliyun[ipaddres]}/thing/event/property/post";//发布主题
  349. var topicReply = $"/sys/{produtInfo.Get("ProductKey")}/{aliyun[ipaddres]}/thing/event/property/post_reply";//订阅主题
  350. if (mqttCollection.ContainsKey(aliyun[ipaddres]))
  351. {
  352. try
  353. {
  354. mqttCollection[aliyun[ipaddres]].Publish((op) =>
  355. {
  356. op.Message = message;
  357. op.Topic = topic;
  358. op.TopicReply = topicReply;
  359. //if (!PropertyReport)
  360. //{
  361. // op.ThresholdCallback += MqttPostProperty_MqttMsgPublishReceived; // MqttPostProperty_MqttMsgPublishReceived;
  362. // PropertyReport = true;
  363. //}
  364. });
  365. }
  366. catch (Exception)
  367. {
  368. //throw;
  369. }
  370. }
  371. }
  372. /// <summary>
  373. /// 料仓模板或输送线模板事件上报
  374. /// </summary>
  375. /// <param name="ipaddres"></param>
  376. /// <param name="model"></param>
  377. /// <param name="eventFlag"></param>
  378. public void AliyunEventReport<T>(string ipaddres, T model, string eventFlag, AliyunMaterialModelType type)
  379. {
  380. string eventIdentifier;
  381. string deviceName;
  382. MessageHandler messageHandler = null;
  383. if (type == AliyunMaterialModelType.StockModel)
  384. {
  385. eventIdentifier = $"{produtInfo.Get("Stock")}:{eventFlag}";//格式:模板名:事件名
  386. deviceName = aliyun[ipaddres];
  387. if (!mqttCollection.ContainsKey(aliyun[ipaddres]))
  388. return;
  389. messageHandler = mqttCollection[aliyun[ipaddres]];
  390. }
  391. else
  392. {
  393. eventIdentifier = $"{produtInfo.Get("Conveyer")}:{eventFlag}";
  394. deviceName = $"{ConveyerInfo.Get("DeviceName")}";
  395. if (!mqttCollection.ContainsKey("Conveyer"))
  396. return;
  397. messageHandler = mqttCollection["Conveyer"];
  398. }
  399. var mqdeviceTestEvent = new PostEventParams<T>();
  400. mqdeviceTestEvent.id = Guid.NewGuid().ToString();
  401. mqdeviceTestEvent.sys = new Sys { ack = 1 };
  402. mqdeviceTestEvent.method = $"thing.event.{eventIdentifier}.post";
  403. mqdeviceTestEvent.version = "1.0";
  404. mqdeviceTestEvent.@params = new EventParam<T> { value = model, time = new DateTimeOffset(DateTime.Now).ToUnixTimeMilliseconds() };
  405. var eventMessage = JsonConvert.SerializeObject(mqdeviceTestEvent);
  406. //事件上报
  407. var eventTopic = $"/sys/{produtInfo.Get("ProductKey")}/{deviceName}/thing/event/{eventIdentifier}/post";
  408. //事件订阅主题
  409. var eventTopicReply = $"/sys/{produtInfo.Get("ProductKey")}/{deviceName}/thing/event/{eventIdentifier}/post_reply";
  410. try
  411. {
  412. messageHandler.Publish((op) =>
  413. {
  414. op.Message = eventMessage;
  415. op.Topic = eventTopic;
  416. op.TopicReply = eventTopicReply;
  417. //if (!EventReport)
  418. //{
  419. // op.ThresholdCallback += MqttPostEvent_MqttMsgPublishReceived; // MqttPostProperty_MqttMsgPublishReceived;
  420. // EventReport = true;
  421. //}
  422. });
  423. }
  424. catch (Exception)
  425. {
  426. //throw;
  427. }
  428. }
  429. /// <summary>
  430. /// 输送线模板属性上报
  431. /// </summary>
  432. public void ConveyerPropertyReport()
  433. {
  434. TaskManage.GetInstance.StartLong(() =>
  435. {
  436. if (mqttCollection.ContainsKey("Conveyer") && mqttCollection["Conveyer"]._mqttClient.IsConnected)
  437. {
  438. AliyunConveyerPropertyReportModel model = new AliyunConveyerPropertyReportModel();
  439. model.TopBucketControlStatus = Convert.ToInt32(SiemensDevice.GetInstance.MySiemens.Read<bool>("DB5.DBX4.0").Content);
  440. model.DownBucketControlStatus = Convert.ToInt32(SiemensDevice.GetInstance.MySiemens.Read<bool>("DB5.DBX4.1").Content);
  441. model.RunStatus = Convert.ToInt32(SiemensDevice.GetInstance.MySiemens.Read<bool>("M10.0").Content);
  442. model.WorkModel = Convert.ToInt32(SiemensDevice.GetInstance.MySiemens.Read<bool>("M10.1").Content);
  443. model.TopBucketSigleCheck = Convert.ToInt32(GlobalDevice.PlcData.OnDetection);
  444. model.ButtonBucketSigleCheck = Convert.ToInt32(GlobalDevice.PlcData.UnderDetection);
  445. model.ConveyerOnlineStatus = Convert.ToInt32(SiemensDevice.GetInstance.MySiemens.IsConnected());
  446. var mqdeviceTestProperty = new PostPropertyParams<AliyunConveyerPropertyReportModel>();
  447. mqdeviceTestProperty.sys = new Sys { ack = 1 };
  448. mqdeviceTestProperty.method = "thing.event.property.post";
  449. mqdeviceTestProperty.version = "1.0";
  450. mqdeviceTestProperty.ModelName = $"{produtInfo.Get("Conveyer")}";
  451. mqdeviceTestProperty.Model = model;
  452. mqdeviceTestProperty.Init();
  453. var message = JsonConvert.SerializeObject(mqdeviceTestProperty);
  454. var topic = $"/sys/{produtInfo.Get("ProductKey")}/Conveyer/thing/event/property/post";//发布主题
  455. var topicReply = $"/sys/{produtInfo.Get("ProductKey")}/Conveyer/thing/event/property/post_reply";//订阅主题
  456. if (mqttCollection.ContainsKey("Conveyer"))
  457. {
  458. try
  459. {
  460. mqttCollection["Conveyer"].Publish((op) =>
  461. {
  462. op.Message = message;
  463. op.Topic = topic;
  464. op.TopicReply = topicReply;
  465. //if (!PropertyReport)
  466. //{
  467. // op.ThresholdCallback += MqttPostProperty_MqttMsgPublishReceived; // MqttPostProperty_MqttMsgPublishReceived;
  468. // PropertyReport = true;
  469. //}
  470. });
  471. }
  472. catch (Exception)
  473. {
  474. //throw;
  475. }
  476. }
  477. }
  478. Thread.Sleep(1000);
  479. }, "输送线属性上报", true);
  480. }
  481. /// <summary>
  482. /// 业务系统事件上报
  483. /// </summary>
  484. /// <param name="eventFlag"></param>
  485. /// <param name="param"></param>
  486. public void SystemEventReport<T>(string eventFlag, T t)
  487. {
  488. var eventIdentifier = eventFlag;
  489. var mqdeviceTestEvent = new PostEventParams<T>();
  490. mqdeviceTestEvent.id = Guid.NewGuid().ToString();
  491. mqdeviceTestEvent.sys = new Sys { ack = 1 };
  492. mqdeviceTestEvent.method = $"thing.event.{eventIdentifier}.post";
  493. mqdeviceTestEvent.version = "1.0";
  494. mqdeviceTestEvent.@params = new EventParam<T> { value = t, time = new DateTimeOffset(DateTime.Now).ToUnixTimeMilliseconds() };
  495. var eventMessage = JsonConvert.SerializeObject(mqdeviceTestEvent);
  496. //事件上报
  497. var eventTopic = $"/sys/{produtInfo.Get("ProductKey")}/Conveyer/thing/event/{eventIdentifier}/post";
  498. //事件订阅主题
  499. var eventTopicReply = $"/sys/{produtInfo.Get("ProductKey")}/Conveyer/thing/event/{eventIdentifier}/post_reply";
  500. if (mqttCollection.ContainsKey("Conveyer"))
  501. {
  502. try
  503. {
  504. mqttCollection["Conveyer"].Publish((op) =>
  505. {
  506. op.Message = eventMessage;
  507. op.Topic = eventTopic;
  508. op.TopicReply = eventTopicReply;
  509. //if (!EventReport)
  510. //{
  511. // op.ThresholdCallback += MqttPostEvent_MqttMsgPublishReceived; // MqttPostProperty_MqttMsgPublishReceived;
  512. // EventReport = true;
  513. //}
  514. });
  515. }
  516. catch (Exception)
  517. {
  518. // throw;
  519. }
  520. }
  521. }
  522. /// <summary>
  523. /// 业务系统属性上报
  524. /// </summary>
  525. public void SystemPropertyReport<T>(T model)
  526. {
  527. var mqdeviceTestProperty = new PostPropertyParams<T>();
  528. mqdeviceTestProperty.sys = new Sys { ack = 1 };
  529. mqdeviceTestProperty.method = "thing.event.property.post";
  530. mqdeviceTestProperty.version = "1.0";
  531. mqdeviceTestProperty.Model = model;
  532. mqdeviceTestProperty.Init();
  533. var message = JsonConvert.SerializeObject(mqdeviceTestProperty);
  534. var topic = $"/sys/{produtInfo.Get("ProductKey")}/Conveyer/thing/event/property/post";//发布主题
  535. var topicReply = $"/sys/{produtInfo.Get("ProductKey")}/Conveyer/thing/event/property/post_reply";//订阅主题
  536. if (mqttCollection.ContainsKey("Conveyer"))
  537. {
  538. try
  539. {
  540. mqttCollection["Conveyer"].Publish((op) =>
  541. {
  542. op.Message = message;
  543. op.Topic = topic;
  544. op.TopicReply = topicReply;
  545. //if (!PropertyReport)
  546. //{
  547. // op.ThresholdCallback += MqttPostProperty_MqttMsgPublishReceived; // MqttPostProperty_MqttMsgPublishReceived;
  548. // PropertyReport = true;
  549. //}
  550. });
  551. }
  552. catch (Exception)
  553. {
  554. //throw;
  555. }
  556. }
  557. }
  558. /// <summary>
  559. /// 云端属性设置回调方法-输送线模板
  560. /// </summary>
  561. /// <param name="sender"></param>
  562. /// <param name="e"></param>
  563. /// <exception cref="NotImplementedException"></exception>
  564. private void ConveyerPropertySetCallback(object sender, MqttMsgPublishEventArgs e)
  565. {
  566. if (Regex.IsMatch(e.Topic, "[0-9a-zA-Z/]*(thing/service/property/set)$"))
  567. {
  568. var rtn = JsonConvert.DeserializeObject<ServiceBaseResponse<object>>(Encoding.UTF8.GetString(e.Message, 0, e.Message.Length));
  569. PropertyInfo property = rtn.@params.GetType().GetProperty("Root");
  570. string result = property.GetValue(rtn.@params).ToString();
  571. var array = result.Replace("\r\n", "").Replace(" ", "").Replace("{", "").Replace("}", "").Replace("\"", "").Split(',');
  572. foreach (var item in array)
  573. {
  574. var str = item.Split(":"); //数据格式:
  575. if (str.Length >= 3)
  576. {
  577. switch (str[1])
  578. {
  579. case "TopBucketControlStatus": SiemensDevice.GetInstance.MySiemens.Write("DB5.DBX4.0", Convert.ToBoolean(int.Parse(str[2]))); MessageNotify.GetInstance.ShowRunLog($"云端控制上桶位气缸,状态值:{str[2]}"); break;
  580. case "DownBucketControlStatus": SiemensDevice.GetInstance.MySiemens.Write("DB5.DBX4.1", Convert.ToBoolean(int.Parse(str[2]))); MessageNotify.GetInstance.ShowRunLog($"云端控制下桶位气缸,状态值:{str[2]}"); break;
  581. }
  582. }
  583. }
  584. }
  585. }
  586. /// <summary>
  587. /// 云端属性设置回调方法-料仓模板
  588. /// </summary>
  589. /// <param name="sender"></param>
  590. /// <param name="e"></param>
  591. public void StockPropertySetCallback(object sender, MqttMsgPublishEventArgs e)
  592. {
  593. if (Regex.IsMatch(e.Topic, "[0-9a-zA-Z/]*(thing/service/property/set)$"))
  594. {
  595. var rtn = JsonConvert.DeserializeObject<ServiceBaseResponse<object>>(Encoding.UTF8.GetString(e.Message, 0, e.Message.Length));
  596. PropertyInfo property = rtn.@params.GetType().GetProperty("Root");
  597. string result = property.GetValue(rtn.@params).ToString();
  598. var array = result.Replace("\r\n", "").Replace(" ", "").Replace("{", "").Replace("}", "").Replace("\"", "").Split(',');
  599. foreach (var item in array)
  600. {
  601. var str = item.Split(":"); //数据格式:
  602. string ip = $"{Json<DevicePar>.Data.BaseParModel.NetworkSegAddress}{e.Topic.Split('/')[3].Substring(e.Topic.Split('/')[3].Length - 1, 1)}0";
  603. switch (str[1])
  604. {
  605. case "StockSlowlyAddWeight": DeviceInquire.GetInstance.GetDevice(ip).modbusTcp.Write(DeviceAddress.SlowlyAddWeight.ToAdd(), float.Parse(str[2])); MessageNotify.GetInstance.ShowRunLog($"云端对料仓设备{ip}设置慢加重量:值:{str[2]}"); break;
  606. case "StockPreCloseValueWeight": DeviceInquire.GetInstance.GetDevice(ip).modbusTcp.Write(DeviceAddress.PreCloseValveWeight.ToAdd(), float.Parse(str[2])); MessageNotify.GetInstance.ShowRunLog($"云端对料仓设备{ip}设置提前关阀重量:值:{str[2]}"); break;
  607. case "StockRapidAcceleration": DeviceInquire.GetInstance.GetDevice(ip).modbusTcp.Write(DeviceAddress.RapidAcceleration.ToAdd(), uint.Parse(str[2])); MessageNotify.GetInstance.ShowRunLog($"云端对料仓设备{ip}设置快加速:值:{str[2]}"); break;
  608. case "StockSlowAcceleration": DeviceInquire.GetInstance.GetDevice(ip).modbusTcp.Write(DeviceAddress.SlowAcceleration.ToAdd(), uint.Parse(str[2])); MessageNotify.GetInstance.ShowRunLog($"云端对料仓设备{ip}设置慢慢重量:值:{str[2]}"); break;
  609. case "StockServoManualSpeed": DeviceInquire.GetInstance.GetDevice(ip).modbusTcp.Write(DeviceAddress.ServoManualSpeed.ToAdd(), uint.Parse(str[2])); MessageNotify.GetInstance.ShowRunLog($"云端对料仓设备{ip}设置伺服手动速度:值:{str[2]}"); break;
  610. case "StockUpperLimitWeight": DeviceInquire.GetInstance.GetDevice(ip).modbusTcp.Write(DeviceAddress.SiloUpperLimitWeight.ToAdd(), uint.Parse(str[2])); MessageNotify.GetInstance.ShowRunLog($"云端对料仓设备{ip}设置上限重量:值:{str[2]}"); break;
  611. case "StockLowerLimitWeight": DeviceInquire.GetInstance.GetDevice(ip).modbusTcp.Write(DeviceAddress.LowerLimitWeightOfSilo.ToAdd(), uint.Parse(str[2])); MessageNotify.GetInstance.ShowRunLog($"云端对料仓设备{ip}设置下限重量:值:{str[2]}"); break;
  612. case "StockStrringSpeed": DeviceInquire.GetInstance.GetDevice(ip).modbusTcp.Write(DeviceAddress.StirringSpeed.ToAdd(), uint.Parse(str[2])); MessageNotify.GetInstance.ShowRunLog($"云端对料仓设备{ip}设置搅拌速度:值:{str[2]}"); break;
  613. }
  614. }
  615. }
  616. }
  617. /// <summary>
  618. /// 云端服务调用回调方法
  619. /// </summary>
  620. /// <param name="sender"></param>
  621. /// <param name="e"></param>
  622. /// <exception cref="NotImplementedException"></exception>
  623. private void ServiceCallback(object sender, MqttMsgPublishEventArgs e)
  624. {
  625. if (Regex.IsMatch(e.Topic, "[0-9a-zA-Z/]*thing/service/[0-9a-zA-Z:]*$"))
  626. {
  627. var rtn = JsonConvert.DeserializeObject<ServiceBaseResponse<object>>(Encoding.UTF8.GetString(e.Message, 0, e.Message.Length));
  628. PropertyInfo property = rtn.@params.GetType().GetProperty("Root");
  629. string result = property.GetValue(rtn.@params).ToString();
  630. var array = result.Replace("\r\n", "").Replace(" ", "").Replace("{", "").Replace("}", "").Replace("\"", "").Split(',');
  631. //单一服务调用
  632. string res = e.Topic.Split("/")[e.Topic.Split("/").Length - 1];
  633. if (res.Contains(":")) //自定义模板
  634. {
  635. var arr = res.Split(":");
  636. switch (arr[0])
  637. {
  638. case "ConveyerModel":
  639. switch (arr[1])
  640. {
  641. case "RunControlService":
  642. if (array.Count() == 1)
  643. {
  644. SiemensDevice.GetInstance.MySiemens.Write("M10.0", Convert.ToBoolean(int.Parse(array[0].Split(":")[1])));//输送下启停控制
  645. MessageNotify.GetInstance.ShowRunLog($"云端对输送线进行启动控制,值:{array[0].Split(":")[1]}");
  646. }
  647. break;
  648. case "StockAirControlService":
  649. if (array.Count() == 2)
  650. {
  651. var info = array[0].Split(":");
  652. var info1 = array[1].Split(":");
  653. if (info[0].Equals("StockNum"))
  654. {
  655. var addRes = SiemensDevice.GetInstance.GetSiemensBitSingleAdd("DB5.DBX", int.Parse(info[1]));//输送线配料气杠控制
  656. SiemensDevice.GetInstance.MySiemens.Write(addRes, Convert.ToBoolean(int.Parse(info1[1])));
  657. MessageNotify.GetInstance.ShowRunLog($"云端对输送线配料{info[1]}气缸进行升降控制,值:{info1[1]}");
  658. }
  659. else
  660. {
  661. var addRes = SiemensDevice.GetInstance.GetSiemensBitSingleAdd("DB5.DBX", int.Parse(info1[1]));
  662. SiemensDevice.GetInstance.MySiemens.Write(addRes, Convert.ToBoolean(int.Parse(info[1])));
  663. MessageNotify.GetInstance.ShowRunLog($"云端对输送线配料{info[1]}气缸进行升降控制,值:{info[1]}");
  664. }
  665. }
  666. break;
  667. }
  668. break;
  669. case "StockModel": break;
  670. }
  671. }
  672. else //默认模板
  673. {
  674. switch (res)
  675. {
  676. case "RecipeSendService":
  677. var info = array[0].Split(":");
  678. RecipeSend(info[1]);
  679. MessageNotify.GetInstance.ShowRunLog($"云端下发配方:{info[1]}");
  680. break;
  681. case "CancelRecipeService":
  682. var info2 = array[0].Split(":");
  683. CancelRecipe(info2[1]);
  684. MessageNotify.GetInstance.ShowRunLog($"云端取消配方:{info2[1]}");
  685. break;
  686. }
  687. }
  688. }
  689. }
  690. /// <summary>
  691. /// 多线程接收工单配方数据。
  692. /// </summary>
  693. private void ThreadTaskInit()
  694. {
  695. TaskManage.GetInstance.StartLong(new Action(() =>
  696. {
  697. while (MqttServer.GetInstance.WorkOrders.Count > 0)
  698. {
  699. if (MqttServer.GetInstance.WorkOrders.TryDequeue(out WorkOrderPusht wod))
  700. {
  701. App.Current?.Dispatcher?.Invoke(new Action(() =>
  702. {
  703. //TODO:工单数据处理,直接新建配方。
  704. foreach (var recipe in wod.ProductList)
  705. {
  706. var tempRecipe = new RecipeModel();
  707. var tempMaterials = new ObservableCollection<RawMaterialModel>();
  708. if (Json<LocalRecipe>.Data.Recipes.Any(p => p.RecipCode == recipe.Id))
  709. {
  710. continue;
  711. }
  712. else
  713. {
  714. tempRecipe.RecipCode = recipe.Id;
  715. }
  716. tempRecipe.RecipeName = recipe.Name;
  717. foreach (var material in recipe.BOMEntryList)
  718. {
  719. tempMaterials.Add(new RawMaterialModel()
  720. {
  721. RawMaterialName = material.MaterialName,
  722. DeviceIp="",
  723. Loc=1,
  724. RawMaterialWeight=(uint)material.BomQty,
  725. RawMaterialSource=0,
  726. RawMaterialId=material.MaterialId,
  727. });
  728. }
  729. tempRecipe.RawMaterials = tempMaterials;
  730. Json<LocalRecipe>.Data.Recipes.Add(tempRecipe);
  731. }
  732. }));
  733. }
  734. }
  735. Thread.Sleep(500);
  736. }), "工单信息监听");
  737. }
  738. /// <summary>
  739. /// 取消配方
  740. /// </summary>
  741. /// <param name="RecipeName"></param>
  742. public async void CancelRecipe(string RecipeName)
  743. {
  744. if (RecipeName != null)
  745. {
  746. //var res = MessageNotify.GetInstance.ShowDialog($"是否取消配方 【{RecipeName}】制作", DialogType.Warning);
  747. //if (res)
  748. //{
  749. int index = Recipes.ToList().FindIndex(p => p.RecipeName == RecipeName);
  750. if (index >= 0 && index < Recipes.Count)
  751. {
  752. await Task.Factory.StartNew(new Action(() =>
  753. {
  754. Recipes.ElementAt(index).IsEnable = true;
  755. Json<LocalRecipe>.Data.Recipes.ElementAt(index).IsEnable = true;
  756. Recipes.ElementAt(index).Are.Set();
  757. App.Current.Dispatcher.Invoke(new Action(() => { recipeProcesses.Clear(); }));
  758. SiemensDevice.GetInstance.MySiemens.Write("M10.5", true);
  759. MessageNotify.GetInstance.ShowRunLog($"M10.5:true");
  760. Thread.Sleep(1000);
  761. SiemensDevice.GetInstance.MySiemens.Write("M10.5", false);
  762. MessageNotify.GetInstance.ShowRunLog($"M10.5:false");
  763. App.Current.Dispatcher.Invoke(() =>
  764. {
  765. NoticeDemoViewModel.OpenMsg(EnumPromptType.Success, App.MainWindow, "提示", $"配方 [{RecipeName}] 取消成功");
  766. });
  767. MessageNotify.GetInstance.ShowUserLog($"取消配方制作 {RecipeName}");
  768. //取消成功
  769. }));
  770. }
  771. else
  772. {
  773. //取消失败
  774. }
  775. //}
  776. }
  777. else
  778. {
  779. MessageNotify.GetInstance.ShowUserLog($"配方 {RecipeName}取消失败");
  780. }
  781. }
  782. /// <summary>
  783. /// 配方下发
  784. /// </summary>
  785. public void RecipeSend(string RecipeName)
  786. {
  787. if (RecipeName != null)
  788. {
  789. int index = Array.FindIndex(Recipes.ToArray(), p => p.RecipeName == RecipeName);
  790. if (index >= 0 && index < Recipes.Count)
  791. {
  792. for (int i = 0; i < Recipes.ElementAt(index).RawMaterials.Count; i++)
  793. {
  794. if (Recipes.ElementAt(index).RawMaterials.ElementAt(i).RawMaterialSource == 1)
  795. {
  796. string ip = Recipes.ElementAt(index).RawMaterials.ElementAt(i).DeviceIp;
  797. var device = DeviceInquire.GetInstance.GetDevice(ip);
  798. if (ip == null && ip == "")
  799. {
  800. MessageNotify.GetInstance.ShowDialog($"原料 【{Recipes.ElementAt(index).RawMaterials.ElementAt(i).RawMaterialName}】配料系统无法配料,请人工配置此原料:原料{Recipes.ElementAt(index).RawMaterials.ElementAt(i).RawMaterialName},重量{Recipes.ElementAt(index).RawMaterials.ElementAt(i).RawMaterialWeight}", DialogType.Information);
  801. return;
  802. }
  803. if (!device.IsConnected)
  804. {
  805. MessageNotify.GetInstance.ShowDialog($"设备 【{device.DeviceName}】 未连接,不允许下发此配方", DialogType.Error);
  806. return;
  807. }
  808. }
  809. }
  810. Recipes.ElementAt(index).IsEnable = false;
  811. Json<LocalRecipe>.Data.Recipes.ElementAt(index).IsEnable = false;
  812. }
  813. MessageNotify.GetInstance.ShowUserLog($"下发工单 {Recipes.ElementAt(index).RecipeName}");
  814. RecipeNames.Enqueue(RecipeName);
  815. var res = Recipes.FirstOrDefault(p => p.RecipeName == RecipeName);
  816. App.Current.Dispatcher.Invoke(() => { UserTreeWait.Add(new RecipeModel { RecipStatus = "等待制作", SerialNum = UserTreeWait.Count + 1, RecipeName = RecipeName, RawMaterials = res.RawMaterials }); });
  817. }
  818. App.Current.Dispatcher.Invoke(() => { NoticeDemoViewModel.OpenMsg(EnumPromptType.Success, App.MainWindow, "提示", $"配方下发成功!"); });
  819. }
  820. /// <summary>
  821. /// 配方业务执行
  822. /// </summary>
  823. private void RecipeRun()
  824. {
  825. TaskManage.GetInstance.StartLong(new Action(() =>
  826. {
  827. if (RecipeNames.Count > 0)
  828. {
  829. int index = Array.FindIndex(Recipes.ToArray(), p => p.RecipeName == RecipeNames.ElementAt(0));
  830. if (index >= 0 && index < Recipes.Count)
  831. {
  832. Recipes.ElementAt(index).Are.Reset();
  833. Recipes.ElementAt(index).IsEnable = false;
  834. StockStatus.Clear();
  835. App.Current.Dispatcher.Invoke(new Action(() =>
  836. {
  837. recipeProcesses.Clear();
  838. if (UserTreeWait.Count > 0) App.Current.Dispatcher.Invoke(() =>
  839. {
  840. UserTreeWait.RemoveAt(0);
  841. });
  842. }));
  843. CurrentRecipeName = Recipes.ElementAt(index).RecipeName;
  844. #region 执行配方以及等待执行配方上报
  845. SystemEventReport("ProcessRecipe", new { RecipeName = CurrentRecipeName });//正在执行配方上报
  846. if (UserTreeWait.Count > 0)
  847. {
  848. string[] recipeNames = new string[UserTreeWait.Count];
  849. for (int i = 0; i < recipeNames.Length; i++)
  850. {
  851. recipeNames[i] = UserTreeWait.ElementAt(i).RecipeName;
  852. }
  853. SystemEventReport("WaitProcessRecipe", new { RecipeNames = recipeNames });//等待执行配方上报
  854. }
  855. else
  856. {
  857. SystemEventReport("WaitProcessRecipe", new { RecipeNames=new string[] { } });//等待执行配方上报
  858. }
  859. #endregion
  860. #region 配方下发到PLC操作相关
  861. //配方数据写入到输送机
  862. var res = Json<LocalRecipe>.Data.Recipes.FirstOrDefault(p => p.RecipeName == CurrentRecipeName);
  863. List<int> BarrelNum = new List<int>();
  864. ConcurrentDictionary<string, int[]> values = new();
  865. if (res != null)
  866. {
  867. var tInfo = res.RawMaterials.GroupBy(p => p.Loc);//获取桶号信息
  868. if (tInfo != null)
  869. {
  870. for (int i = 0; i < tInfo.Count(); i++)
  871. {
  872. int data = 0;
  873. for (int m = 0; m < tInfo.ElementAt(i).Count(); m++)
  874. {
  875. var TempName = tInfo.ElementAt(i).ElementAt(m).RawMaterialName;
  876. var tempDevice = DeviceInquire.GetInstance.devices.FirstOrDefault(p => p.DeviceName == TempName);
  877. if (tempDevice != null)
  878. {
  879. /*data = data.SetBitValue((byte)tempDevice.DeviceNum, true);*/
  880. if (tempDevice.DeviceNum > 0)
  881. {
  882. // //int a = data.SetBitValue((byte)tInfo.ElementAt(i).ElementAt(m).Loc, true);
  883. // //byte[] test1 = a.ToBytes(BPA.Helper.DataFormat.BADC);
  884. // //int item = test1.ToInt();
  885. // int item = data.SetBitValue((byte)tInfo.ElementAt(i).ElementAt(m).Loc, true).ToBytes(BPA.Helper.DataFormat.BADC).ToInt();
  886. // int item1 = SiemensDevice.GetInstance.MySiemens.Read<int>($"DB4.DBD{2 + (tempDevice.DeviceNum - 1) * 4}").Content;
  887. ////prop1:
  888. // var RE = SiemensDevice.GetInstance.MySiemens.Write($"DB4.DBD{2 + (tempDevice.DeviceNum - 1) * 4}", item + item1);
  889. // //var values = SiemensDevice.GetInstance.MySiemens.Read<int>($"DB4.DBD{2 + (tempDevice.DeviceNum - 1) * 4}");
  890. // //if ((values != null && values.ToString() != (item + item1).ToString()) || values == null)
  891. // // goto prop1;
  892. // if (RE.IsSuccess)
  893. // MessageNotify.GetInstance.ShowRunLog($"下发配方DB4.DBD{2 + (tempDevice.DeviceNum - 1) * 4} :{(byte)tInfo.ElementAt(i).ElementAt(m).Loc}-{item + item1}-{(item + item1).ToBinString()}");
  894. // else
  895. // MessageNotify.GetInstance.ShowRunLog($"下发配方DB4.DBD{2 + (tempDevice.DeviceNum - 1) * 4} 失败");
  896. int item = data.SetBitValue((byte)tInfo.ElementAt(i).ElementAt(m).Loc, true).ToBytes(BPA.Helper.DataFormat.BADC).ToInt();
  897. string tempAdd = $"DB4.DBD{2 + (tempDevice.DeviceNum - 1) * 4}";
  898. if (!values.ContainsKey(tempAdd)) values.TryAdd(tempAdd, new int[2] { 0, 0 });
  899. values[tempAdd][0] = values[tempAdd][0] + item;
  900. values[tempAdd][1] = tInfo.ElementAt(i).ElementAt(m).Loc;
  901. }
  902. }
  903. if (tInfo.ElementAt(i).ElementAt(m).Loc > 0)
  904. {
  905. if (!BarrelNum.Contains(tInfo.ElementAt(i).ElementAt(m).Loc))
  906. {
  907. BarrelNum.Add(tInfo.ElementAt(i).ElementAt(m).Loc);
  908. }
  909. }
  910. }
  911. }
  912. }
  913. }
  914. values?.ToList().ForEach(x =>
  915. {
  916. SiemensDevice.GetInstance.MySiemens.Write(x.Key, x.Value[0]).OnSuccess(() =>
  917. {
  918. MessageNotify.GetInstance.ShowRunLog($"下发配方-{x.Key} :桶数:[{x.Value[1]}]-{x.Value[0].ToBinString()}");
  919. }).OnFail(s =>
  920. {
  921. MessageNotify.GetInstance.ShowRunLog($"下发配方-{x.Key} 失败");
  922. });
  923. });
  924. SiemensDevice.GetInstance.MySiemens.Write("DB4.DBD198", BarrelNum.Count);//配方使用桶数写入
  925. SiemensDevice.GetInstance.MySiemens.Write("DB4.DBX0.1", true);//配方执行启动
  926. Stopwatch sw = new Stopwatch();
  927. var recipe = Recipes.ElementAt(index);
  928. ObservableCollection<RawMaterialModel> RawMater = new ObservableCollection<RawMaterialModel>();
  929. foreach (var item in recipe.RawMaterials)
  930. {
  931. RawMater.Add(new RawMaterialModel()
  932. {
  933. RawMaterialName = item.RawMaterialName,
  934. DeviceIp = item.DeviceIp,
  935. DownLimtFeedback = item.DownLimtFeedback,
  936. Loc = item.Loc,
  937. RawMaterialId = item.RawMaterialId,
  938. RawMaterialSource = item.RawMaterialSource,
  939. RawMaterialType = item.RawMaterialType,
  940. RawMaterialWeight = item.RawMaterialWeight,
  941. RecipeStatus = item.RecipeStatus,
  942. SelectIndex = item.SelectIndex,
  943. Status = item.Status,
  944. UpLimtFeedback = item.UpLimtFeedback,
  945. UpLimtWeightFeedback = item.UpLimtWeightFeedback,
  946. WeightFeedback = item.WeightFeedback,
  947. });
  948. }
  949. App.Current.Dispatcher.Invoke(() =>
  950. {
  951. recipeProcesses.Add(new RecipeModel()
  952. {
  953. RawMaterials = RawMater,
  954. IsEnable = recipe.IsEnable,
  955. RecipeName = recipe.RecipeName,
  956. SerialNum = recipe.SerialNum,
  957. RecipCode = recipe.RecipCode,
  958. });
  959. });
  960. sw.Restart();
  961. while (true)
  962. {
  963. if (sw.ElapsedMilliseconds >= 3000 && !GlobalDevice.PlcData.ResComplete)
  964. {
  965. MessageNotify.GetInstance.ShowRunLog("获取配方下发反馈超时");
  966. break;
  967. }
  968. if (GlobalDevice.PlcData.ResComplete)
  969. {
  970. SiemensDevice.GetInstance.MySiemens.Write("DB3.DBX0.1", false);
  971. break;
  972. }
  973. Thread.Sleep(100);
  974. }
  975. #endregion
  976. Recipes.ElementAt(index).Are.WaitOne();//阻塞,直到当前配方完成
  977. RecipeNames.TryDequeue(out string deviceName);
  978. var recipeComple = Recipes.ElementAt(index);
  979. ObservableCollection<RawMaterialModel> RawMaterComple = new ObservableCollection<RawMaterialModel>();
  980. foreach (var item in recipeComple.RawMaterials)
  981. {
  982. RawMaterComple.Add(new RawMaterialModel()
  983. {
  984. RawMaterialName = item.RawMaterialName,
  985. DeviceIp = item.DeviceIp,
  986. DownLimtFeedback = item.DownLimtFeedback,
  987. Loc = item.Loc,
  988. RawMaterialId = item.RawMaterialId,
  989. RawMaterialSource = item.RawMaterialSource,
  990. RawMaterialType = item.RawMaterialType,
  991. RawMaterialWeight = item.RawMaterialWeight,
  992. RecipeStatus = item.RecipeStatus,
  993. SelectIndex = item.SelectIndex,
  994. Status = item.Status,
  995. UpLimtFeedback = item.UpLimtFeedback,
  996. UpLimtWeightFeedback = item.UpLimtWeightFeedback,
  997. WeightFeedback = item.WeightFeedback,
  998. });
  999. }
  1000. App.Current.Dispatcher.Invoke(() =>
  1001. {
  1002. UserTreeCompelete.Add(new RecipeModel()
  1003. {
  1004. RawMaterials = RawMaterComple,
  1005. IsEnable = recipeComple.IsEnable,
  1006. RecipeName = recipeComple.RecipeName,
  1007. SerialNum = UserTreeCompelete.Count + 1,
  1008. RecipCode = recipeComple.RecipCode,
  1009. RecipStatus = "制作完成"
  1010. });
  1011. });
  1012. App.Current.Dispatcher.Invoke(new Action(() =>
  1013. {
  1014. recipeProcesses.Clear();
  1015. CurrentRecipeName = string.Empty;
  1016. }));//完成后清空当前配方
  1017. }
  1018. }
  1019. Thread.Sleep(100);
  1020. }), "启动配方下发", true);
  1021. }
  1022. /// <summary>
  1023. /// 配料逻辑
  1024. /// </summary>
  1025. /// <param name="recipeModel">当前执行的配方</param>
  1026. public void BusinessExcute()
  1027. {
  1028. ThreadManage.GetInstance.StartLong(new Action(() =>
  1029. {
  1030. #region 测试
  1031. ////拿到当前配方
  1032. //for (int j = 0; j < GlobalDevice.PlcData.IsAllowIngredients.Length; j++)//遍历允许配料的料桶
  1033. //{
  1034. // if (GlobalDevice.PlcData.IsAllowIngredients[j])
  1035. // {
  1036. // int barrelNum = j + 1;//桶号
  1037. // int stockLoc = GlobalDevice.PlcData.LocationFeedback[j];//允许配料的料仓位置 0~6 双仓情况下返回的位置是否一样,料仓ip设置顺序怎样的
  1038. // if (stockLoc >= 1 && stockLoc <= Json<DevicePar>.Data.BaseParModel.StockCount)
  1039. // {
  1040. // int index = Array.FindIndex(DeviceInquire.GetInstance.devices.ToArray(), p => p.DeviceNum == stockLoc);
  1041. // if (index >= 0)
  1042. // {
  1043. // //查出到配料位置的原料
  1044. // int result = Array.FindIndex(recipeModel.RawMaterials.ToArray(), p => (p.Loc == barrelNum && p.DeviceIp == DeviceInquire.GetInstance.devices.ElementAt(index).IpAddress));//待定
  1045. // if (result != -1 && DeviceInquire.GetInstance.GetDevice(recipeModel.RawMaterials[result].DeviceIp).deviceStatus.RunStatus == 1 && RecipeControlViewModel.recipeProcesses.ElementAt(0).RawMaterials[result].Status == Status.等待配料)
  1046. // {
  1047. // var weight = recipeModel.RawMaterials[result].RawMaterialWeight;
  1048. // DeviceInquire.GetInstance.GetDevice(recipeModel.RawMaterials.ElementAt(index).DeviceIp).Start(weight);//所有参数下发并启动配料
  1049. // MessageNotify.GetInstance.ShowRunLog($"{recipeModel.RawMaterials[result].DeviceIp}:正在配料");
  1050. // RecipeControlViewModel.recipeProcesses.ElementAt(0).RawMaterials[result].Status = Status.正在配料;
  1051. // }
  1052. // }
  1053. // }
  1054. // else
  1055. // {
  1056. // continue;
  1057. // }
  1058. // }
  1059. //}
  1060. ////配料完成后逻辑
  1061. //for (int k = 0; k < recipeModel.RawMaterials.Count; k++)
  1062. //{
  1063. // if (DeviceInquire.GetInstance.GetDevice(recipeModel.RawMaterials.ElementAt(k).DeviceIp).deviceStatus.RunStatus == 3 && RecipeControlViewModel.recipeProcesses.ElementAt(0).RawMaterials[k].Status != Status.配料完成)//配料完成
  1064. // {
  1065. // int DeviceNum = DeviceInquire.GetInstance.GetDevice(recipeModel.RawMaterials.ElementAt(k).DeviceIp).deviceStatus.DeviceNum;
  1066. // Comcount++;
  1067. // DeviceInquire.GetInstance.GetDevice(recipeModel.RawMaterials.ElementAt(k).DeviceIp).StatusReset();//料仓复位
  1068. // SiemensDevice.GetInstance.MySiemens.Write($"DB4.DBX130.{DeviceNum - 1}", true);
  1069. // Task.Run(() =>
  1070. // {
  1071. // int cout = DeviceNum - 1;
  1072. // while (!SiemensDevice.GetInstance.MySiemens.Read<bool>($"DB3.DBX148.{cout}").Content) //DB3.DBX148.0-31 148.0-148.5代表6个料仓位置
  1073. // {
  1074. // SiemensDevice.GetInstance.MySiemens.Write($"DB4.DBX130.{cout}", true);
  1075. // Thread.Sleep(200);
  1076. // }
  1077. // while (SiemensDevice.GetInstance.MySiemens.Read<bool>($"DB3.DBX148.{cout}").Content)
  1078. // {
  1079. // SiemensDevice.GetInstance.MySiemens.Write($"DB4.DBX130.{cout}", false);
  1080. // }
  1081. // MessageNotify.GetInstance.ShowRunLog($"{cout}号气缸复位信号写入成功!");
  1082. // });
  1083. // RecipeControlViewModel.recipeProcesses.ElementAt(0).RawMaterials[k].Status = Status.配料完成;
  1084. // if (Comcount >= recipeModel.RawMaterials.Count) //配方配料完成 StockStatus.Count >= Recipes.ElementAt(i).RawMaterials.Count &&
  1085. // {
  1086. // Comcount = 0;
  1087. // App.Current.Dispatcher.Invoke(new Action(() => { RecipeControlViewModel.recipeProcesses.Clear(); }));
  1088. // MessageNotify.GetInstance.ShowUserLog($"配方:{recipeModel.RecipeName},配料完成");
  1089. // SiemensDevice.GetInstance.MySiemens.Write("DB4.DBX202.0", true);//配料完成
  1090. // MessageNotify.GetInstance.ShowRunLog($"配方:{recipeModel.RecipeName},配料完成");
  1091. // recipeModel.Are.Set();//待定
  1092. // Thread.Sleep(100);
  1093. // }
  1094. // }
  1095. //}
  1096. #endregion
  1097. #region 正式版
  1098. for (int i = 0; i < Recipes.Count; i++)
  1099. {
  1100. for (int m = 0; m < Recipes.ElementAt(i).RawMaterials.Count; m++)
  1101. {
  1102. var RunStatus = DeviceInquire.GetInstance.GetDevice(Recipes.ElementAt(i).RawMaterials.ElementAt(m).DeviceIp).deviceStatus.RunStatus;
  1103. //设备状态显示
  1104. if (Recipes.ElementAt(i).RecipeName == CurrentRecipeName)
  1105. {
  1106. string tempRawMaterialName = DeviceInquire.GetInstance.GetDevice(Recipes.ElementAt(i).RawMaterials.ElementAt(m).DeviceIp).DeviceName;
  1107. int recIndex = recipeProcesses.ToList().FindIndex(p => p.RecipeName == CurrentRecipeName);
  1108. if (recIndex >= 0 && recIndex < recipeProcesses.Count)
  1109. {
  1110. int index = recipeProcesses.ElementAt(recIndex).RawMaterials.ToList().FindIndex(p => p.RawMaterialName == tempRawMaterialName);
  1111. if (index >= 0 && index < recipeProcesses.ElementAt(recIndex).RawMaterials.Count)
  1112. {
  1113. //测试使用
  1114. recipeProcesses.ElementAt(recIndex).RawMaterials.ElementAt(index).RecipeStatus = RunStatus;
  1115. }
  1116. for (int j = 0; j < GlobalDevice.PlcData.IsAllowIngredients.Length; j++)
  1117. {
  1118. if (GlobalDevice.PlcData.IsAllowIngredients[j])
  1119. {
  1120. int barrel = j + 1;//桶号
  1121. int cnt = GlobalDevice.PlcData.LocationFeedback[j];//允许配料的位置 1~6
  1122. if (RTrig.GetInstance($"a{j}").Start(GlobalDevice.PlcData.IsAllowIngredients[j]))
  1123. {
  1124. MessageNotify.GetInstance.ShowRunLog($"桶号:{barrel},位置:{cnt},允许配料");
  1125. }
  1126. int Location1 = 0;
  1127. int Location2 = 0;
  1128. if (cnt == -1)
  1129. {
  1130. MessageNotify.GetInstance.ShowRunLog("错误");
  1131. return;
  1132. }
  1133. else
  1134. {
  1135. if (cnt >= 1 && cnt <= 6)
  1136. {
  1137. int a1 = Array.FindIndex(DeviceInquire.GetInstance.devices.ToArray(), p => p.DeviceNum == cnt);
  1138. if (a1 >= 0)
  1139. {
  1140. Location1 = Array.FindIndex(Recipes.ElementAt(i).RawMaterials.ToArray(), p => p.RawMaterialName == DeviceInquire.GetInstance.devices.ElementAt(a1).DeviceName && p.Loc == barrel);
  1141. }
  1142. }
  1143. }
  1144. if (Location1 >= 0)
  1145. {
  1146. string RawName = Recipes.ElementAt(i).RawMaterials.ElementAt(Location1).RawMaterialName;
  1147. int abc = Array.FindIndex(DeviceInquire.GetInstance.devices.ToArray(), p => p.DeviceName == RawName);
  1148. int DeviceNum = DeviceInquire.GetInstance.devices.ElementAt(abc).DeviceNum;
  1149. if (DeviceNum > 0)
  1150. {
  1151. float weight = Recipes.ElementAt(i).RawMaterials.ElementAt(Location1).RawMaterialWeight;
  1152. int loc = Array.FindIndex(Recipes.ElementAt(i).RawMaterials.ToArray(), p => (p.RawMaterialName == RawName));
  1153. if (loc >= 0 && RawName != null && weight >= 0)
  1154. {
  1155. int St_index = Array.FindIndex(StockStatus.ToArray(), p => p.MaterialName == RawName);
  1156. if (St_index < 0) //|| (StockStatus.Count < materialCount && St_index > 0)
  1157. {
  1158. StockStatus.Add(new StockStatusModel()
  1159. {
  1160. MaterialName = RawName,
  1161. IssueWeight = weight,
  1162. IssueStatus = 0,
  1163. });
  1164. }
  1165. St_index = Array.FindIndex(StockStatus.ToArray(), p => p.MaterialName == RawName);//&& p.IssueStatus == 0)
  1166. if (St_index >= 0)
  1167. {
  1168. if (RTrig.GetInstance($"ac{j}-{St_index}").Start(GlobalDevice.PlcData.IsAllowIngredients[j]))
  1169. {
  1170. MessageNotify.GetInstance.ShowRunLog($"{St_index}-{j}--》允许配料");
  1171. if (StockStatus.ElementAt(St_index).IssueStatus == 2)
  1172. {
  1173. StockStatus.ElementAt(St_index).IssueStatus = 0;
  1174. MessageNotify.GetInstance.ShowRunLog($"{St_index}-复位");
  1175. }
  1176. }
  1177. var rrr = DeviceInquire.GetInstance.GetDevice(Recipes.ElementAt(i).RawMaterials.ElementAt(loc).DeviceIp).deviceStatus.RunStatus;
  1178. if ((recipeProcesses.ElementAt(recIndex).RawMaterials.ElementAt(loc).RecipeStatus == 1 && StockStatus.ElementAt(St_index).IssueStatus == 0))//
  1179. {
  1180. StockStatus.ElementAt(St_index).IssueStatus = 1;
  1181. DeviceInquire.GetInstance.GetDevice(Recipes.ElementAt(i).RawMaterials.ElementAt(loc).DeviceIp).Start(weight);
  1182. var res = recipeProcesses.ElementAt(recIndex).RawMaterials.FirstOrDefault(p => p.Status != Status.正在配料 && p.Status != Status.配料完成 && p.RawMaterialName == tempRawMaterialName && p.Loc == j + 1);
  1183. if (res != null)
  1184. res.Status = Status.正在配料;
  1185. MessageNotify.GetInstance.ShowRunLog($"设备执行状态:{rrr}");
  1186. MessageNotify.GetInstance.ShowRunLog($"柔性味魔方{Recipes.ElementAt(i).RawMaterials.ElementAt(loc).DeviceIp},开始出料");
  1187. }
  1188. if (recipeProcesses.ElementAt(recIndex).RawMaterials.ElementAt(loc).RecipeStatus == 3 && StockStatus.ElementAt(St_index).IssueStatus == 1)
  1189. {
  1190. //GlobalDevice.PlcData.IsAllowIngredients[j] = false;//测试使用
  1191. Comcount++;
  1192. StockStatus.ElementAt(St_index).IssueStatus = 2;
  1193. DeviceInquire.GetInstance.GetDevice(Recipes.ElementAt(i).RawMaterials.ElementAt(loc).DeviceIp).StatusReset();
  1194. //int a = 0.SetBitValue((byte)(DeviceNum), true);
  1195. //byte[] test1 = a.ToBytes(BPA.Helper.DataFormat.BADC);
  1196. //int item = test1.ToInt();
  1197. //prop1:
  1198. // SiemensDevice.GetInstance.MySiemens.Write("DB4.DBD130", item);
  1199. SiemensDevice.GetInstance.MySiemens.Write($"DB4.DBX130.{DeviceNum - 1}", true);
  1200. Task.Run(() =>
  1201. {
  1202. int cout = DeviceNum - 1;
  1203. while (!SiemensDevice.GetInstance.MySiemens.Read<bool>($"DB3.DBX148.{cout}").Content) //DB3.DBX148.0-31 148.0-148.5代表6个料仓位置
  1204. {
  1205. SiemensDevice.GetInstance.MySiemens.Write($"DB4.DBX130.{cout}", true);
  1206. Thread.Sleep(200);
  1207. }
  1208. while (SiemensDevice.GetInstance.MySiemens.Read<bool>($"DB3.DBX148.{cout}").Content)
  1209. {
  1210. SiemensDevice.GetInstance.MySiemens.Write($"DB4.DBX130.{cout}", false);
  1211. }
  1212. MessageNotify.GetInstance.ShowRunLog($"{cout}号气缸复位信号写入成功!");
  1213. });
  1214. var res = recipeProcesses.ElementAt(recIndex).RawMaterials.FirstOrDefault(p => p.Status != Status.配料完成 && p.RawMaterialName == tempRawMaterialName && p.Loc == j + 1);
  1215. if (res != null)
  1216. res.Status = Status.配料完成;
  1217. MessageNotify.GetInstance.ShowRunLog($"设备完成执行状态:{rrr}");
  1218. MessageNotify.GetInstance.ShowRunLog($"柔性味魔方{Recipes.ElementAt(i).RawMaterials.ElementAt(loc).DeviceIp},出料完成,状态复位");
  1219. }
  1220. }
  1221. }
  1222. }
  1223. }
  1224. }
  1225. }
  1226. if (Comcount >= Recipes.ElementAt(i).RawMaterials.Count) //配方配料完成 StockStatus.Count >= Recipes.ElementAt(i).RawMaterials.Count &&
  1227. {
  1228. SystemEventReport<AliyunSystemEventReportModel>("RecipeCompleteEvent", new AliyunSystemEventReportModel { RecipeName = CurrentRecipeName });
  1229. int cc = recipeProcesses.ElementAt(recIndex).RawMaterials.OrderBy(p => p.RawMaterialName).Count();
  1230. for (int k = 0; k < 32; k++)
  1231. {
  1232. for (int l = 0; l < cc; l++)
  1233. {
  1234. RTrig.GetInstance($"ac{k}-{l}").Start(false);
  1235. }
  1236. }
  1237. Comcount = 0;
  1238. StockStatus.Clear();
  1239. MessageNotify.GetInstance.ShowUserLog($"配方:{recipeProcesses.ElementAt(recIndex).RecipeName},配料完成");
  1240. foreach (var item in recipeProcesses.ElementAt(recIndex).RawMaterials)
  1241. {
  1242. MessageNotify.GetInstance.ShowUserLog($"原料:{item.RawMaterialName},桶号:{item.Loc},设定配料重量{item.RawMaterialWeight}g,实际配料重量{item.UpLimtWeightFeedback}g");
  1243. }
  1244. SiemensDevice.GetInstance.MySiemens.Write("DB4.DBX202.0", true);//配料完成
  1245. MessageNotify.GetInstance.ShowRunLog($"配方:{CurrentRecipeName},配料完成");
  1246. int recipIndex = Array.FindIndex(Recipes.ToArray(), p => p.RecipeName == CurrentRecipeName);
  1247. App.Current.Dispatcher.Invoke(new Action(() => { recipeProcesses.Clear(); }));
  1248. Recipes.ElementAt(recipIndex).IsEnable = true;
  1249. Json<LocalRecipe>.Data.Recipes.ElementAt(recipIndex).IsEnable = true;
  1250. Recipes.ElementAt(recipIndex).Are.Set();
  1251. Thread.Sleep(100);
  1252. }
  1253. }
  1254. }
  1255. }
  1256. }
  1257. #endregion
  1258. Thread.Sleep(10);
  1259. }), "配料业务逻辑");
  1260. }
  1261. }
  1262. }