ATG_Reading_Test.cs 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402
  1. using Application.ATG_Classic_App;
  2. using Application.ATG_Classic_App.Model;
  3. using AutoMapper;
  4. using Edge.Core.Processor;
  5. using Edge.Core.IndustryStandardInterface.Pump;
  6. using Edge.Core.IndustryStandardInterface.ATG;
  7. using Microsoft.EntityFrameworkCore;
  8. using Microsoft.Extensions.DependencyInjection;
  9. using Microsoft.Extensions.Logging;
  10. using Microsoft.Extensions.Logging.Abstractions;
  11. using Microsoft.VisualStudio.TestTools.UnitTesting;
  12. using System;
  13. using System.Collections.Generic;
  14. using System.IO;
  15. using System.Linq;
  16. using System.Reflection;
  17. using System.Text.Json;
  18. using System.Threading.Tasks;
  19. using Edge.Core.UniversalApi;
  20. namespace Application.ATG_Classic_App_Test
  21. {
  22. [TestClass]
  23. public class ATG
  24. {
  25. static int TankCount = 6;
  26. //ServiceProvider serviceProvider;
  27. static List<MockProbeHandler> probeHandlers;
  28. static ATG_Classic_App.App atg;
  29. static List<TankProfileData> sharedTankProfileDatas;
  30. static IEnumerable<TankConfig> tankConfigs;
  31. static TankOverallConfig tankOverallConfig;
  32. static int InventorySamplingInterval = 5000;
  33. [ClassInitialize]
  34. public static void ClassInit(TestContext context)
  35. {
  36. var services = new ServiceCollection();
  37. services.AddSingleton<ILoggerFactory>(NullLoggerFactory.Instance);
  38. #region AutoMapper, resolve all assemblies under entry folder.
  39. var applicationAssFileInfos = new DirectoryInfo(Directory.GetCurrentDirectory())
  40. .GetFiles().Where(f => //f.Name.ToLower().StartsWith("application") &&
  41. f.Extension != null
  42. && (f.Extension.ToLower() == ".dll" || f.Extension.ToLower() == ".exe"));
  43. var assembliesWithAutoMapperProfileDefined = new List<Assembly>();
  44. foreach (var ai in applicationAssFileInfos)
  45. {
  46. try
  47. {
  48. var ass = Assembly.LoadFrom(ai.FullName);
  49. if (ass.GetTypes().Any(t => typeof(Profile).IsAssignableFrom(t)))
  50. assembliesWithAutoMapperProfileDefined.Add(ass);
  51. }
  52. catch
  53. { }
  54. }
  55. services.AddAutoMapper(assembliesWithAutoMapperProfileDefined);
  56. services.AddSingleton(new UniversalApiHub(null, null));
  57. #endregion
  58. var serviceProvider = services.BuildServiceProvider();
  59. probeHandlers = Enumerable.Range(1, TankCount).Select(i => new MockProbeHandler(i, i * 1000)).ToList();
  60. sharedTankProfileDatas = Enumerable.Range(0, 2001).Select(i =>
  61. new TankProfileData()
  62. {
  63. BatchLabel = "shitday",
  64. Height = i,
  65. Volume = i * 2
  66. }).ToList();
  67. tankConfigs = Enumerable.Range(1, TankCount).Select(i => new TankConfig()
  68. {
  69. TankNumber = (byte)i,
  70. Label = "I'm Tank with Number " + i,
  71. Diameter = i * 1000,
  72. ProbeConfig = new ProbeConfig() { DeviceId = i },
  73. ProductConfig = new ProductConfig() { ProductCode = (i + 90).ToString(), ProductLabel = (i + 90).ToString() + "#" },
  74. TankLimitConfig = new TankLimitConfig()
  75. {
  76. FullVolume = 1200 * i,
  77. MaxVolume = 1100 * i,
  78. HighProduct = 900 * i,
  79. LowProduct = 100 * i,
  80. HighWaterWarning = 10 * i,
  81. HighWaterAlarm = 40 * i,
  82. FuelTemperatureLowLimit = i,
  83. FuelTemperatureHighLimit = 2 * i
  84. },
  85. });
  86. tankOverallConfig = new TankOverallConfig() { TcReference = 25, InventorySamplingInterval = InventorySamplingInterval };
  87. var dbContextFactory = new DefaultDbContextFactory();
  88. dbContextFactory.AddProvider(new InMemoryDbContextProvider());
  89. atg = new ATG_Classic_App.App(serviceProvider, 1, true);
  90. atg.DbContextFactory = dbContextFactory;
  91. atg.Init(probeHandlers.Cast<IProcessor>());
  92. var _ = atg.UpsertConfigAsync(tankOverallConfig).Result;
  93. foreach (var tc in tankConfigs)
  94. {
  95. var xx = atg.UpsertConfigAsync(tc).Result;
  96. }
  97. foreach (var tc in tankConfigs)
  98. {
  99. var xx = atg.AddTankProfileDataAsync(
  100. tc.TankNumber,
  101. sharedTankProfileDatas.Select(d => d.Height.ToString() + ":" + d.Volume.ToString()).Aggregate((n, acc) => n + ", " + acc)
  102. ).Result;
  103. }
  104. atg.Start().Wait();
  105. }
  106. class InMemoryDbContextProvider : IDbContextProvider
  107. {
  108. public T CreateDbContext<T>() where T : DbContext
  109. {
  110. //var options = new DbContextOptionsBuilder<InMemoryDbContext>()
  111. // .UseInMemoryDatabase(databaseName: "Test")
  112. // .Options;
  113. return new InMemoryDbContext() as T;
  114. }
  115. public void Dispose()
  116. {
  117. //throw new NotImplementedException();
  118. }
  119. }
  120. [TestInitialize]
  121. public void TestMethodInit()
  122. {
  123. }
  124. [TestMethod]
  125. public async Task TankReading_TestMethod1()
  126. {
  127. var tanks = atg.Tanks;
  128. var mockReading = new Edge.Core.IndustryStandardInterface.ATG.ProbeReading()
  129. {
  130. Height = 1322,
  131. Water = 123,
  132. Temperature = new[] { (double)41 }
  133. };
  134. probeHandlers.ForEach(ph => ph.Mock_SetProbeReadingValueProducer((_) => mockReading));
  135. Assert.AreEqual(true, atg.Tanks != null);
  136. Assert.AreEqual(true, atg.Tanks.Count() == TankCount);
  137. await Task.Delay(atg.polling_fast_TankReadingTimer_Internval);
  138. var volumeCaculatorTester = new HeightToVolumeCaculator(sharedTankProfileDatas);
  139. foreach (var tank in atg.Tanks)
  140. {
  141. var tankConfig = tankConfigs.First(tc => tc.TankNumber == tank.TankNumber);
  142. var tcCaculator = new TemperatureCompensationCaculator(tankConfig.ThermalCoefficient);
  143. var tankReading = await atg.GetTankReadingAsync(tank.TankNumber);
  144. Assert.AreEqual(true, tankReading != null);
  145. Assert.AreEqual(true, tankReading.Height == mockReading.Height);
  146. Assert.AreEqual(true, tankReading.Water == mockReading.Water);
  147. Assert.AreEqual(true, tankReading.Temperature.Value == mockReading.Temperature.First());
  148. Assert.AreEqual(tankReading.TcVolume,
  149. tcCaculator.CaculateCompensatedVolume(tankOverallConfig.TcReference, tankReading.Volume.Value, tankReading.Temperature.Value));
  150. Assert.AreEqual(true, tankReading.WaterVolume == volumeCaculatorTester.GetVolume(tankReading.Water.Value));
  151. Assert.AreEqual(true, tankReading.Volume == volumeCaculatorTester.GetVolume(tankReading.Height.Value) - tankReading.WaterVolume);
  152. Assert.AreEqual(tankReading.Ullage,
  153. volumeCaculatorTester.GetVolume(sharedTankProfileDatas.Max(p => p.Height)) - tankReading.Volume - tankReading.WaterVolume);
  154. }
  155. }
  156. [TestMethod]
  157. public async Task TankReading_TestMethod2()
  158. {
  159. var tanks = atg.Tanks;
  160. Func<IProbeHandler, ProbeReading> mockReadingProducer = (ph) =>
  161. new ProbeReading()
  162. {
  163. Height = ph.Probe.ProbeLength * 0.8,
  164. Water = ph.Probe.ProbeLength * 0.1,
  165. Temperature = new[] { (double)(49 + ph.Probe.ProbeLength) }
  166. };
  167. probeHandlers.ForEach(ph => ph.Mock_SetProbeReadingValueProducer(mockReadingProducer));
  168. Assert.AreEqual(true, atg.Tanks != null);
  169. Assert.AreEqual(true, atg.Tanks.Count() == TankCount);
  170. await Task.Delay(atg.polling_fast_TankReadingTimer_Internval * 2);
  171. var volumeCaculatorTester = new HeightToVolumeCaculator(sharedTankProfileDatas);
  172. foreach (var tank in atg.Tanks)
  173. {
  174. var tankConfig = tankConfigs.First(tc => tc.TankNumber == tank.TankNumber);
  175. var tcCaculator = new TemperatureCompensationCaculator(tankConfig.ThermalCoefficient);
  176. var tankReading = await atg.GetTankReadingAsync(tank.TankNumber);
  177. Assert.AreEqual(true, tankReading != null);
  178. Assert.AreEqual(true, tankReading.Height == tank.Probe.ProbeLength * 0.8);
  179. Assert.AreEqual(true, tankReading.Water == tank.Probe.ProbeLength * 0.1);
  180. Assert.AreEqual(true, tankReading.Temperature.Value == (double)(49 + tank.Probe.ProbeLength));
  181. Assert.AreEqual(tankReading.TcVolume,
  182. tcCaculator.CaculateCompensatedVolume(tankOverallConfig.TcReference, tankReading.Volume.Value, tankReading.Temperature.Value));
  183. Assert.AreEqual(true, tankReading.WaterVolume == volumeCaculatorTester.GetVolume(tankReading.Water.Value));
  184. Assert.AreEqual(true, tankReading.Volume == volumeCaculatorTester.GetVolume(tankReading.Height.Value) - tankReading.WaterVolume);
  185. Assert.AreEqual(tankReading.Ullage,
  186. volumeCaculatorTester.GetVolume(sharedTankProfileDatas.Max(p => p.Height)) - tankReading.Volume - tankReading.WaterVolume);
  187. }
  188. }
  189. [TestMethod]
  190. public async Task Inventory_TestMethod1()
  191. {
  192. var tanks = atg.Tanks;
  193. Func<IProbeHandler, ProbeReading> mockReadingProducer = (ph) =>
  194. new ProbeReading()
  195. {
  196. Height = ph.Probe.ProbeLength * 0.8,
  197. Water = ph.Probe.ProbeLength * 0.1,
  198. Temperature = new[] { (double)(49 + ph.Probe.ProbeLength) }
  199. };
  200. probeHandlers.ForEach(ph => ph.Mock_SetProbeReadingValueProducer(mockReadingProducer));
  201. Assert.AreEqual(true, atg.Tanks != null);
  202. Assert.AreEqual(true, atg.Tanks.Count() == TankCount);
  203. await Task.Delay(InventorySamplingInterval * 3);
  204. var volumeCaculatorTester = new HeightToVolumeCaculator(sharedTankProfileDatas);
  205. foreach (var tank in atg.Tanks)
  206. {
  207. var tankConfig = tankConfigs.First(tc => tc.TankNumber == tank.TankNumber);
  208. var tcCaculator = new TemperatureCompensationCaculator(tankConfig.ThermalCoefficient);
  209. var tankReading = await atg.GetTankReadingAsync(tank.TankNumber);
  210. Assert.AreEqual(true, tankReading != null);
  211. Assert.AreEqual(true, tankReading.Height == tank.Probe.ProbeLength * 0.8);
  212. Assert.AreEqual(true, tankReading.Water == tank.Probe.ProbeLength * 0.1);
  213. Assert.AreEqual(true, tankReading.Temperature.Value == (double)(49 + tank.Probe.ProbeLength));
  214. Assert.AreEqual(tankReading.TcVolume,
  215. tcCaculator.CaculateCompensatedVolume(tankOverallConfig.TcReference, tankReading.Volume.Value, tankReading.Temperature.Value));
  216. Assert.AreEqual(true, tankReading.WaterVolume == volumeCaculatorTester.GetVolume(tankReading.Water.Value));
  217. Assert.AreEqual(true, tankReading.Volume == volumeCaculatorTester.GetVolume(tankReading.Height.Value) - tankReading.WaterVolume);
  218. Assert.AreEqual(tankReading.Ullage,
  219. volumeCaculatorTester.GetVolume(sharedTankProfileDatas.Max(p => p.Height)) - tankReading.Volume - tankReading.WaterVolume);
  220. var inventories = await atg.GetTankInventoryAsync(tank.TankNumber, 1000);
  221. Assert.AreEqual(true, inventories != null && inventories.Any());
  222. Assert.AreEqual(true, inventories.Count() >= 2, "Tank with tankNumber: " + tank.TankNumber + " does not has inventory records >=2");
  223. }
  224. }
  225. [TestMethod]
  226. public async Task Delivery_Manual_TestMethod1()
  227. {
  228. var tanks = atg.Tanks;
  229. var probeReading_OnStart = new ProbeReading()
  230. {
  231. Height = 1000,
  232. Water = 10,
  233. Temperature = new[] { (double)50 }
  234. };
  235. var probeReading_OnStop = new ProbeReading()
  236. {
  237. Height = 5000,
  238. Water = 30,
  239. Temperature = new[] { (double)55 }
  240. };
  241. Func<IProbeHandler, ProbeReading> mockReadingProducer_OnStart_Delivery = (ph) => probeReading_OnStart;
  242. Func<IProbeHandler, ProbeReading> mockReadingProducer_OnStop_Delivery = (ph) => probeReading_OnStop;
  243. probeHandlers.ForEach(ph => ph.Mock_SetProbeReadingValueProducer(mockReadingProducer_OnStart_Delivery));
  244. Assert.AreEqual(true, atg.Tanks != null);
  245. Assert.AreEqual(true, atg.Tanks.Count() == TankCount);
  246. await Task.Delay(atg.polling_fast_TankReadingTimer_Internval * 2);
  247. var volumeCaculatorTester = new HeightToVolumeCaculator(sharedTankProfileDatas);
  248. foreach (var tank in atg.Tanks)
  249. {
  250. var tankConfig = tankConfigs.First(tc => tc.TankNumber == tank.TankNumber);
  251. var tcCaculator = new TemperatureCompensationCaculator(tankConfig.ThermalCoefficient);
  252. var tankReading_startDelivery = await atg.StartOrStopManualDeliveryAsync(tank.TankNumber, "start");
  253. Assert.AreEqual(true, tankReading_startDelivery != null);
  254. Assert.AreEqual(true, tankReading_startDelivery.Height == probeReading_OnStart.Height,
  255. $"for tankNumber: {tank.TankNumber}, expect: {probeReading_OnStart.Height}, but actual: {tankReading_startDelivery.Height}");
  256. Assert.AreEqual(true, tankReading_startDelivery.Water == probeReading_OnStart.Water);
  257. Assert.AreEqual(true, tankReading_startDelivery.Temperature.Value == probeReading_OnStart.Temperature.First());
  258. }
  259. probeHandlers.ForEach(ph => ph.Mock_SetProbeReadingValueProducer(mockReadingProducer_OnStop_Delivery));
  260. await Task.Delay(atg.polling_fast_TankReadingTimer_Internval * 2);
  261. foreach (var tank in atg.Tanks)
  262. {
  263. var tankReading_endDelivery = await atg.StartOrStopManualDeliveryAsync(tank.TankNumber, "stop");
  264. Assert.AreEqual(true, tankReading_endDelivery.Height == probeReading_OnStop.Height);
  265. Assert.AreEqual(true, tankReading_endDelivery.Water == probeReading_OnStop.Water);
  266. Assert.AreEqual(true, tankReading_endDelivery.Temperature.Value == probeReading_OnStop.Temperature.First());
  267. }
  268. foreach (var tank in atg.Tanks)
  269. {
  270. var tankDeliveries = await atg.GetTankDeliveryAsync(tank.TankNumber, 100);
  271. Assert.AreEqual(true, tankDeliveries != null && tankDeliveries.Any());
  272. var latestTankDelivery = tankDeliveries.First();
  273. Assert.AreEqual(true, latestTankDelivery.TankNumber == tank.TankNumber);
  274. // it just happened
  275. //Assert.AreEqual(true, DateTime.Now.Subtract(latestTankDelivery.StartingDateTime).TotalSeconds <= 2);
  276. //Assert.AreEqual(true, DateTime.Now.Subtract(latestTankDelivery.EndingDateTime).TotalSeconds <= InventorySamplingInterval * 4);
  277. //Assert.AreEqual(tankReading_startDelivery.TcVolume,
  278. // tcCaculator.CaculateCompensatedVolume(tankOverallConfig.TcReference, tankReading_startDelivery.Volume.Value, tankReading_startDelivery.Temperature.Value));
  279. //Assert.AreEqual(true, tankReading_startDelivery.WaterVolume == volumeCaculatorTester.GetVolume(tankReading_startDelivery.Water.Value));
  280. //Assert.AreEqual(true, tankReading_startDelivery.Volume == volumeCaculatorTester.GetVolume(tankReading_startDelivery.Height.Value) - tankReading_startDelivery.WaterVolume);
  281. //Assert.AreEqual(tankReading_startDelivery.Ullage,
  282. // volumeCaculatorTester.GetVolume(sharedTankProfileDatas.Max(p => p.Height)) - tankReading_startDelivery.Volume - tankReading_startDelivery.WaterVolume);
  283. await Task.Delay(atg.polling_fast_TankReadingTimer_Internval * 2);
  284. }
  285. }
  286. [TestMethod]
  287. public async Task Alarm_TestMethod1()
  288. {
  289. var receivedAlarms = new List<Edge.Core.IndustryStandardInterface.ATG.Alarm>();
  290. atg.OnAlarm += (s, alEvtArg) =>
  291. {
  292. receivedAlarms.AddRange(alEvtArg.Alarms);
  293. };
  294. var tanks = atg.Tanks;
  295. var probeReading_OnStart = new ProbeReading()
  296. {
  297. Height = 1000,
  298. Water = 10,
  299. Temperature = new[] { (double)50 }
  300. };
  301. var probeReading_OnStop = new ProbeReading()
  302. {
  303. Height = 5000,
  304. Water = 30,
  305. Temperature = new[] { (double)55 }
  306. };
  307. Func<IProbeHandler, ProbeReading> mockReadingProducer_OnStart_Delivery = (ph) => probeReading_OnStart;
  308. Func<IProbeHandler, ProbeReading> mockReadingProducer_OnStop_Delivery = (ph) => probeReading_OnStop;
  309. probeHandlers.ForEach(ph => ph.Mock_SetProbeReadingValueProducer(mockReadingProducer_OnStart_Delivery));
  310. Assert.AreEqual(true, atg.Tanks != null);
  311. Assert.AreEqual(true, atg.Tanks.Count() == TankCount);
  312. await Task.Delay(atg.polling_fast_TankReadingTimer_Internval * 2);
  313. var volumeCaculatorTester = new HeightToVolumeCaculator(sharedTankProfileDatas);
  314. foreach (var tank in atg.Tanks)
  315. {
  316. var tankConfig = tankConfigs.First(tc => tc.TankNumber == tank.TankNumber);
  317. var tcCaculator = new TemperatureCompensationCaculator(tankConfig.ThermalCoefficient);
  318. var tankReading_startDelivery = await atg.StartOrStopManualDeliveryAsync(tank.TankNumber, "start");
  319. Assert.AreEqual(true, tankReading_startDelivery != null);
  320. Assert.AreEqual(true, tankReading_startDelivery.Height == probeReading_OnStart.Height,
  321. $"for tankNumber: {tank.TankNumber}, expect: {probeReading_OnStart.Height}, but actual: {tankReading_startDelivery.Height}");
  322. Assert.AreEqual(true, tankReading_startDelivery.Water == probeReading_OnStart.Water);
  323. Assert.AreEqual(true, tankReading_startDelivery.Temperature.Value == probeReading_OnStart.Temperature.First());
  324. }
  325. probeHandlers.ForEach(ph => ph.Mock_SetProbeReadingValueProducer(mockReadingProducer_OnStop_Delivery));
  326. await Task.Delay(atg.polling_fast_TankReadingTimer_Internval * 2);
  327. foreach (var tank in atg.Tanks)
  328. {
  329. var tankReading_endDelivery = await atg.StartOrStopManualDeliveryAsync(tank.TankNumber, "stop");
  330. Assert.AreEqual(true, tankReading_endDelivery.Height == probeReading_OnStop.Height);
  331. Assert.AreEqual(true, tankReading_endDelivery.Water == probeReading_OnStop.Water);
  332. Assert.AreEqual(true, tankReading_endDelivery.Temperature.Value == probeReading_OnStop.Temperature.First());
  333. }
  334. foreach (var tank in atg.Tanks)
  335. {
  336. var tankDeliveries = await atg.GetTankDeliveryAsync(tank.TankNumber, 100);
  337. Assert.AreEqual(true, tankDeliveries != null && tankDeliveries.Any());
  338. var latestTankDelivery = tankDeliveries.First();
  339. Assert.AreEqual(true, latestTankDelivery.TankNumber == tank.TankNumber);
  340. // it just happened
  341. //Assert.AreEqual(true, DateTime.Now.Subtract(latestTankDelivery.StartingDateTime).TotalSeconds <= 2);
  342. //Assert.AreEqual(true, DateTime.Now.Subtract(latestTankDelivery.EndingDateTime).TotalSeconds <= InventorySamplingInterval * 4);
  343. //Assert.AreEqual(tankReading_startDelivery.TcVolume,
  344. // tcCaculator.CaculateCompensatedVolume(tankOverallConfig.TcReference, tankReading_startDelivery.Volume.Value, tankReading_startDelivery.Temperature.Value));
  345. //Assert.AreEqual(true, tankReading_startDelivery.WaterVolume == volumeCaculatorTester.GetVolume(tankReading_startDelivery.Water.Value));
  346. //Assert.AreEqual(true, tankReading_startDelivery.Volume == volumeCaculatorTester.GetVolume(tankReading_startDelivery.Height.Value) - tankReading_startDelivery.WaterVolume);
  347. //Assert.AreEqual(tankReading_startDelivery.Ullage,
  348. // volumeCaculatorTester.GetVolume(sharedTankProfileDatas.Max(p => p.Height)) - tankReading_startDelivery.Volume - tankReading_startDelivery.WaterVolume);
  349. await Task.Delay(atg.polling_fast_TankReadingTimer_Internval * 2);
  350. }
  351. }
  352. }
  353. }