123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439 |
- using System;
- using System.Collections.Generic;
- using System.Collections.ObjectModel;
- using System.ComponentModel;
- using System.Drawing;
- using System.Linq;
- using System.Runtime.CompilerServices;
- using System.Windows;
- using System.Windows.Input;
- using System.Windows.Media.Imaging;
- using Comal.Classes;
- using ExCSS;
- using InABox.Clients;
- using InABox.Configuration;
- using InABox.Core;
- using InABox.WPF;
- using Syncfusion.UI.Xaml.Diagram;
- using Syncfusion.UI.Xaml.Maps;
- using GeoFence = Comal.Classes.GeoFence;
- using Point = System.Windows.Point;
- namespace PRSDesktop;
- public class MapMarker
- {
- public string Name { get; set; } = "Hi There";
- public string Label { get; set; } = "";
- public string Longitude { get; set; }
- public string Latitude { get; set; }
- }
- public class LiveMapsPanelViewModel : DependencyObject, INotifyPropertyChanged
- {
- private EquipmentGroup[]? _groups;
- private Equipment[]? _items;
- private EquipmentGroup? _selectedGroup;
- private string? _search;
- private DateTime _date = DateTime.Today;
- private Equipment? _selectedItem;
- private ObservableCollection<Point>? _waypoints;
- private Point _center;
- private double _radius;
- private GeoFence[]? _geofences;
- private ObservableCollection<MapElement> _elements;
- private ObservableCollection<MapMarker>? _sites;
- public EquipmentGroup[]? Groups
- {
- get => _groups;
- set => SetField(ref _groups, value);
- }
-
- public EquipmentGroup? SelectedGroup
- {
- get => _selectedGroup;
- set
- {
- SetField(ref _selectedGroup, value);
- SelectedItem = null;
- SaveSettings();
- OnPropertyChanged(nameof(Visible));
- }
- }
- public Equipment[]? Items
- {
- get => _items;
- set => SetField(ref _items, value);
- }
- public GeoFence[]? GeoFences
- {
- get => _geofences;
- set
- {
- _fencesMap.Clear();
- if (value is not null)
- {
- foreach (var fence in value ?? [])
- _fencesMap[fence] = Serialization.Deserialize<GeoFenceDefinition>(fence.Geofence) ?? new GeoFenceDefinition();
- }
- SetField(ref _geofences, value);
- }
- }
-
- private Dictionary<GeoFence,GeoFenceDefinition> _fencesMap = new();
- public string? Search
- {
- get => _search;
- set
- {
- SetField(ref _search, value);
- OnPropertyChanged(nameof(Visible));
- }
- }
-
- public Equipment[]? Visible => Items?.Where(x =>
- x.GroupLink.ID == (SelectedGroup?.ID ?? CoreUtils.FullGuid)
- && (
- string.IsNullOrEmpty(Search)
- || x.Code.Contains(Search,StringComparison.CurrentCultureIgnoreCase)
- || x.Description.Contains(Search,StringComparison.CurrentCultureIgnoreCase)
- )
- ).ToArray();
-
- public DateTime Date
- {
- get => _date;
- set
- {
- SetField(ref _date, value);
- ReloadLocations();
- OnPropertyChanged(nameof(Visible));
- }
- }
- public Equipment? SelectedItem
- {
- get => _selectedItem;
- set
- {
- SetField(ref _selectedItem, value);
- ReloadLocations();
- }
- }
-
- private void CenterMap()
- {
- var nwLon = double.MaxValue;
- var nwLat = double.MinValue;
- var seLon = double.MinValue;
- var seLat = double.MaxValue;
-
- var points = new List<Point>();
-
- if (_waypoints != null)
- points.AddRange(_waypoints);
-
- if (_geofences != null)
- {
- foreach (var geofence in _fencesMap.Where(x=>x.Key.Type == GPSLocationType.Office))
- points.AddRange(geofence.Value.Coordinates.Select(x => new Point(x.Latitude, x.Longitude)));
- }
-
- foreach (var point in points)
- {
- var lat = point.X;
- var lon = point.Y;
- if (lat != 0.0F && lon != 0.00)
- {
- nwLat = lat > nwLat ? lat : nwLat;
- seLat = lat < seLat ? lat : seLat;
- nwLon = lon < nwLon ? lon : nwLon;
- seLon = lon > seLon ? lon : seLon;
- }
- }
-
- var cLat = (nwLat + seLat) / 2.0F;
- var cLon = (nwLon + seLon) / 2.0F;
- //Center = new Point(-33.0 + new Random(DateTime.Now.Millisecond).NextDouble(), 115.0 + new Random(DateTime.Now.Millisecond).NextDouble());
- Center = new Point(cLat, cLon);
- var c = new Location { Latitude = cLat, Longitude = cLon };
- var nw = new Location { Latitude = nwLat, Longitude = nwLon };
- Radius = Math.Max(1.0, c.DistanceTo(nw, UnitOfLength.Kilometers) / 2.0F);
-
- }
- private void ReloadLocations()
- {
- var trackerids = Visible?.Select(x => x.TrackerLink.ID).ToArray() ?? [];
- Client.Query(
- new Filter<GPSTrackerLocation>(x=>x.Tracker.ID).InList(trackerids)
- .And(x => x.Location.Timestamp).IsGreaterThanOrEqualTo(Date.Date)
- .And(x => x.Location.Timestamp).IsLessThan(Date.Date.AddDays(1)),
- Columns.None<GPSTrackerLocation>()
- .Add(x=>x.Tracker.ID)
- .Add(x=>x.Location.Latitude)
- .Add(x=>x.Location.Longitude)
- .Add(x=>x.Location.Address)
- .Add(x=>x.Location.Timestamp),
- new SortOrder<GPSTrackerLocation>(x=>x.Location.Timestamp,SortDirection.Ascending),
- (data, _) =>
- {
- Dispatcher.BeginInvoke(() =>
- {
- Point[]? others = null;
- if (data is null)
- {
- EquipmentColorConverter.Pings = [];
- Waypoints = null;
- Sites = null;
- }
- else
- {
- EquipmentColorConverter.Pings = data.ToArray<GPSTrackerLocation>();
- others = data.Rows
- .Where(r => r.Get<GPSTrackerLocation,Guid>(c=>c.Tracker.ID) != (SelectedItem?.TrackerLink.ID ?? CoreUtils.FullGuid))
- .Select(r => new Point()
- {
- X = r.Get<GPSTrackerLocation, double>(c => c.Location.Latitude),
- Y = r.Get<GPSTrackerLocation, double>(c => c.Location.Longitude)
- }
- ).ToArray();
-
- var locations = data.Rows
- .Where(r => r.Get<GPSTrackerLocation,Guid>(c=>c.Tracker.ID) == (SelectedItem?.TrackerLink.ID ?? CoreUtils.FullGuid))
- .Select(r => new Point(
- r.Get<GPSTrackerLocation, double>(c => c.Location.Latitude),
- r.Get<GPSTrackerLocation, double>(c => c.Location.Longitude)
- )
- )?.ToArray() ?? [];
- Waypoints = new ObservableCollection<Point>(locations);
-
- Dictionary<GeoFence, MapMarker> sites = new Dictionary<GeoFence, MapMarker>();
- GeoFence? curFence = null;
-
- foreach (var row in data.Rows.Where(r => r.Get<GPSTrackerLocation,Guid>(c=>c.Tracker.ID) == (SelectedItem?.TrackerLink.ID ?? CoreUtils.FullGuid)))
- {
- var time = $"{row.Get<GPSTrackerLocation, DateTime>(c => c.Location.Timestamp):h:mm tt}";
- var geopoint = new GeoPoint(row.Get<GPSTrackerLocation, double>(c => c.Location.Latitude), row.Get<GPSTrackerLocation, double>(c => c.Location.Longitude));
- bool bFound = false;
-
- foreach (var geofence in _fencesMap)
- {
-
- if (geofence.Value.Contains(geopoint))
- {
- if (!sites.ContainsKey(geofence.Key))
- sites[geofence.Key] = new MapMarker()
- {
- Latitude = $"{geopoint.Latitude}",
- Longitude = $"{geopoint.Longitude}"
- };
-
- var timelist = sites[geofence.Key].Label.Split('\n').Where(x=>!string.IsNullOrWhiteSpace(x)).ToList();
-
- var first = timelist.FirstOrDefault() ?? "";
- if (!string.Equals(first,geofence.Key.Name))
- timelist.Insert(0,geofence.Key.Name);
-
- if ((geofence.Key == curFence) && timelist.Any())
- {
- var lasttime = timelist.Last().Split(" - ").ToList();
- timelist.Remove(timelist.Last());
- timelist.Add($"{lasttime.First()} - {time}");
- }
- else
- timelist.Add($"{time} - {time}");
- sites[geofence.Key].Label = string.Join("\n", timelist);
- curFence = geofence.Key;
- bFound = true;
- break;
- }
- }
- if (!bFound)
- curFence = null;
- }
- Sites = new ObservableCollection<MapMarker>(sites.Values);
-
- }
- OnPropertyChanged(nameof(Visible));
- RecalculateLayers(others);
- CenterMap();
- });
- }
- );
- }
- public ObservableCollection<MapElement> Elements
- {
- get => _elements;
- set => SetField(ref _elements, value);
- }
- private void RecalculateLayers(Point[]? markers)
- {
- var elements = new ObservableCollection<MapElement>();
- if (_geofences?.Any() == true)
- {
- foreach (var geofence in _geofences)
- {
- var definition = Serialization.Deserialize<GeoFenceDefinition>(geofence.Geofence) ?? new GeoFenceDefinition();
- var polygon = new MapPolygon()
- {
- Fill = new System.Windows.Media.SolidColorBrush(System.Windows.Media.Colors.LightSalmon)
- { Opacity = 0.5 },
- Stroke = System.Windows.Media.Brushes.Firebrick,
- StrokeThickness = 0.75,
- Points = new ObservableCollection<Point>(
- definition.Coordinates.Select(x => new Point(x.Latitude, x.Longitude))),
- };
- elements.Add(polygon);
- }
- }
- if (markers?.Any() == true)
- {
- foreach (var marker in markers.Distinct())
- {
- var circle = new MapCircle()
- {
- Center = marker,
- Fill = new System.Windows.Media.SolidColorBrush(System.Windows.Media.Colors.Magenta) { Opacity = 0.5 },
- Stroke = new System.Windows.Media.SolidColorBrush(System.Windows.Media.Colors.Black),
- StrokeThickness = 0,
- Radius = 10
- };
- elements.Add(circle);
- }
- }
- if (_waypoints?.Any( ) == true)
- {
- var line = new MapPolyline()
- {
- Points = new ObservableCollection<Point>(new ObservableCollection<Point>(_waypoints)),
- Fill = new System.Windows.Media.SolidColorBrush(System.Windows.Media.Colors.Navy) { Opacity = 0.5 },
- Stroke = new System.Windows.Media.SolidColorBrush(System.Windows.Media.Colors.Navy) { Opacity = 0.5 },
- StrokeThickness = 4
- };
- elements.Add(line);
- }
- Elements = elements;
- }
-
- public ICommand RefreshCommand { get; set; }
-
- public ObservableCollection<MapMarker>? Sites
- {
- get => _sites;
- set => SetField(ref _sites, value);
- }
- public ObservableCollection<Point>? Waypoints
- {
- get => _waypoints;
- set => SetField(ref _waypoints, value);
- }
- public Point Center
- {
- get => _center;
- set => SetField(ref _center, value);
- }
- public double Radius
- {
- get => _radius;
- set => SetField(ref _radius, value);
- }
- public LiveMapsSettings Settings { get; private set; }
- public LiveMapsPanelViewModel()
- {
- Settings = new UserConfiguration<LiveMapsSettings>().Load();
- }
- public void SaveSettings()
- {
- Settings.GroupID = _selectedGroup?.ID ?? Guid.Empty;
- Settings.ItemID = _selectedItem?.ID ?? Guid.Empty;
- new UserConfiguration<LiveMapsSettings>().Save(Settings);
- }
-
- public void Refresh()
- {
- MultiQuery query = new MultiQuery();
- query.Add(new Filter<GeoFence>().All());
-
- query.Add(new Filter<EquipmentGroup>().All(),
- Columns.None<EquipmentGroup>()
- .Add(x => x.ID)
- .Add(x => x.Description)
- .Add(x=>x.Thumbnail.ID)
- );
-
- query.Add(
- new Filter<Document>(x=>x.ID).InQuery(new Filter<EquipmentGroup>().All(),x=>x.Thumbnail.ID));
- query.Add(
- new Filter<Equipment>(x => x.TrackerLink.ID).IsNotEqualTo(Guid.Empty),
- Columns.None<Equipment>()
- .Add(x => x.ID)
- .Add(x => x.Code)
- .Add(x => x.Description)
- .Add(x=>x.GroupLink.ID)
- .Add(x=>x.GroupLink.Thumbnail.ID)
- .Add(x=>x.TrackerLink.ID)
- .Add(x=>x.TrackerLink.Location.Timestamp)
- .Add(x=>x.TrackerLink.DeviceID)
- .Add(x=>x.TrackerLink.BatteryLevel)
- );
- query.Query( _ =>
- {
- Dispatcher.BeginInvoke(() =>
- {
- foreach (var row in query.Get<Document>().Rows)
- {
- var img = ImageUtils.LoadImage(row.Get<Document, byte[]>(x => x.Data));
- EquipmentThumbnailConverter.Cache[row.Get<Document, Guid>(x => x.ID)] = img;
- }
- // EquipmentThumbnailConverter.Cache = query.Get<Document>()
- // .ToDictionary<Document, Guid, BitmapImage?>(x => x.ID,
- // x => ImageUtils.LoadImage(x.Data));
- GeoFences = query.Get<GeoFence>().ToArray<GeoFence>();
- Groups = query.Get<EquipmentGroup>().ToArray<EquipmentGroup>();
- SelectedGroup = _groups?.FirstOrDefault(x=>x.ID == _selectedGroup?.ID);
- Items = query.Get<Equipment>().ToArray<Equipment>();
- SelectedItem = _items?.FirstOrDefault(x=>x.ID == _selectedItem?.ID);
- });
- });
- }
-
- public event PropertyChangedEventHandler? PropertyChanged;
- protected virtual void OnPropertyChanged([CallerMemberName] string? propertyName = null)
- {
- PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
- }
- protected bool SetField<T>(ref T field, T value, [CallerMemberName] string? propertyName = null)
- {
- if (EqualityComparer<T>.Default.Equals(field, value)) return false;
- field = value;
- OnPropertyChanged(propertyName);
- return true;
- }
- }
|