자습서 - 디바이스 SDK를 사용하지 않고 MQTT를 사용하여 IoT 디바이스 클라이언트 개발
가능한 경우 Azure IoT 디바이스 SDK 중 하나를 사용하여 IoT 디바이스 클라이언트를 빌드해야 합니다. 그러나 메모리가 제한된 디바이스를 사용하는 시나리오에서는 MQTT 라이브러리를 사용하여 IoT 허브와 통신해야 할 수도 있습니다.
이 자습서의 샘플은 Eclipse Mosquitto MQTT 라이브러리를 사용합니다.
이 자습서에서는 다음을 하는 방법을 알아볼 수 있습니다.
- C 언어 디바이스 클라이언트 샘플 애플리케이션을 빌드합니다.
- MQTT 라이브러리를 사용하여 원격 분석을 보내는 샘플을 실행합니다.
- MQTT 라이브러리를 사용하는 샘플을 실행하여 IoT Hub에서 보낸 클라우드-디바이스 메시지를 처리합니다.
- MQTT 라이브러리를 사용하는 샘플을 실행하여 디바이스에서 디바이스 쌍을 관리합니다.
Windows 또는 Linux 개발 컴퓨터를 사용하여 이 자습서의 단계를 완료할 수 있습니다.
Azure 구독이 아직 없는 경우 시작하기 전에 체험 계정을 만듭니다.
필수 조건
Azure CLI에 대한 환경 준비
Azure Cloud Shell에서 Bash 환경을 사용합니다. 자세한 내용은 Azure Cloud Shell의 Bash에 대한 빠른 시작을 참조하세요.
CLI 참조 명령을 로컬에서 실행하려면 Azure CLI를 설치합니다. Windows 또는 macOS에서 실행 중인 경우 Docker 컨테이너에서 Azure CLI를 실행하는 것이 좋습니다. 자세한 내용은 Docker 컨테이너에서 Azure CLI를 실행하는 방법을 참조하세요.
로컬 설치를 사용하는 경우 az login 명령을 사용하여 Azure CLI에 로그인합니다. 인증 프로세스를 완료하려면 터미널에 표시되는 단계를 수행합니다. 다른 로그인 옵션은 Azure CLI를 사용하여 로그인을 참조하세요.
메시지가 표시되면 처음 사용할 때 Azure CLI 확장을 설치합니다. 확장에 대한 자세한 내용은 Azure CLI에서 확장 사용을 참조하세요.
az version을 실행하여 설치된 버전과 종속 라이브러리를 찾습니다. 최신 버전으로 업그레이드하려면 az upgrade를 실행합니다.
개발 컴퓨터 필수 조건
Windows를 사용하는 경우:
Visual Studio(커뮤니티, 전문가 또는 기업)를 설치합니다. C++를 사용한 데스크톱 개발 워크로드를 사용하도록 설정해야 합니다.
CMake를 설치합니다. 모든 사용자의 시스템 PATH에 CMake 추가 옵션을 사용하도록 설정합니다.
Mosquitto의 x64 버전을 설치합니다.
Linux를 사용하는 경우:
다음 명령을 실행하여 빌드 도구를 설치합니다.
sudo apt install cmake g++
다음 명령을 실행하여 Mosquitto 클라이언트 라이브러리를 설치합니다.
sudo apt install libmosquitto-dev
환경 설정
IoT Hub가 아직 없는 경우 다음 명령을 실행하여 mqtt-sample-rg
라는 리소스 그룹에 무료 계층 IoT Hub를 만듭니다. 이 명령은 만들 IoT 허브 이름의 예로 my-hub
이름을 사용합니다. my-hub
대신 사용할 고유한 IoT 허브 이름을 선택합니다.
az group create --name mqtt-sample-rg --location eastus
az iot hub create --name my-hub --resource-group mqtt-sample-rg --sku F1
나중에 필요하므로 IoT Hub의 이름을 기록해 둡니다.
IoT 허브에 디바이스 등록 다음 명령은 my-hub
라는 IoT Hub에 mqtt-dev-01
이라는 디바이스를 등록합니다. IoT Hub의 이름을 사용해야 합니다.
az iot hub device-identity create --hub-name my-hub --device-id mqtt-dev-01
다음 명령을 사용하여 IoT 허브에 대한 디바이스 액세스 권한을 부여하는 SAS 토큰을 만듭니다. IoT Hub의 이름을 사용해야 합니다.
az iot hub generate-sas-token --device-id mqtt-dev-01 --hub-name my-hub --du 7200
나중에 필요할 때 명령이 출력하는 SAS 토큰을 기록해 둡니다. SAS 토큰은 SharedAccessSignature sr=my-hub.azure-devices.net%2Fdevices%2Fmqtt-dev-01&sig=%2FnM...sNwtnnY%3D&se=1677855761
과 같습니다.
팁
기본적으로 SAS 토큰은 60분 동안 유효합니다. 이전 명령의 --du 7200
옵션은 토큰 기간을 2시간으로 확장합니다. 사용할 준비가 되기 전에 만료되면 새로 생성합니다. 기간이 더 긴 토큰을 만들 수도 있습니다. 자세한 내용은 az iot hub generate-sas-token을 참조하세요.
샘플 리포지토리 복제
다음 명령을 실행하여 로컬 머신의 적절한 위치에 샘플 리포지토리를 복제합니다.
git clone https://github.com/Azure-Samples/IoTMQTTSample.git
리포지토리에는 다음도 포함됩니다.
paho-mqtt
라이브러리를 사용하는 Python 샘플입니다.mosquitto_pub
CLI를 사용하여 IoT 허브와 상호 작용하는 방법에 대한 지침입니다.
C 샘플 빌드
샘플을 빌드하기 전에 IoT Hub 및 디바이스 세부 정보를 추가해야 합니다. 복제된 IoTMQTTSample 리포지토리에서 mosquitto/src/config.h 파일을 엽니다. 다음과 같이 IoT 허브 이름, 디바이스 ID 및 SAS 토큰을 추가합니다. IoT Hub의 이름을 사용해야 합니다.
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
#define IOTHUBNAME "my-hub"
#define DEVICEID "mqtt-dev-01"
#define SAS_TOKEN "SharedAccessSignature sr=my-hub.azure-devices.net%2Fdevices%2Fmqtt-dev-01&sig=%2FnM...sNwtnnY%3D&se=1677855761"
#define CERTIFICATEFILE CERT_PATH "IoTHubRootCA.crt.pem"
참고 항목
IoTHubRootCA.crt.pem 파일에는 TLS 연결을 위한 CA 루트 인증서가 포함되어 있습니다.
변경 내용을 mosquitto/src/config.h 파일에 저장합니다.
샘플을 빌드하려면 셸에서 다음 명령을 실행합니다.
cd mosquitto
cmake -Bbuild
cmake --build build
Linux에서 이진 파일은 mosquitto 폴더 아래의 ./build 폴더에 있습니다.
Windows에서 이진 파일은 mosquitto 폴더 아래의 .\build\Debug 폴더에 있습니다.
원격 분석 전송
mosquitto_telemetry 샘플은 MQTT 라이브러리를 사용하여 IoT Hub에 디바이스-클라우드 원격 분석 메시지를 보내는 방법을 보여 줍니다.
샘플 애플리케이션을 실행하기 전에 다음 명령을 실행하여 IoT Hub에 대한 이벤트 모니터를 시작합니다. IoT Hub의 이름을 사용해야 합니다.
az iot hub monitor-events --hub-name my-hub
mosquitto_telemetry 샘플을 실행합니다. 예를 들어, Linux에서:
./build/mosquitto_telemetry
az iot hub monitor-events
는 디바이스에서 보낸 페이로드를 보여 주는 다음 출력을 생성합니다.
Starting event monitor, use ctrl-c to stop...
{
"event": {
"origin": "mqtt-dev-01",
"module": "",
"interface": "",
"component": "",
"payload": "Bonjour MQTT from Mosquitto"
}
}
이제 이벤트 모니터를 중지할 수 있습니다.
코드 검토
다음 코드 조각은 mosquitto/src/mosquitto_telemetry.cpp 파일에서 가져온 것입니다.
다음 문은 연결 정보와 원격 분석 메시지를 보내는 데 사용하는 MQTT 항목의 이름을 정의합니다.
#define HOST IOTHUBNAME ".azure-devices.net"
#define PORT 8883
#define USERNAME HOST "/" DEVICEID "/?api-version=2020-09-30"
#define TOPIC "devices/" DEVICEID "/messages/events/"
main
함수는 IoT Hub 인증을 위한 사용자 이름과 암호를 설정합니다. 암호는 디바이스용으로 만든 SAS 토큰입니다.
mosquitto_username_pw_set(mosq, USERNAME, SAS_TOKEN);
이 샘플은 MQTT 항목을 사용하여 IoT 허브에 원격 분석 메시지를 보냅니다.
int msgId = 42;
char msg[] = "Bonjour MQTT from Mosquitto";
// once connected, we can publish a Telemetry message
printf("Publishing....\r\n");
rc = mosquitto_publish(mosq, &msgId, TOPIC, sizeof(msg) - 1, msg, 1, true);
if (rc != MOSQ_ERR_SUCCESS)
{
return mosquitto_error(rc);
}
printf("Publish returned OK\r\n");
자세한 내용은 디바이스에서 클라우드로 메시지 보내기를 참조하세요.
클라우드-디바이스 메시지 수신
mosquitto_subscribe 샘플은 MQTT 라이브러리를 사용하여 MQTT 항목을 구독하고 IoT 허브에서 클라우드-디바이스 메시지를 수신하는 방법을 보여 줍니다.
mosquitto_subscribe 샘플을 실행합니다. 예를 들어, Linux에서:
./build/mosquitto_subscribe
다음 명령을 실행하여 IoT Hub에서 클라우드-디바이스 메시지를 보냅니다. IoT Hub의 이름을 사용해야 합니다.
az iot device c2d-message send --hub-name my-hub --device-id mqtt-dev-01 --data "hello world"
mosquitto_subscribe의 출력은 다음 예와 같습니다.
Waiting for C2D messages...
C2D message 'hello world' for topic 'devices/mqtt-dev-01/messages/devicebound/%24.mid=d411e727-...f98f&%24.to=%2Fdevices%2Fmqtt-dev-01%2Fmessages%2Fdevicebound&%24.ce=utf-8&iothub-ack=none'
Got message for devices/mqtt-dev-01/messages/# topic
코드 검토
다음 코드 조각은 mosquitto/src/mosquitto_subscribe.cpp 파일에서 가져온 것입니다.
다음 문은 디바이스에서 클라우드-디바이스 메시지를 수신하는 데 사용하는 항목 필터를 정의합니다. #
은 다단계 와일드카드입니다.
#define DEVICEMESSAGE "devices/" DEVICEID "/messages/#"
main
함수는 mosquitto_message_callback_set
함수를 사용하여 콜백을 설정하여 IoT Hub에서 보낸 메시지를 처리하고 mosquitto_subscribe
함수를 사용하여 모든 메시지를 구독합니다. 다음 코드 조각은 콜백 함수를 보여 줍니다.
void message_callback(struct mosquitto* mosq, void* obj, const struct mosquitto_message* message)
{
printf("C2D message '%.*s' for topic '%s'\r\n", message->payloadlen, (char*)message->payload, message->topic);
bool match = 0;
mosquitto_topic_matches_sub(DEVICEMESSAGE, message->topic, &match);
if (match)
{
printf("Got message for " DEVICEMESSAGE " topic\r\n");
}
}
자세한 내용은 MQTT를 사용하여 클라우드-디바이스 메시지 수신을 참조하세요.
디바이스 쌍 업데이트
mosquitto_device_twin 샘플은 디바이스 쌍에서 reported 속성을 설정한 다음 속성을 다시 읽는 방법을 보여 줍니다.
mosquitto_device_twin 샘플을 실행합니다. 예를 들어, Linux에서:
./build/mosquitto_device_twin
mosquitto_device_twin의 출력은 다음 예와 같습니다.
Setting device twin reported properties....
Device twin message '' for topic '$iothub/twin/res/204/?$rid=0&$version=2'
Setting device twin properties SUCCEEDED.
Getting device twin properties....
Device twin message '{"desired":{"$version":1},"reported":{"temperature":32,"$version":2}}' for topic '$iothub/twin/res/200/?$rid=1'
Getting device twin properties SUCCEEDED.
코드 검토
다음 코드 조각은 mosquitto/src/mosquitto_device_twin.cpp 파일에서 가져온 것입니다.
다음 문은 디바이스가 디바이스 쌍 업데이트를 구독하고 디바이스 쌍을 읽고 디바이스 쌍을 업데이트하는 데 사용하는 항목을 정의합니다.
#define DEVICETWIN_SUBSCRIPTION "$iothub/twin/res/#"
#define DEVICETWIN_MESSAGE_GET "$iothub/twin/GET/?$rid=%d"
#define DEVICETWIN_MESSAGE_PATCH "$iothub/twin/PATCH/properties/reported/?$rid=%d"
main
함수는 mosquitto_connect_callback_set
함수를 사용하여 콜백을 설정하여 IoT Hub에서 보낸 메시지를 처리하고 mosquitto_subscribe
함수를 사용하여 $iothub/twin/res/#
항목을 구독합니다.
다음 코드 조각은 mosquitto_publish
를 사용하여 디바이스 쌍에서 reported 속성을 설정하는 connect_callback
함수를 보여 줍니다. 디바이스가 메시지를 $iothub/twin/PATCH/properties/reported/?$rid=%d
항목에 게시합니다. 디바이스가 항목에 메시지를 게시할 때마다 %d
값이 증가합니다.
void connect_callback(struct mosquitto* mosq, void* obj, int result)
{
// ... other code ...
printf("\r\nSetting device twin reported properties....\r\n");
char msg[] = "{\"temperature\": 32}";
char mqtt_publish_topic[64];
snprintf(mqtt_publish_topic, sizeof(mqtt_publish_topic), DEVICETWIN_MESSAGE_PATCH, device_twin_request_id++);
int rc = mosquitto_publish(mosq, NULL, mqtt_publish_topic, sizeof(msg) - 1, msg, 1, true);
if (rc != MOSQ_ERR_SUCCESS)
// ... other code ...
}
디바이스는 $iothub/twin/res/#
항목을 구독하고 IoT Hub에서 메시지를 수신하면 message_callback
함수가 이를 처리합니다. 샘플을 실행하면 message_callback
함수가 두 번 호출됩니다. 처음으로 디바이스는 reported 속성 업데이트에 대한 IoT Hub의 응답을 받습니다. 그런 다음 디바이스는 디바이스 쌍을 요청합니다. 두 번째로 디바이스는 요청된 디바이스 쌍을 받습니다. 다음 코드 조각은 message_callback
함수를 보여 줍니다.
void message_callback(struct mosquitto* mosq, void* obj, const struct mosquitto_message* message)
{
printf("Device twin message '%.*s' for topic '%s'\r\n", message->payloadlen, (char*)message->payload, message->topic);
const char patchTwinTopic[] = "$iothub/twin/res/204/?$rid=0";
const char getTwinTopic[] = "$iothub/twin/res/200/?$rid=1";
if (strncmp(message->topic, patchTwinTopic, sizeof(patchTwinTopic) - 1) == 0)
{
// Process the reported property response and request the device twin
printf("Setting device twin properties SUCCEEDED.\r\n\r\n");
printf("Getting device twin properties....\r\n");
char msg[] = "{}";
char mqtt_publish_topic[64];
snprintf(mqtt_publish_topic, sizeof(mqtt_publish_topic), DEVICETWIN_MESSAGE_GET, device_twin_request_id++);
int rc = mosquitto_publish(mosq, NULL, mqtt_publish_topic, sizeof(msg) - 1, msg, 1, true);
if (rc != MOSQ_ERR_SUCCESS)
{
printf("Error: %s\r\n", mosquitto_strerror(rc));
}
}
else if (strncmp(message->topic, getTwinTopic, sizeof(getTwinTopic) - 1) == 0)
{
// Process the device twin response and stop the client
printf("Getting device twin properties SUCCEEDED.\r\n\r\n");
mosquitto_loop_stop(mosq, false);
mosquitto_disconnect(mosq); // finished, exit program
}
}
자세한 내용은 MQTT를 사용하여 디바이스 쌍 reported 속성 업데이트 및 MQTT를 사용하여 디바이스 쌍 속성 검색을 참조하세요.
리소스 정리
더 많은 디바이스 개발자 문서를 계속할 계획이라면 이 문서에서 사용한 리소스를 유지하고 재사용할 수 있습니다. 그렇지 않으면 이 문서에서 만든 리소스를 삭제하여 추가 요금을 방지할 수 있습니다.
다음 Azure CLI 명령을 사용하여 전체 리소스 그룹을 삭제하면 허브와 등록된 디바이스를 한 번에 삭제할 수 있습니다. 이러한 리소스가 유지하려는 다른 리소스와 리소스 그룹을 공유하는 경우에는 이 명령을 사용하지 마세요.
az group delete --name <YourResourceGroupName>
IoT 허브만 삭제하려면 Azure CLI을 사용하여 다음 명령을 실행합니다.
az iot hub delete --name <YourIoTHubName>
IoT 허브에 등록한 디바이스 ID만 삭제하려면 Azure CLI를 사용하여 다음 명령을 실행합니다.
az iot hub device-identity delete --hub-name <YourIoTHubName> --device-id <YourDeviceID>
개발 머신에서 복제된 샘플 파일을 제거할 수도 있습니다.
다음 단계
이제 Mosquitto MQTT 라이브러리를 사용하여 IoT Hub와 통신하는 방법을 배웠으므로 제안된 다음 단계는 다음을 검토하는 것입니다.