BorisLange-5180 avatar image
0 Votes"
BorisLange-5180 asked ·

Get device twin inside a module in an offline scenario

Hello dear Azure IoT Edge team,

for a customer of ours we are currently trying to utilize the reported/desired property functionality of module and device twins. The customer decided to manage all configuration parameters that are important to multiple modules within the device properties, in order to prevent "multiple sources of truth".

The problem we face is that the devices are required to be resilient to network outages. While we encounter our desired behavior of the module client, being able to retrieve the module twin even when there is no internet connection available, we sadly see a different behavior of the device client when trying to retrieve the device twin. How can we accomplish retrieving the device twin from inside a module, when the device has no internet/hub connection?

Our demo code looks like this:

 var deviceClient = DeviceClient.CreateFromConnectionString("REDACTED"));
 var deviceTwin = await deviceClient.GetTwinAsync();
 await deviceClient.SetDesiredPropertyUpdateCallbackAsync(DevicePropertiesUpdatedAsync, null);

The exception/stack strace we receive when calling deviceClient.GetTwinAsync():

 Unhandled exception. Microsoft.Azure.Devices.Client.Exceptions.IotHubCommunicationException: Transient network error occurred, please retry.
  ---> System.Net.Sockets.SocketException (11): Resource temporarily unavailable
    at Microsoft.Azure.Devices.Client.Transport.AmqpIoT.AmqpIoTTransport.InitializeAsync(TimeSpan timeout)
    at Microsoft.Azure.Devices.Client.Transport.Amqp.AmqpIoTConnector.OpenConnectionAsync(TimeSpan timeout)
    at Microsoft.Azure.Devices.Client.Transport.Amqp.AmqpConnectionHolder.EnsureConnectionAsync(TimeSpan timeout)
    at Microsoft.Azure.Devices.Client.Transport.Amqp.AmqpConnectionHolder.OpenSessionAsync(DeviceIdentity deviceIdentity, TimeSpan timeout)
    at Microsoft.Azure.Devices.Client.Transport.AmqpIoT.AmqpUnit.EnsureSessionIsOpenAsync(TimeSpan timeout)
    at Microsoft.Azure.Devices.Client.Transport.AmqpIoT.AmqpUnit.OpenAsync(TimeSpan timeout)
    at Microsoft.Azure.Devices.Client.Transport.Amqp.AmqpTransportHandler.OpenAsync(CancellationToken cancellationToken)
    at Microsoft.Azure.Devices.Client.Transport.ProtocolRoutingDelegatingHandler.OpenAsync(CancellationToken cancellationToken)
    at Microsoft.Azure.Devices.Client.Transport.ErrorDelegatingHandler.<>c__DisplayClass27_0.<<ExecuteWithErrorHandlingAsync>b__0>d.MoveNext()
 --- End of stack trace from previous location ---
    at Microsoft.Azure.Devices.Client.Transport.ErrorDelegatingHandler.ExecuteWithErrorHandlingAsync[T](Func`1 asyncOperation)
    --- End of inner exception stack trace ---
    at Microsoft.Azure.Devices.Client.Transport.ErrorDelegatingHandler.ExecuteWithErrorHandlingAsync[T](Func`1 asyncOperation)
    at Microsoft.Azure.Devices.Client.Transport.RetryDelegatingHandler.<>c__DisplayClass38_0.<<OpenInternalAsync>b__0>d.MoveNext()
 --- End of stack trace from previous location ---
    at Microsoft.Azure.Devices.Client.Transport.RetryDelegatingHandler.EnsureOpenedAsync(CancellationToken cancellationToken)
    at Microsoft.Azure.Devices.Client.Transport.RetryDelegatingHandler.<>c__DisplayClass29_0.<<SendTwinGetAsync>b__0>d.MoveNext()
 --- End of stack trace from previous location ---
    at Microsoft.Azure.Devices.Client.Transport.RetryDelegatingHandler.SendTwinGetAsync(CancellationToken cancellationToken)
    at Microsoft.Azure.Devices.Client.InternalClient.GetTwinAsync()
    at Camera.Services.Settings.SettingsService.InitializeAsync() in /app/Services/Settings/SettingsService.cs:line 35
    at Camera.Services.Hosted.CameraService.StartAsync(CancellationToken cancellationToken) in /app/Services/Hosted/CameraService.cs:line 24
    at Microsoft.Extensions.Hosting.Internal.Host.StartAsync(CancellationToken cancellationToken)
    at Microsoft.Extensions.Hosting.HostingAbstractionsHostExtensions.RunAsync(IHost host, CancellationToken token)
    at Microsoft.Extensions.Hosting.HostingAbstractionsHostExtensions.RunAsync(IHost host, CancellationToken token)
    at Camera.Program.Main(String[] args) in /app/Program.cs:line 14
    at Camera.Program.<Main>(String[] args)

Azure IoT Edge Runtime Version: iotedge 1.1.0
Operating System: Ubuntu 18.04 LTS
SDK: Microsoft.Azure.Devices.Client 1.35.0

· 4
10 |1000 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

Hello @BorisLange-5180 Have you come across the below similar question posted on Github in the past?

Get device twin in IoT Edge module

Below is one of the quotes which I borrowed from the comment made by Varun on Github.

No, there is no way to access the device twin from the modules. This is because the device is a separate parent identity for all the modules on the device.

The only way to do this would be to pass in the device connection string to the module, but it is not recommended for security reasons.

I hope this clarifies your question.

0 Votes 0 ·

Hallo @SatishBoddu-MSFT

I actually did quite a bit of research within GitHub, StackOverflow and other sources, but did in fact not find the discussion you mentioned, since my problem is not the one that is discussed within your linked article.

The problem described in the article is about how to create a DeviceClient in a module and how to properly manage the connection string. The problem we face is, that we are not able to retrieve the device twin, when the device is offline (It does work properly when the device is online).

Or are you implying that we should not use the DeviceClient at all within a module? That would leave me kinda baffled. What would the purpose of desired/reported properties and the entire Device SDK sided DeviceClient be? And why does the Microsoft documentation about Device Twins explicitly state:

Desired properties: [...] The solution back end can set desired properties, and the device app can read them. [...]

0 Votes 0 ·

Hello @BorisLange-5180 thanks for getting back on this!

So let me put your question in a simple single one line, please confirm if the below one is your question?

The problem we face is, that "we are not able to retrieve the device twin, when the device is offline" (It does work properly when the device is online).

0 Votes 0 ·
Show more comments
SatishBoddu-MSFT avatar image
0 Votes"
SatishBoddu-MSFT answered ·

Hello @BorisLange-5180 Below is the response from the Microsoft Product Team. I hope this clarifies the issue.

Below is the quote borrowed from the StackOverflow thread answered by the Microsoft Product Team (Venkat).

Accessing device twin from an IoT Edge module is not supported or recommended.

(Edit adding some more detail as to why):

IoT Edge's security/isolation model does not allow modules to access device-level twin by design as the operation needs higher elevation creds that modules don’t/shouldn’t have.

Please let me know if you need further help in this matter, please comment in the below section.

· 2 ·
10 |1000 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

Hello @BorisLange-5180 Just checking in if you have had a chance to see the previous response. If the response is helpful, please click "Accept Answer" and upvote it so that we close this thread and is useful to others with a similar question.

0 Votes 0 ·

At this point I am just confused. There is official Microsoft documentation explaining the device twins desired properties and it's usage here
Explictly stating the usage of properties within the device app.

Then there are official Microsoft guides using the DeviceClient from within modules. For example the device stream quickstart here
Or the device upload developer guide here and here

And then there are your quotes explaining not use explicitly documented functionality.

0 Votes 0 ·
VenkatYalla-0009 avatar image
1 Vote"
VenkatYalla-0009 answered ·

@BorisLange-5180 I think part of the confusion is that you're looking at IoT Hub documentation. IoT Edge uses module twins not device twin. This is mentioned in the IoT Edge documentation.

When using IoT Edge SDKs in module, you have to use module client (vs. device client that is used normally in non-IoT Edge devices) and you don't need to manually configure connection strings. Module credentials automatically get derived by the credentials used to provision the IoT Edge device. For example, see the Python IoT Edge module sample.

The overall architecture is described here.

Hope that helps!

10 |1000 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.