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.
 
 

672 lines
24 KiB

  1. //#define test
  2. using BPA.Message;
  3. using HBLConsole.Communication;
  4. using HBLConsole.Factory;
  5. using HBLConsole.Interface;
  6. using HBLConsole.Model;
  7. using HBLConsole.Service;
  8. using System;
  9. using System.Collections.Generic;
  10. using System.Linq;
  11. using System.Text;
  12. using System.Threading;
  13. using System.Threading.Tasks;
  14. using BPA.Message.Enum;
  15. using HBLConsole.GVL;
  16. using BPA.Models;
  17. using BPA.Message.IOT;
  18. namespace HBLConsole.MORKS
  19. {
  20. public class Control_MORKS : IControl
  21. {
  22. #region 单例模式
  23. private static Control_MORKS _instance;
  24. public static Control_MORKS Instance
  25. {
  26. get
  27. {
  28. if (_instance == null)
  29. _instance = new Control_MORKS();
  30. return _instance;
  31. }
  32. }
  33. public Control_MORKS()
  34. {
  35. }
  36. #endregion
  37. public GVL_MORKS mORKS { get; set; } = new GVL_MORKS();
  38. public void Init()
  39. {
  40. ActionOperate.GetInstance.Register(new Action(() => { WriteRecipeBoms(); }), "recipeBom");
  41. ActionOperate.GetInstance.Register(new Action(() => { DeviceInit(); }), "InitCommand");
  42. }
  43. public object GetT()
  44. {
  45. return mORKS;
  46. }
  47. public void ConnectOk()
  48. {
  49. //WriteRecipeBoms();
  50. ReadData();
  51. Main();
  52. //ResetProgram();
  53. MessageLog.GetInstance.Show("MORKS 设备初始化完成");
  54. }
  55. /// <summary>
  56. /// 复位程序
  57. /// </summary>
  58. private void ResetProgram()
  59. {
  60. ThreadOperate.GetInstance.StartLong(new Action(() =>
  61. {
  62. if (RTrig.GetInstance("ResetProgram").Start(mORKS.DeviceIniting))
  63. {
  64. ThreadOperate.GetInstance.StopTask("MainTask", new Action(() =>
  65. {
  66. mORKS.AllowRun = false;
  67. TakeBowlId = string.Empty;
  68. IngredientsCompleteId = string.Empty;
  69. CookNodelId = new string[6] { string.Empty, string.Empty, string.Empty, string.Empty, string.Empty, string.Empty, };
  70. mORKS.RobotTaskInterlock = false;
  71. OutMealId = string.Empty;
  72. mORKS.TakeBowlInterlock = false;
  73. mORKS.TakeNoodleInterlock = false;
  74. mORKS.OutNoodleing = false;
  75. Main();
  76. }));
  77. }
  78. Thread.Sleep(10);
  79. }), "ResetProgram");
  80. }
  81. /// <summary>
  82. /// 数据读取
  83. /// </summary>
  84. public void ReadData()
  85. {
  86. ThreadOperate.GetInstance.StartLong(new Action(() =>
  87. {
  88. ModbusTcpHelper.GetInstance.Readbool(323, 3, new Action<bool[]>((bools) =>
  89. {
  90. mORKS.RobotTakeNoodle = bools[0];
  91. mORKS.RobotOutMeal = bools[1];
  92. mORKS.MoveTurntable = bools[2];
  93. }));
  94. ModbusTcpHelper.GetInstance.Readbool(1120, 16, new Action<bool[]>((bools) =>
  95. {
  96. mORKS.InitComplete = bools[0];
  97. mORKS.TakeBowlIdle = bools[1];
  98. mORKS.TemperatureReached = bools[2];
  99. mORKS.AllowFallNoodle = bools[3];
  100. mORKS.RbTakeNoodleComplete = bools[4];
  101. mORKS.RbFallNoodleComplete = bools[5];
  102. mORKS.RbOutMealComplete = bools[6];
  103. mORKS.RobotIdle = bools[7];
  104. mORKS.TakeMealDetect = bools[8];
  105. mORKS.MissingBowl = bools[9];
  106. mORKS.DeviceIniting = bools[10];
  107. mORKS.TurntableLowerLimit = bools[11];
  108. mORKS.MissingBowlSignal2 = bools[12];
  109. mORKS.TurntableUpLimit = bools[13];
  110. mORKS.TurntableMoveInPlace = bools[15];
  111. }));
  112. ModbusTcpHelper.GetInstance.Readbool(1136, 6, new Action<bool[]>((bools) =>
  113. {
  114. for (int i = 0; i < 6; i++)
  115. {
  116. mORKS.NoodleCookerStatus[i] = bools[i];
  117. }
  118. }));
  119. ModbusTcpHelper.GetInstance.Readbool(1144, 6, new Action<bool[]>((bools) =>
  120. {
  121. for (int i = 0; i < 6; i++)
  122. {
  123. mORKS.CookNoodlesComplete[i] = bools[i];
  124. }
  125. }));
  126. Thread.Sleep(500);
  127. }), "ReadPLCData");
  128. }
  129. public void SimOrder<T>(T simOrder)
  130. {
  131. if (simOrder != null)
  132. {
  133. if (simOrder is List<ushort> locs)
  134. {
  135. string subId = Guid.NewGuid().ToString();
  136. foreach (var item in locs)
  137. {
  138. if (item >= 1 && item <= 5)
  139. {
  140. mORKS.RBTakeNoodleTask.Enqueue(new OrderLocInfo() { Loc = item, SuborderId = subId });
  141. MessageLog.GetInstance.Show($"添加订单:面条位置【{item}】");
  142. }
  143. if (item >= 10 && item <= 11)
  144. {
  145. mORKS.TakeBowlTask.Enqueue(new OrderLocInfo() { Loc = item, SuborderId = subId });
  146. MessageLog.GetInstance.Show($"添加订单:碗位置【{item}】");
  147. }
  148. }
  149. }
  150. }
  151. }
  152. /// <summary>
  153. /// IOT 广播消息命令
  154. /// </summary>
  155. public void IotBroadcast<T>(T broadcast)
  156. {
  157. if (broadcast != null && broadcast is IOTCommandModel iOTCommand)
  158. {
  159. MessageLog.GetInstance.Show($"IOT 广播消息命令 {iOTCommand.deviceName} 设备命令 {iOTCommand.CommandName} 控制变量{iOTCommand.CommandValue.Keys.First()}{iOTCommand.CommandValue[iOTCommand.CommandValue.Keys.First()]}");
  160. switch (iOTCommand.CommandName)
  161. {
  162. case 0://控制类
  163. if (iOTCommand.CommandValue != null)
  164. {
  165. if (iOTCommand.CommandValue.ContainsKey("SimOrder"))
  166. {
  167. SimOrder(new SimOrderData { NoodleLoc = 1, BowlLoc = 10 });
  168. }
  169. }
  170. break;
  171. case 1://设置属性
  172. break;
  173. case 2://通知消息
  174. break;
  175. default:
  176. break;
  177. }
  178. }
  179. }
  180. /// <summary>
  181. /// 数据解析
  182. /// </summary>
  183. public void DataParse<T>(T order)
  184. {
  185. if (order is MorkOrderPush morkOrderPush)
  186. {
  187. BatchingInfo batching_M = null;//面条
  188. BatchingInfo batching_W = null;//碗
  189. foreach (var item in morkOrderPush.GoodBatchings)
  190. {
  191. var res = Json<BatchingInfoPar>.Data.orderMaterialDelivery.BatchingInfo.FirstOrDefault(p => p.BatchingId == item.BatchingId);
  192. if (res != null)
  193. {
  194. if (ushort.TryParse(res.BatchingLoc, out ushort loc))
  195. {
  196. if (loc >= 1 && loc <= 5) { batching_M = res; }
  197. else if (loc >= 10 && loc <= 11) { batching_W = res; }
  198. }
  199. }
  200. }
  201. if (batching_M != null && batching_W != null)
  202. {
  203. batching_W.BatchingLoc = "10";
  204. mORKS.RBTakeNoodleTask.Enqueue(new OrderLocInfo() { Loc = ushort.Parse(batching_M.BatchingLoc), SuborderId = morkOrderPush.SuborderId, BatchingId = batching_M.BatchingId });
  205. int index = Array.FindIndex(Json<BatchingInfoPar>.Data.recipeBoms.RecipeIds.ToArray(), p => p.RecipeId == morkOrderPush.RecipeId);
  206. index++;
  207. mORKS.TakeBowlTask.Enqueue(new OrderLocInfo() { Loc = ushort.Parse(batching_W.BatchingLoc), SuborderId = morkOrderPush.SuborderId, RecipeNumber = (index >= 1 && index <= 10) ? (ushort)index : (ushort)0 });
  208. }
  209. }
  210. }
  211. #region 临时变量
  212. /// <summary>
  213. /// 取碗订单ID
  214. /// </summary>
  215. string TakeBowlId = string.Empty;
  216. /// <summary>
  217. /// 配料完成订单ID
  218. /// </summary>
  219. string IngredientsCompleteId = string.Empty;
  220. /// <summary>
  221. /// 煮面口对应的订单ID
  222. /// </summary>
  223. string[] CookNodelId = new string[6] { string.Empty, string.Empty, string.Empty, string.Empty, string.Empty, string.Empty, };
  224. /// <summary>
  225. /// 出餐订单ID
  226. /// </summary>
  227. string OutMealId = string.Empty;
  228. /// <summary>
  229. /// 转台位置轮询
  230. /// </summary>
  231. List<ushort> TurntableLoc = new List<ushort>();
  232. #endregion
  233. public void Main()
  234. {
  235. ThreadOperate.GetInstance.StartLong(new Action(() =>
  236. {
  237. //mORKS.AllowRun = mORKS.InitComplete && !mORKS.TemperatureReached;
  238. mORKS.AllowRun = mORKS.InitComplete && mORKS.TemperatureReached;
  239. GeneralConfig.Healthy = true;
  240. //GeneralConfig.Healthy = mORKS.AllowRun;
  241. TakeBowlTask();
  242. TakeNoodleTask();
  243. OutNoodleTask();
  244. SingleDetect();
  245. TurntableControl();
  246. Thread.Sleep(100);
  247. }), "MainTask");
  248. }
  249. /// <summary>
  250. /// 取碗控制
  251. /// </summary>
  252. private void TakeBowlTask()
  253. {
  254. if (mORKS.AllowRun && mORKS.TakeBowlTask.Count > 0 && !mORKS.TakeBowlIdle && !mORKS.TakeBowlInterlock)
  255. {
  256. if (mORKS.TakeBowlTask.TryDequeue(out OrderLocInfo orderLocInfo))
  257. {
  258. TakeBowlId = orderLocInfo.SuborderId;
  259. TakeBowlControl(orderLocInfo.Loc);
  260. SetRecipeNumber(orderLocInfo.RecipeNumber);
  261. SimpleFactory.GetInstance.OrderChanged(TakeBowlId, ORDER_STATUS.COOKING);
  262. MessageLog.GetInstance.Show($"订单【{TakeBowlId}】执行取碗控制,位置:[{orderLocInfo.Loc}]");
  263. }
  264. mORKS.TakeBowlInterlock = true;
  265. }
  266. }
  267. /// <summary>
  268. /// 转台控制
  269. /// </summary>
  270. private void TurntableControl()
  271. {
  272. if (mORKS.TurntableMoveInPlace && mORKS.InitComplete && !mORKS.AllowTakeNoodle && mORKS.RBTakeNoodleTask.Count > 0)
  273. {
  274. if (mORKS.TurntableLowerLimit)
  275. {
  276. SetTurntableLoc(mORKS.RBTakeNoodleTask.ElementAt(0).Loc);
  277. MoveTurntable();
  278. mORKS.AllowTakeNoodle = true;
  279. TurntableLoc.Clear();
  280. MessageLog.GetInstance.Show("转台位置OK");
  281. mORKS.IsNoodles = true;
  282. }
  283. else
  284. {
  285. if (!mORKS.TurntableInterlock)
  286. {
  287. var result = Json<BatchingInfoPar>.Data.orderMaterialDelivery.BatchingInfo.Where(p => p.BatchingId == mORKS.RBTakeNoodleTask.ElementAt(0).BatchingId).ToList();
  288. if (result != null)
  289. {
  290. foreach (var item in result)
  291. {
  292. if (ushort.TryParse(item.BatchingLoc, out ushort loc))
  293. {
  294. if (TurntableLoc.Contains(loc))
  295. {
  296. SetTurntableLoc(loc);
  297. MoveTurntable();
  298. mORKS.TurntableInterlock = true;
  299. TurntableLoc.Add(loc);
  300. return;
  301. }
  302. }
  303. }
  304. mORKS.IsNoodles = false;
  305. MessageLog.GetInstance.Show("转台位置缺少物料");
  306. }
  307. }
  308. }
  309. }
  310. #region 转台优化版
  311. //if (mORKS.InitComplete && !mORKS.TurntableInterlock && !mORKS.AllowTakeNoodle && mORKS.RBTakeNoodleTask.Count > 0)
  312. //{
  313. // var result = Json<BatchingInfoPar>.Data.orderMaterialDelivery.BatchingInfo.Where(p => p.BatchingId == mORKS.RBTakeNoodleTask.ElementAt(0).BatchingId).ToList();
  314. // if (result != null)
  315. // {
  316. // foreach (var item in result)
  317. // {
  318. // if (ushort.TryParse(item.BatchingLoc, out ushort loc))
  319. // {
  320. // if (!TurntableLoc.Contains(loc))
  321. // {
  322. // mORKS.TurntableInterlock=true;
  323. // TurntableLoc.Add(loc);
  324. // SetTurntableLoc(loc);
  325. // MoveTurntable();
  326. // return;
  327. // }
  328. // }
  329. // }
  330. // }
  331. //}
  332. ////转台到位检测
  333. //if (RTrig.GetInstance("TurntableInPlace").Start(mORKS.TurntableMoveInPlace))
  334. //{
  335. // if (mORKS.TurntableInterlock)
  336. // {
  337. // if (mORKS.TurntableLowerLimit)
  338. // {
  339. // TurntableLoc.Clear();
  340. // mORKS.AllowTakeNoodle = true;
  341. // }
  342. // else
  343. // {
  344. // mORKS.TurntableInterlock = false;
  345. // mORKS.AllowTakeNoodle = false;
  346. // }
  347. // }
  348. //}
  349. #endregion
  350. }
  351. /// <summary>
  352. /// 取面任务
  353. /// </summary>
  354. private void TakeNoodleTask()
  355. {
  356. //取面控制
  357. if (mORKS.AllowRun && mORKS.RobotIdle && !mORKS.RobotTaskInterlock && mORKS.AllowTakeNoodle && mORKS.TurntableMoveInPlace && !mORKS.TakeNoodleInterlock && !mORKS.OutNoodleing && mORKS.RBTakeNoodleTask.Count > 0)
  358. {
  359. int loc = Array.FindIndex(mORKS.NoodleCookerStatus, p => p == false);//查找煮面炉空闲位置
  360. if (loc >= 0 && loc <= 5)
  361. {
  362. if (mORKS.RBTakeNoodleTask.TryDequeue(out OrderLocInfo orderLocInfo))
  363. {
  364. //设置转台位置
  365. SetTurntableLoc(orderLocInfo.Loc);
  366. //设置倒面位置
  367. CookNodelId[loc] = orderLocInfo.SuborderId;
  368. SetFallNoodleLoc((ushort)(loc + 1));
  369. //机器人开始取面
  370. RobotTakeNoodle();
  371. SimpleFactory.GetInstance.OrderChanged(orderLocInfo.SuborderId, ORDER_STATUS.COOKING);
  372. MessageLog.GetInstance.Show($"订单【{orderLocInfo.SuborderId}】,转台:[{orderLocInfo}],煮面栏:[{loc + 1}]");
  373. mORKS.TakeNoodleInterlock = true;
  374. }
  375. }
  376. }
  377. }
  378. /// <summary>
  379. /// 出餐控制
  380. /// </summary>
  381. private void OutNoodleTask()
  382. {
  383. if (mORKS.AllowFallNoodle && mORKS.RobotTaskInterlock && !mORKS.TakeNoodleInterlock && mORKS.RobotIdle && !mORKS.TakeMealDetect)
  384. {
  385. int loc = Array.FindIndex(CookNodelId, p => p == IngredientsCompleteId && p.Length > 0);
  386. if (loc >= 0 && loc <= 5)
  387. {
  388. if (mORKS.CookNoodlesComplete[loc])
  389. {
  390. SetTakeNoodleLoc((ushort)(loc + 1));
  391. RobotOutMeal();
  392. CookNoodleStatusReset((ushort)(loc + 1));
  393. ResetAllowFallNoodle();
  394. OutMealId = IngredientsCompleteId;
  395. IngredientsCompleteId = string.Empty;
  396. CookNodelId[loc] = string.Empty;
  397. MessageLog.GetInstance.Show($"{loc + 1}号位置出餐控制");
  398. mORKS.OutNoodleing = true;
  399. }
  400. }
  401. }
  402. }
  403. /// <summary>
  404. /// 信号检测
  405. /// </summary>
  406. private void SingleDetect()
  407. {
  408. //允许倒面信号检测
  409. if (RTrig.GetInstance("AllowFallNoodle").Start(mORKS.AllowFallNoodle))
  410. {
  411. IngredientsCompleteId = TakeBowlId;
  412. TakeBowlId = string.Empty;
  413. MessageLog.GetInstance.Show($"允许到面,{IngredientsCompleteId}");
  414. mORKS.TakeBowlInterlock = false;
  415. }
  416. //出餐完成信号检测
  417. if (RTrig.GetInstance("CompleteChange").Start(mORKS.RbOutMealComplete))
  418. {
  419. SimpleFactory.GetInstance.OrderChanged(OutMealId, ORDER_STATUS.COMPLETED_COOK);
  420. MessageLog.GetInstance.Show($"订单【{OutMealId}】制作完成");
  421. mORKS.OutNoodleing = false;
  422. }
  423. //取餐完成逻辑处理
  424. if (DelayRTrig.GetInstance("CompleteChange1").Start(mORKS.RbOutMealComplete && !mORKS.TakeMealDetect, 2))
  425. {
  426. SimpleFactory.GetInstance.OrderChanged(OutMealId, ORDER_STATUS.COMPLETED_TAKE);
  427. MessageLog.GetInstance.Show($"订单【{OutMealId}】取餐完成");
  428. var RemoveItem = Json<MorkOrderPushPar>.Data.morkOrderPushes.FirstOrDefault(p => p.OrderPush.SuborderId == OutMealId);
  429. if (RemoveItem != null)
  430. {
  431. Json<MorkOrderPushPar>.Data.morkOrderPushes.Remove(RemoveItem);
  432. }
  433. ResetCookComplete();
  434. OutMealId = string.Empty;
  435. }
  436. //机器人取面完成信号检测
  437. if (RTrig.GetInstance("TakeNoodleComplete").Start(mORKS.RbTakeNoodleComplete))
  438. {
  439. mORKS.TakeNoodleInterlock = false;
  440. mORKS.AllowTakeNoodle = false;
  441. MessageLog.GetInstance.Show("取面完成");
  442. TakeNoodleCompleteReset();
  443. }
  444. //转台到位检测,启用优化版后屏蔽掉
  445. if (RTrig.GetInstance("TurntableInPlace").Start(mORKS.TurntableMoveInPlace))
  446. {
  447. mORKS.TurntableInterlock = false;
  448. }
  449. int OutMealRequstCount = mORKS.CookNoodlesComplete.Where(p => p == true).ToList().Count;
  450. int mlCount = mORKS.NoodleCookerStatus.Where(p => p == true).ToList().Count;
  451. mORKS.RobotTaskInterlock = OutMealRequstCount > 0 && mORKS.AllowFallNoodle && (mlCount >= 2 || mORKS.RBTakeNoodleTask.Count == 0);
  452. }
  453. #region PLC 控制函数
  454. /// <summary>
  455. /// 写入配方数据到 PLC
  456. /// </summary>
  457. private void WriteRecipeBoms()
  458. {
  459. List<ushort> recipeBoms = new List<ushort>();
  460. foreach (var item in Json<BatchingInfoPar>.Data.recipeBoms.RecipeIds)
  461. {
  462. foreach (var rec in item.Recipes)
  463. {
  464. recipeBoms.Add((ushort)rec);
  465. }
  466. }
  467. if (recipeBoms.Count > 0)
  468. {
  469. if (ModbusTcpHelper.GetInstance.Write(1100, WriteType.HoldingRegisters, recipeBoms.ToArray()))
  470. {
  471. MessageLog.GetInstance.Show("成功写入配方数据");
  472. }
  473. }
  474. }
  475. /// <summary>
  476. /// 转台移动
  477. /// </summary>
  478. private void MoveTurntable()
  479. {
  480. ModbusTcpHelper.GetInstance.Write(325, WriteType.Coils, true);
  481. }
  482. /// <summary>
  483. /// 取面完成复位
  484. /// </summary>
  485. private void TakeNoodleCompleteReset()
  486. {
  487. ModbusTcpHelper.GetInstance.Write(1124, WriteType.Coils, false);
  488. }
  489. /// <summary>
  490. /// 指定煮面口状态复位
  491. /// </summary>
  492. /// <param name="num"></param>
  493. private void CookNoodleStatusReset(int num)
  494. {
  495. if (num >= 1 && num <= 6)
  496. {
  497. ushort addRess = (ushort)(1136 + num - 1);
  498. ModbusTcpHelper.GetInstance.Write(addRess, WriteType.Coils, false);
  499. MessageLog.GetInstance.Show($"{num}号煮面口占用复位");
  500. }
  501. }
  502. /// <summary>
  503. /// 写配方编号
  504. /// </summary>
  505. /// <param name="num"></param>
  506. private void SetRecipeNumber(ushort num)
  507. {
  508. ModbusTcpHelper.GetInstance.Write(100, WriteType.HoldingRegisters, num);
  509. }
  510. /// <summary>
  511. /// 设置转台位置
  512. /// </summary>
  513. /// <param name="loc"></param>
  514. private void SetTurntableLoc(ushort loc)
  515. {
  516. ModbusTcpHelper.GetInstance.Write(101, WriteType.HoldingRegisters, loc);
  517. }
  518. /// <summary>
  519. /// 设置倒面位置
  520. /// </summary>
  521. /// <param name="loc"></param>
  522. private void SetFallNoodleLoc(ushort loc)
  523. {
  524. ModbusTcpHelper.GetInstance.Write(102, WriteType.HoldingRegisters, loc);
  525. }
  526. /// <summary>
  527. /// 设置取面位置
  528. /// </summary>
  529. /// <param name="loc"></param>
  530. private void SetTakeNoodleLoc(ushort loc)
  531. {
  532. ModbusTcpHelper.GetInstance.Write(103, WriteType.HoldingRegisters, loc);
  533. }
  534. /// <summary>
  535. /// 取碗控制
  536. /// </summary>
  537. /// <param name="loc"></param>
  538. private void TakeBowlControl(ushort loc)
  539. {
  540. if (loc == 10)
  541. {
  542. ModbusTcpHelper.GetInstance.Write(321, WriteType.Coils, true);
  543. }
  544. else if (loc == 11)
  545. {
  546. ModbusTcpHelper.GetInstance.Write(322, WriteType.Coils, true);
  547. }
  548. }
  549. /// <summary>
  550. /// 机器人取面
  551. /// </summary>
  552. private void RobotTakeNoodle()
  553. {
  554. ModbusTcpHelper.GetInstance.Write(323, WriteType.Coils, true);
  555. }
  556. /// <summary>
  557. /// 机器人取餐
  558. /// </summary>
  559. private void RobotOutMeal()
  560. {
  561. ModbusTcpHelper.GetInstance.Write(324, WriteType.Coils, true);
  562. var result = ModbusTcpHelper.GetInstance.Read(324, ReadType.Coils);
  563. if (result is bool res)
  564. while (!res)
  565. {
  566. ModbusTcpHelper.GetInstance.Write(324, WriteType.Coils, true);
  567. }
  568. }
  569. /// <summary>
  570. /// 制作完成信号复位
  571. /// </summary>
  572. private void ResetCookComplete()
  573. {
  574. ModbusTcpHelper.GetInstance.Write(1126, WriteType.Coils, false);
  575. }
  576. /// <summary>
  577. /// 复位允许取面信号
  578. /// </summary>
  579. private void ResetAllowFallNoodle()
  580. {
  581. ModbusTcpHelper.GetInstance.Write(1123, WriteType.Coils, false);
  582. }
  583. /// <summary>
  584. /// 设备初始化
  585. /// </summary>
  586. public async void DeviceInit()
  587. {
  588. ModbusTcpHelper.GetInstance.Write(320, WriteType.Coils, true);
  589. await Task.Delay(1000);
  590. ModbusTcpHelper.GetInstance.Write(320, WriteType.Coils, false);
  591. }
  592. #endregion
  593. }
  594. }