FUSIONManager.cs 67 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363
  1. using System;
  2. using System.Collections;
  3. using System.Collections.Generic;
  4. using System.Linq;
  5. using System.Threading;
  6. using Wayne.FDCPOSLibrary;
  7. using Wayne.ForecourtControl.Fusion.ReadDeviceStatus;
  8. using Wayne.ForecourtControl.OptBridge;
  9. using Wayne.ForecourtControl.OptBridge.Fusion;
  10. using Wayne.ForecourtControl.Vir.Fusion;
  11. using Wayne.Lib;
  12. using Wayne.Lib.Log;
  13. namespace Wayne.ForecourtControl.Fusion
  14. {
  15. public class FUSIONManager : IIdentifiableEntity, IDisposable
  16. {
  17. // Fields
  18. public IFSFManager ifsfManager;
  19. private ConfigurationReader configurationReader;
  20. private bool disposed;
  21. public FUSIONForecourtControl forecourtControl;
  22. private List<int> managedPumpIds;
  23. public AutoResetEvent versionInfoWakeUpEvent;
  24. public string version;
  25. public string release;
  26. public string hotfix;
  27. public string getFwRelease()
  28. {
  29. return version + "." + release + "." + hotfix;
  30. }
  31. public int IdShift = 0;
  32. public int IdPumpShift = 0;
  33. public int IdNozzleShift = 0;
  34. public int IdTankShift = 0;
  35. public int FuelGradeShift = 0;
  36. internal readonly IPumpAuthorizationIdGenerator PumpAuthIdSequence;
  37. private readonly ReadDeviceStatusController _readDeviceStatusController;
  38. private readonly DebugLogger debugLogger;
  39. private ConfigurationSet CurrentConfiguration { get; set; }
  40. public DebugLogger DebugLogger { get { return debugLogger; } }
  41. // Methods
  42. internal FUSIONManager(FUSIONForecourtControl forecourtControl, ForecourtEntityTypes managedEntityTypes, int[] managedPumpIds, IPumpAuthorizationIdGenerator pumpAuthorizaitonIdGenerator, ReadDeviceStatusController readDeviceStatusController)
  43. {
  44. debugLogger = new DebugLogger(this, true);
  45. FuelPriceReadings = new List<IFuelPriceReading>();
  46. this.configurationReader = new ConfigurationReader(this);
  47. this.forecourtControl = forecourtControl;
  48. DebugLog("starting ...");
  49. this.PumpAuthIdSequence = pumpAuthorizaitonIdGenerator;
  50. this._readDeviceStatusController = readDeviceStatusController;
  51. this.ifsfManager = new IFSFManager(this, forecourtControl.Id);
  52. this.ifsfManager.clientSocket.OnConnectionStateChange += new EventHandler<ConnectionChangedEventArgs>(clientSocket_OnConnectionStateChange);
  53. this.ifsfManager.OnDeviceStateChange += new EventHandler<DeviceStateChangedEventArgs>(manager_OnDeviceStateChange);
  54. this.ifsfManager.OnVirStateChange += new EventHandler<VIRStateChangedEventArgs>(manager_OnVirStateChange);
  55. this.ifsfManager.OnFuelModeChange += new EventHandler<FuelModeChangedEventArgs>(manager_OnFuelModeChange);
  56. this.ifsfManager.OnOperationModeChange += manager_OnOperationModeChange;
  57. this.ifsfManager.OnCurrentFuellingStatus += new EventHandler<CurrentFuellingStatusEventArgs>(manager_OnCurrentFuellingStatus);
  58. this.ifsfManager.OnFuelPointTotals += new EventHandler<FuelPointTotalsEventArgs>(manager_OnFuelPointTotals);
  59. this.ifsfManager.OnFuelSaleTrx += new EventHandler<FuelSaleTrxEventArgs>(manager_OnFuelSaleTrx);
  60. this.ifsfManager.OnDeviceAlarm += new EventHandler<DeviceAlarmEventArgs>(manager_OnDeviceAlarm);
  61. this.ifsfManager.OnVersionInfo += new EventHandler<VersionInfoEventArgs>(manager_OnVersionInfo);
  62. this.ifsfManager.OnChangeFuelPrice += new EventHandler<ChangeFuelPriceEventArgs>(manager_OnChangeFuelPrice);
  63. this.ifsfManager.OnClearFuelSaleTrx += new EventHandler<FuelSaleTrxEventArgs>(manager_OnClearFuelSaleTrx);
  64. this.ifsfManager.OnGetAvailableFuelSaleTrx += new EventHandler<FuelSaleTrxEventArgs>(manager_OnGetAvailableFuelSaleTrx);
  65. this.ifsfManager.OnConfigurationChange += new EventHandler<EventArgs>(manager_OnConfigurationChange);
  66. this.ifsfManager.OnTwinMasterReady += new EventHandler<EventArgs>(manager_OnTwinMasterReady);
  67. this.ifsfManager.OnOptRead += new EventHandler<OptReadEventArgs>(manager_OnOptRead);
  68. this.versionInfoWakeUpEvent = new AutoResetEvent(false);
  69. }
  70. private void DebugLog(string s)
  71. {
  72. if (debugLogger.IsActive())
  73. debugLogger.Add(s);
  74. }
  75. private int convertDeviceType(string deviceType)
  76. {
  77. if (deviceType == Wayne.FDCPOSLibrary.DeviceType.DT_FuellingPoint || deviceType == Wayne.FDCPOSLibrary.DeviceType.DT_FuelDispenser)
  78. return (int)(ForecourtEntityTypes.Pump);
  79. else if (deviceType == Wayne.FDCPOSLibrary.DeviceType.DT_PricePole || deviceType == Wayne.FDCPOSLibrary.DeviceType.DT_PricePolePoint)
  80. return (int)(ForecourtEntityTypes.PricePole);
  81. else if (deviceType == Wayne.FDCPOSLibrary.DeviceType.DT_TankLevelGauge || deviceType == Wayne.FDCPOSLibrary.DeviceType.DT_TankProbe)
  82. return (int)(ForecourtEntityTypes.Tank);
  83. return 0;
  84. }
  85. private int getAlarmCategory(int alarmId)
  86. {
  87. switch (alarmId)
  88. {
  89. case 1003:
  90. return 0; // Information
  91. default:
  92. return 1; // Error
  93. }
  94. }
  95. private void clientSocket_OnConnectionStateChange(object sender, ConnectionChangedEventArgs e)
  96. {
  97. DebugLog("manager clientSocket_OnConnectionStateChange ConnectionState=" + e.ConnectionState);
  98. try
  99. {
  100. if (e.ConnectionState == DeviceConnectionState.Connected)
  101. {
  102. // when socket connection is active, start getting configuration
  103. this._readDeviceStatusController.GetConfiguration(this.ConfigurationSetComplete);
  104. }
  105. else if (e.ConnectionState != DeviceConnectionState.Connected)
  106. {
  107. if (e.ConnectionState == DeviceConnectionState.Disconnected)
  108. {
  109. ifsfManager.Disconnect();
  110. var optBridge = (FUSIONOptBridge)(FUSIONOptFactory.getOptBridge());
  111. if (optBridge != null)
  112. {
  113. foreach (IOpt opt in optBridge.Opts)
  114. {
  115. if (((FUSIONOpt)opt).managedBy == OPTManagedBy.SINP)
  116. ((FUSIONOpt)opt).optTCP.Disconnect();
  117. }
  118. }
  119. foreach (FUSIONPump pump in this.forecourtControl.Pumps)
  120. {
  121. pump.WritableState = PumpState.Inoperative;
  122. }
  123. }
  124. this.forecourtControl.WritableConnectionState = e.ConnectionState;
  125. }
  126. }
  127. catch (Exception ex)
  128. {
  129. DebugLog("Exception! " + ex.ToString());
  130. }
  131. }
  132. private void manager_OnDeviceStateChange(object sender, DeviceStateChangedEventArgs e)
  133. {
  134. if (e.deviceType == DeviceType.DT_FuelDispenser || e.deviceType == DeviceType.DT_FuellingPoint)
  135. {
  136. FUSIONPump pump = this.GetPumpById(e.deviceId);
  137. if (pump != null)
  138. {
  139. PumpState state = pump.convertPumpState(e.state, e.substate);
  140. DebugLog(string.Format("pump={0}, State={1}, pump.State={2}, nozzleUp={3}", pump.realId, state, pump.State, e.nozzleUp));
  141. if (pump.State != state)
  142. {
  143. // keep previous "open" state
  144. var pumpWasOpen = pump.Open;
  145. // update current state
  146. pump.WritableState = state;
  147. // Get fuel mode from pump when pump becames open
  148. if (pump.Open && !pumpWasOpen)
  149. this.ifsfManager.GetFuelMode(e.deviceId, null, null, null);
  150. }
  151. int reservedBy;
  152. if (string.IsNullOrEmpty(e.lockingAS))
  153. reservedBy = 0;
  154. else if (!int.TryParse(e.lockingAS, out reservedBy))
  155. reservedBy = -1; // An external device id.
  156. pump.WritableReservedBy = reservedBy;
  157. foreach (FUSIONNozzle nozzle in pump.Nozzles)
  158. {
  159. DebugLog(string.Format("pump={0}, nozzle={1}, nozzle.State={2}", pump.realId, nozzle.Id, nozzle.State));
  160. if (nozzle.State == NozzleState.Out && e.nozzleUp != nozzle.Id)
  161. nozzle.State = NozzleState.In;
  162. else if (nozzle.State == NozzleState.In && e.nozzleUp == nozzle.Id)
  163. nozzle.State = NozzleState.Out;
  164. }
  165. }
  166. }
  167. else if (e.deviceType == DeviceType.DT_OutdoorPaymentTerminal)
  168. {
  169. if (FUSIONOptFactory.getOptBridge() == null)
  170. return;
  171. FUSIONOpt opt = ((FUSIONOptBridge)(FUSIONOptFactory.getOptBridge())).GetOptFromId(e.deviceId);
  172. if (opt != null)
  173. {
  174. DeviceConnectionState state;
  175. if (e.state == LogicalDeviceState.FDC_READY) state = DeviceConnectionState.Connected;
  176. else state = DeviceConnectionState.Disconnected;
  177. DebugLog(string.Format("opt={0}, State={1}", opt.Id, state));
  178. if (opt.ConnectionState != state)
  179. opt.WritableConnectionState = state;
  180. }
  181. }
  182. else if (e.deviceType == DeviceType.DT_TankProbe)
  183. {
  184. FUSIONTank tank = this.getTankByIndex(e.deviceId);
  185. if (tank != null)
  186. {
  187. if (e.state == LogicalDeviceState.FDC_READY)
  188. tank.WritableConnectionState = DeviceConnectionState.Connected;
  189. else
  190. tank.WritableConnectionState = DeviceConnectionState.Disconnected;
  191. }
  192. else
  193. DebugLog(string.Format("manager_OnDeviceStateChange: tank={0} NOT FOUND !", e.deviceId));
  194. }
  195. }
  196. private void manager_OnVirStateChange(object sender, VIRStateChangedEventArgs e)
  197. {
  198. FUSIONVir vir = (FUSIONVir)(FUSIONVirFactory.getVir(e.deviceId));
  199. if (vir != null)
  200. {
  201. if (e.state == DeviceConnectionState.Connected)
  202. vir.Connected(e.virId);
  203. else if (e.state == DeviceConnectionState.Disconnected)
  204. vir.Disconnected(e.virId);
  205. else
  206. DebugLog(string.Format("manager_OnVirStateChange>: vir={0} State={1} NOT managed !", vir.Id, e.state));
  207. }
  208. else
  209. DebugLog(string.Format("manager_OnVirStateChange: vir={0} NOT FOUND !", e.deviceId));
  210. }
  211. private void manager_OnOperationModeChange(object sender, OperationModeChangedEventArgs e)
  212. {
  213. if (e.deviceType == DeviceType.DT_FuelDispenser || e.deviceType == DeviceType.DT_FuellingPoint)
  214. {
  215. FUSIONPump pump = this.GetPumpById(e.deviceId);
  216. if (pump != null)
  217. {
  218. var mode = e.mode;
  219. DebugLog(string.Format("pump={0}, Op mode={1}", pump.realId, mode));
  220. pump.WritableOperationMode = mode;
  221. pump.FireOperationModeChange(mode);
  222. }
  223. }
  224. }
  225. private void manager_OnFuelModeChange(object sender, FuelModeChangedEventArgs e)
  226. {
  227. if (e.deviceType == DeviceType.DT_FuelDispenser || e.deviceType == DeviceType.DT_FuellingPoint)
  228. {
  229. FUSIONPump pump = this.GetPumpById(e.deviceId);
  230. if (pump != null)
  231. {
  232. int mode = e.mode;
  233. pump.WritableFuelMode = mode;
  234. if (pump.CurrentFuelling != null)
  235. {
  236. lock (pump.CurrentFuelling)
  237. {
  238. var currentFuelling = (FUSIONFuelling)(pump.CurrentFuelling);
  239. currentFuelling.WritableType = forecourtControl.ForecourtConfiguration.GetFuellingType(mode, currentFuelling.WritablePriceGroup);
  240. }
  241. }
  242. pump.FireFuelModeChange(mode);
  243. }
  244. }
  245. }
  246. private void manager_OnCurrentFuellingStatus(object sender, CurrentFuellingStatusEventArgs e)
  247. {
  248. if (e.deviceType == DeviceType.DT_FuelDispenser || e.deviceType == DeviceType.DT_FuellingPoint)
  249. {
  250. try
  251. {
  252. FUSIONPump pump = this.GetPumpById(e.deviceId);
  253. if (pump != null && pump.CurrentFuelling != null)
  254. {
  255. var previousFuellingState = pump.CurrentFuelling.State;
  256. var previousFuellingVolume = pump.CurrentFuelling.Quantity;
  257. lock (pump.CurrentFuelling)
  258. {
  259. FUSIONFuelling currentFuelling = null;
  260. currentFuelling = (FUSIONFuelling)(pump.CurrentFuelling);
  261. currentFuelling.WritablePrice = e.price;
  262. currentFuelling.WritableAmount = e.amount;
  263. currentFuelling.WritableQuantity = e.volume;
  264. currentFuelling.WritableState = FuellingState.CurrentPumpData;
  265. currentFuelling.WritableAuthorizationId = e.ReleaseId;
  266. currentFuelling.WritableTransactionId = e.TransactionId;
  267. currentFuelling.WritableCompletionReason = 0; //Ok
  268. currentFuelling.WritableCompletionDateTime = DateTime.Now;
  269. currentFuelling.WritableFuelPeriodId = e.FuelPeriodSequenceNo;
  270. if (pump.Nozzles.Count > e.nozzleId - 1 && e.nozzleId > 0)
  271. {
  272. currentFuelling.WritableNozzle = pump.Nozzles[e.nozzleId - 1];
  273. currentFuelling.WritableFuelGrade =
  274. ((FUSIONNozzle)pump.WritableNozzleList[e.nozzleId - 1]).WritableFuelGrade;
  275. }
  276. else
  277. DebugLog(String.Format("INVALID Nozzle: '{0}'", e.nozzleId));
  278. }
  279. if (pump.State == PumpState.Fuelling && previousFuellingState != FuellingState.CurrentPumpData)
  280. {
  281. // On first current pump data event from pump, fire fuelling state change
  282. pump.FireFuellingStateChange(pump.CurrentFuelling, FuellingState.Fuelling);
  283. }
  284. if (e.volume > 0 && e.volume != previousFuellingVolume && pump.RunningFuellingUpdates)
  285. {
  286. pump.FireFuellingDataChange(pump.CurrentFuelling, pump.CurrentFuelling.Amount,
  287. pump.CurrentFuelling.Quantity);
  288. }
  289. }
  290. }
  291. catch (Exception ex)
  292. {
  293. DebugLog("Exception! " + ex.ToString());
  294. }
  295. }
  296. }
  297. private void manager_OnFuelPointTotals(object sender, FuelPointTotalsEventArgs e)
  298. {
  299. if (e.deviceType == DeviceType.DT_FuelDispenser || e.deviceType == DeviceType.DT_FuellingPoint)
  300. {
  301. try
  302. {
  303. FUSIONPump pump = this.GetPumpById(e.deviceId);
  304. FUSIONNozzle nozzle = (FUSIONNozzle)(pump.Nozzles[e.nozzleId - 1]);
  305. if (pump != null && nozzle != null)
  306. {
  307. PumpAccumulatorReading pumpAccumulatorReading = new PumpAccumulatorReading(pump, nozzle, 0, PumpAccumulatorReadingType.RequestedReading,
  308. e.volume, e.amount, e.originalTransactionData);
  309. this.ifsfManager.clientSocket.ifsfMessages.asyncResponseManager.SendResponse(e.requestId, e.overallResult, pumpAccumulatorReading);
  310. }
  311. }
  312. catch (Exception ex)
  313. {
  314. DebugLog("Exception! " + ex.ToString());
  315. }
  316. }
  317. }
  318. private void manager_OnFuelSaleTrx(object sender, FuelSaleTrxEventArgs e)
  319. {
  320. if (e.deviceType == DeviceType.DT_FuelDispenser || e.deviceType == DeviceType.DT_FuellingPoint)
  321. {
  322. try
  323. {
  324. FUSIONPump pump = this.GetPumpById(e.deviceId);
  325. if (pump != null && pump.CurrentFuelling != null)
  326. {
  327. lock (pump.CurrentFuelling)
  328. {
  329. DebugLog(string.Format("pump={0}, pump.Nozzles.Count={1}, e.nozzleId={2}, Transaction state={3}", pump.realId, pump.Nozzles.Count, e.nozzleId, e.transactionStatus));
  330. FUSIONFuelling fuelling = (FUSIONFuelling)(pump.getFuellingByTransactionId(e.transactionId, e.releaseToken));
  331. FUSIONFuelling currentFuelling = (FUSIONFuelling)(pump.CurrentFuelling);
  332. FuellingState fuellingState = FuellingState.Unknown;
  333. if (e.transactionStatus == Wayne.FDCPOSLibrary.FuellingState.Locked)
  334. fuellingState = FuellingState.Locked;
  335. else if (e.transactionStatus == Wayne.FDCPOSLibrary.FuellingState.Payable)
  336. fuellingState = FuellingState.PayableTransaction;
  337. else if (e.transactionStatus == Wayne.FDCPOSLibrary.FuellingState.Paid)
  338. fuellingState = FuellingState.Paid;
  339. if (fuelling == null)
  340. {
  341. if (pump.Nozzles.Count > e.nozzleId - 1)
  342. {
  343. currentFuelling.WritableCompletionReason = currentFuelling.convertStatus(e.completionReason);
  344. // overwrite the value set when authorising fuelling
  345. currentFuelling.WritableTransactionId = e.transactionId;
  346. currentFuelling.WritableFuellingSequenceNumber = e.fuellingSeqNo;
  347. currentFuelling.WritableCompletionDateTime = e.trxEndDateTime;
  348. currentFuelling.WritablePriceGroup = forecourtControl.ForecourtConfiguration.GetPriceGroup(e.fuelMode, e.fuellingType);
  349. currentFuelling.WritableFuelGrade = (e.nozzleId > 0) ? ((FUSIONNozzle)pump.WritableNozzleList[e.nozzleId - 1]).WritableFuelGrade : 1;
  350. currentFuelling.WritableState = fuellingState;
  351. currentFuelling.WritablePrice = e.price;
  352. currentFuelling.WritableAmount = e.amount;
  353. currentFuelling.WritableFuelPeriodId = e.FuelPeriodSequenceNo;
  354. if (pump.CurrentFuelling.PresetValue == 0)
  355. {
  356. currentFuelling.WritablePresetType = PresetType.Amount;
  357. currentFuelling.WritablePresetValue = e.amount;
  358. }
  359. currentFuelling.WritableQuantity = e.volume;
  360. currentFuelling.WritableNozzle = (e.nozzleId > 0) ? pump.Nozzles[e.nozzleId - 1] : null;
  361. int reservedBy;
  362. if (string.IsNullOrEmpty(e.lockingAS))
  363. reservedBy = 0;
  364. else if (!int.TryParse(e.lockingAS, out reservedBy))
  365. reservedBy = -1; // An external device id.
  366. currentFuelling.WritableReservedBy = reservedBy;
  367. int authorizedBy;
  368. if (string.IsNullOrEmpty(e.authAS))
  369. authorizedBy = 0;
  370. else if (!int.TryParse(e.authAS, out authorizedBy))
  371. authorizedBy = -1; // An external device id.
  372. currentFuelling.WritableAuthorizedBy = authorizedBy;
  373. currentFuelling.WritableSignedReceiptLines = e.MIDLinesNarrow ?? "";
  374. currentFuelling.WritableSignedReceiptLinesWide = e.MIDLinesWide ?? "";
  375. currentFuelling.WritableAuthorizationId = e.releaseToken;
  376. currentFuelling.WritableReservingDeviceId = e.reservingDeviceId;
  377. currentFuelling.WritableType = e.fuellingType;
  378. currentFuelling.origMessageXml = e.origMessageXml;
  379. // add a fuelling to the pump fuellings list
  380. fuelling = new FUSIONFuelling(this, pump);
  381. pump.WritableFuellingList.Add(fuelling);
  382. fuelling.WritableTransactionId = currentFuelling.WritableTransactionId;
  383. fuelling.WritableFuellingSequenceNumber = currentFuelling.WritableFuellingSequenceNumber;
  384. fuelling.WritableCompletionReason = currentFuelling.convertStatus(e.completionReason);
  385. fuelling.WritableCompletionDateTime = e.trxEndDateTime;
  386. fuelling.WritablePriceGroup = forecourtControl.ForecourtConfiguration.GetPriceGroup(e.fuelMode, e.fuellingType);
  387. fuelling.WritablePresetType = currentFuelling.PresetType;
  388. fuelling.WritablePresetValue = currentFuelling.PresetValue;
  389. fuelling.WritableFuelGrade = (e.nozzleId > 0) ? ((FUSIONNozzle)pump.WritableNozzleList[e.nozzleId - 1]).WritableFuelGrade : 1;
  390. fuelling.WritableState = fuellingState;
  391. fuelling.WritablePrice = e.price;
  392. fuelling.WritableAmount = e.amount;
  393. fuelling.WritableQuantity = e.volume;
  394. fuelling.WritableNozzle = (e.nozzleId > 0) ? pump.Nozzles[e.nozzleId - 1] : null;
  395. fuelling.WritableCRC = 0;
  396. fuelling.WritableReservedBy = currentFuelling.WritableReservedBy;
  397. fuelling.WritableAuthorizedBy = currentFuelling.WritableAuthorizedBy;
  398. fuelling.WritableSignedReceiptLines = currentFuelling.WritableSignedReceiptLines;
  399. fuelling.WritableSignedReceiptLinesWide = currentFuelling.WritableSignedReceiptLinesWide;
  400. fuelling.WritableAuthorizationId = e.releaseToken;
  401. fuelling.WritableReservingDeviceId = e.reservingDeviceId;
  402. fuelling.WritableType = currentFuelling.WritableType;
  403. fuelling.WritableFuelPeriodId = currentFuelling.WritableFuelPeriodId;
  404. fuelling.origMessageXml = e.origMessageXml;
  405. DebugLog(String.Format("Firing FuellingStateChange: CurrentFuellingID={0}, pump={1}, state={2}, quantity={3}, amount={4}, authAS={5}, lockAS={6}, reservingDeviceId={7}",
  406. pump.CurrentFuelling.FuellingSequenceNumber, pump.realId, ((Wayne.FDCPOSLibrary.FuellingState)(pump.CurrentFuelling.State)).ToString(), pump.CurrentFuelling.Quantity, pump.CurrentFuelling.Amount, pump.CurrentFuelling.AuthorizedBy, pump.CurrentFuelling.ReservedBy,
  407. pump.CurrentFuelling.ReservingDeviceId));
  408. if (fuellingState == FuellingState.Paid)
  409. pump.WritableFuellingList.Remove(fuelling);
  410. pump.FireFuellingDataChange(pump.CurrentFuelling, pump.CurrentFuelling.Amount, pump.CurrentFuelling.Quantity);
  411. pump.FireFuellingStateChange(fuelling, fuellingState);
  412. }
  413. else
  414. DebugLog(String.Format("INVALID Nozzle: '{0}'", e.nozzleId));
  415. }
  416. else
  417. {
  418. // if fuelling exist the only item that can change is the status
  419. //if (fuellingState != fuelling.State)
  420. {
  421. fuelling.WritableState = fuellingState;
  422. int reservedBy;
  423. if (string.IsNullOrEmpty(e.lockingAS))
  424. reservedBy = 0;
  425. else if (!int.TryParse(e.lockingAS, out reservedBy))
  426. reservedBy = -1; // An external device id.
  427. fuelling.WritableReservedBy = reservedBy;
  428. if (e.transactionId == currentFuelling.TransactionId)
  429. {
  430. currentFuelling.WritableState = fuellingState;
  431. currentFuelling.WritableReservedBy = reservedBy;
  432. }
  433. DebugLog(String.Format("Firing FuellingStateChange: fuellingID={0}, pump={1}, state={2}, quantity={3}, amount={4}, authAS={5}, lockAS={6}",
  434. fuelling.FuellingSequenceNumber, ((FUSIONPump)(fuelling.Pump)).realId, ((Wayne.FDCPOSLibrary.FuellingState)(fuelling.State)).ToString(), fuelling.Quantity, fuelling.Amount, fuelling.AuthorizedBy, fuelling.ReservedBy));
  435. if (fuellingState == FuellingState.Paid)
  436. pump.WritableFuellingList.Remove(fuelling);
  437. pump.FireFuellingStateChange(fuelling, fuellingState);
  438. }
  439. }
  440. }
  441. }
  442. }
  443. catch (Exception ex)
  444. {
  445. DebugLog("Exception! " + ex.ToString());
  446. }
  447. }
  448. }
  449. public void manager_OnDeviceAlarm(object sender, DeviceAlarmEventArgs e)
  450. {
  451. int alarmCategory = getAlarmCategory(e.alarmId);
  452. int deviceType = convertDeviceType(e.deviceType);
  453. int deviceId = e.deviceId;
  454. int alarmCode = e.alarmId;
  455. string debugText = e.alarmDescr;
  456. AlarmEventArgs args = new AlarmEventArgs(deviceId, deviceType, alarmCode, alarmCategory, debugText);
  457. // low level alarm code: 4
  458. const int LOWLEVELALARMCODE = 0x1F; //15;
  459. const int NOALARMCODE = 0;
  460. if ((e.deviceType == Wayne.FDCPOSLibrary.DeviceType.DT_FuellingPoint || e.deviceType == Wayne.FDCPOSLibrary.DeviceType.DT_FuelDispenser) &&
  461. (alarmCode == 0 || alarmCode == LOWLEVELALARMCODE))
  462. {
  463. FUSIONPump pump = this.GetPumpById(deviceId);
  464. DebugLog(string.Format("pump={0}, deviceType={1}, alarmCode={2}, TankLevelSwitchStatus={3}", deviceId, deviceType, alarmCode, (pump != null) ? pump.TankLevelSwitchStatus.ToString() : "invalid"));
  465. if (pump != null)
  466. {
  467. if (alarmCode == LOWLEVELALARMCODE && pump.TankLevelSwitchStatus != TankLevelSwitchStatus.Low)
  468. {
  469. pump.WritableTankLevelSwitchStatus = TankLevelSwitchStatus.Low;
  470. }
  471. else if (alarmCode == NOALARMCODE && pump.TankLevelSwitchStatus == TankLevelSwitchStatus.Low)
  472. {
  473. pump.WritableTankLevelSwitchStatus = TankLevelSwitchStatus.Ok;
  474. }
  475. }
  476. }
  477. else
  478. this.forecourtControl.FireAlarmEvent(args);
  479. }
  480. private void manager_OnVersionInfo(object sender, VersionInfoEventArgs e)
  481. {
  482. this.release = e.release;
  483. this.version = e.version;
  484. this.hotfix = e.hotfix;
  485. versionInfoWakeUpEvent.Set();
  486. }
  487. private void manager_OnChangeFuelPrice(object sender, ChangeFuelPriceEventArgs e)
  488. {
  489. FUSIONFuelPrice fuelPrice = (FUSIONFuelPrice)this.forecourtControl.getFuelPriceByProductId(e.productId);
  490. if (forecourtControl.ForecourtConfiguration.WriteFuelPrice(e.productId, e.mode, e.newPrice))
  491. DebugLog(string.Format("FuelPriceChanged Product={0}, Mode={1}, NewPrice={2}, OldPrice={3}", e.productId, e.mode, e.newPrice, e.oldPrice));
  492. if (fuelPrice == null)
  493. return;
  494. try
  495. {
  496. FUSIONFuelPriceAddPricePerPriceGroup pgd = (FUSIONFuelPriceAddPricePerPriceGroup)(fuelPrice.PriceGroupDelta);
  497. if (pgd != null)
  498. {
  499. Monitor.Enter(fuelPrice.locker);
  500. pgd.setChanged(forecourtControl.ForecourtConfiguration.GetPriceGroups(e.mode), false);
  501. bool resetchange = true;
  502. for (int pg = PriceGroup.MinValue; pg <= PriceGroup.MaxValue; pg++)
  503. {
  504. if (pgd.getChanged(pg))
  505. {
  506. resetchange = false;
  507. break;
  508. }
  509. }
  510. if (resetchange)
  511. fuelPrice.Changed = false;
  512. }
  513. }
  514. catch (Exception ex)
  515. {
  516. DebugLog("Exception! " + ex.ToString());
  517. }
  518. finally
  519. {
  520. Monitor.Exit(fuelPrice.locker);
  521. }
  522. }
  523. private void manager_OnClearFuelSaleTrx(object sender, FuelSaleTrxEventArgs e)
  524. {
  525. // when the transaction is paid it is removed from the pump transaction list
  526. if (e.deviceType == DeviceType.DT_FuelDispenser || e.deviceType == DeviceType.DT_FuellingPoint)
  527. {
  528. FUSIONPump pump = this.GetPumpById(e.deviceId);
  529. if (pump != null)
  530. {
  531. FUSIONFuelling fuelling = (FUSIONFuelling)(pump.getFuellingByTransactionId(e.transactionId, e.releaseToken));
  532. if (fuelling != null)
  533. {
  534. fuelling.Dispose();
  535. }
  536. }
  537. }
  538. }
  539. private void manager_OnGetAvailableFuelSaleTrx(object sender, FuelSaleTrxEventArgs e)
  540. {
  541. this.forecourtControl.manager.ifsfManager.GetFuelSaleTrxDetails(e.deviceId, e.transactionId, e.releaseToken, null, null, null);
  542. }
  543. private void manager_OnConfigurationChange(object sender, EventArgs e)
  544. {
  545. DebugLog("init manager_OnConfigurationChange");
  546. _readDeviceStatusController.GetConfiguration(ReReadConfigurationComplete);
  547. DebugLog("End manager_OnConfigurationChange");
  548. }
  549. private void ReReadConfigurationComplete(object sender, AsyncCompletedEventArgs<ConfigurationSet> e)
  550. {
  551. if (!e.Success)
  552. {
  553. DebugLog("ERROR: FAiled to re-read configuration after configuration change event - give up and continue running as if nothing happened.");
  554. return;
  555. }
  556. if (BreakingChange(e.Result, CurrentConfiguration))
  557. {
  558. DebugLog("Configuration change - and after reading configuration found there were breaking changes - applying configuration and changing connection state");
  559. forecourtControl.ReadStatusBeforeSetConnectionState(DeviceConnectionState.Connecting);
  560. DestroyObjects(false);
  561. ApplyConfigurationSet(e.Result);
  562. this.forecourtControl.ReadStatusBeforeSetConnectionState(DeviceConnectionState.Connected);
  563. }
  564. else
  565. {
  566. DebugLog("Configuration change - after reading configuration found there were NO breaking changes continue operating without change");
  567. }
  568. if (FUSIONConfigFactory.getConfigurator() != null)
  569. {
  570. DebugLog("Configuration change event fired");
  571. FUSIONConfigFactory.getConfigurator().FireOnConfigurationChanged();
  572. }
  573. }
  574. /// <summary>
  575. /// Method that determines if a configuration change from FDC
  576. /// is a breaking change so that we should toggle the connection state.
  577. /// This is done by comparing the current configuration set with a newly read set.
  578. /// </summary>
  579. /// <param name="newConfigurationSet"></param>
  580. /// <param name="currentConfiguration"></param>
  581. /// <returns></returns>
  582. private bool BreakingChange(ConfigurationSet newConfigurationSet, ConfigurationSet currentConfiguration)
  583. {
  584. //Added pump, removed pump
  585. var newPumpIds = newConfigurationSet.PumpNumbers();
  586. var oldPumpIds = currentConfiguration.PumpNumbers();
  587. if (!newPumpIds.SequenceEqual(oldPumpIds))
  588. {
  589. DebugLog("Breaking change : Pump Ids does not match");
  590. return true;
  591. }
  592. //Added nozzle, removed nozzle, changed product, Tank association for nozzle
  593. var newNozzleSetup = newConfigurationSet.NozzleSetup();
  594. var currentNozzleSetup = currentConfiguration.NozzleSetup();
  595. if (!newNozzleSetup.SequenceEqual(currentNozzleSetup))
  596. {
  597. DebugLog("Breaking change : Nozzle setup does not match");
  598. return true;
  599. }
  600. //Added / Removed product
  601. var newProductNumbers = newConfigurationSet.ProductNumbers();
  602. var currentProductNumbers = currentConfiguration.ProductNumbers();
  603. if (!newProductNumbers.SequenceEqual(currentProductNumbers))
  604. {
  605. DebugLog("Breaking change: Changed product setup");
  606. return true;
  607. }
  608. return false;
  609. }
  610. private void manager_OnTwinMasterReady(object sender, EventArgs e)
  611. {
  612. DebugLog("init manager_OnTwinMasterReady");
  613. try
  614. {
  615. if (FUSIONTwinFactory.getTwin() != null)
  616. ((FUSIONTwin)(FUSIONTwinFactory.getTwin())).FireOnTwinMasterReady();
  617. else
  618. DebugLog("manager_OnTwinMasterReady - twin NOT created");
  619. }
  620. catch (Exception ex)
  621. {
  622. }
  623. DebugLog("End manager_OnTwinMasterReady");
  624. }
  625. private void manager_OnOptRead(object sender, OptReadEventArgs e)
  626. {
  627. DebugLog("init");
  628. OptReadEventArgs args = new OptReadEventArgs(e.deviceType, e.deviceId, e.message);
  629. if (FUSIONOptFactory.getOptBridge() != null)
  630. ((FUSIONOptBridge)(FUSIONOptFactory.getOptBridge())).FireOnDataRead(e.deviceId, e.message);
  631. DebugLog("End");
  632. }
  633. public bool CheckConfiguration(ServiceResponseGetConfiguration sr)
  634. {
  635. DebugLog("init CheckConfiguration");
  636. bool bResult = true;
  637. foreach (ServiceDeviceClassConfiguration deviceClass in sr.FDCdata[0].DeviceClass)
  638. {
  639. switch (deviceClass.Type)
  640. {
  641. case Wayne.FDCPOSLibrary.DeviceType.DT_FuelDispenser:
  642. {
  643. //look for FuellingPoint in actual configuration
  644. if (!ConfigPump(deviceClass.DeviceClass[0]))
  645. bResult = false;
  646. }
  647. break;
  648. case Wayne.FDCPOSLibrary.DeviceType.DT_FuellingPoint:
  649. {
  650. //look for FuellingPoint in actual configuration
  651. if (!ConfigPump(deviceClass))
  652. bResult = false;
  653. }
  654. break;
  655. case Wayne.FDCPOSLibrary.DeviceType.DT_TankLevelGauge:
  656. case Wayne.FDCPOSLibrary.DeviceType.DT_TankProbe:
  657. case Wayne.FDCPOSLibrary.DeviceType.DT_PricePole:
  658. break;
  659. }
  660. }
  661. //look for actual pump in new configuration
  662. foreach (FUSIONPump pump in forecourtControl.WritablePumpList)
  663. {
  664. var bPumpFound = false;
  665. foreach (ServiceDeviceClassConfiguration deviceClass in sr.FDCdata[0].DeviceClass)
  666. {
  667. if (deviceClass.Type != Wayne.FDCPOSLibrary.DeviceType.DT_FuellingPoint && deviceClass.Type != Wayne.FDCPOSLibrary.DeviceType.DT_FuelDispenser)
  668. continue;
  669. if (Convert.ToInt32(deviceClass.FPPumpNo) == pump.realId)
  670. {
  671. bPumpFound = true;
  672. break;
  673. }
  674. }
  675. if (!bPumpFound)
  676. {
  677. DebugLog(string.Format("pump {0} not found in new configuration", pump.realId));
  678. DeviceAlarmEventArgs arg = new DeviceAlarmEventArgs(Wayne.FDCPOSLibrary.DeviceType.DT_FuellingPoint, pump.realId, (int)Wayne.FDCPOSLibrary.ErrorCode.ERRCD_BADCONF, string.Format("Pump {0} not found in new configuration", pump.Id));
  679. this.manager_OnDeviceAlarm(this, arg);
  680. bResult = false;
  681. }
  682. }
  683. DebugLog("end CheckConfiguration");
  684. return bResult;
  685. }
  686. internal bool ConfigPump(ServiceDeviceClassConfiguration deviceClass)
  687. {
  688. bool bResult = true;
  689. bool bFPFound = false;
  690. foreach (FUSIONPump pump in this.forecourtControl.WritablePumpList)
  691. {
  692. if (pump.realId == Convert.ToInt32(deviceClass.FPPumpNo))
  693. {
  694. bFPFound = true;
  695. bool bNozzleFound = false;
  696. foreach (ServiceNozzleFPDeviceClassConfiguration FPNozzle in deviceClass.FPNozzle)
  697. {
  698. string productNo = FPNozzle.FPProductId[0].PIFPProductNo ?? FPNozzle.FPProductId[0].PIFPProductNo1;
  699. bNozzleFound = false;
  700. foreach (FUSIONNozzle nozzle in pump.Nozzles)
  701. {
  702. if (nozzle.realId == Convert.ToInt32(FPNozzle.FPNozzleNo))
  703. {
  704. bNozzleFound = true;
  705. if (nozzle.WritableFuelGrade != Convert.ToInt32(productNo))
  706. {
  707. DebugLog(string.Format("pump {0}, nozzle {1}, new product {2}, old product = {3} ", pump.realId, FPNozzle.FPNozzleNo, FPNozzle.FPProductId, nozzle.WritableFuelGrade));
  708. DeviceAlarmEventArgs arg = new DeviceAlarmEventArgs(Wayne.FDCPOSLibrary.DeviceType.DT_FuellingPoint, pump.realId, (int)Wayne.FDCPOSLibrary.ErrorCode.ERRCD_BADCONF, string.Format("Pump {0}: nozzle {1} new productNo {2} configured productNo {3}", pump.Id, FPNozzle.FPNozzleNo, productNo, nozzle.WritableFuelGrade));
  709. this.manager_OnDeviceAlarm(this, arg);
  710. bResult = false;
  711. }
  712. break;
  713. }
  714. }
  715. if (!bNozzleFound)
  716. {
  717. DebugLog(string.Format("pump {0}, nozzle {1}, product {2} not found in actual configuration", pump.realId, FPNozzle.FPNozzleNo, FPNozzle.FPProductId));
  718. DeviceAlarmEventArgs arg = new DeviceAlarmEventArgs(Wayne.FDCPOSLibrary.DeviceType.DT_FuellingPoint, pump.realId, (int)Wayne.FDCPOSLibrary.ErrorCode.ERRCD_BADCONF, string.Format("Pump {0}: new nozzle {1} productNo {2} not configured", pump.Id, FPNozzle.FPNozzleNo, productNo));
  719. this.manager_OnDeviceAlarm(this, arg);
  720. bResult = false;
  721. }
  722. }
  723. foreach (FUSIONNozzle nozzle in pump.Nozzles)
  724. {
  725. bNozzleFound = false;
  726. foreach (ServiceNozzleFPDeviceClassConfiguration FPNozzle in deviceClass.FPNozzle)
  727. {
  728. if (nozzle.realId == Convert.ToInt32(FPNozzle.FPNozzleNo))
  729. {
  730. bNozzleFound = true;
  731. break;
  732. }
  733. }
  734. if (!bNozzleFound)
  735. {
  736. DebugLog(string.Format("pump {0}, nozzle {1}, product {2} not found in new configuration", pump.realId, nozzle.Id, nozzle.WritableFuelGrade));
  737. DeviceAlarmEventArgs arg = new DeviceAlarmEventArgs(Wayne.FDCPOSLibrary.DeviceType.DT_FuellingPoint, pump.realId, (int)Wayne.FDCPOSLibrary.ErrorCode.ERRCD_BADCONF, string.Format("Pump {0}: nozzle {1} productNo {2} not found in new configuration", pump.Id, nozzle.Id, nozzle.WritableFuelGrade));
  738. this.manager_OnDeviceAlarm(this, arg);
  739. bResult = false;
  740. break;
  741. }
  742. }
  743. break;
  744. }
  745. }
  746. if (!bFPFound)
  747. {
  748. bResult = false;
  749. DebugLog(string.Format("pump {0} not found in old configuration", deviceClass.FPPumpNo));
  750. DeviceAlarmEventArgs arg = new DeviceAlarmEventArgs(Wayne.FDCPOSLibrary.DeviceType.DT_FuellingPoint, Convert.ToInt32(deviceClass.FPPumpNo), (int)Wayne.FDCPOSLibrary.ErrorCode.ERRCD_BADCONF, string.Format("Pump {0} not found in previous configuration", deviceClass.FPPumpNo));
  751. this.manager_OnDeviceAlarm(this, arg);
  752. }
  753. return bResult;
  754. }
  755. internal bool Connect(string connectionString)
  756. {
  757. return this.ifsfManager.clientSocket.Connect(connectionString);
  758. }
  759. private void DestroyObjects(bool bDisconnect)
  760. {
  761. foreach (FUSIONPump pump in this.forecourtControl.WritablePumpList)
  762. {
  763. pump.Dispose();
  764. }
  765. this.forecourtControl.WritablePumpList.Clear();
  766. this.forecourtControl.WritableTankGroupList.Clear();
  767. this.forecourtControl.WritablePricePoleList.Clear();
  768. this.forecourtControl.WritableFuelPriceList.Clear();
  769. if (bDisconnect)
  770. ifsfManager.Disconnect();
  771. }
  772. internal void Disconnect()
  773. {
  774. if (FUSIONOptFactory.getOptBridge() != null)
  775. {
  776. foreach (IOpt opt in ((FUSIONOptBridge)(FUSIONOptFactory.getOptBridge())).Opts)
  777. {
  778. if (((FUSIONOpt)opt).managedBy == OPTManagedBy.SINP)
  779. ((FUSIONOpt)opt).optTCP.Disconnect();
  780. else
  781. this.ifsfManager.OptRemove(opt.Id, null, null, null);
  782. }
  783. }
  784. this.ifsfManager.LogOff();
  785. }
  786. public void Dispose()
  787. {
  788. this.Dispose(true);
  789. GC.SuppressFinalize(this);
  790. }
  791. private void Dispose(bool disposing)
  792. {
  793. if (!this.disposed)
  794. {
  795. this.disposed = true;
  796. if (disposing)
  797. {
  798. this.ifsfManager.clientSocket.OnConnectionStateChange -= clientSocket_OnConnectionStateChange;
  799. this.DestroyObjects(true);
  800. ifsfManager.Dispose();
  801. debugLogger.Dispose();
  802. }
  803. }
  804. }
  805. ~FUSIONManager()
  806. {
  807. this.Dispose(false);
  808. }
  809. public FUSIONPump GetPumpById(int pumpNumber)
  810. {
  811. foreach (FUSIONPump pump in this.forecourtControl.Pumps)
  812. {
  813. if (pump.realId == pumpNumber)
  814. {
  815. return pump;
  816. }
  817. }
  818. return null;
  819. }
  820. public FUSIONTankGroup getTankGroupByIndex(int iTankGroupId)
  821. {
  822. foreach (FUSIONTankGroup tankgroup in this.forecourtControl.TankGroups)
  823. {
  824. if (tankgroup.Id == iTankGroupId)
  825. {
  826. return tankgroup;
  827. }
  828. }
  829. return null;
  830. }
  831. public FUSIONTank getTankByIndex(int iTankGroupId, int iTankId)
  832. {
  833. foreach (FUSIONTankGroup tankgroup in this.forecourtControl.TankGroups)
  834. {
  835. if (tankgroup.Id == iTankGroupId)
  836. {
  837. foreach (FUSIONTank tank in tankgroup.Tanks)
  838. {
  839. if (tank.Id == iTankId)
  840. return tank;
  841. }
  842. }
  843. }
  844. return null;
  845. }
  846. public FUSIONTank getTankByIndex(int iTankId)
  847. {
  848. foreach (FUSIONTankGroup tankgroup in this.forecourtControl.TankGroups)
  849. {
  850. foreach (FUSIONTank tank in tankgroup.Tanks)
  851. {
  852. if (tank.Id == iTankId)
  853. return tank;
  854. }
  855. }
  856. return null;
  857. }
  858. private void ConfigurationSetComplete(object sender, AsyncCompletedEventArgs<ReadDeviceStatus.ConfigurationSet> e)
  859. {
  860. if (!e.Success)
  861. {
  862. DebugLog("Failed to read configuration, retrying!");
  863. Disconnect();
  864. return;
  865. }
  866. ApplyConfigurationSet(e.Result);
  867. this.forecourtControl.ReadStatusBeforeSetConnectionState(DeviceConnectionState.Connected);
  868. }
  869. private void ApplyConfigurationSet(ConfigurationSet configurationSet)
  870. {
  871. CurrentConfiguration = configurationSet;
  872. configurationReader.ReadProductTable(CurrentConfiguration.ProductTable);
  873. configurationReader.ReadFuelProducts(CurrentConfiguration.ProductTable);
  874. configurationReader.ReadConfiguration(CurrentConfiguration.DspConfiguration);
  875. configurationReader.ReadConfiguration(CurrentConfiguration.TlgConfiguration);
  876. configurationReader.ReadSomePriceGroupInformation(CurrentConfiguration.DspConfiguration);
  877. }
  878. internal void RequestFillingData(int pumpNumber, bool onlyCurrentFuelling)
  879. {
  880. this.ifsfManager.GetCurrentFuellingStatus(pumpNumber, null, null, null);
  881. }
  882. // Properties
  883. public string EntitySubType
  884. {
  885. get
  886. {
  887. return "";
  888. }
  889. }
  890. public string EntityType
  891. {
  892. get
  893. {
  894. return "FUSIONManager";
  895. }
  896. }
  897. /// <summary>
  898. /// This is used by the logger and should never be set by inheriting classes
  899. /// </summary>
  900. public string FullEntityName { get; set; }
  901. public int Id
  902. {
  903. get
  904. {
  905. return this.forecourtControl.Id;
  906. }
  907. }
  908. public IIdentifiableEntity ParentEntity
  909. {
  910. get
  911. {
  912. return null;
  913. }
  914. }
  915. public List<IFuelPriceReading> FuelPriceReadings { get; private set; }
  916. }
  917. // Nested Types
  918. internal class ConfigurationReader
  919. {
  920. // Fields
  921. private readonly FUSIONManager fusionManager;
  922. private readonly DebugLogger debugLogger;
  923. // Methods
  924. public ConfigurationReader(FUSIONManager fusionManager)
  925. {
  926. this.fusionManager = fusionManager;
  927. debugLogger = fusionManager.DebugLogger;
  928. }
  929. private void DebugLog(string s)
  930. {
  931. if (debugLogger.IsActive())
  932. debugLogger.Add(s);
  933. }
  934. public void ReadProductTable(ServiceResponseGetProductTable sr)
  935. {
  936. if (sr == null || (sr.OverallResult != FDCPOSLibrary.OverallResult.Success.ToString() && sr.OverallResult != "") ||
  937. sr.FDCdata == null || sr.FDCdata.Length == 0 ||
  938. sr.FDCdata[0].FuelProducts == null || sr.FDCdata[0].FuelProducts.Length == 0 ||
  939. sr.FDCdata[0].FuelProducts[0].Product == null || sr.FDCdata[0].FuelProducts[0].Product.Length == 0)
  940. {
  941. DebugLog("error in ServiceResponseGetProductTable");
  942. DeviceAlarmEventArgs arg = new DeviceAlarmEventArgs(Wayne.FDCPOSLibrary.DeviceType.DT_FuellingPoint, 0, (int)Wayne.FDCPOSLibrary.ErrorCode.ERRCD_BADCONF, "Error in GetProductTable");
  943. fusionManager.manager_OnDeviceAlarm(fusionManager, arg);
  944. return;
  945. }
  946. try
  947. {
  948. if (fusionManager.forecourtControl.WritableFuelPriceList.Count > 0)
  949. {
  950. DebugLog(string.Format("forecourtControl.WritableFuelPriceList.Count = {0}, verify prices", fusionManager.forecourtControl.WritableFuelPriceList.Count));
  951. //verify product numberl
  952. if (fusionManager.forecourtControl.WritableFuelPriceList.Count != sr.FDCdata[0].FuelProducts[0].Product.Length)
  953. {
  954. DebugLog(string.Format("forecourtControl.WritableFuelPriceList.Count = {0}, sr.FDCData[0].FuelProducts.Lenght = {1}", fusionManager.forecourtControl.WritableFuelPriceList.Count, sr.FDCdata[0].FuelProducts.Length));
  955. DeviceAlarmEventArgs arg = new DeviceAlarmEventArgs(Wayne.FDCPOSLibrary.DeviceType.DT_FuellingPoint, 0, (int)Wayne.FDCPOSLibrary.ErrorCode.ERRCD_BADCONF, string.Format("GetProductTable: product number received ({0}) differs from product number cofigured ({1})", sr.FDCdata[0].FuelProducts[0].Product.Length, fusionManager.forecourtControl.WritableFuelPriceList.Count));
  956. fusionManager.manager_OnDeviceAlarm(fusionManager, arg);
  957. }
  958. foreach (FUSIONFuelPrice fuelprice in fusionManager.forecourtControl.WritableFuelPriceList)
  959. {
  960. bool bFound = false;
  961. foreach (ServiceResponseProductGetProductTable product in sr.FDCdata[0].FuelProducts[0].Product)
  962. {
  963. if (Convert.ToInt32(product.ProductNo) == fuelprice.WritableFuelGrade)
  964. {
  965. bFound = true;
  966. break;
  967. }
  968. }
  969. if (!bFound)
  970. {
  971. DeviceAlarmEventArgs arg = new DeviceAlarmEventArgs(Wayne.FDCPOSLibrary.DeviceType.DT_FuellingPoint, 0, (int)Wayne.FDCPOSLibrary.ErrorCode.ERRCD_BADCONF, string.Format("GetProductTable: product {0} not present in new configuration", fuelprice.WritableFuelGrade));
  972. fusionManager.manager_OnDeviceAlarm(fusionManager, arg);
  973. break;
  974. }
  975. }
  976. foreach (ServiceResponseProductGetProductTable product in sr.FDCdata[0].FuelProducts[0].Product)
  977. {
  978. bool bFound = false;
  979. foreach (FUSIONFuelPrice fuelprice in fusionManager.forecourtControl.WritableFuelPriceList)
  980. {
  981. if (Convert.ToInt32(product.ProductNo) == fuelprice.WritableFuelGrade)
  982. {
  983. bFound = true;
  984. break;
  985. }
  986. }
  987. if (!bFound)
  988. {
  989. DeviceAlarmEventArgs arg = new DeviceAlarmEventArgs(Wayne.FDCPOSLibrary.DeviceType.DT_FuellingPoint, 0, (int)Wayne.FDCPOSLibrary.ErrorCode.ERRCD_BADCONF, string.Format("GetProductTable: product {0} not present in previous configuration", product.ProductNo));
  990. fusionManager.manager_OnDeviceAlarm(fusionManager, arg);
  991. break;
  992. }
  993. }
  994. }
  995. else
  996. {
  997. foreach (ServiceResponseProductGetProductTable product in sr.FDCdata[0].FuelProducts[0].Product)
  998. {
  999. FUSIONFuelPrice fuelprice = new FUSIONFuelPrice(Convert.ToInt32(product.ProductNo), fusionManager);
  1000. fusionManager.forecourtControl.WritableFuelPriceList.Add(fuelprice);
  1001. }
  1002. }
  1003. }
  1004. catch (Exception exception)
  1005. {
  1006. }
  1007. DebugLog("end");
  1008. }
  1009. public void ReadConfiguration(ServiceResponseGetConfiguration sr)
  1010. {
  1011. DebugLog("init ReadConfiguration");
  1012. try
  1013. {
  1014. if (sr == null ||
  1015. ((sr.RequestType == "GetDSPConfiguration" || sr.RequestType == "GetConfiguration") &&
  1016. sr.OverallResult != FDCPOSLibrary.OverallResult.Success.ToString()) ||
  1017. (sr.RequestType == "GetTLGConfiguration" &&
  1018. sr.OverallResult != FDCPOSLibrary.OverallResult.Success.ToString() &&
  1019. sr.OverallResult != FDCPOSLibrary.OverallResult.NoData.ToString() &&
  1020. sr.OverallResult != FDCPOSLibrary.OverallResult.WrongConfiguration.ToString()) ||
  1021. sr.FDCdata == null || sr.FDCdata.Length == 0 ||
  1022. ((sr.RequestType == "GetDSPConfiguration" || sr.RequestType == "GetConfiguration") &&
  1023. (sr.FDCdata[0].DeviceClass == null || sr.FDCdata[0].DeviceClass.Length == 0)))
  1024. {
  1025. DebugLog("end ReadConfiguration - error in ServiceResponseGetConfiguration");
  1026. DeviceAlarmEventArgs arg =
  1027. new DeviceAlarmEventArgs(Wayne.FDCPOSLibrary.DeviceType.DT_FuellingPoint, 0,
  1028. (int)Wayne.FDCPOSLibrary.ErrorCode.ERRCD_BADCONF,
  1029. string.Format("error in Getconfiguration"));
  1030. fusionManager.manager_OnDeviceAlarm(fusionManager, arg);
  1031. return;
  1032. }
  1033. try
  1034. {
  1035. if (fusionManager.forecourtControl.WritablePumpList.Count > 0 &&
  1036. (sr.RequestType == "GetConfiguration" || sr.RequestType == "GetDSPConfiguration"))
  1037. {
  1038. DebugLog(
  1039. string.Format(
  1040. "end ReadConfiguration - forecourtControl.WritablePumpList.Count = {0}, call CheckConfiguration",
  1041. fusionManager.forecourtControl.WritablePumpList.Count));
  1042. if (!fusionManager.CheckConfiguration(sr))
  1043. {
  1044. DebugLog("Configurazione Fusion != Configurazione interna, send Alarm");
  1045. }
  1046. return;
  1047. }
  1048. else if (fusionManager.forecourtControl.WritableTankGroupList.Count > 0 &&
  1049. sr.RequestType == "GetTLGConfiguration")
  1050. {
  1051. DebugLog(
  1052. string.Format(
  1053. "end ReadConfiguration - forecourtControl.WritableTankGroupList.Count = {0}, call CheckConfiguration",
  1054. fusionManager.forecourtControl.WritableTankGroupList.Count));
  1055. if (!fusionManager.CheckConfiguration(sr))
  1056. {
  1057. DebugLog("Configurazione Fusion != Configurazione interna, send Alarm");
  1058. }
  1059. return;
  1060. }
  1061. if (sr.FDCdata[0].DeviceClass != null)
  1062. {
  1063. foreach (ServiceDeviceClassConfiguration deviceClass in sr.FDCdata[0].DeviceClass)
  1064. {
  1065. switch (deviceClass.Type)
  1066. {
  1067. case Wayne.FDCPOSLibrary.DeviceType.DT_FuelDispenser:
  1068. {
  1069. ReadPriceConfiguration(deviceClass);
  1070. }
  1071. //read FP configuration
  1072. foreach (var dc in deviceClass.DeviceClass)
  1073. {
  1074. if (dc.Type == Wayne.FDCPOSLibrary.DeviceType.DT_FuellingPoint)
  1075. ReadPumpConfiguration(dc);
  1076. }
  1077. break;
  1078. case Wayne.FDCPOSLibrary.DeviceType.DT_FuellingPoint:
  1079. {
  1080. ReadPumpConfiguration(deviceClass);
  1081. }
  1082. break;
  1083. case Wayne.FDCPOSLibrary.DeviceType.DT_TankLevelGauge:
  1084. {
  1085. DebugLog(string.Format("DT_TankLevelGauge.Add id={0}",
  1086. deviceClass.DeviceID));
  1087. foreach (
  1088. ServiceDeviceClassConfiguration nestedDevice in deviceClass.DeviceClass)
  1089. {
  1090. // only 1 tankgroup per product will be created
  1091. FUSIONTankGroup tankgroup =
  1092. fusionManager.getTankGroupByIndex(
  1093. Convert.ToInt32(nestedDevice.TPProductNo));
  1094. if (tankgroup == null)
  1095. {
  1096. tankgroup = new FUSIONTankGroup(fusionManager,
  1097. Convert.ToInt32(
  1098. nestedDevice.TPProductNo),
  1099. Convert.ToInt32(
  1100. nestedDevice.TPProductNo));
  1101. fusionManager.forecourtControl.WritableTankGroupList.Add(tankgroup);
  1102. }
  1103. FUSIONTank tank = new FUSIONTank(fusionManager,
  1104. Convert.ToInt32(nestedDevice.TPTankNo),
  1105. tankgroup);
  1106. tankgroup.WritableTankList.Add(tank);
  1107. DebugLog(string.Format("WritableTankList.Add tank={0}",
  1108. tank.realId));
  1109. }
  1110. }
  1111. break;
  1112. }
  1113. }
  1114. }
  1115. }
  1116. catch (Exception exception)
  1117. {
  1118. DebugLog(string.Format("Exception! : {0}", exception.ToString()));
  1119. }
  1120. }
  1121. finally
  1122. {
  1123. DebugLog("ReadConfiguration finally");
  1124. fusionManager.forecourtControl.FireConfigurationChangeEvent(new ConfigurationChangeEventArgs());
  1125. }
  1126. DebugLog("end ReadConfiguration");
  1127. }
  1128. private void ReadPumpConfiguration(ServiceDeviceClassConfiguration deviceClass)
  1129. {
  1130. FUSIONPump pump = new FUSIONPump(fusionManager);
  1131. pump.WritableParentDevice = fusionManager.forecourtControl;
  1132. pump.WritableCapFuelGradeSelected = false;
  1133. pump.WritableCapNozzleDetection = true;
  1134. pump.WritableCapSetLight = false;
  1135. pump.WritableCapSuspendFuelling = true;
  1136. pump.WritablePumpId = Convert.ToInt32(deviceClass.FPPumpNo);
  1137. pump.WritableDeviceName = "Pump " + deviceClass.FPPumpNo;
  1138. foreach (ServiceNozzleFPDeviceClassConfiguration FPnozzle in deviceClass.FPNozzle)
  1139. {
  1140. string productNo = FPnozzle.FPProductId[0].PIFPProductNo ?? FPnozzle.FPProductId[0].PIFPProductNo1;
  1141. FUSIONNozzle nozzle = new FUSIONNozzle(Convert.ToInt32(FPnozzle.FPNozzleNo), fusionManager, pump);
  1142. nozzle.WritableFuelGrade = Convert.ToInt32(productNo);
  1143. nozzle.PrimaryTankNo = (FPnozzle.FPProductId[0].PIFPProductNo != null) ? Convert.ToInt32(FPnozzle.FPProductId[0].PIFPTankNo1) : 0; ;
  1144. nozzle.SecondaryTankNo = (FPnozzle.FPProductId[0].PIFPProductNo != null) ? Convert.ToInt32(FPnozzle.FPProductId[0].PIFPTankNo2) : 0;
  1145. bool bFound = false;
  1146. foreach (FUSIONFuelPrice fuelprice in fusionManager.forecourtControl.WritableFuelPriceList)
  1147. {
  1148. if (fuelprice.WritableFuelGrade == Convert.ToInt32(productNo))
  1149. {
  1150. bFound = true;
  1151. break;
  1152. }
  1153. }
  1154. if (!bFound)
  1155. {
  1156. DeviceAlarmEventArgs arg = new DeviceAlarmEventArgs(Wayne.FDCPOSLibrary.DeviceType.DT_FuellingPoint, pump.realId, (int)Wayne.FDCPOSLibrary.ErrorCode.ERRCD_BADCONF, string.Format("Pump {0} nozzle {1}: product {2} is not a valid productNo", pump.Id, nozzle.Id, FPnozzle.FPProductId[0].PIFPProductNo));
  1157. fusionManager.manager_OnDeviceAlarm(fusionManager, arg);
  1158. }
  1159. pump.WritableNozzleList.Add(nozzle);
  1160. }
  1161. fusionManager.forecourtControl.WritablePumpList.Add(pump);
  1162. DebugLog(string.Format("WritablePumpList.Add pump={0}", pump.realId));
  1163. }
  1164. protected void ReadPriceConfiguration(ServiceDeviceClassConfiguration deviceClass)
  1165. {
  1166. foreach (var product in deviceClass.DSPProduct)
  1167. {
  1168. FUSIONFuelPrice foundPrice = null;
  1169. foreach (FUSIONFuelPrice fuelprice in fusionManager.forecourtControl.WritableFuelPriceList)
  1170. {
  1171. if (Convert.ToInt32(product.DSPProductNo) == fuelprice.WritableFuelGrade)
  1172. {
  1173. foundPrice = fuelprice;
  1174. break;
  1175. }
  1176. }
  1177. if (foundPrice == null)
  1178. {
  1179. DeviceAlarmEventArgs arg = new DeviceAlarmEventArgs(Wayne.FDCPOSLibrary.DeviceType.DT_FuellingPoint, 0, (int)Wayne.FDCPOSLibrary.ErrorCode.ERRCD_BADCONF, string.Format("ReadPriceConfiguration: product {0} not present in new configuration", product.DSPProductNo));
  1180. fusionManager.manager_OnDeviceAlarm(fusionManager, arg);
  1181. break;
  1182. }
  1183. else
  1184. {
  1185. foundPrice.WritableReserved = true;
  1186. }
  1187. }
  1188. }
  1189. /// <summary>
  1190. /// Price group information - this code was moved here from Ifsf manager.
  1191. /// should probably be moved together with rest of Pump initialization on the
  1192. /// next refactor.
  1193. /// </summary>
  1194. /// <param name="sr"></param>
  1195. public void ReadSomePriceGroupInformation(ServiceResponseGetDSPConfiguration sr)
  1196. {
  1197. if (sr.FDCdata[0] != null && sr.FDCdata[0].DeviceClass != null)
  1198. {
  1199. foreach (var deviceClass in sr.FDCdata[0].DeviceClass)
  1200. {
  1201. if (deviceClass.DSPProduct == null) continue;
  1202. foreach (var product in deviceClass.DSPProduct)
  1203. {
  1204. if (product == null) continue;
  1205. foreach (var dspFuelPrice in product.DSPFuelPrice)
  1206. {
  1207. var foundNew = true;
  1208. var priceGroup = fusionManager.forecourtControl.ForecourtConfiguration.GetPriceGroup(Convert.ToInt32(dspFuelPrice.FPDSPModeNo), FuellingType.OptCardPaid);
  1209. foreach (var reading in fusionManager.FuelPriceReadings)
  1210. {
  1211. if (reading.Fuelgrade == Convert.ToInt32(product.DSPProductNo) && reading.PriceGroup == priceGroup)
  1212. foundNew = false;
  1213. }
  1214. if (foundNew)
  1215. {
  1216. var fuelPriceReading = new FuelPriceReading(Convert.ToInt32(product.DSPProductNo), priceGroup, FDCConvert.ToDecimal(dspFuelPrice.FPDSPPrice), null);
  1217. fusionManager.FuelPriceReadings.Add(fuelPriceReading);
  1218. }
  1219. }
  1220. }
  1221. }
  1222. }
  1223. }
  1224. /// <summary>
  1225. /// Populate the forecourtControl.FuelProducts array
  1226. /// </summary>
  1227. /// <param name="sr"></param>
  1228. public void ReadFuelProducts(ServiceResponseGetProductTable sr)
  1229. {
  1230. fusionManager.forecourtControl.WritableFuelProducts.Clear();
  1231. foreach (var product in sr.FDCdata[0].FuelProducts[0].Product)
  1232. {
  1233. var fuelProduct = new FuelProduct(Convert.ToInt32(product.ProductNo), product.ProductName);
  1234. fusionManager.forecourtControl.WritableFuelProducts.Add(fuelProduct);
  1235. }
  1236. }
  1237. }
  1238. }