Vehicle.cs 64 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933
  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.DB;
  21. using VehicleControlSystem.ControlLayer.Drive;
  22. using VehicleControlSystem.ControlLayer.IO;
  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. /// <summary>
  30. /// Control Layer 의 자원을 여기서 사용하자.
  31. /// </summary>
  32. public class Vehicle : ControlObjectBase, IDisposable
  33. {
  34. /// <summary>
  35. /// OCS Report Code
  36. /// 목적지에 도착해서 Load, Unload 시 발생하는 Alarm
  37. /// </summary>
  38. public enum eFailCode
  39. {
  40. Load_PortHasNotCarrier = 1,
  41. Load_VehicleHasCarrier,
  42. Unload_PortHasCarrier,
  43. Unload_VehicleHasNotCarrier,
  44. LoadPIOInterlockTimeout,
  45. UnlaodPIOInterlockTimeout,
  46. }
  47. static Logger logger = Logger.GetLogger();
  48. static Logger loggerPIO = Logger.GetLogger( "PIO" );
  49. #region Properties
  50. /// <summary>
  51. /// Tag 위치
  52. /// </summary>
  53. private string currentTag = "0000";
  54. public string CurrentTag
  55. {
  56. get { return currentTag; }
  57. set
  58. {
  59. if ( SetField( ref this.currentTag, value ) )
  60. {
  61. var info = sql.VehicleInfoDAL.GetInfo();
  62. info.CurrentTag = value;
  63. sql.VehicleInfoDAL.Update( info );
  64. this.OnCurrentTagChanged?.Invoke( value );
  65. }
  66. }
  67. }
  68. /// <summary>
  69. /// Scale Value
  70. /// </summary>
  71. private double currentPosition;
  72. public double CurrentPosition
  73. {
  74. get { return currentPosition; }
  75. set
  76. {
  77. if ( SetField( ref this.currentPosition, value ) )
  78. {
  79. }
  80. }
  81. }
  82. private double currentSpeed;
  83. public double CurrentSpeed
  84. {
  85. get { return currentSpeed; }
  86. set { SetField( ref this.currentSpeed, value ); }
  87. }
  88. private double currentTorque;
  89. public double CurrentTorque
  90. {
  91. get { return currentTorque; }
  92. set { SetField( ref this.currentTorque, value ); }
  93. }
  94. private bool isContain;
  95. public bool IsContain
  96. {
  97. get { return isContain; }
  98. set { SetField( ref this.isContain, value ); }
  99. }
  100. eClampState _clampState;
  101. public eClampState ClampState
  102. {
  103. get { return this._clampState; }
  104. set { this.SetField( ref this._clampState, value ); }
  105. }
  106. private eSteeringState steeringState;
  107. public eSteeringState SteeringState
  108. {
  109. get { return steeringState; }
  110. set
  111. {
  112. if ( SetField( ref this.steeringState, value ) )
  113. {
  114. Redis.Instance.SetActualSteeringPos( value );
  115. }
  116. }
  117. }
  118. private int _obstacleDrive;
  119. public int ObstacleDrive { get { return this._obstacleDrive; } set { SetField( ref this._obstacleDrive, value ); } }
  120. private int _obstacleCurve;
  121. public int ObstacleCurve { get { return this._obstacleCurve; } set { SetField( ref this._obstacleCurve, value ); } }
  122. private int obstacleCurrent;
  123. public int ObstacleCurrent { get { return this.ObstacleCurrent; } set { SetField( ref this.obstacleCurrent, value ); } }
  124. private eObstacleState obstacleState = eObstacleState.Normal;
  125. public eObstacleState ObstacleStateProperty
  126. {
  127. get { return obstacleState; }
  128. set
  129. {
  130. if ( SetField( ref this.obstacleState, value ) )
  131. {
  132. if ( value == eObstacleState.Blocked )
  133. this.VehicleStateProperty = eVehicleState.Blocked;
  134. }
  135. }
  136. }
  137. private eVehicleState vehicleState = eVehicleState.None;
  138. public eVehicleState VehicleStateProperty
  139. {
  140. get { return vehicleState; }
  141. set
  142. {
  143. if ( SetField( ref this.vehicleState, value ) )
  144. {
  145. var info = sql.VehicleInfoDAL.GetInfo();
  146. info.VehicleState = value;
  147. sql.VehicleInfoDAL.Update( info );
  148. }
  149. }
  150. }
  151. private eMachineMode machineMode = eMachineMode.LocalMode;
  152. public eMachineMode MachineMode
  153. {
  154. get { return machineMode; }
  155. set
  156. {
  157. if ( SetField( ref this.machineMode, value ) )
  158. {
  159. var info = sql.VehicleInfoDAL.GetInfo();
  160. info.MachineMode = value;
  161. sql.VehicleInfoDAL.Update( info );
  162. }
  163. }
  164. }
  165. private int obstaclePattern;
  166. public int ObstaclePattern
  167. {
  168. get { return obstaclePattern; }
  169. set { SetField( ref this.obstaclePattern, value ); }
  170. }
  171. private DriveState frontDriveState;
  172. public DriveState FrontDriveState
  173. {
  174. get { return frontDriveState; }
  175. set { SetField( ref this.frontDriveState, value ); }
  176. }
  177. private DriveState rearDriveState;
  178. public DriveState RearDriveState
  179. {
  180. get { return rearDriveState; }
  181. set { SetField( ref this.rearDriveState, value ); }
  182. }
  183. //이동
  184. public bool Busy
  185. {
  186. get
  187. {
  188. return this.CurrentSubCommand == null ? false : true;
  189. }
  190. set { }
  191. }
  192. public bool IsMoving { get; set; }
  193. #region Battery Property
  194. double batteryVoltage;
  195. public double BatteryVoltage
  196. {
  197. get { return this.batteryVoltage; }
  198. set { this.SetField( ref this.batteryVoltage, value ); }
  199. }
  200. double batteryCurrent;
  201. public double BatteryCurrent
  202. {
  203. get { return this.batteryCurrent; }
  204. set { this.SetField( ref this.batteryCurrent, value ); }
  205. }
  206. double batteryState;
  207. public double BatteryState
  208. {
  209. get { return this.batteryState; }
  210. set { this.SetField( ref this.batteryState, value ); }
  211. }
  212. double batteryChargeTime;
  213. public double BatteryChargeTime
  214. {
  215. get { return this.batteryChargeTime; }
  216. set { this.SetField( ref this.batteryChargeTime, value ); }
  217. }
  218. double batteryDisChargeTime;
  219. public double BatteryDisChargeTime
  220. {
  221. get { return this.batteryDisChargeTime; }
  222. set { this.SetField( ref this.batteryDisChargeTime, value ); }
  223. }
  224. double batteryStateOfCharge;
  225. public double BatteryStateOfCharge
  226. {
  227. get { return this.batteryStateOfCharge; }
  228. set { this.SetField( ref this.batteryStateOfCharge, value ); }
  229. }
  230. double batteryStateOfHealth;
  231. public double BatteryStateOfHealth
  232. {
  233. get { return this.batteryStateOfHealth; }
  234. set { this.SetField( ref this.batteryStateOfHealth, value ); }
  235. }
  236. double batteryCapacity;
  237. public double BatteryCapacity
  238. {
  239. get { return this.batteryCapacity; }
  240. set { this.SetField( ref this.batteryCapacity, value ); }
  241. }
  242. double batteryEnergy;
  243. public double BatteryEnergy
  244. {
  245. get { return this.batteryEnergy; }
  246. set { this.SetField( ref this.batteryEnergy, value ); }
  247. }
  248. double batteryTemperature;
  249. public double BatteryTemperature
  250. {
  251. get { return this.batteryTemperature; }
  252. set { this.SetField( ref this.batteryTemperature, value ); }
  253. }
  254. bool batteryIsConnect;
  255. public bool BatteryIsConnect
  256. {
  257. get
  258. {
  259. return batteryIsConnect;
  260. }
  261. set { this.SetField( ref this.batteryIsConnect, value ); }
  262. }
  263. #endregion
  264. public bool IsError { get; set; }
  265. public SubCmd CurrentSubCommand { get; private set; }
  266. #endregion
  267. #region Event
  268. public event Action OnMoveReady;
  269. public event Action OnMoving;
  270. public event Action OnMoveFinish;
  271. public event Action OnChargingStart;
  272. public event Action OnCharging;
  273. public event Action OnChargingFull;
  274. public event Action<double> OnBatteryVelueChanged;
  275. public event Action<bool> OnPIOStart;
  276. public event Action<bool> OnConveyorStart;
  277. public event Action<bool> OnConveyorStop;
  278. public event Action<bool> OnCarrierDetected;
  279. public event Action OnLoadComplete;
  280. public event Action OnUnloadComplete;
  281. public event Action<string> OnCurrentTagChanged;
  282. public event Action OnManualMove;
  283. public event Action OnManualLoad;
  284. public event Action OnManualUnload;
  285. public event Action OnManualCharging;
  286. public event Action<eFailCode> OnFailReport;
  287. #endregion
  288. #region List.
  289. List<ICylinder> cylinders = new List<ICylinder>();
  290. List<string> obstacleBitList = new List<string>();
  291. #endregion
  292. EzIO iO = null;
  293. GSIDrive drive = null;
  294. SqliteManager sql = null;
  295. Clamp clamp = null;
  296. Steering steering = null;
  297. AutoManager autoManager = null;
  298. BMUManager bMUManager = null;
  299. private Conveyor conveyor = null;
  300. ThreadCancel cancel = new ThreadCancel();
  301. TaskCancel taskCancel = new TaskCancel();
  302. TaskCancel taskMoveCancel = new TaskCancel();
  303. IEventAggregator eventAggregator;
  304. public Vehicle( IIO io, SqliteManager sqliteManager, IEventAggregator ea, AutoManager auto )
  305. {
  306. this.iO = io as EzIO;
  307. this.iO.OnChangedIO += IO_OnChangedIO;
  308. this.sql = sqliteManager;
  309. this.autoManager = auto;
  310. this.autoManager.OnOperationModeChanged += AutoManager_OnOperationModeChanged;
  311. this.obstacleBitList.AddRange( new string[]
  312. {
  313. "OUT_OBSTRUCTION_PATTERN_00",
  314. "OUT_OBSTRUCTION_PATTERN_01",
  315. "OUT_OBSTRUCTION_PATTERN_02",
  316. "OUT_OBSTRUCTION_PATTERN_03",
  317. "OUT_OBSTRUCTION_PATTERN_04",
  318. } );
  319. this.eventAggregator = ea;
  320. /*Drive*/
  321. this.eventAggregator.GetEvent<DriveControlPubSubEvent>().Unsubscribe( ReceiveDriveControlEvent );
  322. this.eventAggregator.GetEvent<DriveControlPubSubEvent>().Subscribe( ReceiveDriveControlEvent );
  323. this.eventAggregator.GetEvent<ObstacleControlPubSubEvent>().Unsubscribe( ObstacleReceiveEvent );
  324. this.eventAggregator.GetEvent<ObstacleControlPubSubEvent>().Subscribe( ObstacleReceiveEvent );
  325. }
  326. private void ObstacleReceiveEvent( ObstacleControlEventArgs obj )
  327. {
  328. if ( this.autoManager.OperationModeProperty != eOperatationMode.ManualMode )
  329. return;
  330. if ( obj.EventDir == ObstacleControlEventArgs.eEventDir.ToBack )
  331. {
  332. switch ( obj.ControlKind )
  333. {
  334. case ObstacleControlEventArgs.eControlKind.NONE:
  335. break;
  336. case ObstacleControlEventArgs.eControlKind.DRIVE:
  337. //this.ChgObstacleDetectPattern( new Random().Next( 0 , 40 ) );
  338. break;
  339. case ObstacleControlEventArgs.eControlKind.CURVE:
  340. //this.ChgObstacleDetectPattern( new Random().Next( 0 , 40 ) );
  341. break;
  342. case ObstacleControlEventArgs.eControlKind.STATE:
  343. //var value = this.GetObstacleDetectPattern();
  344. break;
  345. case ObstacleControlEventArgs.eControlKind.INFO:
  346. {
  347. var msg = new ObstacleControlEventArgs
  348. {
  349. ControlKind = ObstacleControlEventArgs.eControlKind.INFO,
  350. Drive = this.ObstacleDrive,
  351. Curve = this.ObstacleCurve,
  352. Current = this.GetObstacleDetectPattern(),
  353. ObstacleState = this.ObstacleStateProperty.ToString()
  354. };
  355. this.ObstacleControlEventPublish( msg );
  356. }
  357. break;
  358. case ObstacleControlEventArgs.eControlKind.SAVE:
  359. {
  360. this.ObstacleCurve = obj.Curve;
  361. this.ObstacleDrive = obj.Drive;
  362. var reply = new ObstacleControlEventArgs
  363. {
  364. ControlKind = ObstacleControlEventArgs.eControlKind.SAVE
  365. };
  366. reply.Result = Results.Ok( ObstacleControlEventArgs.eControlKind.SAVE );
  367. this.ObstacleControlEventPublish( reply );
  368. }
  369. break;
  370. }
  371. }
  372. }
  373. private void ObstacleControlEventPublish( ObstacleControlEventArgs args )
  374. {
  375. args.EventDir = ObstacleControlEventArgs.eEventDir.ToFront;
  376. this.eventAggregator.GetEvent<ObstacleControlPubSubEvent>().Publish( args );
  377. }
  378. private void ReceiveDriveControlEvent( DriveControlEventArgs _args )
  379. {
  380. if ( this.autoManager.OperationModeProperty != eOperatationMode.ManualMode )
  381. return;
  382. var msg = _args;
  383. if ( msg.EventDir == DriveControlEventArgs.eEventDir.ToBack )
  384. {
  385. switch ( msg.ControlKind )
  386. {
  387. case DriveControlEventArgs.eControlKind.MOVE:
  388. this.ReqMoveToPos( _args );
  389. break;
  390. case DriveControlEventArgs.eControlKind.STOP:
  391. break;
  392. case DriveControlEventArgs.eControlKind.Steering:
  393. if ( msg.MoveDir == DriveControlEventArgs.eMoveDir.LEFT )
  394. this.steering.ControlSteering( true );
  395. else
  396. this.steering.ControlSteering();
  397. break;
  398. case DriveControlEventArgs.eControlKind.SteeringState:
  399. {
  400. var reply = new DriveControlEventArgs();
  401. reply.ControlKind = DriveControlEventArgs.eControlKind.SteeringState;
  402. if ( this.steering.IsLeft() )
  403. {
  404. reply.Args = eSteeringState.Left;
  405. reply.Result = FluentResults.Results.Ok();
  406. }
  407. else if ( this.steering.IsRight() )
  408. {
  409. reply.Args = eSteeringState.Right;
  410. reply.Result = FluentResults.Results.Ok();
  411. }
  412. else
  413. reply.Result = FluentResults.Results.Fail( new Error() );
  414. this.DriveControlEventPublish( reply );
  415. }
  416. break;
  417. case DriveControlEventArgs.eControlKind.ReqCurrentPos:
  418. //this.ReqCurrentPos();
  419. break;
  420. case DriveControlEventArgs.eControlKind.ReqStopCurrentPos:
  421. //this.taskCancel.Cancel();
  422. //this.taskCancel.WaitAll();
  423. break;
  424. case DriveControlEventArgs.eControlKind.FaultReset:
  425. this.ReqFaultReset( _args );
  426. break;
  427. case DriveControlEventArgs.eControlKind.DriveON:
  428. this.ReqDriveOn( _args );
  429. break;
  430. case DriveControlEventArgs.eControlKind.DriveOFF:
  431. this.ReqDriveOff( _args );
  432. break;
  433. case DriveControlEventArgs.eControlKind.JOG:
  434. this.ReqJog( _args );
  435. break;
  436. case DriveControlEventArgs.eControlKind.VehicleState:
  437. ReqVehicleState( _args );
  438. break;
  439. default:
  440. break;
  441. }
  442. }
  443. }
  444. public void ReqConveyorMove( string dir )
  445. {
  446. if ( dir.Equals( "CW" ) )
  447. this.conveyor.OnOffConveyor( true, false );
  448. else if ( dir.Equals( "CCW" ) )
  449. this.conveyor.OnOffConveyor( true, true );
  450. else if ( dir.Equals( "STOP" ) )
  451. this.conveyor.OnOffConveyor( false, false );
  452. }
  453. private void DriveControlEventPublish( DriveControlEventArgs args )
  454. {
  455. args.EventDir = DriveControlEventArgs.eEventDir.ToFront;
  456. this.eventAggregator.GetEvent<DriveControlPubSubEvent>().Publish( args );
  457. }
  458. public void Init()
  459. {
  460. this.CreateClamp();
  461. this.CreateSteering();
  462. this.CreateDrive();
  463. this.CreateBMUManager();
  464. this.CreateConveyor();
  465. ThreadStart();
  466. //TimerUtils.Once(5000, () => { this.CurrentPosition = 1000; });
  467. var v = sql.VehicleInfoDAL.GetInfo();
  468. v.CurrentTag = "0000";
  469. v.VehicleState = eVehicleState.None;
  470. v.MachineMode = eMachineMode.LocalMode;
  471. sql.VehicleInfoDAL.Update( v );
  472. }
  473. public int InitializationVehicle()
  474. {
  475. #if SIMULATION
  476. this.VehicleStateProperty = eVehicleState.Idle;
  477. return 0;
  478. #else
  479. int result = 0;
  480. if ( this.conveyor.IsDetectedCenter() ) //자제가 있으면 Lock
  481. result = this.clamp.Lock_Sync();
  482. else
  483. result = this.clamp.Unlock_Sync();
  484. if ( this.drive.IsErrorOn )
  485. return 22;
  486. this.VehicleStateProperty = eVehicleState.Idle;
  487. return result;
  488. #endif
  489. }
  490. public void Dispose()
  491. {
  492. this.cancel.Cancel();
  493. this.cancel.StopWaitAll();
  494. this.bMUManager.Disconnect();
  495. this.drive.Dispose();
  496. }
  497. #region Request Method
  498. private void ReqVehicleState( DriveControlEventArgs args )
  499. {
  500. VehicleInfo state = new VehicleInfo();
  501. state.CurrentPosition = this.CurrentPosition;
  502. state.CurrentSpeed = this.CurrentSpeed;
  503. state.CurrentTag = this.CurrentTag;
  504. state.CurrentTorque = this.CurrentTorque;
  505. var msg = new DriveControlEventArgs();
  506. msg.ControlKind = args.ControlKind;
  507. msg.Args = state;
  508. DriveControlEventPublish( msg );
  509. }
  510. private void ReqMoveToPos( DriveControlEventArgs args )
  511. {
  512. //var result = drive.Move( args.PositionTag );
  513. //this.MoveTo( "1111" );
  514. var reply = new DriveControlEventArgs();
  515. int targetTag = args.TargetRouteID;
  516. var route = sql.RouteDal.GetK( targetTag );
  517. if ( route == null )
  518. {
  519. reply.Result = Results.Fail( "Not Found Route" );
  520. this.DriveControlEventPublish( reply );
  521. return;
  522. }
  523. this.MoveTo( route.Name );
  524. reply.Result = Results.Ok( "Position Move" );
  525. this.DriveControlEventPublish( reply );
  526. }
  527. void ReqFaultReset( DriveControlEventArgs _args )
  528. {
  529. var drive = 0;
  530. //var result = drive.ResetAmpFault();
  531. var msg = new DriveControlEventArgs
  532. {
  533. ControlKind = DriveControlEventArgs.eControlKind.FaultReset
  534. };
  535. msg.Result = Results.Ok( "Drive On" );
  536. this.DriveControlEventPublish( msg );
  537. }
  538. void ReqJog( DriveControlEventArgs _args )
  539. {
  540. if ( _args.JogDir == DriveControlEventArgs.eJogMoveDir.Positive )
  541. {
  542. //this.drive.JogForWard();
  543. }
  544. else
  545. {
  546. //this.drive.JogBackward();
  547. }
  548. }
  549. void ReqCurrentPos()
  550. {
  551. var task = Task.Factory.StartNew( () =>
  552. {
  553. while ( !this.taskCancel.Canceled )
  554. {
  555. LockUtils.Wait( 500 );
  556. var msg = new DriveControlEventArgs
  557. {
  558. EventDir = DriveControlEventArgs.eEventDir.ToFront,
  559. ControlKind = DriveControlEventArgs.eControlKind.ReqCurrentPos,
  560. CurrentPosition = new Random().Next( 0, 1000 ),
  561. };
  562. this.DriveControlEventPublish( msg );
  563. }
  564. } );
  565. this.taskCancel.Add( task );
  566. }
  567. void ReqDriveOn( DriveControlEventArgs _args )
  568. {
  569. var drive = "Drive Name";
  570. //drive.On();
  571. var msg = new DriveControlEventArgs
  572. {
  573. ControlKind = DriveControlEventArgs.eControlKind.DriveON
  574. };
  575. msg.Result = Results.Ok( "Drive On" );
  576. this.DriveControlEventPublish( msg );
  577. }
  578. void ReqDriveOff( DriveControlEventArgs _args )
  579. {
  580. var drive = "Drive Name";
  581. //drive.Off();
  582. var msg = new DriveControlEventArgs
  583. {
  584. ControlKind = DriveControlEventArgs.eControlKind.DriveOFF
  585. };
  586. msg.Result = Results.Ok( "Drive On" );
  587. this.DriveControlEventPublish( msg );
  588. }
  589. #endregion
  590. #region Thread
  591. void ThreadStart()
  592. {
  593. this.cancel.AddGo( new Action( this._ThSubCmdWorker ) );
  594. this.cancel.AddGo( new Action( this._ThVehicleStateCheck ) );
  595. }
  596. //장애물 감지 Thread
  597. //장애물 감지 패턴 변경도 여기 하자.
  598. private void _ThVehicleStateCheck()
  599. {
  600. while ( !this.cancel.Canceled )
  601. {
  602. try
  603. {
  604. if ( this.autoManager.OperationModeProperty == eOperatationMode.AutoMode )
  605. this.CheckObstacle();
  606. this.CheckIOState();
  607. }
  608. catch ( ThreadInterruptedException threadInterruptedException )
  609. {
  610. }
  611. catch ( Exception exception )
  612. {
  613. logger.E( exception );
  614. }
  615. finally
  616. {
  617. LockUtils.Wait( 5 );
  618. }
  619. }
  620. logger.D( "Vehicle - _ThObstacleChecker Dispose" );
  621. }
  622. /// <summary>
  623. /// Scheduler 가 주는 Sub Command 를 이용하여 동작하자.
  624. /// </summary>
  625. public void _ThSubCmdWorker()
  626. {
  627. while ( !this.cancel.Canceled )
  628. {
  629. try
  630. {
  631. if ( this.ObstacleStateProperty != eObstacleState.Normal ) //장애물 감지 상태 시 조그 동작만 가능하게.
  632. continue;
  633. if ( this.autoManager.AutoModeStateProperty != eAutoModeState.Run ) //
  634. continue;
  635. var subCmd = sql.SubCmdDAL.GetSubCmd();
  636. if ( subCmd == null ) continue;
  637. if ( !sql.CommandDAL.All.Any( x => x.CommandID.Equals( subCmd.CmdID ) ) )
  638. {
  639. if ( subCmd.CmdType == SubCmd.eCmdType.Auto ) //자동 명령중 Main Command 가 없으면 삭제.
  640. {
  641. sql.SubCmdDAL.Delete( subCmd );
  642. logger.I( $"SubCmd Deleted - ID={subCmd.ID}, CommandID={subCmd.CmdID}" );
  643. }
  644. }
  645. switch ( subCmd.Type )
  646. {
  647. case eSubCommandType.Move:
  648. this.CurrentSubCommand = subCmd;
  649. this.Move( subCmd );
  650. break;
  651. case eSubCommandType.Load:
  652. this.CurrentSubCommand = subCmd;
  653. this.LoadCarrier( subCmd );
  654. break;
  655. case eSubCommandType.Unload:
  656. this.CurrentSubCommand = subCmd;
  657. this.UnloadCarrier( subCmd );
  658. break;
  659. case eSubCommandType.Charge:
  660. this.CurrentSubCommand = subCmd;
  661. this.BatteryCharge( subCmd );
  662. break;
  663. default:
  664. break;
  665. }
  666. }
  667. catch ( ThreadInterruptedException threadInterruptedException )
  668. {
  669. }
  670. catch ( Exception exception )
  671. {
  672. logger.E( exception );
  673. }
  674. finally
  675. {
  676. LockUtils.Wait( 500 );
  677. }
  678. }
  679. logger.D( "Vehicle - _ThSubCmdWorker Dispose" );
  680. }
  681. #endregion
  682. #region Control Action Method
  683. public void EStop()
  684. {
  685. this.conveyor.OnOffConveyor( false );
  686. //Clamp EStop
  687. this.clamp.ClampEStop();
  688. //this.drive.EStop();
  689. this.OccurVehicleAlarm( 23 );
  690. }
  691. #region For Moving
  692. void Move( SubCmd sub )
  693. {
  694. //Move 시작 시 충전 중이면 충전 중지 실행.
  695. int result = 0;
  696. if ( this.IsCharging() )
  697. {
  698. result = this.StopBatteryCharge();
  699. if ( result != 0 )
  700. {
  701. OccurVehicleAlarm( result );
  702. return;
  703. }
  704. }
  705. if ( this.MoveTo( sub.TargetID ) )
  706. {
  707. }
  708. sql.SubCmdDAL.Delete( sub );
  709. }
  710. bool MoveTo( string pointID )
  711. {
  712. //this.BuzzerOnOff(true, eBuzzerKind.StartWarn);
  713. ////TimerUtils.Once(3000, BuzzerOnOff, false, eBuzzerKind.StartWarn );
  714. //Thread.Sleep(3000);
  715. //this.BuzzerOnOff(false);
  716. if ( this.VehicleStateProperty == eVehicleState.Idle )
  717. {
  718. this.OnMoveReady?.Invoke();
  719. var moveReadyBuzzerTime = sql.ConfigDal.GetValueToInt( ConstString.BuzzerStartReadyTime );
  720. Thread.Sleep( moveReadyBuzzerTime );
  721. this.VehicleStateProperty = eVehicleState.Move;
  722. }
  723. this.OnMoving?.Invoke();
  724. this.IsMoving = true;
  725. //이전에 있던 작업들 종료 및 삭제
  726. this.taskMoveCancel.Cancel();
  727. this.taskMoveCancel.WaitAll();
  728. this.taskMoveCancel.Add( CheckCrossPoint() );
  729. PhysicalCheckupLogger.Instance.SetPLCStartDrive();
  730. this.VehicleStateProperty = eVehicleState.Move;
  731. //this.BuzzerOnOff(true, eBuzzerKind.Moving);
  732. this.drive.MoveToPoint( pointID, 100 );
  733. bool result = Wait4MoveDone();
  734. //this.BuzzerOnOff(false);
  735. this.taskMoveCancel.Cancel();
  736. this.taskMoveCancel.WaitAll();
  737. //Drive 에서 정지 확인 후 상태 변경
  738. if ( drive.IsStop )
  739. {
  740. this.IsMoving = false;
  741. this.OnMoveFinish?.Invoke();
  742. PhysicalCheckupLogger.Instance.ResetPLCStartDrive();
  743. this.VehicleStateProperty = eVehicleState.Idle;
  744. }
  745. //PhysicalCheckupLogger.Instance.UploadPhysicalCheckupLog();
  746. return result;
  747. }
  748. bool Wait4MoveDone()
  749. {
  750. int waitTime = 9000; //설정 할 수있게.
  751. long st = SwUtils.CurrentTimeMillis;
  752. //Todo: 이동시 확인 사항들.
  753. while ( true )
  754. {
  755. Thread.Sleep( 5 );
  756. if ( SwUtils.Gt( st, waitTime ) )
  757. {
  758. //Todo: 이동시간 초과 시 동작들.
  759. break;
  760. }
  761. //Todo: 이동중 명령이 삭제 되면 처리 할일들.
  762. //이동중 메인 명력이 없어진다면 정지 후
  763. if ( !sql.CommandDAL.HasK( this.CurrentSubCommand.CmdID ) )
  764. {
  765. logger.D( "[Wait Move Done] - 메인 명령 사라짐" );
  766. var cmd = sql.CommandDAL.GetCmd();
  767. if ( cmd == null )
  768. {
  769. logger.D( "[Wait Move Done] - Main Command not Exist Motion Stop" );
  770. drive.Stop();
  771. return true;
  772. }
  773. else
  774. {
  775. logger.D( "[Wait Move Done] - Main Command not Exist Motion command 없음" );
  776. return true;
  777. }
  778. }
  779. //PhysicalCheckupLogger.Instance.DriveStateLog( this.drive.CurrentSpeed.ToString(), this.drive.CurrentTorque.ToString(), "12315", "100", "1234" );
  780. //PhysicalCheckupLogger.Instance.DriveStateLog( this.drive.CurrentSpeed.ToString(), this.drive.CurrentTorque.ToString(), "12315", "100", "1234", false );
  781. //20.04.04 Kang Drive 측으로 상태만 알려주면 알아서 처리함.
  782. //if ( this.ObstacleStateProperty != eObstacleState.Normal )
  783. //{
  784. // if ( this.ObstacleStateProperty == eObstacleState.Blocked )
  785. // this.VehicleStateProperty = eVehicleState.Blocked;
  786. // if ( this.ObstacleStateProperty == eObstacleState.Abnormal )
  787. // {
  788. // this.VehicleStateProperty = eVehicleState.Abnormal;
  789. // this.OccurVehicleAlarm( 24 );
  790. // return false;
  791. // }
  792. //}
  793. }
  794. return true;
  795. }
  796. Task CheckCrossPoint()
  797. {
  798. var task = Task.Run( () =>
  799. {
  800. long sTime = SwUtils.CurrentTimeMillis;
  801. while ( !this.taskMoveCancel.Canceled )
  802. {
  803. Thread.Sleep( 10 );
  804. //ToDo: approach Cross Point Check
  805. //ToDo: Obstacle Laser Sensor Pattern Change Method 구현 필요.
  806. }
  807. } );
  808. return task;
  809. }
  810. #endregion
  811. public bool LoadCarrier( SubCmd sub )
  812. {
  813. this.VehicleStateProperty = eVehicleState.Load;
  814. var route = sql.RouteDal.GetRoute( sub.TargetID );
  815. if ( !CorrectPosition( route, this.CurrentPosition ) )
  816. {
  817. this.OccurVehicleAlarm( 20 );
  818. return false; //Alarm
  819. }
  820. //PIO 내부로 이동.
  821. //int result = this.clamp.Unlock_Sync();
  822. //if ( result != 0 )
  823. //{
  824. // this.OccurVehicleAlarm( result );
  825. // return false;
  826. //}
  827. int result = 0;
  828. this.PIOSensorOn();
  829. result = this.PIOAndLoad( sub.TargetID );
  830. if ( result != 0 )
  831. {
  832. this.iO.OutputOn( "OUT_PIO_SENSOR_ONOFF" );
  833. this.OccurVehicleAlarm( result );
  834. return false;
  835. }
  836. this.PIOSensorOff();
  837. //PIO 내부 이동.
  838. //result = this.clamp.Lock_Sync();
  839. //if ( result != 0 )
  840. //{
  841. // this.OccurVehicleAlarm( result );
  842. // return false;
  843. //}
  844. //Load, Unload 가 끝나면 메인 Command 를 완료 했다고 판단.
  845. sql.CommandDAL.UpdateState( sub.CmdID, eCommandState.Complete );
  846. sql.SubCmdDAL.Delete( sub );
  847. this.VehicleStateProperty = eVehicleState.Idle;
  848. return true;
  849. }
  850. public bool UnloadCarrier( SubCmd sub )
  851. {
  852. this.VehicleStateProperty = eVehicleState.Unload;
  853. var route = sql.RouteDal.GetRoute( sub.TargetID );
  854. if ( !CorrectPosition( route, this.CurrentPosition ) )
  855. {
  856. this.OccurVehicleAlarm( 21 );
  857. return false; //Alarm
  858. }
  859. //PIO 내부로 이동.
  860. //int result = this.clamp.Unlock_Sync();
  861. //if ( result != 0 )
  862. //{
  863. // this.OccurVehicleAlarm( result );
  864. // return false;
  865. //}
  866. this.PIOSensorOn();
  867. int result = 0;
  868. result = this.PIOAndUnload( sub.TargetID );
  869. if ( result != 0 )
  870. {
  871. this.iO.OutputOn( "OUT_PIO_SENSOR_ONOFF" );
  872. this.OccurVehicleAlarm( result );
  873. return false;
  874. }
  875. this.PIOSensorOff();
  876. sql.CommandDAL.UpdateState( sub.CmdID, eCommandState.Complete );
  877. sql.SubCmdDAL.Delete( sub );
  878. this.VehicleStateProperty = eVehicleState.Idle;
  879. return true;
  880. }
  881. public void BatteryCharge( SubCmd subCmd )
  882. {
  883. this.VehicleStateProperty = eVehicleState.Charge;
  884. int result = 0;
  885. result = this.StartBatteryCharge();
  886. sql.CommandDAL.UpdateState( subCmd.CmdID, eCommandState.Complete );
  887. sql.SubCmdDAL.Delete( subCmd );
  888. this.VehicleStateProperty = eVehicleState.Idle;
  889. }
  890. /// <summary>
  891. /// Battery Charge
  892. /// 충전 시 PIO 를 해야 함.
  893. /// </summary>
  894. /// <param name="sub"></param>
  895. /// <returns></returns>
  896. int PIOBatteryCharge( SubCmd sub )
  897. {
  898. var route = sql.RouteDal.GetRoute( sub.TargetID );
  899. if ( !CorrectPosition( route, this.CurrentPosition ) )
  900. {
  901. this.OccurVehicleAlarm( 21 );
  902. return 0; //Alarm
  903. }
  904. var pioTimeout = sql.ConfigDal.GetValueToInt( ConstString.PIOTimeOut );
  905. PIOClear();
  906. loggerPIO.I( $"Start Charge PIO - [{sub.TargetID}]" );
  907. if ( !this.iO.IsOn( "IN_PIO_READY" ) )
  908. {
  909. loggerPIO.E( "[Port] - 1 Ready not On" );
  910. this.OccurVehicleAlarm( 25 );
  911. return 0;
  912. }
  913. this.iO.WriteOutputIO( "OUT_PIO_READY", true );
  914. loggerPIO.I( "[Vehicle] - 1 Ready On" );
  915. if ( !this.iO.WaitChangeInputIO( true, pioTimeout, "IN_PIO_RECEIVE_RUN" ) )
  916. {
  917. PIOClear();
  918. loggerPIO.E( "[Port] - 2 Receive CV Run Timeout" );
  919. this.OccurVehicleAlarm( 26 );
  920. return 0;
  921. }
  922. this.iO.WriteOutputIO( "OUT_PIO_SENDING_RUN", true );
  923. loggerPIO.I( "[Vehicle] - 2 Send Run On" );
  924. var sTime = SwUtils.CurrentTimeMillis;
  925. while ( true )
  926. {
  927. Thread.Sleep( 5 );
  928. if ( !this.iO.IsOn( "IN_PIO_READY" ) || this.iO.IsOn( "IN_PIO_RECEIVE_RUN" ) )
  929. break;
  930. if ( !sql.CommandDAL.HasK( this.CurrentSubCommand.CmdID ) )
  931. {
  932. PIOClear();
  933. logger.D( "[Wait Charging] - 메인 명령 사라짐" );
  934. break;
  935. }
  936. }
  937. if ( !this.iO.WaitChangeInputIO( true, pioTimeout, "IN_PIO_RECEIVE_COMPLITE" ) )
  938. {
  939. PIOClear();
  940. loggerPIO.E( "[Port] - 3 Receive Complete Timeout" );
  941. this.OccurVehicleAlarm( 26 );
  942. return 0;
  943. }
  944. PIOClear();
  945. this.iO.WriteOutputIO( "OUT_PIO_SEND_COMPLITE", true );
  946. Thread.Sleep( 1000 );
  947. this.iO.WriteOutputIO( "OUT_PIO_SEND_COMPLITE", false );
  948. return 0;
  949. }
  950. public int StartBatteryCharge()
  951. {
  952. this.PIOSensorOn();
  953. var pioTimeout = sql.ConfigDal.GetValueToInt( ConstString.PIOTimeOut );
  954. PIOClear();
  955. loggerPIO.I( $"Start Battery Charge PIO" );
  956. if ( !this.iO.WaitChangeInputIO( true, pioTimeout, "IN_PIO_SENDABLE" ) )
  957. {
  958. PIOClear();
  959. loggerPIO.E( "[Port] - 4 Ready Time Out" );
  960. return 34;
  961. }
  962. loggerPIO.E( "[Port] - 4 Ready On" );
  963. this.iO.WriteOutputIO( "OUT_PIO_RECEIVABLE", true );
  964. loggerPIO.I( "[Vehicle] - 4 Receivable" );
  965. if ( !this.iO.WaitChangeInputIO( true, 20000, "IN_PIO_SEND_RUN" ) )
  966. {
  967. PIOClear();
  968. loggerPIO.E( "[Port] - 5 Sending Run Time Out" );
  969. return 35;
  970. }
  971. loggerPIO.I( "[Port] - 5 Sending Run On" );
  972. this.iO.WriteOutputIO( "OUT_PIO_RECEIVE_RUN", true );
  973. loggerPIO.I( "[Vehicle] - 5 Receive Run On" );
  974. this.VehicleStateProperty = eVehicleState.Charge;
  975. return 0;
  976. }
  977. public int StopBatteryCharge()
  978. {
  979. loggerPIO.I( $"Stop Battery Charge PIO" );
  980. var pioTimeout = sql.ConfigDal.GetValueToInt( ConstString.PIOTimeOut );
  981. this.PIOClear();
  982. this.iO.WriteOutputIO( "OUT_PIO_RECIVE_COMPLITE", true );
  983. loggerPIO.I( "[Vehicle] Receive Complete On" );
  984. if ( !this.iO.WaitChangeInputIO( true, 20000, "IN_PIO_SEND_COMPLITE" ) )
  985. {
  986. this.iO.WriteOutputIO( "OUT_PIO_RECIVE_COMPLITE", false );
  987. loggerPIO.E( "[Port] IN_PIO_SEND_COMPLITE On Time Out" );
  988. return 36;
  989. }
  990. loggerPIO.I( "[Port] Send Complete On" );
  991. Thread.Sleep( 1000 );
  992. this.iO.WriteOutputIO( "OUT_PIO_RECIVE_COMPLITE", false );
  993. this.PIOSensorOff();
  994. this.VehicleStateProperty = eVehicleState.Idle;
  995. return 0;
  996. }
  997. #endregion
  998. #region Check Method
  999. bool CheckObstacle()
  1000. {
  1001. if ( this.iO.IsOn( "IN_OBSTRUCTION_DETECT_SAFETY" ) || this.iO.IsOn( "IN_OBSTRUCTION_DETECT_ERROR" ) )
  1002. {
  1003. this.ObstacleStateProperty = eObstacleState.Abnormal;
  1004. this.OccurVehicleAlarm( 9999 );
  1005. }
  1006. if ( this.iO.IsOn( "IN_OBSTRUCTION_DETECT_STOP" ) )
  1007. {
  1008. this.ObstacleStateProperty = eObstacleState.Blocked;
  1009. }
  1010. if ( this.iO.IsOn( "IN_OBSTRUCTION_DETECT_SLOW" ) )
  1011. {
  1012. this.ObstacleStateProperty = eObstacleState.Decelerate;
  1013. }
  1014. this.ObstacleStateProperty = eObstacleState.Normal;
  1015. this.drive.SetObstacleState( this.ObstacleStateProperty );
  1016. return false;
  1017. }
  1018. void CheckIOState()
  1019. {
  1020. //이미 알람이면 체크 안함.
  1021. if ( this.VehicleStateProperty == eVehicleState.Abnormal ) return;
  1022. if ( this.iO.IsConnectError ) return;
  1023. //if ( this.iO.IsOn( "IN_EMS_SW" ) ) this.OccurVehicleAlarm( 28 );
  1024. //if ( !this.iO.IsOn( "IN_CP_ON_SAFETY" ) ) this.OccurVehicleAlarm( 31 );
  1025. //if ( !this.iO.IsOn( "IN_CP_ON_24V" ) ) this.OccurVehicleAlarm( 30 );
  1026. //if ( !this.iO.IsOn( "IN_MC_ON" ) ) this.OccurVehicleAlarm( 29 );
  1027. }
  1028. #endregion
  1029. #region Mechanical Method
  1030. #region IO
  1031. /// <summary>
  1032. /// Out Put 을 On 이면 Sensor Off
  1033. /// </summary>
  1034. public void PIOSensorOn() => this.iO.OutputOff( "OUT_PIO_SENSOR_ONOFF" );
  1035. /// <summary>
  1036. /// Out Put 을 Off 이면 Sensor On
  1037. /// </summary>
  1038. public void PIOSensorOff() => this.iO.OutputOn( "OUT_PIO_SENSOR_ONOFF" );
  1039. /// <summary>
  1040. /// 충전 중일때 MTL PIO Bit 가 살아 있다
  1041. /// 이걸 보고 판단 하자. 충전 단자 전진 상태임.
  1042. /// </summary>
  1043. /// <returns></returns>
  1044. public bool IsCharging() => this.iO.IsOn( "IN_PIO_SEND_RUN" ) && this.iO.IsOn( "IN_PIO_SENDABLE" );
  1045. #endregion
  1046. #region Drive
  1047. //public void DriveServoOff() => this.drive.ServoOff();
  1048. //public void DriveServoOn() => this.drive.ServoOn();
  1049. #endregion
  1050. #region Conveyor
  1051. public void ConveyorOff() => this.conveyor.OnOffConveyor( false );
  1052. public int ConveyorLoad() => this.conveyor.ConveyorLoad();
  1053. public int ConveyorUnload() => this.conveyor.ConveyorUnload();
  1054. public int PIOAndLoad( string targetName )
  1055. {
  1056. #if SIMULATION
  1057. PIOClear();
  1058. loggerPIO.I( $"Start Load PIO - [{targetName}]" );
  1059. this.OnPIOStart?.Invoke( true );
  1060. this.iO.WriteOutputIO( "OUT_PIO_RECEIVE_RUN", true );
  1061. loggerPIO.I( "[Vehicle] - 4 Receive Run On" );
  1062. Thread.Sleep( 1000 );//상대 IO 기다린다 생각.
  1063. loggerPIO.E( "[Port] - 4 Ready On" );
  1064. //Conveyor Start
  1065. loggerPIO.I( "[Vehicle] - Conveyor Run" );
  1066. this.OnConveyorStart?.Invoke( true );
  1067. Thread.Sleep( 10000 );//Conveyor 구동
  1068. this.OnCarrierDetected?.Invoke( true );
  1069. PIOClear();
  1070. Thread.Sleep( 1000 );
  1071. this.OnConveyorStop?.Invoke( true );
  1072. Thread.Sleep( 1000 );
  1073. this.OnLoadComplete?.Invoke();
  1074. #else
  1075. int result = this.clamp.Unlock_Sync();
  1076. if ( result != 0 )
  1077. {
  1078. this.OccurVehicleAlarm( result );
  1079. return result;
  1080. }
  1081. var pioTimeout = sql.ConfigDal.GetValueToInt( ConstString.PIOTimeOut );
  1082. if ( this.conveyor.IsInverterError() )
  1083. return 16;
  1084. //if ( !this.conveyor.IsLifterPositinCheck() )
  1085. // return 14;
  1086. //Todo: Sensor Setting 이 후 주석 풀기.
  1087. //if ( !this.IsLifterDuplication() )
  1088. //{
  1089. // this.OnFailReport?.Invoke( eFailCode.Load_PortHasNotCarrier );
  1090. // return 0;
  1091. //}
  1092. if ( this.conveyor.IsDetectedCenter() )
  1093. {
  1094. this.OnFailReport?.Invoke( eFailCode.Load_VehicleHasCarrier );
  1095. return 0;
  1096. }
  1097. PIOClear();
  1098. loggerPIO.I( $"Start Load PIO - [{targetName}]" );
  1099. this.OnPIOStart?.Invoke( true );
  1100. this.iO.WriteOutputIO( "OUT_PIO_RECEIVABLE", true );
  1101. loggerPIO.I( "[Vehicle] - 4 Receivable" );
  1102. if ( !this.iO.WaitChangeInputIO( true, pioTimeout, "IN_PIO_SENDABLE" ) )
  1103. {
  1104. PIOClear();
  1105. loggerPIO.E( "[Port] - 4 Ready Time Out" );
  1106. this.OnFailReport?.Invoke( eFailCode.LoadPIOInterlockTimeout );
  1107. return 0;
  1108. }
  1109. loggerPIO.E( "[Port] - 4 Ready On" );
  1110. //this.conveyor.SetConveyorSpeed( true );
  1111. this.conveyor.OnOffConveyor( true, true );
  1112. this.iO.WriteOutputIO( "OUT_PIO_RECEIVE_RUN", true, 1000 ); //1Sec 이후 On
  1113. loggerPIO.I( "[Vehicle] - Conveyor Run" );
  1114. this.OnConveyorStart?.Invoke( true );
  1115. if ( !this.iO.WaitChangeInputIO( true, pioTimeout, "IN_PIO_SEND_RUN" ) )
  1116. {
  1117. this.conveyor.OnOffConveyor( false, true );
  1118. PIOClear();
  1119. loggerPIO.E( "[Port] - 5 Sending Run Time Out" );
  1120. this.OnFailReport?.Invoke( eFailCode.LoadPIOInterlockTimeout );
  1121. return 0;
  1122. }
  1123. loggerPIO.I( "[Port] - 5 Sending Run On" );
  1124. bool isStartDetected = false;
  1125. var sTime = SwUtils.CurrentTimeMillis;
  1126. while ( true )
  1127. {
  1128. LockUtils.Wait( 10 );
  1129. if ( SwUtils.Gt( sTime, 20 * ConstUtils.ONE_SECOND ) )
  1130. {
  1131. PIOClear();
  1132. this.conveyor.OnOffConveyor( false, true );
  1133. loggerPIO.E( "[Vehicle] Conveyor Wait Time Out" );
  1134. this.OnFailReport?.Invoke( eFailCode.LoadPIOInterlockTimeout );
  1135. if ( this.conveyor.IsDetectedLoadStart() ) // 감지가 시작 되었으면 이동중 Error 로 판단 설비를 정지 상태로
  1136. return 10; //Conveyor Moving Timeout
  1137. else
  1138. return 0;
  1139. }
  1140. if ( this.conveyor.IsDetectedLoadStart() && !isStartDetected )
  1141. isStartDetected = true;
  1142. if ( !this.conveyor.IsDetectedLoadStart() && isStartDetected ) { }
  1143. //this.conveyor.SetConveyorSpeed( false );
  1144. if ( this.conveyor.IsDetectedLoadStop() ) break;
  1145. if ( this.conveyor.IsPIOInterLockOn() )
  1146. {
  1147. PIOClear();
  1148. this.conveyor.OnOffConveyor( false ); //Stop
  1149. loggerPIO.E( "[Port] PIO InterLock On " );
  1150. return 19; //
  1151. }
  1152. }
  1153. if ( this.conveyor.IsDetectedCenter() )
  1154. this.OnCarrierDetected?.Invoke( true );
  1155. this.conveyor.OnOffConveyor( false ); //Stop
  1156. PIOClear();
  1157. this.OnConveyorStop?.Invoke( true );
  1158. loggerPIO.I( "[Vehicle] Conveyor Stop" );
  1159. this.iO.WriteOutputIO( "OUT_PIO_RECIVE_COMPLITE", true );
  1160. loggerPIO.I( "[Vehicle] Receive Complete On" );
  1161. if ( !this.iO.WaitChangeInputIO( true, pioTimeout, "IN_PIO_SEND_COMPLITE" ) )
  1162. {
  1163. this.iO.WriteOutputIO( "OUT_PIO_RECIVE_COMPLITE", false );
  1164. loggerPIO.E( "[Port] IN_PIO_SEND_COMPLITE On Time Out" );
  1165. }
  1166. loggerPIO.I( "[Port] Send Complete On" );
  1167. this.iO.WriteOutputIO( "OUT_PIO_RECIVE_COMPLITE", false, 1000 );
  1168. this.OnLoadComplete?.Invoke();
  1169. loggerPIO.I( $"End Load PIO - [{targetName}]" );
  1170. result = this.clamp.Lock_Sync();
  1171. if ( result != 0 )
  1172. {
  1173. this.OccurVehicleAlarm( result );
  1174. return result;
  1175. }
  1176. #endif
  1177. return 0;
  1178. }
  1179. public int PIOAndUnload( string targetName )
  1180. {
  1181. #if SIMULATION
  1182. PIOClear();
  1183. loggerPIO.I( $"Start Unload PIO - [{targetName}]" );
  1184. this.OnPIOStart?.Invoke( false );
  1185. Thread.Sleep( 1000 );
  1186. this.iO.WriteOutputIO( "OUT_PIO_READY", true );
  1187. loggerPIO.I( "[Vehicle] - 1 Ready On" );
  1188. Thread.Sleep( 1000 );
  1189. this.OnConveyorStart?.Invoke( false );
  1190. Thread.Sleep( 10000 );
  1191. this.conveyor.OnOffConveyor( false ); //Stop
  1192. this.OnConveyorStop?.Invoke( false );
  1193. PIOClear();
  1194. Thread.Sleep( 1000 );
  1195. this.OnUnloadComplete?.Invoke();
  1196. #else
  1197. int result = this.clamp.Unlock_Sync();
  1198. if ( result != 0 )
  1199. {
  1200. this.OccurVehicleAlarm( result );
  1201. return result;
  1202. }
  1203. var pioTimeout = sql.ConfigDal.GetValueToInt( ConstString.PIOTimeOut );
  1204. if ( this.conveyor.IsInverterError() )
  1205. return 16;
  1206. if ( this.conveyor.IsLifterDuplication() )
  1207. {
  1208. this.OnFailReport?.Invoke( eFailCode.Unload_PortHasCarrier );
  1209. return 0;
  1210. }
  1211. if ( !this.conveyor.IsDetectedCenter() )
  1212. {
  1213. this.OnFailReport?.Invoke( eFailCode.Unload_VehicleHasNotCarrier );
  1214. return 0;
  1215. }
  1216. //if ( !this.conveyor.IsLifterPositinCheck() )
  1217. // return 13;
  1218. PIOClear();
  1219. loggerPIO.I( $"Start Unload PIO - [{targetName}]" );
  1220. this.OnPIOStart?.Invoke( false );
  1221. if ( !this.iO.IsOn( "IN_PIO_READY" ) )
  1222. {
  1223. loggerPIO.E( "[Port] - 1 Ready not On" );
  1224. this.OnFailReport?.Invoke( eFailCode.UnlaodPIOInterlockTimeout );
  1225. return 0;
  1226. }
  1227. this.iO.WriteOutputIO( "OUT_PIO_READY", true );
  1228. loggerPIO.I( "[Vehicle] - 1 Ready On" );
  1229. if ( !this.iO.WaitChangeInputIO( true, pioTimeout, "IN_PIO_RECEIVE_RUN" ) )
  1230. {
  1231. PIOClear();
  1232. loggerPIO.E( "[Port] - 2 Receive CV Run Timeout" );
  1233. this.OnFailReport?.Invoke( eFailCode.UnlaodPIOInterlockTimeout );
  1234. return 0;
  1235. }
  1236. loggerPIO.E( "[Port] - 2 Receive CV Run On" );
  1237. this.iO.WriteOutputIO( "OUT_PIO_SENDING_RUN", true );
  1238. loggerPIO.I( "[Vehicle] - 2 Send Run On" );
  1239. //this.conveyor.SetConveyorSpeed( true );
  1240. this.conveyor.OnOffConveyor( true );
  1241. this.OnConveyorStart?.Invoke( false );
  1242. var sTime = SwUtils.CurrentTimeMillis;
  1243. while ( true )
  1244. {
  1245. if ( SwUtils.Gt( sTime, 20 * ConstUtils.ONE_SECOND ) )
  1246. {
  1247. PIOClear();
  1248. this.conveyor.OnOffConveyor( false, true );
  1249. loggerPIO.E( "[Port] Conveyor Wait Time Out" );
  1250. this.OnFailReport?.Invoke( eFailCode.UnlaodPIOInterlockTimeout );
  1251. if ( this.conveyor.IsDetectedLoadStart() || this.conveyor.IsDetectedCenter() ) //중간에 걸려 있다고 생각해서 알람 처리.
  1252. return 12; //Conveyor Moving Timeout
  1253. else
  1254. return 0;
  1255. }
  1256. if ( !this.conveyor.IsDetectedLoadStart() && !this.conveyor.IsDetectedCenter() )
  1257. {
  1258. if ( this.iO.IsOn( "IN_PIO_RECEIVE_COMPLITE" ) )
  1259. {
  1260. loggerPIO.I( "[Port] - 3 Receive Complete On" );
  1261. break;
  1262. }
  1263. }
  1264. }
  1265. if ( !this.conveyor.IsDetectedCenter() )
  1266. this.OnCarrierDetected?.Invoke( false );
  1267. this.conveyor.OnOffConveyor( false ); //Stop
  1268. this.OnConveyorStop?.Invoke( false );
  1269. PIOClear();
  1270. this.iO.WriteOutputIO( "OUT_PIO_SEND_COMPLITE", true );
  1271. Thread.Sleep( 1000 );
  1272. this.iO.WriteOutputIO( "OUT_PIO_SEND_COMPLITE", false );
  1273. loggerPIO.I( "[Vehicle] - 3 Send Complete OnOff" );
  1274. this.OnUnloadComplete?.Invoke();
  1275. #endif
  1276. loggerPIO.I( $"End Unload PIO - [{targetName}]" );
  1277. return 0;
  1278. }
  1279. void PIOClear()
  1280. {
  1281. 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" };
  1282. pio.FwEach( x => { this.iO.OutputOff( x ); } );
  1283. }
  1284. #endregion
  1285. #endregion
  1286. #region Hardware Create Method
  1287. void CreateSteering()
  1288. {
  1289. this.steering = new Steering( this.iO, this.sql, this.eventAggregator );
  1290. this.steering.OnSteeringError += Steering_OnSteeringError;
  1291. this.steering.PropertyChanged += Steering_PropertyChanged;
  1292. }
  1293. void CreateClamp()
  1294. {
  1295. this.clamp = new Clamp( this.sql, this.eventAggregator );
  1296. this.clamp.Init();
  1297. this.clamp.PropertyChanged += Clamp_PropertyChanged;
  1298. }
  1299. void CreateDrive()
  1300. {
  1301. this.drive = new GSIDrive( this.sql );
  1302. this.drive.PropertyChanged += Motion_PropertyChanged;
  1303. this.drive.Init();
  1304. }
  1305. void CreateConveyor()
  1306. {
  1307. this.conveyor = new Conveyor( this.iO );
  1308. }
  1309. void CreateBMUManager()
  1310. {
  1311. this.bMUManager = new BMUManager();
  1312. this.bMUManager.BMUConfig = new Serial.BatteryTabos.Config() { ID = "0" };
  1313. this.bMUManager.OnConnect += BMUManager_OnConnect;
  1314. this.bMUManager.OnDisconnect += BMUManager_OnDisconnect;
  1315. this.bMUManager.OnChangedReceivedData += BMUManager_OnChangedReceivedData;
  1316. this.bMUManager.OnFirstColtd += BMUManager_OnFirstColtd;
  1317. var setV = sql.ConfigDal.GetValueToInt( ConstString.BatteryCanType );
  1318. var canType = CastTo<BMUManager.eCANSelect>.From<int>( setV );
  1319. this.bMUManager.Connect( canType );
  1320. }
  1321. private void BMUManager_OnDisconnect( string obj )
  1322. {
  1323. this.BatteryIsConnect = false;
  1324. this.OccurVehicleAlarm( 32 );
  1325. }
  1326. private void BMUManager_OnConnect( string obj )
  1327. {
  1328. this.BatteryIsConnect = true;
  1329. }
  1330. private void BMUManager_OnFirstColtd( List<ReceivedData> obj )
  1331. {
  1332. }
  1333. private void BMUManager_OnChangedReceivedData( Serial.DataModel.ReceivedData obj )
  1334. {
  1335. var kind = CastTo<eDataKind>.From<Enum>( obj.DataKind );
  1336. switch ( kind )
  1337. {
  1338. case eDataKind.Voltage:
  1339. this.BatteryVoltage = (double)obj.Value * obj.Scale;
  1340. break;
  1341. case eDataKind.Current:
  1342. this.BatteryCurrent = (double)obj.Value * obj.Scale;
  1343. break;
  1344. case eDataKind.BatteryState:
  1345. if ( obj.Value == null )
  1346. return;
  1347. this.BatteryState = (double)obj.Value;
  1348. break;
  1349. case eDataKind.ChargeCompleteTime:
  1350. if ( obj.Value == null /*|| obj.Value <= 0 */)
  1351. return;
  1352. this.BatteryChargeTime = (double)obj.Value / obj.Scale;
  1353. break;
  1354. case eDataKind.DisChargeCompleteTime:
  1355. if ( obj.Value == null || obj.Value <= 0 )
  1356. return;
  1357. this.BatteryDisChargeTime = (double)obj.Value / obj.Scale;
  1358. break;
  1359. case eDataKind.SOC:
  1360. this.BatteryStateOfCharge = (double)obj.Value * obj.Scale;
  1361. break;
  1362. case eDataKind.SOH:
  1363. this.BatteryStateOfHealth = (double)obj.Value * obj.Scale;
  1364. break;
  1365. case eDataKind.ResidualCapacity:
  1366. this.BatteryCapacity = (double)obj.Value * obj.Scale;
  1367. break;
  1368. case eDataKind.ResidualEnergy:
  1369. this.BatteryEnergy = (double)obj.Value * obj.Scale;
  1370. break;
  1371. case eDataKind.Temperature:
  1372. this.BatteryTemperature = (double)obj.Value * obj.Scale;
  1373. break;
  1374. default:
  1375. break;
  1376. }
  1377. }
  1378. #endregion
  1379. #region Help Method
  1380. /// <summary>
  1381. /// 현재 좌표 값이 등록된 Route 에 맞는 위치인지 확인한다.
  1382. /// 판단 기준은 Route 에 Tolerance 범위를 사용.
  1383. /// </summary>
  1384. /// <param name="route"></param>
  1385. /// <param name="currentPosition"></param>
  1386. /// <returns></returns>
  1387. bool CorrectPosition( Route route, double currentPosition )
  1388. {
  1389. var rScale = route.ScaleValue;
  1390. var rTolerance = route.ScaleTolerance;
  1391. var result = currentPosition - rScale;
  1392. if ( rTolerance < Math.Abs( result ) )
  1393. return false;
  1394. return true;
  1395. }
  1396. /// <summary>
  1397. /// if no is zero, Laser Off
  1398. /// bit Off, On, On, On,On Area1
  1399. /// </summary>
  1400. /// <param name="no"> 0 == Off Laser</param>
  1401. /// <returns></returns>
  1402. public bool ChgObstacleDetectPattern( int no )
  1403. {
  1404. var bitArray = BitUtils.ChgBitArray( no );
  1405. int bitIndex = 0;
  1406. this.obstacleBitList.ForEach( b =>
  1407. {
  1408. if ( bitArray[bitIndex] )
  1409. this.iO.OutputOff( b );
  1410. else
  1411. this.iO.OutputOn( b );
  1412. bitIndex++;
  1413. } );
  1414. ObstaclePattern = no;
  1415. return true;
  1416. }
  1417. public int GetObstacleDetectPattern()
  1418. {
  1419. int bitIndex = 0;
  1420. BitArray bitArray = new BitArray( this.obstacleBitList.Count );
  1421. this.obstacleBitList.ForEach( b =>
  1422. {
  1423. if ( this.iO.IsOn( b, false ) )
  1424. bitArray.Set( bitIndex, false );
  1425. else
  1426. bitArray.Set( bitIndex, true );
  1427. bitIndex++;
  1428. } );
  1429. return BitUtils.ChgInt32( bitArray );
  1430. }
  1431. /// <summary>
  1432. /// Vehicle 이동 및 동작 중 Alarm 발생 시 처리
  1433. /// </summary>
  1434. /// <param name="alarmID"></param>
  1435. void OccurVehicleAlarm( int alarmID )
  1436. {
  1437. this.MachineMode = eMachineMode.LocalMode;
  1438. this.VehicleStateProperty = eVehicleState.Abnormal;
  1439. this.ConveyorOff();
  1440. this.autoManager.ProcessAlarm( alarmID );
  1441. }
  1442. public void SetObstaclePattern( ObstacleControlEventArgs.eControlKind state, int value )
  1443. {
  1444. if ( state == ObstacleControlEventArgs.eControlKind.DRIVE )
  1445. {
  1446. this.ObstacleDrive = value;
  1447. ChgObstacleDetectPattern( this.ObstacleDrive );
  1448. }
  1449. else if ( state == ObstacleControlEventArgs.eControlKind.CURVE )
  1450. {
  1451. this.ObstacleCurve = value;
  1452. ChgObstacleDetectPattern( this.ObstacleCurve );
  1453. }
  1454. else
  1455. return;
  1456. }
  1457. #endregion
  1458. #region Event Subscribe
  1459. private void AutoManager_OnOperationModeChanged( eOperatationMode obj )
  1460. {
  1461. this.drive.SetDriveOperationMode( obj );
  1462. }
  1463. private void Motion_PropertyChanged( object sender, System.ComponentModel.PropertyChangedEventArgs e )
  1464. {
  1465. var property = sender.GetType().GetProperty( e.PropertyName );
  1466. var newValue = property.GetValue( sender, null );
  1467. switch ( e.PropertyName )
  1468. {
  1469. case "CurrentPos":
  1470. {
  1471. var v = CastTo<double>.From<object>( newValue );
  1472. this.CurrentPosition = v;
  1473. }
  1474. break;
  1475. case "CurrentTag":
  1476. {
  1477. var v = CastTo<string>.From<object>( newValue );
  1478. this.CurrentTag = v;
  1479. }
  1480. break;
  1481. case "CurrentSpeed":
  1482. {
  1483. var v = CastTo<double>.From<object>( newValue );
  1484. this.CurrentSpeed = v;
  1485. }
  1486. break;
  1487. case "CurrentTorque":
  1488. {
  1489. var v = CastTo<double>.From<object>( newValue );
  1490. this.CurrentTorque = v;
  1491. }
  1492. break;
  1493. case "ReqSteeringState":
  1494. {
  1495. var v = CastTo<eSteeringState>.From<object>( newValue );
  1496. switch ( v )
  1497. {
  1498. case eSteeringState.None:
  1499. break;
  1500. case eSteeringState.Left:
  1501. this.steering.ControlSteering( true );
  1502. break;
  1503. case eSteeringState.Right:
  1504. this.steering.ControlSteering();
  1505. break;
  1506. default:
  1507. break;
  1508. }
  1509. }
  1510. break;
  1511. case "DriveServoState":
  1512. {
  1513. var v = CastTo<eDriveServoState>.From<object>( newValue );
  1514. if ( v == eDriveServoState.ServoOn )
  1515. this.iO.OutputOn( "OUT_DRIVE_BRAKE_OFF" );
  1516. else
  1517. this.iO.OutputOff( "OUT_DRIVE_BRAKE_OFF" );
  1518. }
  1519. break;
  1520. case "FrontDriveState":
  1521. {
  1522. var v = CastTo<DriveState>.From<object>( newValue );
  1523. this.FrontDriveState = v;
  1524. }
  1525. break;
  1526. case "RearDriveState":
  1527. {
  1528. var v = CastTo<DriveState>.From<object>( newValue );
  1529. this.RearDriveState = v;
  1530. }
  1531. break;
  1532. default:
  1533. break;
  1534. }
  1535. }
  1536. private void Steering_PropertyChanged( object sender, System.ComponentModel.PropertyChangedEventArgs e )
  1537. {
  1538. var property = sender.GetType().GetProperty( e.PropertyName );
  1539. var newValue = property.GetValue( sender, null );
  1540. //Todo: 나중에 Test 하자
  1541. //var ownPropperty = this.GetType().GetProperty(e.PropertyName);
  1542. if ( e.PropertyName.Equals( "SteeringState" ) )
  1543. {
  1544. var v = CastTo<eSteeringState>.From<object>( newValue );
  1545. this.SteeringState = v;
  1546. logger.D( $"steering - {v}" );
  1547. }
  1548. }
  1549. private void Clamp_PropertyChanged( object sender, System.ComponentModel.PropertyChangedEventArgs e )
  1550. {
  1551. var property = sender.GetType().GetProperty( e.PropertyName );
  1552. var newValue = property.GetValue( sender, null );
  1553. if ( e.PropertyName.Equals( "ClampState" ) )
  1554. {
  1555. var v = CastTo<eClampState>.From<object>( newValue );
  1556. this.ClampState = v;
  1557. }
  1558. }
  1559. private void IO_OnChangedIO( BitBlock bit )
  1560. {
  1561. switch ( bit.Tag )
  1562. {
  1563. case "IN_CV_DETECT_01":
  1564. this.IsContain = bit.IsBitOn;
  1565. break;
  1566. case "IN_MC_ON":
  1567. if ( bit.IsBitOn )
  1568. {
  1569. if ( !this.iO.IsOn( "IN_EMS_SW" ) && this.iO.IsOn( "IN_CP_ON_SAFETY" ) && this.iO.IsOn( "IN_CP_ON_24V" ) )
  1570. this.VehicleStateProperty = eVehicleState.Idle;
  1571. }
  1572. else
  1573. this.OccurVehicleAlarm( 29 );
  1574. break;
  1575. case "IN_EMS_SW":
  1576. if ( bit.IsBitOn )
  1577. this.OccurVehicleAlarm( 28 );
  1578. break;
  1579. case "IN_CP_ON_SAFETY":
  1580. if ( !bit.IsBitOn )
  1581. this.OccurVehicleAlarm( 31 );
  1582. break;
  1583. case "IN_CP_ON_24V":
  1584. if ( !bit.IsBitOn )
  1585. this.OccurVehicleAlarm( 30 );
  1586. break;
  1587. default:
  1588. break;
  1589. }
  1590. }
  1591. private void Steering_OnSteeringError( object sender, int e )
  1592. {
  1593. if ( e != 0 )
  1594. {
  1595. logger.E( $"[Steering] - Control Error {e}" );
  1596. this.OccurVehicleAlarm( e );
  1597. }
  1598. else
  1599. {
  1600. var msg = new DriveControlEventArgs()
  1601. {
  1602. EventDir = DriveControlEventArgs.eEventDir.ToFront,
  1603. ControlKind = DriveControlEventArgs.eControlKind.Steering,
  1604. Result = FluentResults.Results.Ok<DriveControlEventArgs.eMoveDir>( DriveControlEventArgs.eMoveDir.LEFT ),
  1605. };
  1606. this.eventAggregator.GetEvent<DriveControlPubSubEvent>().Publish( msg );
  1607. }
  1608. }
  1609. #endregion
  1610. }
  1611. }