I want to use the device provisioning in Azure for my devices.
I'm using the Azure IoT SDK (Java).
I would like to create a new device that have some specific properties inside the JSON of the device twin.
I want to see my new device in Azure portal with a custom JSON for the device twin.
In the ProvisioningTpmSample class (Link GitHub). There is this piece of code:
try
{
deviceClient = DeviceClient.createFromSecurityProvider(iotHubUri, deviceId, securityClientTPMEmulator, IotHubClientProtocol.MQTT);
deviceClient.open();
Message messageToSendFromDeviceToHub = new Message("Whatever message you would like to send");
System.out.println("Sending message from device to IoT Hub...");
deviceClient.sendEventAsync(messageToSendFromDeviceToHub, new IotHubEventCallbackImpl(), null);
}
I find the method setProperty for the Message. It's like
messageToSendFromDeviceToHub.setProperty("test", "test");
Is it possible to defined the desired and required properties of the device twin by this setProperty method?
Thanks a lot
Related
I'd like to know how to represent C2D message and External message on IoT Edge module by IoT Plug & Play DTDL definition.
I thought that a Command with a value of "asynchronous" in commandType property is used as C2D message. But when I check the behavior in IoT Central, such a command is handled as a direct method invocation.
Is it possible to represent C2D message by IoT PnP model? If yes, please let me know how to describe that.
regards,
It is a fully managed service which enable secure bidirectional communication between large no of devices and back end.
Simulated Device: connects to your IoThub and receive cloud-to-device messages.
SendCloudToDevice: app Sends a cloud to device message to device app with the help of IOT hub.
To receive cloud-to-device messages from the IoT hub.
Inside visual studio, in the Simulated Device project add given method to Simulated Device class.
private static async void ReceiveC2dAsync()
{
Console.WriteLine("\nReceiving cloud to device messages from service");
while (true)
{
Message receivedMessage = await s_deviceClient.ReceiveAsync();
if (receivedMessage == null) continue;
Console.ForegroundColor = ConsoleColor.Yellow;
Console.WriteLine("Received message: {0}",
Encoding.ASCII.GetString(receivedMessage.GetBytes()));
Console.ResetColor();
await s_deviceClient.CompleteAsync(receivedMessage);
}
}
Add ReceiveC2dAsync() in main method before console.ReadLine().
Is there anyway to register the new device onto the azure iot-hub programmatically using the self/CA created certificates?
For example say, I want to register my raspberry pi on to my newly created IOT-HUB from the same rasp pi. I know we can do it using the AZ Cli. What I am looking for is there a way to do it programmatically, using MQTT/REST?.
Thanks in advance.
Regards,
Pradeep
You can make use of the device provisioning service - DPS. The DPS is another service whose purpose is to identify your device, and in case that the device identification is recognized by the DPS, the DPS will create an identity in your IoT Hub.
You set the DPS in a way that you create either individual enrollment(for individual device onboarding) or a group enrollment(for a group of the devices, typically if you use certificates or shared access key authentication type).
Enrollments typically contain an identification type that the device should present, and IoT Hub to which the device with the presented identification should be assigned.
The typical flow is that the device reaches out to the DPS with some public identification(certificate chain, TPM registration id, or SAS key). Then internally, the DPS can challenge the device(proof-of-possesion in case of CA certificates), and if the device successfully solves the challenge, that means that the device contains a specific secret(private key in case of CA certs) that identifies that device, so the DPS will create the device identity to the assigned hub in that specific enrollment. This process is called attestation.
As a result, on the device side, you receive at least the IoT Hub endpoint, and the device Id which you use to communicate with the IoT Hub.
Below are the code snippets of how you can do this with CA certificates and C#:
var certificate = new X509Certificate2(leafCertificatePath, leafCertificatePassword);
using (var security = new SecurityProviderX509Certificate(certificate))
using (var transport = new ProvisioningTransportHandlerMqtt(TransportFallbackType.TcpOnly))
{
ProvisioningDeviceClient provClient =
ProvisioningDeviceClient.Create(GlobalDeviceEndpoint, dpsScope, security, transport);
var deviceAuthentication = await GetDeviceRegistrationResultAsync(provClient, security);
var auth = new DeviceAuthenticationWithX509Certificate(deviceAuthentication.DeviceId, security.GetAuthenticationCertificate());
var deviceClient = DeviceClient.Create(hostname: deviceAuthentication.AssignedHub,
authenticationMethod: auth,
transportType: TransportType.Mqtt);
if (deviceClient == null)
{
Console.WriteLine("Failed to create DeviceClient!");
}
else
{
SendEvents(deviceClient, MESSAGE_COUNT).Wait();
}
}
Method for getting the device registration result from the DPS:
static async Task<DeviceRegistrationResult> GetDeviceRegistrationResultAsync(ProvisioningDeviceClient provClient, SecurityProviderX509 security)
{
DeviceRegistrationResult result = await provClient.RegisterAsync().ConfigureAwait(false);
if (result.Status != ProvisioningRegistrationStatusType.Assigned)
{
throw new Exception("Device not assigned");
}
return result;
}
Official example from MSFT you can find here
Here is how you can create and verify certificates with IoT Hub and DPS.
Just to clarify, 'registering' a device in IoTHub/DPS is kind of an overloaded term, and may mean different things to different people. If you are using self-signed certs, it's a two step process.
First, you need to enroll the device in DPS, which lets DPS know that sometime in the future, a device may show up with that name and that certificate. That is generally a backend process typically NOT done from the device itself. Technically, there's nothing stopping you from calling the REST APIs to do so from the device, but since you need some pretty powerful credentials to do so, it's not recommended to have them on your device. This cannot be done over MQTT. You can avoid having to enroll every individual device by uploading, verifying, and using a CA-signed cert, though.
Once that's done, the device can now/later register itself, which is the act of actually having DPS create the device registration record in IoT Hub. The device "phones home" to DPS, authenticates itself using the cert you provided in the enrollment, and registers itself, getting the IoT Hub connection information it needs back from DPS. That process can be done over MQTT and you can find step by step the process on my blog -> http://busbyland.com/azure-device-provisioning-server-over-mqtt-using-x509-certificates
Provisioning a device in IoTHub from the device itself is not recommended, as it will then require IoTHub registry write permission and use of service SDK.
The recommended approach is to use Device Provisioning Service, you can create individual or group enrollment with X509 and it will automatically provision the device in target IoTHub.
The device just needs
mechanism to attest its identity
DPS global endpoint
ID Scope to identify your instance of DPS.
Check this - https://learn.microsoft.com/en-us/azure/iot-dps/concepts-x509-attestation
I have a Azure device provisioning service setup entitled "myDPS" and below IoT hubs are linked.
IoTHub-Dev-Asia
IoTHub-Prod-Europe
Currently there are no enrollment list. The below c# code I am using to enroll the device
private const string RegistrationId = "TestRegID";
private const string OptionalDeviceId = "Device1";
private const ProvisioningStatus OptionalProvisioningStatus = ProvisioningStatus.Enabled;
private const string SampleTpmEndorsementKey = "***"// Key generated using TPM Simulator
static async Task SetRegistrationDataAsync()
{
Console.WriteLine("Starting SetRegistrationData");
Attestation attestation = new TpmAttestation(SampleTpmEndorsementKey);
IndividualEnrollment individualEnrollment = new
IndividualEnrollment(RegistrationId, attestation);
individualEnrollment.DeviceId = OptionalDeviceId;
individualEnrollment.ProvisioningStatus = OptionalProvisioningStatus;
Console.WriteLine("\nAdding new individualEnrollment...");
var serviceClient = ProvisioningServiceClient.CreateFromConnectionString(ServiceConnectionString);
IndividualEnrollment individualEnrollmentResult =
await serviceClient.CreateOrUpdateIndividualEnrollmentAsync(individualEnrollment).ConfigureAwait(false);
Console.WriteLine("\nIndividualEnrollment created with success.");
Console.WriteLine(individualEnrollmentResult);
}
The above code successfully enrolls the device to the DPS but status shows as unassigned
Issue#1 - Enrollment status unassigned, sometimes shows FAILED
Status: failed
Error code: 404201
Issue#2
Once above issue resolved, then I would like to have some configuration where I can specify which device should map to which IoT, so that device can automatically decide it's target IoT hubs.
Example:
Device1->IoTHub-Dev-Asia
Device2->IoTHub-Dev-Asia
Device3->IoTHub-Dev-Europe
I assume Static configuration via the enrollment list can help but not sure how to use it?
The three supported allocation policies determine how devices are assigned to an IoT hub:
Lowest latency: Devices are provisioned to an IoT hub based on the hub with the lowest latency to the device.
Evenly weighted distribution (default): Linked IoT hubs are equally likely to have devices provisioned to them. This is the default setting. If you are provisioning devices to only one IoT hub, you can keep this setting.
Static configuration via the enrollment list: Specification of the desired IoT hub in the enrollment list takes priority over the DPS-level allocation policy.
If you need to assign the device ,you should use a single call to the ProvisioningDeviceClient.RegisterAsync() API. You can refer to the sample.In the sample, you need to replace the RegistrationId with that your created before.
I use Azure Service Bus to communicate IoT Hub with Node.js Functions. On Function side, I need to have access to message body as well as custom properties.
By retrieving messages elsewhere, I have noticed that my message in Service Bus consists of:
Body (the string set on IoT Device side).
Custom properties (include properties set on IoT Device side, IoT Device ID, and some additional metadata).
I have found online that in C# it is possible to access these custom properties using BrokeredMessage object. However, there is no mention on how to make this happen in Node.js. To give some details, I am printing the message as soon as it arrives to Function, using the following code:
module.exports = function(context, message) {
context.log('Message', message, 'of type', (typeof message));
...
}
What I am getting in the log console is:
message { test: true } of type object
Where "{ test: true }" is the content of a message set by IoT Device. No trace of properties though...
Is there some formal way or at least a trick to receive and extract these properties?
Thank you!
Browsing resources mentioned in the link posted by Ling Toh in a comment I got inspired to have a look at the context object.
Apparently, all of the Service Bus custom properties are available in context.bindingData.properties object.
In my case:
properties:
{
type: 'sometype', // <- this is the property I have set manually in IoT Hub message
'iothub-connection-device-id': 'mydeviceid',
'iothub-connection-auth-method': '{"scope":"somescope","type":"sometype","issuer":"external","acceptingIpFilterRule":null}',
'iothub-connection-auth-generation-id': 'someid' // <- These are added by IoT Hub
}
I am looking for a way to see which device has sent which message in Azure.
Via "IoT-hub" we can get a list of the devices but I cannot seem to find a way to correlate the messages to the devices.
Doe anyone have any idea?
Thanks in advance.
Regards
Have a look at this document for more details about the message format.
The device id is a part of the IoT Hub message system properties such as ConnectionDeviceId.
The following example shows a query of the ASA job. You can see how to get the device id from the telemetry message via the stream pipeline:
WITH subquery as (
SELECT
System.Timestamp as time,
counter,
temperature,
humidity,
EventProcessedUtcTime,
IoTHub.ConnectionDeviceId as deviceId,
IoTHub.MessageId as messageId
FROM iot Timestamp by time
)
SELECT
*
INTO
outBlob
FROM
subquery
another example is for Azure EventHubTrigger Function (AF). The telemetry message from the stream pipeline (events endpoint) is serialized into the EventData object and pushed to the AF:
public static async Task Run(EventData ed, TraceWriter log)
{
log.Info($"Label = {ed.SystemProperties["iothub-message-source"]} -{ed.SystemProperties["iothub-connection-device-id"]}/{ed.SequenceNumber}");
// ...
}
You could try Azure IoT Toolkit extension for VS Code to monitor all the messages sent to Azure IoT Hub. You could see which device has sent what message to Azure IoT Hub.
You could also refer to this blog post for more details about how to use this extension to monitor messages.
When a message arrives in IoT Hub, the hub adds a number of system properties to the message, including the deviceid of the device that sent the message - for more information about message properties, see https://learn.microsoft.com/en-us/azure/iot-hub/iot-hub-devguide-messages-construct
If you're using C# to read the messages, see the ConnectionDeviceId property of this class: https://learn.microsoft.com/en-us/dotnet/api/microsoft.azure.devices.messagesystempropertynames?view=azure-dotnet