Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Prep 0.4 #62

Merged
merged 8 commits into from
Sep 29, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 1 addition & 3 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,7 @@ jobs:
- name: Setup .NET
uses: actions/setup-dotnet@v2
with:
dotnet-version: |
6.0.x
3.1.x
dotnet-version: 6.0.x

- name: Restore dependencies
run: dotnet restore
Expand Down
14 changes: 14 additions & 0 deletions MQTTnet.Extensions.MultiCloud.sln
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,10 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "mqtt-device", "samples\mqtt
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "mqtt-grpc-device", "samples\mqtt-grpc-device\mqtt-grpc-device.csproj", "{AF019503-8813-4967-B858-0DDAE43C2073}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "payload-size", "samples\payload-size\payload-size.csproj", "{DF590535-2FDC-4A0A-9EE4-7C9BF818C7B4}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "memmon-protobuff", "samples\memmon-protobuff\memmon-protobuff.csproj", "{20B75646-CBD2-4E72-8C56-22887A519FA3}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Expand Down Expand Up @@ -108,6 +112,14 @@ Global
{AF019503-8813-4967-B858-0DDAE43C2073}.Debug|Any CPU.Build.0 = Debug|Any CPU
{AF019503-8813-4967-B858-0DDAE43C2073}.Release|Any CPU.ActiveCfg = Release|Any CPU
{AF019503-8813-4967-B858-0DDAE43C2073}.Release|Any CPU.Build.0 = Release|Any CPU
{DF590535-2FDC-4A0A-9EE4-7C9BF818C7B4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{DF590535-2FDC-4A0A-9EE4-7C9BF818C7B4}.Debug|Any CPU.Build.0 = Debug|Any CPU
{DF590535-2FDC-4A0A-9EE4-7C9BF818C7B4}.Release|Any CPU.ActiveCfg = Release|Any CPU
{DF590535-2FDC-4A0A-9EE4-7C9BF818C7B4}.Release|Any CPU.Build.0 = Release|Any CPU
{20B75646-CBD2-4E72-8C56-22887A519FA3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{20B75646-CBD2-4E72-8C56-22887A519FA3}.Debug|Any CPU.Build.0 = Debug|Any CPU
{20B75646-CBD2-4E72-8C56-22887A519FA3}.Release|Any CPU.ActiveCfg = Release|Any CPU
{20B75646-CBD2-4E72-8C56-22887A519FA3}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Expand All @@ -120,6 +132,8 @@ Global
{CF342B46-3B96-4270-8881-70FF105DE8E4} = {F5E59EDE-6E77-484C-AB93-C4651F43B9A7}
{F0DE9E2F-0E87-4C2C-875B-79547FD957D6} = {F5E59EDE-6E77-484C-AB93-C4651F43B9A7}
{AF019503-8813-4967-B858-0DDAE43C2073} = {F5E59EDE-6E77-484C-AB93-C4651F43B9A7}
{DF590535-2FDC-4A0A-9EE4-7C9BF818C7B4} = {F5E59EDE-6E77-484C-AB93-C4651F43B9A7}
{20B75646-CBD2-4E72-8C56-22887A519FA3} = {F5E59EDE-6E77-484C-AB93-C4651F43B9A7}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {09914DD8-50B2-48E3-B9AB-7764AE36AD6B}
Expand Down
8 changes: 4 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
### Using `test.mosquitto.org`

- Navigate to the Memory Monitor sample in `samples/memmon` and run it with `dotnet run` (or in Visual Studio hit `F5`). The console app will connect by default to `test.mosquitto.org:8886` (encrypted/no auth) by default.
- Browse to [https://iotmodels.github.io/pnp-mqtt](https://iotmodels.github.io/pnp-mqtt) and connect to `test.mosquitto.org:8081` (websockets, encrypted/no auth)
- Browse to [https://iotmodels.github.io/iotux-mqtt](https://iotmodels.github.io/iotux-mqtt) and connect to `test.mosquitto.org:8081` (websockets, encrypted/no auth)
- You should see a list of devices, select a device matching your machine name. Invoke the command, or change a property. The console application should show those changes.

![test.mosquitto.org](docs/tmo.gif)
Expand All @@ -28,7 +28,7 @@
- The same app can be executed with a local mosquitto server, you can use a pre-configured docker image like: [mosquitto-local](https://github.com/ridomin/mosquitto-local)
- Start mosquitto with `docker run -it --rm -p 8080:8080 -p 1883:1883 -p 8883:8883 -p 8884:8884 -p 8443:8443 ridomin/mosquitto-local:dev`
- Update the connection settings: `dotnet run /ConnectionSettings:cs="HostName=localhost;TcpPort=8883;ClientId=memmon-device;Username=user;Password=password;CaFile=RidoFY23CA.crt"`
- Connect [https://iotmodels.github.io/pnp-mqtt](https://iotmodels.github.io/pnp-mqtt) to `localhost:8443` to interact with your device
- Connect [https://iotmodels.github.io/iotux-mqtt](https://iotmodels.github.io/iotux-mqtt) to `localhost:8443` to interact with your device

### Using `Azure IoT Central`

Expand All @@ -53,7 +53,7 @@ Start from this [device-template](https://github.com/iotmodels/device-template/g
2. Create the base libraries to implement the DTDL interface for each cloud vendor. See the [Memory Monitor sample](samples/memmon/dtmi_rido_pnp_memmon-1.g.cs)
3. Implement the device logic, by using the interface, the device logic can be reused across different cloud vendor implementations. [Device Logic](samples/memmon/Device.cs)
4. Connect the device using different [Connection Settings](docs/ConnectionSettings.md)
5. Interact with the device with a DTDL enabled solution. Like [Azure IoT Central](https://www.azureiotcentral.com), [IoTExplorer](https://docs.microsoft.com/en-us/azure/iot-fundamentals/howto-use-iot-explorer) or [Pnp-Mqtt](https://iotmodels.github.io/pnp-mqtt/)
5. Interact with the device with a DTDL enabled solution. Like [Azure IoT Central](https://www.azureiotcentral.com), [IoTExplorer](https://docs.microsoft.com/en-us/azure/iot-fundamentals/howto-use-iot-explorer) or [Pnp-Mqtt](https://iotmodels.github.io/iotux-mqtt/)


## TL;DR;
Expand All @@ -69,7 +69,7 @@ This repo focuses on the first part: how to implement things/devices that can wo
- Commands. To invoke specific actions in the device from the solution, acka _c2d messages_
- Properties. To manage the device state, reported by the _device_ and optionally being managed from the _solution_. eg How often the telemetry must be sent. _d2c+c2d messages_

3. Enable solutions to reflect those _interaction patterns_ to create UI experiences, IoT Central, IoTExplorer or [Pnp-Mqtt](https://iotmodels.github.io/pnp-mqtt/) are examples of PnP enabled solutions.
3. Enable solutions to reflect those _interaction patterns_ to create UI experiences, IoT Central, IoTExplorer or [Pnp-Mqtt](https://iotmodels.github.io/iotux-mqtt/) are examples of PnP enabled solutions.

Read the [IoT Plug and Play convention](https://docs.microsoft.com/azure/iot-develop/overview-iot-plug-and-play) for more details.

Expand Down
36 changes: 0 additions & 36 deletions Scratch/Scratch.sln

This file was deleted.

35 changes: 35 additions & 0 deletions samples/iot-device/ClientHub.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
using MQTTnet.Client;
using MQTTnet.Extensions.MultiCloud;
using MQTTnet.Extensions.MultiCloud.AzureIoTClient.TopicBindings;
using MQTTnet.Extensions.MultiCloud.AzureIoTClient.Untyped;
using MQTTnet.Extensions.MultiCloud.BrokerIoTClient.Telemetry;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace iot_device
{
internal class ClientHub
{
TwinRequestResponseBinder rr;

public ITelemetry<double> Temperature;
public IReadOnlyProperty<string> SdkInfo;
public ICommand<string, string> Echo;
public IWritableProperty<int> Interval;

public ClientHub(IMqttClient c)
{
rr = new TwinRequestResponseBinder(c);
Temperature = new HubTelemetryUTF8Json<double>(c, "temp");
SdkInfo = new HubReadOnlyPropertyUTFJson<string>(c, "sdkInfo");
Echo = new HubCommandUTF8Json<string, string>(c, "echo");
Interval = new HubWritablePropertyUTFJson<int>(c, "interval");
}

internal async Task<string> GetTwinAsync(CancellationToken cancellationToken = default)
=> await rr.GetTwinAsync(cancellationToken);
}
}
21 changes: 21 additions & 0 deletions samples/iot-device/ClientMsgPack.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
using MQTTnet.Client;
using MQTTnet.Extensions.MultiCloud;
using MQTTnet.Extensions.MultiCloud.BrokerIoTClient.Command;
using MQTTnet.Extensions.MultiCloud.BrokerIoTClient.ReadOnlyProperty;
using MQTTnet.Extensions.MultiCloud.BrokerIoTClient.Telemetry;

namespace iot_device;

internal class ClientMsgPack
{
public ITelemetry<double> Temperature;
public IReadOnlyProperty<string> SdkInfo;
public ICommand<int, string> EchoRepeater;

public ClientMsgPack(IMqttClient c)
{
Temperature = new TelemetryMsgPack<double>(c, "temperature");
SdkInfo = new ReadOnlyPropertyMessagePack<string>(c, "sdkInfo");
EchoRepeater = new CommandMsgPack<int, string>(c, "echoRepeater");
}
}
25 changes: 25 additions & 0 deletions samples/iot-device/ClientProtobuff.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
using device_template_protos;
using MQTTnet.Client;
using MQTTnet.Extensions.MultiCloud;
using MQTTnet.Extensions.MultiCloud.BrokerIoTClient.Command;
using MQTTnet.Extensions.MultiCloud.BrokerIoTClient.ReadOnlyProperty;
using MQTTnet.Extensions.MultiCloud.BrokerIoTClient.Telemetry;
using MQTTnet.Extensions.MultiCloud.BrokerIoTClient.WritableProperty;

namespace iot_device;

internal class ClientProtobuff
{
public ITelemetry<Telemetries> Temperature;
public IReadOnlyProperty<Properties> SdkInfo;
public ICommand<echoRequest, echoResponse> Echo;
public IWritableProperty<Properties, ack> Interval;

public ClientProtobuff(IMqttClient c)
{
Temperature = new TelemetryProtobuff<Telemetries>(c, "temp");
SdkInfo = new ReadOnlyPropertyProtobuff<Properties>(c, "sdkInfo");
Echo = new CommandProtobuff<echoRequest, echoResponse>(c, "echo", echoRequest.Parser);
Interval = new WritablePropertyProtobuff<Properties, ack>(c, "interval", Properties.Parser);
}
}
24 changes: 24 additions & 0 deletions samples/iot-device/ClientUTF8Json.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
using MQTTnet.Client;
using MQTTnet.Extensions.MultiCloud;
using MQTTnet.Extensions.MultiCloud.BrokerIoTClient.Command;
using MQTTnet.Extensions.MultiCloud.BrokerIoTClient.ReadOnlyProperty;
using MQTTnet.Extensions.MultiCloud.BrokerIoTClient.Telemetry;
using MQTTnet.Extensions.MultiCloud.BrokerIoTClient.WritableProperty;

namespace iot_device;

internal class ClientUTF8Json
{
public ITelemetry<double> Temperature;
public IReadOnlyProperty<string> SdkInfo;
public ICommand<string, string> Echo;
public IWritableProperty<int> Interval;

public ClientUTF8Json(IMqttClient c)
{
Temperature = new TelemetryUTF8Json<double>(c, "temp");
SdkInfo = new ReadOnlyPropertyUTFJson<string>(c, "sdkInfo");
Echo = new CommandUTF8Json<string, string>(c, "echo");
Interval = new WritablePropertyUTFJson<int>(c, "interval");
}
}
76 changes: 76 additions & 0 deletions samples/iot-device/DeviceUtf8.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
using MQTTnet.Client;
using MQTTnet.Extensions.MultiCloud.AzureIoTClient;
using MQTTnet.Extensions.MultiCloud.Connections;

using device_template_protos;
using MQTTnet.Extensions.MultiCloud;
using MQTTnet.Extensions.MultiCloud.BrokerIoTClient;

namespace iot_device;

public class DeviceUtf8 : BackgroundService
{
private readonly ILogger<DeviceUtf8> _logger;
private readonly IConfiguration _configuration;

private IMqttClient? mqtt;

public DeviceUtf8(ILogger<DeviceUtf8> logger, IConfiguration configuration)
{
_logger = logger;
_configuration = configuration;
}


protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
ConnectionSettings cs = new(_configuration.GetConnectionString("cs") + ";ModelId=dtmi:com:example:DeviceTemplate;1");
mqtt = await BrokerClientFactory.CreateFromConnectionSettingsAsync(cs, true, stoppingToken);
//mqtt = await HubDpsFactory.CreateFromConnectionSettingsAsync(cs, stoppingToken);
_logger.LogInformation($"Connected {cs}");
var client = new ClientUTF8Json(mqtt!);

client.Interval.Value = 5;
await client!.SdkInfo.SendMessageAsync("my SDK testing hub");

client.Interval.OnMessage = async m =>
{
Ack<int> ack = new Ack<int>();
if (m > 0)
{
client.Interval.Value = m;
ack.Status = 200;
ack.Description = "property accepted";
ack.Value = m;
ack.Version = client.Interval.Version;
}
else
{
ack.Status = 403;
ack.Description = $"negative value ({m}) not accepted";
ack.Value = client.Interval.Value;
ack.Version = client.Interval.Version;
}
return await Task.FromResult(ack);
};

client.Echo.OnMessage = async m =>
{
string result = string.Empty;
for (int i = 0; i < 3; i++)
{
result += m;
}
return await Task.FromResult(result);
};

while (!stoppingToken.IsCancellationRequested)
{
await client.Temperature.SendMessageAsync(32.1);
_logger.LogInformation("Worker running at: {time}, enabled {enabled}", DateTimeOffset.Now, true);
await Task.Delay(client.Interval.Value * 1000, stoppingToken);
}
}


}
73 changes: 73 additions & 0 deletions samples/iot-device/DeviceprotoBuff.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
using MQTTnet.Client;

using MQTTnet.Extensions.MultiCloud.Connections;

using device_template_protos;
using MQTTnet.Extensions.MultiCloud.BrokerIoTClient;

namespace iot_device;

public class DeviceprotoBuff : BackgroundService
{
private readonly ILogger<DeviceprotoBuff> _logger;
private readonly IConfiguration _configuration;

private IMqttClient? mqtt;

public DeviceprotoBuff(ILogger<DeviceprotoBuff> logger, IConfiguration configuration)
{
_logger = logger;
_configuration = configuration;
}


protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
ConnectionSettings cs = new(_configuration.GetConnectionString("cs") + ";ModelId=device-template.proto");
mqtt = await BrokerClientFactory.CreateFromConnectionSettingsAsync(cs, true, stoppingToken);
_logger.LogInformation($"Connected {cs}");

var client = new ClientProtobuff(mqtt!);

client.Interval.Value = new Properties() { Interval = 5};
await client!.SdkInfo.SendMessageAsync(new Properties { SdkInfo = "my SDK"});

client.Interval.OnMessage = async m =>
{
ack ack = new ack(); //<int>(mqtt!, "interval");
if (m.Interval > 0)
{
client.Interval.Value = m;
ack.Status = 200;
ack.Description = "property accepted";
ack.Value = Google.Protobuf.WellKnownTypes.Any.Pack(m);
}
else
{
ack.Status = 403;
ack.Description = $"negative value ({m}) not accepted";
ack.Value = Google.Protobuf.WellKnownTypes.Any.Pack(client.Interval.Value);
}
return await Task.FromResult(ack);
};

client.Echo.OnMessage = async m =>
{
string result = "echo ";
for (int i = 0; i < 3; i++)
{
result += m.InEcho;
}
return await Task.FromResult(new echoResponse { OutEcho = result});
};

while (!stoppingToken.IsCancellationRequested)
{

await client.Temperature.SendMessageAsync(new Telemetries { Temp = 32.1});

_logger.LogInformation("Worker running at: {time}, enabled {enabled}", DateTimeOffset.Now, true);
await Task.Delay(client.Interval.Value.Interval * 1000, stoppingToken);
}
}
}
2 changes: 1 addition & 1 deletion samples/iot-device/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
IHost host = Host.CreateDefaultBuilder(args)
.ConfigureServices(services =>
{
services.AddHostedService<Device>();
services.AddHostedService<DeviceUtf8>();
})
.Build();

Expand Down
Loading