GetTwinAsync returns a device with null properties - azure

I'm trying to read the twin of my device from the registry manager. This is my code:
DeviceClient client =
DeviceClient.CreateFromConnectionString(DeviceConnectionString,
TransportType.Mqtt);
Twin deviceTwin = await deviceClient.GetTwinAsync();
Console.WriteLine(deviceTwin.ToJson());
However, the Json I'm getting is the following.
{"deviceId":null,"etag":null,"version":null,"properties":{"desired":{"$version":1},"reported":{"$version":1}}}

I reproduced your issue.
For this problem, you can open an issue on azure-iot-sdk-csharp repository.
For workarounds, you can either use REST API like this:
Or use Azure IoT Service SDK like this:
using Microsoft.Azure.Devices;
...
var client = RegistryManager.CreateFromConnectionString(IoTHubConnectionString);
var twinData = await client.GetTwinAsync(deviceId);
Console.WriteLine(twinData.ToJson());

This is not an issue and/or workaround. Documentation states:
Retrieve the device twin properties for the current device. For the complete device twin object, use Microsoft.Azure.Devices.RegistryManager.GetTwinAsync(string deviceId).

Related

How to automatically associate a device with a device template?

I want to automatically associate my device with its template. There is an article about this here:
https://learn.microsoft.com/en-us/azure/iot-central/core/concepts-get-connected#automatically-associate-with-a-device-template
the sample code for this is in JS and says to include iotcModelId: '< this is the URN for the capability model>'; OR '__iot:interfaces': { CapabilityModelId: <this is the URN for the capability model> }
I can see in the python device SDK documentation on keyword args available during client creation.
https://github.com/Azure/azure-iot-sdk-python/wiki/key-word-arguments-during-client-creations
But I don't see anything in those keywords about the device template. I've tried a couple of permutations on my own, but nothing seems to work as I'm registering my device using ProvisioningDeviceClient.create_from_x509_certificate.
Anyone know the correct way to include the device template in the registration?
Once you have created your ProvisioningDeviceClient you need to set the provisioning_payload property to the JSON string that contains your model-id per documentation you have linked above.
There's a tutorial and sample on Microsoft Docs that illustrates this using Python: Tutorial: Create and connect a client application to your Azure IoT Central application.

Azure IOT PnP Digital Twin API/SDK to retrieve Property, Command and Telemetry definitions for Device/Twin

I am currently learning about Azure IOT Plug and Play and Digital Twins.
I am running the following Device Sample: Azure\IOT Plug and Play\azure-iot-samples-csharp\iot-hub\Samples\device\PnpDeviceSamples\Thermostat
and the corresponding Service Example: Azure\IOT Plug and Play\azure-iot-samples-csharp\iot-hub\Samples\service\PnpServiceSamples\Thermostat
To interact with the Thermostat: https://github.com/Azure/opendigitaltwins-dtdl/blob/master/DTDL/v2/samples/Thermostat.json
I would like to discover what Properties, Telemetry and Commands are available for a device/twin through an API/SDK based on the twin ID, However I notice that the Microsoft.Azure.Devices.Device and Microsoft.Azure.Devices.Shared.Twin classes only contain Property information and don't define Commands or Telemetry.
Microsoft.Azure.Devices.RegistryManager registryManager = _registryManager;
Microsoft.Azure.Devices.Device device = await registryManager.GetDeviceAsync(_digitalTwinId);
Microsoft.Azure.Devices.Shared.Twin twin = await _registryManager.GetTwinAsync(_digitalTwinId);
Can someone please tell me how I can get the Command and Telemetry definitions please?
To discover all the details of the device model dynamically in your application should do the following:
identify the device's model-id
resolve it to the model file from the repository
parse the model file
See documentation here:
https://learn.microsoft.com/en-us/azure/iot-pnp/concepts-model-discovery
To parse the model you can read the json directly, or use the model parser library to get a rich object model for the device model. See docs here:
https://learn.microsoft.com/en-us/azure/iot-pnp/concepts-model-parser

Sending C2D message to Azure IoT Edge

I know C2D is not supported in Azure IoT Edge and an option is to use Direct Method.
Is that can I use Module Client code and send message to a Module ?
I have a ModuleA which has output1 and ModuleB has a Handler input1.
I have a route as below
"ModuleAToModuleB": "FROM /messages/modules/ModuleA/outputs/output1 INTO BrokeredEndpoint(\"/modules/ModuleB/inputs/input1\")",
And I use the below code from a console app and send message to a specific module based on the connection string of the specific Module (ModuleA connection string)
string dataString = JsonConvert.SerializeObject(jData);
byte[] dataBytes = Encoding.UTF8.GetBytes(dataString);
var pipeMessage = new Message(dataBytes);
var moduleClient = ModuleClient.CreateFromConnectionString("HostName=xxx.azure-devices.net;DeviceId=xxx-01;ModuleId=ModuleA;SharedAccessKey=XXXXXXX", TransportType.Mqtt);
await moduleClient.SendEventAsync("output1", pipeMessage);
Will this code work, Will it send the Message from ModuleA to ModuleB ?
If you want to send anything frfom your laptop/pc in a console app to your IoT Edge device, you will need to use direct methods, like you mentioned in your question. To do that, you can use the Service SDK and use the following method:
InvokeDeviceMethodAsync(string deviceId, string moduleId, CloudToDeviceMethod cloudToDeviceMethod);
In your sample, you suggested using the ModuleClient to send a message to your module. This will not work, ModuleClient is designed to be used only in the Azure IoT Edge runtime, and the method you are using (ModuleClient.CreateFromConnectionString), is one that the runtime will use to set up a connection, using the environment variables available on the device.
With the Service SDK, you can send a direct method to your Module A, and nothing is stopping you to forward the payload of that method into Module B. You already have set up your route correctly.
You need to call function like InvokeMethodAsync which is direct method from moduleA to moduelB can be called. In the example you showed it seems you are calling sendEventAsync which might not work. Example is here in C#.
Also please go through this link which also suggests another method for module to module communication.
In addition to using direct methods, it's also possible for two
modules to communicate directly with each other, bypassing the Edge
Hub. The runtime, via Docker's networking capabilities, manages the
DNS entries for each module (container). This allows one module to
resolve the IP address of another module by its name.
For an example of this in action, you can follow the SQL tutorial
here:
https://learn.microsoft.com/en-us/azure/iot-edge/tutorial-store-data-sql-server.
This tutorial uses a module to read data out of the Edge Hub and write
it into another module hosting SQLServer using the SQLServer client
SDK. This interaction with SQLServer does not use the Edge Hub for
communicating

Azure Speech Recognition not detecting microphone SPXERR_MIC_NOT_FOUND

I have a small sample application to test speech recog. It works in some machines but not in other machines. In my dev environment where I first installed the necessary packages, it all worked 100% with no issues. But, my team mates are unable to get it working with the installation of our software that has this code in it. We have mixed environments where in some cases we are using Remote Desktop with the application running on the remote machine (so with the device integration via RDP). And also locally without RDP. It does not detect the mic in both cases. Windows detects the mic. The recorder app works and testing all works so we know the mic is being recognized by windows.
However, the speech SDK does not recognize it.
I have tried 2 ways. First ,with using the FromDefaultMicrophoneInput But with that not working, i changed it to FromMicrophoneInput instead and specifed the microphone ID.
Using NAudio to enumerate the microphones, the mic is detected and listed:
var enumerator = new MMDeviceEnumerator();
string specifiedMicID = string.Empty;
foreach (var endpoint in
enumerator.EnumerateAudioEndPoints(DataFlow.Capture, DeviceState.Active))
{
if (endpoint.FriendlyName != this.MicName)
continue;
else
{
specifiedMicID = endpoint.ID;
break;
}
}
audioConfig = AudioConfig.FromMicrophoneInput(specifiedMicID);
But, when trying to instantiate the SpeechRecognizer with that audio config:
using (var recognizer = new SpeechRecognizer(config, audioConfig))
{
...
}
We get the SPXERR_MIC_NOT_FOUND. Even thought it is clearly there and working in all other cases in windows and with Naudio detecting it fine.
Any ideas what is going on here?
Thank youj.
Are you creating a UWP application? If so, you'll need to retrieve the audio device IDs differently:
var devices = await DeviceInformation.FindAllAsync(DeviceClass.AudioCapture);
foreach (var device in devices)
{
Console.WriteLine($"{device.Name}, {device.Id}\n");
}
Please refer to the documentation here for more information:
https://learn.microsoft.com/en-us/azure/cognitive-services/speech-service/how-to-select-audio-input-devices#audio-device-ids-on-uwp
If you're still having issues, we'd need to get the SDK logs to debug further. Instructions on how to turn on logging can be found here:
https://learn.microsoft.com/en-us/azure/cognitive-services/speech-service/how-to-use-logging

How to determine data flow between different modules on IoT Edge without having deployment manifest file

Suppose I have got 5 modules installed on my IoT Edge. Is there any easy way to understand how data is flowing between these modules; i.e. data of which module is piped to which other module.
Any way to debug find this information ?
Sander van de Velde has written a nice blog post about visualizing IotEdge routes.
In that blog post he describes that the routes are part of the desired device properties of the IoT Edge EdgeHub module.
You can read them like this:
var connectionString = "HostName=[iothub].azure-devices.net;SharedAccessKeyName=iothubowner;SharedAccessKey=[key]";
var registryManager = RegistryManager.CreateFromConnectionString(connectionString);
var twin = registryManager.GetTwinAsync("LinuxArk1123", "$edgeHub").Result;
var desired = twin.Properties.Desired;
var routes = desired["routes"];
...

Resources