From 2b6300d3c4235a0fbad61a5ff64d8908d7defed3 Mon Sep 17 00:00:00 2001 From: Adrian Stevens Date: Tue, 28 May 2024 11:53:28 -0700 Subject: [PATCH] Release 1.12.0 --- .gitignore | 5 +- .../.vscode/launch.json | 14 - .../Controllers/DatabaseController.cs | 63 --- .../Controllers/DisplayController.cs | 151 ------- .../Controllers/MainTrackerController.cs | 135 ------ .../GnssTracker_SQLite_Demo.csproj | 27 -- .../GnssTracker_SQLite_Demo/MeadowApp.cs | 41 -- .../Models/Data/SensorDataModel.cs | 35 -- .../Models/Logical/AtmosphericModel.cs | 21 - .../Models/Logical/LocationModel.cs | 9 - .../GnssTracker_SQLite_Demo/app.config.yaml | 14 - .../GnssTracker_SQLite_Demo/gnss_tracker.bmp | Bin 91882 -> 0 bytes Source/GnssTracker/GnssTracker.csproj | 14 +- .../Controllers/DisplayController.cs | 409 +++++++++--------- .../GnssTracker_Demo/GnssTracker_Demo.csproj | 2 +- Source/GnssTracker_Demo/MeadowApp.cs | 352 +++++++-------- Source/Meadow.GnssTracker.sln | 11 - 17 files changed, 392 insertions(+), 911 deletions(-) delete mode 100644 Source/Additional Samples/GnssTracker_SQLite_Demo/.vscode/launch.json delete mode 100644 Source/Additional Samples/GnssTracker_SQLite_Demo/Controllers/DatabaseController.cs delete mode 100644 Source/Additional Samples/GnssTracker_SQLite_Demo/Controllers/DisplayController.cs delete mode 100644 Source/Additional Samples/GnssTracker_SQLite_Demo/Controllers/MainTrackerController.cs delete mode 100644 Source/Additional Samples/GnssTracker_SQLite_Demo/GnssTracker_SQLite_Demo.csproj delete mode 100644 Source/Additional Samples/GnssTracker_SQLite_Demo/MeadowApp.cs delete mode 100644 Source/Additional Samples/GnssTracker_SQLite_Demo/Models/Data/SensorDataModel.cs delete mode 100644 Source/Additional Samples/GnssTracker_SQLite_Demo/Models/Logical/AtmosphericModel.cs delete mode 100644 Source/Additional Samples/GnssTracker_SQLite_Demo/Models/Logical/LocationModel.cs delete mode 100644 Source/Additional Samples/GnssTracker_SQLite_Demo/app.config.yaml delete mode 100644 Source/Additional Samples/GnssTracker_SQLite_Demo/gnss_tracker.bmp diff --git a/.gitignore b/.gitignore index cd4637b..5edc593 100644 --- a/.gitignore +++ b/.gitignore @@ -349,5 +349,8 @@ MigrationBackup/ # Ionide (cross platform F# VS Code tools) working folder .ionide/ -## Mac Bullshit +## Mac stuff **/.DS_Store + +## Rider Stuff +**/.idea diff --git a/Source/Additional Samples/GnssTracker_SQLite_Demo/.vscode/launch.json b/Source/Additional Samples/GnssTracker_SQLite_Demo/.vscode/launch.json deleted file mode 100644 index 7418146..0000000 --- a/Source/Additional Samples/GnssTracker_SQLite_Demo/.vscode/launch.json +++ /dev/null @@ -1,14 +0,0 @@ -{ - // Use IntelliSense to learn about possible attributes. - // Hover to view descriptions of existing attributes. - // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 - "version": "0.2.0", - "configurations": [ - { - "name": "Deploy", - "type": "meadow", - "request": "launch", - "preLaunchTask": "meadow: Build" - } - ] -} \ No newline at end of file diff --git a/Source/Additional Samples/GnssTracker_SQLite_Demo/Controllers/DatabaseController.cs b/Source/Additional Samples/GnssTracker_SQLite_Demo/Controllers/DatabaseController.cs deleted file mode 100644 index f0a757f..0000000 --- a/Source/Additional Samples/GnssTracker_SQLite_Demo/Controllers/DatabaseController.cs +++ /dev/null @@ -1,63 +0,0 @@ -using GnssTracker_SQLite_Demo.Models.Data; -using GnssTracker_SQLite_Demo.Models.Logical; -using Meadow; -using Meadow.Logging; -using SQLite; -using System.IO; - -namespace GnssTracker_SQLite_Demo.Controllers -{ - public static class DatabaseController - { - public static SQLiteConnection Database { get; set; } - public static Logger Log { get => Resolver.Log; } - - public static void ConfigureDatabase() - { - // by default, SQLite runs in `Serialized` mode, which is thread safe. - // if you need to change the threading mode, you can do it with the - // following API - //SQLite3.Config(SQLite3.ConfigOption.SingleThread); - - // database files should go in the `DataDirectory` - var databasePath = Path.Combine(MeadowOS.FileSystem.DataDirectory, "SensorReadings.db"); - - // debug only: - Log?.Debug("Deleting old db."); - File.Delete(databasePath); - Log?.Debug("Deleted."); - - Database = new SQLiteConnection(databasePath); - Database.CreateTable(); - } - - /// - /// Saves the atmospheric conditions to the database - /// - /// - public static void SaveAtmosphericLocations(AtmosphericModel conditions, LocationModel location) - { - var dataModel = SensorDataModel.From(conditions, location); - - Log.Debug("Saving conditions to database."); - Database.Insert(dataModel); - Log.Debug("Saved to database."); - - RetrieveData(); - } - - /// - /// retrieves the data from the database and reads them out to the console - /// - public static void RetrieveData() - { - Log.Debug("Reading back the data..."); - var rows = Database.Table(); - - foreach (var r in rows) - { - Log.Debug($"{r.TemperatureC:N2}C, @ {r.Latitude}/{r.Longitude} - {r.Timestamp.ToString("HH:mm:ss")} @"); - } - } - } -} \ No newline at end of file diff --git a/Source/Additional Samples/GnssTracker_SQLite_Demo/Controllers/DisplayController.cs b/Source/Additional Samples/GnssTracker_SQLite_Demo/Controllers/DisplayController.cs deleted file mode 100644 index a6d5fd8..0000000 --- a/Source/Additional Samples/GnssTracker_SQLite_Demo/Controllers/DisplayController.cs +++ /dev/null @@ -1,151 +0,0 @@ -using GnssTracker_SQLite_Demo.Models.Logical; -using Meadow; -using Meadow.Foundation.Graphics; -using Meadow.Foundation.Graphics.MicroLayout; -using Meadow.Peripherals.Displays; - -namespace GnssTracker_SQLite_Demo.Controllers -{ - public class DisplayController - { - private int counter = 0; - - private DisplayScreen displayScreen; - - private AbsoluteLayout splashLayout; - private AbsoluteLayout dataLayout; - - private Font12x20 largeFont; - private Font4x8 smallFont; - - private Label temperatureLabel; - private Label humidityLabel; - private Label pressureLabel; - private Label latitudeLabel; - private Label longitudeLabel; - private Label counterLabel; - - public DisplayController(IPixelDisplay display) - { - largeFont = new Font12x20(); - smallFont = new Font4x8(); - - displayScreen = new DisplayScreen(display, RotationType._270Degrees); - - splashLayout = new AbsoluteLayout(displayScreen, 0, 0, displayScreen.Width, displayScreen.Height); - - var image = Image.LoadFromResource("GnssTracker_SQLite_Demo.gnss_tracker.bmp"); - var displayImage = new Picture(0, 0, 250, 122, image) - { - BackColor = Color.FromHex("#23ABE3"), - HorizontalAlignment = HorizontalAlignment.Center, - VerticalAlignment = VerticalAlignment.Center, - }; - - splashLayout.Controls.Add(displayImage); - - dataLayout = new AbsoluteLayout(displayScreen, 0, 0, displayScreen.Width, displayScreen.Height); - - var box = new Box(0, 0, displayScreen.Width, displayScreen.Height) - { - ForeColor = Color.White, - IsFilled = true - }; - var frame = new Box(5, 5, 240, 112) - { - ForeColor = Color.Black, - IsFilled = false - }; - temperatureLabel = new Label(10, 10, displayScreen.Width - 20, largeFont.Height) - { - Text = $"Temp: 0.00°C", - TextColor = Color.Black, - BackColor = Color.White, - Font = largeFont, - VerticalAlignment = VerticalAlignment.Center, - HorizontalAlignment = HorizontalAlignment.Left - }; - humidityLabel = new Label(10, 30, displayScreen.Width - 20, largeFont.Height) - { - Text = $"Humidity: 0.00%", - TextColor = Color.Black, - BackColor = Color.White, - Font = largeFont, - VerticalAlignment = VerticalAlignment.Center, - HorizontalAlignment = HorizontalAlignment.Left - }; - pressureLabel = new Label(10, 50, displayScreen.Width - 20, largeFont.Height) - { - Text = $"Pressure: 0.00atm", - TextColor = Color.Black, - BackColor = Color.White, - Font = largeFont, - VerticalAlignment = VerticalAlignment.Center, - HorizontalAlignment = HorizontalAlignment.Left - }; - latitudeLabel = new Label(10, 72, displayScreen.Width - 20, largeFont.Height) - { - Text = $"Lat: 0°0'0.0\"", - TextColor = Color.White, - BackColor = Color.Red, - Font = largeFont, - VerticalAlignment = VerticalAlignment.Center, - HorizontalAlignment = HorizontalAlignment.Left - }; - longitudeLabel = new Label(10, 92, displayScreen.Width - 20, largeFont.Height) - { - Text = $"Lon: 0°0'0.0\"", - TextColor = Color.White, - BackColor = Color.Red, - Font = largeFont, - VerticalAlignment = VerticalAlignment.Center, - HorizontalAlignment = HorizontalAlignment.Left - }; - counter++; - counterLabel = new Label(222, 113, 20, 8) - { - Text = $"{counter.ToString("D4")}", - TextColor = Color.Black, - BackColor = Color.White, - Font = smallFont, - VerticalAlignment = VerticalAlignment.Center, - HorizontalAlignment = HorizontalAlignment.Center - }; - - dataLayout.Controls.Add(box, frame, temperatureLabel, humidityLabel, pressureLabel, latitudeLabel, longitudeLabel, counterLabel); - - displayScreen.Controls.Add(splashLayout, dataLayout); - - dataLayout.IsVisible = false; - } - - public void UpdateDisplay(AtmosphericModel conditions, LocationModel locationInfo) - { - splashLayout.IsVisible = false; - dataLayout.IsVisible = true; - - temperatureLabel.Text = $"Temp: {conditions.Temperature?.Celsius:n2}°C"; - humidityLabel.Text = $"Humidity: {conditions.RelativeHumidity?.Percent:n2}%"; - pressureLabel.Text = $"Pressure: {conditions.Pressure?.StandardAtmosphere:n2}atm"; - - string lat = locationInfo.PositionInformation == null - ? $"Lat: 0°0'0.0\"" - : $"Lat: " + - $"{locationInfo.PositionInformation?.Position?.Latitude?.Degrees}°" + - $"{locationInfo.PositionInformation?.Position?.Latitude?.Minutes:n2}'" + - $"{locationInfo.PositionInformation?.Position?.Latitude?.Seconds}\""; - latitudeLabel.Text = lat; - - string lon = locationInfo.PositionInformation == null - ? $"Lon: 0°0'0.0\"" - : $"Lon: " + - $"{locationInfo.PositionInformation?.Position?.Longitude?.Degrees}°" + - $"{locationInfo.PositionInformation?.Position?.Longitude?.Minutes:n2}'" + - $"{locationInfo.PositionInformation?.Position?.Longitude?.Seconds}\""; - longitudeLabel.Text = lon; - - counter++; - counterLabel.Text = $"{counter.ToString("D4")}"; - } - } -} \ No newline at end of file diff --git a/Source/Additional Samples/GnssTracker_SQLite_Demo/Controllers/MainTrackerController.cs b/Source/Additional Samples/GnssTracker_SQLite_Demo/Controllers/MainTrackerController.cs deleted file mode 100644 index 2ec9ec6..0000000 --- a/Source/Additional Samples/GnssTracker_SQLite_Demo/Controllers/MainTrackerController.cs +++ /dev/null @@ -1,135 +0,0 @@ -using GnssTracker_SQLite_Demo.Models.Logical; -using Meadow; -using Meadow.Devices; -using Meadow.Logging; -using Meadow.Peripherals.Sensors.Location.Gnss; -using System; -using System.Threading.Tasks; - -namespace GnssTracker_SQLite_Demo.Controllers -{ - /// - /// This is the main tracker application controller. It's responsible for - /// orchestrating the entire operation of the application. - /// - public class MainTrackerController - { - GnssPositionInfo lastGNSSPosition; - DateTime lastGNSSPositionReportTime = DateTime.MinValue; - readonly TimeSpan GNSSPositionReportInterval = TimeSpan.FromSeconds(15); - - private TimeSpan UPDATE_INTERVAL = TimeSpan.FromMinutes(1); - - protected IGnssTrackerHardware GnssTracker { get; set; } - - protected Logger Log { get => Resolver.Log; } - - protected AtmosphericModel? LastAtmosphericConditions { get; set; } - - protected LocationModel? LastLocationInfo { get; set; } - - protected DisplayController DisplayController { get; set; } - - public MainTrackerController() { } - - public async Task Initialize(IGnssTrackerHardware gnssTracker) - { - GnssTracker = gnssTracker; - - LastLocationInfo = new LocationModel(); - LastAtmosphericConditions = new AtmosphericModel(); - - if (gnssTracker.Display is { } display) - { - DisplayController = new DisplayController(display); - await Task.Delay(TimeSpan.FromSeconds(20)); - } - - if (gnssTracker.Gnss is { } gnss) - { - gnss.RmcReceived += GnssRmcReceived; - gnss.GllReceived += GnssGllReceived; - } - } - - private void GnssRmcReceived(object sender, GnssPositionInfo e) - { - if (e.Valid) - { - ReportGNSSPosition(e); - lastGNSSPosition = e; - } - } - - private void GnssGllReceived(object sender, GnssPositionInfo e) - { - if (e.Valid) - { - ReportGNSSPosition(e); - lastGNSSPosition = e; - } - } - - private void ReportGNSSPosition(GnssPositionInfo e) - { - if (e.Valid) - { - if (DateTime.UtcNow - lastGNSSPositionReportTime >= GNSSPositionReportInterval) - { - Resolver.Log.Info($"GNSS POSITION: LAT: [{e.Position.Latitude}], LONG: [{e.Position.Longitude}]"); - - lastGNSSPositionReportTime = DateTime.UtcNow; - } - } - } - - private void AtmosphericSensorUpdated() - { - Log.Info($"BME688 - Temperature: {GnssTracker.TemperatureSensor.Temperature.Value.Celsius:N2}C,"); - Log.Info($"BME688 - Humidity: {GnssTracker.HumiditySensor.Humidity.Value.Percent:N2}%, "); - Log.Info($"BME688 - Pressure: {GnssTracker.BarometricPressureSensor.Pressure.Value.Millibar:N2}mbar ({GnssTracker.BarometricPressureSensor.Pressure.Value.StandardAtmosphere:N2}atm)"); - - var newConditions = new AtmosphericModel - { - Temperature = GnssTracker.TemperatureSensor.Temperature, - RelativeHumidity = GnssTracker.HumiditySensor.Humidity, - Pressure = GnssTracker.BarometricPressureSensor.Pressure, - Timestamp = DateTime.Now - }; - LastAtmosphericConditions.Update(newConditions); - - DatabaseController.SaveAtmosphericLocations(LastAtmosphericConditions, LastLocationInfo); - DisplayController.UpdateDisplay(LastAtmosphericConditions, LastLocationInfo); - } - - public async void Run() - { - if (GnssTracker.TemperatureSensor is { } temperatureSensor) - { - temperatureSensor.StartUpdating(UPDATE_INTERVAL); - } - - if (GnssTracker.BarometricPressureSensor is { } barometer) - { - barometer.StartUpdating(UPDATE_INTERVAL); - } - - if (GnssTracker.HumiditySensor is { } humiditySensor) - { - humiditySensor.StartUpdating(UPDATE_INTERVAL); - } - - if (GnssTracker.Gnss is { } gnss) - { - gnss.StartUpdating(); - } - - while (true) - { - AtmosphericSensorUpdated(); - - await Task.Delay(UPDATE_INTERVAL); - } - } - } -} \ No newline at end of file diff --git a/Source/Additional Samples/GnssTracker_SQLite_Demo/GnssTracker_SQLite_Demo.csproj b/Source/Additional Samples/GnssTracker_SQLite_Demo/GnssTracker_SQLite_Demo.csproj deleted file mode 100644 index 1a2d08b..0000000 --- a/Source/Additional Samples/GnssTracker_SQLite_Demo/GnssTracker_SQLite_Demo.csproj +++ /dev/null @@ -1,27 +0,0 @@ - - - netstandard2.1 - true - Library - App - - - - - - - - - - Always - - - - - - - - - - - diff --git a/Source/Additional Samples/GnssTracker_SQLite_Demo/MeadowApp.cs b/Source/Additional Samples/GnssTracker_SQLite_Demo/MeadowApp.cs deleted file mode 100644 index 35d8c80..0000000 --- a/Source/Additional Samples/GnssTracker_SQLite_Demo/MeadowApp.cs +++ /dev/null @@ -1,41 +0,0 @@ -using GnssTracker_SQLite_Demo.Controllers; -using Meadow; -using Meadow.Devices; -using System; -using System.Threading.Tasks; - -namespace GnssTracker_SQLite_Demo -{ - public class MeadowApp : App - { - protected MainTrackerController MainController { get; set; } - - public override async Task Initialize() - { - Resolver.Log.Info("Initialize hardware..."); - - var gnssTracker = GnssTracker.Create(); - - try - { - DatabaseController.ConfigureDatabase(); - } - catch (Exception e) - { - Resolver.Log.Info($"Err bringing up database: {e.Message}"); - } - - MainController = new MainTrackerController(); - await MainController.Initialize(gnssTracker); - } - - public override Task Run() - { - Resolver.Log.Info("Running"); - - MainController.Run(); - - return base.Run(); - } - } -} \ No newline at end of file diff --git a/Source/Additional Samples/GnssTracker_SQLite_Demo/Models/Data/SensorDataModel.cs b/Source/Additional Samples/GnssTracker_SQLite_Demo/Models/Data/SensorDataModel.cs deleted file mode 100644 index 8ae10a5..0000000 --- a/Source/Additional Samples/GnssTracker_SQLite_Demo/Models/Data/SensorDataModel.cs +++ /dev/null @@ -1,35 +0,0 @@ -using SQLite; -using System; - -namespace GnssTracker_SQLite_Demo.Models.Data -{ - [Table("SensorReadings")] - public class SensorDataModel - { - [PrimaryKey, AutoIncrement] - public int ID { get; set; } - public DateTime Timestamp { get; set; } - public double? TemperatureC { get; set; } - public double? RelativeHumidityPercent { get; set; } - public double? PressureAtmos { get; set; } - public string? Latitude { get; set; } - public string? Longitude { get; set; } - - public SensorDataModel() { } - - public static SensorDataModel From(Logical.AtmosphericModel atmospheric, Logical.LocationModel location) - { - var dataModel = new SensorDataModel - { - TemperatureC = atmospheric.Temperature?.Celsius, - RelativeHumidityPercent = atmospheric.RelativeHumidity?.Percent, - PressureAtmos = atmospheric.Pressure?.StandardAtmosphere, - Timestamp = atmospheric.Timestamp.Value, - Latitude = $"{location.PositionInformation?.Position?.Latitude?.Degrees} {location.PositionInformation?.Position?.Latitude?.Minutes}'{location.PositionInformation?.Position?.Latitude?.Seconds}\"", - Longitude = $"{location.PositionInformation?.Position?.Longitude?.Degrees} {location.PositionInformation?.Position?.Longitude?.Minutes}'{location.PositionInformation?.Position?.Longitude?.Seconds}\"", - }; - - return dataModel; - } - } -} \ No newline at end of file diff --git a/Source/Additional Samples/GnssTracker_SQLite_Demo/Models/Logical/AtmosphericModel.cs b/Source/Additional Samples/GnssTracker_SQLite_Demo/Models/Logical/AtmosphericModel.cs deleted file mode 100644 index 33e9fa3..0000000 --- a/Source/Additional Samples/GnssTracker_SQLite_Demo/Models/Logical/AtmosphericModel.cs +++ /dev/null @@ -1,21 +0,0 @@ -using Meadow.Units; -using System; - -namespace GnssTracker_SQLite_Demo.Models.Logical -{ - public class AtmosphericModel - { - public DateTime? Timestamp { get; set; } - public Temperature? Temperature { get; set; } - public RelativeHumidity? RelativeHumidity { get; set; } - public Pressure? Pressure { get; set; } - - public void Update(AtmosphericModel model) - { - if (model.Timestamp is { } time) { Timestamp = time; } - if (model.Temperature is { } temp) { Temperature = temp; } - if (model.RelativeHumidity is { } humidity) { RelativeHumidity = humidity; } - if (model.Pressure is { } pressure) { Pressure = pressure; } - } - } -} \ No newline at end of file diff --git a/Source/Additional Samples/GnssTracker_SQLite_Demo/Models/Logical/LocationModel.cs b/Source/Additional Samples/GnssTracker_SQLite_Demo/Models/Logical/LocationModel.cs deleted file mode 100644 index 9bcaee0..0000000 --- a/Source/Additional Samples/GnssTracker_SQLite_Demo/Models/Logical/LocationModel.cs +++ /dev/null @@ -1,9 +0,0 @@ -using Meadow.Peripherals.Sensors.Location.Gnss; - -namespace GnssTracker_SQLite_Demo.Models.Logical -{ - public class LocationModel - { - public GnssPositionInfo? PositionInformation { get; set; } - } -} \ No newline at end of file diff --git a/Source/Additional Samples/GnssTracker_SQLite_Demo/app.config.yaml b/Source/Additional Samples/GnssTracker_SQLite_Demo/app.config.yaml deleted file mode 100644 index 7ec1876..0000000 --- a/Source/Additional Samples/GnssTracker_SQLite_Demo/app.config.yaml +++ /dev/null @@ -1,14 +0,0 @@ -# Uncomment additional options as needed. -# To learn more about these config options, including custom application configuration settings, check out the Application Settings Configuration documentation. -# http://developer.wildernesslabs.co/Meadow/Meadow.OS/Configuration/Application_Settings_Configuration/ - -Lifecycle: - # Control whether Meadow will restart when an unhandled app exception occurs. Combine with Lifecycle > AppFailureRestartDelaySeconds to control restart timing. - RestartOnAppFailure: false - # # When app set to restart automatically on app failure, - #AppFailureRestartDelaySeconds: 15 - -# Adjust the level of logging detail. -Logging: - LogLevel: - Default: Trace \ No newline at end of file diff --git a/Source/Additional Samples/GnssTracker_SQLite_Demo/gnss_tracker.bmp b/Source/Additional Samples/GnssTracker_SQLite_Demo/gnss_tracker.bmp deleted file mode 100644 index 073e8ae7180a4ca49200f0013f1f8c46f41382b3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 91882 zcmeI5JFG5Ob;qwsu#}_#97RfX@kLRT4hSU?7&oaRAQhGZ7#q3dp>$Cs>>^DHOp7JJ z(DUk2@kr03OJ}GP@o3US0`j~5>Hb-)Ju}~Y-+brs-7_ORtXX@#_S*lw_MUy_ocruQ z{P#;w+imfBno$FFpDCm%sccfA^>V^+$j8Pp|&% z@AdE9`{VlX(8zx68MreU*zta6hI;QP8QAf@!{9DuV8{Di8tuKWJKlE;+@%ccc)v@d zz4vv;`;LLTlz|=ZcWJcuzV3M6F>seMu;cwMjrQKx9q&5^?otMJyx*nK-ut@aeaFCE z%D|5IyENK+Uw6Fk7`RIr*ztasMtkq;j`tk{cPRrq-tW?A?|nTt-hcbs-(GZ5FFpR- zpZuH6@VW86G2bm2?Qx@V)X#2kdq{H@Hio)UeJ-j={^)DuOe!8^&e@scA2fK&@P07f z(*$aIDt(%@s@1HuM+u89ufcLq?&+*q|aJz-|zAjzzmgH(R-k*8%TF816 zX#M-y&wh4L;A>y|8Zz&B&wHMJ`st5+=p>FTecjU;mocZ-4vS7{tz;k*13zL$@|VyWf#9(@C8VGHz zTbYIgr$ut?;~~7qxqroD!ThoScwZ0zWwvsE;tBsw$wLNc`qG!aH0hMU7#xru#dp5* zouV&_3<&h|&p$s}*rH2cn2}gE)aI7~AKirmoKfT=wlE>gGf~+E?Ax0BSK$Tv#TQ@H z{>pojV_yuOdsUz8QO$f6hCab&^`72UrXj&e>uJOxyvM42%Hv2Z3oPK>%rU|gHN><` z-2oa7KC@vQcA)Xz_r4dWD1sdxRm4ItWzkRi6EnhSMK}CW_fwzxl&u6{49HCCQq(^C z+0U8;0*=i_WJaKR7!hK!hOUh zef;J(zgcB;q-$DD%Xhx>o%D`^uDk^gZ1^}XHc?qa+%(?p$AbqCg7g}7z%?T1bD#Sh z2>{VSdR6@CPk$O@1+x(VYv?j8ZhOL)0BGtmk{PGDsz%nG9APtmoQ8(Dl0*p31~6=ZQa@-c;x&@_RL$Y@{Sz@G%W zG8wdncXrT3vaFkGlA)_Mmvz7R#V=wXBd&QXjzu!1WBH5*2lruD>nyua|m3wTKf zp}7pH)%O;sl5TP$X@pp#b<(B+46EwRrmb^(B&U>$-u1pdEs@-S_drr(1`@-Kn8dpq z4+g&pw@2PmNRM;ECV|to_AMSH0VYu;{pyM}K-avq$4Oo5?@HYou*R9S!~?F)#s@$6 z!RpjWMowT_DC_Il*t@D5y5XI^kC(#1yOtfkuYUEbv{HphxDyvXOBzPL{`Ie`_^oe! zi&pm)+@ax+Rb-&Ke*EJfkCJk@V-Wme6LcFJqiJiyI|%{T+HCiecQqUEo*qb;u*S@z zBaBQq5W)u(y!+knrt9>N!o5(kqpRWws0c_1Z7f&58ebNBDxPuC%U6&aGn$*-E?<@Fd<7k6|zbpZLTlh@30+JrP!d z8cnV|i6rK^y6hTO$6DG_&Rt*JaqYTJNUS>Cxl%%^>!aumcyE3Typ4QhCc$Ej`}xm* zju-<@w&*b(Wd=Cf+N9C}Qo0*!D{C}}8>^(cF*QfHWeVQym+>@}vCDJ;N%|5=dPk4A zGIvb~HC-8mQK?geF(>%i>sVVLR^lBCYw*6{XrT$Pn<(ydA@o6_tuCW3oCUvYn$CoG z%M%@%^Xc$1;1wP2QeDAEMN~Kh00?fSD}2BLzUCBT${j*5D}UK(beVIwXu3o~%2)cW zV!#$_gpK`VKo@iqrlDpw!1=)set=3Q1e`V3M!dIIqUteWS7xOnz;>RWB+O&0h205i&~oclJKlVakH_LYhgS}tch;wB+2txs&LgWZ zG#urX^!+nOkF`)KMjx#@&CcXwQ?I9?HOQ6pk$9gQYR1Z7Co#x)TBEaGXH@0S?aL7J ztb8=9;&?7^zwzk4g{a1u)veW}W(#~NFzRLw&G~)fjW^UyPq8eVnE}-cG^hW#;HPE? zLol#Oi;_++rbSa+csv&GNlx87gjvIIae_mr<7MQn9w;^$zmlV!8pfphBy%Alt?3Zn zGXe>19BMeUGM-|SY%#*|14iUCGb>*KkgjgqyU`j&${chIO2EM*x>S>9mZks}fechE zuu8$_8g(hbRkw{i7R2VHE`3p#sa8V*$jGNYCJYFN9eMgvRg^K#wkTHhk#2YgYvZL> z&Le&Flo4SDg7-r@ZkeXlAQ?Ugn2|)7x7mkze1sw;lQf%%9}X95i3DPf9Zh)`)wMP& z>fsoncWsVnsWJ=nqevG-Y%&B#n`#Tj353U>gVCm7(E}vu4Lze(q!S~YxxJ8ZKnAnW z*x@22uIAVu!EQ(xG;Q2*ggY>W5mUk$Cmd)Z8GDBd29VZ-iY~!N*Qh3SHLEUu`N=x> z>O2vC>)hGr>$?RvU3?pk)GDWc*?gu54w5UK-2!|iZ zYLgid0f+`|o7yC(>dW*WhCe4u=JW#r5JXvmVoX@a%`Qa>I5YtUb9ux-uAqob3Gy+g zs5@FyETYTT3FgCbn@lP_oz$f-YjpV`E%PZJL(unDrtv~6X6JHC69R2(A7Q5*Q!1Qg zLKMIM{qLt2a~BAr>DgzW#V^S*lN=4eH+ar~;b%dDPaRKx2`QFc36NysB1RL#!4ImS zF$kYWuc+fRSB6G)y$A195d2p?Yr%u;8-la3C?K!j9_ zIWGs*o1%CZP?IIKF@rey^tu_$V_+DxLZI$+QJoP-o;yu&q6;ynu1r-o^H|Wb0+TkY z{gw1;ywBOILCwj?UzS|ox-7XI!}?aU9yqL5tdbi;Jwd(V9mpKK(m^Bv9lf4&>PpiL zQiAQTD?0Ut$4J&6mQ5Z~#(Px{-fJdRN31eWpf}@vjnBChuF*Za%oq%uk$D!p6Z~j- zp+`pvFW5PuNg&f}b!#MSAsWovBX2@#`H`^2y2)S!nH*Bu8oaCSz2RN&d3mmqC(ze| z_rz7R80LCnqxyPBNS=)MD+=&%}-20OnM*VS;;vE-fM%m`wezv()A>YDUNifUhG>uJIqQz*;Rnzn_?>N;8$NrMm<&D`i^%lZIb8M#6oPc zkVG9}CP%(4pt8Sd;NdMyy?Y*Mgs4v*h1DSE=yTv*+beN27szenb4*Bf>*?n92p3Yc z&~%hvkV3_56_&?ZF)gW}rdqCbHtLgjuj-^oncw{8H`SW7lHT)!t*WjVeIFe)CebS6 zy#+tIp5vSe@8=q>xiBj~zCzU2jkGqK<@Pwbm=l=ej~3t@B|K>XCU^%C0jy&A-RcUN z_W6)oZv{L{LD$DgNoqF&lShv_je2a-LCW-;P3D0%lZVMeO4XH&qxHn`csHB`wcgcL zNFE!;octVrGUlU%wNO7(y$3^0gL5T)a0H6#pXH!5bZ>8Jfw`H z7*U-$0SAOmx<;mXSF$m)khC}I_*zLEkN0M{jvjk}Yq(C{yS2!#^s%O8*^$5QqRe`& zIh*30y8UW4PH}|Dw~SPF;F)tiM}$ve=!+MB90p;w*!&%n8i0qC%H%*%0UjS| z|Nj4VgfFf+@09zTM-qvc@#s*Or^n; z+rTzO{FIYWA3S*Ag7KjbeTc`vKSmf$djtV9g{DFN1n_1Iv48T0G;vCZcLN4WBhx1C zb|>m^kf(RyG-7$~PCAka_Tv;{Qc{5y(xjx!lkboGpKL(II&{}l7hxH2XvZgWE?~#3v!}%q-4K*NjhL=;;hk9s7d?I<<+unxQTxGAurL)B{Q8dEJJ#i)^delNn z)3L-hyf<%*d7aW(5F?hM2$81s1c^^>AgIC%xIHG!;`i5JsJ z0^p$Dg3%yoG9K3(a0TS@Aq>3a zYRFnpT-g+C#sx$x2{yI&ZSAWbY|7-ZS~Jg+l5Gg8mNpTPxjv*xn@xRXauC~w_vVMt z2&DG1?o37^f|y@Fm(2sWxv1-tBH%QY*?@KDInsXYD=rWiJs{jJt{f zyO9LlA~BC7zJm%Op|9`T+GkjP} zeb=V<$>iiX6JH3R%f)&Ft)~zPK`a~_ zweqRI3tmVJ-Yx5aJo18_l{B%jVJH3AtY*nKzEI~a!B;GXj;^WB=vCKmyz%glErIK? zJAt0^XWzERV?xrAcVbq+8eoOUm%!155Y+ZMd>*T{N;gSWNDeZ1@lo|jNdl|Z8f~-- z>WOeYaW#0yKO>yVOFt&NyFSc0$(FGCx_}A^1Mg-rkSD5&R=~?n17Vqsclg0g?F09 zXxrIgvsvXQ&m*-=kV^V-=cJ=*Y9)PEyw}X(zvX`NBbJq6E{N5tO{&Col@CH|ld+N1 ztc(FH_@z>7Az;T#Y{sLIhhKG}BMC8X+vBl{or|^_rqZyrz_NgCi;B$8fBy5jW&x`} z4vndLb~qO&nMCrt-~DbC7;VB)poIi-xH2=K5kojOnVry4uU?L#&x&_F8!R+KO)X32 zAQ~2qigZEP(i}%4paOa4+z57!SJ(piNw6zfAz!t|4z@|pvZsY)X`x>yG&OfxnA{RH zX0itXvg#w*Ymtn>E8irmkt8ww0Why(DF>Ub(fY#6 zh`T`Em!ewPYrp|-4A#nCB?Ecf*|pJW+qP$)Q0<(T7Vq>CfUsK-9Udrh_mSEP*hvVN zuaT5~grR+bR6WO;h!JFfrn<+3lom|oRb0vR$l>rjk|vOgm+JjTKl+ivY+4dhPI(Q< zbJM)a;%oelGae5TSB!W32N(99ZXFEjpg?jTNz$qPIWMS0rhTW&q!=zz3@QJvQpG3;PGCzsTB9AynSHj~$a_gXPYCshy5v5`i;0y9hqM%AqaF1#kaH1*}j zYX2x2Og)O?;r}yeN2#AI+)9fvSc|#y$lhGzpoT~8KDIqOO}T7}2?0 z<)-erDf3d{HeLsVX#&@RcVc8h)_w!b7RbquH30y;dAW+$g%)ZJz$U6#4P!i^Y!=S= zIQgsD#DfdA!$ieiPIpS?&?fIIHS$VRmlNmMWtzfFWv}X?t9O|R$tL5Z$$92(paq{u zjwP-I?*^6KuDwjAj}3WQz9oBoRa!Q?zLhywu`{`~UvKR+NibrP7tSNAWueO7)MzJy zRi@FvUl-h;dg>`#D>JQ?Xr(+hJ$kGMpZRD~^>d-+8u3o&KJbAL)ZVj4OHoMIw-fCr z-&gdyFc&A)y!P>Ww(Tt#5^D^m*G>e_Z+9TY^`_z7--C8{4B{xw zk)+x}C-^E!BvsNEV>TO&$?I;8GjkqER7g6#v`I)@bH|wo=ZLh0bZkN*e~oyzqwFQ! zmpOaSxRFnvaKxK_tq%OyE3H>Y)X#nKex2L))~VpVCIMtsF%V5_m{l^g@<=jdlagzg zt!iVF0n&RMLEvJPM7T-TE}TGLBi<8THu3_0^58JSClm2vQd6x?Hn^-<7Zv(NJ-W6< zWem(?LXeURU{X>oIm&YkLaX&1js-gM5O9=-CWn@C$`voVaN3%IFfLU8#y7s93o~Eq zJBa4OwWo~A`_h0gO)Azn^-im3Vc9_aT-PO>KE866?e-kR{G^yvkw{5#e zBDko%KCj1Xvlhe&I{o^Rl=?myjCh~CgW0H%B4s8AsCtj7svbLQh-<`q4X0K^I&pOy z`Rh3PwzH8m-jNEV12 z!aET$nQI!Tk0fl&*+T5CY1C~SYTPlgn%4Hm=7n|tscQ4$v+0<)bN6|NjcfzdwqnBsd$OrXp z2{DUXyu@-%aQmSyb?S{r-x61`YolHLv(2#AS^en(S5i@l8X@vFRc3y|S+yD+M=IJX zGwL=GA+3p1=H%9ex=75EA=U6!(l?5CVx-`j74Pkrb60j^Qmk#LtCv=WCe>FmbC#xk z%1~8gpz7l_&<*b#>46u10s*qT5-=NZK;$-@;1e4$XX%yc*&*vz&7rg}vDiU{yS3Z5 zW!9MLJ?h%z=k2KEGZ-o#k-MwWW{xv?BytjqJO&fzX+-JhX$CfGQHANHix(*b{%|(h zL_N!&!@?J&bz+^%OUA_bvy0ds|H&2_-nAn$Nj4|IhgR-BR*#LTx?=4P604&0s9s%< z@^Grz*c_SL>&H#woxV0~rn{4gS;L&%P-hU#;`YOFmLlts2AM-{+qaL&nm*3Sh)qi* zUFKpVk=iQm{2`RBAOHBrjo$()6BR~*n#)F>s!bDSSqZqq=N^J41dvA&!VFNg=hU%T zBS)Ua1246{2LJ{}@VL{_<=1z6PlxPWa$mD@6g_UJvtW?aT4=VsE;KKM?YFE)g?bgj zWRgDCZq~#~J0pSB*d!;2(+)s3)Nv})REzV6ugPDavEPmi z62nzz=GNeyj-K`fKvGpV)MRvS#x%5M^<0^0X3QL4W{rU`+T$4ZL4i?4&W+-IjJj>)P3m0imEU$mKyqQP(!8+Xj*(R3q4Cn*{dhM{ z>un%BI|Q~XuVk2)8&r7Y${{7Sfk*N~QxH0dcO-dho&0rgtj*cX*8as8UtA8D6SgXF za@ubc?;}8{o^G)%3cwbQV#|*6?YN0;=E#=~io1C@A*OeNyFZQGZ#%Vl9-ESG*NlZIU1pWs* z1n!avh&3B(ehOMgesc38%yajZDUP2?F4qe%-%+ACN9w)ZBNy>s|CkY|=;j zWi77fk|nL+ywiwX>sS)Nx)oIcr}h9OY#kw5#K+$Geh2 zagMD(ZkV-@EY}0oJv*H2UDjZ~IcPGV7{7NI?`)|3H!dw4>^CO2*hg)sGfR?eZ2Gz& z>gTF<^Wp(tvFk>j((Gz$v6w5(ljG2s zqnE%oCpmiI=X)#v(bwkU+8!(3>BS__45s0odJTk4DRmh-#n&^={FYvoWcKqy%a2K6 z0!gpDg-&{BW0R9h^yP| zKXu%MxsgBPhT7q38+p8NAmb~Rl^yS?cLcd*ZjF6BBgg&w$3FHkZ3bnPF#d*jt2WTi z1xF)rP`8w`$yCynAd{e~`zzIXLDjWu24YyCY|x6?tOQ5l9fOZ=eJAB@!h0N?0US5f zj?%IB_PWr#Fay}z9BcFX@^iOBNieHB4SM?=|76#5Hyo1URZpOGIE2$ z!TWLy5%u7`9<^&T!V=jcR=h7nP9%>h z-p5X}p|05?yU7;9X8}8Q+D0CaLBtr+E#w@;yNTl7>btphn-Rd)4)Tgv^FK+et|S9g z2PIV-esq)Dm3Swf#~SZ7Vf57!W5Q0}P&b=(NToB{3=3XZT1J^$%MrzVKLeDOuY5ma zLO4^T<5uKkz;1dT*{3&-a(U! zHr4mlX0WMO$y&$Jili1AV8wegzVO)8$1coqE)DN<{n+_tfLaXb)?bsr@vFyd7ukwn zkcvE-t?y3+pyVh92T2zaUR=Sxg(Pb&({xfROjJS>Nq!7-?6~iEKQ?2xUOpf?Hqw(7 z=NwHMoMg^f2>&##sE4>5yq~Mb>G}epuj}-<5X==djlCN=SLFHz&F*-=!Q@|{>r0;# zmxK2U1jioonKQ6`w(WR7^N`#kbKB9ey)z3jEHrKRJ7?j-@qXT%o!8o2$}fmNmk{}L zt#ojq>1Mls;dsB<FK)>8fH!1d$NPrl?Wz}-fgSG`H)MOj8#1uteM9ng z)r-r(j`xcjvOVAp8QAf@A$hy%#bsc}`^62}9`J???0Dahyj}I;GO*+Q;)ZMwctZwu zyl+U}u6l79*ztaGL$(LJAp<+!HzaRYy|@hQc)z$I+XLQ^fgSG~lDDf~Tn2W$U)+%G L0dL5_y?g%;9-upY diff --git a/Source/GnssTracker/GnssTracker.csproj b/Source/GnssTracker/GnssTracker.csproj index dfd79e7..738f27d 100644 --- a/Source/GnssTracker/GnssTracker.csproj +++ b/Source/GnssTracker/GnssTracker.csproj @@ -22,12 +22,12 @@ - - - - - - - + + + + + + + diff --git a/Source/GnssTracker_Demo/Controllers/DisplayController.cs b/Source/GnssTracker_Demo/Controllers/DisplayController.cs index 2d7cf34..2070bcb 100644 --- a/Source/GnssTracker_Demo/Controllers/DisplayController.cs +++ b/Source/GnssTracker_Demo/Controllers/DisplayController.cs @@ -5,214 +5,213 @@ using Meadow.Peripherals.Sensors.Location.Gnss; using Meadow.Units; -namespace GnssTracker_Demo.Controllers +namespace GnssTracker_Demo.Controllers; + +public class DisplayController { - public class DisplayController + private readonly int marginX = 8; + private readonly int offsetY = 5; + + private readonly Font8x12 largeFont = new Font8x12(); + + private readonly DisplayScreen displayScreen; + private readonly AbsoluteLayout dataLayout; + + private readonly Label solarVoltageLabel; + private readonly Label temperatureLabel; + private readonly Label humidityLabel; + private readonly Label pressureLabel; + private readonly Label co2LevelsLabel; + private readonly Label latitudeLabel; + private readonly Label longitudeLabel; + private readonly Label batteryVoltageLabel; + + public DisplayController(IPixelDisplay display) { - private readonly int marginX = 8; - private readonly int offsetY = 5; - - private readonly Font8x12 largeFont = new Font8x12(); - - private readonly DisplayScreen displayScreen; - private readonly AbsoluteLayout dataLayout; - - private readonly Label solarVoltageLabel; - private readonly Label temperatureLabel; - private readonly Label humidityLabel; - private readonly Label pressureLabel; - private readonly Label co2LevelsLabel; - private readonly Label latitudeLabel; - private readonly Label longitudeLabel; - private readonly Label batteryVoltageLabel; - - public DisplayController(IPixelDisplay display) - { - displayScreen = new DisplayScreen(display, RotationType._90Degrees); - - displayScreen.BeginUpdate(); - - dataLayout = new AbsoluteLayout(displayScreen, 0, 0, displayScreen.Width, displayScreen.Height) - { - BackgroundColor = Color.White - }; - - dataLayout.Controls.Add(new Box(0, 0 + offsetY, displayScreen.Width, 15) - { - ForeColor = Color.Red, - IsFilled = true - }); - - dataLayout.Controls.Add(new Label(marginX, 3 + offsetY, displayScreen.Width, largeFont.Height) - { - Text = $"BATTERY VOLTAGE:", - TextColor = Color.White, - Font = largeFont - }); - batteryVoltageLabel = new Label(0, 3 + offsetY, displayScreen.Width - marginX, largeFont.Height) - { - Text = $"0.00 V", - TextColor = Color.White, - Font = largeFont, - HorizontalAlignment = HorizontalAlignment.Right - }; - dataLayout.Controls.Add(batteryVoltageLabel); - - dataLayout.Controls.Add(new Label(marginX, 18 + offsetY, displayScreen.Width, largeFont.Height) - { - Text = $"SOLAR VOLTAGE:", - TextColor = Color.Black, - Font = largeFont - }); - solarVoltageLabel = new Label(0, 18 + offsetY, displayScreen.Width - marginX, largeFont.Height) - { - Text = $"0.00 V", - TextColor = Color.Black, - Font = largeFont, - HorizontalAlignment = HorizontalAlignment.Right, - }; - dataLayout.Controls.Add(solarVoltageLabel); - - dataLayout.Controls.Add(new Label(marginX, 33 + offsetY, displayScreen.Width / 2, largeFont.Height) - { - Text = $"TEMPERATURE:", - TextColor = Color.Black, - Font = largeFont - }); - temperatureLabel = new Label(0, 33 + offsetY, displayScreen.Width - marginX, largeFont.Height) - { - Text = $"0.0 C", - TextColor = Color.Black, - Font = largeFont, - HorizontalAlignment = HorizontalAlignment.Right, - }; - dataLayout.Controls.Add(temperatureLabel); - - dataLayout.Controls.Add(new Label(marginX, 48 + offsetY, displayScreen.Width, largeFont.Height) - { - Text = $"HUMIDITY:", - TextColor = Color.Black, - Font = largeFont - }); - humidityLabel = new Label(0, 48 + offsetY, displayScreen.Width - marginX, largeFont.Height) - { - Text = $"0.0 %", - TextColor = Color.Black, - Font = largeFont, - HorizontalAlignment = HorizontalAlignment.Right, - }; - dataLayout.Controls.Add(humidityLabel); - - dataLayout.Controls.Add(new Label(marginX, 63 + offsetY, displayScreen.Width, largeFont.Height) - { - Text = $"PRESSURE:", - TextColor = Color.Black, - Font = largeFont - }); - pressureLabel = new Label(0, 63 + offsetY, displayScreen.Width - marginX, largeFont.Height) - { - Text = $"0.0 ATM", - TextColor = Color.Black, - Font = largeFont, - HorizontalAlignment = HorizontalAlignment.Right, - }; - dataLayout.Controls.Add(pressureLabel); - - dataLayout.Controls.Add(new Label(marginX, 78 + offsetY, displayScreen.Width, largeFont.Height) - { - Text = $"CO2 LEVELS:", - TextColor = Color.Black, - Font = largeFont - }); - co2LevelsLabel = new Label(0, 78 + offsetY, displayScreen.Width - marginX, largeFont.Height) - { - Text = $"0.0 PPM", - TextColor = Color.Black, - Font = largeFont, - HorizontalAlignment = HorizontalAlignment.Right, - }; - dataLayout.Controls.Add(co2LevelsLabel); - - dataLayout.Controls.Add(new Box(0, 90 + offsetY, displayScreen.Width, 32) - { - ForeColor = Color.Red, - IsFilled = true - }); - - dataLayout.Controls.Add(new Label(marginX, 94 + offsetY, displayScreen.Width, largeFont.Height) - { - Text = $"LATITUDE:", - TextColor = Color.White, - Font = largeFont - }); - latitudeLabel = new Label(0, 94 + offsetY, displayScreen.Width - marginX, largeFont.Height) - { - Text = $"00 00' 0.0\"", - TextColor = Color.White, - Font = largeFont, - HorizontalAlignment = HorizontalAlignment.Right, - }; - dataLayout.Controls.Add(latitudeLabel); - - dataLayout.Controls.Add(new Label(marginX, 109 + offsetY, displayScreen.Width, largeFont.Height) - { - Text = $"LONGITUDE:", - TextColor = Color.White, - Font = largeFont - }); - longitudeLabel = new Label(0, 109 + offsetY, displayScreen.Width - marginX, largeFont.Height) - { - Text = $"00 00' 0.0\"", - TextColor = Color.White, - Font = largeFont, - HorizontalAlignment = HorizontalAlignment.Right, - }; - dataLayout.Controls.Add(longitudeLabel); - - displayScreen.Controls.Add(dataLayout); - - displayScreen.EndUpdate(); - } + displayScreen = new DisplayScreen(display, RotationType._90Degrees); + + displayScreen.BeginUpdate(); + + dataLayout = new AbsoluteLayout(0, 0, displayScreen.Width, displayScreen.Height) + { + BackgroundColor = Color.White + }; + + dataLayout.Controls.Add(new Box(0, 0 + offsetY, displayScreen.Width, 15) + { + ForeColor = Color.Red, + IsFilled = true + }); + + dataLayout.Controls.Add(new Label(marginX, 3 + offsetY, displayScreen.Width, largeFont.Height) + { + Text = $"BATTERY VOLTAGE:", + TextColor = Color.White, + Font = largeFont + }); + batteryVoltageLabel = new Label(0, 3 + offsetY, displayScreen.Width - marginX, largeFont.Height) + { + Text = $"0.00 V", + TextColor = Color.White, + Font = largeFont, + HorizontalAlignment = HorizontalAlignment.Right + }; + dataLayout.Controls.Add(batteryVoltageLabel); + + dataLayout.Controls.Add(new Label(marginX, 18 + offsetY, displayScreen.Width, largeFont.Height) + { + Text = $"SOLAR VOLTAGE:", + TextColor = Color.Black, + Font = largeFont + }); + solarVoltageLabel = new Label(0, 18 + offsetY, displayScreen.Width - marginX, largeFont.Height) + { + Text = $"0.00 V", + TextColor = Color.Black, + Font = largeFont, + HorizontalAlignment = HorizontalAlignment.Right, + }; + dataLayout.Controls.Add(solarVoltageLabel); + + dataLayout.Controls.Add(new Label(marginX, 33 + offsetY, displayScreen.Width / 2, largeFont.Height) + { + Text = $"TEMPERATURE:", + TextColor = Color.Black, + Font = largeFont + }); + temperatureLabel = new Label(0, 33 + offsetY, displayScreen.Width - marginX, largeFont.Height) + { + Text = $"0.0 C", + TextColor = Color.Black, + Font = largeFont, + HorizontalAlignment = HorizontalAlignment.Right, + }; + dataLayout.Controls.Add(temperatureLabel); + + dataLayout.Controls.Add(new Label(marginX, 48 + offsetY, displayScreen.Width, largeFont.Height) + { + Text = $"HUMIDITY:", + TextColor = Color.Black, + Font = largeFont + }); + humidityLabel = new Label(0, 48 + offsetY, displayScreen.Width - marginX, largeFont.Height) + { + Text = $"0.0 %", + TextColor = Color.Black, + Font = largeFont, + HorizontalAlignment = HorizontalAlignment.Right, + }; + dataLayout.Controls.Add(humidityLabel); + + dataLayout.Controls.Add(new Label(marginX, 63 + offsetY, displayScreen.Width, largeFont.Height) + { + Text = $"PRESSURE:", + TextColor = Color.Black, + Font = largeFont + }); + pressureLabel = new Label(0, 63 + offsetY, displayScreen.Width - marginX, largeFont.Height) + { + Text = $"0.0 ATM", + TextColor = Color.Black, + Font = largeFont, + HorizontalAlignment = HorizontalAlignment.Right, + }; + dataLayout.Controls.Add(pressureLabel); + + dataLayout.Controls.Add(new Label(marginX, 78 + offsetY, displayScreen.Width, largeFont.Height) + { + Text = $"CO2 LEVELS:", + TextColor = Color.Black, + Font = largeFont + }); + co2LevelsLabel = new Label(0, 78 + offsetY, displayScreen.Width - marginX, largeFont.Height) + { + Text = $"0.0 PPM", + TextColor = Color.Black, + Font = largeFont, + HorizontalAlignment = HorizontalAlignment.Right, + }; + dataLayout.Controls.Add(co2LevelsLabel); + + dataLayout.Controls.Add(new Box(0, 90 + offsetY, displayScreen.Width, 32) + { + ForeColor = Color.Red, + IsFilled = true + }); - public void UpdateDisplay( - Voltage? BatteryVoltage, - Voltage? SolarVoltage, - Temperature? Temperature, - RelativeHumidity? Humidity, - Pressure? Pressure, - Concentration? Concentration, - GnssPositionInfo locationInfo) - { - displayScreen.BeginUpdate(); - - batteryVoltageLabel.Text = $"{BatteryVoltage?.Volts:N2} V"; - solarVoltageLabel.Text = $"{SolarVoltage?.Volts:N2} V"; - temperatureLabel.Text = $"{Temperature?.Celsius:N1} C"; - humidityLabel.Text = $"{Humidity?.Percent:N1} %"; - pressureLabel.Text = $"{Pressure?.StandardAtmosphere:N1} ATM"; - - if (Concentration != null) - { - co2LevelsLabel.Text = $"{Concentration?.PartsPerMillion:N1} PPM"; - } - - string lat = locationInfo == null - ? $"00 00' 0.00\"" - : $"" + - $"{locationInfo?.Position?.Latitude?.Degrees:N2} " + - $"{locationInfo?.Position?.Latitude?.Minutes:N2}'" + - $"{locationInfo?.Position?.Latitude?.Seconds:N2}\""; - latitudeLabel.Text = lat; - - string lon = locationInfo == null - ? $"00 00' 0.00\"" - : $"" + - $"{locationInfo?.Position?.Longitude?.Degrees:N2} " + - $"{locationInfo?.Position?.Longitude?.Minutes:N2}'" + - $"{locationInfo?.Position?.Longitude?.Seconds:N2}\""; - longitudeLabel.Text = lon; - - displayScreen.EndUpdate(); + dataLayout.Controls.Add(new Label(marginX, 94 + offsetY, displayScreen.Width, largeFont.Height) + { + Text = $"LATITUDE:", + TextColor = Color.White, + Font = largeFont + }); + latitudeLabel = new Label(0, 94 + offsetY, displayScreen.Width - marginX, largeFont.Height) + { + Text = $"00 00' 0.0\"", + TextColor = Color.White, + Font = largeFont, + HorizontalAlignment = HorizontalAlignment.Right, + }; + dataLayout.Controls.Add(latitudeLabel); + + dataLayout.Controls.Add(new Label(marginX, 109 + offsetY, displayScreen.Width, largeFont.Height) + { + Text = $"LONGITUDE:", + TextColor = Color.White, + Font = largeFont + }); + longitudeLabel = new Label(0, 109 + offsetY, displayScreen.Width - marginX, largeFont.Height) + { + Text = $"00 00' 0.0\"", + TextColor = Color.White, + Font = largeFont, + HorizontalAlignment = HorizontalAlignment.Right, + }; + dataLayout.Controls.Add(longitudeLabel); + + displayScreen.Controls.Add(dataLayout); + + displayScreen.EndUpdate(); + } + + public void UpdateDisplay( + Voltage? BatteryVoltage, + Voltage? SolarVoltage, + Temperature? Temperature, + RelativeHumidity? Humidity, + Pressure? Pressure, + Concentration? Concentration, + GnssPositionInfo? locationInfo) + { + displayScreen.BeginUpdate(); + + batteryVoltageLabel.Text = $"{BatteryVoltage?.Volts:N2} V"; + solarVoltageLabel.Text = $"{SolarVoltage?.Volts:N2} V"; + temperatureLabel.Text = $"{Temperature?.Celsius:N1} C"; + humidityLabel.Text = $"{Humidity?.Percent:N1} %"; + pressureLabel.Text = $"{Pressure?.StandardAtmosphere:N1} ATM"; + + if (Concentration != null) + { + co2LevelsLabel.Text = $"{Concentration?.PartsPerMillion:N1} PPM"; } + + string lat = locationInfo == null + ? $"00 00' 0.00\"" + : $"" + + $"{locationInfo?.Position?.Latitude?.Degrees:N2} " + + $"{locationInfo?.Position?.Latitude?.Minutes:N2}'" + + $"{locationInfo?.Position?.Latitude?.Seconds:N2}\""; + latitudeLabel.Text = lat; + + string lon = locationInfo == null + ? $"00 00' 0.00\"" + : $"" + + $"{locationInfo?.Position?.Longitude?.Degrees:N2} " + + $"{locationInfo?.Position?.Longitude?.Minutes:N2}'" + + $"{locationInfo?.Position?.Longitude?.Seconds:N2}\""; + longitudeLabel.Text = lon; + + displayScreen.EndUpdate(); } } \ No newline at end of file diff --git a/Source/GnssTracker_Demo/GnssTracker_Demo.csproj b/Source/GnssTracker_Demo/GnssTracker_Demo.csproj index 0fe1d8f..fde6ff8 100644 --- a/Source/GnssTracker_Demo/GnssTracker_Demo.csproj +++ b/Source/GnssTracker_Demo/GnssTracker_Demo.csproj @@ -13,7 +13,7 @@ - + diff --git a/Source/GnssTracker_Demo/MeadowApp.cs b/Source/GnssTracker_Demo/MeadowApp.cs index c90d00b..9b70b68 100644 --- a/Source/GnssTracker_Demo/MeadowApp.cs +++ b/Source/GnssTracker_Demo/MeadowApp.cs @@ -6,244 +6,244 @@ using System; using System.Threading.Tasks; -namespace GnssTracker_Demo -{ - public class MeadowApp : App - { - GnssPositionInfo lastGNSSPosition; - Voltage? solarVoltage = new Voltage(0); - Voltage? batteryVoltage = new Voltage(0); - DateTime lastGNSSPositionReportTime = DateTime.MinValue; - - protected DisplayController displayController { get; set; } - - protected IGnssTrackerHardware gnssTracker { get; set; } - - readonly TimeSpan GNSSPositionReportInterval = TimeSpan.FromSeconds(15); - - readonly TimeSpan sensorUpdateInterval = TimeSpan.FromSeconds(90); - - public override Task Initialize() - { - Resolver.Log.Info("Initialize hardware..."); - - gnssTracker = GnssTracker.Create(); +namespace GnssTracker_Demo; - if (gnssTracker.TemperatureSensor is { } temperatureSensor) - { - temperatureSensor.Updated += TemperatureSensorUpdated; - } - - if (gnssTracker.HumiditySensor is { } humiditySensor) - { - humiditySensor.Updated += HumiditySensorUpdated; - } - - if (gnssTracker.BarometricPressureSensor is { } barometer) - { - barometer.Updated += BarometerUpdated; - } - - if (gnssTracker.GasResistanceSensor is { } gasResistanceSensor) - { - gasResistanceSensor.Updated += GasResistanceSensorUpdated; - } - - if (gnssTracker.CO2ConcentrationSensor is { } cO2ConcentrationSensor) - { - cO2ConcentrationSensor.Updated += CO2ConcentrationSensorUpdated; - } - - if (gnssTracker.Gyroscope is { } gyroscope) - { - gyroscope.Updated += GyroscopeUpdated; - } +public class MeadowApp : App +{ + GnssPositionInfo lastGNSSPosition; + Voltage? solarVoltage = new Voltage(0); + Voltage? batteryVoltage = new Voltage(0); + DateTime lastGNSSPositionReportTime = DateTime.MinValue; - if (gnssTracker.Accelerometer is { } accelerometer) - { - accelerometer.Updated += AccelerometerUpdated; ; - } + protected DisplayController displayController { get; set; } - if (gnssTracker.BatteryVoltageInput is { } batteryvoltage) - { - batteryvoltage.Updated += BatteryVoltageUpdated; - } + protected IGnssTrackerHardware gnssTracker { get; set; } - if (gnssTracker.SolarVoltageInput is { } solarVoltage) - { - solarVoltage.Updated += SolarVoltageUpdated; - } + readonly TimeSpan GNSSPositionReportInterval = TimeSpan.FromMinutes(5); - if (gnssTracker.Gnss is { } gnss) - { - gnss.RmcReceived += GnssRmcReceived; - gnss.GllReceived += GnssGllReceived; - } + readonly TimeSpan sensorUpdateInterval = TimeSpan.FromMinutes(5); - if (gnssTracker.Display is { } display) - { - displayController = new DisplayController(display); - } + public override Task Initialize() + { + Resolver.Log.Info("Initialize hardware..."); - if (gnssTracker.OnboardRgbLed is { } onboardRgbLed) - { - onboardRgbLed.StartPulse(Color.Magenta); - } + gnssTracker = GnssTracker.Create(); - Resolver.Log.Info("Initialization complete"); + if (gnssTracker.TemperatureSensor is { } temperatureSensor) + { + temperatureSensor.Updated += TemperatureSensorUpdated; + } - return Task.CompletedTask; + if (gnssTracker.HumiditySensor is { } humiditySensor) + { + humiditySensor.Updated += HumiditySensorUpdated; } - private void TemperatureSensorUpdated(object sender, IChangeResult e) + if (gnssTracker.BarometricPressureSensor is { } barometer) { - Resolver.Log.Info($"TEMPERATURE: {e.New.Celsius:N1}C"); + barometer.Updated += BarometerUpdated; } - private void HumiditySensorUpdated(object sender, IChangeResult e) + if (gnssTracker.GasResistanceSensor is { } gasResistanceSensor) { - Resolver.Log.Info($"HUMIDITY: {e.New.Percent:N1}%"); + gasResistanceSensor.Updated += GasResistanceSensorUpdated; } - private void BarometerUpdated(object sender, IChangeResult e) + if (gnssTracker.CO2ConcentrationSensor is { } cO2ConcentrationSensor) { - Resolver.Log.Info($"PRESSURE: {e.New.Millibar:N1}mbar"); + cO2ConcentrationSensor.Updated += CO2ConcentrationSensorUpdated; } - private void GasResistanceSensorUpdated(object sender, IChangeResult e) + if (gnssTracker.Gyroscope is { } gyroscope) { - Resolver.Log.Info($"RESISTANCE: {e.New.Megaohms:N1}MΩ"); + gyroscope.Updated += GyroscopeUpdated; } - private void CO2ConcentrationSensorUpdated(object sender, IChangeResult e) + if (gnssTracker.Accelerometer is { } accelerometer) { - Resolver.Log.Info($"CO2 CONCENTRATION: {e.New.PartsPerMillion:N1}ppm"); + accelerometer.Updated += AccelerometerUpdated; ; } - private void GyroscopeUpdated(object sender, IChangeResult e) + if (gnssTracker.BatteryVoltageInput is { } batteryvoltage) { - Resolver.Log.Info($"GYROSCOPE: X:{e.New.X.DegreesPerSecond:N1}°/s, Y:{e.New.Y.DegreesPerSecond:N1}°/s, Z:{e.New.Z.DegreesPerSecond:N1}°/s"); + batteryvoltage.Updated += BatteryVoltageUpdated; } - private void AccelerometerUpdated(object sender, IChangeResult e) + if (gnssTracker.SolarVoltageInput is { } solarVoltage) { - Resolver.Log.Info($"ACCELEROMETER: X:{e.New.X.Gravity:N1}g, Y:{e.New.Y.Gravity:N1}g, Z:{e.New.Z.Gravity:N1}g"); + solarVoltage.Updated += SolarVoltageUpdated; } - private void BatteryVoltageUpdated(object sender, IChangeResult e) + if (gnssTracker.Gnss is { } gnss) { - // Note: Battery Voltage input has a voltage divider, check schematics to learn more - batteryVoltage = e.New * 1.60; - Resolver.Log.Info($"BATTERY VOLTAGE: {batteryVoltage:N2} volts"); + gnss.RmcReceived += GnssRmcReceived; + gnss.GllReceived += GnssGllReceived; } - private void SolarVoltageUpdated(object sender, IChangeResult e) + if (gnssTracker.Display is { } display) { - // Note: Solar Voltage input has a voltage divider, check schematics to learn more - solarVoltage = e.New * 1.40; - Resolver.Log.Info($"SOLAR VOLTAGE: {solarVoltage:N2} volts"); + displayController = new DisplayController(display); + } + if (gnssTracker.OnboardRgbLed is { } onboardRgbLed) + { + onboardRgbLed.StartPulse(Color.Magenta); } - private void GnssRmcReceived(object sender, GnssPositionInfo e) + Resolver.Log.Info("Initialization complete"); + + return Task.CompletedTask; + } + + private void TemperatureSensorUpdated(object sender, IChangeResult e) + { + Resolver.Log.Info($"TEMPERATURE: {e.New.Celsius:N1}C"); + } + + private void HumiditySensorUpdated(object sender, IChangeResult e) + { + Resolver.Log.Info($"HUMIDITY: {e.New.Percent:N1}%"); + } + + private void BarometerUpdated(object sender, IChangeResult e) + { + Resolver.Log.Info($"PRESSURE: {e.New.Millibar:N1}mbar"); + } + + private void GasResistanceSensorUpdated(object sender, IChangeResult e) + { + Resolver.Log.Info($"RESISTANCE: {e.New.Megaohms:N1}MΩ"); + } + + private void CO2ConcentrationSensorUpdated(object sender, IChangeResult e) + { + Resolver.Log.Info($"CO2 CONCENTRATION: {e.New.PartsPerMillion:N1}ppm"); + } + + private void GyroscopeUpdated(object sender, IChangeResult e) + { + Resolver.Log.Info($"GYROSCOPE: X:{e.New.X.DegreesPerSecond:N1}°/s, Y:{e.New.Y.DegreesPerSecond:N1}°/s, Z:{e.New.Z.DegreesPerSecond:N1}°/s"); + } + + private void AccelerometerUpdated(object sender, IChangeResult e) + { + Resolver.Log.Info($"ACCELEROMETER: X:{e.New.X.Gravity:N1}g, Y:{e.New.Y.Gravity:N1}g, Z:{e.New.Z.Gravity:N1}g"); + } + + private void BatteryVoltageUpdated(object sender, IChangeResult e) + { + // Note: Battery Voltage input has a voltage divider, check schematics to learn more + batteryVoltage = e.New * 1.60; + Resolver.Log.Info($"BATTERY VOLTAGE: {batteryVoltage:N2} volts"); + } + + private void SolarVoltageUpdated(object sender, IChangeResult e) + { + // Note: Solar Voltage input has a voltage divider, check schematics to learn more + solarVoltage = e.New * 1.40; + Resolver.Log.Info($"SOLAR VOLTAGE: {solarVoltage:N2} volts"); + + } + + private void GnssRmcReceived(object sender, GnssPositionInfo e) + { + if (e.Valid) { - if (e.Valid) - { - ReportGNSSPosition(e); - lastGNSSPosition = e; - } + ReportGNSSPosition(e); + lastGNSSPosition = e; } + } - private void GnssGllReceived(object sender, GnssPositionInfo e) + private void GnssGllReceived(object sender, GnssPositionInfo e) + { + if (e.Valid) { - if (e.Valid) - { - ReportGNSSPosition(e); - lastGNSSPosition = e; - } + ReportGNSSPosition(e); + lastGNSSPosition = e; } + } - private void ReportGNSSPosition(GnssPositionInfo e) + private void ReportGNSSPosition(GnssPositionInfo e) + { + if (e.Valid) { - if (e.Valid) + if (DateTime.UtcNow - lastGNSSPositionReportTime >= GNSSPositionReportInterval) { - if (DateTime.UtcNow - lastGNSSPositionReportTime >= GNSSPositionReportInterval) - { - Resolver.Log.Info($"GNSS POSITION: LAT: [{e.Position.Latitude}], LONG: [{e.Position.Longitude}]"); + Resolver.Log.Info($"GNSS POSITION: LAT: [{e.Position.Latitude}], LONG: [{e.Position.Longitude}]"); - lastGNSSPositionReportTime = DateTime.UtcNow; - } + lastGNSSPositionReportTime = DateTime.UtcNow; } } + } - public override async Task Run() - { - Resolver.Log.Info("Run..."); + public override async Task Run() + { + Resolver.Log.Info("Run..."); - if (gnssTracker.TemperatureSensor is { } temperatureSensor) - { - temperatureSensor.StartUpdating(sensorUpdateInterval); - } + if (gnssTracker.TemperatureSensor is { } temperatureSensor) + { + temperatureSensor.StartUpdating(sensorUpdateInterval); + } - if (gnssTracker.HumiditySensor is { } humiditySensor) - { - humiditySensor.StartUpdating(sensorUpdateInterval); - } + if (gnssTracker.HumiditySensor is { } humiditySensor) + { + humiditySensor.StartUpdating(sensorUpdateInterval); + } - if (gnssTracker.BarometricPressureSensor is { } barometer) - { - barometer.StartUpdating(sensorUpdateInterval); - } + if (gnssTracker.BarometricPressureSensor is { } barometer) + { + barometer.StartUpdating(sensorUpdateInterval); + } - if (gnssTracker.GasResistanceSensor is { } gasResistanceSensor) - { - gasResistanceSensor.StartUpdating(sensorUpdateInterval); - } + if (gnssTracker.GasResistanceSensor is { } gasResistanceSensor) + { + gasResistanceSensor.StartUpdating(sensorUpdateInterval); + } - if (gnssTracker.CO2ConcentrationSensor is { } cO2ConcentrationSensor) - { - cO2ConcentrationSensor.StartUpdating(sensorUpdateInterval); - } + if (gnssTracker.CO2ConcentrationSensor is { } cO2ConcentrationSensor) + { + cO2ConcentrationSensor.StartUpdating(sensorUpdateInterval); + } - if (gnssTracker.Gyroscope is { } gyroscope) - { - gyroscope.StartUpdating(sensorUpdateInterval); - } + if (gnssTracker.Gyroscope is { } gyroscope) + { + gyroscope.StartUpdating(sensorUpdateInterval); + } - if (gnssTracker.Accelerometer is { } accelerometer) - { - accelerometer.StartUpdating(sensorUpdateInterval); - } + if (gnssTracker.Accelerometer is { } accelerometer) + { + accelerometer.StartUpdating(sensorUpdateInterval); + } - if (gnssTracker.BatteryVoltageInput is { } batteryVoltageInput) - { - batteryVoltageInput.StartUpdating(sensorUpdateInterval); - } + if (gnssTracker.BatteryVoltageInput is { } batteryVoltageInput) + { + batteryVoltageInput.StartUpdating(sensorUpdateInterval); + } - if (gnssTracker.SolarVoltageInput is { } solarVoltageInput) - { - solarVoltageInput.StartUpdating(sensorUpdateInterval); - } + if (gnssTracker.SolarVoltageInput is { } solarVoltageInput) + { + solarVoltageInput.StartUpdating(sensorUpdateInterval); + } - if (gnssTracker.Gnss is { } gnss) - { - gnss.StartUpdating(); - } + if (gnssTracker.Gnss is { } gnss) + { + //TODO: This should be set with an interval, no? + gnss.StartUpdating(); + } - while (true) - { - Resolver.Log.Info("=================================================="); - - displayController.UpdateDisplay( - batteryVoltage, - solarVoltage, - gnssTracker.TemperatureSensor.Temperature, - gnssTracker.HumiditySensor.Humidity, - gnssTracker.BarometricPressureSensor.Pressure, - gnssTracker.CO2ConcentrationSensor?.CO2Concentration ?? null, - lastGNSSPosition); - await Task.Delay(sensorUpdateInterval); - } + while (true) + { + Resolver.Log.Info("=================================================="); + + displayController.UpdateDisplay( + batteryVoltage, + solarVoltage, + gnssTracker.TemperatureSensor.Temperature, + gnssTracker.HumiditySensor.Humidity, + gnssTracker.BarometricPressureSensor.Pressure, + gnssTracker.CO2ConcentrationSensor?.CO2Concentration ?? null, + lastGNSSPosition); + await Task.Delay(sensorUpdateInterval); } } } \ No newline at end of file diff --git a/Source/Meadow.GnssTracker.sln b/Source/Meadow.GnssTracker.sln index fda2c38..cd71ac8 100644 --- a/Source/Meadow.GnssTracker.sln +++ b/Source/Meadow.GnssTracker.sln @@ -7,10 +7,6 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "GnssTracker_Demo", "GnssTra EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "GnssTracker", "GnssTracker\GnssTracker.csproj", "{0A4FBC32-409E-4D72-AB1F-E79DD3B397FF}" EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "AdditionalSamples", "AdditionalSamples", "{ACC86F2A-3B1A-4E21-A156-0CE930148B91}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "GnssTracker_SQLite_Demo", "Additional Samples\GnssTracker_SQLite_Demo\GnssTracker_SQLite_Demo.csproj", "{0106A830-D574-4231-9537-44A564A67FB0}" -EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -25,18 +21,11 @@ Global {0A4FBC32-409E-4D72-AB1F-E79DD3B397FF}.Debug|Any CPU.Build.0 = Debug|Any CPU {0A4FBC32-409E-4D72-AB1F-E79DD3B397FF}.Release|Any CPU.ActiveCfg = Release|Any CPU {0A4FBC32-409E-4D72-AB1F-E79DD3B397FF}.Release|Any CPU.Build.0 = Release|Any CPU - {0106A830-D574-4231-9537-44A564A67FB0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {0106A830-D574-4231-9537-44A564A67FB0}.Debug|Any CPU.Build.0 = Debug|Any CPU - {0106A830-D574-4231-9537-44A564A67FB0}.Debug|Any CPU.Deploy.0 = Debug|Any CPU - {0106A830-D574-4231-9537-44A564A67FB0}.Release|Any CPU.ActiveCfg = Release|Any CPU - {0106A830-D574-4231-9537-44A564A67FB0}.Release|Any CPU.Build.0 = Release|Any CPU - {0106A830-D574-4231-9537-44A564A67FB0}.Release|Any CPU.Deploy.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection GlobalSection(NestedProjects) = preSolution - {0106A830-D574-4231-9537-44A564A67FB0} = {ACC86F2A-3B1A-4E21-A156-0CE930148B91} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {0F0B7DD0-BD16-4CB0-B369-5649BDD66664}