جدولة مهام البث (Java)

استخدم مركز loT لـ Azure لجدولة المهام التي تحدث ملايين الأجهزة وتعقبها. استخدام الوظائف لإجراء ما يلي:

  • تحديث الخصائص المطلوبة
  • تحديث العلامات
  • استدعاء أساليب مباشرة

تضمن الوظيفة أحد هذه الإجراءات وتعقب التنفيذ مقابل مجموعة من الأجهزة. يحدد استعلام الجهاز المزدوج مجموعة الأجهزة التي تنفذ الوظيفة مقابلها. على سبيل المثال، يمكن للتطبيق الخلفي استخدام مهمة لاستدعاء أسلوب مباشر على 10,000 جهاز يعيد تشغيل الأجهزة. يمكنك تحديد مجموعة الأجهزة مع استعلام جهاز مزدوج وجدولة المهمة للتشغيل في وقت مستقبلي. تتعقب المهمة مدى التقدم حيث يتلقى كل جهاز أسلوب إعادة التشغيل المباشر وينفذه.

لمعرفة المزيد حول كل من هذه القدرات، اطلع على ما يلي:

إشعار

تتوفر الميزات الموضحة في هذه المقالة فقط في المستوى القياسي لمركز إنترنت الأشياء. لمزيد من المعلومات حول مستويات IoT Hub الأساسية والقياسية/المجانية، راجع اختيار طبقة IoT Hub المناسبة للحل الخاص بك.

توضح لك هذه المقالة كيفية إنشاء تطبيقي Java:

  • تطبيق جهاز، simulated-device، ينفذ أسلوبًا مباشرًا يسمى LockDoor، والذي يمكن استدعاؤه بواسطة التطبيق الخلفي.

  • تطبيق خلفي، schedule-jobs، يقوم بإنشاء وظيفتين. تستدعي إحدى الوظائف الأسلوب المباشر lockDoor وترسل مهمة أخرى تحديثات الخصائص المطلوبة إلى أجهزة متعددة.

إشعار

راجع Azure IoT SDKs لمزيد من المعلومات حول أدوات SDK المتوفرة لإنشاء كل من الجهاز والتطبيقات الخلفية.

المتطلبات الأساسية

  • مركز IoT في اشتِراك Azure الخاص بك. إذا لم تكن لديك مركز بعد، فإنه يمكنك اتباع الخطوات الواردة في إنشاء مركز IoT.

  • جهاز مسجل في مركز IoT الخاص بك. إذا لم يكن لديك جهاز في مركز IoT، فاتبع الخطوات الواردة في تسجيل جهاز.

  • حزمة تطور Java SE 8. تأكد من تحديد Java 8 ضمن الدعم طويل الأجل للوصول إلى التنزيلات لـ JDK 8.

  • Maven 3

  • تأكد من أن المنفذ 8883 مفتوح في جدار الحماية. يستخدم نموذج الجهاز في هذه المقالة بروتوكول MQTT، الذي يتصل عبر المنفذ 8883. قد يُحظر هذا المنفذ في بعض بيئات الشبكات التعليمية، وشبكات الشركات. لمزيد من المعلومات وطرق التغلب على هذه المشكلة، راجع الاتصال بمركز IoT (MQTT).

إشعار

للحفاظ على بساطة الأمور، لا تنفذ هذه المقالة سياسة إعادة المحاولة. في كود الإنتاج، يجب عليك تنفيذ نُهج إعادة المحاولة (مثل التراجع الأسي)، كما هو مقترح في المقالة، معالجة الأخطاء المؤقتة.

الحصول على سلسلة اتصال IoT Hub

في هذه المقالة، تقوم بإنشاء خدمة خلفية تقوم بجدولة مهمة لاستدعاء أسلوب مباشر على أحد الأجهزة، وتقوم بجدولة مهمة لتحديث الجهاز المزدوج، وتراقب تقدم كل وظيفة. لتنفيذ هذه العمليات، تحتاج خدمتك إلى أذونات قراءة السجل وكتابة السجل. افتراضيًا، يتم إنشاء كافة مراكز IoT باستخدام نهج الوصول المشترك يسمى registryReadWrite التي تمنح هذه الأذونات.

للحصول على سلسلة اتصال IoT Hub لنهج RegistryReadWrite، اتبع الخطوات التالية:

  1. في مدخل Microsoft Azure، حدد Resource groups. حدد مجموعة الموارد حيث يوجد المركز الخاص بك، ثم حدد المركز الخاص بك من قائمة الموارد.

  2. في الجزء الأيسر من مركز IoT، قم بتحديد Shared access policies.

  3. من قائمة النهج، حدد نهج registryReadWrite.

  4. انسخ سلسلة الاتصال الأساسية واحفظ القيمة.

    لقطة شاشة تعرض الطريقة لاسترداد سلسلة الاتصال

للمزيد من المعلومات حول نهج الوصول المشترك لـIoT Hub والأذونات، راجع التحكم في الوصول والأذونات.

أنشئ تطبيق الخدمة

في هذا القسم، يمكنك إنشاء تطبيق وحدة تحكم Java يستخدم الوظائف لإجراء ما يلي:

  • استدعاء الأسلوب المباشر lockDoor على أجهزة متعددة.

  • أرسل الخصائص المطلوبة إلى أجهزة متعددة.

لإنشاء التطبيق:

  1. على جهاز التطوير الخاص بك، أنشئ مجلدًا فارغًا يسمى iot-java-schedule-jobs.

  2. في مجلد iot-java-schedule-jobs، أنشئ مشروع Maven يسمى schedule-jobs باستخدام الأمر التالي في موجه الأوامر. لاحظ أن هذا أمر واحد طويل:

    mvn archetype:generate -DgroupId=com.mycompany.app -DartifactId=schedule-jobs -DarchetypeArtifactId=maven-archetype-quickstart -DinteractiveMode=false
    
  3. في موجه الأوامر، انتقل إلى مجلد schedule-jobs.

  4. باستخدام محرر نصوص، افتح الملف pom.xml في مجلد schedule-jobs وأضف التبعية التالية إلى عقدة dependencies. تمكنك هذه التبعية من استخدام حزمة iot-service-client في تطبيقك للاتصال بـ IoT Hub الخاص بك:

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

    إشعار

    يمكنك التحقق من أحدث إصدار من iot-service-client باستخدام Maven search.

  5. أضف عقدة إنشاء التالية بعد عقدة التبعيات. يوجه هذا التكوين Maven لاستخدام Java 1.8 لإنشاء التطبيق:

    <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. حفظ ملف pom.xml وإغلاقه.

  7. باستخدام محرر نصوص، افتح ملف schedule-jobs\src\main\java\com\mycompany\app\App.java.

  8. أضف عبارات import التالية إلى الملف:

    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. أضف متغيرات مستوى الفئة التالية إلى فئة التطبيق. استبدل {youriothubconnectionstring} بسلسلة اتصال IoT Hub التي نسختها مسبقاً في الحصول على سلسلة اتصال IoT Hub:

    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. أضف الأسلوب التالي إلى فئة التطبيق لجدولة مهمة لتحديث الخصائص المطلوبة للإنشاء والطابق في الجهاز المزدوج:

    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. لجدولة مهمة لاستدعاء أسلوب lockDoor، أضف الأسلوب التالي إلى فئة التطبيق:

    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. لمراقبة مهمة، أضف الأسلوب التالي إلى فئة التطبيق:

    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. للاستعلام عن تفاصيل المهام التي شغلتها، أضف الأسلوب التالي:

    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. حدّث توقيع الأسلوب الرئيسي لتضمين عبارة throws التالية:

    public static void main( String[] args ) throws Exception
    
  15. لتشغيل ومراقبة مهمتين بشكل تسلسلي، استبدل التعليمات البرمجية في الأسلوب الرئيسي بالتعليمات البرمجية التالية:

    // 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. احفظ ملف schedule-jobs\src\main\java\com\mycompany\app\App.java وأغلقه.

  17. إنشاء تطبيق schedule-jobs وتصحيح أي أخطاء. في موجه الأوامر، انتقل إلى مجلد schedule-jobs وشغل الأمر التالي:

    mvn clean package -DskipTests
    

أنشئ تطبيقاً للجهاز

في هذا القسم، يمكنك إنشاء تطبيق وحدة تحكم Java يعالج الخصائص المطلوبة المرسلة من IoT Hub وينفذ استدعاء الأسلوب المباشر.

  1. في مجلد iot-java-schedule-jobs، أنشئ مشروع Maven يسمى simulated-device باستخدام الأمر التالي في موجه الأوامر. لاحظ أن هذا أمر واحد طويل:

    mvn archetype:generate -DgroupId=com.mycompany.app -DartifactId=simulated-device -DarchetypeArtifactId=maven-archetype-quickstart -DinteractiveMode=false
    
  2. في موجه الأوامر، انتقل إلى المجلد simulated-device.

  3. باستخدام محرر نصوص، افتح الملف pom.xml في مجلد schedule-jobs وأضف التبعية التالية إلى عقدة dependencies. تمكنك هذه التبعية من استخدام حزمة iot-device-client في تطبيقك للاتصال بـ IoT Hub الخاص بك:

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

    إشعار

    يمكنك التحقق من أحدث إصدار من iot-device-client باستخدام Maven search.

  4. أضف التبعية التالية إلى عقدة التبعيات. تهيئ هذه التبعية NOP لواجهة تسجيل Apache SLF4J، والتي يتم استخدامها بواسطة عميل الجهاز SDK لتنفيذ التسجيل. هذا التكوين اختياري، ولكن إذا حذفته، فقد ترى تحذيرًا في وحدة التحكم عند تشغيل التطبيق. لمزيد من المعلومات حول تسجيل الدخول إلى عدة تطوير البرامج لعميل الجهاز، راجع تسجيل الدخول إلى عينات لملف عدة تطوير البرامج لجهاز Azure IoT لـ Java readme.

    <dependency>
      <groupId>org.slf4j</groupId>
      <artifactId>slf4j-nop</artifactId>
      <version>1.7.28</version>
    </dependency>
    
  5. أضف عقدة إنشاء التالية بعد عقدة التبعيات. يوجه هذا التكوين Maven لاستخدام Java 1.8 لإنشاء التطبيق:

    <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. حفظ ملف pom.xml وإغلاقه.

  7. باستخدام محرر نصوص، افتح الملف simulated-device\src\main\java\com\mycompany\app\App.java.

  8. أضف عبارات import التالية إلى الملف:

    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. أضف متغيرات مستوى الفئة التالية إلى فئة التطبيق. استبدل {yourdeviceconnectionstring} بسلسلة اتصال الجهاز التي رأيتها عند تسجيل جهاز في 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;
    

    يستخدم هذا النموذج من التطبيق متغير البروتوكول عندما ينشئ عنصر DeviceClient.

  10. لطباعة إخطارات الجهاز المزدوج إلى وحدة التحكم، أضف الفئة المتداخلة التالية إلى فئة التطبيق:

    // 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. لطباعة إخطارات الأسلوب المباشر إلى وحدة التحكم، أضف الفئة المتداخلة التالية إلى فئة التطبيق:

    // 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. لمعالجة استدعاءات الأسلوب المباشر من IoT Hub، أضف الفئة المتداخلة التالية إلى فئة التطبيق:

    // 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. حدّث توقيع الأسلوب الرئيسي لتضمين عبارة throws التالية:

    public static void main( String[] args ) throws IOException, URISyntaxException
    
  14. استبدل التعليمة البرمجية في الطريقة main بالتعليمة البرمجية التالية من أجل:

    • أنشئ عميل جهاز للتواصل مع IoT Hub.
    • أنشئ عنصر جهاز لتخزين خصائص الجهاز المزدوج.
    // 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. لبدء خدمات عميل الجهاز، أضف التعليمات البرمجية التالية إلى الأسلوب الرئيسي:

    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. لانتظار المستخدم للضغط على المفتاح Enter قبل إيقاف التشغيل، أضف التعليمات البرمجية التالية إلى نهاية الأسلوب الرئيسي:

    // 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. احفظ ملف simulated-device\src\main\java\com\mycompany\app\App.java وأغلقه.

  18. أنشئ تطبيق simulated-device وصحح أي أخطاء. في موجه الأوامر، انتقل إلى المجلد simulated-device وقم بتشغيل الأمر التالي:

    mvn clean package -DskipTests
    

قم بتشغيل التطبيقات

أنت الآن جاهز لتشغيل تطبيقات وحدة التحكم.

  1. في موجه الأوامر في مجلد simulated-device، شغل الأمر التالي لبدء تطبيق الجهاز الاستماع إلى تغييرات الخاصية المطلوبة واستدعاءات الأسلوب المباشر:

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

    يبدأ تشغيل عميل الجهاز

  2. في موجه الأوامر في schedule-jobs المجلد، شغل الأمر التالي لتشغيل تطبيق خدمة schedule-jobs لتشغيل مهمتين. تقوم المهمة الأول بتعيين قيم الخاصية المطلوبة، والثانية تستدعي الأسلوب المباشر:

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

    ينشئ تطبيق خدمة Java IoT Hub مهمتين

  3. يعالج تطبيق الجهاز تغيير الخاصية المطلوبة واستدعاء الأسلوب المباشر:

    عميل الجهاز يستجيب للتغييرات

الخطوات التالية

في هذه المقالة، قمت بجدولة المهام لتشغيل أسلوب مباشر وتحديث خصائص توأم الجهاز.

لمتابعة استكشاف IoT Hub وأنماط إدارة الجهاز، قم بتحديث صورة في البرنامج التعليمي Device Update for Azure IoT Hub باستخدام Raspberry Pi 3 B + صورة مرجعية.