ReadDeviceStatusController.cs 8.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228
  1. using System;
  2. using System.Collections.Generic;
  3. using Wayne.ForecourtControl.Fusion.StatusStateMachine.States;
  4. using Wayne.ForecourtControl.Vir.Fusion;
  5. using Wayne.Lib;
  6. using Wayne.Lib.Log;
  7. using Wayne.Lib.StateEngine;
  8. namespace Wayne.ForecourtControl.Fusion.ReadDeviceStatus
  9. {
  10. public class ReadDeviceStatusController : IDisposable, Wayne.Lib.IIdentifiableEntity
  11. {
  12. private readonly FUSIONForecourtControl _forecourtControl;
  13. public StateMachine StateMachine { get; private set; }
  14. // Dictionary that holds the event types for the event handlers registered by CreateEventHandler<TAsyncCompleted> method.
  15. private readonly Dictionary<object, object> _userTokenEventTypeDict = new Dictionary<object, object>();
  16. private readonly object _eventTypeDictSyncObj = new object();
  17. public IFSFManager IfsfManager
  18. {
  19. get { return _forecourtControl.manager.ifsfManager; }
  20. }
  21. public ReadDeviceStatusController(IIdentifiableEntity parentEntity, FUSIONForecourtControl forecourtControl)
  22. {
  23. Id = forecourtControl.Id;
  24. _forecourtControl = forecourtControl;
  25. ParentEntity = parentEntity;
  26. IServiceContainer serviceContainer = ServiceContainerFactory.Create();
  27. StateMachine = StateMachine.Create("", StateMachineType.Synchronous, new DebugLogger(this, true), "StateMachine");
  28. StateMachine.AddStateFactory(new StateFactory<ReadDeviceStatusController>(this, serviceContainer));
  29. StateMachine.OnFinalStateEntered += StateMachineOnOnFinalStateEntered;
  30. StateMachine.LogNameKind = StateNameKind.InstanceName;
  31. }
  32. private void StateMachineOnOnFinalStateEntered(object sender, EventArgs eventArgs)
  33. {
  34. using (var debugLogger = new DebugLogger(this))
  35. {
  36. if (debugLogger.IsActive(DebugLogLevel.Detailed))
  37. debugLogger.Add("ReadDevice Status final state entered", DebugLogLevel.Detailed);
  38. }
  39. Dispose();
  40. }
  41. /// <summary>
  42. /// Initializes the manager. Initializes the state machine.
  43. /// </summary>
  44. public void Initialize()
  45. {
  46. var stateConfigurator = new StateConfigurator();
  47. stateConfigurator.Config(StateMachine.StateTransitionLookup);
  48. StateMachine.Initialize();
  49. if (!StateMachine.Started)
  50. {
  51. StateMachine.Start();
  52. }
  53. }
  54. public void Start()
  55. {
  56. StateMachine.IncomingEvent(new StateEngineEvent(EventType.ReadDeviceStatus));
  57. }
  58. public void GetConfiguration(EventHandler<AsyncCompletedEventArgs<ConfigurationSet>> readCompleted)
  59. {
  60. //Fail the ongoing reading and replace with new.
  61. var currentResponseDelgate = CurrentReadConfigurationResponseDelegate;
  62. currentResponseDelgate.Fire(this, new AsyncCompletedEventArgs<ConfigurationSet>(false, null, null));
  63. CurrentReadConfigurationResponseDelegate = readCompleted;
  64. StateMachine.IncomingEvent(new StateEngineEvent(EventType.GetConfiguration));
  65. }
  66. public EventHandler<AsyncCompletedEventArgs<ConfigurationSet>> CurrentReadConfigurationResponseDelegate { get; set; }
  67. public void SetConnectedStatus()
  68. {
  69. _forecourtControl.WritableConnectionState = DeviceConnectionState.Connected;
  70. }
  71. public void GetDeviceState(string deviceType, EventHandler<AsyncCompletedEventArgs> eventHandler, object userToken)
  72. {
  73. _forecourtControl.manager.ifsfManager.GetDeviceState(deviceType, -1, eventHandler, userToken, null);
  74. }
  75. public EventHandler<TEventArgs> EventHander<TEventArgs>() where TEventArgs : EventArgs
  76. {
  77. return (sender, e) => StateMachine.IncomingEvent(GenericEvent.Create(EventType.Response, sender, e));
  78. }
  79. public void GetFuelSaleTrx(EventHandler<AsyncCompletedEventArgs> eventHandler, object userToken)
  80. {
  81. _forecourtControl.manager.ifsfManager.GetAvailableFuelSaleTrxs(-1, eventHandler, userToken, null);
  82. }
  83. #region Generic asynchronous event handler
  84. /// <summary>
  85. /// Method for automatically creating a asynchronous completion event handler. It connects to a private method
  86. /// that generically encapsulates the event argument to a state engine generic event.
  87. /// </summary>
  88. /// <typeparam name="TAsyncCompleted">Type of the event argument.</typeparam>
  89. /// <param name="eventType">State engine event type that should be set for the generic event in the state machine.</param>
  90. /// <param name="userToken">The method creates a user token that should be used for the asynchronous call, so it can look up the eventtype properly.</param>
  91. /// <returns></returns>
  92. public EventHandler<TAsyncCompleted> CreateEventHandler<TAsyncCompleted>(object eventType, out object userToken) where TAsyncCompleted : Wayne.Lib.UserTokenEventArgs
  93. {
  94. lock (_eventTypeDictSyncObj)
  95. {
  96. userToken = new object();
  97. _userTokenEventTypeDict.Add(userToken, eventType);
  98. return new EventHandler<TAsyncCompleted>(GenericHandleEvent<TAsyncCompleted>);
  99. }
  100. }
  101. /// <summary>
  102. /// Internal generic event handler that is the target of the event handlers created in the CreateEventHandler &lt;TAsyncCompleted&gt; method.
  103. /// </summary>
  104. /// <typeparam name="TAsyncCompleted"></typeparam>
  105. /// <param name="sender"></param>
  106. /// <param name="e"></param>
  107. private void GenericHandleEvent<TAsyncCompleted>(object sender, TAsyncCompleted e) where TAsyncCompleted : Wayne.Lib.UserTokenEventArgs
  108. {
  109. GenericEvent<TAsyncCompleted> genericEvent = null;
  110. lock (_eventTypeDictSyncObj)
  111. {
  112. if (_userTokenEventTypeDict.ContainsKey(e.UserToken))
  113. {
  114. var eventType = _userTokenEventTypeDict[e.UserToken];
  115. _userTokenEventTypeDict.Remove(e.UserToken);
  116. genericEvent = new GenericEvent<TAsyncCompleted>(eventType, sender, e);
  117. }
  118. }
  119. if (genericEvent != null)
  120. {
  121. StateMachine.IncomingEvent(genericEvent);
  122. }
  123. }
  124. /// <summary>
  125. /// Cancel the automatically created event handler. If the event handler is not cancelled, it will remain in memory forever, since it might never be used.
  126. /// </summary>
  127. /// <param name="userToken"></param>
  128. public void CancelEventHandler(object userToken)
  129. {
  130. lock (_eventTypeDictSyncObj)
  131. {
  132. if (_userTokenEventTypeDict.ContainsKey(userToken))
  133. _userTokenEventTypeDict.Remove(userToken);
  134. }
  135. }
  136. #endregion
  137. #region Implementation of IDisposable
  138. /// <summary>
  139. /// Finalizer
  140. /// </summary>
  141. ~ReadDeviceStatusController()
  142. {
  143. Dispose(false);
  144. }
  145. /// <summary>
  146. /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
  147. /// </summary>
  148. public void Dispose()
  149. {
  150. Dispose(true);
  151. GC.SuppressFinalize(this);
  152. }
  153. private void Dispose(bool disposing)
  154. {
  155. if (disposing)
  156. StateMachine.Dispose();
  157. }
  158. #endregion
  159. #region Implementation of IIdentifiableEntity
  160. /// <summary>
  161. /// The ID of the entity.
  162. /// </summary>
  163. public int Id { get; private set; }
  164. /// <summary>
  165. /// The main type of entity.
  166. /// </summary>
  167. public string EntityType
  168. {
  169. get { return "DeviceStatusReader"; }
  170. }
  171. /// <summary>
  172. /// This is used by the logger and should never be set by inheriting classes
  173. /// </summary>
  174. public string FullEntityName { get; set; }
  175. /// <summary>
  176. /// A more refined type of the entity, e.g. a specific implementation or brand.
  177. /// </summary>
  178. public string EntitySubType
  179. {
  180. get { return "FusionFC"; }
  181. }
  182. /// <summary>
  183. /// Reference to a possible parent device.
  184. /// </summary>
  185. public IIdentifiableEntity ParentEntity { get; private set; }
  186. public ConfigurationSet Configuration { get; set; }
  187. #endregion
  188. public bool HasVirs()
  189. {
  190. return FUSIONVirFactory.Virs.Count > 0;
  191. }
  192. }
  193. }