Skip to content

Commit

Permalink
Adjusting SDK not to embed certificate, adjusting for connection with…
Browse files Browse the repository at this point in the history
… a clean session (#2)
  • Loading branch information
Ellerbach committed Jul 5, 2021
1 parent cd95e68 commit d909946
Show file tree
Hide file tree
Showing 14 changed files with 167 additions and 228 deletions.
21 changes: 2 additions & 19 deletions Azure.Devices.DeviceClient/Azure.Devices.DeviceClient.nfproj
Original file line number Diff line number Diff line change
Expand Up @@ -35,11 +35,6 @@
<Compile Include="MethodCalback.cs" />
<Compile Include="DeviceClient.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Resources.Designer.cs">
<DesignTime>True</DesignTime>
<AutoGen>True</AutoGen>
<DependentUpon>Resources.resx</DependentUpon>
</Compile>
<Compile Include="Status.cs" />
<Compile Include="StatusUpdatedEventArgs.cs" />
<Compile Include="Twin.cs" />
Expand All @@ -49,13 +44,6 @@
</ItemGroup>
<ItemGroup>
<None Include="packages.config" />
<None Include="Resources\AzureRoot.der" />
</ItemGroup>
<ItemGroup>
<EmbeddedResource Include="Resources.resx">
<Generator>nFResXFileCodeGenerator</Generator>
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
</EmbeddedResource>
</ItemGroup>
<ItemGroup>
<Reference Include="mscorlib, Version=1.10.5.0, Culture=neutral, PublicKeyToken=c07d481e9758c731">
Expand All @@ -68,13 +56,8 @@
<Private>True</Private>
<SpecificVersion>True</SpecificVersion>
</Reference>
<Reference Include="nanoFramework.M2Mqtt, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null">
<HintPath>..\packages\nanoFramework.M2Mqtt.4.6.1-preview.89\lib\nanoFramework.M2Mqtt.dll</HintPath>
<Private>True</Private>
<SpecificVersion>True</SpecificVersion>
</Reference>
<Reference Include="nanoFramework.ResourceManager, Version=1.1.2.0, Culture=neutral, PublicKeyToken=c07d481e9758c731">
<HintPath>..\packages\nanoFramework.ResourceManager.1.1.2-preview.42\lib\nanoFramework.ResourceManager.dll</HintPath>
<Reference Include="nanoFramework.M2Mqtt, Version=5.0.0.0, Culture=neutral, PublicKeyToken=c07d481e9758c731">
<HintPath>..\packages\nanoFramework.M2Mqtt.5.0.0-preview.2\lib\nanoFramework.M2Mqtt.dll</HintPath>
<Private>True</Private>
<SpecificVersion>True</SpecificVersion>
</Reference>
Expand Down
95 changes: 51 additions & 44 deletions Azure.Devices.DeviceClient/DeviceClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@
using System.Text;
using System.Threading;
using System.Web;
using uPLibrary.Networking.M2Mqtt;
using uPLibrary.Networking.M2Mqtt.Messages;
using nanoFramework.M2Mqtt;
using nanoFramework.M2Mqtt.Messages;

namespace nanoFramework.Azure.Devices.Client
{
Expand Down Expand Up @@ -40,6 +40,7 @@ public class DeviceClient
private readonly ArrayList _waitForConfirmation = new ArrayList();
private readonly object _lock = new object();
private Timer _timerTokenRenew;
private readonly X509Certificate _azureRootCACert;

/// <summary>
/// Device twin updated event.
Expand All @@ -63,7 +64,8 @@ public class DeviceClient
/// <param name="deviceId">The device ID which is the name of your device.</param>
/// <param name="sasKey">One of the SAS Key either primary, either secondary.</param>
/// <param name="qosLevel">The default quality level delivery for the MQTT messages, default to the lower quality</param>
public DeviceClient(string iotHubName, string deviceId, string sasKey, byte qosLevel = MqttMsgBase.QOS_LEVEL_AT_MOST_ONCE)
/// <param name="azureCert">Azure certificate for the connection to Azure IoT Hub</param>
public DeviceClient(string iotHubName, string deviceId, string sasKey, MqttQoSLevel qosLevel = MqttQoSLevel.AtMostOnce, X509Certificate azureCert = null)
{
_clientCert = null;
_privateKey = null;
Expand All @@ -75,6 +77,7 @@ public DeviceClient(string iotHubName, string deviceId, string sasKey, byte qosL
_ioTHubStatus.Message = string.Empty;
_deviceMessageTopic = $"devices/{_deviceId}/messages/devicebound/";
QosLevel = qosLevel;
_azureRootCACert = azureCert;
}

/// <summary>
Expand All @@ -84,7 +87,8 @@ public DeviceClient(string iotHubName, string deviceId, string sasKey, byte qosL
/// <param name="deviceId">The device ID which is the name of your device.</param>
/// <param name="clientCert">The certificate to connect the device containing both public and private key.</param>
/// <param name="qosLevel">The default quality level delivery for the MQTT messages, default to the lower quality</param>
public DeviceClient(string iotHubName, string deviceId, X509Certificate2 clientCert, byte qosLevel = MqttMsgBase.QOS_LEVEL_AT_MOST_ONCE)
/// /// <param name="azureCert">Azure certificate for the connection to Azure IoT Hub</param>
public DeviceClient(string iotHubName, string deviceId, X509Certificate2 clientCert, MqttQoSLevel qosLevel = MqttQoSLevel.AtMostOnce, X509Certificate azureCert = null)
{
_clientCert = clientCert;
_privateKey = Convert.ToBase64String(clientCert.PrivateKey);
Expand All @@ -96,6 +100,7 @@ public DeviceClient(string iotHubName, string deviceId, X509Certificate2 clientC
_ioTHubStatus.Message = string.Empty;
_deviceMessageTopic = $"devices/{_deviceId}/messages/devicebound/";
QosLevel = qosLevel;
_azureRootCACert = azureCert;
}

/// <summary>
Expand All @@ -111,7 +116,7 @@ public DeviceClient(string iotHubName, string deviceId, X509Certificate2 clientC
/// <summary>
/// The default level quality.
/// </summary>
public byte QosLevel { get; set; }
public MqttQoSLevel QosLevel { get; set; }

/// <summary>
/// True if the device connected
Expand All @@ -124,18 +129,12 @@ public DeviceClient(string iotHubName, string deviceId, X509Certificate2 clientC
/// <returns></returns>
public bool Open()
{
// nanoFramework socket implementation requires a valid root CA to authenticate with.
// This can be supplied to the caller (as it's doing on the code bellow) or the Root CA has to be stored in the certificate store
// Root CA for Azure from here: https://github.com/Azure/azure-iot-sdk-c/blob/master/certs/certs.c
// We are storing this certificate in the resources
X509Certificate azureRootCACert = new X509Certificate(Resources.GetBytes(Resources.BinaryResources.AzureRoot));

// Creates MQTT Client with default port 8883 using TLS protocol
_mqttc = new MqttClient(
_iotHubName,
8883,
true,
azureRootCACert,
_azureRootCACert,
_clientCert,
MqttSslProtocols.TLSv1_2);

Expand All @@ -147,47 +146,51 @@ public bool Open()
_mqttc.ConnectionClosed += ClientConnectionClosed;

// Now connect the device
Reconnect();
string key = _clientCert == null ? GetSharedAccessSignature(null, _sasKey, $"{_iotHubName}/devices/{_deviceId}", new TimeSpan(24, 0, 0)) : _privateKey;
_mqttc.Connect(
_deviceId,
$"{_iotHubName}/{_deviceId}/api-version=2020-09-30",
key,
false,
MqttQoSLevel.ExactlyOnce,
false, "$iothub/twin/GET/?$rid=999",
"Disconnected",
true,
60
);

if (_mqttc.IsConnected)
{
_ioTHubStatus.Status = Status.Connected;
_ioTHubStatus.Message = string.Empty;
StatusUpdated?.Invoke(this, new StatusUpdatedEventArgs(_ioTHubStatus));
_mqttc.Subscribe(
new[] {
$"devices/{_deviceId}/messages/devicebound/#",
"$iothub/twin/#",
"$iothub/methods/POST/#"
$"devices/{_deviceId}/messages/devicebound/#",
"$iothub/twin/#",
"$iothub/methods/POST/#"
},
new[] {
MqttMsgBase.QOS_LEVEL_AT_LEAST_ONCE,
MqttMsgBase.QOS_LEVEL_AT_LEAST_ONCE,
MqttMsgBase.QOS_LEVEL_AT_LEAST_ONCE
MqttQoSLevel.AtLeastOnce,
MqttQoSLevel.AtLeastOnce,
MqttQoSLevel.AtLeastOnce
}
);

_ioTHubStatus.Status = Status.Connected;
_ioTHubStatus.Message = string.Empty;
StatusUpdated?.Invoke(this, new StatusUpdatedEventArgs(_ioTHubStatus));
// We will renew 10 minutes before just in case
_timerTokenRenew = new Timer(TimerCallbackReconnect, null, new TimeSpan(23, 50, 0), TimeSpan.MaxValue);
}

return _mqttc.IsConnected;
}

private void Reconnect()
/// <summary>
/// Reconnect to Azure Iot Hub
/// </summary>
public void Reconnect()
{
Close();
_mqttc.Connect(
_deviceId,
$"{_iotHubName}/{_deviceId}/api-version=2020-09-30",
_clientCert == null ? GetSharedAccessSignature(null, _sasKey, $"{_iotHubName}/devices/{_deviceId}", new TimeSpan(24, 0, 0)) : _privateKey,
false,
MqttMsgBase.QOS_LEVEL_EXACTLY_ONCE,
false, "$iothub/twin/GET/?$rid=999",
"Disconnected",
false,
60
);

// We will renew 10 minutes before just in case
_timerTokenRenew = new Timer(TimerCallbackReconnect, null, new TimeSpan(23, 50, 0), TimeSpan.MaxValue);
Open();
}

private void TimerCallbackReconnect(object state)
Expand All @@ -204,12 +207,16 @@ public void Close()
if (_mqttc.IsConnected)
{
_mqttc.Unsubscribe(new[] {
$"devices/{_deviceId}/messages/devicebound/#",
"$iothub/twin/#",
"$iothub/methods/POST/#"
$"devices/{_deviceId}/messages/devicebound/#",
"$iothub/twin/#",
"$iothub/methods/POST/#"
});
_mqttc.Disconnect();
// Make sure all get disconnected, cleared
Thread.Sleep(1000);
}

_timerTokenRenew.Dispose();
}

/// <summary>
Expand All @@ -222,7 +229,7 @@ public void Close()
public Twin GetTwin(CancellationToken cancellationToken = default)
{
_twinReceived = false;
_mqttc.Publish($"{TwinDesiredPropertiesTopic}?$rid={Guid.NewGuid()}", Encoding.UTF8.GetBytes(""), MqttMsgBase.QOS_LEVEL_AT_LEAST_ONCE, false);
_mqttc.Publish($"{TwinDesiredPropertiesTopic}?$rid={Guid.NewGuid()}", Encoding.UTF8.GetBytes(""), MqttQoSLevel.AtLeastOnce, false);

while (!_twinReceived && !cancellationToken.IsCancellationRequested)
{
Expand All @@ -242,7 +249,7 @@ public bool UpdateReportedProperties(TwinCollection reported, CancellationToken
{
string twin = reported.ToJson();
Debug.WriteLine($"update twin: {twin}");
var rid = _mqttc.Publish($"{TwinReportedPropertiesTopic}?$rid={Guid.NewGuid()}", Encoding.UTF8.GetBytes(twin), MqttMsgBase.QOS_LEVEL_AT_MOST_ONCE, false);
var rid = _mqttc.Publish($"{TwinReportedPropertiesTopic}?$rid={Guid.NewGuid()}", Encoding.UTF8.GetBytes(twin), MqttQoSLevel.AtLeastOnce, false);
_ioTHubStatus.Status = Status.TwinUpdated;
_ioTHubStatus.Message = string.Empty;
StatusUpdated?.Invoke(this, new StatusUpdatedEventArgs(_ioTHubStatus));
Expand Down Expand Up @@ -380,11 +387,11 @@ private void ClientMqttMsgReceived(object sender, MqttMsgPublishEventArgs e)
try
{
var res = mt.Invoke(rid, message);
_mqttc.Publish($"$iothub/methods/res/200/?$rid={rid}", Encoding.UTF8.GetBytes(res), MqttMsgBase.QOS_LEVEL_AT_LEAST_ONCE, false);
_mqttc.Publish($"$iothub/methods/res/200/?$rid={rid}", Encoding.UTF8.GetBytes(res), MqttQoSLevel.AtLeastOnce, false);
}
catch (Exception ex)
{
_mqttc.Publish($"$iothub/methods/res/504/?$rid={rid}", Encoding.UTF8.GetBytes($"{{\"Exception:\":\"{ex}\"}}"), MqttMsgBase.QOS_LEVEL_AT_LEAST_ONCE, false);
_mqttc.Publish($"$iothub/methods/res/504/?$rid={rid}", Encoding.UTF8.GetBytes($"{{\"Exception:\":\"{ex}\"}}"), MqttQoSLevel.AtLeastOnce, false);
}
}
}
Expand Down
38 changes: 0 additions & 38 deletions Azure.Devices.DeviceClient/Resources.Designer.cs

This file was deleted.

Loading

0 comments on commit d909946

Please sign in to comment.