PLCLinker.cs 60 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425
  1. using System;
  2. using System.Collections;
  3. using System.Collections.Generic;
  4. using System.Linq;
  5. using System.Text;
  6. using System.Threading.Tasks;
  7. using System.Threading;
  8. using System.Timers;
  9. using HslCommunication.ModBus;
  10. using HslCommunication;
  11. using HslCommunication.BasicFramework;
  12. using System.Configuration;
  13. namespace PLCLinker
  14. {
  15. /// <summary>
  16. /// PLC通信类
  17. /// </summary>
  18. public class PLCLinker : IEquipments
  19. {
  20. public IEquipments ins { get; set; }
  21. /// <summary>
  22. /// PLC 连接状态flag
  23. /// </summary>
  24. private Boolean isConnection = false;
  25. /// <summary>
  26. /// 激光数据记录状态flag
  27. /// </summary>
  28. private bool isRecorded = false;
  29. /// <summary>
  30. /// 读写异常状态flag
  31. /// </summary>
  32. private bool exceptionBreak = false;
  33. /// <summary>
  34. /// 系统关闭flag
  35. /// </summary>
  36. private bool isClosing = false;
  37. /// <summary>
  38. /// 从PLC读到的字符串
  39. /// </summary>
  40. private static string json = "";
  41. /// <summary>
  42. /// 将写入PLC的字符串
  43. /// </summary>
  44. private string json2 = "";
  45. /// <summary>
  46. /// 从plc获得结构化数据
  47. /// </summary>
  48. private PLCMessage plcMsg;
  49. /// <summary>
  50. /// 定时器
  51. /// </summary>
  52. System.Timers.Timer timer;
  53. /// <summary>
  54. /// 读PLC初始地址
  55. /// </summary>
  56. private int startAddr = 0;
  57. /// <summary>
  58. /// 读PLC地址长度
  59. /// </summary>
  60. private int addrLength = 110;
  61. /// <summary>
  62. /// plc重连标记位
  63. /// </summary>
  64. private int linkCount = 0;
  65. /// <summary>
  66. /// 无法获取配置文件时使用的PLC刷新频率
  67. /// </summary>
  68. private const short PLC_TIME_SCALE = 200;
  69. /// <summary>
  70. /// PLC的IP地址
  71. /// </summary>
  72. private string ipString;
  73. /// <summary>
  74. /// PLC的端口号
  75. /// </summary>
  76. private int port;
  77. /// <summary>
  78. /// 工作站号
  79. /// </summary>
  80. private byte station;
  81. /// <summary>
  82. /// 取车启动机械手PLC地址
  83. /// </summary>
  84. private int fetching_startRobot_address;
  85. /// <summary>
  86. /// 停车启动机械手PLC地址
  87. /// </summary>
  88. private int parking_startRobot_address;
  89. /// <summary>
  90. /// 停车位ID对应PLC地址
  91. /// </summary>
  92. private int parkingSpaceID_address;
  93. /// <summary>
  94. /// 停车激光数据入口
  95. /// </summary>
  96. private int parkingLaserCenterX_address;
  97. /// <summary>
  98. /// 启动激光地址
  99. /// </summary>
  100. private int laser_start_address;
  101. /// <summary>
  102. /// 取车完成地址
  103. /// </summary>
  104. private int fetch_completed_address;
  105. /// <summary>
  106. /// 取车完成已获得标志地址
  107. /// </summary>
  108. private int fetch_completed_acknowledge_address;
  109. /// <summary>
  110. /// 取至缓冲区地址
  111. /// </summary>
  112. private int fetch_to_address;
  113. /// <summary>
  114. /// 前轮距转存地址
  115. /// </summary>
  116. private int frontWheelbase_address;
  117. /// <summary>
  118. /// 后轮距转存地址
  119. /// </summary>
  120. private int rearWheelbase_address;
  121. /// <summary>
  122. /// 停车完成地址
  123. /// </summary>
  124. private int park_completed_address;
  125. /// <summary>
  126. /// 停车完成已获得地址
  127. /// </summary>
  128. private int park_completed_acknowledge_address;
  129. /// <summary>
  130. /// 激光重测总数
  131. /// </summary>
  132. private int LASER_RESCAN_COUNT;
  133. /// <summary>
  134. /// 激光心跳检测窗口阈值
  135. /// </summary>
  136. private int LASER_HEARTBEAT_PERIOD;
  137. /// <summary>
  138. /// PLC刷新频率,来自于配置文件
  139. /// </summary>
  140. private int PLC_refresh_interval;
  141. /// <summary>
  142. /// 激光管理list
  143. /// </summary>
  144. private List<LaserProcessUnit> laserMgmtList = new List<LaserProcessUnit>();
  145. /// <summary>
  146. /// 机械手处理单元实例
  147. /// </summary>
  148. private RobotProcessUnit rpu1;
  149. /// <summary>
  150. /// PLC列表中被压缩的地址块
  151. /// </summary>
  152. private List<string> decompressIndex;
  153. /// <summary>
  154. /// plc构造函数
  155. /// </summary>
  156. public PLCLinker()
  157. {
  158. try
  159. {
  160. LASER_RESCAN_COUNT = Int32.Parse(ConfigurationManager.AppSettings.Get("laser_rescan_count"));
  161. LASER_HEARTBEAT_PERIOD = Int32.Parse(ConfigurationManager.AppSettings.Get("laser_countdown"));
  162. PLC_refresh_interval = Int32.Parse(ConfigurationManager.AppSettings.Get("PLC_refresh_interval"));
  163. parking_startRobot_address = Int32.Parse(ConfigurationManager.AppSettings.Get("parking_startRobot_address"));
  164. parkingLaserCenterX_address = Int32.Parse(ConfigurationManager.AppSettings.Get("parkingLaserCenterX_address"));
  165. parkingSpaceID_address = Int32.Parse(ConfigurationManager.AppSettings.Get("parkingSpaceID_address"));
  166. park_completed_address = Int32.Parse(ConfigurationManager.AppSettings.Get("park_completed_address"));
  167. park_completed_acknowledge_address = Int32.Parse(ConfigurationManager.AppSettings.Get("park_completed_acknowledge_address"));
  168. fetching_startRobot_address = Int32.Parse(ConfigurationManager.AppSettings.Get("fetching_startRobot_address"));
  169. fetch_to_address = Int32.Parse(ConfigurationManager.AppSettings.Get("fetch_to_address"));
  170. fetch_completed_address = Int32.Parse(ConfigurationManager.AppSettings.Get("fetch_completed_address"));
  171. fetch_completed_acknowledge_address = Int32.Parse(ConfigurationManager.AppSettings.Get("fetch_completed_acknowledge_address"));
  172. frontWheelbase_address = Int32.Parse(ConfigurationManager.AppSettings.Get("frontWheelbase_address"));
  173. rearWheelbase_address = Int32.Parse(ConfigurationManager.AppSettings.Get("rearWheelbase_address"));
  174. laser_start_address = Int32.Parse(ConfigurationManager.AppSettings.Get("laser_start_address"));
  175. plcMsg = new PLCMessage();
  176. rpu1 = new RobotProcessUnit(1, parking_startRobot_address, parkingLaserCenterX_address, parkingSpaceID_address, park_completed_address, park_completed_acknowledge_address, fetching_startRobot_address, fetch_to_address, fetch_completed_address, fetch_completed_acknowledge_address, frontWheelbase_address, rearWheelbase_address);
  177. //激光管理
  178. for (int i = 1; i < 20; i++)
  179. {
  180. try
  181. {
  182. if (ConfigurationManager.AppSettings.AllKeys.Contains("laser" + i + "_status_address"))
  183. {
  184. string laser = ConfigurationManager.AppSettings.Get("laser" + i + "_status_address");
  185. int laser_status_address = Int32.Parse(laser);
  186. LaserProcessUnit lpu = new LaserProcessUnit(this, i, laser_start_address, laser_status_address, LASER_RESCAN_COUNT, LASER_HEARTBEAT_PERIOD);
  187. laserMgmtList.Add(lpu);
  188. plcMsg.laserMsgList.Add(lpu.laserMsg);
  189. }
  190. else { break; }
  191. }
  192. catch (Exception) { }
  193. }
  194. //定义plc被压缩的地址段
  195. decompressIndex = new List<string>();
  196. //25-27
  197. for (int i = 0; i < 3; i++)
  198. {
  199. decompressIndex.Add((25 + i).ToString());
  200. }
  201. //48-53
  202. for (int i = 0; i < 6; i++)
  203. {
  204. decompressIndex.Add((48 + i).ToString());
  205. }
  206. //70-82
  207. for (int i = 0; i < 13; i++)
  208. {
  209. decompressIndex.Add((70 + i).ToString());
  210. }
  211. }
  212. catch (Exception)
  213. {
  214. Console.WriteLine("PLC相关配置文件异常");
  215. }
  216. }
  217. //**************************************** PLC读写相关方法 **************************************
  218. /// <summary>
  219. /// PLC连接对象
  220. /// </summary>
  221. private ModBusTcpClient busTcpClient
  222. {
  223. get;
  224. set;
  225. }
  226. /// <summary>
  227. /// 写入字符串到json2
  228. /// </summary>
  229. /// <param name="message">将写入的字符串</param>
  230. private void WriteMessage(string message)
  231. {
  232. isRecorded = true;
  233. //json2 = "[{\"Adress\":\"1\",\"Value\":\"0043\"},{\"Adress\":\"2\",\"Value\":\"0043\"}]";
  234. json2 = message;
  235. }
  236. /// <summary>
  237. /// 采集数据显示转json
  238. /// </summary>
  239. /// <param name="str">将被转为json字符串的字符串</param>
  240. private static void DisplayString_ToJson(string str)
  241. {
  242. List<PLCNode> return_Value = new List<PLCNode>();
  243. if (!string.IsNullOrEmpty(str))
  244. {
  245. ArrayList array = GetSeparateSubString(str, 4);
  246. int Read_Address = 0;//0地址
  247. return_Value.Clear();
  248. foreach (string arr in array)
  249. {
  250. PLCNode rv = new PLCNode();
  251. //Console.WriteLine("地址:" + Read_Address + ": " + arr);
  252. rv.Address = Read_Address.ToString();
  253. rv.Value = Int32.Parse(arr, System.Globalization.NumberStyles.HexNumber).ToString();//plc数据16进制?
  254. return_Value.Add(rv);
  255. Read_Address++;
  256. }
  257. }
  258. json = JsonHelper.SerializeObject(return_Value);//序列化
  259. //List<PLCValue> prv = JsonHelper.DeserializeJsonToList<PLCValue>(json);
  260. //Console.WriteLine(json);
  261. }
  262. /// <summary>
  263. /// 截取字符串到字符串数组
  264. /// </summary>
  265. /// <param name="txtString">输入字符串</param>
  266. /// <param name="charNumber">最大字符个数</param>
  267. /// <returns></returns>
  268. private static ArrayList GetSeparateSubString(string txtString, int charNumber)
  269. {
  270. ArrayList arrList = new ArrayList();
  271. string tempStr = txtString;
  272. for (int i = 0; i < tempStr.Length; i += charNumber)
  273. {
  274. if ((tempStr.Length - i) > charNumber)
  275. {
  276. arrList.Add(tempStr.Substring(i, charNumber));
  277. }
  278. else
  279. {
  280. arrList.Add(tempStr.Substring(i));
  281. }
  282. }
  283. return arrList;
  284. }
  285. /// <summary>
  286. /// 初始化定时器
  287. /// </summary>
  288. private void InitTimer()
  289. {
  290. try
  291. {
  292. timer = new System.Timers.Timer(PLC_refresh_interval);
  293. }
  294. catch (Exception)
  295. {
  296. timer = new System.Timers.Timer(PLC_TIME_SCALE);
  297. }
  298. timer.AutoReset = true;
  299. timer.Enabled = true;
  300. timer.Elapsed += new ElapsedEventHandler(TimerUp);
  301. }
  302. /// <summary>
  303. /// 实时采集
  304. /// </summary>
  305. /// <param name="sender">发送者对象,系统提供</param>
  306. /// <param name="e">定时数据</param>
  307. private void TimerUp(object sender, System.Timers.ElapsedEventArgs e)
  308. {
  309. try
  310. {
  311. if (isConnection)
  312. {
  313. //从哪个地址开始,读取长度
  314. PLC_Read((ushort)startAddr, (ushort)addrLength);
  315. //LaserMonitor();
  316. }
  317. else
  318. {
  319. //plc掉线则将系统暂停
  320. //EntityForCore.ins.globalStatus = false;
  321. if (linkCount-- >= 0)
  322. {
  323. Task.Factory.StartNew(() =>
  324. {
  325. MyTimer mt = new MyTimer();
  326. mt.StartTiming();
  327. while (!isClosing)
  328. {
  329. mt.EndTiming();
  330. int count;
  331. if (mt.IsLonger(1, 1, true, out count))
  332. {
  333. ////断线后只显示一次
  334. //UILogServer.ins.warn("尝试重连PLC");
  335. //Log.WriteLog(LogType.NOT_DATABASE, LogFile.LOG, "PLC重连中,请稍候。。。。。。");
  336. }
  337. LinkStart();
  338. Thread.Sleep(10000);
  339. if (isConnection)
  340. {
  341. //EntityForCore.ins.globalStatus = true;
  342. linkCount = 0;
  343. break;
  344. }
  345. }
  346. });
  347. linkCount = -1;
  348. }
  349. }
  350. }
  351. catch (Exception ex)
  352. {
  353. Console.WriteLine(ex.Message);
  354. }
  355. }
  356. /// <summary>
  357. /// 从PLC读取数据
  358. /// </summary>
  359. /// <param name="address">地址</param>
  360. /// <param name="length">值</param>
  361. private void PLC_Read(ushort address, ushort length)
  362. {
  363. try
  364. {
  365. OperateResult<byte[]> read = busTcpClient.ReadRegister(address, length);
  366. if (read.IsSuccess)
  367. {
  368. string returned_value = SoftBasic.ByteToHexString(read.Content);
  369. DisplayString_ToJson(returned_value);
  370. }
  371. else
  372. {
  373. if (!exceptionBreak)
  374. {
  375. //AsyncCmdServer.ins.send(AsyncCmdType.PLCReadException);
  376. isConnection = false;
  377. exceptionBreak = true;
  378. }
  379. }
  380. }
  381. catch (Exception ex)
  382. {
  383. Console.WriteLine(ex.Message);
  384. }
  385. }
  386. /// <summary>
  387. /// 写入Json字符串到PLC
  388. /// </summary>
  389. /// <param name="json">json格式字符串</param>
  390. private void WriteJson(string json)
  391. {
  392. try
  393. {
  394. if (!string.IsNullOrEmpty(json))
  395. {
  396. List<PLCNode> PLC_Value = JsonHelper.DeserializeJsonToList<PLCNode>(json);
  397. foreach (var item in PLC_Value)
  398. {
  399. //WriteResultRender(busTcpClient.WriteRegister(ushort.Parse(item.Address), ushort.Parse(item.Value)), item.Address);
  400. busTcpClient.WriteRegister(ushort.Parse(item.Address), ushort.Parse(item.Value));
  401. Thread.Sleep(20);
  402. }
  403. }
  404. }
  405. catch (Exception ex)
  406. {
  407. Console.WriteLine(ex.Message);
  408. }
  409. }
  410. /// <summary>
  411. /// 判断写入是否成功
  412. /// </summary>
  413. /// <param name="result">判断结果</param>
  414. private static void WriteResultRender(OperateResult result)
  415. {
  416. if (result.IsSuccess)
  417. {
  418. Console.WriteLine("写入成功");
  419. }
  420. else
  421. {
  422. Console.WriteLine("写入失败");
  423. }
  424. }
  425. /// <summary>
  426. /// 地址-值写入plc
  427. /// </summary>
  428. /// <param name="addr">地址</param>
  429. /// <param name="value">值</param>
  430. private void SendtoPLC(string addr, string value)
  431. {
  432. PLCNode wrv = new PLCNode();
  433. wrv.Address = addr;
  434. wrv.Value = value;
  435. json2 = "[" + JsonHelper.SerializeObject(wrv) + "]";
  436. WriteMessage(json2);
  437. if (isConnection && isRecorded)
  438. {
  439. WriteJson(json2);
  440. isRecorded = false;
  441. }
  442. }
  443. /// <summary>启动与plc的连接</summary>
  444. private void LinkStart()
  445. {
  446. if (busTcpClient != null)
  447. {
  448. busTcpClient.ConnectClose();
  449. }
  450. busTcpClient = new ModBusTcpClient(ipString, port, station);
  451. try
  452. {
  453. if (busTcpClient != null)
  454. {
  455. OperateResult connect = busTcpClient.ConnectServer();
  456. if (connect.IsSuccess)
  457. {
  458. //AsyncCmdServer.ins.send(AsyncCmdType.PLCOnline);
  459. //UILogServer.ins.info("PLC连接成功");
  460. isConnection = true;
  461. linkCount = 0;
  462. }
  463. else
  464. {
  465. //AsyncCmdServer.ins.send(AsyncCmdType.PLCOffline);
  466. //UILogServer.ins.error("PLC连接失败,重试");
  467. isConnection = false;
  468. }
  469. }
  470. }
  471. catch (Exception ex)
  472. {
  473. Console.WriteLine(ex.Message);
  474. }
  475. InitTimer();//启动计时器
  476. }
  477. /// <summary>
  478. /// 将plc地址块完全解压
  479. /// </summary>
  480. /// <param name="plcList">原始PLC数据列表</param>
  481. /// <param name="decompressIndex">压缩数据段</param>
  482. /// <returns>解压后的数据列表</returns>
  483. private List<PLCNode> ListDecompression(List<PLCNode> plcList, List<string> decompressIndex)
  484. {
  485. List<string> temp = new List<string>();
  486. List<PLCNode> decomPlcList = new List<PLCNode>();
  487. if (plcList != null && addrLength > 100)
  488. {
  489. try
  490. {
  491. for (int i = 0; i < plcList.Count; i++)
  492. {
  493. if (!decompressIndex.Contains(plcList[i].Address))
  494. {
  495. temp.Add(plcList[i].Value);
  496. }
  497. //定位三个被压缩区域
  498. else
  499. {
  500. //默认LSB优先
  501. int value = Int32.Parse(plcList[i].Value);
  502. int count = 16;
  503. while (count-- > 0)
  504. {
  505. temp.Add((value & 0x01).ToString());
  506. value = value >> 1;
  507. }
  508. }
  509. }
  510. }
  511. catch (Exception) { }
  512. }
  513. for (int i = 0; i < temp.Count; i++)
  514. {
  515. decomPlcList.Add(new PLCNode(i.ToString(), temp[i]));
  516. }
  517. return decomPlcList;
  518. }
  519. //************************************ 雷达相关方法 **************************************
  520. /// <summary>
  521. /// 根据PLC处获得的关于激光的数据,做出相应的操作
  522. /// </summary>
  523. private void LaserMonitor()
  524. {
  525. try
  526. {
  527. if (plcMsg.originalPlcList != null && plcMsg.originalPlcList.Count != 0)
  528. {
  529. foreach (LaserProcessUnit lds in laserMgmtList)
  530. {
  531. foreach (PLCNode p in plcMsg.originalPlcList)
  532. {
  533. int addr = Int32.Parse(p.Address);
  534. int value = Int32.Parse(p.Value);
  535. lds.LaserStatusChecking(addr, value);
  536. }
  537. lds.LaserRecord(plcMsg.originalPlcList);
  538. }
  539. }
  540. else
  541. {
  542. //AsyncCmdServer.ins.send(AsyncCmdType.PLCReadException);
  543. return;
  544. }
  545. Thread.Sleep(200);
  546. }
  547. catch (Exception)
  548. {
  549. //AsyncCmdServer.ins.send(AsyncCmdType.PLCReadException);
  550. return;
  551. }
  552. }
  553. /// <summary>
  554. /// 实时更新激光状态值
  555. /// </summary>
  556. private void UpdateLaserStatus()
  557. {
  558. try
  559. {
  560. lock (plcMsg)
  561. {
  562. if (plcMsg.originalPlcList != null && plcMsg.originalPlcList.Count != 0)
  563. {
  564. foreach (LaserProcessUnit lds in laserMgmtList)
  565. {
  566. foreach (PLCNode p in plcMsg.originalPlcList)
  567. {
  568. int addr = Int32.Parse(p.Address);
  569. int value = Int32.Parse(p.Value);
  570. lds.UpdateLaserStatus(addr, value);
  571. }
  572. }
  573. }
  574. else
  575. {
  576. //AsyncCmdServer.ins.send(AsyncCmdType.PLCReadException);
  577. return;
  578. }
  579. }
  580. }
  581. catch (Exception)
  582. {
  583. //AsyncCmdServer.ins.send(AsyncCmdType.PLCReadException);
  584. return;
  585. }
  586. }
  587. /// <summary>
  588. /// 等待激光空闲状态/心跳状态
  589. /// </summary>
  590. /// <param name="lpuTemp">激光处理单元</param>
  591. private void WaitForLaserReady(LaserProcessUnit lpuTemp)
  592. {
  593. bool jumpOut = false;
  594. MyTimer mt = new MyTimer();
  595. mt.StartTiming();
  596. lock (lpuTemp)
  597. {
  598. while (!jumpOut)
  599. {
  600. Thread.Sleep(1000);
  601. if (plcMsg != null && plcMsg.originalPlcList.Count > lpuTemp.laser_status_address)
  602. {
  603. foreach (PLCNode node in plcMsg.originalPlcList)
  604. {
  605. //判断激光空闲状态
  606. lock (lpuTemp.laserMsg)
  607. {
  608. if (node.Address.Equals(lpuTemp.laser_status_address.ToString()) && (node.Value.Equals("254") || node.Value.Equals("255")) && !lpuTemp.laserMsg.occupied)
  609. {
  610. lpuTemp.laserMsg.occupied = true;
  611. jumpOut = true;
  612. //UILogServer.ins.log("获取摆扫激光空闲状态,准备启动激光");
  613. //Log.WriteLog(LogType.NOT_DATABASE, LogFile.LOG, "获取摆扫激光空闲状态,准备启动激光");
  614. Console.WriteLine("获取摆扫激光空闲状态,准备启动激光");
  615. break;
  616. }
  617. }
  618. }
  619. }
  620. mt.EndTiming();
  621. int activationCount = 0;
  622. if (mt.IsLonger(15, 1, false, out activationCount))
  623. {
  624. if (activationCount == 1)
  625. {
  626. //UILogServer.ins.info("启动前暂未获取摆扫激光空闲状态,继续等待");
  627. Console.WriteLine("启动前暂未获取摆扫激光空闲状态,继续等待");
  628. }
  629. if (MyTimer.restart && !mt.rolledBack)
  630. {
  631. mt.rolledBack = true;
  632. //UILogServer.ins.error("启动前超时未能获取摆扫空闲状态,请检查设备");
  633. //Log.WriteLog(LogType.NOT_DATABASE, LogFile.ERROR, "启动前超时未能获取摆扫空闲状态,请检查设备");
  634. Console.WriteLine("启动前超时未能获取摆扫空闲状态,请检查设备");
  635. }
  636. Thread.Sleep(100);
  637. }
  638. }
  639. }
  640. }
  641. //***************公有方法****************
  642. /// <summary>
  643. /// 获取plc数据与激光数据
  644. /// </summary>
  645. /// <returns>返回plc消息实例</returns>
  646. public AbstractMessage GetMessage()
  647. {
  648. try
  649. {
  650. if (json != "")
  651. {
  652. plcMsg.originalPlcList = JsonHelper.DeserializeJsonToList<PLCNode>(json);
  653. }
  654. if (decompressIndex != null && decompressIndex.Count != 0)
  655. {
  656. plcMsg.extendedPlcList = ListDecompression(plcMsg.originalPlcList, decompressIndex);
  657. }
  658. return (PLCMessage)plcMsg.Clone();
  659. }
  660. catch (Exception)
  661. {
  662. //AsyncCmdServer.ins.send(AsyncCmdType.PLCReadException);
  663. return new PLCMessage();
  664. }
  665. }
  666. /// <summary>
  667. /// 传入信息写入plc
  668. /// </summary>
  669. /// <param name="message">plc消息则传入plc,控制消息则根据指令编号分别处理</param>
  670. public void SetMessage(AbstractMessage message)
  671. {
  672. if (message.GetType().Equals(typeof(PLCMessage)))
  673. {
  674. PLCMessage ps = (PLCMessage)message;
  675. for (int i = 0; i < ps.originalPlcList.Count; i++)
  676. {
  677. SendtoPLC(ps.originalPlcList[i].Address, ps.originalPlcList[i].Value);
  678. }
  679. }
  680. else if (message.GetType().Equals(typeof(PLCNode)))
  681. {
  682. PLCNode pv = (PLCNode)message;
  683. SendtoPLC(pv.Address, pv.Value);
  684. }
  685. else if (message.GetType().Equals(typeof(ControlMessage)))
  686. {
  687. ControlMessage cm = (ControlMessage)message;
  688. if (cm != null && cm.status != 0)
  689. {
  690. switch (cm.status)
  691. {
  692. //停车startLaser--park_command_address
  693. case 1:
  694. //start laser scanning for parking
  695. LaserProcessUnit lpuTemp = null;
  696. Task.Factory.StartNew(() =>
  697. {
  698. string laser_start_addr = "";
  699. foreach (LaserProcessUnit lpu in laserMgmtList)
  700. {
  701. if (cm.laserID == lpu.id)
  702. {
  703. lpuTemp = lpu;
  704. laser_start_addr = lpu.laser_start_address.ToString();
  705. break;
  706. }
  707. }
  708. if (laser_start_addr == "")
  709. return;
  710. lock (lpuTemp)
  711. {
  712. WaitForLaserReady(lpuTemp);
  713. SendtoPLC(laser_start_addr, "0");
  714. lpuTemp.laserMsg.licenseNum = cm.LicenseNum;
  715. Thread.Sleep(300);
  716. SendtoPLC(laser_start_addr, "1");
  717. Thread.Sleep(100);
  718. //SendtoPLC("1", "1");//停车指令置1
  719. //Log.WriteLog(LogType.NOT_DATABASE, "已发送激光" + lpuTemp.id + "启动指令");
  720. Console.WriteLine("已发送激光" + lpuTemp.id + "启动指令");
  721. //UILogServer.ins.info("已发送激光" + lpuTemp.id + "启动指令");
  722. }
  723. });
  724. //Console.WriteLine("扫摆激光启动");
  725. break;
  726. //停车激光的6个数据,停车机械手,车位信息4个
  727. case 2:
  728. if (cm.RobotID == 1)
  729. {
  730. //停车指令置1
  731. SendtoPLC("1", "1");
  732. //停车启动机械手
  733. SendtoPLC(rpu1.parking_startRobot_address.ToString(), "1");
  734. //自动或手动输入激光雷达数据
  735. SendtoPLC(rpu1.parking_laserCenterX_address.ToString(), cm.centerX);
  736. SendtoPLC((rpu1.parking_laserCenterX_address + 1).ToString(), cm.centerY);
  737. SendtoPLC((rpu1.parking_laserCenterX_address + 2).ToString(), cm.angleA);
  738. //车位信息
  739. SendtoPLC(rpu1.parkingSpaceID_address.ToString(), cm.parkingSpaceID);
  740. SendtoPLC((rpu1.parkingSpaceID_address + 1).ToString(), cm.parkingSpaceX);
  741. SendtoPLC((rpu1.parkingSpaceID_address + 2).ToString(), cm.parkingSpaceY);
  742. SendtoPLC((rpu1.parkingSpaceID_address + 3).ToString(), cm.parkingSpaceZ);
  743. }
  744. break;
  745. //停车完成归零--park_completed_address
  746. case 3:
  747. if (cm.RobotID == 1)
  748. {
  749. //SendtoPLC(rpu1.park_completed_address.ToString(), "0");//停车完成复位
  750. SendtoPLC(rpu1.park_completed_acknowledge_address.ToString(), "0");
  751. SendtoPLC("1", "0");//停车指令置0
  752. //Console.WriteLine("停车完成");
  753. }
  754. break;
  755. //取车机械手,车位信息4个
  756. case 4:
  757. if (cm.RobotID == 1 && cm.fetchPosition != 0)
  758. {
  759. //前后轮轮距
  760. SendtoPLC(rpu1.frontWheelbase.ToString(), cm.frontWheelbase.ToString());
  761. SendtoPLC(rpu1.rearWheelbase.ToString(), cm.rearWheelbase.ToString());
  762. //取至区域
  763. //SendtoPLC(rpu1.fetch_to_address.ToString(), pm.fetchPosition.ToString());
  764. SendtoPLC(rpu1.fetch_to_address.ToString(), cm.parkingSpaceX);
  765. //车位信息
  766. SendtoPLC(rpu1.parkingSpaceID_address.ToString(), cm.parkingSpaceID);
  767. SendtoPLC((rpu1.parkingSpaceID_address + 1).ToString(), cm.parkingSpaceX);
  768. SendtoPLC((rpu1.parkingSpaceID_address + 2).ToString(), cm.parkingSpaceY);
  769. SendtoPLC((rpu1.parkingSpaceID_address + 3).ToString(), cm.parkingSpaceZ);
  770. SendtoPLC(rpu1.fetching_startRobot_address.ToString(), "1");
  771. }
  772. break;
  773. case 5:
  774. if (cm.RobotID == 1)
  775. {
  776. //取车完成复位
  777. SendtoPLC(rpu1.fetch_completed_acknowledge_address.ToString(), "0");
  778. SendtoPLC(rpu1.fetch_to_address.ToString(), "0");
  779. }
  780. break;
  781. default:
  782. //Log.WriteLog(LogType.NOT_DATABASE, LogFile.ERROR, "输入PLC数据异常");
  783. break;
  784. }
  785. }
  786. }
  787. else
  788. {
  789. //AsyncCmdServer.ins.send(AsyncCmdType.PLCWriteException);
  790. }
  791. }
  792. /// <summary>
  793. /// 开启激光线程与模拟plc自动重置子线程
  794. /// </summary>
  795. public void Start()
  796. {
  797. ins = this as IEquipments;
  798. exceptionBreak = false; linkCount = 0;
  799. try
  800. {
  801. ipString = ConfigurationManager.AppSettings.Get("PLC_ip_address");
  802. port = Int32.Parse(ConfigurationManager.AppSettings.Get("PLC_port"));
  803. station = (byte)Int32.Parse(ConfigurationManager.AppSettings.Get("PLC_station"));
  804. startAddr = Int32.Parse(ConfigurationManager.AppSettings.Get("PLC_start_address"));
  805. addrLength = Int32.Parse(ConfigurationManager.AppSettings.Get("PLC_address_length"));
  806. }
  807. catch (Exception) {
  808. //UILogServer.ins.error("PLC配置文件异常"); Log.WriteLog(LogType.NOT_DATABASE, LogFile.ERROR, "PLC配置文件异常");
  809. Console.WriteLine("PLC配置文件异常");
  810. }
  811. for (int i = startAddr; i < startAddr + addrLength; i++)
  812. {
  813. plcMsg.originalPlcList.Add(new PLCNode(i.ToString(), "0"));
  814. }
  815. LinkStart();
  816. Task.Factory.StartNew(() =>
  817. {
  818. while (!isClosing)
  819. {
  820. LaserMonitor();
  821. }
  822. });
  823. Task.Factory.StartNew(() =>
  824. {
  825. while (!isClosing)
  826. {
  827. UpdateLaserStatus();
  828. }
  829. });
  830. //模拟plc与激光自动操作
  831. Task.Factory.StartNew(() =>
  832. {
  833. laserAnim();
  834. });
  835. Task.Factory.StartNew(() =>
  836. {
  837. wheelbaseAnim();
  838. });
  839. Task.Factory.StartNew(() =>
  840. {
  841. autoCycling();
  842. });
  843. }
  844. /// <summary>
  845. /// 系统停止
  846. /// </summary>
  847. public void Stop()
  848. {
  849. exceptionBreak = false; isClosing = true;
  850. busTcpClient.ConnectClose();//stop释放资源
  851. //throw new NotImplementedException();
  852. }
  853. /// <summary>
  854. /// 模拟摆扫激光
  855. /// </summary>
  856. private void laserAnim()
  857. {
  858. bool laserWorking = false;
  859. while (!isClosing)
  860. {
  861. if (plcMsg.originalPlcList != null)
  862. {
  863. //模拟plc与激光操作
  864. foreach (PLCNode p in plcMsg.originalPlcList)
  865. {
  866. int addr = Int32.Parse(p.Address);
  867. int value = Int32.Parse(p.Value);
  868. //模拟摆扫激光
  869. if (laserMgmtList.Count != 0)
  870. {
  871. if (addr == laser_start_address)
  872. {
  873. //心跳
  874. if (value == 0)
  875. {
  876. laserWorking = false;
  877. SendtoPLC(laserMgmtList[0].laser_status_address.ToString(), "254");
  878. Thread.Sleep(500);
  879. SendtoPLC(laserMgmtList[0].laser_status_address.ToString(), "255");
  880. Thread.Sleep(500);
  881. }
  882. //模拟测量
  883. else
  884. {
  885. if (!laserWorking)
  886. {
  887. SendtoPLC(laserMgmtList[0].laser_status_address.ToString(), "1");
  888. Thread.Sleep(300);
  889. SendtoPLC(laserMgmtList[0].laser_status_address.ToString(), "2");
  890. Thread.Sleep(500);
  891. SendtoPLC((laserMgmtList[0].laser_status_address + 1).ToString(), (new Random(DateTime.Now.Millisecond).Next(4000, 7000)).ToString());
  892. SendtoPLC((laserMgmtList[0].laser_status_address + 2).ToString(), (new Random(DateTime.Now.Millisecond).Next(4000, 7000)).ToString());
  893. SendtoPLC((laserMgmtList[0].laser_status_address + 3).ToString(), (new Random(DateTime.Now.Millisecond).Next(90, 150)).ToString());
  894. SendtoPLC(laserMgmtList[0].laser_status_address.ToString(), "3");
  895. Thread.Sleep(500);
  896. }
  897. laserWorking = true;
  898. }
  899. }
  900. }
  901. }
  902. }
  903. Thread.Sleep(100);
  904. }
  905. }
  906. /// <summary>
  907. /// 模拟轮距雷达
  908. /// </summary>
  909. private void wheelbaseAnim()
  910. {
  911. bool working = false;
  912. while (!isClosing)
  913. {
  914. if (plcMsg.originalPlcList != null)
  915. {
  916. //模拟plc与激光操作
  917. foreach (PLCNode p in plcMsg.originalPlcList)
  918. {
  919. int addr = Int32.Parse(p.Address);
  920. int value = Int32.Parse(p.Value);
  921. //模拟轮距激光
  922. if (addr == parking_startRobot_address)
  923. {
  924. if (value == 1)
  925. {
  926. if (!working)
  927. {
  928. working = true;
  929. Thread.Sleep(500);
  930. SendtoPLC(frontWheelbase_address.ToString(), (new Random(DateTime.Now.Millisecond).Next(100, 300)).ToString());
  931. Thread.Sleep(1);
  932. SendtoPLC(rearWheelbase_address.ToString(), (new Random(DateTime.Now.Millisecond).Next(100, 300)).ToString());
  933. SendtoPLC("87", "3");
  934. Thread.Sleep(500);
  935. }
  936. }
  937. else
  938. {
  939. working = false;
  940. SendtoPLC("87", "254");
  941. Thread.Sleep(500);
  942. SendtoPLC("87", "255");
  943. Thread.Sleep(500);
  944. }
  945. }
  946. }
  947. }
  948. Thread.Sleep(200);
  949. }
  950. }
  951. /// <summary>
  952. /// 模拟PLC操作
  953. /// </summary>
  954. private void autoCycling()
  955. {
  956. while (!isClosing)
  957. {
  958. if (plcMsg.originalPlcList != null)
  959. {
  960. //模拟plc与激光操作
  961. foreach (PLCNode p in plcMsg.originalPlcList)
  962. {
  963. int addr = Int32.Parse(p.Address);
  964. int value = Int32.Parse(p.Value);
  965. //停取车复位
  966. if (addr == park_completed_acknowledge_address && value == 0)
  967. {
  968. Thread.Sleep(1000);
  969. SendtoPLC(park_completed_address.ToString(), "0");
  970. SendtoPLC(park_completed_acknowledge_address.ToString(), "1");
  971. }
  972. if (addr == fetch_completed_acknowledge_address && value == 0)
  973. {
  974. Thread.Sleep(1000);
  975. SendtoPLC(fetch_completed_address.ToString(), "0");
  976. SendtoPLC(fetch_completed_acknowledge_address.ToString(), "1");
  977. }
  978. //停车完成
  979. if (addr == parking_startRobot_address && value == 1)
  980. {
  981. Thread.Sleep(2000);
  982. SendtoPLC(park_completed_address.ToString(), "1");
  983. SendtoPLC(addr.ToString(), "0");
  984. }
  985. //取车完成
  986. if (addr == fetching_startRobot_address && value == 1)
  987. {
  988. Thread.Sleep(2000);
  989. SendtoPLC(fetch_completed_address.ToString(), "1");
  990. SendtoPLC(addr.ToString(), "0");
  991. }
  992. }
  993. }
  994. Thread.Sleep(200);
  995. }
  996. }
  997. }
  998. /// <summary>
  999. /// 激光数据记录与处理类
  1000. /// </summary>
  1001. class LaserProcessUnit
  1002. {
  1003. /// <summary>
  1004. /// 激光启动对应PLC地址
  1005. /// </summary>
  1006. public int laser_start_address { get; set; }
  1007. /// <summary>
  1008. /// 激光状态对应PLC地址
  1009. /// </summary>
  1010. public int laser_status_address { get; set; }
  1011. /// <summary>
  1012. /// 激光id
  1013. /// </summary>
  1014. public int id { get; set; }
  1015. private int LASER_RESCAN_COUNT, LASER_HEARTBEAT_PERIOD, laser_rescan_countdown, laser_heartbeat_countdown;
  1016. private bool laser_record, laser_heartbeat_test, enable_status_check = true, disordered = false;
  1017. private HashSet<int> laser_heartbeat = new HashSet<int>();
  1018. /// <summary>
  1019. /// plc类句柄
  1020. /// </summary>
  1021. private IEquipments plc = null;
  1022. /// <summary>
  1023. /// 激光消息,用于保存激光数据、状态等信息
  1024. /// </summary>
  1025. public LaserMessage laserMsg = new LaserMessage();
  1026. /// <summary>
  1027. /// 激光处理单元构造函数,初始化各属性值
  1028. /// </summary>
  1029. /// <param name="id">编号</param>
  1030. /// <param name="park_command_address">停车指令地址</param>
  1031. /// <param name="laser_status_address">激光状态地址</param>
  1032. /// <param name="laser_rescan_count">激光重测次数</param>
  1033. /// <param name="laser_heartbeat_period">激光心跳时间窗口</param>
  1034. public LaserProcessUnit(IEquipments plc, int id, int park_command_address, int laser_status_address, int laser_rescan_count, int laser_heartbeat_period)
  1035. {
  1036. try
  1037. {
  1038. laserMsg.id = id;
  1039. this.id = id;
  1040. laserMsg.status = 6;
  1041. this.laser_start_address = park_command_address;
  1042. this.laser_status_address = laser_status_address;
  1043. LASER_RESCAN_COUNT = laser_rescan_count;
  1044. LASER_HEARTBEAT_PERIOD = laser_heartbeat_period;
  1045. laser_rescan_countdown = LASER_RESCAN_COUNT;
  1046. laser_heartbeat_countdown = LASER_HEARTBEAT_PERIOD;
  1047. this.plc = plc;
  1048. }
  1049. catch (Exception)
  1050. {
  1051. //UILogServer.ins.error("激光设备配置文件错误");
  1052. //Log.WriteLog(LogType.NOT_DATABASE, LogFile.ERROR, "激光设备配置文件错误");
  1053. }
  1054. }
  1055. /// <summary>
  1056. /// 更新激光状态
  1057. /// </summary>
  1058. /// <param name="addr">地址</param>
  1059. /// <param name="value">值</param>
  1060. public void UpdateLaserStatus(int addr, int value)
  1061. {
  1062. int status_addr = laser_status_address;
  1063. if (addr == status_addr)
  1064. {
  1065. laserMsg.status = value;
  1066. //UILogServer.ins.log(value.ToString());
  1067. //系统异常状态复位
  1068. if (value != 5 && disordered)
  1069. {
  1070. disordered = false;
  1071. }
  1072. }
  1073. }
  1074. /// <summary>
  1075. /// 激光状态监测
  1076. /// </summary>
  1077. /// <param name="addr">地址</param>
  1078. /// <param name="value">值</param>
  1079. public void LaserStatusChecking(int addr, int value)
  1080. {
  1081. if (enable_status_check)
  1082. {
  1083. int status_addr = laser_status_address;
  1084. if (addr == status_addr)
  1085. {
  1086. //after status 0, start to check laser heartbeat
  1087. if (value == 0)
  1088. {
  1089. laserMsg.abort_rescan = false;//就绪状态设置允许重测
  1090. laser_heartbeat_test = true;
  1091. }
  1092. //after status 3 or 4, start to check laser heartbeat
  1093. if (value == 3 && !laserMsg.recorded && laserMsg.licenseNum != "")
  1094. {
  1095. if (plc == null)
  1096. {
  1097. Console.WriteLine("plc为null");
  1098. }
  1099. if (plc != null)
  1100. {
  1101. PLCNode pn = new PLCNode(laser_start_address.ToString(), "0");
  1102. plc.SetMessage(pn);
  1103. //停车指令置0
  1104. MyTimer mt = new MyTimer();
  1105. mt.StartTiming();
  1106. while (laserMsg.status != 254 && laserMsg.status != 255)
  1107. {
  1108. Thread.Sleep(1000);
  1109. mt.EndTiming();
  1110. int activationCount = 0;
  1111. if (mt.IsLonger(15, 1, false, out activationCount))
  1112. {
  1113. if (activationCount == 1)
  1114. {
  1115. //UILogServer.ins.info("记录数据前未获得心跳,继续等待");
  1116. Console.WriteLine("记录数据前未获得心跳,继续等待");
  1117. }
  1118. if (MyTimer.restart && !mt.rolledBack)
  1119. {
  1120. mt.rolledBack = true;
  1121. //UILogServer.ins.error("记录数据前超时未获得心跳,请检查设备");
  1122. //Log.WriteLog(LogType.NOT_DATABASE, LogFile.ERROR, "记录数据前超时未获得心跳");
  1123. Console.WriteLine("记录数据前超时未获得心跳,请检查设备");
  1124. return;
  1125. }
  1126. Thread.Sleep(100);
  1127. }
  1128. }
  1129. laser_record = true;
  1130. laser_rescan_countdown = LASER_RESCAN_COUNT;
  1131. laser_heartbeat_test = true;
  1132. }
  1133. }
  1134. else if (value == 4)
  1135. {
  1136. laser_record = false;
  1137. //启动重测指令
  1138. if (laser_rescan_countdown > 0)
  1139. {
  1140. enable_status_check = false;
  1141. Task t = Task.Factory.StartNew(() =>
  1142. {
  1143. Thread.Sleep(500);
  1144. if (plc == null)
  1145. {
  1146. //plc = EquipmentSimpleFactory.ins.FindEquipment(EquipmentName.PLC);
  1147. Console.WriteLine("plc为null");
  1148. }
  1149. if (plc != null)
  1150. {
  1151. laser_rescan_countdown--;
  1152. //停车指令置0
  1153. PLCNode pn = new PLCNode(laser_start_address.ToString(), "0");
  1154. plc.SetMessage(pn);
  1155. //未终止重测,车未开走,停车指令归零后置1
  1156. if (!laserMsg.abort_rescan)
  1157. {
  1158. //UILogServer.ins.error("激光" + laserMsg.id + "计算异常,重新测量");
  1159. //Log.WriteLog(LogType.NOT_DATABASE, LogFile.ERROR, "激光" + laserMsg.id + "计算异常,重新测量");
  1160. //重测检测心跳
  1161. Task rescan_wait_heartbeat = Task.Factory.StartNew(() =>
  1162. {
  1163. MyTimer mt = new MyTimer();
  1164. mt.StartTiming();
  1165. while (laserMsg.status != 254 && laserMsg.status != 255)
  1166. {
  1167. Thread.Sleep(1000);
  1168. mt.EndTiming();
  1169. int activationCount = 0;
  1170. if (mt.IsLonger(15, 1, false, out activationCount))
  1171. {
  1172. if (activationCount == 1)
  1173. {
  1174. //UILogServer.ins.info("重测前未获得心跳,继续等待");
  1175. Console.WriteLine("重测前未获得心跳,继续等待");
  1176. }
  1177. if (MyTimer.restart && !mt.rolledBack)
  1178. {
  1179. mt.rolledBack = true;
  1180. //UILogServer.ins.error("发起重测前超时未能获取摆扫激光心跳,请检查设备");
  1181. //Log.WriteLog(LogType.NOT_DATABASE, LogFile.ERROR, "发起重测前超时未能获取摆扫激光心跳");
  1182. Console.WriteLine("发起重测前超时未能获取摆扫激光心跳");
  1183. return;
  1184. }
  1185. Thread.Sleep(100);
  1186. }
  1187. }
  1188. });
  1189. //Log.WriteLog(LogType.NOT_DATABASE, LogFile.LOG, "获得心跳,准备发起重测");
  1190. Console.WriteLine("获得心跳,准备发起重测");
  1191. rescan_wait_heartbeat.Wait();
  1192. pn = new PLCNode(laser_start_address.ToString(), "1");
  1193. plc.SetMessage(pn);
  1194. }
  1195. }
  1196. Thread.Sleep(500);
  1197. enable_status_check = true;
  1198. });
  1199. }
  1200. else if (laser_rescan_countdown == 0)
  1201. {
  1202. //激光1异常
  1203. laser_rescan_countdown = -1;
  1204. laser_heartbeat_test = false;
  1205. //UILogServer.ins.error("激光" + laserMsg.id + "计算异常超过重测次数,请检查");
  1206. //Log.WriteLog(LogType.NOT_DATABASE, LogFile.ERROR, "激光" + laserMsg.id + "计算异常超过重测次数");
  1207. Console.WriteLine("激光" + laserMsg.id + "计算异常超过重测次数,请检查");
  1208. }
  1209. }
  1210. //status 5, system error
  1211. if (value == 5)
  1212. {
  1213. lock (laserMsg)
  1214. {
  1215. laser_heartbeat_test = false;
  1216. if (!disordered)
  1217. {
  1218. //UILogServer.ins.error("激光" + laserMsg.id + "系统异常,请检查");
  1219. //Log.WriteLog(LogType.NOT_DATABASE, LogFile.ERROR, "激光" + laserMsg.id + "系统异常");
  1220. Console.WriteLine("激光" + laserMsg.id + "系统异常,请检查");
  1221. }
  1222. disordered = true;
  1223. }
  1224. }
  1225. //find the heartbeat of laser
  1226. if (laser_heartbeat_test && laser_heartbeat_countdown-- > 0 && value != 3 && value != 4)
  1227. {
  1228. if (value == 254 || value == 255)
  1229. laser_heartbeat.Add(value);
  1230. if (laser_heartbeat.Contains(254) && laser_heartbeat.Contains(255))
  1231. {
  1232. lock (laserMsg)
  1233. {
  1234. laserMsg.disconnected = false;
  1235. }
  1236. laser_heartbeat_countdown = LASER_HEARTBEAT_PERIOD;
  1237. laser_heartbeat_test = false;
  1238. laser_heartbeat.Clear();
  1239. }
  1240. //fail to check laser heartbeat
  1241. if (laser_heartbeat_countdown <= 0)
  1242. {
  1243. laser_heartbeat_countdown = LASER_HEARTBEAT_PERIOD;
  1244. lock (laserMsg)
  1245. {
  1246. if (laserMsg.status >= 0 && !laserMsg.disconnected)
  1247. {
  1248. //UILogServer.ins.error("激光" + laserMsg.id + "心跳检测失败");
  1249. //Log.WriteLog(LogType.NOT_DATABASE, LogFile.ERROR, "激光" + laserMsg.id + "心跳检测失败");
  1250. Console.WriteLine("激光" + laserMsg.id + "心跳检测失败");
  1251. }
  1252. laserMsg.disconnected = true;
  1253. }
  1254. }
  1255. }
  1256. }
  1257. }
  1258. else { return; }
  1259. }
  1260. /// <summary>
  1261. /// 激光数据记录
  1262. /// </summary>
  1263. /// <param name="plist">plc数据列表</param>
  1264. public void LaserRecord(List<PLCNode> plist)
  1265. {
  1266. lock (laserMsg)
  1267. {
  1268. //激光未掉线,记录数据写入plc
  1269. if (laserMsg.status != -1)
  1270. {
  1271. if (laser_record)
  1272. {
  1273. laser_record = false;
  1274. foreach (PLCNode p in plist)
  1275. {
  1276. int addr = Int32.Parse(p.Address);
  1277. int value = Int32.Parse(p.Value);
  1278. if (addr == laser_status_address + 1)
  1279. laserMsg.data.centerX = value;
  1280. else if (addr == laser_status_address + 2)
  1281. laserMsg.data.centerY = value;
  1282. else if (addr == laser_status_address + 3)
  1283. laserMsg.data.angleA = value;
  1284. else if (addr == laser_status_address + 4)
  1285. laserMsg.data.length = value;
  1286. else if (addr == laser_status_address + 5)
  1287. laserMsg.data.width = value;
  1288. else if (addr == laser_status_address + 6)
  1289. laserMsg.data.height = value;
  1290. }
  1291. laserMsg.recorded = true;
  1292. //UILogServer.ins.info("摆扫激光测量数据已记录");
  1293. Console.WriteLine("摆扫激光测量数据已记录");
  1294. }
  1295. }
  1296. }
  1297. }
  1298. }
  1299. /// <summary>
  1300. /// 机械手逻辑处理类
  1301. /// </summary>
  1302. class RobotProcessUnit
  1303. {
  1304. /// <summary>
  1305. /// 机械手id
  1306. /// </summary>
  1307. public int id { get; set; }
  1308. /// <summary>
  1309. /// 停车启动机械手对应PLC地址
  1310. /// </summary>
  1311. public int parking_startRobot_address { get; set; }
  1312. /// <summary>
  1313. /// 停车激光数据写入入口
  1314. /// </summary>
  1315. public int parking_laserCenterX_address { get; set; }
  1316. /// <summary>
  1317. /// 停车位ID对应PLC地址
  1318. /// </summary>
  1319. public int parkingSpaceID_address { get; set; }
  1320. /// <summary>
  1321. /// 停车完成对应PLC地址
  1322. /// </summary>
  1323. public int park_completed_address { get; set; }
  1324. /// <summary>
  1325. /// 用于停车完成复位PLC地址
  1326. /// </summary>
  1327. public int park_completed_acknowledge_address { get; set; }
  1328. /// <summary>
  1329. /// 取车启动机械手PLC地址
  1330. /// </summary>
  1331. public int fetching_startRobot_address { get; set; }
  1332. /// <summary>
  1333. /// 取车完成PLC地址
  1334. /// </summary>
  1335. public int fetch_completed_address { get; set; }
  1336. /// <summary>
  1337. /// 用于取车完成复位PLC地址
  1338. /// </summary>
  1339. public int fetch_completed_acknowledge_address { get; set; }
  1340. /// <summary>
  1341. /// 取车放置位置PLC地址
  1342. /// </summary>
  1343. public int fetch_to_address { get; set; }
  1344. /// <summary>
  1345. /// 前轮轮距记录
  1346. /// </summary>
  1347. public int frontWheelbase { get; set; }
  1348. /// <summary>
  1349. /// 后轮轮距记录
  1350. /// </summary>
  1351. public int rearWheelbase { get; set; }
  1352. /// <summary>
  1353. /// 构造函数,初始化各属性值
  1354. /// </summary>
  1355. /// <param name="id">编号</param>
  1356. /// <param name="parking_startRobot_address">停车启动机械手地址</param>
  1357. /// <param name="parking_laserCenterX_address">停车激光中心X坐标</param>
  1358. /// <param name="parkingSpaceID_address">车位ID地址</param>
  1359. /// <param name="park_completed_address">停车完成地址</param>
  1360. /// <param name="park_completed_acknowledge_address">停车完成获取标志地址</param>
  1361. /// <param name="fetching_startRobot_address">取车启动机械手地址</param>
  1362. /// <param name="fetch_to_address">取至缓冲区地址</param>
  1363. /// <param name="fetch_completed_address">取车完成地址</param>
  1364. /// <param name="fetch_completed_acknowledge_address">取车完成获得标志地址</param>
  1365. /// <param name="frontWheelbase">前轮距转存</param>
  1366. /// <param name="rearWheelbase">后轮距转存</param>
  1367. public RobotProcessUnit(int id, int parking_startRobot_address, int parking_laserCenterX_address, int parkingSpaceID_address, int park_completed_address, int park_completed_acknowledge_address, int fetching_startRobot_address, int fetch_to_address, int fetch_completed_address, int fetch_completed_acknowledge_address, int frontWheelbase, int rearWheelbase)
  1368. {
  1369. this.id = id;
  1370. this.parking_startRobot_address = parking_startRobot_address;
  1371. this.parking_laserCenterX_address = parking_laserCenterX_address;
  1372. this.parkingSpaceID_address = parkingSpaceID_address;
  1373. this.park_completed_address = park_completed_address;
  1374. this.park_completed_acknowledge_address = park_completed_acknowledge_address;
  1375. this.fetching_startRobot_address = fetching_startRobot_address;
  1376. this.fetch_completed_address = fetch_completed_address;
  1377. this.fetch_completed_acknowledge_address = fetch_completed_acknowledge_address;
  1378. this.fetch_to_address = fetch_to_address;
  1379. this.frontWheelbase = frontWheelbase;
  1380. this.rearWheelbase = rearWheelbase;
  1381. }
  1382. }
  1383. }