Get started with Meadow.Blazor
Meadow.Blazor in combination with Meadow.Desktop offers an environment for developing Meadow applications that can run on Windows, Mac and Linux. Developing with Meadow.Blazor requires setting up your development machine with some prerequisites. Then, after connecting any external components, you can deploy and run your Meadow application.
Meadow Blazor enables you to combine a Blazor front-end while accessing physical components by way of an FTDI breakout board such as FT232H that provide GPIO, SPI, and I2C.
Prerequisites
Before you can get started with Meadow.Blazor, make sure your development machine is set up for Meadow development.
If not installed already, install the .NET 8.0 SDK. You can find the latest version of the .NET SDK from the .NET downloads.
Using GPIO and SPI
With an additional accessory, you can add GPIO and SPI capabilities to your desktop device. You can use an FTDI breakout board such as FT232H to provide GPIO and SPI capabilities. (The FT232H also supports I2C, but in this early stage, Meadow.Blazor does not yet support it.)
Create your first Meadow.Blazor app
Create a new dotnet app on your development machine and navigate to that new project.
dotnet new blazorserver -n MeadowBlazorSampleApp
cd MeadowBlazorSampleAppAdd the Meadow.Blazor NuGet reference to your project.
dotnet add package Meadow.Blazor
Create a new file named
MeadowApplication
in your project with the following code:using Meadow;
internal class MeadowApplication : App<Meadow.Desktop>
{
public override Task Initialize()
{
//initialize hardware here and add to sensor serivce
return base.Initialize();
}
public override Task Run()
{
return base.Run();
}
}If using external hardware, you'll need to add the relevant Meadow nuget packages and initialize the drivers in the
Initialize
method - for example:using Meadow;
using Meadow.Foundation.ICs.IOExpanders;
using Meadow.Foundation.Leds;
using Meadow.Foundation.Sensors.Atmospheric;
using Meadow.Peripherals.Leds;
internal class MeadowApplication : App<Meadow.Desktop>
{
public override Task Initialize()
{
FtdiExpanderCollection.Devices.Refresh();
var ftdi = FtdiExpanderCollection.Devices[0];
var output = ftdi.Pins.D7.CreateDigitalOutputPort(false);
Resolver.Services.Add(output);
var bme680 = new Bme680(ftdi.CreateSpiBus(), ftdi.Pins.C7);
Resolver.Services.Add(bme680);
var led = new Led(ftdi.Pins.C0);
Resolver.Services.Add<ILed>(led);
return base.Initialize();
}
public override Task Run()
{
return base.Run();
}
}Meadow.Desktop is initialized via an extension method on
WebApplication
included with Meadow.Blazor method namedUseMeadow
. AddUseMethod
to your program.cs file.using Meadow.Blazor;
using Meadow.Blazor.Services;
var builder = WebApplication.CreateBuilder(args);
...
var app = builder.Build();
...
app.UseMeadow<MeadowApplication>();
...
app.Run();Build the app for your development machine using either Visual Studio or the
dotnet
tool.dotnet build
Run the app.
dotnet run
Access peripherals from a Blazor server app
You'll decide on the architecture of your Blazor application but a common pattern is to create view models to support razor pages.
Here's an example view model that presents sensor data via string
properties for a BME680
atmospheric sensor. Note the StateChanged?.Invoke()
call to notify the UI of updates.
```csharp
using Meadow.Foundation.Sensors.Atmospheric;
using Meadow.Peripherals.Leds;
using Meadow.Units;
namespace Meadow.Blazor.Services
{
public class SensorViewModel : IDisposable
{
private readonly Bme680 _bme680;
public string TemperatureValue { get; private set; } = "0°C";
public string PressureValue { get; private set; } = "0atm";
public event Action? StateChanged;
public SensorViewModel()
{
_bme680 = Resolver.Services.Get<Bme680>() ?? throw new Exception("BME68x not found");
_bme680.Updated += Bme680Updated;
_bme680.StartUpdating(TimeSpan.FromSeconds(2));
}
private void Bme680Updated(object? sender, IChangeResult<(Temperature? Temperature, RelativeHumidity? Humidity, Pressure? Pressure, Resistance? GasResistance)> e)
{
TemperatureValue = $"{e.New.Temperature?.Celsius:n0}°C";
PressureValue = $"{e.New.Pressure?.StandardAtmosphere:n2}atm";
_led.IsOn = false;
StateChanged?.Invoke();
}
public void Dispose()
{
_bme680?.StopUpdating();
}
}
}
```
And here's example razor page that uses the view model above:
```
@page "/"
@inject Meadow.Blazor.Services.SensorViewModel ViewModel
<div class="container">
<div class="content">
<div class="image-container">
<img src="Assets/meadow.png" alt="Meadow" />
</div>
<h1>Meadow on Blazor</h1>
<h2>Atmospheric readings from a BME680</h2>
<div class="readings">
<div class="reading">
<span>Temperature:</span>
<span>@ViewModel.TemperatureValue</span>
</div>
<div class="reading">
<span>Pressure:</span>
<span>@ViewModel.PressureValue</span>
</div>
</div>
</div>
</div>
@code {
protected override void OnInitialized()
{
ViewModel.StateChanged += OnViewModelStateChanged;
}
private void OnViewModelStateChanged()
{
InvokeAsync(StateHasChanged);
}
public void Dispose()
{
ViewModel.StateChanged -= OnViewModelStateChanged;
}
}
```
Next steps
Now that you have your Meadow.Blazor device set up and your first Meadow app running on it, you can start working with the Meadow.Foundation libraries to add functionality to your Meadow app. Check out the other samples in the Meadow.Desktop.Samples.