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

Validate 0.4 #64

Merged
merged 7 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: 4 additions & 0 deletions .editorconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
[*.cs]

# CS0067: The event 'MockMqttClient.ConnectedAsync' is never used
dotnet_diagnostic.CS0067.severity = silent
3 changes: 2 additions & 1 deletion MQTTnet.Extensions.MultiCloud.sln
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "_actions", "_actions", "{68
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{F618E3CF-0552-44BD-A92A-A926AF319D00}"
ProjectSection(SolutionItems) = preProject
.editorconfig = .editorconfig
.runsettings = .runsettings
.runsettings.template = .runsettings.template
src\Directory.Build.props = src\Directory.Build.props
Expand All @@ -58,7 +59,7 @@ 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}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "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
Expand Down
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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/iotux-mqtt/) are examples of PnP enabled solutions.
3. Enable solutions to reflect those _interaction patterns_ to create UI experiences, IoT Central, IoTExplorer or [iotux-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 Expand Up @@ -128,7 +128,7 @@ Read and Update the Device Twin:

```cs
var twin = await client.GetTwinAsync(stoppingToken);
var version = await client.ReportPropertyAsync(new { started = DateTime.Now });
var version = await client.UpdateTwinAsync(new { started = DateTime.Now });
```

Properties Updates (aka Writable Properties) handling:
Expand Down Expand Up @@ -218,7 +218,7 @@ public class memmon : AwsMqttClient, Imemmon
For any MQTT compatible broker

```cs
public class memmon : PnPMqttClient, Imemmon
public class memmon : Imemmon
```

### X509 Support
Expand Down
2 changes: 1 addition & 1 deletion docs/ConnectionSettings.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ Connection settings can be established using the API or parsing a connection str
- `SharedAccessKey` Device Shared Access Key
- `SasMinutes` SasToken expire time in minutes, default to `60`.
- `X509Key` __pathtopfx>|<pfxpassword__ see details in [X509Certificates](X509Certificates.md)
- `ModelId` DTDL Model ID in DTMI format to create PnP Devices
- `ModelId` DTDL Model ID in DTMI/Proto format to indicate the model the device implements
- `ModuleId` IoTHub Device Module Identity
- `UserName` Username to be used to authenticate with MQTT Brokers
- `Password` Username to be used to authenticate with MQTT Brokers
Expand Down
1 change: 0 additions & 1 deletion samples/iothub-sample/Device.cs
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,6 @@ protected override async Task ExecuteAsync(CancellationToken stoppingToken)
client.OnPropertyUpdateReceived = m =>
{
Console.WriteLine(m.ToString());

return new GenericPropertyAck
{
Value = m.ToJsonString(),
Expand Down
2 changes: 1 addition & 1 deletion samples/mqtt-grpc-device/mqtt-grpc-device.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
<TargetFramework>net6.0</TargetFramework>
<Nullable>enable</Nullable>
<RootNamespace>mqtt_grpc_device</RootNamespace>
<IsPackable>false</IsPackable>
<IsPackable>false</IsPackable>
</PropertyGroup>

<ItemGroup>
Expand Down
23 changes: 11 additions & 12 deletions samples/payload-size/AvroDeviceClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,18 @@
using MQTTnet.Extensions.MultiCloud;
using MQTTnet.Extensions.MultiCloud.BrokerIoTClient;

namespace payload_size
namespace payload_size;

internal class AvroDeviceClient
{
internal class AvroDeviceClient
{
internal ITelemetry<avros.Telemetries> Telemetry { get; set; }
internal IReadOnlyProperty<avros.Properties> Props { get; set; }
internal IReadOnlyProperty<avros.Properties> Prop_SdkInfo { get; set; }
internal ITelemetry<avros.Telemetries> Telemetry { get; set; }
internal IReadOnlyProperty<avros.Properties> Props { get; set; }
internal IReadOnlyProperty<avros.Properties> Prop_SdkInfo { get; set; }

public AvroDeviceClient(IMqttClient mqtt)
{
Telemetry = new TelemetryAvro<avros.Telemetries>(mqtt, new avros.Telemetries().Schema);
Props = new ReadOnlyPropertyAvro<avros.Properties>(mqtt, new avros.Properties().Schema);
Prop_SdkInfo = new ReadOnlyPropertyAvro<avros.Properties>(mqtt, new avros.Properties().Schema) { NameInTopic = true };
}
public AvroDeviceClient(IMqttClient mqtt)
{
Telemetry = new TelemetryAvro<avros.Telemetries>(mqtt, new avros.Telemetries().Schema);
Props = new ReadOnlyPropertyAvro<avros.Properties>(mqtt, new avros.Properties().Schema);
Prop_SdkInfo = new ReadOnlyPropertyAvro<avros.Properties>(mqtt, new avros.Properties().Schema) { NameInTopic = true };
}
}
22 changes: 10 additions & 12 deletions samples/payload-size/ProtoDeviceClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,17 @@
using MQTTnet.Extensions.MultiCloud;
using MQTTnet.Extensions.MultiCloud.BrokerIoTClient;

namespace payload_size
namespace payload_size;
internal class ProtoDeviceClient
{
internal class ProtoDeviceClient
{
internal ITelemetry<proto_model.Telemetries> Telemetry { get; set; }
internal IReadOnlyProperty<proto_model.Properties> Props { get; set; }
internal IReadOnlyProperty<proto_model.Properties> Prop_SdkInfo { get; set; }
internal ITelemetry<proto_model.Telemetries> Telemetry { get; set; }
internal IReadOnlyProperty<proto_model.Properties> Props { get; set; }
internal IReadOnlyProperty<proto_model.Properties> Prop_SdkInfo { get; set; }

public ProtoDeviceClient(IMqttClient mqtt)
{
Telemetry = new TelemetryProtobuff<proto_model.Telemetries>(mqtt);
Props = new ReadOnlyPropertyProtobuff<proto_model.Properties>(mqtt);
Prop_SdkInfo = new ReadOnlyPropertyProtobuff<proto_model.Properties>(mqtt) { NameInTopic = true };
}
public ProtoDeviceClient(IMqttClient mqtt)
{
Telemetry = new TelemetryProtobuff<proto_model.Telemetries>(mqtt);
Props = new ReadOnlyPropertyProtobuff<proto_model.Properties>(mqtt);
Prop_SdkInfo = new ReadOnlyPropertyProtobuff<proto_model.Properties>(mqtt) { NameInTopic = true };
}
}
2 changes: 1 addition & 1 deletion samples/payload-size/payload-size.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
<RootNamespace>payload_size</RootNamespace>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<IsPackable>false</IsPackable>
<IsPackable>false</IsPackable>
</PropertyGroup>

<ItemGroup>
Expand Down
14 changes: 7 additions & 7 deletions src/MQTTnet.Extensions.MultiCloud.AwsIoTClient/AwsMqttClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,17 +11,17 @@ public class AwsMqttClient
{
public IMqttClient Connection { get; private set; }
private readonly ShadowRequestResponseBinder getShadowBinder;


public AwsMqttClient(IMqttClient c, string modelId = "") //: base(c)
{
Connection = c;
var birthMsg =
var birthMsg =
new UTF8JsonSerializer().ToBytes(
new BirthConvention.BirthMessage(BirthConvention.ConnectionStatus.online)
{
ModelId = modelId
});
{
ModelId = modelId
});
_ = Connection.PublishBinaryAsync(
BirthConvention.BirthTopic(Connection.Options.ClientId),
birthMsg,
Expand All @@ -30,9 +30,9 @@ public AwsMqttClient(IMqttClient c, string modelId = "") //: base(c)
getShadowBinder = new ShadowRequestResponseBinder(c);
}

public Task<string> GetShadowAsync(CancellationToken cancellationToken = default) =>
public Task<string> GetShadowAsync(CancellationToken cancellationToken = default) =>
getShadowBinder.GetShadowAsync(cancellationToken);
public Task<string> UpdateShadowAsync(object payload, CancellationToken cancellationToken = default) =>
public Task<string> UpdateShadowAsync(object payload, CancellationToken cancellationToken = default) =>
getShadowBinder.UpdateShadowAsync(payload, cancellationToken);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@
<TargetFramework>net6.0</TargetFramework>
<Nullable>enable</Nullable>
<Title>AWS IoT Core client base don MQTTnet</Title>
<Description>Provides base APIs to create MQTT PnP clients for AWS Iot Core</Description>
<PackageTags>mqtt; aws iot core; pnp</PackageTags>
<Description>Provides base APIs to create MQTT clients for AWS IoT Core</Description>
<PackageTags>mqtt; aws iot core</PackageTags>
<PackageIcon>iotpnp-128.png</PackageIcon>
</PropertyGroup>

Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,6 @@
using MQTTnet.Client;
using MQTTnet.Extensions.MultiCloud.Binders;
using MQTTnet.Extensions.MultiCloud.Serializers;
using System;
using System.Text.Json;
using System.Text.Json.Nodes;
using System.Threading;
using System.Threading.Tasks;

namespace MQTTnet.Extensions.MultiCloud.AwsIoTClient.TopicBindings
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@
using System.Collections.Concurrent;
using System.Diagnostics;
using System.Text;
using System.Threading.Tasks;
using System.Threading;
using System.Threading.Tasks;
using System.Web;

namespace MQTTnet.Extensions.MultiCloud.AwsIoTClient.TopicBindings;
Expand All @@ -17,8 +17,8 @@ public class ShadowRequestResponseBinder
private readonly ConcurrentDictionary<int, TaskCompletionSource<string>> pendingGetshadowRequests = new();
public Func<string, Task<string>>? OnMessage { get; set; }

readonly IMqttClient connection;
readonly string topicBase = String.Empty;
private readonly IMqttClient connection;
private readonly string topicBase = String.Empty;
public ShadowRequestResponseBinder(IMqttClient connection)
{
this.connection = connection;
Expand All @@ -28,7 +28,7 @@ public ShadowRequestResponseBinder(IMqttClient connection)
connection.ApplicationMessageReceivedAsync += async m =>
{
await Task.Yield();

var topic = m.ApplicationMessage.Topic;
if (topic.StartsWith(topicBase + "/+/accepted"))
{
Expand Down Expand Up @@ -111,15 +111,15 @@ public async Task<string> UpdateShadowAsync(object payload, CancellationToken ca


[DebuggerStepThrough()]
static class RidCounter
private static class RidCounter
{
private static int counter = 0;
internal static int Current => counter;
internal static int NextValue() => Interlocked.Increment(ref counter);
internal static void Reset() => counter = 0;
}

class TopicParser
private class TopicParser
{
internal static (int rid, int shadowVersion) ParseTopic(string topic)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,6 @@ public interface IHubMqttClient
Task<string> GetTwinAsync(CancellationToken cancellationToken = default);
Task<int> UpdateTwinAsync(object payload, CancellationToken cancellationToken = default);
Task<MqttClientPublishResult> SendTelemetryAsync(object payload, CancellationToken t = default);

}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@
<Description>Implements basic Azure IoT Hub primitives, including:
SaS and X509 Auth, Telemetry, Properties and Commands.

Provides an API surface to implement IoT PnP Devices.</Description>
<PackageTags>mqtt; azure-iot; pnp; dtdl</PackageTags>
Provides an API surface to implement IoT Devices using MQTT.</Description>
<PackageTags>mqtt; azure-iot; dtdl</PackageTags>
<PackageIcon>iotpnp-128.png</PackageIcon>
</PropertyGroup>

Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,7 @@
using MQTTnet.Client;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Text.Json;
using System.Text.Json.Nodes;
using System.Threading.Tasks;

namespace MQTTnet.Extensions.MultiCloud.AzureIoTClient
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -89,11 +89,20 @@ public async Task<string> GetTwinAsync(CancellationToken cancellationToken = def
public async Task<int> UpdateTwinAsync(object payload, CancellationToken cancellationToken = default)
{
await connection.SubscribeWithReplyAsync("$iothub/twin/res/#");
var rid = RidCounter.NextValue();

byte[] patchBytes;
if (payload is string)
{
patchBytes = Encoding.UTF8.GetBytes((string)payload);
}
else
{
patchBytes = new UTF8JsonSerializer().ToBytes(payload);
}

var rid = RidCounter.NextValue();
var puback = await connection.PublishBinaryAsync(
$"$iothub/twin/PATCH/properties/reported/?$rid={rid}",
new UTF8JsonSerializer().ToBytes(payload),
patchBytes,
MqttQualityOfServiceLevel.AtMostOnce,
false,
cancellationToken);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ public GenericDesiredUpdatePropertyBinder(IMqttClient c, TwinRequestResponseBind
var ack = OnProperty_Updated(desired);
if (ack != null)
{
//_ = updTwinBinder.ReportPropertyAsync(ack.BuildAck());
_ = updTwinBinder.UpdateTwinAsync(ack.BuildAck());
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ public WritableProperty(IMqttClient c, string name)
: base(c, name)
{
TopicTemplate = "$iothub/twin/PATCH/properties/desired/#";
ResponseTopic = "$iothub/twin/PATCH/properties/reported/?$rid={rid}&version={version}";
ResponseTopic = "$iothub/twin/PATCH/properties/reported/?$rid={rid}&$version={version}";
UnwrapRequest = true;
WrapResponse = true;
PreProcessMessage = tp =>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,5 @@
using MQTTnet.Client;
using MQTTnet.Extensions.MultiCloud.Connections;
using System;
using System.Text.Json;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using MQTTnet.Extensions.MultiCloud.Serializers;

namespace MQTTnet.Extensions.MultiCloud.BrokerIoTClient
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
using MQTTnet.Client;
using MQTTnet.Extensions.MultiCloud.Binders;
using MQTTnet.Extensions.MultiCloud.Serializers;

namespace MQTTnet.Extensions.MultiCloud.BrokerIoTClient;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@
<TargetFramework>net6.0</TargetFramework>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
<Title>MQTT PnP Client based on MQTTnet</Title>
<Description>Base APIs to create PnP Clients to work with any complaiant MQTT Broker</Description>
<Title>MQTT Client based on MQTTnet</Title>
<Description>Base APIs to create MQTT Clients to work with any complaiant MQTT Broker</Description>
<PackageIcon>iotpnp-128.png</PackageIcon>
</PropertyGroup>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ public class ReadOnlyProperty<T> : DeviceToCloudBinder<T>, IReadOnlyProperty<T>
{

public ReadOnlyProperty(IMqttClient mqttClient) : this(mqttClient, string.Empty) { }
public ReadOnlyProperty(IMqttClient mqttClient, string name)
public ReadOnlyProperty(IMqttClient mqttClient, string name)
: base(mqttClient, name)
{
TopicPattern = "device/{clientId}/props/{name}";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,10 @@ namespace MQTTnet.Extensions.MultiCloud.BrokerIoTClient;

public class ReadOnlyPropertyAvro<T> : DeviceToCloudBinder<T>, IReadOnlyProperty<T>
{
public ReadOnlyPropertyAvro(IMqttClient mqttClient, Schema schema)
public ReadOnlyPropertyAvro(IMqttClient mqttClient, Schema schema)
: this(mqttClient, string.Empty, schema) { }

public ReadOnlyPropertyAvro(IMqttClient mqttClient, string name, Schema schema)
public ReadOnlyPropertyAvro(IMqttClient mqttClient, string name, Schema schema)
: base(mqttClient, name, new AvroSerializer(schema))
{
TopicPattern = "device/{clientId}/props";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ public class ReadOnlyPropertyProtobuff<T> : DeviceToCloudBinder<T>, IReadOnlyPro
{
public ReadOnlyPropertyProtobuff(IMqttClient mqttClient) : this(mqttClient, string.Empty) { }

public ReadOnlyPropertyProtobuff(IMqttClient mqttClient, string name)
public ReadOnlyPropertyProtobuff(IMqttClient mqttClient, string name)
: base(mqttClient, name, new ProtobufSerializer())
{
TopicPattern = "device/{clientId}/props";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,9 @@ namespace MQTTnet.Extensions.MultiCloud.BrokerIoTClient;

public class TelemetryAvro<T> : DeviceToCloudBinder<T>, ITelemetry<T>
{
public TelemetryAvro(IMqttClient mqttClient, Schema schema) :
this(mqttClient, string.Empty, schema) { }
public TelemetryAvro(IMqttClient mqttClient, Schema schema) :
this(mqttClient, string.Empty, schema)
{ }

public TelemetryAvro(IMqttClient mqttClient, string name, Schema schema)
: base(mqttClient, name, new AvroSerializer(schema))
Expand Down
Loading