Artikel ini menjelaskan cara memanggil operasi API Link SDK untuk C guna menghubungkan perangkat berbasis MQTT dengan Platform IoT dan menerima pesan. Dalam contoh ini, digunakan file kode sampel ./mqtt_basic_demo.c.
Informasi latar belakang
Untuk informasi lebih lanjut tentang koneksi MQTT, lihat Ikhtisar.
Langkah 1: Inisialisasi klien
Tambahkan file header.
#include "aiot_state_api.h" #include "aiot_sysdep_api.h" #include "aiot_mqtt_api.h"Tambahkan dependensi dasar dan konfigurasikan fitur keluaran log.
aiot_sysdep_set_portfile(&g_aiot_sysdep_portfile); aiot_state_set_logcb(demo_state_logcb);Panggil operasi aiot_mqtt_init untuk membuat instans klien MQTT dan menginisialisasi parameter default.
mqtt_handle = aiot_mqtt_init(); if (mqtt_handle == NULL) { printf("aiot_mqtt_init failed\n"); return -1; }
Langkah 2: Konfigurasi fitur yang diperlukan
Panggil operasi aiot_mqtt_setopt untuk mengonfigurasi hal-hal berikut:
Untuk informasi lebih lanjut tentang parameter operasi tersebut, lihat aiot_mqtt_option_t.
Atur parameter koneksi.
Kode sampel
char *product_key = "a18wP******"; char *device_name = "LightSwitch"; char *device_secret = "uwMTmVAMnGGHaAkqmeDY6cHxxB******"; char *mqtt_host = "iot-06z00ax1o******.mqtt.iothub.aliyuncs.com"; ... ... /* Set the endpoint of the MQTT broker. */ aiot_mqtt_setopt(mqtt_handle, AIOT_MQTTOPT_HOST, (void *)url); /* Set the port of the MQTT broker. */ aiot_mqtt_setopt(mqtt_handle, AIOT_MQTTOPT_PORT, (void *)&port); /* Set the ProductKey of the device. */ aiot_mqtt_setopt(mqtt_handle, AIOT_MQTTOPT_PRODUCT_KEY, (void *)product_key); /* Set the DeviceName of the device. */ aiot_mqtt_setopt(mqtt_handle, AIOT_MQTTOPT_DEVICE_NAME, (void *)device_name); /* Set the DeviceSecret of the device. */ aiot_mqtt_setopt(mqtt_handle, AIOT_MQTTOPT_DEVICE_SECRET, (void *)device_secret); /* Set the security credential of the connection. */ aiot_mqtt_setopt(mqtt_handle, AIOT_MQTTOPT_NETWORK_CRED, (void *)&cred);Parameter:
Parameter
Contoh
Deskripsi
mqtt_host
iot-06z00ax1o******.mqtt.iothub.aliyuncs.com
Titik akhir.
Jika Anda menggunakan instans Edisi Perusahaan atau instans publik yang diaktifkan pada 30 Juli 2021 atau setelahnya, lihat titik akhir di halaman Detail Instans. Klik Lihat Konfigurasi Pengembangan di pojok kanan atas. Titik akhir akan ditampilkan di panel Development Configurations.
Jika Anda menggunakan instans publik yang diaktifkan sebelum 30 Juli 2021, titik akhirnya adalah
${YourProductKey}.iot-as-mqtt.${YourRegionId}.aliyuncs.com.
product_key
a18wP******
Informasi autentikasi perangkat. Untuk informasi selengkapnya, lihat Dapatkan informasi autentikasi perangkat.
Dalam contoh ini, digunakan metode otentikasi sertifikat unik per perangkat.
device_name
LightSwitch
device_secret
uwMTmVAMnGGHaAkqmeDY6cHxxB******
Deskripsi keep-alive MQTT:
PentingSelama periode keep-alive, perangkat harus mengirim setidaknya satu pesan, termasuk permintaan ping.
Pengatur waktu dimulai ketika Platform IoT mengirim pesan CONNACK sebagai tanggapan terhadap pesan CONNECT. Ketika Platform IoT menerima pesan PUBLISH, SUBSCRIBE, PING, atau PUBACK, pengatur waktu diatur ulang. Platform IoT memeriksa heartbeat koneksi MQTT setiap 30 detik. Waktu tunggu untuk pemeriksaan heartbeat adalah periode antara waktu perangkat terhubung ke Platform IoT dan waktu pemeriksaan heartbeat berikutnya dilakukan. Periode timeout maksimum dihitung menggunakan rumus berikut:
Interval heartbeat × 1,5 + Waktu tunggu untuk pemeriksaan heartbeat. Jika server tidak menerima pesan apa pun dari perangkat dalam periode timeout maksimum tersebut, server akan mengakhiri koneksi dengan perangkat.
Link SDK untuk C menyediakan kemampuan keep-alive. Anda dapat menentukan parameter berikut untuk menyesuaikan heartbeat koneksi. Jika tidak, nilai default akan digunakan.
Parameter
Nilai default
Deskripsi
AIOT_MQTTOPT_HEARTBEAT_MAX_LOST
2
Jumlah maksimum heartbeat yang boleh hilang. Jika batas ini terlampaui, koneksi akan dibuat ulang.
AIOT_MQTTOPT_HEARTBEAT_INTERVAL_MS
25.000
Interval heartbeat. Satuan: milidetik. Nilai valid: 1.000 hingga 1.200.000.
AIOT_MQTTOPT_KEEPALIVE_SEC
1.200
Waktu hidup thread. Setelah heartbeat hilang, Anda dapat membuat ulang koneksi dalam periode yang ditentukan. Nilai valid: 30 hingga 1.200. Satuan: detik. Disarankan untuk menetapkan nilai yang lebih besar dari 300.
Konfigurasi callback untuk memantau status dan menerima pesan.
Tentukan callback untuk memantau status.
Kode sampel
int main(int argc, char *argv[]) { ... ... /* Specify the default callback to receive MQTT messages. */ aiot_mqtt_setopt(mqtt_handle, AIOT_MQTTOPT_RECV_HANDLER, (void *)demo_mqtt_default_recv_handler); /* Specify the callback to handle MQTT events. */ aiot_mqtt_setopt(mqtt_handle, AIOT_MQTTOPT_EVENT_HANDLER, (void *)demo_mqtt_event_handler); ... ... }Parameter:
Parameter
Contoh
Deskripsi
AIOT_MQTTOPT_RECV_HANDLER
demo_mqtt_default_recv_handler
Ketika sebuah pesan diterima, callback dipanggil untuk melakukan operasi yang diperlukan.
AIOT_MQTTOPT_EVENT_HANDLER
demo_mqtt_event_handler
Ketika status koneksi perangkat berubah, callback dipanggil untuk melakukan operasi yang diperlukan.
Definisikan callback untuk memantau status.
PentingJangan tentukan logika yang memakan waktu lama untuk menangani event. Jika tidak, thread yang digunakan untuk menerima paket mungkin akan diblokir.
Perubahan status koneksi mencakup pengecualian jaringan, koneksi ulang otomatis, dan pemutusan koneksi.
Untuk menangani perubahan status koneksi, Anda dapat memodifikasi kode sesuai kebutuhan di bagian
TODO.
/* The callback to handle MQTT events. When the connection is created, recovered, or closed, the callback is called. For information about the event definition, see core/aiot_mqtt_api.h. */ void demo_mqtt_event_handler(void *handle, const aiot_mqtt_event_t *event, void *userdata) { switch (event->type) { /* Call the aiot_mqtt_connect operation to establish a connection with the MQTT broker. */ case AIOT_MQTTEVT_CONNECT: { printf("AIOT_MQTTEVT_CONNECT\n"); /* TODO: Specify the processing logic after the connection is established. Do not call time-consuming functions that may block threads. */ } break; /* If a disconnection error occurs due to a network exception, the SDK automatically initiates a request to reconnect with the MQTT broker. */ case AIOT_MQTTEVT_RECONNECT: { printf("AIOT_MQTTEVT_RECONNECT\n"); /* TODO: Specify the processing logic after the connection is re-established. Do not call time-consuming functions that may block threads. */ } break; /* A disconnection error occurs due to a network exception. The underlying read or write operation fails. A heartbeat response is not obtained from the MQTT broker. */ case AIOT_MQTTEVT_DISCONNECT: { char *cause = (event->data.disconnect == AIOT_MQTTDISCONNEVT_NETWORK_DISCONNECT) ? ("network disconnect") : ("heartbeat disconnect"); printf("AIOT_MQTTEVT_DISCONNECT: %s\n", cause); /* TODO: Specify the logic to process disconnection issues. Do not call time-consuming functions that may block threads. */ } break; default: { } } }Definisikan callback untuk menerima pesan.
PentingJangan tentukan logika yang memakan waktu lama untuk memproses pesan. Jika tidak, thread yang digunakan untuk menerima paket mungkin akan diblokir.
Untuk memproses pesan yang diterima, Anda dapat memodifikasi kode sesuai kebutuhan di bagian
TODO.
/* The default callback to process MQTT messages. When the SDK receives messages from the MQTT broker and you do not configure callbacks, the following operation is called. */ void demo_mqtt_default_recv_handler(void *handle, const aiot_mqtt_recv_t *packet, void *userdata) { switch (packet->type) { case AIOT_MQTTRECV_HEARTBEAT_RESPONSE: { printf("heartbeat response\n"); /* TODO: Specify the logic to process heartbeat responses from the MQTT broker. In most cases, this logic is not required. */ } break; case AIOT_MQTTRECV_SUB_ACK: { printf("suback, res: -0x%04X, packet id: %d, max qos: %d\n", -packet->data.sub_ack.res, packet->data.sub_ack.packet_id, packet->data.sub_ack.max_qos); /* TODO: Specify the logic to process the responses of the MQTT broker to subscription requests. In most cases, this logic is not required. */ } break; case AIOT_MQTTRECV_PUB: { printf("pub, qos: %d, topic: %.*s\n", packet->data.pub.qos, packet->data.pub.topic_len, packet->data.pub.topic); printf("pub, payload: %.*s\n", packet->data.pub.payload_len, packet->data.pub.payload); /* TODO: Specify the logic to process the messages that are sent from the MQTT broker. */ } break; case AIOT_MQTTRECV_PUB_ACK: { printf("puback, packet id: %d\n", packet->data.pub_ack.packet_id); /* TODO: Specify the logic to process the responses of the MQTT broker to QoS 1 messages. In most cases, this logic is not required. */ } break; default: { } } }
Langkah 3: Membangun koneksi
Panggil operasi aiot_mqtt_connect untuk mengirim permintaan koneksi dan autentikasi ke Platform IoT. Untuk informasi tentang cara menentukan parameter, lihat Atur parameter koneksi.
/* Establish an MQTT connection with IoT Platform. */
res = aiot_mqtt_connect(mqtt_handle);
if (res < STATE_SUCCESS) {
/* Release resources of the MQTT instance if the MQTT connection fails to be established. */
aiot_mqtt_deinit(&mqtt_handle);
printf("aiot_mqtt_connect failed: -0x%04X\n", -res);
return -1;
}Langkah 4: Aktifkan thread keep-alive
Panggil operasi aiot_mqtt_process untuk mengirim pesan heartbeat ke Broker MQTT dan mengirim ulang pesan QoS 1 yang belum mendapat tanggapan. Dengan cara ini, koneksi persisten diaktifkan.
Aktifkan thread keep-alive.
res = pthread_create(&g_mqtt_process_thread, NULL, demo_mqtt_process_thread, mqtt_handle); if (res < 0) { printf("pthread_create demo_mqtt_process_thread failed: %d\n", res); return -1; }Konfigurasi fungsi untuk mengelola thread keep-alive.
void *demo_mqtt_process_thread(void *args) { int32_t res = STATE_SUCCESS; while (g_mqtt_process_thread_running) { res = aiot_mqtt_process(args); if (res == STATE_USER_INPUT_EXEC_DISABLED) { break; } sleep(1); } return NULL; }
Langkah 5: Aktifkan thread untuk menerima pesan
Panggil operasi aiot_mqtt_recv untuk menerima pesan MQTT dari broker. Operasi yang diperlukan dilakukan menggunakan callback untuk menerima pesan. Jika terjadi pemutusan koneksi diikuti dengan koneksi ulang otomatis, operasi yang diperlukan dilakukan menggunakan callback untuk menangani event.
Aktifkan thread untuk menerima pesan.
res = pthread_create(&g_mqtt_recv_thread, NULL, demo_mqtt_recv_thread, mqtt_handle); if (res < 0) { printf("pthread_create demo_mqtt_recv_thread failed: %d\n", res); return -1; }Konfigurasi fungsi untuk mengelola thread.
void *demo_mqtt_recv_thread(void *args) { int32_t res = STATE_SUCCESS; while (g_mqtt_recv_thread_running) { res = aiot_mqtt_recv(args); if (res < STATE_SUCCESS) { if (res == STATE_USER_INPUT_EXEC_DISABLED) { break; } sleep(1); } } return NULL; }
Langkah 6: Berlangganan topik
Panggil operasi aiot_mqtt_sub untuk berlangganan topik tertentu.
Kode sampel
{ char *sub_topic = "/a18wP******/LightSwitch/user/get"; res = aiot_mqtt_sub(mqtt_handle, sub_topic, NULL, 1, NULL); if (res < 0) { printf("aiot_mqtt_sub failed, res: -0x%04X\n", -res); return -1; } }CatatanSetelah Anda mengonfigurasi kode sampel, hapus simbol anotasi di kedua sisi kode.
Parameter:
Parameter
Contoh
Deskripsi
sub_topic
/a18wP******/LightSwitch/user/get
Topik yang memiliki izin Berlangganan.
a18wP******menunjukkan ProductKey perangkat.LightSwitchmenunjukkan DeviceName perangkat.
Dalam contoh ini, digunakan topik kustom default.
Perangkat dapat menerima pesan dari Platform IoT melalui topik ini.
Untuk informasi lebih lanjut tentang topik, lihat Topik.
Langkah 7: Mengirim pesan
Panggil operasi aiot_mqtt_pub untuk mengirim pesan ke topik tertentu.
Kode sampel
{ char *pub_topic = "/a18wP******/LightSwitch/user/update"; char *pub_payload = "{\"id\":\"1\",\"version\":\"1.0\",\"params\":{\"LightSwitch\":0}}"; res = aiot_mqtt_pub(mqtt_handle, pub_topic, (uint8_t *)pub_payload, (uint32_t)strlen(pub_payload), 0); if (res < 0) { printf("aiot_mqtt_sub failed, res: -0x%04X\n", -res); return -1; } }CatatanSetelah Anda mengonfigurasi kode sampel, hapus simbol anotasi di kedua sisi kode.
Parameter:
Parameter
Contoh
Deskripsi
pub_topic
/a18wP******/LightSwitch/user/update
Topik yang memiliki izin Publish.
a18wP******menunjukkan ProductKey perangkat.LightSwitchmenunjukkan DeviceName perangkat.
Perangkat dapat mengirim pesan ke Platform IoT melalui topik ini.
Untuk informasi lebih lanjut tentang topik, lihat Topik.
pub_payload
{\"id\":\"1\",\"version\":\"1.0\",\"params\":{\"LightSwitch\":0}}
Pesan yang dikirim ke Platform IoT.
Dalam contoh ini, digunakan topik kustom. Oleh karena itu, Anda dapat menyesuaikan format pesan.
Untuk informasi lebih lanjut tentang format pesan, lihat Format data.
Setelah koneksi MQTT antara perangkat dan Platform IoT berhasil dibangun, pastikan jumlah pesan tidak melebihi ambang batas.
Untuk informasi lebih lanjut tentang batasan, lihat Koneksi dan komunikasi pada topik Limits dalam dokumentasi Platform IoT.
Jika jumlah pesan melebihi ambang batas, masuk ke konsol Platform IoT untuk melihat pesan yang tertumpuk. Untuk informasi lebih lanjut, lihat Lihat dan pantau kelompok konsumen.
Langkah 8: Putuskan koneksi perangkat dari Platform IoT
Koneksi MQTT diterapkan pada perangkat yang tetap terhubung secara persisten. Anda dapat memutuskan koneksi perangkat dari Platform IoT secara manual.
Dalam contoh ini, thread utama digunakan untuk mengatur parameter dan membangun koneksi. Setelah koneksi berhasil dibangun, Anda dapat menidurkan thread utama.
Panggil operasi aiot_mqtt_disconnect untuk memutuskan koneksi perangkat dari Platform IoT.
res = aiot_mqtt_disconnect(mqtt_handle);
if (res < STATE_SUCCESS) {
aiot_mqtt_deinit(&mqtt_handle);
printf("aiot_mqtt_disconnect failed: -0x%04X\n", -res);
return -1;
}Langkah 9: Keluar dari program
Panggil operasi aiot_mqtt_deinit untuk menghapus instans klien MQTT dan melepaskan sumber daya.
res = aiot_mqtt_deinit(&mqtt_handle);
if (res < STATE_SUCCESS) {
printf("aiot_mqtt_deinit failed: -0x%04X\n", -res);
return -1;
}Langkah selanjutnya
Setelah Anda mengonfigurasi file kode sampel, kompilasi file tersebut untuk menghasilkan file yang dapat dieksekusi. Dalam contoh ini, dihasilkan file yang dapat dieksekusi
./output/mqtt-basic-demo.Untuk informasi lebih lanjut, lihat Kompilasi dan menjalankan.
Untuk informasi lebih lanjut tentang hasil eksekusi, lihat Lihat log.