GPSTrackerLocationStore.cs 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183
  1. using System.Collections.Concurrent;
  2. using Comal.Classes;
  3. using InABox.Core;
  4. using InABox.Database;
  5. using System.Drawing;
  6. using Guid = System.Guid;
  7. namespace Comal.Stores
  8. {
  9. public class GPSTrackerLocationStore : BaseStore<GPSTrackerLocation>
  10. {
  11. private static ConcurrentDictionary<string, Guid> _cache;
  12. private static ConcurrentBag<Tuple<double, double, GeoFenceDefinition, Guid, string>> _addresses;
  13. static GPSTrackerLocationStore()
  14. {
  15. _cache = new ConcurrentDictionary<string, Guid>();
  16. _addresses = new ConcurrentBag<Tuple<double, double, GeoFenceDefinition, Guid, string>>();
  17. RegisterListener<GPSTracker>(ReloadTrackers);
  18. RegisterListener<CompanyInformation>(ReloadAddresses);
  19. RegisterListener<Job>(ReloadAddresses);
  20. RegisterListener<Supplier>(ReloadAddresses);
  21. RegisterListener<Employee>(ReloadAddresses);
  22. }
  23. private static void ReloadTrackers(Guid[] ids)
  24. {
  25. _cache = new ConcurrentDictionary<string, Guid>(
  26. DbFactory.NewProvider(Logger.Main).Query(
  27. Filter<GPSTracker>.Where(x => x.DeviceID).IsNotEqualTo(Guid.Empty.ToString())
  28. .And(x => x.DeviceID).IsNotEqualTo(null),
  29. Columns.None<GPSTracker>().Add(x => x.DeviceID).Add(x => x.ID)
  30. ).Rows
  31. .Select(r => new KeyValuePair<string, Guid>(
  32. r.Get<GPSTracker, String>(c => c.DeviceID),
  33. r.Get<GPSTracker, Guid>(c => c.ID))
  34. )
  35. );
  36. }
  37. private static void ReloadAddresses(Guid[] ids)
  38. {
  39. var locations = DbFactory.NewProvider(Logger.Main).Query<Classes.GeoFence>().ToObjects<Classes.GeoFence>();
  40. _addresses = new ConcurrentBag<Tuple<double, double, GeoFenceDefinition, Guid, string>>(
  41. DbFactory.NewProvider(Logger.Main).Query<Classes.GeoFence>()
  42. .Rows
  43. .Select( r => new Tuple<double, double, GeoFenceDefinition, Guid, string>(
  44. r.Get<Classes.GeoFence,double>(c=>c.Latitude),
  45. r.Get<Classes.GeoFence,double>(c=>c.Longitude),
  46. Serialization.Deserialize<GeoFenceDefinition>(r.Get<Classes.GeoFence,string>(c=>c.Geofence)) ?? new GeoFenceDefinition(),
  47. r.Get<Classes.GeoFence,Guid>(x=>x.ID),
  48. $"{r.Get<Classes.GeoFence,string>(c=>c.Code)}: {r.Get<Classes.GeoFence,string>(c=>c.Name)}"))
  49. );
  50. }
  51. public override void Init()
  52. {
  53. Logger.Send(LogType.Information, "", "Initializing GPS Tracker Cache");
  54. ReloadTrackers([]);
  55. Logger.Send(LogType.Information, "", "Initializing GPS Location Cache");
  56. ReloadAddresses([]);
  57. }
  58. public string ReverseGeocode(double latitude, double longitude)
  59. {
  60. var geopoint = new GeoPoint(latitude, longitude);
  61. var address = _addresses.FirstOrDefault(a => a.Item3.Contains(geopoint));
  62. return address?.Item5 ?? "";
  63. // var tuple = _addresses.FirstOrDefault(x => Equals(x.Item1, latitude) && Equals(x.Item2, longitude));
  64. // if (tuple == null)
  65. // {
  66. // try
  67. // {
  68. // var address = StoreUtils.ReverseGeocode(latitude, longitude);
  69. // if (!string.IsNullOrWhiteSpace(address))
  70. // {
  71. // tuple = new Tuple<double, double, string>(latitude, longitude, address);
  72. // _addresses.Add(tuple);
  73. // }
  74. // }
  75. // catch (Exception e)
  76. // {
  77. // Logger.Send(LogType.Error, "", e.ToString());
  78. // }
  79. // }
  80. //
  81. // return tuple != null ? tuple.Item3 : "";
  82. }
  83. protected override void BeforeSave(GPSTrackerLocation entity)
  84. {
  85. base.BeforeSave(entity);
  86. if (Equals(entity.Tracker.ID, Guid.Empty))
  87. {
  88. if (!_cache.ContainsKey(entity.DeviceID))
  89. {
  90. Logger.Send(LogType.Information, "", string.Format("- Tracker Cache Update Required: {0}", entity.DeviceID));
  91. var row = Provider.Query(
  92. Filter<GPSTracker>.Where(x => x.DeviceID).IsEqualTo(entity.DeviceID),
  93. Columns.None<GPSTracker>().Add(x => x.ID)
  94. ).Rows.FirstOrDefault();
  95. if (row != null)
  96. {
  97. entity.Tracker.ID = row.Get<GPSTracker, Guid>(x => x.ID);
  98. _cache[entity.DeviceID] = entity.Tracker.ID;
  99. Logger.Send(LogType.Information, "",
  100. string.Format("- Adding Tracker to Cache: {0} => {1}", entity.DeviceID, entity.Tracker.ID));
  101. }
  102. }
  103. else
  104. {
  105. entity.Tracker.ID = _cache[entity.DeviceID];
  106. }
  107. }
  108. if (!Equals(entity.Tracker.ID, Guid.Empty)
  109. && string.IsNullOrWhiteSpace(entity.Location.Address)
  110. && !Equals(entity.Location.Latitude, 0.0D)
  111. && !Equals(entity.Location.Longitude, 0.0D)
  112. )
  113. entity.Location.Address = ReverseGeocode(entity.Location.Latitude, entity.Location.Longitude);
  114. }
  115. private void UpdateTrackers(IEnumerable<GPSTrackerLocation> entities, ref string auditnote)
  116. {
  117. var updates = new List<GPSTracker>();
  118. foreach (var entity in entities)
  119. {
  120. if (entity.Tracker.IsValid())
  121. {
  122. var tracker = new GPSTracker();
  123. tracker.SetID(entity.Tracker.ID);
  124. tracker.Location.Longitude = entity.Location.Longitude;
  125. tracker.Location.Latitude = entity.Location.Latitude;
  126. tracker.Location.Timestamp = entity.Location.Timestamp;
  127. tracker.Location.Address = entity.Location.Address;
  128. tracker.BatteryLevel = entity.BatteryLevel;
  129. tracker.Hours = entity.Hours;
  130. tracker.Distance = entity.Distance;
  131. tracker.Counter1 = entity.Counter1;
  132. tracker.Counter2 = entity.Counter2;
  133. tracker.Counter3 = entity.Counter3;
  134. tracker.Counter4 = entity.Counter4;
  135. updates.Add(tracker);
  136. }
  137. else
  138. {
  139. Logger.Send(LogType.Error, "", string.Format("Skipping GPS Tracker Update (Cache Size={0})", _cache.Count));
  140. }
  141. }
  142. if (updates.Any())
  143. {
  144. Provider.Save(updates);
  145. //AuditTrail(updates, new[] { auditnote });
  146. }
  147. auditnote = null;
  148. }
  149. protected override void OnSave(GPSTrackerLocation[] entities, ref string auditnote)
  150. {
  151. var updates = entities.Where(x => !Equals(x.Tracker.ID, Guid.Empty)).ToArray();
  152. if (updates.Any())
  153. {
  154. UpdateTrackers(updates, ref auditnote);
  155. base.OnSave(updates, ref auditnote);
  156. }
  157. }
  158. protected override void OnSave(GPSTrackerLocation entity, ref string auditnote)
  159. {
  160. if (Equals(entity.Tracker.ID, Guid.Empty))
  161. return;
  162. UpdateTrackers(new[] { entity }, ref auditnote);
  163. base.OnSave(entity, ref auditnote);
  164. }
  165. }
  166. }