Skip to content

Commit

Permalink
Merge pull request #72 from WildernessLabs/feature/clean-up
Browse files Browse the repository at this point in the history
More clean-up and refactoring of power and sensor telemetry
  • Loading branch information
ctacke committed Apr 19, 2024
2 parents 18d9cf6 + e4972c4 commit 797a4a3
Show file tree
Hide file tree
Showing 12 changed files with 524 additions and 67 deletions.
1 change: 1 addition & 0 deletions Source/Clima_Demo/Clima_Demo.csproj
Expand Up @@ -5,6 +5,7 @@
<OutputType>Library</OutputType>
<AssemblyName>App</AssemblyName>
<LangVersion>10</LangVersion>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\Meadow.Clima\Meadow.Clima.csproj" />
Expand Down
52 changes: 4 additions & 48 deletions Source/Clima_Demo/MeadowApp.cs
Expand Up @@ -8,67 +8,23 @@ namespace Clima_Demo;

public class MeadowApp : App<F7CoreComputeV2>
{
private IClimaHardware clima;
private NotificationController notificationController;
private SensorController sensorController;
private PowerController powerController;
private LocationController locationController;
private MainController mainController;

public MeadowApp()
{
Resolver.Services.Add(new CloudController());
mainController = new MainController();
}

public override void OnBootFromCrash(IEnumerable<string> crashReports)
{
Resolver.Services.Get<CloudController>()?.LogAppStartupAfterCrash();
mainController.LogAppStartupAfterCrash(crashReports);
}

public override Task Initialize()
{
Resolver.Log.LogLevel = Meadow.Logging.LogLevel.Information;

Resolver.Log.Info("Initialize hardware...");

clima = Clima.Create();

notificationController = new NotificationController(clima.RgbLed);
Resolver.Services.Add<NotificationController>(notificationController);

notificationController.Starting();

Resolver.Services.Get<CloudController>()?.LogAppStartup(clima.RevisionString);
Resolver.Log.Info($"Running on Clima Hardware {clima.RevisionString}");

sensorController = new SensorController(clima);
powerController = new PowerController(clima);
locationController = new LocationController(clima);

var wifi = Device.NetworkAdapters.Primary<IWiFiNetworkAdapter>();
wifi.NetworkConnected += OnNetworkConnected;
wifi.NetworkDisconnected += OnNetworkDisconnected;

if (wifi.IsConnected)
{
notificationController.NetworkConnected();
}
else
{
notificationController.NetworkDisconnected();
}

Resolver.Log.Info("Initialization complete");
mainController.Initialize(Clima.Create(), wifi);

return Task.CompletedTask;
}

private void OnNetworkDisconnected(INetworkAdapter sender, NetworkDisconnectionEventArgs args)
{
notificationController.NetworkDisconnected();
}

private void OnNetworkConnected(INetworkAdapter sender, NetworkConnectionEventArgs args)
{
notificationController.NetworkConnected();
}
}
15 changes: 15 additions & 0 deletions Source/Meadow.Clima.sln
Expand Up @@ -58,6 +58,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Clima_SQLite_Demo", "Additi
EndProject
Project("{D954291E-2A0B-460D-934E-DC6B0785DB48}") = "CommonContracts", "Additional Samples\CommonContracts\CommonContracts.shproj", "{567267B3-ED96-4FEA-B555-2EE203372EA4}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Serialization.MicroJson", "..\..\Meadow.Foundation\Source\Meadow.Foundation.Libraries_and_Frameworks\Serialization.MicroJson\Driver\Serialization.MicroJson.csproj", "{6300EAB4-806F-4C18-8FE0-57C45A2C0C58}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Expand Down Expand Up @@ -488,6 +490,18 @@ Global
{494082D7-2C48-45A6-8FF7-DD553D27BC4A}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
{494082D7-2C48-45A6-8FF7-DD553D27BC4A}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
{494082D7-2C48-45A6-8FF7-DD553D27BC4A}.Release|iPhoneSimulator.Deploy.0 = Release|Any CPU
{6300EAB4-806F-4C18-8FE0-57C45A2C0C58}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{6300EAB4-806F-4C18-8FE0-57C45A2C0C58}.Debug|Any CPU.Build.0 = Debug|Any CPU
{6300EAB4-806F-4C18-8FE0-57C45A2C0C58}.Debug|iPhone.ActiveCfg = Debug|Any CPU
{6300EAB4-806F-4C18-8FE0-57C45A2C0C58}.Debug|iPhone.Build.0 = Debug|Any CPU
{6300EAB4-806F-4C18-8FE0-57C45A2C0C58}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU
{6300EAB4-806F-4C18-8FE0-57C45A2C0C58}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU
{6300EAB4-806F-4C18-8FE0-57C45A2C0C58}.Release|Any CPU.ActiveCfg = Release|Any CPU
{6300EAB4-806F-4C18-8FE0-57C45A2C0C58}.Release|Any CPU.Build.0 = Release|Any CPU
{6300EAB4-806F-4C18-8FE0-57C45A2C0C58}.Release|iPhone.ActiveCfg = Release|Any CPU
{6300EAB4-806F-4C18-8FE0-57C45A2C0C58}.Release|iPhone.Build.0 = Release|Any CPU
{6300EAB4-806F-4C18-8FE0-57C45A2C0C58}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
{6300EAB4-806F-4C18-8FE0-57C45A2C0C58}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Expand Down Expand Up @@ -517,6 +531,7 @@ Global
{0B2E742C-9C97-4CE1-8B2A-1390CB3F1B03} = {4AB0FC09-05D2-4F55-9C2D-13C133456E2F}
{494082D7-2C48-45A6-8FF7-DD553D27BC4A} = {4AB0FC09-05D2-4F55-9C2D-13C133456E2F}
{567267B3-ED96-4FEA-B555-2EE203372EA4} = {4AB0FC09-05D2-4F55-9C2D-13C133456E2F}
{6300EAB4-806F-4C18-8FE0-57C45A2C0C58} = {2889A476-F914-49E8-9F97-4CC6CA34A901}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {CA61E123-F783-4CB3-8EB2-099EE930ADD4}
Expand Down
1 change: 1 addition & 0 deletions Source/Meadow.Clima/Constants/CloudEventIds.cs
Expand Up @@ -3,5 +3,6 @@
public enum CloudEventIds
{
DeviceStarted = 100,
Telemetry = 110,
BootFromCrash = 200
}
81 changes: 73 additions & 8 deletions Source/Meadow.Clima/Controllers/CloudController.cs
@@ -1,22 +1,51 @@
using Meadow;
using Meadow.Cloud;
using System;
using System.Linq;

namespace Clima_Demo;

public class CloudController
{
public void LogAppStartupAfterCrash()
{
LogEvent(CloudEventIds.DeviceStarted, $"Device restarted after crash");
SendEvent(CloudEventIds.DeviceStarted, $"Device restarted after crash");
}

public void LogAppStartup(string hardwareRevision)
{
LogEvent(CloudEventIds.DeviceStarted, $"Device started (hardware {hardwareRevision})");
SendEvent(CloudEventIds.DeviceStarted, $"Device started (hardware {hardwareRevision})");
}

private void LogEvent(CloudEventIds eventId, string message)
public void LogWarning(string message)
{
SendLog(message, "warning");
}

public void LogMessage(string message)
{
SendLog(message, "information");
}

public void LogTelemetry(SensorData sensorData, PowerData powerData)
{
var measurements = sensorData
.AsTelemetryDictionary()
.Concat(powerData.AsTelemetryDictionary())
.ToDictionary(kvp => kvp.Key, kvp => kvp.Value);

var cloudEvent = new CloudEvent
{
Description = "Clima Telemetry",
Timestamp = DateTime.UtcNow,
EventId = (int)CloudEventIds.Telemetry,
Measurements = measurements
};

SendEvent(cloudEvent);
}

private void SendLog(string message, string severity)
{
if (Resolver.MeadowCloudService == null)
{
Expand All @@ -30,14 +59,50 @@ private void LogEvent(CloudEventIds eventId, string message)
return;
}

Resolver.Log.Info($"Sending cloud event");
Resolver.Log.Info($"Sending cloud log");

Resolver.MeadowCloudService.SendEvent(
new CloudEvent
Resolver.MeadowCloudService.SendLog(
new CloudLog
{
EventId = (int)eventId,
Description = message,
Message = message,
Timestamp = DateTime.UtcNow,
Severity = severity
});
}

private void SendEvent(CloudEventIds eventId, string message)
{
SendEvent(new CloudEvent
{
EventId = (int)eventId,
Description = message,
Timestamp = DateTime.UtcNow,
});
}

private void SendEvent(CloudEvent cloudEvent)
{
if (Resolver.MeadowCloudService == null)
{
Resolver.Log.Warn($"CLOUD SERVICE IS NULL");
return;
}

if (!Resolver.MeadowCloudService.IsEnabled)
{
Resolver.Log.Warn($"CLOUD INTEGRATION IS DISABLED");
return;
}

Resolver.Log.Info($"Sending cloud event");

try
{
Resolver.MeadowCloudService.SendEvent(cloudEvent);
}
catch (Exception ex)
{
Resolver.Log.Warn($"Failed to send cloud event: {ex.Message}");
}
}
}
54 changes: 54 additions & 0 deletions Source/Meadow.Clima/Controllers/NetworkController.cs
@@ -0,0 +1,54 @@
using Meadow.Hardware;
using System;
using System.Threading;

namespace Meadow.Devices;

public class NetworkController
{
public event EventHandler<bool>? ConnectionStateChanged;
public event EventHandler<TimeSpan>? NetworkDown;

private readonly INetworkAdapter networkAdapter;
private DateTimeOffset? lastDown;
private Timer downEventTimer;

public bool IsConnected => networkAdapter.IsConnected;
public TimeSpan DownTime => lastDown == null ? TimeSpan.Zero : DateTime.UtcNow - lastDown.Value;
public TimeSpan DownEventPeriod { get; } = TimeSpan.FromSeconds(30);

public NetworkController(INetworkAdapter networkAdapter)
{
this.networkAdapter = networkAdapter;

networkAdapter.NetworkConnected += OnNetworkConnected;
networkAdapter.NetworkDisconnected += OnNetworkDisconnected;

downEventTimer = new Timer(DownEventTimerProc, null, -1, -1);
}

private void DownEventTimerProc(object _)
{
if (networkAdapter.IsConnected)
{
downEventTimer.Change(-1, -1);
return;
}

NetworkDown?.Invoke(this, DownTime);
downEventTimer.Change(DownEventPeriod, TimeSpan.FromMilliseconds(-1));
}

private void OnNetworkDisconnected(INetworkAdapter sender, NetworkDisconnectionEventArgs args)
{
lastDown = DateTimeOffset.UtcNow;
downEventTimer.Change(DownEventPeriod, TimeSpan.FromMilliseconds(-1));
ConnectionStateChanged?.Invoke(this, false);
}

private void OnNetworkConnected(INetworkAdapter sender, NetworkConnectionEventArgs args)
{
lastDown = null;
ConnectionStateChanged?.Invoke(this, true);
}
}
45 changes: 36 additions & 9 deletions Source/Meadow.Clima/Controllers/NotificationController.cs
@@ -1,31 +1,58 @@
using Meadow;
using Meadow.Peripherals.Leds;
using Meadow.Peripherals.Leds;
using System;

namespace Clima_Demo;

public class NotificationController
{
[Flags]
public enum Warnings
{
None = 0,
NetworkDisconnected = 1 << 0,
SolarLoadLow = 1 << 1,
BatteryLow = 1 << 2,
}

private readonly IRgbPwmLed? rgbLed;
private Warnings activeWarnings = Warnings.None;

public NotificationController(IRgbPwmLed? rgbLed)
{
this.rgbLed = rgbLed;
}

public void Starting()
public void SystemStarting()
{
rgbLed?.SetColor(RgbLedColors.Red);
}

public void NetworkConnected()
public void SystemUp()
{
ReportWarnings();
}

public void SetWarning(Warnings warning)
{
activeWarnings |= warning;
ReportWarnings();
}

public void ClearWarning(Warnings warning)
{
Resolver.Log.Info("Network connected");
rgbLed?.SetColor(RgbLedColors.Green);
activeWarnings &= ~warning;
ReportWarnings();
}

public void NetworkDisconnected()
private void ReportWarnings()
{
Resolver.Log.Info("Network disconnected");
rgbLed?.SetColor(RgbLedColors.Yellow);
if (activeWarnings != Warnings.None)
{
rgbLed?.SetColor(RgbLedColors.Yellow);
}
else
{
rgbLed?.SetColor(RgbLedColors.Green);
}
}
}

0 comments on commit 797a4a3

Please sign in to comment.