Get device twin inside a module in an offline scenario

Boris Lange 1 Reputation point
2021-02-22T13:35:30.443+00:00

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

Azure IoT Edge
Azure IoT Edge
An Azure service that is used to deploy cloud workloads to run on internet of things (IoT) edge devices via standard containers.
534 questions
Azure IoT Hub
Azure IoT Hub
An Azure service that enables bidirectional communication between internet of things (IoT) devices and applications.
1,113 questions
Azure IoT SDK
Azure IoT SDK
An Azure software development kit that facilitates building applications that connect to Azure IoT services.
207 questions
{count} votes

2 answers

Sort by: Most helpful
  1. VenkatYalla-0009 751 Reputation points
    2021-03-04T00:10:29.143+00:00

    @Boris Lange 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!

    1 person found this answer helpful.
    0 comments No comments

  2. QuantumCache 20,031 Reputation points
    2021-02-25T01:07:25.887+00:00

    Hello @Boris Lange 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.