Skip to content

Commit

Permalink
Merge pull request #566 from WildernessLabs/v1.12.8
Browse files Browse the repository at this point in the history
Release 1.12.8
  • Loading branch information
ctacke authored Jul 29, 2024
2 parents cf22558 + 0a6a43f commit fecdddc
Show file tree
Hide file tree
Showing 122 changed files with 3,872 additions and 2,332 deletions.
1 change: 1 addition & 0 deletions .github/workflows/develop-ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ name: Develop Build
on:
workflow_dispatch:
pull_request:
branches: [ develop ]
push:
branches: [ develop ]

Expand Down
7 changes: 3 additions & 4 deletions .github/workflows/main-ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,10 @@ jobs:
with:
path: Meadow.Core

- name: Setup .NET SDK
uses: actions/setup-dotnet@v3
- name: Setup .NET
uses: actions/setup-dotnet@v1
with:
dotnet-version:
7.0.x
dotnet-version: 8.0.x

- name: Install MAUI Workload
run: dotnet workload install maui --ignore-failed-sources
Expand Down
43 changes: 43 additions & 0 deletions doc/services.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
# Meadow Core Services

## MeadowCloudConnectionService
## MeadowCloudCommandService
## MeadowCloudUpdateService
## SensorService

## ReliabilityService

Part of platform stability, beyond not crashing, is the ability to detect crashes and to manage the device restart whenever possible.

The Meadow `ReliabilityService` provides applications an aggregation of data and behaviors related to device reliability.

### Handling crashes

Crashes generally fall into two categories: stable and unstable.

An unstable crash leaves the device oeprating system or the .NET runtime in an unstable state and the application has no opportunity to coordinate a shutdown. Examples might be an unhandled applicatin exception or an out-of-memory condition. In these cases the device will restart without providing the application any pre-restart warning (generally the app is dead at this point and couldn't do anything anyway). When the application comes back up, it has a variety of ways to know the crash occurred and to get data about the crash. These are discussed in more detail in the next section.

A stable crash is when a subsystem for the device has failed, but the application can continue to run, even if it's in a degraded state. An example of this is the network subsystem crashing. In this case the application may not be able to execute all of it's features (like sending data to the Cloud) but it can still execute. In these cases, the application is notified of the crash and provided a recommendation on whether the device should be restarted to recover full capabilities. The application can then do things like save state or go through an ordered shutdown procedure before restarting.

Stable crashes are handled by subscribng to the `RelaibilityService.MeadowSystemError` event. The handler will have the following signature:

```
void OnMeadowSystemError(MeadowSystemErrorInfo error, bool recommendReset, out bool forceReset)
```

Information about the error will be passed to the application along with a boolean flag that will be *true* if the device should be reset to recover. The application can then set the `forceReset` parameter to *true* to let the `ReliabilityService` reset the device, or alternatively return *false* and handle resetting the device itself.

If no `MeadowSystemError` handler is registered by the application, the `ReliabilityService` will automatically follow the system reset recommendation and reset automatically where appropriate.


### Booting after a crash

It is often useful to know if your application is starting after a crash. The `ReliabilityService` provides information on this state through the following properties and methods:

- `LastBootWasFromCrash` will return true if the app is booting after a crash. This property signals if there is crash data available (i.e. if you don't clear crash data, it will continue to return true)
- `IsCrashDataAvailable` will return true if any crash data is available. Crash data can come from multiple sources (app crash, runtime failure, OS failure, coprocessor failure, etc)
- `GetCrashData()` will retrieve all crash data.
- `ClearCrashData()` erases stored crash data, returning the devcie to a clean state
- `LastResetReason` returns a `ResetReason` enumeration corresponding to the reason for the last devcie reset
- `SystemResetCount` returns the total number of lifetime resets the device has seen
- `SystemPowerCycleCount` returns the total number of cold boots (non-reset power ups) the device has seen
16 changes: 7 additions & 9 deletions source/Meadow.Core.sln
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,6 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Meadow.F7", "implementation
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Meadow.Simulation", "implementations\simulation\Meadow.Simulation\Meadow.Simulation.csproj", "{5543D2D5-FA80-43CE-8844-40510A7DBED6}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Meadow.Simulation.Unit.Tests", "implementations\simulation\Meadow.Simulation.Unit.Tests\Meadow.Simulation.Unit.Tests.csproj", "{40647101-F527-478F-888E-8D2041A8A614}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "linux", "linux", "{B187C117-A16E-4A75-B862-3CA7DCA464B8}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Meadow.Linux", "implementations\linux\Meadow.Linux\Meadow.Linux.csproj", "{4DEA563C-50EE-4729-ACA4-C77A251655BC}"
Expand All @@ -42,6 +40,13 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "desktop", "desktop", "{915A
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Meadow.Desktop", "implementations\desktop\Meadow.Desktop\Meadow.Desktop.csproj", "{FAAB5C33-D500-4414-B83C-605CCD08598C}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "_docs", "_docs", "{C3582F8C-7D7C-4898-8BE7-5B0AE537DC4D}"
ProjectSection(SolutionItems) = preProject
..\Interrupt.md = ..\Interrupt.md
..\README.md = ..\README.md
..\doc\services.md = ..\doc\services.md
EndProjectSection
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Core|Any CPU = Core|Any CPU
Expand Down Expand Up @@ -76,12 +81,6 @@ Global
{5543D2D5-FA80-43CE-8844-40510A7DBED6}.Debug|Any CPU.Build.0 = Debug|Any CPU
{5543D2D5-FA80-43CE-8844-40510A7DBED6}.Release|Any CPU.ActiveCfg = Release|Any CPU
{5543D2D5-FA80-43CE-8844-40510A7DBED6}.Release|Any CPU.Build.0 = Release|Any CPU
{40647101-F527-478F-888E-8D2041A8A614}.Core|Any CPU.ActiveCfg = Debug|Any CPU
{40647101-F527-478F-888E-8D2041A8A614}.Core|Any CPU.Build.0 = Debug|Any CPU
{40647101-F527-478F-888E-8D2041A8A614}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{40647101-F527-478F-888E-8D2041A8A614}.Debug|Any CPU.Build.0 = Debug|Any CPU
{40647101-F527-478F-888E-8D2041A8A614}.Release|Any CPU.ActiveCfg = Release|Any CPU
{40647101-F527-478F-888E-8D2041A8A614}.Release|Any CPU.Build.0 = Release|Any CPU
{4DEA563C-50EE-4729-ACA4-C77A251655BC}.Core|Any CPU.ActiveCfg = Debug|Any CPU
{4DEA563C-50EE-4729-ACA4-C77A251655BC}.Core|Any CPU.Build.0 = Debug|Any CPU
{4DEA563C-50EE-4729-ACA4-C77A251655BC}.Core|Any CPU.Deploy.0 = Debug|Any CPU
Expand Down Expand Up @@ -129,7 +128,6 @@ Global
{93DFC566-A413-4039-A0C1-90A42A356386} = {7BCFC6D6-228E-4C93-8145-EAD121AA8587}
{E377CD5F-1E6C-4FFD-BA70-F17620A9273E} = {716A47C0-59CB-485F-B6C8-57F073F5B633}
{5543D2D5-FA80-43CE-8844-40510A7DBED6} = {89E8BFD9-BC4E-4409-8AB5-9B1FD0A72CAB}
{40647101-F527-478F-888E-8D2041A8A614} = {7BCFC6D6-228E-4C93-8145-EAD121AA8587}
{B187C117-A16E-4A75-B862-3CA7DCA464B8} = {CC469899-D08C-417C-A908-C052CA155BEC}
{4DEA563C-50EE-4729-ACA4-C77A251655BC} = {B187C117-A16E-4A75-B862-3CA7DCA464B8}
{716A47C0-59CB-485F-B6C8-57F073F5B633} = {CC469899-D08C-417C-A908-C052CA155BEC}
Expand Down
31 changes: 5 additions & 26 deletions source/Meadow.Core/Bases/App.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,7 @@
/// class for Meadow applications to get strongly-typed access to the current
/// device information.
/// </summary>
public abstract class App<D> : IApp, IAsyncDisposable
where D : class, IMeadowDevice
public abstract class AppBase : IApp
{
private ExecutionContext executionContext;

Expand All @@ -24,11 +23,10 @@ public abstract class App<D> : IApp, IAsyncDisposable
/// <summary>
/// Base constructor for the App class
/// </summary>
protected App()
protected AppBase()
{
executionContext = Thread.CurrentThread.ExecutionContext;

Device = MeadowOS.CurrentDevice as D ?? throw new ArgumentException($"Current device is not {typeof(D).Name}"); // 'D' is guaranteed to be initialized and the same type
Abort = MeadowOS.AppAbort.Token;

Resolver.Services.Add<IApp>(this);
Expand All @@ -39,25 +37,11 @@ protected App()
/// </summary>
/// <param name="action">The action to call</param>
/// <param name="state">An optional state object to pass to the Action</param>
public void InvokeOnMainThread(Action<object?> action, object? state = null)
public virtual void InvokeOnMainThread(Action<object?> action, object? state = null)
{
switch (Device.Information.Platform)
{
// ExecutionContext in Mono on the F7 isn't fully working - but we also don't worry about a MainThread there either
case Hardware.MeadowPlatform.F7FeatherV1:
case Hardware.MeadowPlatform.F7FeatherV2:
case Hardware.MeadowPlatform.F7CoreComputeV2:
action.Invoke(state);
break;
default:
ExecutionContext.Run(executionContext, new ContextCallback(action), state);
break;
}
action.Invoke(state);
}

/// <inheritdoc/>
public virtual void OnBootFromCrash(IEnumerable<string> crashReports) { }

/// <summary>
/// Called by MeadowOS when everything is ready for the App to run
/// </summary>
Expand Down Expand Up @@ -99,11 +83,6 @@ public void OnUpdateComplete(Version oldVersion, out bool rollbackUpdate)
rollbackUpdate = false;
}

/// <summary>
/// The root Device interface
/// </summary>
public static D Device { get; protected set; } = default!;

/// <summary>
/// The app cancellation token
/// </summary>
Expand All @@ -113,4 +92,4 @@ public void OnUpdateComplete(Version oldVersion, out bool rollbackUpdate)
/// Virtual method provided for App implementations to clean up resources on Disposal
/// </summary>
public virtual ValueTask DisposeAsync() { return new ValueTask(Task.CompletedTask); }
}
}
43 changes: 43 additions & 0 deletions source/Meadow.Core/Bases/App_D.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
namespace Meadow;

using System;


/// <summary>
/// Provides a base implementation for the Meadow App. Use this
/// class for Meadow applications to get strongly-typed access to the current
/// device information.
/// </summary>
public abstract class App<D> : AppBase
where D : class, IMeadowDevice
{
/// <summary>
/// The root Device interface
/// </summary>
public static D Device { get; protected set; } = default!;

/// <summary>
/// Base constructor for the App class
/// </summary>
public App()
{
Device = MeadowOS.CurrentDevice as D ?? throw new ArgumentException($"Current device is not {typeof(D).Name}"); // 'D' is guaranteed to be initialized and the same type
}

/// <inheritdoc/>
public override void InvokeOnMainThread(Action<object?> action, object? state = null)
{
switch (Device.Information.Platform)
{
// ExecutionContext in Mono on the F7 isn't fully working - but we also don't worry about a MainThread there either
case Hardware.MeadowPlatform.F7FeatherV1:
case Hardware.MeadowPlatform.F7FeatherV2:
case Hardware.MeadowPlatform.F7CoreComputeV2:
action.Invoke(state);
break;
default:
base.InvokeOnMainThread(action, state);
break;
}
}
}
20 changes: 20 additions & 0 deletions source/Meadow.Core/Bases/App_D_P_H.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
namespace Meadow;

/// <summary>
/// Provides a base implementation for the Meadow App. Use this
/// class for Meadow applications to get strongly-typed access to the current
/// device information.
/// </summary>
/// <typeparam name="D">The type of the IMeadowDevice this app targets</typeparam>
/// <typeparam name="P">The type of the IMeadowAppEmbeddedHardwareProvider to create</typeparam>
/// <typeparam name="H">The type of the IMeadowAppEmbeddedHardware the Provider will return</typeparam>
public abstract class App<D, P, H> : AppBase
where D : class, IMeadowDevice
where P : IMeadowAppEmbeddedHardwareProvider<H>
where H : IMeadowAppEmbeddedHardware
{
/// <summary>
/// The instance if the IMeadowAppEmbeddedHardware on which the stack is running
/// </summary>
public static H Hardware { get; internal set; } = default!;
}
87 changes: 0 additions & 87 deletions source/Meadow.Core/Cloud/CrashReporter.cs

This file was deleted.

Loading

0 comments on commit fecdddc

Please sign in to comment.