다음을 통해 공유


MQTT 프로토콜을 사용하여 IoT 허브와 통신

이 문서에서는 지원되는 MQTT 동작을 사용하여 디바이스에서 Azure IoT Hub와 통신할 수 있는 방법을 설명합니다. IoT Hub를 사용하면 다음을 사용하여 IoT Hub 디바이스 엔드포인트와 통신할 수 있습니다.

  • 8883 TCP 포트의 MQTT v3.1.1
  • 443 TCP 포트의 WebSocket을 통한 MQTT v3.1.1

참고 항목

클라우드-디바이스 메시지, 디바이스 트윈스, 디바이스 관리 등 이 문서에 언급된 일부 기능은 IoT Hub의 표준 계층에서만 사용할 수 있습니다. 기본 및 표준/무료 IoT Hub 계층에 대한 자세한 내용은 솔루션에 적합한 IoT Hub 계층 선택을 참조하세요.

IoT Hub와 통신하는 모든 디바이스는 TLS/SSL을 사용하여 보호되어야 합니다. 따라서 IoT Hub는 1883 TCP 포트를 통한 비보안 연결을 지원하지 않습니다.

IoT Hub 및 Event Grid에서 MQTT 지원 비교

IoT Hub는 모든 기능을 갖춘 MQTT broker가 아니며 MQTT v3.1.1 표준에 지정된 모든 동작을 지원하지는 않습니다. 솔루션에 MQTT가 필요한 경우 Azure Event Grid에서 MQTT를 지원하는 것이 좋습니다. Event Grid를 사용하면 pub-sub 메시징 모델을 사용하여 유연한 계층적 토픽에서 MQTT 클라이언트 간에 양방향 통신을 수행할 수 있습니다. 또한 추가 처리를 위해 MQTT 메시지를 Azure 서비스 또는 사용자 지정 엔드포인트로 라우팅할 수 있습니다.

다음 표에서는 두 서비스 간의 MQTT 지원의 차이점을 설명합니다.

IoT Hub Event Grid
디바이스와 클라우드 앱이 긴밀하게 결합된 클라이언트-서버 모델 게시자와 구독자를 분리하는 게시-구독 모델
MQTT v3.1.1에 대해 제한된 기능 지원 및 미리 보기 모드의 MQTT v5에 대해 제한된 기능 지원. 예정된 추가 기능 지원 없음 더 많은 기능 지원 및 업계 규정 준수가 계획된 MQTT v3.1.1 및 v5 프로토콜 지원
정적 미리 정의된 토픽 와일드카드가 지원되는 사용자 지정 계층적 토픽
클라우드-디바이스 브로드캐스트 및 디바이스-디바이스 통신 지원하지 않음 디바이스-클라우드, 높은 팬아웃 클라우드-디바이스 브로드캐스트 및 디바이스-디바이스 통신 패턴 지원
최대 메시지 크기 - 256KB 최대 메시지 크기 - 512KB

IoT Hub에 연결

디바이스는 다음 옵션을 통해 MQTT 프로토콜을 사용하여 IoT 허브에 연결할 수 있습니다.

MQTT 포트(8883 TCP 포트)는 많은 회사 및 교육 네트워킹 환경에서 차단됩니다. 방화벽에서 8883 포트를 열 수 없는 경우 WebSocket을 통한 MQTT를 사용하는 것이 좋습니다. WebSocket을 통한 MQTT는 네트워킹 환경에서 거의 항상 열려 있는 443 포트를 통해 통신합니다. Azure IoT SDK를 사용하는 경우 MQTT 및 WebSocket을 통한 MQTT 프로토콜을 지정하는 방법을 알아보려면 디바이스 SDK 사용을 참조하세요.

디바이스 SDK 사용

MQTT 프로토콜을 지원하는 디바이스 SDK는 Java, Node.js, C, C# 및 Python에서 사용할 수 있습니다. 디바이스 SDK는 선택한 인증 메커니즘을 사용하여 IoT 허브에 대한 연결을 설정합니다. MQTT 프로토콜을 사용하려면 클라이언트 프로토콜 매개 변수를 MQTT에 설정해야 합니다. 클라이언트 프로토콜 매개 변수에서 WebSocket을 통한 MQTT를 지정할 수도 있습니다. 기본적으로는 디바이스 SDK는 CleanSession 플래그가 0으로 설정된 IoT Hub에 연결되고 QoS 1을 사용하여 IoT Hub와 메시지를 교환합니다. 더 빠른 메시지 교환을 위해 QoS 0을 구성할 수 있지만 전송이 보장되거나 승인되지 않는다는 점에 유의해야 합니다. 이러한 이유로 QoS 0을 종종 “실행 후 망각”이라고 부릅니다.

디바이스가 IoT Hub에 연결되면 디바이스 SDK는 IoT Hub와 메시지를 교환할 수 있게 하는 메서드를 제공합니다.

다음 표에는 지원되는 각 언어의 코드 샘플에 대한 링크가 있고, MQTT 또는 WebSocket을 통한 MQTT 프로토콜을 사용하여 IoT Hub에 대한 연결을 설정하는 데 사용할 매개 변수를 지정합니다.

언어 MQTT 프로토콜 매개 변수 WebSocket을 통한 MQTT 프로토콜 매개 변수
Node.JS azure-iot-device-mqtt.Mqtt azure-iot-device-mqtt.MqttWs
Java IotHubClientProtocol.MQTT IotHubClientProtocol.MQTT_WS
C MQTT_Protocol MQTT_WebSocket_Protocol
C# TransportType.Mqtt MQTT가 실패하는 경우 TransportType.Mqtt는 WebSocket을 통한 MQTT로 대체됩니다. WebSocket을 통한 MQTT만 지정하려면 TransportType.Mqtt_WebSocket_Only를 사용합니다.
Python 기본적으로 MQTT를 지원합니다. 호출에 websockets=True를 추가하여 클라이언트를 만듭니다.

다음 조각에서는 Azure IoT Node.js SDK를 사용하는 경우 WebSocket을 통한 MQTT 프로토콜을 지정하는 방법을 보여줍니다.

var Client = require('azure-iot-device').Client;
var Protocol = require('azure-iot-device-mqtt').MqttWs;
var client = Client.fromConnectionString(deviceConnectionString, Protocol);

다음 조각에서는 Azure IoT Python SDK를 사용하는 경우 WebSocket을 통한 MQTT 프로토콜을 지정하는 방법을 보여줍니다.

from azure.iot.device.aio import IoTHubDeviceClient
device_client = IoTHubDeviceClient.create_from_connection_string(deviceConnectionString, websockets=True)

Important

이 문서에서는 공유 액세스 서명(대칭 키 인증이라고도 함)을 사용하여 디바이스를 연결하는 단계를 설명합니다. 이 인증 방법은 테스트와 평가에 편리하지만, X.509 인증서를 사용하여 디바이스를 인증하는 것이 더 안전한 방식입니다. 자세한 내용은 보안 모범 사례 > 연결 보안을 참조하세요.

기본 keep-alive 시간 제한

클라이언트/IoT Hub 연결을 유지하기 위해 서비스와 클라이언트는 둘 다 서로에게 정기적으로 keep-alive ping을 전송합니다. IoT SDK를 사용하는 클라이언트는 연결 유지를 아래 표에 정의된 간격으로 보냅니다.

언어 기본 keep-alive 간격 구성 가능 여부
Node.js 180초 아니요
Java 230초
C 240초
C# 300초*
Python 60초

*C# SDK는 MQTT KeepAliveInSeconds 속성의 기본값을 300초로 정의합니다. 실제로 SDK는 연결 유지 기간 집합당 ping 요청을 4회 보냅니다. 즉, SDK는 75초마다 한 번씩 keep-alive ping을 보냅니다.

MQTT v3.1.1 사양에 따라 IoT Hub의 연결 유지 ping 간격은 클라이언트 연결 유지 값의 1.5배입니다. 그러나 IoT Hub는 서버 쪽 최대 시간 제한을 29.45분(1,767초)으로 제한합니다. 이 제한은 모든 Azure 서비스가 Azure 부하 분산 장치 TCP 유휴 시간 제한(29.45분)에 바인딩되기 때문입니다.

예를 들어 Java SDK를 사용하는 디바이스는 keep-alive ping을 전송한 다음 네트워크 연결이 해제됩니다. 230초 후에 디바이스는 오프라인 상태이기 때문에 keep-alive ping을 놓칩니다. 그러나 IoT Hub는 즉시 연결을 닫지 않습니다. 디바이스의 연결을 끊기 전에 또 다른 (230 * 1.5) - 230 = 115초 동안 대기하고 404104 DeviceConnectionClosedRemotely 오류가 발생합니다.

설정할 수 있는 최대 클라이언트 keep-alive 값은 1767 / 1.5 = 1177초입니다. 모든 트래픽은 keep-alive를 다시 설정합니다. 예를 들어 SAS(공유 액세스 서명) 토큰 새로 고침이 성공하면 연결 유지가 다시 설정됩니다.

디바이스 앱을 AMQP에서 MQTT로 마이그레이션

디바이스 SDK를 사용하는 경우 AMQP에서 MQTT 사용으로 전환하려면 이전에 언급한 대로 클라이언트 초기화에서 프로토콜 매개 변수를 변경해야 합니다.

이렇게 할 경우 다음 항목을 확인해야 합니다.

  • AMQP는 많은 조건에 대한 오류를 반환하는 한편 MQTT는 연결을 종료합니다. 결과적으로 예외 처리 논리를 일부 변경해야 합니다.

  • MQTT는 클라우드-디바이스 메시지를 수신할 때 reject 작업을 지원하지 않습니다. 백 엔드 앱이 디바이스 앱에서 응답을 수신해야 할 경우 직접 메서드 사용을 고려합니다.

  • AMQP는 Python SDK에서 지원되지 않습니다.

MQTT 프로토콜 직접 사용(디바이스로)

디바이스가 디바이스 SDK를 사용할 수 없는 경우라도 포트 8883에서 MQTT 프로토콜을 사용하는 공용 디바이스 엔드포인트에 연결할 수 있습니다.

CONNECT 패킷에서 디바이스는 다음 값을 사용해야 합니다.

  • ClientId 필드에 deviceId를 사용합니다.

  • Username 필드에 {iotHub-hostname}/{device-id}/?api-version=2021-04-12를 사용합니다. 여기서 {iotHub-hostname}은 IoT 허브의 전체 CName입니다.

    예를 들어, IoT Hub의 이름이 contoso.azure devices.net이고 디바이스의 이름이 MyDevice01이면 전체 Username 필드에 다음이 포함되어야 합니다.

    contoso.azure-devices.net/MyDevice01/?api-version=2021-04-12

    필드에는 api-version을 포함하는 것이 좋습니다. 그러지 않으면 예기치 않은 동작이 발생할 수 있습니다.

  • 암호 필드에는 SAS 토큰을 사용합니다. SAS 토큰의 형식은 HTTPS 및 AMQP 프로토콜에 대해 동일합니다.

    SharedAccessSignature sig={signature-string}&se={expiry}&sr={URL-encoded-resourceURI}

    참고 항목

    X.509 인증서 인증을 사용하는 경우 SAS 토큰 암호는 필요하지 않습니다. 자세한 내용은 자습서: 테스트를 위한 인증서 만들기 및 업로드를 참조하고 TLS/SSL 구성 섹션의 코드 지침을 따르세요.

    SAS 토큰을 생성하는 방법에 대한 자세한 내용은 공유 액세스 서명을 사용하여 IoT Hub에 대한 액세스 제어SAS 토큰을 디바이스로 사용 섹션을 참조하세요.

    또한 플랫폼 간 Visual Studio Code용 Azure IoT Hub 확장 또는 az iot hub generate-sas-token CLI 확장 명령을 사용하여 SAS 토큰을 빠르게 생성할 수 있습니다. 그런 다음, 테스트를 위해 SAS 토큰을 복사하여 사용자 고유의 코드에 붙여넣을 수 있습니다.

MQTT를 직접 사용하는 방법에 대한 자습서는 디바이스 SDK를 사용하지 않고 MQTT를 사용하여 IoT 디바이스 클라이언트 개발을 참조하세요.

Visual Studio Code용 Azure IoT Hub 확장 사용

  1. 사이드바의 Azure IoT Hub 섹션 아래에서 디바이스 노드를 확장합니다.

  2. IoT 디바이스를 마우스 오른쪽 단추로 클릭하고 바로 가기 메뉴에서 디바이스에 대한 SAS 토큰 생성을 선택합니다.

  3. 입력 상자에 SAS 토큰의 만료 시간(시간)을 입력한 다음 Enter 키를 선택합니다.

  4. SAS 토큰이 생성되어 클립보드에 복사됩니다.

    생성되는 SAS 토큰은 다음 구조를 갖습니다.

    HostName={iotHub-hostname};DeviceId=javadevice;SharedAccessSignature=SharedAccessSignature sr={iotHub-hostname}%2Fdevices%2FMyDevice01%2Fapi-version%3D2016-11-14&sig=vSgHBMUG.....Ntg%3d&se=1456481802

    이 토큰에서 MQTT를 사용하여 연결할 때 암호 필드에서와 같이 사용하는 부분은 다음과 같습니다.

    SharedAccessSignature sr={iotHub-hostname}%2Fdevices%2FMyDevice01%2Fapi-version%3D2016-11-14&sig=vSgHBMUG.....Ntg%3d&se=1456481802

디바이스 앱은 CONNECT 패킷에 Will 메시지를 지정할 수 있습니다. 디바이스 앱은 devices/{device-id}/messages/events/ 또는 devices/{device-id}/messages/events/{property-bag}Will 항목 이름으로 사용하여 원격 분석 메시지로서 전달할 Will 메시지를 정의할 수 있습니다. 이 경우 네트워크 연결이 닫혀 있지만 DISCONNECT 패킷이 이전에 디바이스에서 수신되지 않은 경우 IoT Hub는 CONNECT 패킷에 제공된 Will 메시지를 원격 분석 채널로 전송합니다. 원격 분석 채널은 기본 이벤트 엔드포인트 또는 IoT Hub 라우팅으로 정의되는 사용자 지정 엔드포인트일 수 있습니다. 메시지에는 Will 값이 할당된 iothub MessageType 속성이 지정됩니다.

MQTT 프로토콜 직접 사용(모듈로)

디바이스로 IoT Hub에 연결하는 것과 비슷하게 모듈 ID를 사용하여 MQTT를 통해 IoT Hub에 연결할 수 있습니다. MQTT를 통해 디바이스로 IoT Hub에 연결하는 방법에 대한 자세한 내용은 MQTT 프로토콜 직접 사용(디바이스로)을 참조하세요. 그러나 다음 값을 사용해야 합니다.

  • 클라이언트 ID를 {device-id}/{module-id}로 설정합니다.

  • 사용자 이름 과 암호를 사용하여 인증하는 경우 사용자 이름을 <hubname>.azure-devices.net/{device_id}/{module_id}/?api-version=2021-04-12으로 설정하고 모듈 ID와 연결된 SAS 토큰을 암호로 사용합니다.

  • devices/{device-id}/modules/{module-id}/messages/events/를 원격 분석 데이터 게시용 토픽으로 사용합니다.

  • devices/{device-id}/modules/{module-id}/messages/events/를 Will 토픽으로 사용합니다.

  • devices/{device-id}/modules/{module-id}/#를 메시지 수신용 토픽으로 사용합니다.

  • GET 및 PATCH 쌍 토픽은 모듈과 디바이스에 대해 동일합니다.

  • 쌍 상태 토픽은 모듈과 디바이스에 대해 동일합니다.

모듈에서 MQTT를 사용하는 방법에 대한 자세한 내용은 IoT Edge로 게시 및 구독을 참조하고 IoT Edge 허브 MQTT 엔드포인트에 대해 자세히 알아보세요.

Azure IoT SDK 없이 MQTT를 사용하는 샘플

IoT MQTT 샘플 리포지토리에는 Azure 디바이스 SDK를 사용하지 않고 원격 분석 메시지를 보내고, 클라우드-디바이스 메시지를 받고, 디바이스 쌍을 사용하는 방법을 보여주는 C/C++, Python, CLI 샘플이 포함되어 있습니다.

C/C++ 샘플은 Eclipse Mosquitto 라이브러리를 사용하고, Python 샘플은 Eclipse Paho를 사용하며, CLI 샘플은 mosquitto_pub를 사용합니다.

자세한 내용은 자습서 - MQTT를 사용하여 IoT 디바이스 클라이언트 개발을 참조하세요.

TLS/SSL 구성

MQTT 프로토콜을 직접 사용하려면 클라이언트가 반드시 TLS/SSL를 통해 연결되어야 합니다. 이 단계를 건너뛰려고 하면 연결 오류가 발생하여 실패합니다.

TLS 연결을 설정하려면 DigiCert 루트 인증서를 다운로드하여 참조해야 할 수 있습니다. 2023년 2월 15일부터 10월 15일까지 Azure IoT Hub는 DigiCert Baltimore 루트 인증서에서 DigiCert 글로벌 루트 G2로 TLS 루트 인증서를 마이그레이션합니다. 마이그레이션 기간 동안 연결을 보장하려면 디바이스에 두 인증서가 모두 있어야 합니다. 마이그레이션에 대한 자세한 내용은 IoT 리소스를 새 TLS 인증서 루트로 마이그레이션을 참조하세요. 이러한 인증서에 대한 자세한 내용은 Digicert의 웹 사이트를 참조하세요.

다음 예제에서는 Eclipse Foundation의 Paho MQTT 라이브러리 Python 버전을 사용하여 이 구성을 구현하는 방법을 보여줍니다.

먼저, 명령줄 환경에서 Paho 라이브러리를 설치합니다.

pip install paho-mqtt

그런 다음, Python 스크립트로 클라이언트를 구현합니다. 뒤에 나오는 코드 조각에서 다음과 같은 자리 표시자를 바꿉니다.

  • <local path to digicert.cer>은 DigiCert 루트 인증서가 포함된 로컬 파일의 경로입니다. C에 대한 Azure IoT SDK에서 certs.c의 인증서 정보를 복사하여 이 파일을 만들 수 있습니다. -----BEGIN CERTIFICATE----------END CERTIFICATE----- 줄을 포함하고 모든 줄의 시작과 끝에서 " 표시를 제거한 다음, 모든 줄의 마지막에서 \r\n 문자를 제거합니다.

  • <device id from device registry> IoT Hub에 추가된 디바이스의 ID입니다.

  • <generated SAS token>은 이 문서의 앞에서 설명한 디바이스에 대한 SAS 토큰입니다.

  • <iot hub name>은 IoT Hub의 이름입니다.

from paho.mqtt import client as mqtt
import ssl

path_to_root_cert = "<local path to digicert.cer file>"
device_id = "<device id from device registry>"
sas_token = "<generated SAS token>"
iot_hub_name = "<iot hub name>"


def on_connect(client, userdata, flags, rc):
    print("Device connected with result code: " + str(rc))


def on_disconnect(client, userdata, rc):
    print("Device disconnected with result code: " + str(rc))


def on_publish(client, userdata, mid):
    print("Device sent message")


client = mqtt.Client(client_id=device_id, protocol=mqtt.MQTTv311)

client.on_connect = on_connect
client.on_disconnect = on_disconnect
client.on_publish = on_publish

client.username_pw_set(username=iot_hub_name+".azure-devices.net/" +
                       device_id + "/?api-version=2021-04-12", password=sas_token)

client.tls_set(ca_certs=path_to_root_cert, certfile=None, keyfile=None,
               cert_reqs=ssl.CERT_REQUIRED, tls_version=ssl.PROTOCOL_TLSv1_2, ciphers=None)
client.tls_insecure_set(False)

client.connect(iot_hub_name+".azure-devices.net", port=8883)

client.publish("devices/" + device_id + "/messages/events/", '{"id":123}', qos=1)
client.loop_forever()

디바이스 인증서를 사용하여 인증하려면 이전 코드 조각을 다음 코드 조각에 지정된 변경 내용으로 업데이트합니다. 인증서 기반 인증을 준비하는 방법에 대한 자세한 내용은 X.509 CA 인증서를 사용하여 디바이스 인증X.509 CA 인증서 가져오기 섹션을 참조하세요.

# Create the client as before
# ...

# Set the username but not the password on your client
client.username_pw_set(username=iot_hub_name+".azure-devices.net/" +
                       device_id + "/?api-version=2021-04-12", password=None)

# Set the certificate and key paths on your client
cert_file = "<local path to your certificate file>"
key_file = "<local path to your device key file>"
client.tls_set(ca_certs=path_to_root_cert, certfile=cert_file, keyfile=key_file,
               cert_reqs=ssl.CERT_REQUIRED, tls_version=ssl.PROTOCOL_TLSv1_2, ciphers=None)

# Connect as before
client.connect(iot_hub_name+".azure-devices.net", port=8883)

디바이스-클라우드 메시지 보내기

디바이스 연결 후 devices/{device-id}/messages/events/ 또는 devices/{device-id}/messages/events/{property-bag}토픽 이름으로 사용하여 IoT Hub에 메시지를 보낼 수 있습니다. {property-bag} 요소를 사용하면 디바이스에서 URL로 인코딩된 형식의 다른 속성이 있는 메시지를 보낼 수 있습니다. 예시:

RFC 2396-encoded(<PropertyName1>)=RFC 2396-encoded(<PropertyValue1>)&RFC 2396-encoded(<PropertyName2>)=RFC 2396-encoded(<PropertyValue2>)…

참고 항목

{property_bag} 요소는 HTTPS 프로토콜의 쿼리 문자열과 동일한 인코딩을 사용합니다.

참고 항목

D2C 메시지를 Azure Storage 계정으로 라우팅하고 JSON 인코딩을 활용하려는 경우 $.ct=application%2Fjson&$.ce=utf-8을 포함하여 콘텐츠 형식 및 콘텐츠 인코딩 정보를 이전 참고 사항에서 언급한 {property_bag}의 일부로 지정해야 합니다.

이러한 특성의 형식은 프로토콜에 따라 다릅니다. IoT Hub는 이러한 특성을 해당 시스템 속성으로 변환합니다. 자세한 내용은 IoT Hub 메시지 라우팅 쿼리 구문시스템 속성 섹션을 참조하세요.

다음 목록에서는 IoT Hub 구현 관련 동작을 설명합니다.

  • IoT Hub에서는 QoS 2 메시지를 지원하지 않습니다. 디바이스 앱이 QoS 2의 메시지를 게시하는 경우, IoT Hub는 네트워크 연결을 닫습니다.

  • IoT Hub에서는 보관 메시지가 지속되지 않습니다. 디바이스에서 RETAIN 플래그가 1로 설정된 메시지를 보내는 경우 IoT Hub는 mqtt-retain 애플리케이션 속성을 메시지에 추가합니다. 이 경우에 IoT Hub는 보관 메시지를 유지하지 않고 백 엔드 앱에 전달합니다.

  • IoT Hub는 디바이스 당 하나의 활성 MQTT 연결만을 지원합니다. 동일한 디바이스 ID를 대신하는 모든 새 MQTT 연결로 인해 IoT Hub는 기존 연결을 끊으며 IoT Hub 로그에는 400027 ConnectionForcefullyClosedOnNewConnection이 기록됩니다.

  • 메시지 본문에 따라 메시지를 라우팅하려면 먼저 다음 예제와 같이 'contentType'(ct) 속성을 MQTT 토픽 끝에 추가하고 해당 값을 application/json;charset=utf-8로 설정해야 합니다. 메시지 속성 또는 메시지 본문에 따라 메시지를 라우팅하는 방법에 대한 자세한 내용은 IoT Hub 메시지 라우팅 쿼리 구문 설명서를 참조하세요.

    devices/{device-id}/messages/events/$.ct=application%2Fjson%3Bcharset%3Dutf-8

자세한 내용은 IoT Hub를 사용하여 디바이스-클라우드 및 클라우드-디바이스 메시지 보내기를 참조하세요.

클라우드-디바이스 메시지 수신

IoT Hub에서 메시지를 수신하려면 디바이스는 devices/{device-id}/messages/devicebound/#토픽 필터로 사용하여 구독해야 합니다. 토픽 필터의 # 다단계 와일드카드는 디바이스가 토픽 이름에서 더 많은 속성을 받을 수 있도록 허용하는 데만 사용됩니다. IoT Hub는 하위 토픽의 필터링을 위한 # 또는 ? 와일드카드의 사용을 허용하지 않습니다. IoT Hub는 범용 발행-구독 메시징 브로커가 아니므로 문서화된 토픽 이름 및 토픽 필터만 지원합니다. 디바이스는 한 번에 5개 토픽만 구독할 수 있습니다.

디바이스는 devices/{device-id}/messages/devicebound/# 토픽 필터로 표시되는 디바이스별 엔드포인트를 성공적으로 구독할 때까지 IoT Hub에서 어떤 메시지도 받지 않습니다. 구독이 설정된 후에는 디바이스가 구독 시간 이후 전송된 클라우드-디바이스 메시지를 수신합니다. 디바이스가 CleanSession 플래그가 0으로 설정되어 연결되면 다양한 세션 간에 구독이 유지됩니다. 이 경우 다음 번에 디바이스가 CleanSession 0으로 연결될 때, 연결되지 않은 동안 보내진 미해결 메시지를 수신하게 됩니다. 디바이스에서 1로 설정된 CleanSession 플래그를 사용하는 경우 해당 디바이스 엔드포인트를 구독할 때까지 IoT Hub에서 어떤 메시지도 받지 않습니다.

IoT Hub는 토픽 이름을 devices/{device-id}/messages/devicebound/사용하거나 devices/{device-id}/messages/devicebound/{property-bag} 메시지 속성이 있는 경우 메시지를 배달합니다. {property-bag} 에는 메시지 속성의 URL 인코딩된 키/값 쌍이 있습니다. 애플리케이션 속성 및 사용자 설정 가능 시스템 속성(예: messageId 또는 correlationId)만 속성 모음에 포함됩니다. 시스템 속성 이름에는 접두사 $가 있으며, 애플리케이션 속성은 접두사가 없는 원래 속성 이름을 사용합니다. 속성 모음의 형식에 대한 자세한 내용은 디바이스-클라우드 메시지 보내기를 참조하세요.

클라우드-디바이스 메시지에서 속성 모음의 값은 다음 표와 같이 표시됩니다.

속성 값 표현 설명
null key 속성 모음에 키만 표시됩니다.
빈 문자열 key= 키 뒤에 값이 없는 등호 기호가 있습니다.
null이 아니며 비어 있지 않은 값 key=value 키 뒤에 등호와 값이 있습니다.

다음 예제는 세 가지 애플리케이션 속성이 포함된 속성 모음인 null 값이 있는 prop1, 빈 문자열("")인 prop2, "문자열" 값이 있는 prop3을 보여 줍니다.

/?prop1&prop2=&prop3=a%20string

디바이스 앱이 QoS 2의 토픽을 구독하는 경우, IoT Hub는 SUBACK 패킷에서 최대 QoS level 1을 부여합니다. 그런 다음 IoT Hub는 메시지를 QoS 1을 사용하는 디바이스에 전달합니다.

디바이스 쌍 속성 검색

먼저 작업의 응답을 수신하기 위해 디바이스가 $iothub/twin/res/#을 구독합니다. 그런 다음 요청 ID에 채워진 값을 사용하여 빈 메시지를 $iothub/twin/GET/?$rid={request id} 항목에 보냅니다. 그러면 서비스는 요청과 동일한 요청 ID를 사용하여 $iothub/twin/res/{status}/?$rid={request-id} 항목에 대한 디바이스 쌍 데이터를 포함하는 응답 메시지를 보냅니다.

요청 ID는 메시지 속성 값에 대한 유효한 값일 수 있으며, 상태는 정수로 확인됩니다. 자세한 내용은 IoT Hub를 사용하여 디바이스-클라우드 및 클라우드-디바이스 메시지 보내기를 참조하세요.

응답 본문에는 다음 응답 예제와 같이 디바이스 쌍의 속성 섹션이 포함되어 있습니다.

{
    "desired": {
        "telemetrySendFrequency": "5m",
        "$version": 12
    },
    "reported": {
        "telemetrySendFrequency": "5m",
        "batteryLevel": 55,
        "$version": 123
    }
}

가능한 상태 코드:

상태 설명
200 Success
429 요청이 너무 많습니다(제한됨). 자세한 내용은 IoT Hub 제한을 참조하세요.
5** 서버 오류

자세한 내용은 IoT Hub의 디바이스 쌍 이해 및 사용을 참조하세요.

디바이스 쌍의 reported 속성 업데이트

reported 속성을 업데이트하기 위해 디바이스는 지정된 MQTT 토픽에서 게시를 통해 IoT Hub에 요청을 발급합니다. IoT Hub는 요청을 처리한 후에 다른 항목에 대한 게시를 통해 업데이트 작업의 성공 또는 실패 상태를 응답합니다. 해당 쌍 업데이트 요청의 결과에 대해 알리기 위해 디바이스에서 이 토픽을 구독할 수 있습니다. MQTT에서 이 형식의 요청/응답 상호 작용을 구현하려면 해당 업데이트 요청의 디바이스에서 처음에 제공한 요청 ID($rid)의 개념을 사용합니다. 이 요청 ID는 IoT Hub의 응답에도 포함되어 디바이스가 이전의 특정 요청에 대한 응답을 상호 연결하도록 합니다.

다음 시퀀스에서는 디바이스가 IoT Hub의 디바이스 쌍에서 보고된 속성을 업데이트하는 방법을 설명합니다.

  1. 디바이스는 먼저 $iothub/twin/res/# 항목을 구독하여 IoT Hub에서 작업의 응답을 수신해야 합니다.

  2. 디바이스는 디바이스 쌍 업데이트를 포함하는 메시지를 $iothub/twin/PATCH/properties/reported/?$rid={request-id} 항목에 전송합니다. 이 메시지는 요청 ID 값을 포함합니다.

  3. 그러면 서비스에서는 항목 $iothub/twin/res/{status}/?$rid={request-id}에 대해 보고된 속성 컬렉션의 새 ETag 값을 포함하는 응답 메시지를 보냅니다. 이 응답 메시지는 동일한 요청 ID를 요청으로 사용합니다.

요청 메시지 본문은 보고된 속성에 대한 새 값을 포함하는 JSON 문서를 포함합니다. JSON 문서의 각 멤버는 디바이스 쌍의 문서에 있는 해당 멤버를 업데이트하거나 추가합니다. null로 설정된 구성원은 포함하는 개체에서 구성원을 삭제합니다. 예시:

{
    "telemetrySendFrequency": "35m",
    "batteryLevel": 60
}

가능한 상태 코드:

상태 설명
204 성공(반환되는 콘텐츠 없음)
400 잘못된 요청. 형식이 잘못된 JSON
429 너무 많은 요청(제한됨), IoT Hub 제한 참조
5** 서버 오류

다음 Python 코드 조각에서는 Paho MQTT 클라이언트를 사용하여 MQTT를 통한 쌍 reported 속성 업데이트 프로세스를 보여줍니다.

from paho.mqtt import client as mqtt

# authenticate the client with IoT Hub (not shown here)

client.subscribe("$iothub/twin/res/#")
rid = "1"
twin_reported_property_patch = "{\"firmware_version\": \"v1.1\"}"
client.publish("$iothub/twin/PATCH/properties/reported/?$rid=" +
               rid, twin_reported_property_patch, qos=0)

이전 코드 조각에서 쌍 reported 속성 업데이트 프로세스가 성공하면 IoT Hub의 게시 메시지에는 $iothub/twin/res/204/?$rid=1&$version=6 토픽이 있습니다. 여기서 204는 성공을 나타내는 상태 코드이고, $rid=1은 코드에서 디바이스가 제공한 요청 ID에 해당하며, $version은 업데이트 후 디바이스 쌍의 reported 속성 섹션 버전에 해당합니다.

자세한 내용은 IoT Hub의 디바이스 쌍 이해 및 사용을 참조하세요.

desired 속성 업데이트 알림 수신

디바이스가 연결되면 IoT Hub는 $iothub/twin/PATCH/properties/desired/?$version={new-version} 항목에 알림을 보내는데 여기에는 솔루션 백 엔드에 의해 수행된 업데이트 콘텐츠가 포함됩니다. 예시:

{
    "telemetrySendFrequency": "5m",
    "route": null,
    "$version": 8
}

속성 업데이트의 경우 null 값은 JSON 개체 멤버가 삭제되고 있음을 의미합니다. 또한 $version은 쌍에 포함된 원하는 속성 섹션의 새 버전을 나타냅니다.

Important

IoT Hub는 디바이스가 연결된 경우에만 변경 알림을 생성하여 desired 속성이 IoT Hub와 디바이스 앱 간에 동기화 상태를 유지하기 위해 디바이스 다시 연결 흐름이 수행되도록 합니다.

자세한 내용은 IoT Hub의 디바이스 쌍 이해 및 사용을 참조하세요.

직접 메서드에 응답

먼저 디바이스가 $iothub/methods/POST/#을 구독해야 합니다. IoT Hub는 $iothub/methods/POST/{method-name}/?$rid={request-id} 항목에 유효한 JSON 또는 빈 본문으로 메서드 요청을 보냅니다.

응답하기 위해 디바이스는 올바른 JSON 또는 빈 본문이 있는 메시지를 $iothub/methods/res/{status}/?$rid={request-id} 토픽에 보냅니다. 이 메시지에서 요청 ID는 요청 메시지의 것과 일치하고 상태는 정수여야 합니다.

자세한 내용은 IoT Hub의 직접 메서드 이해 및 호출을 참조하세요.

다음 단계

MQTT 사용에 대한 자세한 내용은 다음을 참조하세요.

IoT 디바이스 SDK 사용에 대한 자세한 내용은 다음을 참조하세요.

IoT Hub 배포를 계획하는 방법에 대한 자세한 내용은 다음을 참조하세요.