#IoT Device Provisioning Example with Send/Receive Messages

1 messages · Page 1 of 1 (latest)

keen skiff
#

Can someone point me to the correct examples where I can see an IoT device being provisioned and then messages being sent and received? The provisioning examples only show the device being provisioned and not communicating with the IoT Hub.

fresh geyser
#

There a bunch of IoT Hub samples there. And some examples on the repo readme too. I'm pretty sure that is covered there...

desert yarrow
keen skiff
# fresh geyser There a bunch of IoT Hub samples there. And some examples on the repo readme too...

Hi Jose,

I am currently struggling with the provisioning part, as it keeps failing. I want to make sure I am inputting the correct values. I am trying to use the DPS example.

Should we use the Global device endpoint instead of the Service endpoint (which includes my domain name)?
The ID Scope is obtained from the portal.

I plan to use the group enrolment option, as the aim is to have a key that allows my device to connect based on the firmware. However, when it comes to:

const string SasKey = "alongkeyencodedbase64"

Do I simply obtain this from the portal? If so, which field should I use?
Do I need to perform any additional steps (for example, deriving a device key), or can I use it directly?

I also have attached root certs i am using for your refernce.

Thanks.

keen skiff
#

Yes, but that is for individual enrollment, meaning I would need to do this for each device individually? We could have batches of 100 devices so the reason for grouping is that it would unessarily time consuming to do this for each device.

#

So does the libary support group enrollement?

desert yarrow
#

ok, so, here is the high level:

#

for each device, you need to compute the key with something like:

device_key = HMAC-SHA256(
    decoded_group_key,
    registration_id
)
  • Result is Base64‑encoded
  • That derived key is what the device uses for SAS authentication
  • DPS validates it by recomputing the same value (see the previous link where it's explained)
#

Each device only needs:

  • Scope ID (from DPS)
  • Registration ID (unique per device)
  • Derived device key (the one you've processed)
    No IoT Hub hostname or device ID is required up front (DPS handles that).
#

You can flash each device with a config file in the internal storage with the 3 needed elements. Computing the key is easy and can be done at flash time (script, small C# code) and you can use nanoff to deploy the config file

#

The IoT Hub and the device ID and key will be given by DPS so that then you can connect

#

That's about it 🙂 Thanks for giving me the opportunity to refresh my memory 🙂

#

Note: I really don't recommend you to flash the master key on the device and do the computation here. It's risky as if that one get stolen or lost, you can enrol almost any device with it or mess up your system. That's one of the reason, DPS only accept a derivative key that it can recompute.

keen skiff
#

Thanks
This is how i am computing my key.

private static string ComputeDeviceKey(string groupPrimaryKeyBase64, string registrationId) { byte[] groupKey = Convert.FromBase64String(groupPrimaryKeyBase64); var hmac = new HMACSHA256(groupKey); byte[] deviceKey = hmac.ComputeHash( Encoding.UTF8.GetBytes(registrationId)); return Convert.ToBase64String(deviceKey); }

keen skiff
#

I checked my device key being generated against the examples using PowerShell
And they are identical, so I think the keys are correct, but I am getting these exceptions:

++++ Exception System.Net.Sockets.SocketException - CLR_E_FAIL (4) ++++ ++++ Message: ++++ System.Net.Security.SslNative::SecureConnect [IP: 0000] ++++ ++++ System.Net.Security.SslStream::Authenticate [IP: 0054] ++++ ++++ System.Net.Security.SslStream::AuthenticateAsClient [IP: 000a] ++++ ++++ nanoFramework.M2Mqtt.MqttNetworkChannel::Connect [IP: 0063] ++++ ++++ nanoFramework.Azure.Devices.Provisioning.Client.ProvisioningDeviceClient::.ctor [IP: 008f] ++++ ++++ nanoFramework.Azure.Devices.Provisioning.Client.ProvisioningDeviceClient::Create [IP: 000a] ++++ ++++ BluetoothLESerial.azureiothub::TryProvisionDevice [IP: 00b5] ++++ ++++ BluetoothLESerial.azureiothub::WorkerLoop [IP: 0098] ++++ ++++ Exception nanoFramework.M2Mqtt.Exceptions.MqttConnectionException - 0x00000000 (4) ++++ ++++ Message: Socket exception connecting to the broker: -9984 ++++ nanoFramework.M2Mqtt.MqttClient::Connect [IP: 0049] ++++ ++++ nanoFramework.Azure.Devices.Provisioning.Client.ProvisioningDeviceClient::.ctor [IP: 008f] ++++ ++++ nanoFramework.Azure.Devices.Provisioning.Client.ProvisioningDeviceClient::Create [IP: 000a] ++++ ++++ BluetoothLESerial.azureiothub::TryProvisionDevice [IP: 00b5] ++++ ++++ BluetoothLESerial.azureiothub::WorkerLoop [IP: 0098] ++++ Exception thrown: 'nanoFramework.M2Mqtt.Exceptions.MqttConnectionException' in nanoFramework.M2Mqtt.dll

keen skiff
fresh geyser
#

@keen skiff the above looks like an issue with the root CA. A couple of suggestions: either use the one included in the Azure SDK, or if you're using another, make sure to test it with a plain simple app (like the SSL in samples repo) connecting to an Azure IoT endpoint just to check the connection (and validate the SSL negotiation).

keen skiff
#

I believe we just need to use DigiCert Global Root G2. I will copy the file content from the sample to see if it makes a difference. Is it possible to disable the root certificate check for testing purposes?

#

It seems the samples have Baltimore CyberTrust Root and DigiCert Global Root G2

I believe DigiCert Global Root G2 should be sufficient. I have attached what i am using

fresh geyser
#

@keen skiff have you tested with a sample app as I've suggested above?

keen skiff
#

Just trying, it uses

X509Certificate2 deviceCert = new X509Certificate2(cert, privateKey, "1234");

Where else my required projects require the group, I was using
_deviceKey = ComputeDeviceKey(GroupPrimaryKey, RegistrationID);

I believe the sample using X509?

So for my _deviceKey? Do i need to do anything in perticualr?

fresh geyser
#

I suggest you focus on one issue at a time. 😅
Either root CA or computing the device key...

keen skiff
#

Ok, so which example would you recommend I start with? Regardless of the authentication method, I still need the root certificate, which is DigiCert Global Root G2. However, it seems the DPS example requires us to provide our own X.509 certificate, so I will need to look at how I can generate my own key and certificate.

#

I have never used 509 certs so will need to check how to use to create it

fresh geyser
#

From the above I think we're not on the same page....
My previous answers were related with the root CA cert to CONNECT to Azure endpoint.

#

If you're looking for a cert to sign the device keys, that's a totally different story.

keen skiff
#

My issue seems to be failing at this point:

provisioning = ProvisioningDeviceClient.Create( DpsAddress, IdScope, RegistrationID, _deviceKey, _azureCA); }

desert yarrow
keen skiff
#

This is the Global G2 cert?

#

First of all, does this library support group provisioning, as there seem to be no examples of with the Nano Framework? This worked with free rtos example in C, so was trying to replicate this

#

I just tried Individual enrollment, same issue, so how can I check that the cert i am applying is correct? Are there any debug changes I can do? Should the sting include
-----BEGIN CERTIFICATE-----

fresh geyser
#

Yes, that has to be there. You just grab the certificate content and paste it as it is. Don't mess with it.

#

Still, if your issue is with System.Net.Security.SslStream::Authenticate I strongly suggest that you "debug" the certificate with the SSL sample app has I've recomended

keen skiff
#

Yes, i am just using the following process:
string pem = Properties.Resources.GetString(
Properties.Resources.StringResources.DigiCertGlobalRootG2);

Which example app did you recomend, was this independent from the Azure IoT examples?

fresh geyser
#

SSL sample in the Samples repo

keen skiff
#

great thank i will check it out

desert yarrow
#

CA Certs can be specific to your DPS, just read the doc and check which one is the right one.

keen skiff
#

i think you are correct. for some reason my when i check the string and the object its referring to the old Baltimore Cyber Trust cert which is now expired. I have made sure the project includes on the G2 cert, but it seems it not being loaded.

Can it be that the old certs are being cached some how in project?

Maybe i need to delete a file manually?

fresh geyser
#

certs aren't cached in the project

#

if you feel better, manually delete bin and obj folders

keen skiff
#

ok let me try

fresh geyser
#

and yes Baltimore should not be used anymore

keen skiff
#

For some reason, when I run the SSL projects, it corrupts something on my device, where i need to reflash the ESp32. I expirmenting with connecting with Azure IoT Hub using basic methods

indigo sorrel
keen skiff
#

Ok will give that ago.

#

I am still having issues with SSL.
I am placing my Cert as a string variable instead.

 `   private const string AzureRootCertPem ="MIID ...=";

Then calling:
_azureIoT = new DeviceClient(
IotBrokerAddress,
DeviceID,
SasKey,
azureCert: new X509Certificate(cert));

  bool ok = _azureIoT.Open();

`

Then i am getting:

[AzureBasic] Opening connection... ++++ Exception System.Exception - CLR_E_FAIL (1) ++++ ++++ Message: ++++ System.Convert::FromBase64String [IP: 0000] ++++ ++++ nanoFramework.Azure.Devices.Helper::GetSharedAccessSignature [IP: 0021] ++++ ++++ nanoFramework.Azure.Devices.Client.DeviceClient::Open [IP: 0099] ++++ ++++ BluetoothLESerial.AzureIotHubBasic::Start [IP: 0044] ++++ ++++ BluetoothLESerial.Program::Main [IP: 014f] ++++ Exception thrown: 'System.Exception' in mscorlib.dll [AzureBasic] Start failed: Exception was thrown: System.Exception

Is there anything additional I can do for debugging to see what is causing this?

#

When I try to run the TLS project ParseCertificate and run the code, it seems to be just running my actual application. For some reason, it is as if I can not overwrite the previous project. Am I missing a step?

keen skiff
#

Also, how can I confirm that my date and time are also set correctly?

#

Out of curosity, is it possible to connect wire shark to modules to see what is happening or what points its failing?

desert yarrow
#

Just use debug and breakpoint and you will see what is happening.

#

All this is perfectly working. I have some devices connecting like this to IoT hub. The sample is based on this.

keen skiff
#

Ok, for example, if we want to see what is happening inside, I can not place a breakpoint inside the compiled functions.

_azureIoT = new DeviceClient( IotBrokerAddress, DeviceID, SasKey, azureCert: new X509Certificate(cert)); bool ok = _azureIoT.Open();

I am trying to connect using the basic method. My device ID is a valid ID, the SAS key is valid for a week, and the cert is GIgiG2. I don't use a client cert, but just the root cert.

Additionally, is there any issue with the library version I need to keep in mind?

indigo sorrel
#

If there is a dependency mismatch on the library version then you will not be able to deploy (error during deployment proccess).

keen skiff
#

ok

#

How do i add a break point inside actuall libary, to see the point it fails, is this possible?

indigo sorrel
#

Possible but you need to download the source code of the libary then add it to you project and add the reference to that library project. Remember to remove the nuget of that library from your project.

keen skiff
#

I am using ESp32-s3, would that have any reflection on what is happenong

indigo sorrel
#

Default official firmware has reflection enabled.

keen skiff
#

ok

#

At the moment i am just depending on the output display in VS if i was to use the direct COM port, can i get more information on what's happening?

indigo sorrel
#

baudrate 115200 you see the RTOS boot message, at 912600 you see the Debug.WriteLine and Console.WriteLine messages. Debug.WriteLine will not appear in release mode app.

keen skiff
#

So it the RTOS that i need to read, as Debug.Write, i Can already see it?

Just to confirm these are the packeges i am using:

Are these correct? As i have M2Mqtt and M2Mqtt.Core.

Just want to make sure there is no clash with libaries or any compatability issues?

#

<packages> <package id="nanoFramework.Azure.Devices.Client" version="1.2.107" targetFramework="netnano1.0" /> <package id="nanoFramework.CoreLibrary" version="1.17.11" targetFramework="netnano1.0" /> <package id="nanoFramework.Device.Bluetooth" version="1.1.115" targetFramework="netnano1.0" /> <package id="nanoFramework.Hardware.Esp32" version="1.6.37" targetFramework="netnano1.0" /> <package id="nanoFramework.Json" version="2.2.203" targetFramework="netnano1.0" /> <package id="nanoFramework.M2Mqtt" version="5.1.209" targetFramework="netnano1.0" /> <package id="nanoFramework.M2Mqtt.Core" version="5.1.209" targetFramework="netnano1.0" /> <package id="nanoFramework.Networking.Sntp" version="1.6.42" targetFramework="netnano1.0" /> <package id="nanoFramework.ResourceManager" version="1.2.32" targetFramework="netnano1.0" /> <package id="nanoFramework.Runtime.Events" version="1.11.32" targetFramework="netnano1.0" /> <package id="nanoFramework.Runtime.Native" version="1.7.11" targetFramework="netnano1.0" /> <package id="nanoFramework.System.Collections" version="1.5.67" targetFramework="netnano1.0" /> <package id="nanoFramework.System.Device.Wifi" version="1.5.139" targetFramework="netnano1.0" /> <package id="nanoFramework.System.IO.Streams" version="1.1.96" targetFramework="netnano1.0" /> <package id="nanoFramework.System.Math" version="1.5.116" targetFramework="netnano1.0" /> <package id="nanoFramework.System.Net" version="1.11.50" targetFramework="netnano1.0" /> <package id="nanoFramework.System.Net.Http" version="1.5.200" targetFramework="netnano1.0" /> <package id="nanoFramework.System.Text" version="1.3.42" targetFramework="netnano1.0" /> <package id="nanoFramework.System.Threading" version="1.1.52" targetFramework="netnano1.0" /> </packages>

desert yarrow
#

what message do you get when you debug with Visual Studio?

indigo sorrel
keen skiff
# desert yarrow what message do you get when you debug with Visual Studio?

This is output i am getting when i try to open a connection:

[NET] Online: 192.168.1.187 DNS OK -> 51.104.30.143
[SNTP] Started, waiting for time sync...
[SNTP] Final UTC time = 04/10/2026 09:23:08
[AzureBasic] Creating DeviceClient...
[AzureBasic] Opening connection...
++++ Exception System.Net.Sockets.SocketException - CLR_E_FAIL (1) ++++
++++ Message:
++++ System.Net.Security.SslNative::SecureConnect [IP: 0000] ++++
++++ System.Net.Security.SslStream::Authenticate [IP: 0054] ++++
++++ System.Net.Security.SslStream::AuthenticateAsClient [IP: 000a] ++++
++++ nanoFramework.M2Mqtt.MqttNetworkChannel::Connect [IP: 0098] ++++
++++ nanoFramework.Azure.Devices.Client.DeviceClient::Open [IP: 00b6] ++++
++++ BluetoothLESerial.AzureIotHubBasic::Start [IP: 0046] ++++
++++ BluetoothLESerial.Program::Main [IP: 014f] ++++
++++ Exception nanoFramework.M2Mqtt.Exceptions.MqttConnectionException - 0x00000000 (1) ++++
++++ Message: Socket exception connecting to the broker: -29312
++++ nanoFramework.M2Mqtt.MqttClient::Connect [IP: 0049] ++++
++++ nanoFramework.Azure.Devices.Client.DeviceClient::Open [IP: 00b6] ++++
++++ BluetoothLESerial.AzureIotHubBasic::Start [IP: 0046] ++++
++++ BluetoothLESerial.Program::Main [IP: 014f] ++++
Exception thrown: 'nanoFramework.M2Mqtt.Exceptions.MqttConnectionException' in nanoFramework.M2Mqtt.dll

keen skiff
indigo sorrel
#

no, serial terminal is only necessary to see if the MCU is doing a boot loop.

#

It looks like you have a socket error. First is the dateTime correct on the MCU (date time is in UTC). second is your CA cert valid and the correct one.

desert yarrow
#

Cert or key issue.

keen skiff
#

I am confident the SAS and root cert is correct , as this what i am using for other devices and it working.

But i am declaring them as strings.

Is there any other way to verify they are formated correctly before i call an OPEN

fresh geyser
#

@keen skiff I'll ask this one last time: have you validated the root CA with the sample client app connecting an Azure endpoint?

keen skiff
#

Well the SSL example projects, is not able to run, it just stops loading, so i have tried to port the code on my project, but not much luck. I believe this is the ParseCertificate project?
Unless i need to configure it in particular way?

Also there is plugin for Azure Full Managed? Is that of any advantage to use

fresh geyser
#

Parsing a certificate does not validate if it can be used to connect to Azure.
Please use the SecureClient WiFi sample.

keen skiff
#

On slightly side questions

I am trying to run project, but the output display seems to be running the previous project(my project); Why does this happen?

Do i need to do something before jumping to this new project.

It

#

Error: a2000000 Waiting for debug commands... The nanoDevice runtime is loading the application assemblies and starting execution. The program '[1] .NET nanoFramework application: Managed' has exited with code 0 (0x0).
I get error when running the new project

indigo sorrel
#

Are you using Generics in your code

keen skiff
#

No i am just running the example project SecureClient WiFi sample.

indigo sorrel
#

Are you using the preview firmware or preview VS extension

keen skiff
#

Previous Firmware

indigo sorrel
#

Is this a running the Sample code or your own code. Normally Error: a200000 is due to syntax that is not supported.

keen skiff
#

Well i am now trying to run the sample code

fresh geyser
#

And what firmware are you using on your device (which hardware, BTW)?

keen skiff
#

Hadrware is ESP32-S3-WROOM.

What must i type in cmd to confirm the firmware? Sorry..

indigo sorrel
#

The second icon in the Device Explorer

keen skiff
#

Firmware build Info:
Date: Apr 8 2026
Type: MinSizeRel build, chip rev. >= 0, support for PSRAM, support for BLE
CLR Version: 1.16.0.449
Compiler: GNU ARM GCC v14.2.0

indigo sorrel
#

can you run this #1431334376054198272 message in a hello world to see if you have enough memory

keen skiff
#

Well i have dev kit with 16mb PSRAM, so memory is not an issue, or attest i dont it should

Where do i run # uknown?

indigo sorrel
#
 public static void PrintMemory(string msg)
    {
        NativeMemory.GetMemoryInfo(NativeMemory.MemoryType.Internal, out uint totalSize, out uint totalFreeSize, out uint largestBlock);
        Debug.WriteLine($"\n{msg}-> Internal Total Mem {totalSize} Total Free {totalFreeSize} Largest Block {largestBlock}");
        Debug.WriteLine($"nF Mem {nanoFramework.Runtime.Native.GC.Run(false)}\n ");
        NativeMemory.GetMemoryInfo(NativeMemory.MemoryType.SpiRam, out uint totalSize1, out uint totalFreeSize1, out uint largestBlock1);
        Debug.WriteLine($"\n{msg}-> SpiRam Total Mem {totalSize1} Total Free {totalFreeSize1} Largest Block {largestBlock1}");
    }
}```
keen skiff
#

But i can not get the sample project to laod

#

*load

fresh geyser
#

Can you run the hello world app from the executable template?

keen skiff
#

let me check

#

Where do i find this project, is it in the samples?

indigo sorrel
#

Just create a new project and deploy

keen skiff
#

ok, i can add that at start of my project

keen skiff
#

Hello World-> Internal Total Mem 284548 Total Free 40152 Largest Block 31744
nF Mem 15612

Hello World-> SpiRam Total Mem 0 Total Free 0 Largest Block 0

#

This is my usage:

`Hello World-> Internal Total Mem 284548 Total Free 40152 Largest Block 31744
nF Mem 15612

Hello World-> SpiRam Total Mem 0 Total Free 0 Largest Block 0`

keen skiff
#

By the way i am using
nanoFramework.Azure.Devices.Client

but what is nanoFramework.Azure.Devices.Client.FullyManged? As this is not yet insalled?

desert yarrow
keen skiff
#

Ok

#

Does this memory output suggest its fine?

keen skiff
#

Ok, i been doing a little debugging, using the Step into option, and this is what it displays before the exception. It seems it could be related to SAS Key

tep into: Stepping over non-user code 'System.Web.Private.HttpUtility.IsSafe' Step into: Stepping over non-user code 'System.Web.Private.HttpUtility.UrlEncodeBytesToBytesInternal' Step into: Stepping over non-user code 'System.Web.Private.HttpUtility.UrlEncodeToBytes' Step into: Stepping over non-user code 'System.Web.Private.HttpUtility.UrlEncode' Step into: Stepping over non-user code 'System.Web.Private.HttpUtility.UrlEncode' Step into: Stepping over non-user code 'System.Web.Private.HttpUtility.UrlEncode' Step into: Stepping over non-user code 'nanoFramework.Azure.Devices.Helper.GetSharedAccessSignature' ++++ Exception System.Exception - CLR_E_FAIL (1) ++++ ++++ Message: ++++ System.Convert::FromBase64String [IP: 0000] ++++ ++++ nanoFramework.Azure.Devices.Helper::GetSharedAccessSignature [IP: 0021] ++++ ++++ nanoFramework.Azure.Devices.Client.DeviceClient::Open [IP: 0099] ++++ ++++ BluetoothLESerial.AzureIotHubBasic::Start [IP: 0045] ++++ ++++ BluetoothLESerial.Program::Main [IP: 0156] ++++ Exception thrown: 'System.Exception' in mscorlib.dll

keen skiff
indigo sorrel
indigo sorrel
#

Internal Total Mem 284548 Total Free 40152 Largest Block 31744 nF Mem 15612
a) Total Free is the max free memory in the native side
b) Largest Block is the largest contiguous free memory
c) nF Mem is the free memory that nanoframework c# has access to.

#

SpiRam Total Mem 0 Total Free 0 Largest Block 0
SpiRam is the PSRAM

keen skiff
#

I am using the following:
https://eu.mouser.com/ProductDetail/Espressif-Systems/ESP32-S3-DevKitC-1-N32R16V?qs=sqEgtWRSLJ3pTWIVKUeIew%3D%3D&countryCode=GB&currencyCode=GBP

This is my device information:
C:\Users\djosh>nanoff --platform esp32 --serialport COM8 --devicedetails
.NET nanoFramework Firmware Flasher v2.5.131+6bd4d0daab
Copyright (C) 2019 .NET Foundation and nanoFramework project contributors

Reading details from chip...OK

Connected to:
ESP32-S3 (ESP32-S3 (QFN56) (revision v0.2)) Features Wi-Fi, BT 5 (LE), Dual Core + LP Core, 240MHz, Embedded PSRAM 16MB (AP_1v8) Flash size 32MB unknown from MACRONIX (manufacturer 0x194 device 0x-32711) PSRAM: 16MB Crystal 40MHz MAC 90:E5:B1:CB:D2:88

The firmware is ESP32_S3_BLE , What must i have installed, as I don't see a PSRAM variation for the S3?

In addition to this, I have realised that the SAS key should be the device primary key, with the token generated internally. Previously, I was generating the token myself. I no longer receive an interrupt; instead, the system hangs when the Open connection is called, which may indicate a memory issue, as previously mentioned.

indigo sorrel
#

Flash it with the ESP32_S3_ALL firmware then run the memory test.

#

nanoff --target ESP32_S3_ALL --update --serialport COMx --masserase

keen skiff
#

Thanks, I got it working, i can communicate with Azure IoT Hub

Hello World-> Internal Total Mem 317307 Total Free 110815 Largest Block 31744 nF Mem 15411540 Hello World-> SpiRam Total Mem 16777216 Total Free 1307860 Largest Block 1277952

I have some general questions regarding security regarding IoT Hub, I will open a new post

indigo sorrel
#

Wow I am jealous, you have 15MB of nF ram.