diff --git a/.github/workflows/meadow-samples-develop-ci.yml b/.github/workflows/meadow-samples-develop-ci.yml index 3da178c3..41be93c4 100644 --- a/.github/workflows/meadow-samples-develop-ci.yml +++ b/.github/workflows/meadow-samples-develop-ci.yml @@ -111,6 +111,13 @@ jobs: path: Meadow.ProjectLab ref: develop + - name: Checkout Meadow.GnssTracker + uses: actions/checkout@v3 + with: + repository: WildernessLabs/GNSS_Sensor_Tracker + path: GNSS_Sensor_Tracker + ref: develop + - name: Checkout Meadow.Samples uses: actions/checkout@v3 with: diff --git a/Design/wildernesslabs-gnss-tracker-bluetooth.png b/Design/wildernesslabs-gnss-tracker-bluetooth.png new file mode 100644 index 00000000..ba6f7c61 Binary files /dev/null and b/Design/wildernesslabs-gnss-tracker-bluetooth.png differ diff --git a/Design/wildernesslabs-gnss-tracker-getting-started.png b/Design/wildernesslabs-gnss-tracker-getting-started.png new file mode 100644 index 00000000..8d97c054 Binary files /dev/null and b/Design/wildernesslabs-gnss-tracker-getting-started.png differ diff --git a/Design/wildernesslabs-gnss-tracker-wifi.png b/Design/wildernesslabs-gnss-tracker-wifi.png new file mode 100644 index 00000000..205cc1ab Binary files /dev/null and b/Design/wildernesslabs-gnss-tracker-wifi.png differ diff --git a/Design/wildernesslabs-meadow-gnss-sensor-tracker.jpg b/Design/wildernesslabs-meadow-gnss-sensor-tracker.jpg new file mode 100644 index 00000000..6adb0bf0 Binary files /dev/null and b/Design/wildernesslabs-meadow-gnss-sensor-tracker.jpg differ diff --git a/README.md b/README.md index f7cff7e7..c0fedb09 100644 --- a/README.md +++ b/README.md @@ -19,8 +19,8 @@ Contents: * IoT Accelerators * [Project Lab](#project-lab) * [Juego](#juego) + * [GNSS Sensor Tracker](#gnss-sensor-tracker) * [Clima](https://github.com/WildernessLabs/Clima) - * [GNSS Sensor Tracker](https://github.com/WildernessLabs/GNSS_Sensor_Tracker) * [Support](#support) ## Meadow.Desktop @@ -149,6 +149,7 @@ Also check the pinout to make sure to connect the peripheral or sensor on the ri * [Battery Level](./Source/Meadow%20F7/OS/BatteryLevel/) * [Charge State](./Source/Meadow%20F7/OS/ChargeState/) * [Config Files](./Source/Meadow%20F7/OS/ConfigFiles/) + * [Crash Detection](./Source/Meadow%20F7/OS/CrashDetect/) * [File System Basics](./Source/Meadow%20F7/OS/FileSystem_Basics/) * [Json Basics](./Source/Meadow%20F7/OS/Json_Basics/) * [Logging](./Source/Meadow%20F7/OS/Logging) @@ -480,14 +481,14 @@ Meadow.Cloud provides secure, Over-the-Air (OtA) updates, which enable you to pu Source Code -
+
Send diagnostics logs from Meadow to Meadow.Cloud
- Source Code + Source Code -
+
Check your Meadow's Health Metrics on Meadow.Cloud
- Source Code + Source Code @@ -524,7 +525,7 @@ Meadow.Cloud provides secure, Over-the-Air (OtA) updates, which enable you to pu ## Azure -[![Meadow.SBCs.Samples](Design/wildernesslabs-meadow-azure-banner.jpg)](/Source/RaspberryPi/) +[![Meadow.SBCs.Samples](Design/wildernesslabs-meadow-azure-banner.jpg)](/Source/Azure/) Meadow project samples using Microsoft Azure. Click on any of these sample project to learn how they work. @@ -731,6 +732,45 @@ A collection of samples for the Wilderness Labs [Juego IoT Accelerator](https:// [Back to top](#meadowsamples) +## Gnss Sensor Tracker + +[![Gnss Sensor Tracker](Design/wildernesslabs-meadow-gnss-sensor-tracker.jpg)](/Source/GnssTracker/) + +Meadow project samples with a Gnss Sensor Tracker. Click on any of these sample project to learn how they work. + + + + + + + + + + + + +
+
+ Getting started with GNSS Tracker running a diagnostics app
+ Source Code +
+
+ Control a GNSS Tracker over Bluetooth with a MAUI app
+ Source Code +
+
+ Control a GNSS Tracker over WiFi with a MAUI app
+ Source Code +
+

                                

+
+

                                

+
+

                                

+
+ +[Back to top](#meadowsamples) + ## Support Having trouble building/running these projects? diff --git a/Source/Azure/ProjectLab_AzureIoTHub/MainController.cs b/Source/Azure/ProjectLab_AzureIoTHub/Controllers/MainController.cs similarity index 94% rename from Source/Azure/ProjectLab_AzureIoTHub/MainController.cs rename to Source/Azure/ProjectLab_AzureIoTHub/Controllers/MainController.cs index 17f6fe2c..95397cd0 100644 --- a/Source/Azure/ProjectLab_AzureIoTHub/MainController.cs +++ b/Source/Azure/ProjectLab_AzureIoTHub/Controllers/MainController.cs @@ -1,17 +1,16 @@ using Meadow; using Meadow.Hardware; using Meadow.Units; -using ProjectLab_AzureIoTHub.Controllers; using ProjectLab_AzureIoTHub.Hardware; using System; using System.Threading; using System.Threading.Tasks; -namespace ProjectLab_AzureIoTHub; +namespace ProjectLab_AzureIoTHub.Controllers; internal class MainController { - bool useMQTT = true; + bool useMQTT = false; int TIMEZONE_OFFSET = -8; // UTC-8 diff --git a/Source/Azure/ProjectLab_AzureIoTHub/MeadowApp.cs b/Source/Azure/ProjectLab_AzureIoTHub/MeadowApp.cs index d7e87a63..a4ad3477 100644 --- a/Source/Azure/ProjectLab_AzureIoTHub/MeadowApp.cs +++ b/Source/Azure/ProjectLab_AzureIoTHub/MeadowApp.cs @@ -1,6 +1,7 @@ using Meadow; using Meadow.Devices; using Meadow.Hardware; +using ProjectLab_AzureIoTHub.Controllers; using ProjectLab_AzureIoTHub.Hardware; using System.Threading.Tasks; diff --git a/Source/Azure/ProjectLab_AzureIoTHub/app.config.yaml b/Source/Azure/ProjectLab_AzureIoTHub/app.config.yaml index 2de306ea..cf45ba9e 100644 --- a/Source/Azure/ProjectLab_AzureIoTHub/app.config.yaml +++ b/Source/Azure/ProjectLab_AzureIoTHub/app.config.yaml @@ -2,13 +2,20 @@ # 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/ +# App lifecycle 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 + + # Control whether Meadow will restart when an unhandled app exception occurs. Combine with Lifecycle > AppFailureRestartDelaySeconds to control restart timing. + RestartOnAppFailure: false -# Adjust the level of logging detail. + # When app set to restart automatically on app failure, +# AppFailureRestartDelaySeconds: 15 + +# Logging configuration. Logging: - LogLevel: - Default: Trace \ No newline at end of file + + # Adjust the level of logging detail. + LogLevel: + + # Trace, Debug, Information, Warning, or Error + Default: Trace \ No newline at end of file diff --git a/Source/Azure/ProjectLab_AzureIoTHub/wifi.config.yaml b/Source/Azure/ProjectLab_AzureIoTHub/wifi.config.yaml index 71126001..5a80943a 100644 --- a/Source/Azure/ProjectLab_AzureIoTHub/wifi.config.yaml +++ b/Source/Azure/ProjectLab_AzureIoTHub/wifi.config.yaml @@ -2,7 +2,11 @@ # 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/WiFi_Configuration/ -# # To enable automatically connecting to a default network, make sure to enable the Coprocessor > AutomaticallyStartNetwork value in meadow.config.yaml. -#Credentials: - Ssid: YourSSID - Password: SSIDPassword \ No newline at end of file +# WiFi network credentials +Credentials: + + # WiFi SSID + Ssid: YourSSID + + # WiFi Password + Password: SSIDPassword \ No newline at end of file diff --git a/Source/GnssTracker/Connectivity/GnssTrackerConnectivity.Common/Bluetooth/BluetoothConstants.cs b/Source/GnssTracker/Connectivity/GnssTrackerConnectivity.Common/Bluetooth/BluetoothConstants.cs new file mode 100644 index 00000000..e6db1e85 --- /dev/null +++ b/Source/GnssTracker/Connectivity/GnssTrackerConnectivity.Common/Bluetooth/BluetoothConstants.cs @@ -0,0 +1,12 @@ +namespace GnssTrackerConnectivity.Common.Bluetooth; + +public static class CharacteristicsConstants +{ + public const string LED_PAIRING = "19933423-6f14-41c0-bb03-637b2e6ef6b0"; + public const string LED_TOGGLE = "2eb9edce-d7c4-4079-b3d3-5becfcf0c49d"; + public const string LED_BLINK = "7cb9817d-6754-46e7-be72-d5790eaf678b"; + public const string LED_PULSE = "23d3bd90-5966-4eff-9ac7-b6cafe9c182a"; + public const string ATMOSPHERIC_DATA = "8787e846-51e5-4d9b-87aa-eaf4a8f0056f"; + public const string MOTION_DATA = "29171115-4bbe-4ac1-a0b0-257b54bcc464"; + public const string VOLTAGE_DATA = "8468a412-99ae-457c-b2fd-2085ab9aac37"; +} \ No newline at end of file diff --git a/Source/GnssTracker/Connectivity/GnssTrackerConnectivity.Common/DTOs/AtmosphericReadingsDTO.cs b/Source/GnssTracker/Connectivity/GnssTrackerConnectivity.Common/DTOs/AtmosphericReadingsDTO.cs new file mode 100644 index 00000000..5b1c331c --- /dev/null +++ b/Source/GnssTracker/Connectivity/GnssTrackerConnectivity.Common/DTOs/AtmosphericReadingsDTO.cs @@ -0,0 +1,14 @@ +namespace GnssTrackerConnectivity.Common.Models; + +public class AtmosphericReadingsDTO +{ + public string? Temperature { get; set; } + + public string? Pressure { get; set; } + + public string? Humidity { get; set; } + + public string? GasResistance { get; set; } + + public string? Co2Concentration { get; set; } +} \ No newline at end of file diff --git a/Source/GnssTracker/Connectivity/GnssTrackerConnectivity.Common/DTOs/MotionReadingsDTO.cs b/Source/GnssTracker/Connectivity/GnssTrackerConnectivity.Common/DTOs/MotionReadingsDTO.cs new file mode 100644 index 00000000..b0a8de72 --- /dev/null +++ b/Source/GnssTracker/Connectivity/GnssTrackerConnectivity.Common/DTOs/MotionReadingsDTO.cs @@ -0,0 +1,12 @@ +namespace GnssTrackerConnectivity.Common.Models; + +public class MotionReadingsDTO +{ + public string Acceleration3dX { get; set; } + public string Acceleration3dY { get; set; } + public string Acceleration3dZ { get; set; } + + public string AngularVelocity3dX { get; set; } + public string AngularVelocity3dY { get; set; } + public string AngularVelocity3dZ { get; set; } +} \ No newline at end of file diff --git a/Source/GnssTracker/Connectivity/GnssTrackerConnectivity.Common/DTOs/VoltageReadingsDTO.cs b/Source/GnssTracker/Connectivity/GnssTrackerConnectivity.Common/DTOs/VoltageReadingsDTO.cs new file mode 100644 index 00000000..e9e60264 --- /dev/null +++ b/Source/GnssTracker/Connectivity/GnssTrackerConnectivity.Common/DTOs/VoltageReadingsDTO.cs @@ -0,0 +1,8 @@ +namespace GnssTrackerConnectivity.Common.Models; + +public class VoltageReadingsDTO +{ + public string? BatteryVoltage { get; set; } + + public string? SolarVoltage { get; set; } +} \ No newline at end of file diff --git a/Source/GnssTracker/Connectivity/GnssTrackerConnectivity.Common/GnssTrackerConnectivity.Common.projitems b/Source/GnssTracker/Connectivity/GnssTrackerConnectivity.Common/GnssTrackerConnectivity.Common.projitems new file mode 100644 index 00000000..8220bdd6 --- /dev/null +++ b/Source/GnssTracker/Connectivity/GnssTrackerConnectivity.Common/GnssTrackerConnectivity.Common.projitems @@ -0,0 +1,21 @@ + + + + $(MSBuildAllProjects);$(MSBuildThisFileFullPath) + true + b37359b9-3d61-42bd-b485-fc76275f0585 + + + GnssTrackerConnectivity.Common + + + + + + + + + + + + \ No newline at end of file diff --git a/Source/GnssTracker/Connectivity/GnssTrackerConnectivity.Common/GnssTrackerConnectivity.Common.shproj b/Source/GnssTracker/Connectivity/GnssTrackerConnectivity.Common/GnssTrackerConnectivity.Common.shproj new file mode 100644 index 00000000..18523622 --- /dev/null +++ b/Source/GnssTracker/Connectivity/GnssTrackerConnectivity.Common/GnssTrackerConnectivity.Common.shproj @@ -0,0 +1,13 @@ + + + + b37359b9-3d61-42bd-b485-fc76275f0585 + 14.0 + + + + + + + + diff --git a/Source/ProjectLab/ProjectLabWiFiBle/.vscode/launch.config b/Source/GnssTracker/Connectivity/GnssTrackerConnectivity/.vscode/launch.json similarity index 100% rename from Source/ProjectLab/ProjectLabWiFiBle/.vscode/launch.config rename to Source/GnssTracker/Connectivity/GnssTrackerConnectivity/.vscode/launch.json diff --git a/Source/GnssTracker/Connectivity/GnssTrackerConnectivity/ConnectionType.cs b/Source/GnssTracker/Connectivity/GnssTrackerConnectivity/ConnectionType.cs new file mode 100644 index 00000000..fe425877 --- /dev/null +++ b/Source/GnssTracker/Connectivity/GnssTrackerConnectivity/ConnectionType.cs @@ -0,0 +1,7 @@ +namespace GnssTrackerConnectivity; + +public enum ConnectionType +{ + WiFi, + Bluetooth +} \ No newline at end of file diff --git a/Source/GnssTracker/Connectivity/GnssTrackerConnectivity/Connectivity/BluetoothServer.cs b/Source/GnssTracker/Connectivity/GnssTrackerConnectivity/Connectivity/BluetoothServer.cs new file mode 100644 index 00000000..f02273b9 --- /dev/null +++ b/Source/GnssTracker/Connectivity/GnssTrackerConnectivity/Connectivity/BluetoothServer.cs @@ -0,0 +1,154 @@ +using GnssTrackerConnectivity.Common.Bluetooth; +using GnssTrackerConnectivity.Controllers; +using GnssTrackerConnectivity.Models; +using Meadow; +using Meadow.Gateways.Bluetooth; + +namespace GnssTrackerConnectivity.Connectivity; + +public class BluetoothServer +{ + private CommandController commandController; + + private ICharacteristic ledPairingCharacteristic; + private ICharacteristic ledToggleCharacteristic; + private ICharacteristic ledBlinkCharacteristic; + private ICharacteristic ledPulseCharacteristic; + private ICharacteristic atmosphericDataCharacteristic; + private ICharacteristic motionDataCharacteristic; + private ICharacteristic voltageDataCharacteristic; + + public BluetoothServer() + { + commandController = Resolver.Services.Get(); + + var sensorController = Resolver.Services.Get(); + sensorController.AtmosphericConditionsChanged += UpdateAtmosphericConditions; + sensorController.MotionConditionsChanged += UpdateMotionConditions; + sensorController.VoltageReadingsChanged += UpdateVoltageReadings; + } + + private void PairingCharacteristicValueSet(ICharacteristic c, object data) + { + commandController.FirePairing((bool)data); + } + + private void LedToggleCharacteristicValueSet(ICharacteristic c, object data) + { + commandController.FireLedToggle(); + } + + private void LedBlinkCharacteristicValueSet(ICharacteristic c, object data) + { + commandController.FireLedBlink(); + } + + private void LedPulseCharacteristicValueSet(ICharacteristic c, object data) + { + commandController.FireLedPulse(); + } + + public void UpdateAtmosphericConditions(object sender, AtmosphericConditions atmosphericConditions) + { + string stringValue = $"" + + $"{atmosphericConditions.Temperature.Celsius:N1};" + + $"{atmosphericConditions.Pressure.StandardAtmosphere:N1};" + + $"{atmosphericConditions.Humidity.Percent:N1};" + + $"{atmosphericConditions.GasResistance.Megaohms:N1};"; + Resolver.Log.Info($"{stringValue}"); + atmosphericDataCharacteristic.SetValue(stringValue); + } + + public void UpdateMotionConditions(object sender, MotionConditions motionConditions) + { + string stringValue = $"" + + $"{motionConditions.Acceleration3D.X.CentimetersPerSecondSquared:N1};" + + $"{motionConditions.Acceleration3D.Y.CentimetersPerSecondSquared:N1};" + + $"{motionConditions.Acceleration3D.Z.CentimetersPerSecondSquared:N1};" + + $"{motionConditions.AngularVelocity3D.X.DegreesPerSecond:N1};" + + $"{motionConditions.AngularVelocity3D.Y.DegreesPerSecond:N1};" + + $"{motionConditions.AngularVelocity3D.Z.DegreesPerSecond:N1};"; + Resolver.Log.Info($"{stringValue}"); + motionDataCharacteristic.SetValue(stringValue); + } + + private void UpdateVoltageReadings(object sender, VoltageReadings e) + { + string stringValue = $"" + + $"{e.BatteryVoltage:N1};" + + $"{e.SolarVoltage:N1};"; + Resolver.Log.Info($"{stringValue}"); + voltageDataCharacteristic.SetValue(stringValue); + } + + public Definition GetDefinition() + { + ledPairingCharacteristic = new CharacteristicBool( + name: nameof(CharacteristicsConstants.LED_PAIRING), + uuid: CharacteristicsConstants.LED_PAIRING, + permissions: CharacteristicPermission.Read | CharacteristicPermission.Write, + properties: CharacteristicProperty.Read | CharacteristicProperty.Write); + ledPairingCharacteristic.ValueSet += PairingCharacteristicValueSet; + + ledToggleCharacteristic = new CharacteristicBool( + name: nameof(CharacteristicsConstants.LED_TOGGLE), + uuid: CharacteristicsConstants.LED_TOGGLE, + permissions: CharacteristicPermission.Read | CharacteristicPermission.Write, + properties: CharacteristicProperty.Read | CharacteristicProperty.Write); + ledToggleCharacteristic.ValueSet += LedToggleCharacteristicValueSet; + + ledBlinkCharacteristic = new CharacteristicBool( + name: nameof(CharacteristicsConstants.LED_BLINK), + uuid: CharacteristicsConstants.LED_BLINK, + permissions: CharacteristicPermission.Read | CharacteristicPermission.Write, + properties: CharacteristicProperty.Read | CharacteristicProperty.Write); + ledBlinkCharacteristic.ValueSet += LedBlinkCharacteristicValueSet; + + ledPulseCharacteristic = new CharacteristicBool( + name: nameof(CharacteristicsConstants.LED_PULSE), + uuid: CharacteristicsConstants.LED_PULSE, + permissions: CharacteristicPermission.Read | CharacteristicPermission.Write, + properties: CharacteristicProperty.Read | CharacteristicProperty.Write); + ledPulseCharacteristic.ValueSet += LedPulseCharacteristicValueSet; + + atmosphericDataCharacteristic = new CharacteristicString( + name: nameof(CharacteristicsConstants.ATMOSPHERIC_DATA), + uuid: CharacteristicsConstants.ATMOSPHERIC_DATA, + maxLength: 32, + permissions: CharacteristicPermission.Read, + properties: CharacteristicProperty.Read); + + motionDataCharacteristic = new CharacteristicString( + name: nameof(CharacteristicsConstants.MOTION_DATA), + uuid: CharacteristicsConstants.MOTION_DATA, + maxLength: 32, + permissions: CharacteristicPermission.Read, + properties: CharacteristicProperty.Read); + + voltageDataCharacteristic = new CharacteristicString( + name: nameof(CharacteristicsConstants.VOLTAGE_DATA), + uuid: CharacteristicsConstants.VOLTAGE_DATA, + maxLength: 32, + permissions: CharacteristicPermission.Read, + properties: CharacteristicProperty.Read); + + ICharacteristic[] characteristics = + { + ledPairingCharacteristic, + ledToggleCharacteristic, + ledBlinkCharacteristic, + ledPulseCharacteristic, + atmosphericDataCharacteristic, + motionDataCharacteristic, + voltageDataCharacteristic + }; + + var service = new Service( + name: "Service", + uuid: 253, + characteristics + ); + + return new Definition("GnssTracker", service); + } +} \ No newline at end of file diff --git a/Source/GnssTracker/Connectivity/GnssTrackerConnectivity/Connectivity/MapleRequestHandler.cs b/Source/GnssTracker/Connectivity/GnssTrackerConnectivity/Connectivity/MapleRequestHandler.cs new file mode 100644 index 00000000..db312062 --- /dev/null +++ b/Source/GnssTracker/Connectivity/GnssTrackerConnectivity/Connectivity/MapleRequestHandler.cs @@ -0,0 +1,88 @@ +using GnssTrackerConnectivity.Common.Models; +using GnssTrackerConnectivity.Controllers; +using Meadow; +using Meadow.Foundation.Web.Maple; +using Meadow.Foundation.Web.Maple.Routing; + +namespace GnssTrackerConnectivity.Connectivity; + +public class MapleRequestHandler : RequestHandlerBase +{ + public MapleRequestHandler() { } + + [HttpPost("/toggle")] + public IActionResult Toggle() + { + var commandController = Resolver.Services.Get(); + commandController.FireLedToggle(); + return new OkResult(); + } + + [HttpPost("/blink")] + public IActionResult Blink() + { + var commandController = Resolver.Services.Get(); + commandController.FireLedBlink(); + return new OkResult(); + } + + [HttpPost("/pulse")] + public IActionResult Pulse() + { + var commandController = Resolver.Services.Get(); + commandController.FireLedPulse(); + return new OkResult(); + } + + [HttpGet("/getEnvironmentalData")] + public IActionResult GetEnvironmentalData() + { + var sensorController = Resolver.Services.Get(); + + var data = new AtmosphericReadingsDTO() + { + Temperature = $"{sensorController.AtmosphericConditions.Temperature.Celsius:N1}", + Humidity = $"{sensorController.AtmosphericConditions.Humidity.Percent:N1}", + Pressure = $"{sensorController.AtmosphericConditions.Pressure.StandardAtmosphere:N1}", + GasResistance = $"{sensorController.AtmosphericConditions.GasResistance.Megaohms:N1}", + Co2Concentration = $"{sensorController.AtmosphericConditions.Co2Concentration.PartsPerMillion:N1}" + }; + + Context.Response.ContentType = ContentTypes.Application_Json; + return new JsonResult(data); + } + + [HttpGet("/getMotionData")] + public IActionResult GetMotionData() + { + var sensorController = Resolver.Services.Get(); + + var data = new MotionReadingsDTO() + { + Acceleration3dX = $"{sensorController.MotionConditions.Acceleration3D.X.CentimetersPerSecondSquared:N2}", + Acceleration3dY = $"{sensorController.MotionConditions.Acceleration3D.Y.CentimetersPerSecondSquared:N2}", + Acceleration3dZ = $"{sensorController.MotionConditions.Acceleration3D.Z.CentimetersPerSecondSquared:N2}", + AngularVelocity3dX = $"{sensorController.MotionConditions.AngularVelocity3D.X.DegreesPerSecond:N2}", + AngularVelocity3dY = $"{sensorController.MotionConditions.AngularVelocity3D.Y.DegreesPerSecond:N2}", + AngularVelocity3dZ = $"{sensorController.MotionConditions.AngularVelocity3D.Z.DegreesPerSecond:N2}", + }; + + Context.Response.ContentType = ContentTypes.Application_Json; + return new JsonResult(data); + } + + [HttpGet("/getVoltageData")] + public IActionResult GetVoltageData() + { + var sensorController = Resolver.Services.Get(); + + var data = new VoltageReadingsDTO() + { + BatteryVoltage = $"{sensorController.VoltageReadings.BatteryVoltage:N1}", + SolarVoltage = $"{sensorController.VoltageReadings.SolarVoltage:N1}", + }; + + Context.Response.ContentType = ContentTypes.Application_Json; + return new JsonResult(data); + } +} \ No newline at end of file diff --git a/Source/ProjectLab/ProjectLabWiFiBle/ProjectLabWiFiBle/Controllers/CommandController.cs b/Source/GnssTracker/Connectivity/GnssTrackerConnectivity/Controllers/CommandController.cs similarity index 90% rename from Source/ProjectLab/ProjectLabWiFiBle/ProjectLabWiFiBle/Controllers/CommandController.cs rename to Source/GnssTracker/Connectivity/GnssTrackerConnectivity/Controllers/CommandController.cs index 31845466..744f2712 100644 --- a/Source/ProjectLab/ProjectLabWiFiBle/ProjectLabWiFiBle/Controllers/CommandController.cs +++ b/Source/GnssTracker/Connectivity/GnssTrackerConnectivity/Controllers/CommandController.cs @@ -1,7 +1,7 @@ using Meadow; using System; -namespace MeadowConnectedSample.Controllers; +namespace GnssTrackerConnectivity.Controllers; public class CommandController { @@ -34,4 +34,4 @@ public void FireLedPulse() { LedPulseValueSet?.Invoke(this, true); } -} +} \ No newline at end of file diff --git a/Source/GnssTracker/Connectivity/GnssTrackerConnectivity/Controllers/DisplayController.cs b/Source/GnssTracker/Connectivity/GnssTrackerConnectivity/Controllers/DisplayController.cs new file mode 100644 index 00000000..637722f8 --- /dev/null +++ b/Source/GnssTracker/Connectivity/GnssTrackerConnectivity/Controllers/DisplayController.cs @@ -0,0 +1,118 @@ +using Meadow; +using Meadow.Foundation.Graphics; +using Meadow.Foundation.Graphics.MicroLayout; +using Meadow.Peripherals.Displays; + +namespace GnssTrackerConnectivity.Controllers; + +public class DisplayController +{ + // Screen height is 122 but buffer is 128 + private readonly int OFFSET_Y = 6; + + private Image ble = Image.LoadFromResource("GnssTrackerConnectivity.Resources.img-ble.bmp"); + private Image wifi = Image.LoadFromResource("GnssTrackerConnectivity.Resources.img-wifi.bmp"); + + private readonly DisplayScreen displayScreen; + private readonly AbsoluteLayout dataLayout; + + private Picture connectivityIcon; + private Label Line1; + private Label Line2; + private Label Line3; + + public DisplayController(IPixelDisplay display) + { + displayScreen = new DisplayScreen(display, RotationType._90Degrees); + + displayScreen.BeginUpdate(); + + dataLayout = new AbsoluteLayout(displayScreen, 0, 0, displayScreen.Width, displayScreen.Height); + + displayScreen.Controls.Add(new Box( + 0, + 0 + OFFSET_Y, + displayScreen.Width, + displayScreen.Height - OFFSET_Y) + { + IsFilled = true, + ForeColor = Color.Red + }); + + displayScreen.Controls.Add(new Box( + 5, + 5 + OFFSET_Y, + displayScreen.Width - 10, + displayScreen.Height - 10 - OFFSET_Y) + { + IsFilled = true, + ForeColor = Color.White + }); + + connectivityIcon = new Picture( + 15, + 22 + OFFSET_Y, + 60, + 78, + wifi); + dataLayout.Controls.Add(connectivityIcon); + + Line1 = new Label( + 84, + 22 + OFFSET_Y, + 151, + 16) + { + Text = "-", + TextColor = Color.Black, + Font = new Font12x16() + }; + dataLayout.Controls.Add(Line1); + + Line2 = new Label( + 84, + 55 + OFFSET_Y, + 151, + 16) + { + Text = "-", + TextColor = Color.Black, + Font = new Font8x12() + }; + dataLayout.Controls.Add(Line2); + + Line3 = new Label( + 84, + 84 + OFFSET_Y, + 151, + 16) + { + Text = "-", + TextColor = Color.Black, + Font = new Font12x16() + }; + dataLayout.Controls.Add(Line3); + + displayScreen.Controls.Add(dataLayout); + } + + public void ShowBluetoothReady() + { + connectivityIcon.Image = ble; + Line1.Text = "Bluetooth"; + Line2.Text = "Discoverable"; + Line3.Text = "Ready"; + + displayScreen.EndUpdate(); + } + + public void ShowMapleReady(string ipAddress) + { + connectivityIcon.Image = wifi; + Line1.Text = "WiFi (Maple)"; + Line2.Text = $"{ipAddress}"; + Line3.Text = "Ready"; + + displayScreen.EndUpdate(); + } +} \ No newline at end of file diff --git a/Source/GnssTracker/Connectivity/GnssTrackerConnectivity/Controllers/LedController.cs b/Source/GnssTracker/Connectivity/GnssTrackerConnectivity/Controllers/LedController.cs new file mode 100644 index 00000000..51fe4933 --- /dev/null +++ b/Source/GnssTracker/Connectivity/GnssTrackerConnectivity/Controllers/LedController.cs @@ -0,0 +1,59 @@ +using Meadow; +using Meadow.Peripherals.Leds; +using System; +using System.Threading.Tasks; + +namespace GnssTrackerConnectivity.Controllers; + +public class LedController +{ + IRgbPwmLed rgbPwmLed; + bool isAnimating; + + public LedController(IRgbPwmLed rgbPwmLed) + { + this.rgbPwmLed = rgbPwmLed; + } + + public async Task SetColor(Color color) + { + await rgbPwmLed.StopAnimation(); + rgbPwmLed.SetColor(color); + } + + public async Task Toggle() + { + if (rgbPwmLed.IsOn || isAnimating) + { + await rgbPwmLed.StopAnimation(); + rgbPwmLed.IsOn = false; + isAnimating = false; + } + else + { + await rgbPwmLed.StopAnimation(); + rgbPwmLed.SetColor(GetRandomColor()); + rgbPwmLed.IsOn = true; + } + } + + public async Task StartBlink() + { + await rgbPwmLed.StopAnimation(); + await rgbPwmLed.StartBlink(GetRandomColor()); + isAnimating = true; + } + + public async Task StartPulse() + { + await rgbPwmLed.StopAnimation(); + await rgbPwmLed.StartPulse(GetRandomColor()); + isAnimating = true; + } + + protected Color GetRandomColor() + { + var random = new Random(); + return new Color(random.Next(256), random.Next(256), random.Next(256)); + } +} \ No newline at end of file diff --git a/Source/GnssTracker/Connectivity/GnssTrackerConnectivity/Controllers/MainController.cs b/Source/GnssTracker/Connectivity/GnssTrackerConnectivity/Controllers/MainController.cs new file mode 100644 index 00000000..23a16c33 --- /dev/null +++ b/Source/GnssTracker/Connectivity/GnssTrackerConnectivity/Controllers/MainController.cs @@ -0,0 +1,112 @@ +using GnssTrackerConnectivity.Connectivity; +using Meadow; +using Meadow.Devices; +using Meadow.Foundation.Web.Maple; +using Meadow.Gateways; +using Meadow.Hardware; +using System; +using System.Threading; +using System.Threading.Tasks; + +namespace GnssTrackerConnectivity.Controllers; + +public class MainController +{ + // Connect via Maple (WiFi) or Bluetooth? + private ConnectionType connectionType = ConnectionType.Bluetooth; + //private ConnectionType connectionType = ConnectionType.WiFi; + + private IGnssTrackerHardware hardware; + private IWiFiNetworkAdapter wifi; + private IBluetoothAdapter bluetooth; + + private SensorController sensorController; + private CommandController commandController; + private BluetoothServer bluetoothServer; + + private DisplayController displayController; + private LedController ledController; + + public MainController(IGnssTrackerHardware hardware, IWiFiNetworkAdapter wifi, IBluetoothAdapter bluetooth) + { + this.hardware = hardware; + this.wifi = wifi; + this.bluetooth = bluetooth; + } + + public async Task Initialize() + { + sensorController = new SensorController(hardware); + _ = sensorController.StartUpdating(TimeSpan.FromSeconds(15)); + + commandController = new CommandController(); + SubscribeLedCommands(); + + displayController = new DisplayController(hardware.Display); + + ledController = new LedController(hardware.OnboardRgbLed); + + if (connectionType == ConnectionType.WiFi) + { + await StartMapleServer(); + } + else + { + StartBluetoothServer(); + } + } + + private async Task StartMapleServer() + { + wifi.NetworkConnected += (s, e) => + { + var mapleServer = new MapleServer(s.IpAddress, 5417, advertise: true, logger: Resolver.Log); + mapleServer.Start(); + + displayController.ShowMapleReady(e.IpAddress.ToString()); + ledController.SetColor(Color.Green); + }; + + await wifi.Connect(Secrets.WIFI_NAME, Secrets.WIFI_PASSWORD); + } + + private void StartBluetoothServer() + { + bluetoothServer = new BluetoothServer(); + + commandController.PairingValueSet += (s, e) => + { + _ = ledController.StartBlink(); + + Thread.Sleep(300); + + ledController.SetColor(Color.Green); + }; + + var definition = bluetoothServer.GetDefinition(); + bluetooth.StartBluetoothServer(definition); + + displayController.ShowBluetoothReady(); + + ledController.SetColor(Color.Green); + } + + private void SubscribeLedCommands() + { + commandController.LedToggleValueSet += (s, e) => + { + Resolver.Log.Info("LedToggleValueSet"); + _ = ledController.Toggle(); + }; + commandController.LedBlinkValueSet += (s, e) => + { + Resolver.Log.Info("LedBlinkValueSet"); + _ = ledController.StartBlink(); + }; + commandController.LedPulseValueSet += (s, e) => + { + Resolver.Log.Info("LedPulseValueSet"); + _ = ledController.StartPulse(); + }; + } +} \ No newline at end of file diff --git a/Source/GnssTracker/Connectivity/GnssTrackerConnectivity/Controllers/SensorController.cs b/Source/GnssTracker/Connectivity/GnssTrackerConnectivity/Controllers/SensorController.cs new file mode 100644 index 00000000..cc3da1cd --- /dev/null +++ b/Source/GnssTracker/Connectivity/GnssTrackerConnectivity/Controllers/SensorController.cs @@ -0,0 +1,110 @@ +using GnssTrackerConnectivity.Models; +using Meadow; +using Meadow.Devices; +using Meadow.Hardware; +using Meadow.Peripherals.Sensors; +using Meadow.Peripherals.Sensors.Atmospheric; +using Meadow.Peripherals.Sensors.Environmental; +using Meadow.Peripherals.Sensors.Location.Gnss; +using Meadow.Peripherals.Sensors.Motion; +using System; +using System.Threading.Tasks; + +namespace GnssTrackerConnectivity.Controllers; + +public class SensorController +{ + private TimeSpan SAMPLE_INTERVAL = TimeSpan.FromSeconds(15); + + private ITemperatureSensor temperatureSensor; + private IBarometricPressureSensor pressureSensor; + private IHumiditySensor humiditySensor; + private IGasResistanceSensor gasResistanceSensor; + private ICO2ConcentrationSensor co2ConcentrationSensor; + private IGyroscope gyroscope; + private IAccelerometer accelerometer; + private IAnalogInputPort batteryVoltageInput; + private IAnalogInputPort solarVoltageInput; + private IGnssSensor gnssSensor; + + public AtmosphericConditions AtmosphericConditions { get; set; } + + public MotionConditions MotionConditions { get; set; } + + public VoltageReadings VoltageReadings { get; set; } + + public event EventHandler AtmosphericConditionsChanged = default!; + + public event EventHandler MotionConditionsChanged = default!; + + public event EventHandler VoltageReadingsChanged = default!; + + public SensorController(IGnssTrackerHardware hardware) + { + Resolver.Services.Add(this); + + temperatureSensor = hardware.TemperatureSensor; + pressureSensor = hardware.BarometricPressureSensor; + humiditySensor = hardware.HumiditySensor; + gasResistanceSensor = hardware.GasResistanceSensor; + co2ConcentrationSensor = hardware.CO2ConcentrationSensor; + gyroscope = hardware.Gyroscope; + accelerometer = hardware.Accelerometer; + batteryVoltageInput = hardware.BatteryVoltageInput; + solarVoltageInput = hardware.SolarVoltageInput; + gnssSensor = hardware.Gnss; + } + + public async Task StartUpdating(TimeSpan updateInterval) + { + while (true) + { + var temperature = await temperatureSensor.Read(); + var pressure = await pressureSensor.Read(); + var humidity = await humiditySensor.Read(); + var gasResistance = await gasResistanceSensor.Read(); + //var co2Concentration = await co2ConcentrationSensor.Read(); + var angularVelocityReading = await gyroscope.Read(); + var acceleration3DReading = await accelerometer.Read(); + var batteryVoltageReading = await batteryVoltageInput.Read(); + var solarVoltageReading = await solarVoltageInput.Read(); + + Resolver.Log.Info($"" + + $"Temperature: {temperature.Celsius:N1} | " + + $"Pressure: {pressure.StandardAtmosphere:N1} | " + + $"Humidity: {humidity.Percent:N1} | " + + $"Gas Resistance: {gasResistance.Megaohms:N1} | " + + //$"CO2 Concentration: {co2Concentration.PartsPerMillion:N1} | " + + $"AngularVelocity3D: ({angularVelocityReading.X.RevolutionsPerMinute:N1},{angularVelocityReading.Y.RevolutionsPerMinute:N1},{angularVelocityReading.Z.RevolutionsPerMinute:N1}) | " + + $"Acceleration3D: ({acceleration3DReading.X.CentimetersPerSecondSquared:N1}, {acceleration3DReading.Y.CentimetersPerSecondSquared:N1}, {acceleration3DReading.Z.CentimetersPerSecondSquared:N1}) | " + + $"Battery Voltage: {batteryVoltageReading.Volts:N1} | " + + $"Solar Voltage: {solarVoltageReading.Volts:N1} "); + + AtmosphericConditions = new AtmosphericConditions() + { + Temperature = temperature, + Pressure = pressure, + Humidity = humidity, + GasResistance = gasResistance, + //Co2Concentration = co2Concentration + }; + AtmosphericConditionsChanged?.Invoke(this, AtmosphericConditions); + + MotionConditions = new MotionConditions() + { + Acceleration3D = acceleration3DReading, + AngularVelocity3D = angularVelocityReading + }; + MotionConditionsChanged?.Invoke(this, MotionConditions); + + VoltageReadings = new VoltageReadings() + { + BatteryVoltage = batteryVoltageReading, + SolarVoltage = solarVoltageReading + }; + VoltageReadingsChanged?.Invoke(this, VoltageReadings); + + await Task.Delay(updateInterval); + } + } +} \ No newline at end of file diff --git a/Source/GnssTracker/Connectivity/GnssTrackerConnectivity/GnssTrackerConnectivity.csproj b/Source/GnssTracker/Connectivity/GnssTrackerConnectivity/GnssTrackerConnectivity.csproj new file mode 100644 index 00000000..3b850b1b --- /dev/null +++ b/Source/GnssTracker/Connectivity/GnssTrackerConnectivity/GnssTrackerConnectivity.csproj @@ -0,0 +1,28 @@ + + + netstandard2.1 + true + Library + App + 10.0 + + + + + + + + + + + + + + + + + Always + + + + \ No newline at end of file diff --git a/Source/GnssTracker/Connectivity/GnssTrackerConnectivity/MeadowApp.cs b/Source/GnssTracker/Connectivity/GnssTrackerConnectivity/MeadowApp.cs new file mode 100644 index 00000000..8c4da4d4 --- /dev/null +++ b/Source/GnssTracker/Connectivity/GnssTrackerConnectivity/MeadowApp.cs @@ -0,0 +1,24 @@ +using GnssTrackerConnectivity.Controllers; +using Meadow; +using Meadow.Devices; +using Meadow.Hardware; +using System.Threading.Tasks; + +namespace GnssTrackerConnectivity; + +public class MeadowApp : App +{ + public override async Task Initialize() + { + Resolver.Log.Info("Initialize..."); + + var gnssTracker = GnssTracker.Create(); + Resolver.Log.Info($"Running on GnssTracker Hardware"); + + var wifi = Device.NetworkAdapters.Primary(); + var ble = Device.BluetoothAdapter; + + var mainController = new MainController(gnssTracker, wifi, ble); + await mainController.Initialize(); + } +} \ No newline at end of file diff --git a/Source/GnssTracker/Connectivity/GnssTrackerConnectivity/Models/AtmosphericConditions.cs b/Source/GnssTracker/Connectivity/GnssTrackerConnectivity/Models/AtmosphericConditions.cs new file mode 100644 index 00000000..ba6309c5 --- /dev/null +++ b/Source/GnssTracker/Connectivity/GnssTrackerConnectivity/Models/AtmosphericConditions.cs @@ -0,0 +1,16 @@ +using Meadow.Units; + +namespace GnssTrackerConnectivity.Models; + +public class AtmosphericConditions +{ + public Temperature Temperature { get; set; } + + public Pressure Pressure { get; set; } + + public RelativeHumidity Humidity { get; set; } + + public Resistance GasResistance { get; set; } + + public Concentration Co2Concentration { get; set; } +} \ No newline at end of file diff --git a/Source/GnssTracker/Connectivity/GnssTrackerConnectivity/Models/GnssConditions.cs b/Source/GnssTracker/Connectivity/GnssTrackerConnectivity/Models/GnssConditions.cs new file mode 100644 index 00000000..c139461f --- /dev/null +++ b/Source/GnssTracker/Connectivity/GnssTrackerConnectivity/Models/GnssConditions.cs @@ -0,0 +1,10 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace GnssTrackerConnectivity.Models +{ + internal class GnssConditions + { + } +} diff --git a/Source/GnssTracker/Connectivity/GnssTrackerConnectivity/Models/MotionConditions.cs b/Source/GnssTracker/Connectivity/GnssTrackerConnectivity/Models/MotionConditions.cs new file mode 100644 index 00000000..eebaa949 --- /dev/null +++ b/Source/GnssTracker/Connectivity/GnssTrackerConnectivity/Models/MotionConditions.cs @@ -0,0 +1,10 @@ +using Meadow.Units; + +namespace GnssTrackerConnectivity.Models; + +public class MotionConditions +{ + public Acceleration3D Acceleration3D { get; set; } + + public AngularVelocity3D AngularVelocity3D { get; set; } +} \ No newline at end of file diff --git a/Source/GnssTracker/Connectivity/GnssTrackerConnectivity/Models/VoltageReadings.cs b/Source/GnssTracker/Connectivity/GnssTrackerConnectivity/Models/VoltageReadings.cs new file mode 100644 index 00000000..faf2dabe --- /dev/null +++ b/Source/GnssTracker/Connectivity/GnssTrackerConnectivity/Models/VoltageReadings.cs @@ -0,0 +1,10 @@ +using Meadow.Units; + +namespace GnssTrackerConnectivity.Models; + +public class VoltageReadings +{ + public Voltage BatteryVoltage { get; set; } + + public Voltage SolarVoltage { get; set; } +} \ No newline at end of file diff --git a/Source/GnssTracker/Connectivity/GnssTrackerConnectivity/Resources/img-ble.bmp b/Source/GnssTracker/Connectivity/GnssTrackerConnectivity/Resources/img-ble.bmp new file mode 100644 index 00000000..935962cf Binary files /dev/null and b/Source/GnssTracker/Connectivity/GnssTrackerConnectivity/Resources/img-ble.bmp differ diff --git a/Source/GnssTracker/Connectivity/GnssTrackerConnectivity/Resources/img-wifi.bmp b/Source/GnssTracker/Connectivity/GnssTrackerConnectivity/Resources/img-wifi.bmp new file mode 100644 index 00000000..68a0e00c Binary files /dev/null and b/Source/GnssTracker/Connectivity/GnssTrackerConnectivity/Resources/img-wifi.bmp differ diff --git a/Source/ProjectLab/ProjectLabWiFiBle/ProjectLabWiFiBle/Secrets.cs b/Source/GnssTracker/Connectivity/GnssTrackerConnectivity/Secrets.cs similarity index 56% rename from Source/ProjectLab/ProjectLabWiFiBle/ProjectLabWiFiBle/Secrets.cs rename to Source/GnssTracker/Connectivity/GnssTrackerConnectivity/Secrets.cs index 23253814..ee5559f7 100644 --- a/Source/ProjectLab/ProjectLabWiFiBle/ProjectLabWiFiBle/Secrets.cs +++ b/Source/GnssTracker/Connectivity/GnssTrackerConnectivity/Secrets.cs @@ -1,14 +1,14 @@ -namespace MeadowConnectedSample; +namespace GnssTrackerConnectivity; public class Secrets { /// /// Name of the WiFi network to use. /// - public const string WIFI_NAME = "WIFI_NAME"; + public const string WIFI_NAME = "YourSSID"; /// /// Password for the WiFi network names in WIFI_NAME. /// - public const string WIFI_PASSWORD = "WIFI_PASSWORD"; + public const string WIFI_PASSWORD = "SSIDPassword"; } \ No newline at end of file diff --git a/Source/GnssTracker/Connectivity/GnssTrackerConnectivity/app.config.yaml b/Source/GnssTracker/Connectivity/GnssTrackerConnectivity/app.config.yaml new file mode 100644 index 00000000..e208dbf7 --- /dev/null +++ b/Source/GnssTracker/Connectivity/GnssTrackerConnectivity/app.config.yaml @@ -0,0 +1,36 @@ +# 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/ + +# App lifecycle 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 + +# Logging configuration. +Logging: + + # Adjust the level of logging detail. + LogLevel: + + # Trace, Debug, Information, Warning, or Error + Default: Information + +# Meadow.Cloud configuration. +MeadowCloud: + + # Enable Logging, Events, Command + Control +# Enabled: false + + # Enable Over-the-air Updates +# EnableUpdates: false + + # Enable Health Metrics +# EnableHealthMetrics: false + + # How often to send metrics to Meadow.Cloud +# HealthMetricsIntervalMinutes: 60 \ No newline at end of file diff --git a/Source/GnssTracker/Connectivity/MobileGnssTrackerConnectivity/App.xaml b/Source/GnssTracker/Connectivity/MobileGnssTrackerConnectivity/App.xaml new file mode 100644 index 00000000..57c1c550 --- /dev/null +++ b/Source/GnssTracker/Connectivity/MobileGnssTrackerConnectivity/App.xaml @@ -0,0 +1,14 @@ + + + + + + + + + + + diff --git a/Source/GnssTracker/Connectivity/MobileGnssTrackerConnectivity/App.xaml.cs b/Source/GnssTracker/Connectivity/MobileGnssTrackerConnectivity/App.xaml.cs new file mode 100644 index 00000000..b7012705 --- /dev/null +++ b/Source/GnssTracker/Connectivity/MobileGnssTrackerConnectivity/App.xaml.cs @@ -0,0 +1,12 @@ +namespace MobileGnssTrackerConnectivity +{ + public partial class App : Application + { + public App() + { + InitializeComponent(); + + MainPage = new AppShell(); + } + } +} \ No newline at end of file diff --git a/Source/GnssTracker/Connectivity/MobileGnssTrackerConnectivity/AppShell.xaml b/Source/GnssTracker/Connectivity/MobileGnssTrackerConnectivity/AppShell.xaml new file mode 100644 index 00000000..a24701c7 --- /dev/null +++ b/Source/GnssTracker/Connectivity/MobileGnssTrackerConnectivity/AppShell.xaml @@ -0,0 +1,14 @@ + + + + + + diff --git a/Source/GnssTracker/Connectivity/MobileGnssTrackerConnectivity/AppShell.xaml.cs b/Source/GnssTracker/Connectivity/MobileGnssTrackerConnectivity/AppShell.xaml.cs new file mode 100644 index 00000000..256f082f --- /dev/null +++ b/Source/GnssTracker/Connectivity/MobileGnssTrackerConnectivity/AppShell.xaml.cs @@ -0,0 +1,9 @@ +namespace MobileGnssTrackerConnectivity; + +public partial class AppShell : Shell +{ + public AppShell() + { + InitializeComponent(); + } +} diff --git a/Source/GnssTracker/Connectivity/MobileGnssTrackerConnectivity/Converter/InverseBoolConverter.cs b/Source/GnssTracker/Connectivity/MobileGnssTrackerConnectivity/Converter/InverseBoolConverter.cs new file mode 100644 index 00000000..6cd10824 --- /dev/null +++ b/Source/GnssTracker/Connectivity/MobileGnssTrackerConnectivity/Converter/InverseBoolConverter.cs @@ -0,0 +1,17 @@ +using System.Globalization; + +namespace MobileGnssTrackerConnectivity.Converter +{ + public class InverseBoolConverter + { + public object Convert(object value, Type targetType, object parameter, CultureInfo culture) + { + return !(bool)value; + } + + public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) + { + return !(bool)value; + } + } +} \ No newline at end of file diff --git a/Source/GnssTracker/Connectivity/MobileGnssTrackerConnectivity/MauiProgram.cs b/Source/GnssTracker/Connectivity/MobileGnssTrackerConnectivity/MauiProgram.cs new file mode 100644 index 00000000..18ec5d40 --- /dev/null +++ b/Source/GnssTracker/Connectivity/MobileGnssTrackerConnectivity/MauiProgram.cs @@ -0,0 +1,18 @@ +namespace MobileGnssTrackerConnectivity; + +public static class MauiProgram +{ + public static MauiApp CreateMauiApp() + { + var builder = MauiApp.CreateBuilder(); + builder + .UseMauiApp() + .ConfigureFonts(fonts => + { + fonts.AddFont("OpenSans-Regular.ttf", "OpenSansRegular"); + fonts.AddFont("OpenSans-Semibold.ttf", "OpenSansSemibold"); + }); + + return builder.Build(); + } +} diff --git a/Source/GnssTracker/Connectivity/MobileGnssTrackerConnectivity/MobileGnssTrackerConnectivity.csproj b/Source/GnssTracker/Connectivity/MobileGnssTrackerConnectivity/MobileGnssTrackerConnectivity.csproj new file mode 100644 index 00000000..627bdb65 --- /dev/null +++ b/Source/GnssTracker/Connectivity/MobileGnssTrackerConnectivity/MobileGnssTrackerConnectivity.csproj @@ -0,0 +1,59 @@ + + + net8.0-android + + + Exe + MobileGnssTrackerConnectivity + true + true + enable + + + GnssTracker + + + com.companyname.MobileGnssTrackerConnectivity + 2750A062-72A3-4E67-A82F-AAC0A348C7B4 + + + 1.0 + 1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Source/GnssTracker/Connectivity/MobileGnssTrackerConnectivity/MobileGnssTrackerConnectivity.sln b/Source/GnssTracker/Connectivity/MobileGnssTrackerConnectivity/MobileGnssTrackerConnectivity.sln new file mode 100644 index 00000000..8d15ad91 --- /dev/null +++ b/Source/GnssTracker/Connectivity/MobileGnssTrackerConnectivity/MobileGnssTrackerConnectivity.sln @@ -0,0 +1,27 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.5.002.0 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MobileGnssTrackerConnectivity", "MobileGnssTrackerConnectivity.csproj", "{4C49DDDB-583D-4A7D-8BB1-9C2E935CFCB0}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {4C49DDDB-583D-4A7D-8BB1-9C2E935CFCB0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {4C49DDDB-583D-4A7D-8BB1-9C2E935CFCB0}.Debug|Any CPU.Build.0 = Debug|Any CPU + {4C49DDDB-583D-4A7D-8BB1-9C2E935CFCB0}.Debug|Any CPU.Deploy.0 = Debug|Any CPU + {4C49DDDB-583D-4A7D-8BB1-9C2E935CFCB0}.Release|Any CPU.ActiveCfg = Release|Any CPU + {4C49DDDB-583D-4A7D-8BB1-9C2E935CFCB0}.Release|Any CPU.Build.0 = Release|Any CPU + {4C49DDDB-583D-4A7D-8BB1-9C2E935CFCB0}.Release|Any CPU.Deploy.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {CA026A2F-B423-420E-A260-A03C6DB53413} + EndGlobalSection +EndGlobal diff --git a/Source/ProjectLab/ProjectLabWiFiBle/MobileProjectLabWiFiBle/Platforms/Android/AndroidManifest.xml b/Source/GnssTracker/Connectivity/MobileGnssTrackerConnectivity/Platforms/Android/AndroidManifest.xml similarity index 100% rename from Source/ProjectLab/ProjectLabWiFiBle/MobileProjectLabWiFiBle/Platforms/Android/AndroidManifest.xml rename to Source/GnssTracker/Connectivity/MobileGnssTrackerConnectivity/Platforms/Android/AndroidManifest.xml diff --git a/Source/GnssTracker/Connectivity/MobileGnssTrackerConnectivity/Platforms/Android/MainActivity.cs b/Source/GnssTracker/Connectivity/MobileGnssTrackerConnectivity/Platforms/Android/MainActivity.cs new file mode 100644 index 00000000..bf781653 --- /dev/null +++ b/Source/GnssTracker/Connectivity/MobileGnssTrackerConnectivity/Platforms/Android/MainActivity.cs @@ -0,0 +1,14 @@ +using Android.App; +using Android.Content.PM; + +namespace MobileGnssTrackerConnectivity +{ + [Activity(Theme = "@style/Maui.SplashTheme", MainLauncher = true, + ConfigurationChanges = ConfigChanges.ScreenSize | ConfigChanges.Orientation | + ConfigChanges.UiMode | ConfigChanges.ScreenLayout | ConfigChanges.SmallestScreenSize | + ConfigChanges.Density)] + public class MainActivity : MauiAppCompatActivity + { + + } +} \ No newline at end of file diff --git a/Source/GnssTracker/Connectivity/MobileGnssTrackerConnectivity/Platforms/Android/MainApplication.cs b/Source/GnssTracker/Connectivity/MobileGnssTrackerConnectivity/Platforms/Android/MainApplication.cs new file mode 100644 index 00000000..b2d0eeef --- /dev/null +++ b/Source/GnssTracker/Connectivity/MobileGnssTrackerConnectivity/Platforms/Android/MainApplication.cs @@ -0,0 +1,15 @@ +using Android.App; +using Android.Runtime; + +namespace MobileGnssTrackerConnectivity; + +[Application] +public class MainApplication : MauiApplication +{ + public MainApplication(IntPtr handle, JniHandleOwnership ownership) + : base(handle, ownership) + { + } + + protected override MauiApp CreateMauiApp() => MauiProgram.CreateMauiApp(); +} diff --git a/Source/ProjectLab/ProjectLabWiFiBle/MobileProjectLabWiFiBle/Platforms/Android/Resources/values/colors.xml b/Source/GnssTracker/Connectivity/MobileGnssTrackerConnectivity/Platforms/Android/Resources/values/colors.xml similarity index 100% rename from Source/ProjectLab/ProjectLabWiFiBle/MobileProjectLabWiFiBle/Platforms/Android/Resources/values/colors.xml rename to Source/GnssTracker/Connectivity/MobileGnssTrackerConnectivity/Platforms/Android/Resources/values/colors.xml diff --git a/Source/ProjectLab/ProjectLabWiFiBle/MobileProjectLabWiFiBle/Platforms/Android/Resources/xml/network_security_config.xml b/Source/GnssTracker/Connectivity/MobileGnssTrackerConnectivity/Platforms/Android/Resources/xml/network_security_config.xml similarity index 100% rename from Source/ProjectLab/ProjectLabWiFiBle/MobileProjectLabWiFiBle/Platforms/Android/Resources/xml/network_security_config.xml rename to Source/GnssTracker/Connectivity/MobileGnssTrackerConnectivity/Platforms/Android/Resources/xml/network_security_config.xml diff --git a/Source/ProjectLab/ProjectLabWiFiBle/MobileProjectLabWiFiBle/Properties/launchSettings.json b/Source/GnssTracker/Connectivity/MobileGnssTrackerConnectivity/Properties/launchSettings.json similarity index 100% rename from Source/ProjectLab/ProjectLabWiFiBle/MobileProjectLabWiFiBle/Properties/launchSettings.json rename to Source/GnssTracker/Connectivity/MobileGnssTrackerConnectivity/Properties/launchSettings.json diff --git a/Source/ProjectLab/ProjectLabWiFiBle/MobileProjectLabWiFiBle/Resources/AppIcon/appicon.svg b/Source/GnssTracker/Connectivity/MobileGnssTrackerConnectivity/Resources/AppIcon/appicon.svg similarity index 100% rename from Source/ProjectLab/ProjectLabWiFiBle/MobileProjectLabWiFiBle/Resources/AppIcon/appicon.svg rename to Source/GnssTracker/Connectivity/MobileGnssTrackerConnectivity/Resources/AppIcon/appicon.svg diff --git a/Source/ProjectLab/ProjectLabWiFiBle/MobileProjectLabWiFiBle/Resources/AppIcon/appiconfg.svg b/Source/GnssTracker/Connectivity/MobileGnssTrackerConnectivity/Resources/AppIcon/appiconfg.svg similarity index 100% rename from Source/ProjectLab/ProjectLabWiFiBle/MobileProjectLabWiFiBle/Resources/AppIcon/appiconfg.svg rename to Source/GnssTracker/Connectivity/MobileGnssTrackerConnectivity/Resources/AppIcon/appiconfg.svg diff --git a/Source/ProjectLab/ProjectLabWiFiBle/MobileProjectLabWiFiBle/Resources/Fonts/OpenSans-Regular.ttf b/Source/GnssTracker/Connectivity/MobileGnssTrackerConnectivity/Resources/Fonts/OpenSans-Regular.ttf similarity index 100% rename from Source/ProjectLab/ProjectLabWiFiBle/MobileProjectLabWiFiBle/Resources/Fonts/OpenSans-Regular.ttf rename to Source/GnssTracker/Connectivity/MobileGnssTrackerConnectivity/Resources/Fonts/OpenSans-Regular.ttf diff --git a/Source/ProjectLab/ProjectLabWiFiBle/MobileProjectLabWiFiBle/Resources/Fonts/OpenSans-Semibold.ttf b/Source/GnssTracker/Connectivity/MobileGnssTrackerConnectivity/Resources/Fonts/OpenSans-Semibold.ttf similarity index 100% rename from Source/ProjectLab/ProjectLabWiFiBle/MobileProjectLabWiFiBle/Resources/Fonts/OpenSans-Semibold.ttf rename to Source/GnssTracker/Connectivity/MobileGnssTrackerConnectivity/Resources/Fonts/OpenSans-Semibold.ttf diff --git a/Source/ProjectLab/ProjectLabWiFiBle/MobileProjectLabWiFiBle/Resources/Images/img_ble_pair.svg b/Source/GnssTracker/Connectivity/MobileGnssTrackerConnectivity/Resources/Images/img_ble_pair.svg similarity index 100% rename from Source/ProjectLab/ProjectLabWiFiBle/MobileProjectLabWiFiBle/Resources/Images/img_ble_pair.svg rename to Source/GnssTracker/Connectivity/MobileGnssTrackerConnectivity/Resources/Images/img_ble_pair.svg diff --git a/Source/ProjectLab/ProjectLabWiFiBle/MobileProjectLabWiFiBle/Resources/Images/img_ble_paired.svg b/Source/GnssTracker/Connectivity/MobileGnssTrackerConnectivity/Resources/Images/img_ble_paired.svg similarity index 100% rename from Source/ProjectLab/ProjectLabWiFiBle/MobileProjectLabWiFiBle/Resources/Images/img_ble_paired.svg rename to Source/GnssTracker/Connectivity/MobileGnssTrackerConnectivity/Resources/Images/img_ble_paired.svg diff --git a/Source/GnssTracker/Connectivity/MobileGnssTrackerConnectivity/Resources/Images/img_project_lab.png b/Source/GnssTracker/Connectivity/MobileGnssTrackerConnectivity/Resources/Images/img_project_lab.png new file mode 100644 index 00000000..bc99a993 Binary files /dev/null and b/Source/GnssTracker/Connectivity/MobileGnssTrackerConnectivity/Resources/Images/img_project_lab.png differ diff --git a/Source/ProjectLab/ProjectLabWiFiBle/MobileProjectLabWiFiBle/Resources/Images/img_search.svg b/Source/GnssTracker/Connectivity/MobileGnssTrackerConnectivity/Resources/Images/img_search.svg similarity index 100% rename from Source/ProjectLab/ProjectLabWiFiBle/MobileProjectLabWiFiBle/Resources/Images/img_search.svg rename to Source/GnssTracker/Connectivity/MobileGnssTrackerConnectivity/Resources/Images/img_search.svg diff --git a/Source/ProjectLab/ProjectLabWiFiBle/MobileProjectLabWiFiBle/Resources/Raw/AboutAssets.txt b/Source/GnssTracker/Connectivity/MobileGnssTrackerConnectivity/Resources/Raw/AboutAssets.txt similarity index 100% rename from Source/ProjectLab/ProjectLabWiFiBle/MobileProjectLabWiFiBle/Resources/Raw/AboutAssets.txt rename to Source/GnssTracker/Connectivity/MobileGnssTrackerConnectivity/Resources/Raw/AboutAssets.txt diff --git a/Source/ProjectLab/ProjectLabWiFiBle/MobileProjectLabWiFiBle/Resources/Splash/splash.svg b/Source/GnssTracker/Connectivity/MobileGnssTrackerConnectivity/Resources/Splash/splash.svg similarity index 100% rename from Source/ProjectLab/ProjectLabWiFiBle/MobileProjectLabWiFiBle/Resources/Splash/splash.svg rename to Source/GnssTracker/Connectivity/MobileGnssTrackerConnectivity/Resources/Splash/splash.svg diff --git a/Source/ProjectLab/ProjectLabWiFiBle/MobileProjectLabWiFiBle/Resources/Styles/Colors.xaml b/Source/GnssTracker/Connectivity/MobileGnssTrackerConnectivity/Resources/Styles/Colors.xaml similarity index 100% rename from Source/ProjectLab/ProjectLabWiFiBle/MobileProjectLabWiFiBle/Resources/Styles/Colors.xaml rename to Source/GnssTracker/Connectivity/MobileGnssTrackerConnectivity/Resources/Styles/Colors.xaml diff --git a/Source/ProjectLab/ProjectLabWiFiBle/MobileProjectLabWiFiBle/Resources/Styles/Styles.xaml b/Source/GnssTracker/Connectivity/MobileGnssTrackerConnectivity/Resources/Styles/Styles.xaml similarity index 100% rename from Source/ProjectLab/ProjectLabWiFiBle/MobileProjectLabWiFiBle/Resources/Styles/Styles.xaml rename to Source/GnssTracker/Connectivity/MobileGnssTrackerConnectivity/Resources/Styles/Styles.xaml diff --git a/Source/GnssTracker/Connectivity/MobileGnssTrackerConnectivity/Utils/BleConstants.cs b/Source/GnssTracker/Connectivity/MobileGnssTrackerConnectivity/Utils/BleConstants.cs new file mode 100644 index 00000000..b4b58570 --- /dev/null +++ b/Source/GnssTracker/Connectivity/MobileGnssTrackerConnectivity/Utils/BleConstants.cs @@ -0,0 +1,14 @@ +namespace MobileGnssTrackerConnectivity.Utils +{ + public static class CharacteristicsConstants + { + public const string ON = "73cfbc6f-61fa-4d80-a92f-eec2a90f8a3e"; + public const string OFF = "6315119d-d619-49bb-a21d-ef9e99941948"; + public const string PULSING = "d7551801-31fc-435d-a994-1e7f15e17baf"; + public const string BLINKING = "3a6cc4f2-a6ab-4709-a9bf-c9611c6bf892"; + public const string RUNNING_COLORS = "30df1258-f42b-4788-af2e-a8ed9d0b932f"; + + public const string IS_CYCLING = "24517ccc-888e-4ffc-9da5-21884353b08d"; + public const string ANGLE = "5a0bb016-69ab-4a49-a2f2-de5b292458f3"; + } +} \ No newline at end of file diff --git a/Source/GnssTracker/Connectivity/MobileGnssTrackerConnectivity/View/BluetoothPage.xaml b/Source/GnssTracker/Connectivity/MobileGnssTrackerConnectivity/View/BluetoothPage.xaml new file mode 100644 index 00000000..5936ab1a --- /dev/null +++ b/Source/GnssTracker/Connectivity/MobileGnssTrackerConnectivity/View/BluetoothPage.xaml @@ -0,0 +1,267 @@ + + + + + + #555 + + + + + + + + + + + + + + + + + + + + +