GPSTrackerLocationStore.cs 6.4 KB

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