Skip to content

Commit

Permalink
Add CellularSample
Browse files Browse the repository at this point in the history
  • Loading branch information
jorgedevs committed Jul 30, 2024
1 parent d969b65 commit 2536709
Show file tree
Hide file tree
Showing 14 changed files with 388 additions and 0 deletions.
12 changes: 12 additions & 0 deletions Source/Meadow.Samples.sln
Original file line number Diff line number Diff line change
Expand Up @@ -435,6 +435,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DesktopModbusClient", "Modb
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MeadowModbusServer", "Modbus\MeadowModbusServer\MeadowModbusServer.csproj", "{F6BA3311-6502-4A7E-89A9-D943245DCA00}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CellularSample", "ProjectLab\CellularSample\CellularSample.csproj", "{F7301799-6DAF-4A80-A034-0267DF5426AE}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Expand Down Expand Up @@ -1916,6 +1918,15 @@ Global
{F6BA3311-6502-4A7E-89A9-D943245DCA00}.Simulation|Any CPU.ActiveCfg = Debug|Any CPU
{F6BA3311-6502-4A7E-89A9-D943245DCA00}.Simulation|Any CPU.Build.0 = Debug|Any CPU
{F6BA3311-6502-4A7E-89A9-D943245DCA00}.Simulation|Any CPU.Deploy.0 = Debug|Any CPU
{F7301799-6DAF-4A80-A034-0267DF5426AE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{F7301799-6DAF-4A80-A034-0267DF5426AE}.Debug|Any CPU.Build.0 = Debug|Any CPU
{F7301799-6DAF-4A80-A034-0267DF5426AE}.Debug|Any CPU.Deploy.0 = Debug|Any CPU
{F7301799-6DAF-4A80-A034-0267DF5426AE}.Release|Any CPU.ActiveCfg = Release|Any CPU
{F7301799-6DAF-4A80-A034-0267DF5426AE}.Release|Any CPU.Build.0 = Release|Any CPU
{F7301799-6DAF-4A80-A034-0267DF5426AE}.Release|Any CPU.Deploy.0 = Release|Any CPU
{F7301799-6DAF-4A80-A034-0267DF5426AE}.Simulation|Any CPU.ActiveCfg = Debug|Any CPU
{F7301799-6DAF-4A80-A034-0267DF5426AE}.Simulation|Any CPU.Build.0 = Debug|Any CPU
{F7301799-6DAF-4A80-A034-0267DF5426AE}.Simulation|Any CPU.Deploy.0 = Debug|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Expand Down Expand Up @@ -2123,6 +2134,7 @@ Global
{029D7D51-257B-4CA9-80AC-F8B0238B55DF} = {3B2ADC8C-1ACB-49F3-8A3C-4F453FF9FE75}
{4A4C3198-BF16-47DB-BA01-25DDCF77B2F5} = {3B2ADC8C-1ACB-49F3-8A3C-4F453FF9FE75}
{F6BA3311-6502-4A7E-89A9-D943245DCA00} = {3B2ADC8C-1ACB-49F3-8A3C-4F453FF9FE75}
{F7301799-6DAF-4A80-A034-0267DF5426AE} = {DA0CC626-D072-457F-89B7-C22427D4C775}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {E3F002EA-1A25-487F-9A5D-93D1E7EC6E31}
Expand Down
14 changes: 14 additions & 0 deletions Source/ProjectLab/CellularSample/.vscode/launch.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
{
// 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"
}
]
}
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
41 changes: 41 additions & 0 deletions Source/ProjectLab/CellularSample/CellularSample.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
<Project Sdk="Meadow.Sdk/1.1.0">
<PropertyGroup>
<TargetFramework>netstandard2.1</TargetFramework>
<CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies>
<OutputType>Library</OutputType>
<AssemblyName>App</AssemblyName>
<LangVersion>10.0</LangVersion>
</PropertyGroup>
<ItemGroup>
<None Remove="Assets\img-cell-0.bmp" />
<None Remove="Assets\img-cell-1.bmp" />
<None Remove="Assets\img-cell-2.bmp" />
<None Remove="Assets\img-cell-3.bmp" />
<None Remove="Assets\img-cell-4.bmp" />
</ItemGroup>
<ItemGroup>
<EmbeddedResource Include="Assets\img-cell-0.bmp" />
<EmbeddedResource Include="Assets\img-cell-1.bmp" />
<EmbeddedResource Include="Assets\img-cell-2.bmp" />
<EmbeddedResource Include="Assets\img-cell-3.bmp" />
<EmbeddedResource Include="Assets\img-cell-4.bmp" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Meadow.Foundation.Graphics.MicroLayout" Version="*" />
<PackageReference Include="Meadow.ProjectLab" Version="*" />
</ItemGroup>
<ItemGroup>
<None Update="app.build.yaml">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
<None Update="app.config.yaml">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
<None Update="cell.config.yaml">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
<None Update="meadow.config.yaml">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
</ItemGroup>
</Project>
94 changes: 94 additions & 0 deletions Source/ProjectLab/CellularSample/DisplayController.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
using Meadow;
using Meadow.Foundation.Graphics;
using Meadow.Foundation.Graphics.MicroLayout;
using Meadow.Peripherals.Displays;

namespace CellularSample;

public class DisplayController
{
DisplayScreen screen;

private readonly Image imgSignal0Bar = Image.LoadFromResource("CellularSample.Assets.img-cell-0.bmp");
private readonly Image imgSignal1Bar = Image.LoadFromResource("CellularSample.Assets.img-cell-1.bmp");
private readonly Image imgSignal2Bar = Image.LoadFromResource("CellularSample.Assets.img-cell-2.bmp");
private readonly Image imgSignal3Bar = Image.LoadFromResource("CellularSample.Assets.img-cell-3.bmp");
private readonly Image imgSignal4Bar = Image.LoadFromResource("CellularSample.Assets.img-cell-4.bmp");

private Label status;
private Label ipAddress;
private Picture signalBars;

public DisplayController(IPixelDisplay _display)
{
screen = new DisplayScreen(_display, RotationType._270Degrees)
{
BackgroundColor = Color.FromHex("14607F")
};

screen.Controls.Add(new Box(5, 5, screen.Width - 10, screen.Height - 10)
{
IsFilled = false,
ForeColor = Color.FromHex("F9E000")
});

signalBars = new Picture(105, 33, 110, 103, imgSignal0Bar);
screen.Controls.Add(signalBars);

status = new Label(60, 149, 200, 24)
{
Text = "OFFLINE...",
TextColor = Color.FromHex("F9E000"),
Font = new Font16x24(),
HorizontalAlignment = HorizontalAlignment.Center,
};
screen.Controls.Add(status);

ipAddress = new Label(35, 183, 250, 28)
{
Text = "---.---.---.---",
TextColor = Color.FromHex("14607F"),
Font = new Font16x24(),
BackColor = Color.FromHex("F9E000"),
HorizontalAlignment = HorizontalAlignment.Center,
VerticalAlignment = VerticalAlignment.Bottom,
};
screen.Controls.Add(ipAddress);
}

public void UpdateSignalBar(int strength)
{
Resolver.Log.Info("Signal Strength: " + strength);

switch (strength)
{
case int n when (n >= -70 && n <= -20):
signalBars.Image = imgSignal4Bar;
break;
case int n when (n >= -80 && n <= -71):
signalBars.Image = imgSignal3Bar;
break;
case int n when (n >= -90 && n <= -81):
signalBars.Image = imgSignal2Bar;
break;
case int n when (n >= -100 && n <= -91):
signalBars.Image = imgSignal1Bar;
break;
default:
signalBars.Image = imgSignal0Bar;
break;
}
}

public void UpdateStatus(string status)
{
this.status.Text = status;
}

public void UpdateIpAddress(string ipAddress)
{
this.ipAddress.Text = string.IsNullOrEmpty(ipAddress)
? "---.---.---.---"
: ipAddress;
}
}
145 changes: 145 additions & 0 deletions Source/ProjectLab/CellularSample/MeadowApp.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,145 @@
using Meadow;
using Meadow.Devices;
using Meadow.Foundation;
using Meadow.Hardware;
using System;
using System.Diagnostics;
using System.Net.Http;
using System.Threading.Tasks;

namespace CellularSample;

public class MeadowApp : ProjectLabCoreComputeApp
{
private DisplayController? displayController;

public override Task Initialize()
{
Resolver.Log.Info("Initialize...");

var cell = Hardware.ComputeModule.NetworkAdapters.Primary<ICellNetworkAdapter>();
cell.NetworkConnected += CellAdapterNetworkConnected;
cell.NetworkConnecting += CellNetworkConnecting;
cell.NetworkDisconnected += CellAdapterNetworkDisconnected;
cell.NetworkConnectFailed += CellNetworkConnectFailed;

Resolver.Log.Info($"Running on ProjectLab Hardware {Hardware.RevisionString}");

if (Hardware.RgbLed is { } rgbLed)
{
rgbLed.SetColor(Color.Blue);
}

if (Hardware.Display is { } display)
{
displayController = new DisplayController(display);

displayController.UpdateSignalBar(cell.GetSignalQuality());
displayController.UpdateStatus(cell.IsConnected ? "CONNECTED" : "DISCONNECTED");
displayController.UpdateIpAddress(cell.IsConnected ? cell.IpAddress.ToString() : "---.---.---.---");
}

return Task.CompletedTask;
}

private async void CellAdapterNetworkConnected(INetworkAdapter networkAdapter, NetworkConnectionEventArgs e)
{
var cell = networkAdapter as ICellNetworkAdapter;

if (cell != null)
{
Resolver.Log.Info("Cell CSQ at the time of connection (dbm): " + cell.Csq);
Resolver.Log.Info("Cell IMEI: " + cell.Imei);

displayController.UpdateStatus("CONNECTED");
displayController.UpdateIpAddress(cell.IpAddress.ToString());
displayController.UpdateSignalBar(cell.Csq);

await GetWebPageViaHttpClient("https://postman-echo.com/get?fool=bar1&foo2=bar2");
}
}

private void CellNetworkConnecting(INetworkAdapter sender)
{
displayController.UpdateStatus("CONNECTING");
displayController.UpdateIpAddress("---.---.---.---");
displayController.UpdateSignalBar(-9999);
}

private void CellAdapterNetworkDisconnected(INetworkAdapter sender, NetworkDisconnectionEventArgs args)
{
displayController.UpdateStatus("DISCONNECTED");
displayController.UpdateIpAddress("---.---.---.---");
displayController.UpdateSignalBar(-9999);
}

private void CellNetworkConnectFailed(INetworkAdapter sender)
{
displayController.UpdateStatus("RECONNECT FAILED");
displayController.UpdateIpAddress("---.---.---.---");
displayController.UpdateSignalBar(-9999);
}

private async Task GetWebPageViaHttpClient(string uri)
{
Resolver.Log.Info($"Requesting {uri} - {DateTime.Now}");
Stopwatch stopwatch = new Stopwatch();
stopwatch.Start();

using (HttpClient client = new HttpClient())
{
// In weak signal connections and/or large download scenarios, it's recommended to increase the client timeout
client.Timeout = TimeSpan.FromMinutes(5);
using (HttpResponseMessage response = await client.GetAsync(uri, HttpCompletionOption.ResponseHeadersRead))
{
try
{
response.EnsureSuccessStatusCode();

var contentLength = response.Content.Headers.ContentLength ?? -1L;
var progress = new Progress<long>(totalBytes =>
{
Resolver.Log.Info($"{totalBytes} bytes downloaded ({(double)totalBytes / contentLength:P2})");
});

using (var stream = await response.Content.ReadAsStreamAsync())
{
var buffer = new byte[4096];
long totalBytesRead = 0;
int bytesRead;

while ((bytesRead = await stream.ReadAsync(buffer, 0, buffer.Length)) > 0)
{
totalBytesRead += bytesRead;
((IProgress<long>)progress).Report(totalBytesRead);
}
}

stopwatch.Stop();
Resolver.Log.Info($"Download complete. Time taken: {stopwatch.Elapsed.TotalSeconds:F2} seconds");
}
catch (TaskCanceledException)
{
Resolver.Log.Info("Request timed out.");
}
catch (Exception e)
{
Resolver.Log.Info($"Request went sideways: {e.Message}");
}
}
}
}

public override Task Run()
{
Resolver.Log.Info("Run...");

if (Hardware?.RgbLed is { } rgbLed)
{
Resolver.Log.Info("starting blink");
_ = rgbLed.StartBlink(WildernessLabsColors.PearGreen, TimeSpan.FromMilliseconds(500), TimeSpan.FromMilliseconds(2000), 0.5f);
}

return Task.CompletedTask;
}
}
2 changes: 2 additions & 0 deletions Source/ProjectLab/CellularSample/app.build.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
Deploy:
NoLink: [ ProjectLab ]
36 changes: 36 additions & 0 deletions Source/ProjectLab/CellularSample/app.config.yaml
Original file line number Diff line number Diff line change
@@ -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: true

# 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: Trace

# 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
5 changes: 5 additions & 0 deletions Source/ProjectLab/CellularSample/cell.config.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
Settings:
APN: teal # (required) Access Point Name
Module: BG95M3 # (required) Module model (BG770A, BG95M3 or M95)
Interface: COM1 # (required) Serial interface (COM1 (default), COM4 or COM6)
EnablePin: A3 # (required) Enable MCU pin to turn the module on/off.
Loading

0 comments on commit 2536709

Please sign in to comment.