Taken plannen en uitzenden (Java)
Gebruik Azure IoT Hub om taken te plannen en bij te houden die miljoenen apparaten bijwerken. Taken gebruiken om:
- Gewenste eigenschappen bijwerken
- Tags bijwerken
- Directe methoden aanroepen
Een taak verpakt een van deze acties en houdt de uitvoering bij op een set apparaten. Een apparaatdubbelquery definieert de set apparaten waarop de taak wordt uitgevoerd. Een back-end-app kan bijvoorbeeld een taak gebruiken om een directe methode aan te roepen op 10.000 apparaten waarmee de apparaten opnieuw worden opgestart. U geeft de set apparaten op met een apparaatdubbelquery en plant de taak op een later tijdstip uit te voeren. De taak houdt de voortgang bij terwijl elk van de apparaten de directe methode voor opnieuw opstarten ontvangt en uitvoert.
Zie voor meer informatie over elk van deze mogelijkheden:
Apparaatdubbel en eigenschappen: Aan de slag met apparaatdubbels en Apparaatdubbels begrijpen en gebruiken in IoT Hub
Directe methoden: Ontwikkelaarshandleiding voor IoT Hub - directe methoden
Notitie
De functies die in dit artikel worden beschreven, zijn alleen beschikbaar in de standaardlaag van de IoT Hub. Zie De juiste IoT Hub-laag voor uw oplossing kiezen voor meer informatie over de Basic- en Standard-/gratis IoT Hub-lagen.
In dit artikel leest u hoe u twee Java-apps maakt:
Een apparaat-app, gesimuleerd-apparaat, die een directe methode implementeert met de naam lockDoor, die kan worden aangeroepen door de back-end-app.
Een back-end-app, planningstaken, waarmee twee taken worden gemaakt. Een taak roept de directe lockDoor-methode aan en een andere taak verzendt gewenste eigenschapsupdates naar meerdere apparaten.
Notitie
Zie Azure IoT SDK's voor meer informatie over de SDK-hulpprogramma's die beschikbaar zijn voor het bouwen van zowel apparaat- als back-end-apps.
Vereisten
Een IoT-hub in uw Azure-abonnement. Als u nog geen hub hebt, kunt u de stappen volgen in Een IoT-hub maken.
Een apparaat dat is geregistreerd in uw IoT-hub. Als u geen apparaat in uw IoT-hub hebt, volgt u de stappen in Een apparaat registreren.
Java SE Development Kit 8. Zorg ervoor dat u Java 8 selecteert onder Langetermijnondersteuning om naar downloads voor JDK 8 te gaan.
Zorg ervoor dat de poort 8883 is geopend in uw firewall. Het apparaatvoorbeeld in dit artikel maakt gebruik van het MQTT-protocol, dat via poort 8883 communiceert. Deze poort is in sommige netwerkomgevingen van bedrijven en onderwijsinstellingen mogelijk geblokkeerd. Zie Verbinding maken met IoT Hub (MQTT) voor meer informatie en manieren om dit probleem te omzeilen.
Notitie
Om het eenvoudig te houden, implementeert dit artikel geen beleid voor opnieuw proberen. In productiecode moet u beleid voor opnieuw proberen implementeren (zoals een exponentiële uitstel), zoals wordt voorgesteld in het artikel Tijdelijke foutafhandeling.
De IoT Hub-verbindingsreeks ophalen
In dit artikel maakt u een back-endservice die een taak plant om een directe methode op een apparaat aan te roepen, een taak plant om de apparaatdubbel bij te werken en de voortgang van elke taak bewaakt. Om deze bewerkingen uit te voeren, heeft uw service de lees- en schrijfmachtigingen voor het register nodig. Standaard wordt elke IoT-hub gemaakt met een gedeeld toegangsbeleid met de naam registryReadWrite dat deze machtigingen verleent.
Voer de volgende stappen uit om de IoT Hub-verbindingsreeks voor het registerReadWrite-beleid op te halen:
Selecteer resourcegroepen in de Azure-portal. Selecteer de resourcegroep waar uw hub zich bevindt en selecteer vervolgens uw hub in de lijst met resources.
Selecteer in het linkerdeelvenster van uw hub beleid voor gedeelde toegang.
Selecteer in de lijst met beleidsregels het registerReadWrite-beleid .
Kopieer de primaire verbindingsreeks en sla de waarde op.
Zie Toegangsbeheer en machtigingen voor meer informatie over beleid en machtigingen voor gedeelde toegang van IoT Hub.
Belangrijk
Dit artikel bevat stappen voor het maken van verbinding met een service met behulp van een handtekening voor gedeelde toegang. Deze verificatiemethode is handig voor testen en evalueren, maar verificatie bij een service met Microsoft Entra ID of beheerde identiteiten is een veiligere benadering. Zie Best practices > voor beveiliging voor cloudbeveiliging voor meer informatie.
De service-app maken
In deze sectie maakt u een Java-console-app die gebruikmaakt van taken voor het volgende:
Roep de directe methode lockDoor aan op meerdere apparaten.
De gewenste eigenschappen naar meerdere apparaten verzenden.
De app maken:
Maak op uw ontwikkelcomputer een lege map met de naam iot-java-schedule-jobs.
Maak in de map iot-java-schedule-jobs een Maven-project met de naam schedule-jobs met behulp van de volgende opdracht bij de opdrachtprompt. Let op: dit is één enkele, lange opdracht:
mvn archetype:generate -DgroupId=com.mycompany.app -DartifactId=schedule-jobs -DarchetypeArtifactId=maven-archetype-quickstart -DinteractiveMode=false
Navigeer in de opdrachtprompt naar de map schedule-jobs .
Open met behulp van een teksteditor het pom.xml bestand in de map schedule-jobs en voeg de volgende afhankelijkheid toe aan het knooppunt afhankelijkheden . Met deze afhankelijkheid kunt u het iot-service-clientpakket in uw app gebruiken om te communiceren met uw IoT-hub:
<dependency> <groupId>com.microsoft.azure.sdk.iot</groupId> <artifactId>iot-service-client</artifactId> <version>1.17.1</version> <type>jar</type> </dependency>
Notitie
U vindt de meest recente versie van iot-service-client met Maven zoeken.
Voeg het volgende build-knooppunt toe na het knooppunt afhankelijkheden . Met deze configuratie verwijst Maven naar het gebruik van Java 1.8 om de app te bouwen:
<build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>3.3</version> <configuration> <source>1.8</source> <target>1.8</target> </configuration> </plugin> </plugins> </build>
Sla het bestand pom.xml op en sluit het.
Open met behulp van een teksteditor het bestand schedule-jobs\src\main\java\com\mycompany\app\App.java .
Voeg de volgende importinstructies toe aan het bestand:
import com.microsoft.azure.sdk.iot.service.devicetwin.DeviceTwinDevice; import com.microsoft.azure.sdk.iot.service.devicetwin.Pair; import com.microsoft.azure.sdk.iot.service.devicetwin.Query; import com.microsoft.azure.sdk.iot.service.devicetwin.SqlQuery; import com.microsoft.azure.sdk.iot.service.jobs.JobClient; import com.microsoft.azure.sdk.iot.service.jobs.JobResult; import com.microsoft.azure.sdk.iot.service.jobs.JobStatus; import java.util.Date; import java.time.Instant; import java.util.HashSet; import java.util.Set; import java.util.UUID;
Voeg de volgende variabelen op klasseniveau toe aan de App-klasse. Vervang
{youriothubconnectionstring}
door uw IoT-hub verbindingsreeks die u eerder hebt gekopieerd in De IoT-hub ophalen verbindingsreeks:public static final String iotHubConnectionString = "{youriothubconnectionstring}"; public static final String deviceId = "myDeviceId"; // How long the job is permitted to run without // completing its work on the set of devices private static final long maxExecutionTimeInSeconds = 30;
Voeg de volgende methode toe aan de App-klasse om een taak te plannen voor het bijwerken van de gewenste eigenschappen van gebouw en verdieping in de apparaatdubbel:
private static JobResult scheduleJobSetDesiredProperties(JobClient jobClient, String jobId) { DeviceTwinDevice twin = new DeviceTwinDevice(deviceId); Set<Pair> desiredProperties = new HashSet<Pair>(); desiredProperties.add(new Pair("Building", 43)); desiredProperties.add(new Pair("Floor", 3)); twin.setDesiredProperties(desiredProperties); // Optimistic concurrency control twin.setETag("*"); // Schedule the update twin job to run now // against a single device System.out.println("Schedule job " + jobId + " for device " + deviceId); try { JobResult jobResult = jobClient.scheduleUpdateTwin(jobId, "deviceId='" + deviceId + "'", twin, new Date(), maxExecutionTimeInSeconds); return jobResult; } catch (Exception e) { System.out.println("Exception scheduling desired properties job: " + jobId); System.out.println(e.getMessage()); return null; } }
Als u een taak wilt plannen om de lockDoor-methode aan te roepen, voegt u de volgende methode toe aan de app-klasse :
private static JobResult scheduleJobCallDirectMethod(JobClient jobClient, String jobId) { // Schedule a job now to call the lockDoor direct method // against a single device. Response and connection // timeouts are set to 5 seconds. System.out.println("Schedule job " + jobId + " for device " + deviceId); try { JobResult jobResult = jobClient.scheduleDeviceMethod(jobId, "deviceId='" + deviceId + "'", "lockDoor", 5L, 5L, null, new Date(), maxExecutionTimeInSeconds); return jobResult; } catch (Exception e) { System.out.println("Exception scheduling direct method job: " + jobId); System.out.println(e.getMessage()); return null; } };
Als u een taak wilt bewaken, voegt u de volgende methode toe aan de app-klasse :
private static void monitorJob(JobClient jobClient, String jobId) { try { JobResult jobResult = jobClient.getJob(jobId); if(jobResult == null) { System.out.println("No JobResult for: " + jobId); return; } // Check the job result until it's completed while(jobResult.getJobStatus() != JobStatus.completed) { Thread.sleep(100); jobResult = jobClient.getJob(jobId); System.out.println("Status " + jobResult.getJobStatus() + " for job " + jobId); } System.out.println("Final status " + jobResult.getJobStatus() + " for job " + jobId); } catch (Exception e) { System.out.println("Exception monitoring job: " + jobId); System.out.println(e.getMessage()); return; } }
Als u een query wilt uitvoeren op de details van de taken die u hebt uitgevoerd, voegt u de volgende methode toe:
private static void queryDeviceJobs(JobClient jobClient, String start) throws Exception { System.out.println("\nQuery device jobs since " + start); // Create a jobs query using the time the jobs started Query deviceJobQuery = jobClient .queryDeviceJob(SqlQuery.createSqlQuery("*", SqlQuery.FromType.JOBS, "devices.jobs.startTimeUtc > '" + start + "'", null).getQuery()); // Iterate over the list of jobs and print the details while (jobClient.hasNextJob(deviceJobQuery)) { System.out.println(jobClient.getNextJob(deviceJobQuery)); } }
Werk de handtekening van de hoofdmethode bij om de volgende
throws
component op te nemen:public static void main( String[] args ) throws Exception
Als u twee taken opeenvolgend wilt uitvoeren en bewaken, vervangt u de code in de hoofdmethode door de volgende code:
// Record the start time String start = Instant.now().toString(); // Create JobClient JobClient jobClient = JobClient.createFromConnectionString(iotHubConnectionString); System.out.println("JobClient created with success"); // Schedule twin job desired properties // Maximum concurrent jobs is 1 for Free and S1 tiers String desiredPropertiesJobId = "DPCMD" + UUID.randomUUID(); scheduleJobSetDesiredProperties(jobClient, desiredPropertiesJobId); monitorJob(jobClient, desiredPropertiesJobId); // Schedule twin job direct method String directMethodJobId = "DMCMD" + UUID.randomUUID(); scheduleJobCallDirectMethod(jobClient, directMethodJobId); monitorJob(jobClient, directMethodJobId); // Run a query to show the job detail queryDeviceJobs(jobClient, start); System.out.println("Shutting down schedule-jobs app");
Sla het schedule-jobs\src\main\java\com\mycompany\app\App.java bestand op en sluit het
Bouw de schedule-jobs-app en corrigeer eventuele fouten. Navigeer in de opdrachtprompt naar de map schedule-jobs en voer de volgende opdracht uit:
mvn clean package -DskipTests
Een apparaat-app maken
In deze sectie maakt u een Java-console-app die de gewenste eigenschappen verwerkt die vanuit IoT Hub worden verzonden en de aanroep van de directe methode implementeert.
Belangrijk
Dit artikel bevat stappen voor het verbinden van een apparaat met behulp van een Shared Access Signature, ook wel symmetrische sleutelverificatie genoemd. Deze verificatiemethode is handig voor testen en evalueren, maar het verifiëren van een apparaat met X.509-certificaten is een veiligere benadering. Zie Best practices > voor beveiliging voor verbindingsbeveiliging voor meer informatie.
Maak in de map iot-java-schedule-jobs een Maven-project met de naam simulated-device met behulp van de volgende opdracht bij de opdrachtprompt. Let op: dit is één enkele, lange opdracht:
mvn archetype:generate -DgroupId=com.mycompany.app -DartifactId=simulated-device -DarchetypeArtifactId=maven-archetype-quickstart -DinteractiveMode=false
Navigeer in de opdrachtprompt naar de map simulated-device .
Open met behulp van een teksteditor het pom.xml-bestand in de map simulated-device en voeg de volgende afhankelijkheden toe aan het knooppunt afhankelijkheden. Met deze afhankelijkheid kunt u het iot-device-clientpakket in uw app gebruiken om te communiceren met uw IoT-hub:
<dependency> <groupId>com.microsoft.azure.sdk.iot</groupId> <artifactId>iot-device-client</artifactId> <version>1.17.5</version> </dependency>
Notitie
U vindt de meest recente versie van iot-device-client met Maven zoeken.
Voeg de volgende afhankelijkheid toe aan het knooppunt afhankelijkheden . Deze afhankelijkheid configureert een NOP voor de Apache SLF4J-logboekregistratiefaçade , die wordt gebruikt door de client-SDK van het apparaat om logboekregistratie te implementeren. Deze configuratie is optioneel, maar als u deze weglaat, ziet u mogelijk een waarschuwing in de console wanneer u de app uitvoert. Zie Logboekregistratiein de voorbeelden voor de Azure IoT-apparaat-SDK voor Java-leesmij-bestand voor meer informatie over logboekregistratie in de SDK voor de apparaatclient.
<dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-nop</artifactId> <version>1.7.28</version> </dependency>
Voeg het volgende build-knooppunt toe na het knooppunt afhankelijkheden . Met deze configuratie verwijst Maven naar het gebruik van Java 1.8 om de app te bouwen:
<build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>3.3</version> <configuration> <source>1.8</source> <target>1.8</target> </configuration> </plugin> </plugins> </build>
Sla het bestand pom.xml op en sluit het.
Open met behulp van een teksteditor het bestand simulated-device\src\main\java\com\mycompany\app\App.java .
Voeg de volgende importinstructies toe aan het bestand:
import com.microsoft.azure.sdk.iot.device.*; import com.microsoft.azure.sdk.iot.device.DeviceTwin.*; import java.io.IOException; import java.net.URISyntaxException; import java.util.Scanner;
Voeg de volgende variabelen op klasseniveau toe aan de App-klasse. Vervang
{yourdeviceconnectionstring}
door het apparaat verbindingsreeks u hebt gezien toen u een apparaat in uw IoT Hub registreerde:private static String connString = "{yourdeviceconnectionstring}"; private static IotHubClientProtocol protocol = IotHubClientProtocol.MQTT; private static final int METHOD_SUCCESS = 200; private static final int METHOD_NOT_DEFINED = 404;
Deze voorbeeld-app gebruikt de protocol-variabele bij het maken van een DeviceClient-object.
Als u meldingen van apparaatdubbels naar de console wilt afdrukken, voegt u de volgende geneste klasse toe aan de app-klasse :
// Handler for device twin operation notifications from IoT Hub protected static class DeviceTwinStatusCallBack implements IotHubEventCallback { public void execute(IotHubStatusCode status, Object context) { System.out.println("IoT Hub responded to device twin operation with status " + status.name()); } }
Als u directe methodemeldingen naar de console wilt afdrukken, voegt u de volgende geneste klasse toe aan de app-klasse :
// Handler for direct method notifications from IoT Hub protected static class DirectMethodStatusCallback implements IotHubEventCallback { public void execute(IotHubStatusCode status, Object context) { System.out.println("IoT Hub responded to direct method operation with status " + status.name()); } }
Als u directe methode-aanroepen vanuit IoT Hub wilt verwerken, voegt u de volgende geneste klasse toe aan de app-klasse :
// Handler for direct method calls from IoT Hub protected static class DirectMethodCallback implements DeviceMethodCallback { @Override public DeviceMethodData call(String methodName, Object methodData, Object context) { DeviceMethodData deviceMethodData; switch (methodName) { case "lockDoor": { System.out.println("Executing direct method: " + methodName); deviceMethodData = new DeviceMethodData(METHOD_SUCCESS, "Executed direct method " + methodName); break; } default: { deviceMethodData = new DeviceMethodData(METHOD_NOT_DEFINED, "Not defined direct method " + methodName); } } // Notify IoT Hub of result return deviceMethodData; } }
Werk de handtekening van de hoofdmethode bij om de volgende
throws
component op te nemen:public static void main( String[] args ) throws IOException, URISyntaxException
Vervang de code in de hoofdmethode door de volgende code om:
- Maak een apparaatclient om te communiceren met IoT Hub.
- Maak een apparaatobject om de eigenschappen van de apparaatdubbel op te slaan.
// Create a device client DeviceClient client = new DeviceClient(connString, protocol); // An object to manage device twin desired and reported properties Device dataCollector = new Device() { @Override public void PropertyCall(String propertyKey, Object propertyValue, Object context) { System.out.println("Received desired property change: " + propertyKey + " " + propertyValue); } };
Als u de clientservices voor apparaten wilt starten, voegt u de volgende code toe aan de hoofdmethode :
try { // Open the DeviceClient // Start the device twin services // Subscribe to direct method calls client.open(); client.startDeviceTwin(new DeviceTwinStatusCallBack(), null, dataCollector, null); client.subscribeToDeviceMethod(new DirectMethodCallback(), null, new DirectMethodStatusCallback(), null); } catch (Exception e) { System.out.println("Exception, shutting down \n" + " Cause: " + e.getCause() + " \n" + e.getMessage()); dataCollector.clean(); client.closeNow(); System.out.println("Shutting down..."); }
Als u wilt wachten totdat de gebruiker op de Enter-toets drukt voordat u afsluit, voegt u de volgende code toe aan het einde van de hoofdmethode :
// Close the app System.out.println("Press any key to exit..."); Scanner scanner = new Scanner(System.in); scanner.nextLine(); dataCollector.clean(); client.closeNow(); scanner.close();
Sla het bestand simulated-device\src\main\java\com\mycompany\app\App.java op en sluit het.
Bouw de app simulated-device en corrigeer eventuele fouten. Navigeer in de opdrachtprompt naar de map simulated-device en voer de volgende opdracht uit:
mvn clean package -DskipTests
De apps uitvoeren
U bent nu klaar om de console-apps uit te voeren.
Voer bij een opdrachtprompt in de map simulated-device de volgende opdracht uit om de apparaat-app te starten die luistert naar gewenste eigenschapswijzigingen en directe methode-aanroepen:
mvn exec:java -Dexec.mainClass="com.mycompany.app.App"
Voer bij een opdrachtprompt in de
schedule-jobs
map de volgende opdracht uit om de schedule-jobs service-app uit te voeren om twee taken uit te voeren. De eerste stelt de gewenste eigenschapswaarden in, de tweede roept de directe methode aan:mvn exec:java -Dexec.mainClass="com.mycompany.app.App"
De apparaat-app verwerkt de gewenste eigenschapswijziging en de aanroep van de directe methode:
Volgende stappen
In dit artikel hebt u taken gepland om een directe methode uit te voeren en de eigenschappen van de apparaatdubbel bij te werken.
Als u ioT Hub- en apparaatbeheerpatronen wilt blijven verkennen, werkt u een afbeelding bij in de zelfstudie Apparaatupdate voor Azure IoT Hub met behulp van de Raspberry Pi 3 B+ Reference Image.