| title | Get started with Azure IoT Hub device twins (Java) | ||||
|---|---|---|---|---|---|
| titleSuffix | Azure IoT Hub | ||||
| description | How to use the Azure IoT SDK for Java to create device and backend service application code for device twins. | ||||
| author | SoniaLopezBravo | ||||
| ms.author | sonialopez | ||||
| ms.service | azure-iot-hub | ||||
| ms.devlang | java | ||||
| ms.topic | include | ||||
| ms.date | 07/20/2024 | ||||
| ms.custom |
|
- Requires Java SE Development Kit 8. Make sure you select Java 8 under Long-term support to navigate to downloads for JDK 8.
This article describes how to use the Azure IoT SDK for Java to create device and backend service application code for device twins.
Device applications can read and write twin reported properties, and be notified of desired twin property changes that are set by a backend application or IoT Hub.
This section describes how to create device application code to:
- Retrieve and view a device twin
- Update reported device twin properties
- Subscribe to desired property changes
The DeviceClient class exposes all the methods you require to interact with device twins from the device.
[!INCLUDE iot-authentication-device-connection-string.md]
Use the following device import statements to access the Azure IoT SDK for Java.
import com.microsoft.azure.sdk.iot.device.*;
import com.microsoft.azure.sdk.iot.device.DeviceTwin.*;A device app can authenticate with IoT Hub using the following methods:
- Shared access key
- X.509 certificate
[!INCLUDE iot-authentication-device-connection-string.md]
To connect a device to IoT Hub:
-
Use IotHubClientProtocol to choose a transport protocol. For example:
IotHubClientProtocol protocol = IotHubClientProtocol.MQTT;
-
Use the
DeviceClientconstructor to add the device primary connection string and protocol.String connString = "{IoT hub device connection string}"; DeviceClient client = new DeviceClient(connString, protocol);
-
Use open to connect the device to IoT hub. If the client is already open, the method does nothing.
client.open(true);
[!INCLUDE iot-hub-howto-auth-device-cert-java]
After opening the client connection, call getTwin to retrieve the current twin properties into a Twin object.
For example:
private static Twin twin;
System.out.println("Getting current twin");
twin = client.getTwin();
System.out.println("Received current twin:");
System.out.println(twin);After retrieving the current twin, you can begin making reported property updates. You can also make reported property updates without getting the current twin as long as you have the correct reported properties version. If you send reported properties and receive a "precondition failed" error, then your reported properties version is out of date. In that case, get the latest version by calling getTwin again.
To update reported properties:
-
Call getReportedProperties to fetch the twin reported properties into a TwinCollection object.
-
Use put to update a reported property within the
TwinCollectionobject. Callputfor each reported property update. -
Use updateReportedProperties to apply the group of reported properties that were updated using the
putmethod.
For example:
TwinCollection reportedProperties = twin.getReportedProperties();
int newTemperature = new Random().nextInt(80);
reportedProperties.put("HomeTemp(F)", newTemperature);
System.out.println("Updating reported property \"HomeTemp(F)\" to value " + newTemperature);
ReportedPropertiesUpdateResponse response = client.updateReportedProperties(reportedProperties);
System.out.println("Successfully set property \"HomeTemp(F)\" to value " + newTemperature);Call subscribeToDesiredProperties to subscribe to desired property changes. This client receives a callback with a Twin object each time a desired property is updated. That callback either contains the full desired properties set, or only the updated desired property depending on how the desired property was changed.
This example subscribes to desired property changes. Any desired property changes are passed to a handler named DesiredPropertiesUpdatedHandler.
client.subscribeToDesiredProperties(new DesiredPropertiesUpdatedHandler(), null);In this example, the DesiredPropertiesUpdatedHandler desired property change callback handler calls getDesiredProperties to retrieve the property changes, then prints the updated twin properties.
private static class DesiredPropertiesUpdatedHandler implements DesiredPropertiesCallback
{
@Override
public void onDesiredPropertiesUpdated(Twin desiredPropertyUpdateTwin, Object context)
{
if (twin == null)
{
// No need to care about this update because these properties will be present in the twin retrieved by getTwin.
System.out.println("Received desired properties update before getting current twin. Ignoring this update.");
return;
}
// desiredPropertyUpdateTwin.getDesiredProperties() contains all the newly updated desired properties as well as the new version of the desired properties
twin.getDesiredProperties().putAll(desiredPropertyUpdateTwin.getDesiredProperties());
twin.getDesiredProperties().setVersion(desiredPropertyUpdateTwin.getDesiredProperties().getVersion());
System.out.println("Received desired property update. Current twin:");
System.out.println(twin);
}
}The Azure IoT SDK for Java includes a working sample to test the device app concepts described in this article. For more information, see Device twin sample.
This section describes how to create a backend application that:
- Updates device twin tags
- Queries devices using filters on the tags and properties
The ServiceClient DeviceTwin class contains methods that services can use to access device twins.
Use the following service import statements to access the Azure IoT SDK for Java.
import com.microsoft.azure.sdk.iot.service.devicetwin.*;
import com.microsoft.azure.sdk.iot.service.exceptions.IotHubException;You can connect a backend service to IoT Hub using the following methods:
- Shared access policy
- Microsoft Entra
[!INCLUDE iot-authentication-service-connection-string.md]
Use a DeviceTwin constructor to create the connection to IoT hub. The DeviceTwin object handles the communication with your IoT hub.
Your application needs the service connect permission to modify desired properties of a device twin, and it needs registry read permission to query the identity registry. There is no default shared access policy that contains only these two permissions, so you need to create one if a one does not already exist. Supply this shared access policy connection string as a parameter to fromConnectionString. For more information about shared access policies, see Control access to IoT Hub with shared access signatures.
The DeviceTwinDevice object represents the device twin with its properties and tags.
For example:
public static final String iotHubConnectionString = "{Shared access policy connection string}";
public static final String deviceId = "myDeviceId";
public static final String region = "US";
public static final String plant = "Redmond43";
// Get the DeviceTwin and DeviceTwinDevice objects
DeviceTwin twinClient = new DeviceTwin(iotHubConnectionString);
DeviceTwinDevice device = new DeviceTwinDevice(deviceId);[!INCLUDE iot-hub-howto-connect-service-iothub-entra-java]
To update device twin fields:
-
Use getTwin to retrieve the current device twin fields
This example retrieves and prints the device twin fields:
// Get the device twin from IoT Hub System.out.println("Device twin before update:"); twinClient.getTwin(device); System.out.println(device);
-
Use a
HashSetobject toadda group of twin tag pairs -
Use setTags to add a group of tag pairs from a
tagsobject to aDeviceTwinDeviceobject -
Use updateTwin to update the twin in the IoT hub
This example updates the region and plant device twin tags for a device twin:
// Update device twin tags if they are different // from the existing values String currentTags = device.tagsToString(); if ((!currentTags.contains("region=" + region) && !currentTags.contains("plant=" + plant))) { // Create the tags and attach them to the DeviceTwinDevice object Set<Pair> tags = new HashSet<Pair>(); tags.add(new Pair("region", region)); tags.add(new Pair("plant", plant)); device.setTags(tags); // Update the device twin in IoT Hub System.out.println("Updating device twin"); twinClient.updateTwin(device); } // Retrieve and display the device twin with the tag values from IoT Hub System.out.println("Device twin after update:"); twinClient.getTwin(device); System.out.println(device);
This section demonstrates two device twin queries. Device twin queries are SQL-like queries that return a result set of device twins.
The Query class contains methods that can be used to create SQL-style queries to IoT Hub for twins, jobs, device jobs, or raw data.
To create a device query:
-
Use createSqlQuery to build the twins SQL query
-
Use queryTwin to execute the query
-
Use hasNextDeviceTwin to check if there's another device twin in the result set
-
Use getNextDeviceTwin to retrieve the next device twin from the result set
The following example queries return a maximum of 100 devices.
This example query selects only the device twins of devices located in the Redmond43 plant.
// Query the device twins in IoT Hub
System.out.println("Devices in Redmond:");
// Construct the query
SqlQuery sqlQuery = SqlQuery.createSqlQuery("*", SqlQuery.FromType.DEVICES, "tags.plant='Redmond43'", null);
// Run the query, returning a maximum of 100 devices
Query twinQuery = twinClient.queryTwin(sqlQuery.getQuery(), 100);
while (twinClient.hasNextDeviceTwin(twinQuery)) {
DeviceTwinDevice d = twinClient.getNextDeviceTwin(twinQuery);
System.out.println(d.getDeviceId());
}This example query refines the first query to select only the devices that are also connected through a cellular network.
System.out.println("Devices in Redmond using a cellular network:");
// Construct the query
sqlQuery = SqlQuery.createSqlQuery("*", SqlQuery.FromType.DEVICES, "tags.plant='Redmond43' AND properties.reported.connectivityType = 'cellular'", null);
// Run the query, returning a maximum of 100 devices
twinQuery = twinClient.queryTwin(sqlQuery.getQuery(), 3);
while (twinClient.hasNextDeviceTwin(twinQuery)) {
DeviceTwinDevice d = twinClient.getNextDeviceTwin(twinQuery);
System.out.println(d.getDeviceId());
}The Azure IoT SDK for Java provides a working sample of a service app that handles device twin tasks. For more information, see Device twin sample.