Vehicle.cs 87 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525
  1. using System;
  2. using System.Collections;
  3. using System.Collections.Generic;
  4. using System.Linq;
  5. using System.Threading;
  6. using System.Threading.Tasks;
  7. using FluentResults;
  8. using GSG.NET.Concurrent;
  9. using GSG.NET.Extensions;
  10. using GSG.NET.LINQ;
  11. using GSG.NET.Logging;
  12. using GSG.NET.Quartz;
  13. using GSG.NET.Utils;
  14. using OHV.Common.Events;
  15. using OHV.Common.Model;
  16. using OHV.Common.Shareds;
  17. using OHV.SqliteDAL;
  18. using Prism.Events;
  19. using VehicleControlSystem.ControlLayer.Actuator.Cylinder;
  20. using VehicleControlSystem.ControlLayer.Drive;
  21. using VehicleControlSystem.ControlLayer.IO;
  22. using VehicleControlSystem.ControlLayer.MQ;
  23. using VehicleControlSystem.ControlLayer.Serial.BatteryTabos;
  24. using VehicleControlSystem.ControlLayer.Serial.DataModel;
  25. using VehicleControlSystem.Managers;
  26. using static VehicleControlSystem.ControlLayer.Drive.GSIDrive;
  27. namespace VehicleControlSystem.ControlLayer
  28. {
  29. public class VehicleRefObjects
  30. {
  31. public GSIDrive Drive { get; set; }
  32. public Clamp Clamp { get; set; }
  33. public Conveyor Conveyor { get; set; }
  34. public EzIO IO { get; set; }
  35. public Steering Steering { get; set; }
  36. public BMUManager BMUManager { get; set; }
  37. public ZmqManager ZmqManager { get; set; }
  38. public List<Alarm> Alarms { get; set; }
  39. public HostManager HostManager { get; set; }
  40. public SqliteManager Sqlite { get; set; }
  41. public AutoManager AutoManager { get; set; }
  42. }
  43. /// <summary>
  44. /// Control Layer 의 자원을 여기서 사용하자.
  45. /// </summary>
  46. public class Vehicle : ControlObjectBase, IDisposable
  47. {
  48. /// <summary>
  49. /// OCS Report Code
  50. /// 목적지에 도착해서 Load, Unload 시 발생하는 Alarm
  51. /// </summary>
  52. public enum eFailCode
  53. {
  54. Load_PortHasNotCarrier = 1,
  55. Load_VehicleHasCarrier,
  56. Unload_PortHasCarrier,
  57. Unload_VehicleHasNotCarrier,
  58. LoadPIOInterlockTimeout,
  59. UnlaodPIOInterlockTimeout,
  60. }
  61. static Logger logger = Logger.GetLogger();
  62. static Logger loggerPIO = Logger.GetLogger( "PIO" );
  63. #region Properties
  64. /// <summary>
  65. /// Tag 위치
  66. /// </summary>
  67. private int currentTag = 0;
  68. public int CurrentTag
  69. {
  70. get { return currentTag; }
  71. set
  72. {
  73. if ( SetField( ref this.currentTag, value ) )
  74. {
  75. var info = this.refObjects.Sqlite.VehicleInfoDAL.GetAll().FirstOrDefault();
  76. info.CurrentTag = value.ToString();
  77. this.refObjects.Sqlite.VehicleInfoDAL.Update( info );
  78. this.OnCurrentTagChanged?.Invoke( value );
  79. }
  80. }
  81. }
  82. /// <summary>
  83. /// Scale Value
  84. /// </summary>
  85. private double currentPosition;
  86. public double CurrentPosition
  87. {
  88. get { return currentPosition; }
  89. set
  90. {
  91. if ( SetField( ref this.currentPosition, value ) )
  92. {
  93. }
  94. }
  95. }
  96. private double currentSpeed;
  97. public double CurrentSpeed
  98. {
  99. get { return currentSpeed; }
  100. set { SetField( ref this.currentSpeed, value ); }
  101. }
  102. private double currentTorque;
  103. public double CurrentTorque
  104. {
  105. get { return currentTorque; }
  106. set { SetField( ref this.currentTorque, value ); }
  107. }
  108. private bool isContain;
  109. public bool IsContain
  110. {
  111. get { return isContain; }
  112. set { SetField( ref this.isContain, value ); }
  113. }
  114. eClampState _clampState;
  115. public eClampState ClampState
  116. {
  117. get { return this._clampState; }
  118. set { this.SetField( ref this._clampState, value ); }
  119. }
  120. private eSteeringState steeringState;
  121. public eSteeringState SteeringState
  122. {
  123. get { return steeringState; }
  124. set
  125. {
  126. if ( SetField( ref this.steeringState, value ) )
  127. {
  128. this.refObjects.ZmqManager.SetCurrentSteeringState( value );
  129. }
  130. }
  131. }
  132. private int _obstacleDrive;
  133. public int ObstacleDrive { get { return this._obstacleDrive; } set { SetField( ref this._obstacleDrive, value ); } }
  134. private int _obstacleCurve;
  135. public int ObstacleCurve { get { return this._obstacleCurve; } set { SetField( ref this._obstacleCurve, value ); } }
  136. private int obstacleCurrent;
  137. public int ObstacleCurrent { get { return this.ObstacleCurrent; } set { SetField( ref this.obstacleCurrent, value ); } }
  138. private eObstacleState obstacleState = eObstacleState.Normal;
  139. public eObstacleState ObstacleStateProperty
  140. {
  141. get { return obstacleState; }
  142. set
  143. {
  144. if ( SetField( ref this.obstacleState, value ) )
  145. {
  146. if ( value == eObstacleState.Blocked )
  147. this.VehicleStateProperty = eVehicleState.Blocked;
  148. }
  149. }
  150. }
  151. private eVehicleState vehicleState = eVehicleState.None;
  152. public eVehicleState VehicleStateProperty
  153. {
  154. get { return vehicleState; }
  155. set
  156. {
  157. if ( SetField( ref this.vehicleState, value ) )
  158. {
  159. var info = this.refObjects.Sqlite.VehicleInfoDAL.GetAll().FirstOrDefault();
  160. info.VehicleState = value;
  161. this.refObjects.Sqlite.VehicleInfoDAL.Update( info );
  162. }
  163. }
  164. }
  165. private eMachineMode machineMode = eMachineMode.LocalMode;
  166. public eMachineMode MachineMode
  167. {
  168. get { return machineMode; }
  169. set
  170. {
  171. if ( SetField( ref this.machineMode, value ) )
  172. {
  173. var info = this.refObjects.Sqlite.VehicleInfoDAL.GetAll().FirstOrDefault();
  174. info.MachineMode = value;
  175. this.refObjects.Sqlite.VehicleInfoDAL.Update( info );
  176. }
  177. }
  178. }
  179. private int obstaclePattern;
  180. public int ObstaclePattern
  181. {
  182. get { return obstaclePattern; }
  183. set { SetField( ref this.obstaclePattern, value ); }
  184. }
  185. private DriveState frontDriveState;
  186. public DriveState FrontDriveState
  187. {
  188. get { return frontDriveState; }
  189. set { SetField( ref this.frontDriveState, value ); }
  190. }
  191. private DriveState rearDriveState;
  192. public DriveState RearDriveState
  193. {
  194. get { return rearDriveState; }
  195. set { SetField( ref this.rearDriveState, value ); }
  196. }
  197. private eVehicleAutoReadyState autoReadyState;
  198. public eVehicleAutoReadyState AutoReadyState
  199. {
  200. get { return autoReadyState; }
  201. set { SetField(ref this.autoReadyState, value);}
  202. }
  203. //이동
  204. public bool Busy
  205. {
  206. get
  207. {
  208. return this.CurrentSubCommand == null ? false : true;
  209. }
  210. set { }
  211. }
  212. public bool IsMoving { get => this.refObjects.Drive.IsDriveMoving(); }
  213. private bool batteryChargeState;
  214. public bool BatteryChargeState
  215. {
  216. get { return batteryChargeState; }
  217. set
  218. {
  219. if ( SetField( ref batteryChargeState, value ) )
  220. {
  221. if ( value )
  222. {
  223. this.OnChargingStart?.Invoke();
  224. LockUtils.Wait( 200 );
  225. this.OnCharging?.Invoke();
  226. QuartzUtils.Invoke( "BatterLogger", QuartzUtils.GetExpnMinute( 1 ), () => { batteryLogger.I( $"SOC - {this.BatteryStateOfCharge} / Current - {this.BatteryCurrent} / Voltage - {this.BatteryVoltage} / Capacity - {this.BatteryCapacity} / Energy - {this.BatteryEnergy}" ); } );
  227. }
  228. else
  229. QuartzUtils.StopSchedule( "BatterLogger" );
  230. }
  231. }
  232. }
  233. #region Battery Property
  234. double batteryVoltage;
  235. public double BatteryVoltage
  236. {
  237. get { return this.batteryVoltage; }
  238. set
  239. {
  240. //var d = Math.Truncate( value * 10 ) / 10;
  241. //this.SetField( ref this.batteryVoltage, d );
  242. this.SetField( ref this.batteryVoltage, value );
  243. }
  244. }
  245. double batteryCurrent;
  246. public double BatteryCurrent
  247. {
  248. get { return this.batteryCurrent; }
  249. set { this.SetField( ref this.batteryCurrent, value ); }
  250. }
  251. double batteryState;
  252. public double BatteryState
  253. {
  254. get { return this.batteryState; }
  255. set { this.SetField( ref this.batteryState, value ); }
  256. }
  257. double batteryChargeTime;
  258. public double BatteryChargeTime
  259. {
  260. get { return this.batteryChargeTime; }
  261. set { this.SetField( ref this.batteryChargeTime, value ); }
  262. }
  263. double batteryDisChargeTime;
  264. public double BatteryDisChargeTime
  265. {
  266. get { return this.batteryDisChargeTime; }
  267. set { this.SetField( ref this.batteryDisChargeTime, value ); }
  268. }
  269. double batteryStateOfCharge;
  270. public double BatteryStateOfCharge
  271. {
  272. get { return this.batteryStateOfCharge; }
  273. set { if ( this.SetField( ref this.batteryStateOfCharge, value ) ) { this.BatteryChargeStateLED( value ); } }
  274. }
  275. double batteryStateOfHealth;
  276. public double BatteryStateOfHealth
  277. {
  278. get { return this.batteryStateOfHealth; }
  279. set
  280. {
  281. if ( this.SetField( ref this.batteryStateOfHealth, value ) ) { }
  282. }
  283. }
  284. double batteryCapacity;
  285. public double BatteryCapacity
  286. {
  287. get { return this.batteryCapacity; }
  288. set { this.SetField( ref this.batteryCapacity, value ); }
  289. }
  290. double batteryEnergy;
  291. public double BatteryEnergy
  292. {
  293. get { return this.batteryEnergy; }
  294. set
  295. {
  296. var d = Math.Truncate( value * 10 ) / 10;
  297. this.SetField( ref this.batteryEnergy, d );
  298. }
  299. }
  300. double batteryTemperature;
  301. public double BatteryTemperature
  302. {
  303. get { return this.batteryTemperature; }
  304. set { this.SetField( ref this.batteryTemperature, value ); }
  305. }
  306. bool batteryIsConnect;
  307. public bool BatteryIsConnect
  308. {
  309. get
  310. {
  311. return batteryIsConnect;
  312. }
  313. set { this.SetField( ref this.batteryIsConnect, value ); }
  314. }
  315. #endregion
  316. public bool IsError { get; set; }
  317. public SubCmd CurrentSubCommand { get; private set; }
  318. double frontLoadFactor = 0;
  319. public double FrontLoadFactor
  320. {
  321. get { return this.frontLoadFactor; }
  322. set { SetField( ref this.frontLoadFactor, value ); }
  323. }
  324. double frontRpm = 0;
  325. public double FrontRpm
  326. {
  327. get { return this.frontRpm; }
  328. set { SetField( ref this.frontRpm, value ); }
  329. }
  330. double frontSpeed = 0;
  331. public double FrontSpeed
  332. {
  333. get { return this.frontSpeed; }
  334. set { SetField( ref this.frontSpeed, value ); }
  335. }
  336. double frontTorque = 0;
  337. public double FrontTorque
  338. {
  339. get { return this.frontTorque; }
  340. set { SetField( ref this.frontTorque, value ); }
  341. }
  342. double rearLoadFactor = 0;
  343. public double RearLoadFactor
  344. {
  345. get { return this.rearLoadFactor; }
  346. set { SetField( ref this.rearLoadFactor, value ); }
  347. }
  348. double rearRpm = 0;
  349. public double RearRpm
  350. {
  351. get { return this.rearRpm; }
  352. set { SetField( ref this.rearRpm, value ); }
  353. }
  354. double rearSpeed = 0;
  355. public double RearSpeed
  356. {
  357. get { return this.rearSpeed; }
  358. set { SetField( ref this.rearSpeed, value ); }
  359. }
  360. double rearTorque = 0;
  361. public double RearTorque
  362. {
  363. get { return this.rearTorque; }
  364. set { SetField( ref this.rearTorque, value ); }
  365. }
  366. private double linearSpeed;
  367. public double LinearSpeed
  368. {
  369. get { return linearSpeed; }
  370. set { SetField(ref this.linearSpeed, value); }
  371. }
  372. private double curveSpeed;
  373. public double CurveSpeed
  374. {
  375. get { return curveSpeed; }
  376. set { SetField(ref this.curveSpeed, value); }
  377. }
  378. private double accelSpeed;
  379. public double AccelSpeed
  380. {
  381. get { return accelSpeed; }
  382. set { SetField(ref this.accelSpeed , value); }
  383. }
  384. private double decelSpeed;
  385. public double DecelSpeed
  386. {
  387. get { return decelSpeed; }
  388. set { SetField(ref this.decelSpeed, value); }
  389. }
  390. private double creepSpeed;
  391. public double CreepSpeed
  392. {
  393. get { return creepSpeed; }
  394. set { SetField(ref this.creepSpeed, value); }
  395. }
  396. private double creepDistance;
  397. public double CreepDistance
  398. {
  399. get { return creepDistance; }
  400. set { SetField(ref this.creepDistance , value); }
  401. }
  402. private double jogSpeed;
  403. public double JogSPeed
  404. {
  405. get { return jogSpeed; }
  406. set { SetField(ref this.jogSpeed , value); }
  407. }
  408. #endregion
  409. #region Event
  410. public event Action OnMoveReady;
  411. public event Action OnMoving;
  412. public event Action OnMoveFinish;
  413. public event Action OnChargingStart;
  414. public event Action OnCharging;
  415. public event Action OnChargingFull;
  416. public event Action<double> OnBatteryVelueChanged;
  417. public event Action<bool> OnPIOStart;
  418. public event Action<bool> OnConveyorStart;
  419. public event Action<bool> OnConveyorStop;
  420. public event Action<bool> OnCarrierDetected;
  421. public event Action OnLoadComplete;
  422. public event Action OnUnloadComplete;
  423. public event Action<int> OnCurrentTagChanged;
  424. public event Action OnManualMove;
  425. public event Action OnManualLoad;
  426. public event Action OnManualUnload;
  427. public event Action OnManualCharging;
  428. public event Action<eFailCode> OnFailReport;
  429. #endregion
  430. #region List.
  431. List<ICylinder> cylinders = new List<ICylinder>();
  432. List<string> obstacleBitList = new List<string>();
  433. #endregion
  434. VehicleRefObjects refObjects = null;
  435. //SqliteManager sql = null;
  436. //AutoManager autoManager = null;
  437. ThreadCancel cancel = new ThreadCancel();
  438. TaskCancel taskCancel = new TaskCancel();
  439. TaskCancel taskMoveCancel = new TaskCancel();
  440. IEventAggregator eventAggregator;
  441. public Vehicle( IEventAggregator ea )
  442. {
  443. this.obstacleBitList.AddRange( new string[]
  444. {
  445. "OUT_OBSTRUCTION_PATTERN_00",
  446. "OUT_OBSTRUCTION_PATTERN_01",
  447. "OUT_OBSTRUCTION_PATTERN_02",
  448. "OUT_OBSTRUCTION_PATTERN_03",
  449. "OUT_OBSTRUCTION_PATTERN_04",
  450. } );
  451. this.eventAggregator = ea;
  452. this.eventAggregator.GetEvent<DriveControlPubSubEvent>().Unsubscribe( ReceiveDriveControlEvent );
  453. this.eventAggregator.GetEvent<DriveControlPubSubEvent>().Subscribe( ReceiveDriveControlEvent );
  454. this.eventAggregator.GetEvent<ObstacleControlPubSubEvent>().Unsubscribe( ObstacleReceiveEvent );
  455. this.eventAggregator.GetEvent<ObstacleControlPubSubEvent>().Subscribe( ObstacleReceiveEvent );
  456. }
  457. public void DependencyInjection( VehicleRefObjects vehicleRefObjects )
  458. {
  459. this.refObjects = vehicleRefObjects;
  460. this.refObjects.IO.OnChangedIO += IO_OnChangedIO;
  461. this.refObjects.BMUManager.OnConnect += BMUManager_OnConnect;
  462. this.refObjects.BMUManager.OnDisconnect += BMUManager_OnDisconnect;
  463. this.refObjects.BMUManager.OnChangedReceivedData += BMUManager_OnChangedReceivedData;
  464. this.refObjects.BMUManager.OnFirstColtd += BMUManager_OnFirstColtd;
  465. this.refObjects.Drive.PropertyChanged += Motion_PropertyChanged;
  466. this.refObjects.Clamp.PropertyChanged += Clamp_PropertyChanged;
  467. this.refObjects.Steering.OnSteeringError += Steering_OnSteeringError;
  468. this.refObjects.Steering.PropertyChanged += Steering_PropertyChanged;
  469. this.refObjects.ZmqManager.PropertyChanged += ZmqManager_PropertyChanged;
  470. this.refObjects.AutoManager.OnOperationModeChanged += AutoManager_OnOperationModeChanged;
  471. }
  472. private void ObstacleReceiveEvent( ObstacleControlEventArgs obj )
  473. {
  474. if ( this.refObjects.AutoManager.OperationModeProperty != eOperatationMode.ManualMode )
  475. return;
  476. if ( obj.EventDir == ObstacleControlEventArgs.eEventDir.ToBack )
  477. {
  478. switch ( obj.ControlKind )
  479. {
  480. case ObstacleControlEventArgs.eControlKind.NONE:
  481. break;
  482. case ObstacleControlEventArgs.eControlKind.DRIVE:
  483. //this.ChgObstacleDetectPattern( new Random().Next( 0 , 40 ) );
  484. break;
  485. case ObstacleControlEventArgs.eControlKind.CURVE:
  486. //this.ChgObstacleDetectPattern( new Random().Next( 0 , 40 ) );
  487. break;
  488. case ObstacleControlEventArgs.eControlKind.STATE:
  489. //var value = this.GetObstacleDetectPattern();
  490. break;
  491. case ObstacleControlEventArgs.eControlKind.INFO:
  492. {
  493. var msg = new ObstacleControlEventArgs
  494. {
  495. ControlKind = ObstacleControlEventArgs.eControlKind.INFO,
  496. Drive = this.ObstacleDrive,
  497. Curve = this.ObstacleCurve,
  498. Current = this.GetObstacleDetectPattern(),
  499. ObstacleState = this.ObstacleStateProperty.ToString()
  500. };
  501. this.ObstacleControlEventPublish( msg );
  502. }
  503. break;
  504. case ObstacleControlEventArgs.eControlKind.SAVE:
  505. {
  506. this.ObstacleCurve = obj.Curve;
  507. this.ObstacleDrive = obj.Drive;
  508. var reply = new ObstacleControlEventArgs
  509. {
  510. ControlKind = ObstacleControlEventArgs.eControlKind.SAVE
  511. };
  512. reply.Result = Results.Ok( ObstacleControlEventArgs.eControlKind.SAVE );
  513. this.ObstacleControlEventPublish( reply );
  514. }
  515. break;
  516. }
  517. }
  518. }
  519. private void ObstacleControlEventPublish( ObstacleControlEventArgs args )
  520. {
  521. args.EventDir = ObstacleControlEventArgs.eEventDir.ToFront;
  522. this.eventAggregator.GetEvent<ObstacleControlPubSubEvent>().Publish( args );
  523. }
  524. private void ReceiveDriveControlEvent( DriveControlEventArgs _args )
  525. {
  526. var msg = _args;
  527. if ( msg.EventDir == DriveControlEventArgs.eEventDir.ToBack )
  528. {
  529. switch ( msg.ControlKind )
  530. {
  531. case DriveControlEventArgs.eControlKind.MOVE:
  532. this.ReqMoveToPos( _args );
  533. break;
  534. case DriveControlEventArgs.eControlKind.STOP:
  535. break;
  536. case DriveControlEventArgs.eControlKind.Steering:
  537. if ( msg.MoveDir == DriveControlEventArgs.eMoveDir.LEFT )
  538. this.refObjects.Steering.ControlSteering( true );
  539. else
  540. this.refObjects.Steering.ControlSteering();
  541. break;
  542. case DriveControlEventArgs.eControlKind.SteeringState:
  543. {
  544. var reply = new DriveControlEventArgs();
  545. reply.ControlKind = DriveControlEventArgs.eControlKind.SteeringState;
  546. if ( this.refObjects.Steering.IsLeft() )
  547. {
  548. reply.Args = eSteeringState.Left;
  549. reply.Result = FluentResults.Results.Ok();
  550. }
  551. else if ( this.refObjects.Steering.IsRight() )
  552. {
  553. reply.Args = eSteeringState.Right;
  554. reply.Result = FluentResults.Results.Ok();
  555. }
  556. else
  557. reply.Result = FluentResults.Results.Fail( new Error() );
  558. this.DriveControlEventPublish( reply );
  559. }
  560. break;
  561. case DriveControlEventArgs.eControlKind.ReqCurrentPos:
  562. //this.ReqCurrentPos();
  563. break;
  564. case DriveControlEventArgs.eControlKind.ReqStopCurrentPos:
  565. //this.taskCancel.Cancel();
  566. //this.taskCancel.WaitAll();
  567. break;
  568. case DriveControlEventArgs.eControlKind.FaultReset:
  569. this.ReqFaultReset( _args );
  570. break;
  571. case DriveControlEventArgs.eControlKind.DriveON:
  572. this.ReqDriveOn( _args );
  573. break;
  574. case DriveControlEventArgs.eControlKind.DriveOFF:
  575. this.ReqDriveOff( _args );
  576. break;
  577. case DriveControlEventArgs.eControlKind.JOG:
  578. this.ReqJog( _args );
  579. break;
  580. case DriveControlEventArgs.eControlKind.VehicleState:
  581. ReqVehicleState( _args );
  582. break;
  583. default:
  584. break;
  585. }
  586. }
  587. }
  588. public void ReqConveyorMove( string dir )
  589. {
  590. if ( dir.Equals( "CW" ) )
  591. this.refObjects.Conveyor.OnOffConveyor( true, false );
  592. else if ( dir.Equals( "CCW" ) )
  593. this.refObjects.Conveyor.OnOffConveyor( true, true );
  594. else if ( dir.Equals( "STOP" ) )
  595. this.refObjects.Conveyor.OnOffConveyor( false, false );
  596. }
  597. private void DriveControlEventPublish( DriveControlEventArgs args )
  598. {
  599. args.EventDir = DriveControlEventArgs.eEventDir.ToFront;
  600. this.eventAggregator.GetEvent<DriveControlPubSubEvent>().Publish( args );
  601. }
  602. public void Init()
  603. {
  604. ThreadStart();
  605. //TimerUtils.Once(5000, () => { this.CurrentPosition = 1000; });
  606. var v = refObjects.Sqlite.VehicleInfoDAL.GetAll().FirstOrDefault();
  607. v.CurrentTag = "0000";
  608. v.VehicleState = eVehicleState.None;
  609. v.MachineMode = eMachineMode.LocalMode;
  610. refObjects.Sqlite.VehicleInfoDAL.Update( v );
  611. }
  612. public int InitializationVehicle()
  613. {
  614. #if SIMULATION
  615. this.VehicleStateProperty = eVehicleState.Idle;
  616. return 0;
  617. #else
  618. int result = 0;
  619. //PIOClear();
  620. //PIOSensorOff();
  621. result = this.refObjects.Clamp.IsAllAxisOriginReturn();
  622. if ( result != ConstInt.EXECUTE_SUCCESS )
  623. {
  624. this.refObjects.Clamp.AllOriginReturn();
  625. LockUtils.Wait( 2000 );
  626. }
  627. if ( this.refObjects.Conveyor.IsDetectedCenter() ) //자제가 있으면 Lock
  628. result = this.refObjects.Clamp.Lock_Sync();
  629. else
  630. result = this.refObjects.Clamp.Unlock_Sync();
  631. result = 0;
  632. if ( result != 0 )
  633. {
  634. this.VehicleStateProperty = eVehicleState.Abnormal;
  635. return result;
  636. }
  637. if ( this.refObjects.Drive.IsErrorOn )
  638. return 22;
  639. this.VehicleStateProperty = eVehicleState.Idle;
  640. return result;
  641. #endif
  642. }
  643. public void Dispose()
  644. {
  645. this.taskCancel.Cancel();
  646. this.cancel.Cancel();
  647. this.cancel.StopWaitAll();
  648. //this.bMUManager.Disconnect();
  649. //this.drive.Dispose();
  650. }
  651. #region Request Method
  652. private void ReqVehicleState( DriveControlEventArgs args )
  653. {
  654. VehicleInfo state = new VehicleInfo();
  655. state.CurrentPosition = this.CurrentPosition;
  656. state.CurrentSpeed = this.CurrentSpeed;
  657. state.CurrentTag = this.CurrentTag.ToString();
  658. state.CurrentTorque = this.CurrentTorque;
  659. var msg = new DriveControlEventArgs();
  660. msg.ControlKind = args.ControlKind;
  661. msg.Args = state;
  662. DriveControlEventPublish( msg );
  663. }
  664. private void ReqMoveToPos( DriveControlEventArgs args )
  665. {
  666. //var result = drive.Move( args.PositionTag );
  667. //this.MoveTo( "1111" );
  668. var reply = new DriveControlEventArgs();
  669. int targetTag = args.TargetRouteID;
  670. var route = this.refObjects.Sqlite.RouteDal.Get( x => x.Name.Equals( targetTag ) ).FirstOrDefault();
  671. if ( route == null )
  672. {
  673. reply.Result = Results.Fail( "Not Found Route" );
  674. this.DriveControlEventPublish( reply );
  675. return;
  676. }
  677. var subCommand = new SubCmd();
  678. subCommand.TargetID = route.Name;
  679. this.MoveTo( subCommand );
  680. reply.Result = Results.Ok( "Position Move" );
  681. this.DriveControlEventPublish( reply );
  682. }
  683. void ReqFaultReset( DriveControlEventArgs _args )
  684. {
  685. var drive = 0;
  686. //var result = drive.ResetAmpFault();
  687. var msg = new DriveControlEventArgs
  688. {
  689. ControlKind = DriveControlEventArgs.eControlKind.FaultReset
  690. };
  691. msg.Result = Results.Ok( "Drive On" );
  692. this.DriveControlEventPublish( msg );
  693. }
  694. void ReqJog( DriveControlEventArgs _args )
  695. {
  696. if ( _args.JogDir == DriveControlEventArgs.eJogMoveDir.Positive )
  697. this.refObjects.Drive.JogForword();
  698. else
  699. this.refObjects.Drive.JogBackword();
  700. }
  701. Logger batteryLogger = Logger.GetLogger( "BatteryLogger" );
  702. void ReqCurrentPos()
  703. {
  704. var task = Task.Factory.StartNew( () =>
  705. {
  706. while ( !this.taskCancel.Canceled )
  707. {
  708. LockUtils.Wait( 1000 );
  709. batteryLogger.I( $"SOC - {this.BatteryStateOfCharge} / Current - {this.BatteryCurrent} / Voltage - {this.BatteryVoltage} / Capacity - {this.BatteryCapacity} / Energy - {this.BatteryEnergy}" );
  710. //var msg = new DriveControlEventArgs
  711. //{
  712. // EventDir = DriveControlEventArgs.eEventDir.ToFront,
  713. // ControlKind = DriveControlEventArgs.eControlKind.ReqCurrentPos,
  714. // CurrentPosition = new Random().Next( 0, 1000 ),
  715. //};
  716. //this.DriveControlEventPublish( msg );
  717. }
  718. } );
  719. this.taskCancel.Add( task );
  720. }
  721. void ReqDriveOn( DriveControlEventArgs _args )
  722. {
  723. var ll = this.refObjects.ZmqManager.SetDriveControl( eDriveControl.ServoOn );
  724. if(ll == 38)
  725. {
  726. logger.E( $"Servo On Error" );
  727. }
  728. var msg = new DriveControlEventArgs
  729. {
  730. ControlKind = DriveControlEventArgs.eControlKind.DriveON
  731. };
  732. msg.Result = Results.Ok( "Drive On" );
  733. this.DriveControlEventPublish( msg );
  734. }
  735. void ReqDriveOff( DriveControlEventArgs _args )
  736. {
  737. var ll = this.refObjects.ZmqManager.SetDriveControl( eDriveControl.ServoOff );
  738. if ( ll == 38 )
  739. {
  740. logger.E( $"Servo Off Error" );
  741. }
  742. var msg = new DriveControlEventArgs
  743. {
  744. ControlKind = DriveControlEventArgs.eControlKind.DriveOFF
  745. };
  746. msg.Result = Results.Ok( "Drive On" );
  747. this.DriveControlEventPublish( msg );
  748. }
  749. #endregion
  750. #region Thread
  751. void ThreadStart()
  752. {
  753. this.cancel.AddGo( new Action( this._ThSubCmdWorker ) );
  754. this.cancel.AddGo( new Action( this._ThVehicleStateCheck ) );
  755. }
  756. //장애물 감지 Thread
  757. //장애물 감지 패턴 변경도 여기 하자.
  758. private void _ThVehicleStateCheck()
  759. {
  760. while ( !this.cancel.Canceled )
  761. {
  762. try
  763. {
  764. //if ( this.autoManager.OperationModeProperty == eOperatationMode.AutoMode )
  765. //this.CheckObstacle();
  766. //this.CheckIOState();
  767. }
  768. catch ( ThreadInterruptedException threadInterruptedException )
  769. {
  770. }
  771. catch ( Exception exception )
  772. {
  773. logger.E( exception );
  774. }
  775. finally
  776. {
  777. LockUtils.Wait( 5 );
  778. }
  779. }
  780. logger.D( "Vehicle - _ThObstacleChecker Dispose" );
  781. }
  782. /// <summary>
  783. /// Scheduler 가 주는 Sub Command 를 이용하여 동작하자.
  784. /// </summary>
  785. public void _ThSubCmdWorker()
  786. {
  787. while ( !this.cancel.Canceled )
  788. {
  789. try
  790. {
  791. if ( this.ObstacleStateProperty != eObstacleState.Normal ) //장애물 감지 상태 시 조그 동작만 가능하게.
  792. continue;
  793. if ( this.refObjects.AutoManager.AutoModeStateProperty != eAutoModeState.Run ) //
  794. continue;
  795. var subCmd = this.refObjects.Sqlite.SubCmdDAL.GetAll().FirstOrDefault();
  796. if ( subCmd == null ) continue;
  797. if ( !this.refObjects.Sqlite.CommandDAL.GetAll().Any( x => x.CommandID.Equals( subCmd.CmdID ) ) )
  798. {
  799. if ( subCmd.CmdType == SubCmd.eCmdType.Auto ) //자동 명령중 Main Command 가 없으면 삭제.
  800. {
  801. this.refObjects.Sqlite.SubCmdDAL.Delete( subCmd.ID );
  802. logger.I( $"SubCmd Deleted - ID={subCmd.ID}, CommandID={subCmd.CmdID}" );
  803. }
  804. }
  805. switch ( subCmd.Type )
  806. {
  807. case eSubCommandType.Move:
  808. this.CurrentSubCommand = subCmd;
  809. this.Move( subCmd );
  810. break;
  811. case eSubCommandType.Load:
  812. this.CurrentSubCommand = subCmd;
  813. this.LoadCarrier( subCmd );
  814. break;
  815. case eSubCommandType.Unload:
  816. this.CurrentSubCommand = subCmd;
  817. this.UnloadCarrier( subCmd );
  818. break;
  819. case eSubCommandType.Charge:
  820. this.CurrentSubCommand = subCmd;
  821. this.BatteryCharge( subCmd );
  822. break;
  823. case eSubCommandType.Cancel:
  824. this.CurrentSubCommand = subCmd;
  825. CancelCommand( subCmd );
  826. break;
  827. default:
  828. break;
  829. }
  830. }
  831. catch ( Exception exception )
  832. {
  833. logger.E( exception );
  834. }
  835. finally
  836. {
  837. LockUtils.Wait( 500 );
  838. }
  839. }
  840. logger.D( "Vehicle - _ThSubCmdWorker Dispose" );
  841. }
  842. private void CancelCommand( SubCmd subCmd )
  843. {
  844. this.refObjects.Drive.CancelCommand( subCmd );
  845. var cmd = this.refObjects.Sqlite.CommandDAL.GetById( subCmd.CmdID );
  846. cmd.State = eCommandState.Complete;
  847. this.refObjects.Sqlite.CommandDAL.Update( cmd );
  848. this.refObjects.Sqlite.SubCmdDAL.Clean();
  849. logger.D( $"[Cancel Command] {cmd.TargetID} / {cmd.Type}" );
  850. }
  851. #endregion
  852. #region Control Action Method
  853. public void EStop()
  854. {
  855. this.refObjects.Conveyor.OnOffConveyor( false );
  856. //Clamp EStop
  857. this.refObjects.Clamp.ClampEStop();
  858. //this.drive.EStop();
  859. this.OccurVehicleAlarm( 23 );
  860. }
  861. #region For Moving
  862. void Move( SubCmd sub )
  863. {
  864. logger.I( $"[SubCommand Start] - Target : {sub.TargetID} / Type : {sub.Type}" );
  865. //Move 시작 시 충전 중이면 충전 중지 실행.
  866. int result = 0;
  867. if ( this.CheckBatteryCharge() || this.VehicleStateProperty == eVehicleState.Charge || this.BatteryChargeState )
  868. {
  869. result = this.StopBatteryCharge();
  870. if ( result != 0 )
  871. {
  872. OccurVehicleAlarm( result );
  873. return;
  874. }
  875. }
  876. var iTarget = Convert.ToInt32( sub.TargetID );
  877. if ( iTarget != CurrentTag ) //하나의 목표 위치로 왔을때 현재 위치와 동일 하면 이동안함.
  878. {
  879. result = this.MoveTo( sub );
  880. if ( result != ConstInt.EXECUTE_SUCCESS )
  881. {
  882. OccurVehicleAlarm( result );
  883. }
  884. }
  885. this.refObjects.Sqlite.SubCmdDAL.Clean();
  886. this.taskMoveCancel.Cancel();
  887. this.taskMoveCancel.WaitAll();
  888. this.CheckOCSConnectionState();
  889. logger.I( $"[SubCommand Complete] - Target : {sub.TargetID} / Type : {sub.Type}" );
  890. }
  891. int MoveTo( SubCmd sub )
  892. {
  893. if ( this.VehicleStateProperty == eVehicleState.Idle )
  894. {
  895. this.OnMoveReady?.Invoke();
  896. var moveReadyBuzzerTime = Convert.ToInt32( this.refObjects.Sqlite.ConfigDal.GetById( ConstString.BuzzerStartReadyTime ).Value );
  897. Thread.Sleep( moveReadyBuzzerTime );
  898. this.VehicleStateProperty = eVehicleState.Move;
  899. }
  900. this.OnMoving?.Invoke();
  901. //이전에 있던 작업들 종료 및 삭제
  902. this.taskMoveCancel.Cancel();
  903. this.taskMoveCancel.WaitAll();
  904. this.taskMoveCancel.Add( CheckCrossPoint() );
  905. this.VehicleStateProperty = eVehicleState.Move;
  906. int result = this.refObjects.Drive.MoveToPoint( sub, 100 );
  907. if ( result != ConstInt.EXECUTE_SUCCESS )
  908. return result;
  909. result = this.Wait4MoveDone();
  910. if ( result != ConstInt.EXECUTE_SUCCESS )
  911. return result;
  912. //Drive 에서 정지 확인 후 상태 변경
  913. if ( this.refObjects.Drive.IsDriveStop() )
  914. {
  915. this.OnMoveFinish?.Invoke();
  916. this.VehicleStateProperty = eVehicleState.Idle;
  917. logger.D( "Move Finish" );
  918. }
  919. return result;
  920. }
  921. int Wait4MoveDone()
  922. {
  923. int waitTime = ConstUtils.ONE_HOUR; //설정 할 수있게.
  924. long st = SwUtils.CurrentTimeMillis;
  925. //Todo: 이동시 확인 사항들.
  926. while ( true )
  927. {
  928. Thread.Sleep( 5 );
  929. if ( SwUtils.Gt( st, waitTime ) )
  930. {
  931. logger.D( "Wait4MoveDone Time Over" );
  932. return 39;
  933. }
  934. //Todo: 이동중 명령이 삭제 되면 처리 할일들.
  935. //이동중 메인 명력이 없어진다면 정지 후
  936. if ( null == this.refObjects.Sqlite.CommandDAL.GetById( this.CurrentSubCommand.CmdID ) )
  937. {
  938. logger.D( "[Wait Move Done] - 메인 명령 사라짐" );
  939. var cmd = this.refObjects.Sqlite.CommandDAL.GetAll();
  940. if ( cmd == null )
  941. {
  942. logger.D( "[Wait Move Done] - Main Command not Exist Motion Stop" );
  943. this.refObjects.Drive.Stop();
  944. return 40;
  945. }
  946. else
  947. {
  948. logger.D( "[Wait Move Done] - Main Command not Exist Motion command, New Command Exist" );
  949. break;
  950. }
  951. }
  952. if ( this.refObjects.Drive.IsDriveStop() ) //Move Stop
  953. break;
  954. }
  955. return ConstInt.EXECUTE_SUCCESS;
  956. }
  957. Task CheckCrossPoint()
  958. {
  959. var task = Task.Run( () =>
  960. {
  961. long sTime = SwUtils.CurrentTimeMillis;
  962. while ( !this.taskMoveCancel.Canceled )
  963. {
  964. Thread.Sleep( 10 );
  965. //ToDo: approach Cross Point Check
  966. //ToDo: Obstacle Laser Sensor Pattern Change Method 구현 필요.
  967. }
  968. } );
  969. return task;
  970. }
  971. #endregion
  972. public bool LoadCarrier( SubCmd sub )
  973. {
  974. logger.I( $"[SubCommand Start] - Target : {sub.TargetID} / Type : {sub.Type}" );
  975. this.VehicleStateProperty = eVehicleState.Load;
  976. //var route = sql.RouteDal.GetRoute( sub.TargetID );
  977. //if ( !CorrectPosition( route, this.CurrentPosition ) )
  978. //{
  979. // this.OccurVehicleAlarm( 20 );
  980. // return false; //Alarm
  981. //}
  982. int result = 0;
  983. result = this.PIOAndLoad( sub.TargetID );
  984. if ( result != 0 )
  985. {
  986. this.PIOSensorOff();
  987. this.OccurVehicleAlarm( result );
  988. return false;
  989. }
  990. this.PIOSensorOff();
  991. //Load, Unload 가 끝나면 메인 Command 를 완료 했다고 판단.
  992. logger.I( $"[SubCommand Complete] - Target : {sub.TargetID} / Type : {sub.Type}" );
  993. this.refObjects.Sqlite.SubCmdDAL.Clean();
  994. var cmd = this.refObjects.Sqlite.CommandDAL.GetById( sub.CmdID );
  995. if ( cmd != null )
  996. {
  997. cmd.State = eCommandState.Complete;
  998. this.refObjects.Sqlite.CommandDAL.Update( cmd );
  999. }
  1000. TimerUtils.Once( 1000, this.OnLoadComplete );
  1001. //LockUtils.Wait( 1000 );
  1002. //this.OnLoadComplete?.Invoke(); //일찍 주면 다음 명령을 500ms 안에 주는 현상 있음. 그러니까 천천히 주자
  1003. this.VehicleStateProperty = eVehicleState.Idle;
  1004. return true;
  1005. }
  1006. public bool UnloadCarrier( SubCmd sub )
  1007. {
  1008. logger.I( $"[SubCommand Start] - Target : {sub.TargetID} / Type : {sub.Type}" );
  1009. this.VehicleStateProperty = eVehicleState.Unload;
  1010. var targetNo = Convert.ToInt32( sub.TargetID );
  1011. if ( this.CurrentTag != targetNo )
  1012. {
  1013. this.OccurVehicleAlarm( 21 );
  1014. return false; //Alarm
  1015. }
  1016. //var route = sql.RouteDal.GetRoute( sub.TargetID );
  1017. //if ( !CorrectPosition( route, this.CurrentPosition ) )
  1018. //{
  1019. // this.OccurVehicleAlarm( 21 );
  1020. // return false; //Alarm
  1021. //}
  1022. //PIO 내부로 이동.
  1023. //int result = this.clamp.Unlock_Sync();
  1024. //if ( result != 0 )
  1025. //{
  1026. // this.OccurVehicleAlarm( result );
  1027. // return false;
  1028. //}
  1029. int result = 0;
  1030. result = this.PIOAndUnload( sub.TargetID );
  1031. if ( result != 0 )
  1032. {
  1033. this.refObjects.IO.OutputOn( "OUT_PIO_SENSOR_ONOFF" );
  1034. this.OccurVehicleAlarm( result );
  1035. return false;
  1036. }
  1037. this.PIOSensorOff();
  1038. logger.I( $"[SubCommand Complete] - Target : {sub.TargetID} / Type : {sub.Type}" );
  1039. this.refObjects.Sqlite.SubCmdDAL.Clean();
  1040. var cmd = this.refObjects.Sqlite.CommandDAL.GetById( sub.CmdID );
  1041. if ( cmd != null )
  1042. {
  1043. cmd.State = eCommandState.Complete;
  1044. this.refObjects.Sqlite.CommandDAL.Update( cmd );
  1045. }
  1046. TimerUtils.Once( 1000, this.OnUnloadComplete );
  1047. //LockUtils.Wait( 1000 );
  1048. //this.OnUnloadComplete?.Invoke(); //일찍 주면 다음 명령을 500ms 안에 주는 현상 있음. 그러니까 천천히 주자
  1049. this.VehicleStateProperty = eVehicleState.Idle;
  1050. return true;
  1051. }
  1052. public void BatteryCharge( SubCmd subCmd )
  1053. {
  1054. int result = 0;
  1055. result = this.StartBatteryCharge();
  1056. if ( result != ConstInt.EXECUTE_SUCCESS )
  1057. this.OccurVehicleAlarm( result );
  1058. this.refObjects.Sqlite.SubCmdDAL.Clean();
  1059. var cmd = this.refObjects.Sqlite.CommandDAL.GetById( subCmd.CmdID );
  1060. if ( cmd == null )
  1061. return;
  1062. cmd.State = eCommandState.Complete;
  1063. this.refObjects.Sqlite.CommandDAL.Update( cmd );
  1064. }
  1065. /// <summary>
  1066. /// Battery Charge
  1067. /// 충전 시 PIO 를 해야 함.
  1068. /// </summary>
  1069. /// <param name="sub"></param>
  1070. /// <returns></returns>
  1071. int PIOBatteryCharge( SubCmd sub )
  1072. {
  1073. var route = this.refObjects.Sqlite.RouteDal.GetById( sub.TargetID );
  1074. if ( !CorrectPosition( route, this.CurrentPosition ) )
  1075. {
  1076. this.OccurVehicleAlarm( 21 );
  1077. return 0; //Alarm
  1078. }
  1079. var pioTimeout = CastTo<int>.From<string>( this.refObjects.Sqlite.ConfigDal.GetById( ConstString.PIOTimeOut ).Value );
  1080. PIOClear();
  1081. loggerPIO.I( $"Start Charge PIO - [{sub.TargetID}]" );
  1082. if ( !this.refObjects.IO.IsOn( "IN_PIO_READY" ) )
  1083. {
  1084. loggerPIO.E( "[Port] - 1 Ready not On" );
  1085. this.OccurVehicleAlarm( 25 );
  1086. return 0;
  1087. }
  1088. this.refObjects.IO.WriteOutputIO( "OUT_PIO_READY", true );
  1089. loggerPIO.I( "[Vehicle] - 1 Ready On" );
  1090. if ( !this.refObjects.IO.WaitChangeInputIO( true, pioTimeout, "IN_PIO_RECEIVE_RUN" ) )
  1091. {
  1092. PIOClear();
  1093. loggerPIO.E( "[Port] - 2 Receive CV Run Timeout" );
  1094. this.OccurVehicleAlarm( 26 );
  1095. return 0;
  1096. }
  1097. this.refObjects.IO.WriteOutputIO( "OUT_PIO_SENDING_RUN", true );
  1098. loggerPIO.I( "[Vehicle] - 2 Send Run On" );
  1099. var sTime = SwUtils.CurrentTimeMillis;
  1100. while ( true )
  1101. {
  1102. Thread.Sleep( 5 );
  1103. if ( !this.refObjects.IO.IsOn( "IN_PIO_READY" ) || this.refObjects.IO.IsOn( "IN_PIO_RECEIVE_RUN" ) )
  1104. break;
  1105. if ( null == this.refObjects.Sqlite.CommandDAL.GetById( this.CurrentSubCommand.CmdID ) )
  1106. {
  1107. PIOClear();
  1108. logger.D( "[Wait Charging] - 메인 명령 사라짐" );
  1109. break;
  1110. }
  1111. }
  1112. if ( !this.refObjects.IO.WaitChangeInputIO( true, pioTimeout, "IN_PIO_RECEIVE_COMPLITE" ) )
  1113. {
  1114. PIOClear();
  1115. loggerPIO.E( "[Port] - 3 Receive Complete Timeout" );
  1116. this.OccurVehicleAlarm( 26 );
  1117. return 0;
  1118. }
  1119. PIOClear();
  1120. this.refObjects.IO.WriteOutputIO( "OUT_PIO_SEND_COMPLITE", true );
  1121. Thread.Sleep( 1000 );
  1122. this.refObjects.IO.WriteOutputIO( "OUT_PIO_SEND_COMPLITE", false );
  1123. return 0;
  1124. }
  1125. public int StartBatteryCharge()
  1126. {
  1127. #if SIMULATION
  1128. this.PIOSensorOn();
  1129. var pioTimeout = CastTo<int>.From<string>( sql.ConfigDal.GetById( ConstString.PIOTimeOut ).Value );
  1130. PIOClear();
  1131. loggerPIO.I( $"Start Battery Charge PIO" );
  1132. //if ( !this.iO.WaitChangeInputIO( true, pioTimeout, "IN_PIO_SENDABLE" ) )
  1133. //{
  1134. // PIOClear();
  1135. // loggerPIO.E( "[Port] - 4 Ready Time Out" );
  1136. // return 34;
  1137. //}
  1138. Thread.Sleep( 1000 );
  1139. loggerPIO.E( "[Port] - 4 Ready On" );
  1140. this.refObjects.IO.WriteOutputIO( "OUT_PIO_RECEIVABLE", true );
  1141. loggerPIO.I( "[Vehicle] - 4 Receivable" );
  1142. //if ( !this.iO.WaitChangeInputIO( true, 20000, "IN_PIO_SEND_RUN" ) )
  1143. //{
  1144. // PIOClear();
  1145. // loggerPIO.E( "[Port] - 5 Sending Run Time Out" );
  1146. // return 35;
  1147. //}
  1148. Thread.Sleep( 1000 );
  1149. loggerPIO.I( "[Port] - 5 Sending Run On" );
  1150. this.refObjects.IO.WriteOutputIO( "OUT_PIO_RECEIVE_RUN", true );
  1151. loggerPIO.I( "[Vehicle] - 5 Receive Run On" );
  1152. this.VehicleStateProperty = eVehicleState.Charge;
  1153. this.OnChargingStart?.Invoke();
  1154. Thread.Sleep( 1000 );
  1155. this.OnCharging?.Invoke();
  1156. return 0;
  1157. #else
  1158. this.PIOSensorOn();
  1159. LockUtils.Wait( 500 );
  1160. var pioTimeout = Convert.ToInt32( this.refObjects.Sqlite.ConfigDal.GetById( ConstString.PIOTimeOut ).Value );
  1161. PIOClear();
  1162. loggerPIO.I( $"Start Battery Charge PIO" );
  1163. if ( !this.refObjects.IO.WaitChangeInputIO( true, pioTimeout, "IN_PIO_SENDABLE" ) )
  1164. {
  1165. PIOClear();
  1166. loggerPIO.E( "[Port] - 4 Ready Time Out" );
  1167. return 34;
  1168. }
  1169. loggerPIO.E( "[Port] - 4 Ready On" );
  1170. this.refObjects.IO.WriteOutputIO( "OUT_PIO_RECEIVABLE", true );
  1171. loggerPIO.I( "[Vehicle] - 4 Receivable" );
  1172. if ( !this.refObjects.IO.WaitChangeInputIO( true, 5000, "IN_PIO_SEND_RUN" ) )
  1173. {
  1174. PIOClear();
  1175. loggerPIO.E( "[Port] - 5 Sending Run Time Out" );
  1176. return 35;
  1177. }
  1178. loggerPIO.I( "[Port] - 5 Sending Run On" );
  1179. this.refObjects.IO.WriteOutputIO( "OUT_PIO_RECEIVE_RUN", true );
  1180. loggerPIO.I( "[Vehicle] - 5 Receive Run On" );
  1181. this.VehicleStateProperty = eVehicleState.Charge;
  1182. return 0;
  1183. #endif
  1184. }
  1185. public int StopBatteryCharge()
  1186. {
  1187. #if SIMULATION
  1188. loggerPIO.I( $"Stop Battery Charge PIO" );
  1189. var pioTimeout = CastTo<int>.From<string>( sql.ConfigDal.GetById( ConstString.PIOTimeOut ).Value );
  1190. this.PIOClear();
  1191. this.refObjects.IO.WriteOutputIO( "OUT_PIO_RECIVE_COMPLITE", true );
  1192. loggerPIO.I( "[Vehicle] Receive Complete On" );
  1193. //if ( !this.iO.WaitChangeInputIO( true, 20000, "IN_PIO_SEND_COMPLITE" ) )
  1194. //{
  1195. // this.iO.WriteOutputIO( "OUT_PIO_RECIVE_COMPLITE", false );
  1196. // loggerPIO.E( "[Port] IN_PIO_SEND_COMPLITE On Time Out" );
  1197. // return 36;
  1198. //}
  1199. Thread.Sleep( 1000 );
  1200. loggerPIO.I( "[Port] Send Complete On" );
  1201. Thread.Sleep( 1000 );
  1202. this.refObjects.IO.WriteOutputIO( "OUT_PIO_RECIVE_COMPLITE", false );
  1203. this.OnChargingFull?.Invoke();
  1204. this.PIOSensorOff();
  1205. this.VehicleStateProperty = eVehicleState.Idle;
  1206. return 0;
  1207. #else
  1208. loggerPIO.I( $"Stop Battery Charge PIO" );
  1209. var pioTimeout = Convert.ToInt32( this.refObjects.Sqlite.ConfigDal.GetById( ConstString.PIOTimeOut ).Value );
  1210. this.PIOClear();
  1211. this.refObjects.IO.WriteOutputIO( "OUT_PIO_RECIVE_COMPLITE", true );
  1212. loggerPIO.I( "[Vehicle] Receive Complete On" );
  1213. if ( !this.refObjects.IO.WaitChangeInputIO( true, 5000, "IN_PIO_SEND_COMPLITE" ) )
  1214. {
  1215. this.refObjects.IO.WriteOutputIO( "OUT_PIO_RECIVE_COMPLITE", false );
  1216. loggerPIO.E( "[Port] IN_PIO_SEND_COMPLITE On Time Out" );
  1217. return 36;
  1218. }
  1219. loggerPIO.I( "[Port] Send Complete On" );
  1220. Thread.Sleep( 1000 );
  1221. this.refObjects.IO.WriteOutputIO( "OUT_PIO_RECIVE_COMPLITE", false );
  1222. this.PIOSensorOff();
  1223. this.OnChargingFull?.Invoke();
  1224. this.VehicleStateProperty = eVehicleState.Idle;
  1225. return 0;
  1226. #endif
  1227. }
  1228. #endregion
  1229. #region Check Method
  1230. bool CheckObstacle()
  1231. {
  1232. if ( this.refObjects.IO.IsOff( "IN_OBSTRUCTION_DETECT_SAFETY" ) || this.refObjects.IO.IsOff( "IN_OBSTRUCTION_DETECT_ERROR" ) )
  1233. {
  1234. this.ObstacleStateProperty = eObstacleState.Abnormal;
  1235. //this.OccurVehicleAlarm( 42 );
  1236. }
  1237. else if ( this.refObjects.IO.IsOff( "IN_OBSTRUCTION_DETECT_STOP" ) )
  1238. {
  1239. this.ObstacleStateProperty = eObstacleState.Blocked;
  1240. }
  1241. else if ( this.refObjects.IO.IsOff( "IN_OBSTRUCTION_DETECT_SLOW" ) )
  1242. {
  1243. this.ObstacleStateProperty = eObstacleState.Decelerate;
  1244. }
  1245. else
  1246. {
  1247. this.ObstacleStateProperty = eObstacleState.Normal;
  1248. }
  1249. this.refObjects.Drive.SetObstacleState( this.ObstacleStateProperty );
  1250. return false;
  1251. }
  1252. void CheckIOState()
  1253. {
  1254. //이미 알람이면 체크 안함.
  1255. if ( this.VehicleStateProperty == eVehicleState.Abnormal ) return;
  1256. if ( this.refObjects.IO.IsConnectError ) return;
  1257. //if ( this.iO.IsOn( "IN_EMS_SW" ) ) this.OccurVehicleAlarm( 28 );
  1258. //if ( !this.iO.IsOn( "IN_CP_ON_SAFETY" ) ) this.OccurVehicleAlarm( 31 );
  1259. //if ( !this.iO.IsOn( "IN_CP_ON_24V" ) ) this.OccurVehicleAlarm( 30 );
  1260. //if ( !this.iO.IsOn( "IN_MC_ON" ) ) this.OccurVehicleAlarm( 29 );
  1261. }
  1262. #endregion
  1263. #region Mechanical Method
  1264. #region IO
  1265. /// <summary>
  1266. /// Out Put 을 On 이면 Sensor Off
  1267. /// </summary>
  1268. public void PIOSensorOn() => this.refObjects.IO.OutputOff( "OUT_PIO_SENSOR_ONOFF" );
  1269. /// <summary>
  1270. /// Out Put 을 Off 이면 Sensor On
  1271. /// </summary>
  1272. public void PIOSensorOff() => this.refObjects.IO.OutputOn( "OUT_PIO_SENSOR_ONOFF" );
  1273. /// <summary>
  1274. /// 충전 중일때 MTL PIO Bit 가 살아 있다
  1275. /// 이걸 보고 판단 하자. 충전 단자 전진 상태임.
  1276. /// </summary>
  1277. /// <returns></returns>
  1278. public bool CheckBatteryCharge()
  1279. {
  1280. this.PIOSensorOn();
  1281. LockUtils.Wait( 500 );
  1282. if ( this.BatteryChargeState || this.VehicleStateProperty == eVehicleState.Charge )
  1283. {
  1284. }
  1285. //var ret = this.refObjects.IO.IsOn( "OUT_PIO_RECEIVABLE", false )
  1286. // && this.refObjects.IO.IsOn( "OUT_PIO_RECEIVE_RUN", false )
  1287. // && this.refObjects.IO.IsOn( "IN_PIO_SEND_RUN" );
  1288. var ret = this.refObjects.IO.IsOn( "IN_PIO_SEND_RUN" );
  1289. //this.PIOSensorOff();
  1290. return ret;
  1291. }
  1292. #endregion
  1293. #region Drive
  1294. //public void DriveServoOff() => this.drive.ServoOff();
  1295. //public void DriveServoOn() => this.drive.ServoOn();
  1296. #endregion
  1297. #region Conveyor
  1298. public void ConveyorOff() => this.refObjects.Conveyor.OnOffConveyor( false );
  1299. public int ConveyorLoad() => this.refObjects.Conveyor.ConveyorLoad();
  1300. public int ConveyorUnload() => this.refObjects.Conveyor.ConveyorUnload();
  1301. public int PIOAndLoad( string targetName )
  1302. {
  1303. #if SIMULATION
  1304. PIOClear();
  1305. loggerPIO.I( $"Start Load PIO - [{targetName}]" );
  1306. this.OnPIOStart?.Invoke( true );
  1307. this.refObjects.IO.WriteOutputIO( "OUT_PIO_RECEIVE_RUN", true );
  1308. loggerPIO.I( "[Vehicle] - 4 Receive Run On" );
  1309. Thread.Sleep( 1000 );//상대 IO 기다린다 생각.
  1310. loggerPIO.E( "[Port] - 4 Ready On" );
  1311. //Conveyor Start
  1312. loggerPIO.I( "[Vehicle] - Conveyor Run" );
  1313. this.OnConveyorStart?.Invoke( true );
  1314. Thread.Sleep( 10000 );//Conveyor 구동
  1315. this.OnCarrierDetected?.Invoke( true );
  1316. PIOClear();
  1317. Thread.Sleep( 1000 );
  1318. this.OnConveyorStop?.Invoke( true );
  1319. Thread.Sleep( 1000 );
  1320. this.OnLoadComplete?.Invoke();
  1321. #else
  1322. loggerPIO.I( $"Start Load PIO - [{targetName}]" );
  1323. this.PIOSensorOn();
  1324. LockUtils.Wait( 500 );
  1325. int result = 0;
  1326. var pioTimeout = Convert.ToInt32( this.refObjects.Sqlite.ConfigDal.GetById( ConstString.PIOTimeOut ).Value );
  1327. result = this.refObjects.Clamp.Unlock_Sync();
  1328. if ( result != 0 )
  1329. {
  1330. this.OccurVehicleAlarm( result );
  1331. return result;
  1332. }
  1333. if ( this.refObjects.Conveyor.IsInverterError() )
  1334. return 16;
  1335. if ( this.refObjects.Conveyor.IsDetectedCenter() )
  1336. {
  1337. this.OnFailReport?.Invoke( eFailCode.Load_VehicleHasCarrier );
  1338. return 0;
  1339. }
  1340. if ( !this.refObjects.IO.WaitChangeInputIO( true, 40 * ConstUtils.ONE_SECOND, "IN_LIFTER_POSITION_DETECT" ) )
  1341. {
  1342. loggerPIO.E( "[Port] - Lift Position Check Error" );
  1343. TimerUtils.Once( 1000, this.OnFailReport, eFailCode.LoadPIOInterlockTimeout );
  1344. //this.OnFailReport?.Invoke( eFailCode.LoadPIOInterlockTimeout );
  1345. return 0; //14
  1346. }
  1347. //if ( !this.refObjects.Conveyor.IsLifterPositinCheck() )
  1348. //{
  1349. // loggerPIO.E( "[Port] - Lift Position Check Error" );
  1350. // this.OnFailReport?.Invoke( eFailCode.LoadPIOInterlockTimeout );
  1351. // return 0; //14
  1352. //}
  1353. //Todo: Sensor Setting 이 후 주석 풀기.
  1354. //if ( !this.IsLifterDuplication() )
  1355. //{
  1356. // this.OnFailReport?.Invoke( eFailCode.Load_PortHasNotCarrier );
  1357. // return 0;
  1358. //}
  1359. PIOClear();
  1360. this.OnPIOStart?.Invoke( true );
  1361. this.refObjects.IO.WriteOutputIO( "OUT_PIO_RECEIVABLE", true );
  1362. loggerPIO.I( "[Vehicle] - 4 Receivable" );
  1363. if ( !this.refObjects.IO.WaitChangeInputIO( true, 20 * ConstUtils.ONE_SECOND, "IN_PIO_SENDABLE" ) )
  1364. {
  1365. PIOClear();
  1366. loggerPIO.E( "[Port] - 4 Ready Time Out" );
  1367. TimerUtils.Once( 1000, this.OnFailReport, eFailCode.LoadPIOInterlockTimeout );
  1368. //this.OnFailReport?.Invoke( eFailCode.LoadPIOInterlockTimeout );
  1369. return 0;
  1370. }
  1371. loggerPIO.E( "[Port] - 4 Ready On" );
  1372. //this.conveyor.SetConveyorSpeed( true );
  1373. this.refObjects.Conveyor.OnOffConveyor( true, true );
  1374. this.refObjects.IO.WriteOutputIO( "OUT_PIO_RECEIVE_RUN", true, 1000 ); //1Sec 이후 On
  1375. loggerPIO.I( "[Vehicle] - Conveyor Run" );
  1376. this.OnConveyorStart?.Invoke( true );
  1377. if ( !this.refObjects.IO.WaitChangeInputIO( true, pioTimeout, "IN_PIO_SEND_RUN" ) )
  1378. {
  1379. this.refObjects.Conveyor.OnOffConveyor( false, true );
  1380. PIOClear();
  1381. loggerPIO.E( "[Port] - 5 Sending Run Time Out" );
  1382. TimerUtils.Once( 1000, this.OnFailReport, eFailCode.LoadPIOInterlockTimeout );
  1383. //this.OnFailReport?.Invoke( eFailCode.LoadPIOInterlockTimeout );
  1384. return 0;
  1385. }
  1386. loggerPIO.I( "[Port] - 5 Sending Run On" );
  1387. bool isStartDetected = false;
  1388. var sTime = SwUtils.CurrentTimeMillis;
  1389. while ( true )
  1390. {
  1391. LockUtils.Wait( 10 );
  1392. if ( SwUtils.Gt( sTime, 20 * ConstUtils.ONE_SECOND ) )
  1393. {
  1394. PIOClear();
  1395. this.refObjects.Conveyor.OnOffConveyor( false, true );
  1396. loggerPIO.E( "[Vehicle] Conveyor Wait Time Out" );
  1397. TimerUtils.Once( 1000, this.OnFailReport, eFailCode.LoadPIOInterlockTimeout );
  1398. //this.OnFailReport?.Invoke( eFailCode.LoadPIOInterlockTimeout );
  1399. if ( this.refObjects.Conveyor.IsDetectedLoadStart() ) // 감지가 시작 되었으면 이동중 Error 로 판단 설비를 정지 상태로
  1400. return 10; //Conveyor Moving Timeout
  1401. else
  1402. return 0;
  1403. }
  1404. if ( this.refObjects.Conveyor.IsDetectedLoadStart() && !isStartDetected )
  1405. isStartDetected = true;
  1406. if ( !this.refObjects.Conveyor.IsDetectedLoadStart() && isStartDetected ) { }
  1407. //this.conveyor.SetConveyorSpeed( false );
  1408. if ( this.refObjects.Conveyor.IsDetectedLoadStop() ) break;
  1409. if ( this.refObjects.Conveyor.IsPIOInterLockOn() )
  1410. {
  1411. PIOClear();
  1412. this.refObjects.Conveyor.OnOffConveyor( false ); //Stop
  1413. loggerPIO.E( "[Port] PIO InterLock On " );
  1414. return 19; //
  1415. }
  1416. }
  1417. if ( this.refObjects.Conveyor.IsDetectedCenter() )
  1418. this.OnCarrierDetected?.Invoke( true );
  1419. this.refObjects.Conveyor.OnOffConveyor( false ); //Stop
  1420. PIOClear();
  1421. this.OnConveyorStop?.Invoke( true );
  1422. loggerPIO.I( "[Vehicle] Conveyor Stop" );
  1423. this.refObjects.IO.WriteOutputIO( "OUT_PIO_RECIVE_COMPLITE", true );
  1424. loggerPIO.I( "[Vehicle] Receive Complete On" );
  1425. if ( !this.refObjects.IO.WaitChangeInputIO( true, pioTimeout, "IN_PIO_SEND_COMPLITE" ) )
  1426. {
  1427. this.refObjects.IO.WriteOutputIO( "OUT_PIO_RECIVE_COMPLITE", false );
  1428. loggerPIO.E( "[Port] IN_PIO_SEND_COMPLITE On Time Out" );
  1429. }
  1430. loggerPIO.I( "[Port] Send Complete On" );
  1431. this.refObjects.IO.WriteOutputIO( "OUT_PIO_RECIVE_COMPLITE", false, 1000 );
  1432. loggerPIO.I( $"End Load PIO - [{targetName}]" );
  1433. result = this.refObjects.Clamp.Lock_Sync();
  1434. if ( result != 0 )
  1435. {
  1436. this.OccurVehicleAlarm( result );
  1437. return result;
  1438. }
  1439. #endif
  1440. return 0;
  1441. }
  1442. public int PIOAndUnload( string targetName )
  1443. {
  1444. #if SIMULATION
  1445. PIOClear();
  1446. loggerPIO.I( $"Start Unload PIO - [{targetName}]" );
  1447. this.OnPIOStart?.Invoke( false );
  1448. Thread.Sleep( 1000 );
  1449. this.refObjects.IO.WriteOutputIO( "OUT_PIO_READY", true );
  1450. loggerPIO.I( "[Vehicle] - 1 Ready On" );
  1451. Thread.Sleep( 1000 );
  1452. this.OnConveyorStart?.Invoke( false );
  1453. Thread.Sleep( 10000 );
  1454. this.refObjects.Conveyor.OnOffConveyor( false ); //Stop
  1455. this.OnConveyorStop?.Invoke( false );
  1456. PIOClear();
  1457. Thread.Sleep( 1000 );
  1458. this.OnUnloadComplete?.Invoke();
  1459. #else
  1460. loggerPIO.E( $"Start Unload PIO -[{targetName}]" );
  1461. this.PIOSensorOn();
  1462. LockUtils.Wait( 500 );
  1463. int result = 0;
  1464. var pioTimeout = Convert.ToInt32( this.refObjects.Sqlite.ConfigDal.GetById( ConstString.PIOTimeOut ).Value );
  1465. if ( this.refObjects.Conveyor.IsInverterError() )
  1466. return 16;
  1467. //if ( this.refObjects.Conveyor.IsLifterDuplication() )
  1468. //{
  1469. // this.OnFailReport?.Invoke( eFailCode.Unload_PortHasCarrier );
  1470. // return 0;
  1471. //}
  1472. if ( !this.refObjects.Conveyor.IsDetectedCenter() )
  1473. {
  1474. TimerUtils.Once( 1000, this.OnFailReport, eFailCode.Unload_VehicleHasNotCarrier );
  1475. //this.OnFailReport?.Invoke( eFailCode.Unload_VehicleHasNotCarrier );
  1476. return 0;
  1477. }
  1478. if ( !this.refObjects.IO.WaitChangeInputIO( true, 40 * ConstUtils.ONE_SECOND, "IN_LIFTER_POSITION_DETECT" ) )
  1479. {
  1480. loggerPIO.E( "[Port] - Lift Position Check Error" );
  1481. TimerUtils.Once( 1000, this.OnFailReport, eFailCode.UnlaodPIOInterlockTimeout );
  1482. //this.OnFailReport?.Invoke( eFailCode.UnlaodPIOInterlockTimeout );
  1483. return 0;
  1484. }
  1485. //if ( !this.refObjects.Conveyor.IsLifterPositinCheck() )
  1486. //{
  1487. // loggerPIO.E( "[Port] - Lift Position Check Error" );
  1488. // this.OnFailReport?.Invoke( eFailCode.UnlaodPIOInterlockTimeout ); //Unloading Fail Code 를 Time Out 으로 하자. 정의 된 코드 없음.
  1489. // return 0; //13 -> Alarm Code 보고 없음. 경알람 상태 이므로 한번 보고 후 정상 동작
  1490. //}
  1491. PIOClear();
  1492. this.OnPIOStart?.Invoke( false );
  1493. if ( !this.refObjects.IO.WaitChangeInputIO( true, 20 * ConstUtils.ONE_SECOND, "IN_PIO_READY" ) )
  1494. {
  1495. loggerPIO.E( "[Port] - 1 Ready not On" );
  1496. TimerUtils.Once( 1000, this.OnFailReport, eFailCode.UnlaodPIOInterlockTimeout );
  1497. //this.OnFailReport?.Invoke( eFailCode.UnlaodPIOInterlockTimeout );
  1498. return 0;
  1499. }
  1500. this.refObjects.IO.WriteOutputIO( "OUT_PIO_READY", true );
  1501. loggerPIO.I( "[Vehicle] - 1 Ready On" );
  1502. if ( !this.refObjects.IO.WaitChangeInputIO( true, 10 * ConstUtils.ONE_SECOND, "IN_PIO_RECEIVE_RUN" ) )
  1503. {
  1504. PIOClear();
  1505. loggerPIO.E( "[Port] - 2 Receive CV Run Timeout" );
  1506. TimerUtils.Once( 1000, this.OnFailReport, eFailCode.UnlaodPIOInterlockTimeout );
  1507. //this.OnFailReport?.Invoke( eFailCode.UnlaodPIOInterlockTimeout );
  1508. return 0;
  1509. }
  1510. loggerPIO.E( "[Port] - 2 Receive CV Run On" );
  1511. result = this.refObjects.Clamp.Unlock_Sync();
  1512. if ( result != 0 )
  1513. {
  1514. this.OccurVehicleAlarm( result );
  1515. return result;
  1516. }
  1517. this.refObjects.IO.WriteOutputIO( "OUT_PIO_SENDING_RUN", true );
  1518. loggerPIO.I( "[Vehicle] - 2 Send Run On" );
  1519. //this.conveyor.SetConveyorSpeed( true );
  1520. this.refObjects.Conveyor.OnOffConveyor( true );
  1521. this.OnConveyorStart?.Invoke( false );
  1522. var sTime = SwUtils.CurrentTimeMillis;
  1523. while ( true )
  1524. {
  1525. if ( SwUtils.Gt( sTime, 20 * ConstUtils.ONE_SECOND ) )
  1526. {
  1527. PIOClear();
  1528. this.refObjects.Conveyor.OnOffConveyor( false, true );
  1529. loggerPIO.E( "[Port] Conveyor Wait Time Out" );
  1530. TimerUtils.Once( 1000, this.OnFailReport, eFailCode.UnlaodPIOInterlockTimeout );
  1531. //this.OnFailReport?.Invoke( eFailCode.UnlaodPIOInterlockTimeout );
  1532. if ( this.refObjects.Conveyor.IsDetectedLoadStart() || this.refObjects.Conveyor.IsDetectedCenter() ) //중간에 걸려 있다고 생각해서 알람 처리.
  1533. return 12; //Conveyor Moving Timeout
  1534. else
  1535. {
  1536. if ( this.refObjects.Conveyor.IsDetectedCenter() ) //Time Out 후 아직 Tray 가 있으면 다시 Clamp Lock.
  1537. {
  1538. result = this.refObjects.Clamp.Unlock_Sync();
  1539. if ( result != 0 )
  1540. {
  1541. this.OccurVehicleAlarm( result );
  1542. return result;
  1543. }
  1544. }
  1545. else
  1546. return 0;
  1547. }
  1548. }
  1549. if ( !this.refObjects.Conveyor.IsDetectedLoadStart() && !this.refObjects.Conveyor.IsDetectedCenter() )
  1550. {
  1551. if ( this.refObjects.IO.IsOn( "IN_PIO_RECEIVE_COMPLITE" ) )
  1552. {
  1553. loggerPIO.I( "[Port] - 3 Receive Complete On" );
  1554. break;
  1555. }
  1556. }
  1557. }
  1558. if ( !this.refObjects.Conveyor.IsDetectedCenter() )
  1559. this.OnCarrierDetected?.Invoke( false );
  1560. this.refObjects.Conveyor.OnOffConveyor( false ); //Stop
  1561. this.OnConveyorStop?.Invoke( false );
  1562. PIOClear();
  1563. this.refObjects.IO.WriteOutputIO( "OUT_PIO_SEND_COMPLITE", true );
  1564. Thread.Sleep( 1000 );
  1565. this.refObjects.IO.WriteOutputIO( "OUT_PIO_SEND_COMPLITE", false );
  1566. loggerPIO.I( "[Vehicle] - 3 Send Complete OnOff" );
  1567. #endif
  1568. loggerPIO.I( $"End Unload PIO - [{targetName}]" );
  1569. return 0;
  1570. }
  1571. void PIOClear()
  1572. {
  1573. string[] pio = { "OUT_PIO_READY", "OUT_PIO_SENDING_RUN", "OUT_PIO_SEND_COMPLITE", "OUT_PIO_RECEIVABLE", "OUT_PIO_RECEIVE_RUN", "OUT_PIO_RECIVE_COMPLITE", "OUT_PIO_INTERLOCK" };
  1574. pio.FwEach( x => { this.refObjects.IO.OutputOff( x ); } );
  1575. }
  1576. #endregion
  1577. #endregion
  1578. #region Help Method
  1579. Task taskHostConnection = null;
  1580. /// <summary>
  1581. /// Move 이후 OCS 연결을 확인 후 Disconnected 상태이면 5분 상태 확인 후 Alarm 발생.
  1582. /// </summary>
  1583. void CheckOCSConnectionState()
  1584. {
  1585. if ( this.taskHostConnection != null )
  1586. return;
  1587. if ( refObjects.HostManager.IsConnected )
  1588. return;
  1589. this.taskHostConnection = new Task( () =>
  1590. {
  1591. long sTime = SwUtils.CurrentTimeMillis;
  1592. while ( !refObjects.HostManager.IsConnected )
  1593. {
  1594. LockUtils.Wait( 100 );
  1595. if ( SwUtils.Gt( sTime, 30 * ConstUtils.ONE_SECOND ) )
  1596. {
  1597. OccurVehicleAlarm( 43 );
  1598. break;
  1599. }
  1600. }
  1601. } );
  1602. this.taskHostConnection = null;
  1603. }
  1604. void BatteryChargeStateLED( double percent )
  1605. {
  1606. if ( percent > 60 )
  1607. {
  1608. this.refObjects.IO.WriteOutputIO( "OUT_BATTERY_LED_00", true );
  1609. this.refObjects.IO.WriteOutputIO( "OUT_BATTERY_LED_01", true );
  1610. this.refObjects.IO.WriteOutputIO( "OUT_BATTERY_LED_02", true );
  1611. this.refObjects.IO.WriteOutputIO( "OUT_BATTERY_LED_03", true );
  1612. }
  1613. else if ( percent > 45 )
  1614. {
  1615. this.refObjects.IO.WriteOutputIO( "OUT_BATTERY_LED_00", true );
  1616. this.refObjects.IO.WriteOutputIO( "OUT_BATTERY_LED_01", true );
  1617. this.refObjects.IO.WriteOutputIO( "OUT_BATTERY_LED_02", true );
  1618. this.refObjects.IO.WriteOutputIO( "OUT_BATTERY_LED_03", false );
  1619. }
  1620. else if ( percent > 30 )
  1621. {
  1622. this.refObjects.IO.WriteOutputIO( "OUT_BATTERY_LED_00", true );
  1623. this.refObjects.IO.WriteOutputIO( "OUT_BATTERY_LED_01", true );
  1624. this.refObjects.IO.WriteOutputIO( "OUT_BATTERY_LED_02", false );
  1625. this.refObjects.IO.WriteOutputIO( "OUT_BATTERY_LED_03", false );
  1626. }
  1627. else
  1628. {
  1629. this.refObjects.IO.WriteOutputIO( "OUT_BATTERY_LED_00", true );
  1630. this.refObjects.IO.WriteOutputIO( "OUT_BATTERY_LED_01", false );
  1631. this.refObjects.IO.WriteOutputIO( "OUT_BATTERY_LED_02", false );
  1632. this.refObjects.IO.WriteOutputIO( "OUT_BATTERY_LED_03", false );
  1633. }
  1634. }
  1635. /// <summary>
  1636. /// 현재 Point 가 변경될때 장애물 감지 센서의 패턴을 변경한다.
  1637. /// </summary>
  1638. /// <param name="v"></param>
  1639. private void ObstaclePatternChange( int v )
  1640. {
  1641. if ( !RouteManager.Instance.Segments.Any( s => s.ID == v ) )
  1642. {
  1643. logger.E( "Current Tag Not Exist RouteManager Point List" );
  1644. return;
  1645. }
  1646. //Todo: 현재 Segment ID 를 가져 와서 변경하는 방식으로 변경 필요.
  1647. var obstacle = RouteManager.Instance.Obstacles.Where( o => o.segmentID == v ).Single();
  1648. this.ChgObstacleDetectPattern( obstacle.fieldset );
  1649. logger.D( $"[Obstacle Pattern Chg] - {obstacle.fieldset}" );
  1650. }
  1651. /// <summary>
  1652. /// 현재 좌표 값이 등록된 Route 에 맞는 위치인지 확인한다.
  1653. /// 판단 기준은 Route 에 Tolerance 범위를 사용.
  1654. /// </summary>
  1655. /// <param name="route"></param>
  1656. /// <param name="currentPosition"></param>
  1657. /// <returns></returns>
  1658. bool CorrectPosition( Route route, double currentPosition )
  1659. {
  1660. var rScale = route.ScaleValue;
  1661. var rTolerance = route.ScaleTolerance;
  1662. var result = currentPosition - rScale;
  1663. if ( rTolerance < Math.Abs( result ) )
  1664. return false;
  1665. return true;
  1666. }
  1667. /// <summary>
  1668. /// if no is zero, Laser Off
  1669. /// bit Off, On, On, On,On Area1
  1670. /// </summary>
  1671. /// <param name="no"> 0 == Off Laser</param>
  1672. /// <returns></returns>
  1673. public bool ChgObstacleDetectPattern( int no )
  1674. {
  1675. var bitArray = BitUtils.ChgBitArray( no );
  1676. int bitIndex = 0;
  1677. this.obstacleBitList.ForEach( b =>
  1678. {
  1679. if ( bitArray[bitIndex] )
  1680. this.refObjects.IO.OutputOff( b );
  1681. else
  1682. this.refObjects.IO.OutputOn( b );
  1683. bitIndex++;
  1684. } );
  1685. ObstaclePattern = no;
  1686. return true;
  1687. }
  1688. public int GetObstacleDetectPattern()
  1689. {
  1690. int bitIndex = 0;
  1691. BitArray bitArray = new BitArray( this.obstacleBitList.Count );
  1692. this.obstacleBitList.ForEach( b =>
  1693. {
  1694. if ( this.refObjects.IO.IsOn( b, false ) )
  1695. bitArray.Set( bitIndex, false );
  1696. else
  1697. bitArray.Set( bitIndex, true );
  1698. bitIndex++;
  1699. } );
  1700. return BitUtils.ChgInt32( bitArray );
  1701. }
  1702. /// <summary>
  1703. /// Vehicle 이동 및 동작 중 Alarm 발생 시 처리
  1704. /// </summary>
  1705. /// <param name="alarmID"></param>
  1706. public void OccurVehicleAlarm( int alarmID )
  1707. {
  1708. var alarm = refObjects.Alarms.Where( x => x.AlarmId == alarmID ).FirstOrDefault();
  1709. if ( alarm != null )
  1710. {
  1711. if ( alarm.Level == eAlarmLevel.Warn )
  1712. {
  1713. HisAlarm hisAlarm = new HisAlarm();
  1714. hisAlarm.AlarmId = alarmID;
  1715. hisAlarm.Text = alarm.Name + " - " + alarm.Text;
  1716. hisAlarm.Solution = alarm.Solution;
  1717. var clone = ObjectCopyUtils.DeepClone<Alarm>( alarm );
  1718. this.refObjects.Sqlite.HisAlarmDAL.Insert( hisAlarm );
  1719. return;
  1720. }
  1721. }
  1722. this.MachineMode = eMachineMode.LocalMode;
  1723. this.VehicleStateProperty = eVehicleState.Abnormal;
  1724. this.ConveyorOff();
  1725. this.refObjects.AutoManager.ProcessAlarm( alarmID );
  1726. }
  1727. public void SetObstaclePattern( ObstacleControlEventArgs.eControlKind state, int value )
  1728. {
  1729. if ( state == ObstacleControlEventArgs.eControlKind.DRIVE )
  1730. {
  1731. this.ObstacleDrive = value;
  1732. ChgObstacleDetectPattern( this.ObstacleDrive );
  1733. }
  1734. else if ( state == ObstacleControlEventArgs.eControlKind.CURVE )
  1735. {
  1736. this.ObstacleCurve = value;
  1737. ChgObstacleDetectPattern( this.ObstacleCurve );
  1738. }
  1739. else
  1740. return;
  1741. }
  1742. public eSteeringState GetESteeringState() => this.refObjects.Steering.GetSteeringState();
  1743. #endregion
  1744. #region Event Subscribe
  1745. private void BMUManager_OnDisconnect( string obj )
  1746. {
  1747. this.BatteryIsConnect = false;
  1748. this.OccurVehicleAlarm( 32 );
  1749. }
  1750. private void BMUManager_OnConnect( string obj )
  1751. {
  1752. this.BatteryIsConnect = true;
  1753. //ReqCurrentPos();
  1754. }
  1755. private void BMUManager_OnFirstColtd( List<ReceivedData> obj )
  1756. {
  1757. }
  1758. private void BMUManager_OnChangedReceivedData( Serial.DataModel.ReceivedData obj )
  1759. {
  1760. var kind = CastTo<eDataKind>.From<Enum>( obj.DataKind );
  1761. switch ( kind )
  1762. {
  1763. case eDataKind.Voltage:
  1764. this.BatteryVoltage = (double)obj.Value;
  1765. break;
  1766. case eDataKind.Current:
  1767. this.BatteryCurrent = (double)obj.Value;
  1768. if ( BatteryCurrent > 3 )
  1769. this.BatteryChargeState = true;
  1770. else
  1771. this.BatteryChargeState = false;
  1772. break;
  1773. case eDataKind.BatteryState:
  1774. this.BatteryState = (double)obj.Value;
  1775. break;
  1776. case eDataKind.ChargeCompleteTime:
  1777. this.BatteryChargeTime = (double)obj.Value;
  1778. break;
  1779. case eDataKind.DisChargeCompleteTime:
  1780. this.BatteryDisChargeTime = (double)obj.Value;
  1781. break;
  1782. case eDataKind.SOC:
  1783. this.BatteryStateOfCharge = (double)obj.Value;
  1784. break;
  1785. case eDataKind.SOH:
  1786. this.BatteryStateOfHealth = (double)obj.Value;
  1787. break;
  1788. case eDataKind.ResidualCapacity:
  1789. this.BatteryCapacity = (double)obj.Value;
  1790. break;
  1791. case eDataKind.ResidualEnergy:
  1792. this.BatteryEnergy = (double)obj.Value;
  1793. break;
  1794. case eDataKind.Temperature:
  1795. this.BatteryTemperature = (double)obj.Value;
  1796. break;
  1797. default:
  1798. break;
  1799. }
  1800. }
  1801. private void AutoManager_OnOperationModeChanged( eOperatationMode obj )
  1802. {
  1803. this.refObjects.Drive.SetDriveOperationMode( obj );
  1804. }
  1805. private void ZmqManager_PropertyChanged( object sender, System.ComponentModel.PropertyChangedEventArgs e )
  1806. {
  1807. var property = sender.GetType().GetProperty( e.PropertyName );
  1808. var newValue = property.GetValue( sender, null );
  1809. switch ( e.PropertyName )
  1810. {
  1811. case "SegmentID":
  1812. {
  1813. var v = CastTo<int>.From<object>( newValue );
  1814. this.ObstaclePatternChange( v );
  1815. }
  1816. break;
  1817. case "RequestSteering":
  1818. {
  1819. var v = CastTo<eSteeringState>.From<object>( newValue );
  1820. switch ( v )
  1821. {
  1822. case eSteeringState.None:
  1823. break;
  1824. case eSteeringState.Left:
  1825. this.refObjects.Steering.ControlSteering( true );
  1826. break;
  1827. case eSteeringState.Right:
  1828. this.refObjects.Steering.ControlSteering();
  1829. break;
  1830. default:
  1831. break;
  1832. }
  1833. logger.D( $"[Request Steering] - {v}" );
  1834. }
  1835. break;
  1836. case "CurrentPointNo":
  1837. {
  1838. var v = CastTo<int>.From<object>( newValue );
  1839. logger.D( $"{this.CurrentTag} -> {v}" );
  1840. this.CurrentTag = v;
  1841. }
  1842. break;
  1843. case "RearDriveState":
  1844. {
  1845. var v = CastTo<DriveState>.From<object>( newValue );
  1846. this.RearDriveState = v;
  1847. }
  1848. break;
  1849. case "FrontLoadFactor":
  1850. {
  1851. var v = CastTo<double>.From<object>( newValue );
  1852. this.FrontLoadFactor = v;
  1853. this.FrontTorque = Math.Truncate( ( ( v * 1.9 ) / 1000 ) * 100 ) / 100;
  1854. }
  1855. break;
  1856. case "FrontRPM":
  1857. {
  1858. var v = CastTo<double>.From<object>( newValue );
  1859. this.FrontRpm = v;
  1860. var ll = ( ( ( ( v / 60 ) * ( 2 * Math.PI ) ) * 0.06 ) / 10 );
  1861. this.FrontSpeed = Math.Truncate( ll * 100 ) / 100;
  1862. }
  1863. break;
  1864. case "RearLoadFactor":
  1865. {
  1866. var v = CastTo<double>.From<object>( newValue );
  1867. this.RearLoadFactor = v;
  1868. this.RearTorque = Math.Truncate( ( ( v * 1.9 ) / 1000 ) * 100 ) / 100;
  1869. }
  1870. break;
  1871. case "RearRPM":
  1872. {
  1873. var v = CastTo<double>.From<object>( newValue );
  1874. this.RearRpm = v;
  1875. var ll = ( ( ( ( v / 60 ) * ( 2 * Math.PI ) ) * 0.06 ) / 10 );
  1876. this.RearSpeed = Math.Truncate( ll * 100 ) / 100;
  1877. }
  1878. break;
  1879. case "AutoReadyState":
  1880. {
  1881. var v = CastTo<eVehicleAutoReadyState>.From<object>(newValue);
  1882. this.AutoReadyState = v;
  1883. }
  1884. break;
  1885. case "LinearSpeed":
  1886. {
  1887. this.LinearSpeed = CastTo<double>.From<object>(newValue);
  1888. }
  1889. break;
  1890. case "CurveSpeed":
  1891. {
  1892. this.CurveSpeed = CastTo<double>.From<object>(newValue);
  1893. }
  1894. break;
  1895. case "JogSPeed":
  1896. {
  1897. this.JogSPeed = CastTo<double>.From<object>(newValue);
  1898. }
  1899. break;
  1900. case "AccelSpeed":
  1901. {
  1902. this.AccelSpeed = CastTo<double>.From<object>(newValue);
  1903. }
  1904. break;
  1905. case "DecelSpeed":
  1906. {
  1907. this.DecelSpeed = CastTo<double>.From<object>(newValue);
  1908. }
  1909. break;
  1910. case "CreepSpeed":
  1911. {
  1912. this.CreepSpeed = CastTo<double>.From<object>(newValue);
  1913. }
  1914. break;
  1915. case "CreepDistance":
  1916. {
  1917. this.CreepDistance = CastTo<double>.From<object>(newValue);
  1918. }
  1919. break;
  1920. default:
  1921. break;
  1922. }
  1923. }
  1924. private void Motion_PropertyChanged( object sender, System.ComponentModel.PropertyChangedEventArgs e )
  1925. {
  1926. var property = sender.GetType().GetProperty( e.PropertyName );
  1927. var newValue = property.GetValue( sender, null );
  1928. switch ( e.PropertyName )
  1929. {
  1930. case "CurrentPos":
  1931. {
  1932. var v = CastTo<double>.From<object>( newValue );
  1933. this.CurrentPosition = v;
  1934. }
  1935. break;
  1936. //case "CurrentTag":
  1937. // {
  1938. // var v = CastTo<int>.From<object>( newValue );
  1939. // logger.D( $"{this.CurrentTag} -> {v}" );
  1940. // this.CurrentTag = v;
  1941. // }
  1942. // break;
  1943. case "CurrentSpeed":
  1944. {
  1945. var v = CastTo<double>.From<object>( newValue );
  1946. this.CurrentSpeed = v;
  1947. }
  1948. break;
  1949. case "CurrentTorque":
  1950. {
  1951. var v = CastTo<double>.From<object>( newValue );
  1952. this.CurrentTorque = v;
  1953. }
  1954. break;
  1955. case "ReqSteeringState":
  1956. //{
  1957. // var v = CastTo<eSteeringState>.From<object>( newValue );
  1958. // switch ( v )
  1959. // {
  1960. // case eSteeringState.None:
  1961. // break;
  1962. // case eSteeringState.Left:
  1963. // this.refObjects.Steering.ControlSteering( true );
  1964. // break;
  1965. // case eSteeringState.Right:
  1966. // this.refObjects.Steering.ControlSteering();
  1967. // break;
  1968. // default:
  1969. // break;
  1970. // }
  1971. //}
  1972. break;
  1973. case "DriveServoState":
  1974. {
  1975. var v = CastTo<eDriveServoState>.From<object>( newValue );
  1976. if ( v == eDriveServoState.ServoOn )
  1977. this.refObjects.IO.OutputOn( "OUT_DRIVE_BRAKE_OFF" );
  1978. else
  1979. this.refObjects.IO.OutputOff( "OUT_DRIVE_BRAKE_OFF" );
  1980. }
  1981. break;
  1982. case "FrontDriveState":
  1983. {
  1984. var v = CastTo<DriveState>.From<object>( newValue );
  1985. this.FrontDriveState = v;
  1986. }
  1987. break;
  1988. case "RearDriveState":
  1989. {
  1990. var v = CastTo<DriveState>.From<object>( newValue );
  1991. this.RearDriveState = v;
  1992. }
  1993. break;
  1994. default:
  1995. break;
  1996. }
  1997. }
  1998. private void Steering_PropertyChanged( object sender, System.ComponentModel.PropertyChangedEventArgs e )
  1999. {
  2000. var property = sender.GetType().GetProperty( e.PropertyName );
  2001. var newValue = property.GetValue( sender, null );
  2002. //Todo: 나중에 Test 하자
  2003. //var ownPropperty = this.GetType().GetProperty(e.PropertyName);
  2004. if ( e.PropertyName.Equals( "SteeringState" ) )
  2005. {
  2006. var v = CastTo<eSteeringState>.From<object>( newValue );
  2007. this.SteeringState = v;
  2008. logger.D( $"steering - {v}" );
  2009. }
  2010. }
  2011. private void Clamp_PropertyChanged( object sender, System.ComponentModel.PropertyChangedEventArgs e )
  2012. {
  2013. var property = sender.GetType().GetProperty( e.PropertyName );
  2014. var newValue = property.GetValue( sender, null );
  2015. if ( e.PropertyName.Equals( "ClampState" ) )
  2016. {
  2017. var v = CastTo<eClampState>.From<object>( newValue );
  2018. this.ClampState = v;
  2019. }
  2020. }
  2021. private void IO_OnChangedIO( BitBlock bit )
  2022. {
  2023. switch ( bit.Tag )
  2024. {
  2025. case "IN_CV_DETECT_01":
  2026. this.IsContain = bit.IsBitOn;
  2027. this.refObjects.ZmqManager.Publish( "Contain", this.IsContain.ToString() );
  2028. break;
  2029. case "IN_MC_ON":
  2030. if ( bit.IsBitOn )
  2031. {
  2032. if ( !this.refObjects.IO.IsOn( "IN_EMS_SW" ) && this.refObjects.IO.IsOn( "IN_CP_ON_SAFETY" ) && this.refObjects.IO.IsOn( "IN_CP_ON_24V" ) )
  2033. this.VehicleStateProperty = eVehicleState.Idle;
  2034. }
  2035. else
  2036. {
  2037. if ( this.ObstacleStateProperty == eObstacleState.Abnormal )
  2038. this.OccurVehicleAlarm( 42 );
  2039. else
  2040. this.OccurVehicleAlarm( 29 );
  2041. }
  2042. break;
  2043. case "IN_EMS_SW":
  2044. if ( bit.IsBitOn )
  2045. this.OccurVehicleAlarm( 28 );
  2046. break;
  2047. case "IN_CP_ON_SAFETY":
  2048. if ( !bit.IsBitOn )
  2049. this.OccurVehicleAlarm( 31 );
  2050. break;
  2051. case "IN_CP_ON_24V":
  2052. if ( !bit.IsBitOn )
  2053. this.OccurVehicleAlarm( 30 );
  2054. break;
  2055. case "IN_OBSTRUCTION_DETECT_ERROR":
  2056. case "IN_OBSTRUCTION_DETECT_SAFETY":
  2057. case "IN_OBSTRUCTION_DETECT_STOP":
  2058. case "IN_OBSTRUCTION_DETECT_SLOW":
  2059. CheckObstacle();
  2060. break;
  2061. case "IN_BUMPER_DETECT":
  2062. if ( bit.IsBitOn )
  2063. this.refObjects.ZmqManager.SetSafetyBumper();
  2064. break;
  2065. default:
  2066. break;
  2067. }
  2068. }
  2069. private void Steering_OnSteeringError( object sender, int e )
  2070. {
  2071. if ( e != 0 )
  2072. {
  2073. logger.E( $"[Steering] - Control Error {e}" );
  2074. this.OccurVehicleAlarm( e );
  2075. }
  2076. else
  2077. {
  2078. var msg = new DriveControlEventArgs()
  2079. {
  2080. EventDir = DriveControlEventArgs.eEventDir.ToFront,
  2081. ControlKind = DriveControlEventArgs.eControlKind.Steering,
  2082. Result = FluentResults.Results.Ok<DriveControlEventArgs.eMoveDir>( DriveControlEventArgs.eMoveDir.LEFT ),
  2083. };
  2084. this.eventAggregator.GetEvent<DriveControlPubSubEvent>().Publish( msg );
  2085. }
  2086. }
  2087. #endregion
  2088. }
  2089. }