Vehicle.cs 58 KB

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