Share via


디바이스 관리 시작(Java)

백 엔드 앱에서는 디바이스 쌍직접 메서드 같은 Azure IoT Hub 기본 형식을 사용하여 디바이스에서 장치 관리 작업을 원격으로 시작하고 모니터링할 수 있습니다. 이 문서에서는 백 엔드 앱 및 디바이스 앱이 함께 작동하여 IoT Hub를 사용하여 원격 디바이스 다시 부팅을 시작하고 모니터링하는 방법을 보여 줍니다.

참고 항목

이 문서에서 설명하는 기능은 IoT Hub의 표준 계층에서만 사용할 수 있습니다. 기본 및 표준/무료 IoT Hub 계층에 대한 자세한 내용은 솔루션에 적합한 IoT Hub 계층 선택을 참조하세요.

직접 메서드를 사용하여 클라우드의 백 엔드 앱에서 디바이스 관리 작업(예: 재부팅, 초기화 및 펌웨어 업데이트)을 시작합니다. 디바이스는 다음과 같은 역할을 합니다.

  • IoT Hub에서 보낸 메서드 요청 처리.

  • 디바이스에서 해당하는 디바이스 특정 작업 시작.

  • reported 속성을 통해 IoT Hub에 상태 업데이트 제공.

클라우드에서 백 엔드 앱을 사용하여 디바이스 쌍 쿼리를 실행하고 디바이스 관리 작업의 진행 상태를 보고할 수 있습니다.

이 문서에서는 다음을 만드는 방법을 보여 줍니다.

  • simulated-device: 디바이스를 다시 부팅하고 마지막 다시 부팅 시간을 보고하는 직접 메서드가 있는 시뮬레이션된 디바이스 앱입니다. 직접 메서드는 클라우드에서 호출됩니다.

  • trigger-reboot: IoT 허브를 통해 시뮬레이션된 디바이스 앱에서 직접 메서드를 호출하는 Java 앱입니다. 응답 및 업데이트된 reported 속성을 표시합니다.

참고 항목

디바이스와 솔루션 백 엔드에서 실행할 애플리케이션을 빌드하는 데 사용할 수 있는 SDK에 대한 자세한 내용은 Azure IoT SDK를 참조하세요.

필수 조건

  • IoT 허브. CLI 또는 Azure Portal을 사용하여 만듭니다.

  • 등록된 디바이스. Azure Portal에 하나를 등록합니다.

  • Java SE Development Kit 8. JDK 8용 다운로드를 가져오려면 장기 지원에서 Java 8을 선택해야 합니다.

  • Maven 3

  • 방화벽에서 포트 8883이 열려 있는지 확인합니다. 이 문서의 디바이스 샘플은 포트 8883을 통해 통신하는 MQTT 프로토콜을 사용합니다. 이 포트는 일부 회사 및 교육용 네트워크 환경에서 차단될 수 있습니다. 이 문제를 해결하는 자세한 내용과 방법은 IoT Hub에 연결(MQTT)을 참조하세요.

직접 메서드를 사용하여 디바이스 앱 만들기

이 섹션에서는 디바이스를 시뮬레이트하는 Java 콘솔 앱을 만듭니다. 이 앱은 IoT Hub의 재부팅 직접 메서드 호출을 수신하고 그 즉시 해당 호출에 응답합니다. 그런 다음 잠시 유휴 상태로 전환하여 재부팅 프로세스를 시뮬레이트한 후 보고된 속성을 사용하여 trigger-reboot 백 엔드 앱에 재부팅이 완료되었음을 알립니다.

  1. 명령 프롬프트에서 다음 명령을 사용하여 dm-get-started 폴더에 simulated-device라는 Maven 프로젝트를 만듭니다.

    mvn archetype:generate -DgroupId=com.mycompany.app -DartifactId=simulated-device -DarchetypeArtifactId=maven-archetype-quickstart -DinteractiveMode=false
    
  2. 명령 프롬프트에서 simulated-device 폴더로 이동합니다.

  3. 텍스트 편집기를 사용하여 simulated-device 폴더에서 pom.xml 파일을 열고 종속성 노드에 다음 종속성을 추가합니다. 이러한 종속성을 통해 IoT Hub와 통신하도록 앱에서 iot-service-client 패키지를 사용할 수 있습니다.

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

    참고 항목

    Maven 검색을 사용하여 iot-device-client의 최신 버전을 확인할 수 있습니다.

  4. 종속성 노드에 다음 종속성을 추가합니다. 이 종속성은 디바이스 클라이언트 SDK에서 로깅을 구현하는 데 사용하는 Apache SLF4J 로깅 외관에 맞게 NOP를 구성합니다. 이 구성은 선택 사항이지만, 건너뛰면 앱을 실행할 때 콘솔에 경고가 표시될 수 있습니다. 디바이스 클라이언트 SDK에 로그인하는 방법에 대한 자세한 내용은 Java용 Azure IoT 디바이스 SDK 샘플 추가 정보 파일에서 로깅을 참조하세요.

    <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.time.LocalDateTime;
    import java.util.Scanner;
    import java.util.Set;
    import java.util.HashSet;
    
  9. 다음 클래스 수준 변수를 App 클래스에 추가합니다. {yourdeviceconnectionstring}을 IoT Hub에 디바이스를 등록할 때 본 디바이스 연결 문자열로 바꿉니다.

    private static final int METHOD_SUCCESS = 200;
    private static final int METHOD_NOT_DEFINED = 404;
    
    private static IotHubClientProtocol protocol = IotHubClientProtocol.MQTT;
    private static String connString = "{yourdeviceconnectionstring}";
    private static DeviceClient client;
    
  10. 직접 메서드 상태 이벤트에 대한 콜백 처리기를 구현하려면 App 클래스에 다음 중첩 클래스를 추가합니다.

    protected static class DirectMethodStatusCallback implements IotHubEventCallback
    {
      public void execute(IotHubStatusCode status, Object context)
      {
        System.out.println("IoT Hub responded to device method operation with status " + status.name());
      }
    }
    
  11. 디바이스 쌍 상태 이벤트에 대한 콜백 처리기를 구현하려면 App 클래스에 다음 중첩 클래스를 추가합니다.

    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());
        }
    }
    
  12. 속성 이벤트에 대한 콜백 처리기를 구현하려면 App 클래스에 다음 중첩 클래스를 추가합니다.

    protected static class PropertyCallback implements PropertyCallBack<String, String>
    {
      public void PropertyCall(String propertyKey, String propertyValue, Object context)
      {
        System.out.println("PropertyKey:     " + propertyKey);
        System.out.println("PropertyKvalue:  " + propertyKey);
      }
    }
    
  13. 디바이스 재부팅을 시뮬레이트하는 스레드를 구현하려면 App 클래스에 다음 중첩 클래스를 추가합니다. 이 스레드는 5초 동안 유휴 상태를 유지한 후 lastReboot 보고된 속성을 설정합니다.

    protected static class RebootDeviceThread implements Runnable {
      public void run() {
        try {
          System.out.println("Rebooting...");
          Thread.sleep(5000);
          Property property = new Property("lastReboot", LocalDateTime.now());
          Set<Property> properties = new HashSet<Property>();
          properties.add(property);
          client.sendReportedProperties(properties);
          System.out.println("Rebooted");
        }
        catch (Exception ex) {
          System.out.println("Exception in reboot thread: " + ex.getMessage());
        }
      }
    }
    
  14. 디바이스에서 직접 메서드를 구현하려면 App 클래스에 다음 중첩 클래스를 추가합니다. 시뮬레이트된 앱은 재부팅 직접 메서드에 대한 호출을 수신하면 호출자에게 수신 확인을 반환한 후 재부팅을 처리하기 위한 스레드를 시작합니다.

    protected static class DirectMethodCallback implements com.microsoft.azure.sdk.iot.device.DeviceTwin.DeviceMethodCallback
    {
      @Override
      public DeviceMethodData call(String methodName, Object methodData, Object context)
      {
        DeviceMethodData deviceMethodData;
        switch (methodName)
        {
          case "reboot" :
          {
            int status = METHOD_SUCCESS;
            System.out.println("Received reboot request");
            deviceMethodData = new DeviceMethodData(status, "Started reboot");
            RebootDeviceThread rebootThread = new RebootDeviceThread();
            Thread t = new Thread(rebootThread);
            t.start();
            break;
          }
          default:
          {
            int status = METHOD_NOT_DEFINED;
            deviceMethodData = new DeviceMethodData(status, "Not defined direct method " + methodName);
          }
        }
        return deviceMethodData;
      }
    }
    
  15. 다음 예외를 throw하도록 main 메서드의 서명을 수정합니다.

    public static void main(String[] args) throws IOException, URISyntaxException
    
  16. DeviceClient를 인스턴스화하려면 main 메서드의 코드를 다음 코드로 바꿉니다.

    System.out.println("Starting device client sample...");
    client = new DeviceClient(connString, protocol);
    
  17. 직접 메서드 호출 수신을 시작하려면 main 메서드에 다음 코드를 추가합니다.

    try
    {
      client.open();
      client.subscribeToDeviceMethod(new DirectMethodCallback(), null, new DirectMethodStatusCallback(), null);
      client.startDeviceTwin(new DeviceTwinStatusCallback(), null, new PropertyCallback(), null);
      System.out.println("Subscribed to direct methods and polling for reported properties. Waiting...");
    }
    catch (Exception e)
    {
      System.out.println("On exception, shutting down \n" + " Cause: " + e.getCause() + " \n" +  e.getMessage());
      client.close();
      System.out.println("Shutting down...");
    }
    
  18. 디바이스 시뮬레이터를 종료하려면 main 메서드에 다음 코드를 추가합니다.

    System.out.println("Press any key to exit...");
    Scanner scanner = new Scanner(System.in);
    scanner.nextLine();
    scanner.close();
    client.close();
    System.out.println("Shutting down...");
    
  19. simulated-device\src\main\java\com\mycompany\app\App.java 파일을 저장한 후 닫습니다.

  20. simulated-device 앱을 빌드하고 오류를 수정합니다. 명령 프롬프트에서 simulated-device 폴더로 이동한 후 다음 명령을 실행합니다.

    mvn clean package -DskipTests
    

IoT Hub 연결 문자열 가져오기

이 문서에서는 디바이스에서 직접 메서드를 호출하는 백 엔드 서비스를 만듭니다. IoT Hub를 통해 디바이스에서 직접 메서드를 호출하려면 서비스에 서비스 연결 권한이 있어야 합니다. 기본적으로 모든 IoT Hub는 이 사용 권한을 부여하는 service라는 공유 액세스 정책을 사용하여 만듭니다.

service 정책에 대한 IoT Hub 연결 문자열을 가져오려면 다음 단계를 수행합니다.

  1. Azure Portal에서 리소스 그룹을 선택합니다. 허브가 있는 리소스 그룹을 선택한 다음, 리소스 목록에서 허브를 선택합니다.

  2. IoT Hub의 왼쪽 창에서 공유 액세스 정책을 선택합니다.

  3. 정책 목록에서 ervice 정책을 선택합니다.

  4. 기본 연결 문자열을 복사하고 값을 저장합니다.

Screenshot that shows how to retrieve the connection string from your IoT Hub in the Azure portal.

IoT Hub 공유 액세스 정책 및 사용 권한에 대한 자세한 내용은 액세스 제어 및 권한을 참조하세요.

다시 부팅을 트리거하는 서비스 앱 만들기

이 섹션에서는 다음을 수행하는 Java 콘솔 앱을 만듭니다.

  1. 시뮬레이트된 디바이스 앱에서 재부팅 직접 메서드를 호출합니다.

  2. 응답을 표시합니다.

  3. 디바이스에서 보낸 보고된 속성을 폴링하여 재부팅이 완료되는 시간을 확인합니다.

이 콘솔 앱은 IoT Hub에 연결하여 직접 메서드를 호출하고 보고된 속성을 읽습니다.

  1. dm-get-started라는 빈 폴더를 만듭니다.

  2. 명령 프롬프트에서 다음 명령을 사용하여 dm-get-started 폴더에 trigger-reboot라는 Maven 프로젝트를 만듭니다.

    mvn archetype:generate -DgroupId=com.mycompany.app -DartifactId=trigger-reboot -DarchetypeArtifactId=maven-archetype-quickstart -DinteractiveMode=false
    
  3. 명령 프롬프트에서 trigger-reboot 폴더로 이동합니다.

  4. 텍스트 편집기를 사용하여 trigger-reboot 폴더에서 pom.xml 파일을 열고 종속성 노드에 다음 종속성을 추가합니다. 이러한 종속성을 통해 IoT Hub와 통신하도록 앱에서 iot-service-client 패키지를 사용할 수 있습니다.

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

    참고 항목

    Maven 검색을 사용하여 iot-service-client의 최신 버전을 확인할 수 있습니다.

  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. 텍스트 편집기를 사용하여 trigger-reboot\src\main\java\com\mycompany\app\App.java 원본 파일을 엽니다.

  8. 파일에 다음 import 문을 추가합니다.

    import com.microsoft.azure.sdk.iot.service.devicetwin.DeviceMethod;
    import com.microsoft.azure.sdk.iot.service.devicetwin.MethodResult;
    import com.microsoft.azure.sdk.iot.service.exceptions.IotHubException;
    import com.microsoft.azure.sdk.iot.service.devicetwin.DeviceTwin;
    import com.microsoft.azure.sdk.iot.service.devicetwin.DeviceTwinDevice;
    
    import java.io.IOException;
    import java.util.concurrent.TimeUnit;
    import java.util.concurrent.Executors;
    import java.util.concurrent.ExecutorService;
    
  9. 다음 클래스 수준 변수를 App 클래스에 추가합니다. {youriothubconnectionstring}을 이전에 IoT Hub 연결 문자열 가져오기에서 복사한 IoT Hub 연결 문자열로 바꿉니다.

    public static final String iotHubConnectionString = "{youriothubconnectionstring}";
    public static final String deviceId = "myDeviceId";
    
    private static final String methodName = "reboot";
    private static final Long responseTimeout = TimeUnit.SECONDS.toSeconds(30);
    private static final Long connectTimeout = TimeUnit.SECONDS.toSeconds(5);
    
  10. 디바이스 쌍에서 10초마다 보고되는 속성을 읽는 스레드를 구현하려면 App 클래스에 다음 중첩 클래스를 추가합니다.

    private static class ShowReportedProperties implements Runnable {
      public void run() {
        try {
          DeviceTwin deviceTwins = DeviceTwin.createFromConnectionString(iotHubConnectionString);
          DeviceTwinDevice twinDevice = new DeviceTwinDevice(deviceId);
          while (true) {
            System.out.println("Get reported properties from device twin");
            deviceTwins.getTwin(twinDevice);
            System.out.println(twinDevice.reportedPropertiesToString());
            Thread.sleep(10000);
          }
        } catch (Exception ex) {
          System.out.println("Exception reading reported properties: " + ex.getMessage());
        }
      }
    }
    
  11. 다음 예외를 throw하도록 main 메서드의 서명을 수정합니다.

    public static void main(String[] args) throws IOException
    
  12. 시뮬레이트된 디바이스에서 재부팅 직접 메서드를 호출하려면 main 메서드의 코드를 다음 코드로 바꿉니다.

    System.out.println("Starting sample...");
    DeviceMethod methodClient = DeviceMethod.createFromConnectionString(iotHubConnectionString);
    
    try
    {
      System.out.println("Invoke reboot direct method");
      MethodResult result = methodClient.invoke(deviceId, methodName, responseTimeout, connectTimeout, null);
    
      if(result == null)
      {
        throw new IOException("Invoke direct method reboot returns null");
      }
      System.out.println("Invoked reboot on device");
      System.out.println("Status for device:   " + result.getStatus());
      System.out.println("Message from device: " + result.getPayload());
    }
    catch (IotHubException e)
    {
        System.out.println(e.getMessage());
    }
    
  13. 시뮬레이트된 디바이스에서 보고된 속성을 스레드가 폴링을 시작하도록 하려면 main 메서드에 다음 코드를 추가합니다.

    ShowReportedProperties showReportedProperties = new ShowReportedProperties();
    ExecutorService executor = Executors.newFixedThreadPool(1);
    executor.execute(showReportedProperties);
    
  14. 앱을 중지할 수 있도록 하려면 main 메서드에 다음 코드를 추가합니다.

    System.out.println("Press ENTER to exit.");
    System.in.read();
    executor.shutdownNow();
    System.out.println("Shutting down sample...");
    
  15. trigger-reboot\src\main\java\com\mycompany\app\App.java 파일을 저장한 후 닫습니다.

  16. trigger-reboot 백 엔드 앱을 빌드하고 오류를 수정합니다. 명령 프롬프트에서 trigger-reboot 폴더로 이동한 후 다음 명령을 실행합니다.

    mvn clean package -DskipTests
    

앱 실행

이제 앱을 실행할 준비가 되었습니다.

  1. simulated-device 폴더의 명령 프롬프트에서 다음 명령을 실행하여 IoT Hub의 재부팅 메서드 호출에 대한 수신 대기를 시작합니다.

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

    Java IoT Hub simulated device app to listen for reboot direct method calls

  2. trigger-reboot 폴더의 명령 프롬프트에서 다음 명령을 실행하여 IoT Hub의 시뮬레이트된 디바이스에 대해 재부팅 메서드를 호출합니다.

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

    Java IoT Hub service app to call the reboot direct method

  3. 시뮬레이트된 디바이스는 재부팅 직접 메서드 호출에 응답합니다.

    Java IoT Hub simulated device app responds to the direct method call

디바이스 관리 작업 사용자 지정 및 확장

IoT 솔루션에서 정의된 디바이스 관리 패턴 집합을 확장하거나 디바이스 쌍 및 클라우드-디바이스 메서드 기본 형식을 사용하여 사용자 지정 패턴을 활성화하도록 설정할 수 있습니다. 디바이스 관리 작업의 다른 예로 공장 재설정, 펌웨어 업데이트, 소프트웨어 업데이트, 전원 관리, 네트워크 및 연결 관리, 데이터 암호화가 있습니다.

디바이스 유지 관리 기간

일반적으로 서비스 중단 및 가동 중지 시간을 최소화하면서 작업을 수행하도록 디바이스를 구성합니다. 디바이스 유지 관리 기간은 디바이스에서 해당 구성을 업데이트해야 할 경우 시간을 정의하는 데 널리 사용되는 패턴입니다. 백 엔드 솔루션에서는 디바이스 쌍의 desired 속성을 사용하여 유지 관리 기간을 사용하는 디바이스에 대한 정책을 정의하고 활성화할 수 있습니다. 디바이스에서 유지 관리 기간 정책을 수신하면 디바이스 쌍의 reported 속성을 사용하여 정책의 상태를 보고할 수 있습니다. 그런 다음, 백 엔드 앱은 디바이스 쌍 쿼리를 사용하여 디바이스 및 각 정책의 규정 준수를 입증합니다.

다음 단계

이 문서에서는 디바이스에서 원격 다시 시작을 트리거하는 데 직접 메서드를 사용했습니다. 보고된 속성을 사용하여 디바이스에서 마지막으로 다시 시작한 시간을 보고하고, 디바이스 쌍을 쿼리하여 디바이스가 클라우드에서 마지막으로 다시 시작한 시간을 확인했습니다.

Raspberry Pi 3 B+ 참조 이미지를 사용한 Device Update for Azure IoT Hub 문서에서 IoT Hub 및 엔드투엔드 이미지 기반 업데이트와 같은 디바이스 관리 패턴을 계속 시작하려면

IoT 솔루션을 확장하고 여러 디바이스에서 메서드 호출을 예약하는 방법을 알아보려면 jobs 예약 및 브로드캐스트를 참조하세요.