Dela via


Schemalägga och sända jobb (Java)

Använd Azure IoT Hub för att schemalägga och spåra jobb som uppdaterar miljontals enheter. Använd jobb för att:

  • Uppdatera önskade egenskaper
  • Uppdatera taggar
  • Anropa direktmetoder

Ett jobb omsluter en av dessa åtgärder och spårar körningen mot en uppsättning enheter. En enhetstvillingfråga definierar den uppsättning enheter som jobbet körs mot. En serverdelsapp kan till exempel använda ett jobb för att anropa en direktmetod på 10 000 enheter som startar om enheterna. Du anger uppsättningen enheter med en enhetstvillingfråga och schemalägger jobbet så att det körs vid en framtida tidpunkt. Jobbet spårar förloppet när var och en av enheterna tar emot och kör direktmetoden för omstart.

Mer information om var och en av dessa funktioner finns i:

Kommentar

De funktioner som beskrivs i den här artikeln är endast tillgängliga på standardnivån för IoT Hub. Mer information om de grundläggande och standard-/kostnadsfria IoT Hub-nivåerna finns i Välj rätt IoT Hub-nivå för din lösning.

Den här artikeln visar hur du skapar två Java-appar:

  • En enhetsapp, simulated-device, som implementerar en direktmetod som kallas lockDoor, som kan anropas av serverdelsappen.

  • En serverdelsapp, schemajobb, som skapar två jobb. Ett jobb anropar lockDoor-direktmetoden och ett annat jobb skickar önskade egenskapsuppdateringar till flera enheter.

Förutsättningar

  • En IoT-hubb i din Azure-prenumeration. Om du inte har någon hubb ännu kan du följa stegen i Skapa en IoT-hubb.

  • En enhet som är registrerad i din IoT-hubb. Om du inte har en enhet i din IoT-hubb följer du stegen i Registrera en enhet.

  • Java SE Development Kit 8. Se till att du väljer Java 8 under Långsiktigt stöd för att komma till nedladdningar för JDK 8.

  • Maven 3

  • Kontrollera att port 8883 är öppen i brandväggen. Enhetsexemplet i den här artikeln använder MQTT-protokollet, som kommunicerar via port 8883. Den här porten kan blockeras i vissa företags- och utbildningsnätverksmiljöer. Mer information och sätt att kringgå det här problemet finns i Ansluta till IoT Hub (MQTT).

Kommentar

För att hålla det enkelt implementerar den här artikeln inte en återförsöksprincip. I produktionskoden bör du implementera återförsöksprinciper (till exempel en exponentiell backoff), enligt vad som föreslås i artikeln Tillfälliga felhantering.

Hämta IoT Hub-anslutningssträng

I den här artikeln skapar du en serverdelstjänst som schemalägger ett jobb för att anropa en direktmetod på en enhet, schemalägger ett jobb för att uppdatera enhetstvillingen och övervakar förloppet för varje jobb. För att utföra dessa åtgärder behöver tjänsten behörigheterna för registerläsning och registerskrivning . Som standard skapas varje IoT-hubb med en princip för delad åtkomst med namnet registryReadWrite som ger dessa behörigheter.

Följ dessa steg för att hämta IoT Hub-anslutningssträng för registryReadWrite-principen:

  1. I Azure Portal väljer du Resursgrupper. Välj den resursgrupp där hubben finns och välj sedan din hubb i listan över resurser.

  2. I den vänstra rutan i hubben väljer du Principer för delad åtkomst.

  3. I listan över principer väljer du registerReadWrite-principen .

  4. Kopiera den primära anslutningssträng och spara värdet.

    Skärmbild som visar hur du hämtar anslutningssträng

Mer information om principer och behörigheter för delad åtkomst i IoT Hub finns i Åtkomstkontroll och behörigheter.

Viktigt!

Den här artikeln innehåller steg för att ansluta till en tjänst med hjälp av en signatur för delad åtkomst. Den här autentiseringsmetoden är praktisk för testning och utvärdering, men autentisering till en tjänst med Microsoft Entra-ID eller hanterade identiteter är en säkrare metod. Mer information finns i Metodtips för > säkerhet Molnsäkerhet.

Skapa tjänstappen

I det här avsnittet skapar du en Java-konsolapp som använder jobb för att:

  • Anropa lockDoor-direktmetoden på flera enheter.

  • Skicka önskade egenskaper till flera enheter.

Så här skapar du appen:

  1. På utvecklingsdatorn skapar du en tom mapp med namnet iot-java-schedule-jobs.

  2. I mappen iot-java-schedule-jobs skapar du ett Maven-projekt med namnet schedule-jobs med hjälp av följande kommando i kommandotolken. Observera att detta är ett enda långt kommando:

    mvn archetype:generate -DgroupId=com.mycompany.app -DartifactId=schedule-jobs -DarchetypeArtifactId=maven-archetype-quickstart -DinteractiveMode=false
    
  3. Gå till mappen schedule-jobs i kommandotolken.

  4. Med hjälp av en textredigerare öppnar du filen pom.xml i mappen schedule-jobs och lägger till följande beroende till noden beroenden. Med det här beroendet kan du använda iot-service-client-paketet i din app för att kommunicera med din IoT-hubb:

    <dependency>
      <groupId>com.microsoft.azure.sdk.iot</groupId>
      <artifactId>iot-service-client</artifactId>
      <version>1.17.1</version>
      <type>jar</type>
    </dependency>
    

    Kommentar

    Du kan söka efter den senaste versionen av iot-service-client med Maven-sökning.

  5. Lägg till följande byggnod efter noden beroenden. Den här konfigurationen instruerar Maven att använda Java 1.8 för att skapa appen:

    <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>
    
  6. Spara och stäng filen pom.xml.

  7. Öppna filen schedule-jobs\src\main\java\com\mycompany\app\App.java med hjälp av en textredigerare.

  8. Lägg till följande Import-instruktioner i filen:

    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;
    
  9. Lägg till följande variabler på klassnivå till klassen App. Ersätt {youriothubconnectionstring} med din IoT Hub-anslutningssträng som du kopierade tidigare i Hämta IoT Hub-anslutningssträng:

    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;
    
  10. Lägg till följande metod i klassen App för att schemalägga ett jobb för att uppdatera egenskaperna Byggnad och Golv i enhetstvillingen:

    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;
      }
    }
    
  11. Om du vill schemalägga ett jobb för att anropa metoden lockDoor lägger du till följande metod i klassen App :

    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;
      }
    };
    
  12. Om du vill övervaka ett jobb lägger du till följande metod i klassen App :

    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;
      }
    }
    
  13. Om du vill fråga efter information om de jobb som du körde lägger du till följande metod:

    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));
      }
    }
    
  14. Uppdatera huvudmetodsignaturen så att den innehåller följande throws sats:

    public static void main( String[] args ) throws Exception
    
  15. Om du vill köra och övervaka två jobb sekventiellt ersätter du koden i huvudmetoden med följande kod:

    // 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");
    
  16. Spara och stäng filen schedule-jobs\src\main\java\com\mycompany\app\App.java

  17. Skapa appen schedule-jobs och korrigera eventuella fel. I kommandotolken navigerar du till mappen schedule-jobs och kör följande kommando:

    mvn clean package -DskipTests
    

Skapa en enhetsapp

I det här avsnittet skapar du en Java-konsolapp som hanterar önskade egenskaper som skickas från IoT Hub och implementerar direktmetodanropet.

Viktigt!

Den här artikeln innehåller steg för att ansluta en enhet med en signatur för delad åtkomst, även kallad symmetrisk nyckelautentisering. Den här autentiseringsmetoden är praktisk för testning och utvärdering, men att autentisera en enhet med X.509-certifikat är en säkrare metod. Mer information finns i Metodtips > för säkerhet Anslutningssäkerhet.

  1. I mappen iot-java-schedule-jobs skapar du ett Maven-projekt med namnet simulated-device med hjälp av följande kommando i kommandotolken. Observera att detta är ett enda långt kommando:

    mvn archetype:generate -DgroupId=com.mycompany.app -DartifactId=simulated-device -DarchetypeArtifactId=maven-archetype-quickstart -DinteractiveMode=false
    
  2. Gå till mappen simulated-device i kommandotolken.

  3. Med hjälp av en textredigerare öppnar du filen pom.xml i mappen simulated-device och lägger till följande beroenden i noden dependencies . Med det här beroendet kan du använda iot-device-client-paketet i din app för att kommunicera med din IoT-hubb:

    <dependency>
      <groupId>com.microsoft.azure.sdk.iot</groupId>
      <artifactId>iot-device-client</artifactId>
      <version>1.17.5</version>
    </dependency>
    

    Kommentar

    Du kan söka efter den senaste versionen av iot-device-client med Maven-sökning.

  4. Lägg till följande beroende till noden beroenden. Det här beroendet konfigurerar en NOP för Apache SLF4J-loggningsfasaden , som används av enhetens klient-SDK för att implementera loggning. Den här konfigurationen är valfri, men om du utelämnar den kan du se en varning i konsolen när du kör appen. Mer information om loggning i enhetsklient-SDK finns i Loggningi exempel för Azure IoT-enhets-SDK för Java-readme-filen .

    <dependency>
      <groupId>org.slf4j</groupId>
      <artifactId>slf4j-nop</artifactId>
      <version>1.7.28</version>
    </dependency>
    
  5. Lägg till följande byggnod efter noden beroenden. Den här konfigurationen instruerar Maven att använda Java 1.8 för att skapa appen:

    <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>
    
  6. Spara och stäng filen pom.xml.

  7. Öppna filen simulated-device\src\main\java\com\mycompany\app\App.java med hjälp av en textredigerare.

  8. Lägg till följande Import-instruktioner i filen:

    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;
    
  9. Lägg till följande variabler på klassnivå till klassen App. Ersätt {yourdeviceconnectionstring} med enheten anslutningssträng du såg när du registrerade en enhet i din IoT Hub:

    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;
    

    Den här exempelappen använder variabeln protocol när den instantierar ett DeviceClient-objekt.

  10. Om du vill skriva ut enhetstvillingmeddelanden till konsolen lägger du till följande kapslade klass i klassen App :

    // 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());
      }
    }
    
  11. Om du vill skriva ut direktmetodmeddelanden till konsolen lägger du till följande kapslade klass i klassen App :

    // 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());
      }
    }
    
  12. Om du vill hantera direkta metodanrop från IoT Hub lägger du till följande kapslade klass i appklassen:

    // 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;
      }
    }
    
  13. Uppdatera huvudmetodsignaturen så att den innehåller följande throws sats:

    public static void main( String[] args ) throws IOException, URISyntaxException
    
  14. Ersätt koden i huvudmetoden med följande kod för att:

    • Skapa en enhetsklient för att kommunicera med IoT Hub.
    • Skapa ett enhetsobjekt för att lagra egenskaperna för enhetstvillingen.
    // 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);
      }
    };
    
  15. Om du vill starta klienttjänsterna för enheten lägger du till följande kod i huvudmetoden :

    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...");
    }
    
  16. Om du vill vänta tills användaren trycker på Retur-tangenten innan den stängs av lägger du till följande kod i slutet av huvudmetoden:

    // 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();
    
  17. Spara och stäng filen simulated-device\src\main\java\com\mycompany\app\App.java .

  18. Skapa appen simulated-device och korrigera eventuella fel. I kommandotolken navigerar du till mappen simulated-device och kör följande kommando:

    mvn clean package -DskipTests
    

Köra apparna

Nu är du redo att köra konsolapparna.

  1. I en kommandotolk i mappen simulated-device kör du följande kommando för att starta enhetsappen och lyssna efter önskade egenskapsändringar och direktmetodanrop:

    mvn exec:java -Dexec.mainClass="com.mycompany.app.App"
    

    Enhetsklienten startar

  2. Kör följande kommando i en kommandotolk i schedule-jobs mappen för att köra tjänstappen schedule-jobs för att köra två jobb. Den första anger önskade egenskapsvärden, den andra anropar direktmetoden:

    mvn exec:java -Dexec.mainClass="com.mycompany.app.App"
    

    Java IoT Hub-tjänstappen skapar två jobb

  3. Enhetsappen hanterar önskad egenskapsändring och direktmetodanropet:

    Enhetsklienten svarar på ändringarna

Nästa steg

I den här artikeln har du schemalagt jobb för att köra en direktmetod och uppdatera enhetstvillingens egenskaper.

Om du vill fortsätta utforska IoT Hub- och enhetshanteringsmönster uppdaterar du en avbildning i självstudiekursen Enhetsuppdatering för Azure IoT Hub med hjälp av Raspberry Pi 3 B+-referensbilden.