全部产品
Search
文档中心

IoT Platform:Menghubungkan perangkat ke IoT Platform menggunakan CoAP

更新时间:Jun 21, 2025

Topik ini menjelaskan cara menghubungkan perangkat ke IoT Platform menggunakan Constrained Application Protocol (CoAP). Dalam contoh ini, kode Java digunakan.

Informasi latar belakang

CoAP cocok untuk perangkat hemat daya dan dengan sumber daya terbatas, seperti perangkat NB-IoT. Untuk informasi tentang cara menghubungkan perangkat ke IoT Platform menggunakan CoAP, lihat Menghubungkan Perangkat ke IoT Platform melalui CoAP.

null Anda hanya dapat menghubungkan perangkat ke IoT Platform menggunakan CoAP di wilayah Tiongkok (Shanghai).

Saat menghubungkan perangkat ke IoT Platform menggunakan CoAP, Anda harus menentukan parameter yang diperlukan, menghasilkan tanda tangan untuk perangkat, dan melakukan operasi lainnya. Kode contoh berbasis Eclipse Californium digunakan untuk menggambarkan proses konfigurasi. Untuk memastikan keamanan data, enkripsi simetris digunakan.

Menyiapkan lingkungan pengembangan

Lingkungan pengembangan Java berikut siap digunakan.

Prosedur

  1. Buka IntelliJ IDEA dan buat proyek Maven. Contoh: IotCoap-demo.
  2. Tambahkan dependensi berikut ke file pom.xml dalam proyek, lalu klik Load Maven Changes untuk mengunduh paket dependensi. Dengan cara ini, kerangka kerja Californium, toolkit Apache Commons, dan paket fastjson Alibaba Cloud diimpor.
    <dependency>
      <groupId>org.eclipse.californium</groupId>
      <artifactId>californium-core</artifactId>
      <version>2.0.0-M17</version>
    </dependency>
    <dependency>
      <groupId>org.apache.commons</groupId>
      <artifactId>commons-lang3</artifactId>
      <version>3.5</version>
    </dependency>
    <dependency>
      <groupId>commons-codec</groupId>
      <artifactId>commons-codec</artifactId>
      <version>1.13</version>
    </dependency>
    <dependency>
      <groupId>com.alibaba</groupId>
      <artifactId>fastjson</artifactId>
      <version>1.2.83</version>
    </dependency>
  3. Di direktori /src/main/java dari proyek IotCoap-demo, buat kelas Java seperti IotCoapClientWithAes.java, dan masukkan kode. Contoh kode:
    import java.io.IOException;
    import java.nio.charset.StandardCharsets;
    import java.security.MessageDigest;
    import java.security.NoSuchAlgorithmException;
    import java.util.Set;
    import java.util.SortedMap;
    import java.util.TreeMap;
    
    import javax.crypto.Cipher;
    import javax.crypto.Mac;
    import javax.crypto.spec.IvParameterSpec;
    import javax.crypto.spec.SecretKeySpec;
    
    import org.apache.commons.codec.DecoderException;
    import org.apache.commons.codec.binary.Hex;
    import org.apache.commons.lang3.RandomUtils;
    import org.eclipse.californium.core.CoapClient;
    import org.eclipse.californium.core.CoapResponse;
    import org.eclipse.californium.core.Utils;
    import org.eclipse.californium.core.coap.CoAP;
    import org.eclipse.californium.core.coap.CoAP.Code;
    import org.eclipse.californium.core.coap.CoAP.Type;
    import org.eclipse.californium.core.coap.MediaTypeRegistry;
    import org.eclipse.californium.core.coap.Option;
    import org.eclipse.californium.core.coap.OptionNumberRegistry;
    import org.eclipse.californium.core.coap.OptionSet;
    import org.eclipse.californium.core.coap.Request;
    import org.eclipse.californium.elements.exception.ConnectorException;
    
    import com.alibaba.fastjson.JSONObject;
    
    /**
     * Kode berbasis Eclipse Californium berikut menunjukkan cara menghubungkan perangkat ke IoT Platform menggunakan CoAP.
     * Untuk informasi lebih lanjut tentang proses pengembangan dan parameter akses otonom, lihat bagian "Menghubungkan perangkat menggunakan enkripsi simetris" dalam topik Menghubungkan perangkat ke IoT Platform melalui CoAP.
     */
    public class IotCoapClientWithAes {
    
        // ======================== Anda harus menentukan parameter berikut. ===========================
        // ID wilayah. Tiongkok (Shanghai) digunakan dalam contoh ini.
        private static String regionId = "cn-shanghai";
        // ProductKey produk tempat perangkat Anda termasuk.
        private static String productKey = "ProductKey perangkat Anda";
        // DeviceName perangkat.
        private static String deviceName = "DeviceName perangkat Anda";
        // DeviceSecret perangkat.
        private static String deviceSecret = "DeviceSecret perangkat Anda";
        //======================= Akhir ===========================
    
        // Tetapkan parameter HMAC_ALGORITHM ke hmacsha1 atau hmacmd5. Nilai yang Anda tentukan harus sama dengan nilai parameter signmethod.
        private static final String HMAC_ALGORITHM = "hmacsha1";
    
        // Titik akhir yang digunakan untuk menghubungkan perangkat ke instance IoT Platform melalui CoAP. Jika Anda menggunakan enkripsi simetris, nomor port titik akhir adalah 5682.
        private static String serverURI = "coap://" + productKey + ".coap." + regionId + ".link.aliyuncs.com:5682";
    
        // Topik tempat pesan dikirim. Di konsol IoT Platform, Anda dapat membuat topik kustom dan memberikan izin Publish pada topik kepada perangkat.
        private static String updateTopic = "/" + productKey + "/" + deviceName + "/user/update";
    
        // token option
        private static final int COAP2_OPTION_TOKEN = 2088;
        // seq option
        private static final int COAP2_OPTION_SEQ = 2089;
    
        // Algoritma enkripsi SHA-256.
        private static final String SHA_256 = "SHA-256";
    
        private static final int DIGITAL_16 = 16;
        private static final int DIGITAL_48 = 48;
    
        // Klien CoAP.
        private CoapClient coapClient = new CoapClient();
    
        // Masa berlaku token adalah tujuh hari. Setelah token kedaluwarsa, Anda harus mendapatkan token baru.
        private String token = null;
        private String random = null;
        @SuppressWarnings("unused")
        private long seqOffset = 0;
    
        /**
         * Inisialisasi klien CoAP.
         *
         * @param productKey: ProductKey produk tempat perangkat Anda termasuk.
         * @param deviceName: DeviceName perangkat Anda.
         * @param deviceSecret: DeviceSecret perangkat Anda.
         */
        public void connect(String productKey, String deviceName, String deviceSecret) {
            try {
                // Titik akhir yang digunakan untuk autentikasi.
                String uri = serverURI + "/auth";
    
                // Hanya metode POST yang didukung.
                Request request = new Request(Code.POST, Type.CON);
    
                // Tentukan opsi.
                OptionSet optionSet = new OptionSet();
                optionSet.addOption(new Option(OptionNumberRegistry.CONTENT_FORMAT, MediaTypeRegistry.APPLICATION_JSON));
                optionSet.addOption(new Option(OptionNumberRegistry.ACCEPT, MediaTypeRegistry.APPLICATION_JSON));
                request.setOptions(optionSet);
    
                // Tentukan titik akhir yang dapat Anda gunakan untuk mengautentikasi perangkat.
                request.setURI(uri);
    
                // Tentukan parameter yang diperlukan untuk permintaan autentikasi.
                request.setPayload(authBody(productKey, deviceName, deviceSecret));
    
                // Kirim permintaan autentikasi.
                CoapResponse response = coapClient.advanced(request);
                System.out.println(Utils.prettyPrint(response));
                System.out.println();
    
                // Analisis respons.
                JSONObject json = JSONObject.parseObject(response.getResponseText());
                token = json.getString("token");
                random = json.getString("random");
                seqOffset = json.getLongValue("seqOffset");
            } catch (ConnectorException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    
        /**
         * Kirim pesan.
         *
         @param topic Topik tempat pesan dikirim.
         * @param payload Isi pesan.
         */
        public void publish(String topic, byte[] payload) {
            try {
                // Titik akhir topik. Sintaks topik adalah /topic/${topic}.
                String uri = serverURI + "/topic" + topic;
    
                // Enkripsi opsi seq menggunakan algoritma enkripsi AES. seq=RandomUtils.nextInt().
                String shaKey = encod(deviceSecret + "," + random);
                byte[] keys = Hex.decodeHex(shaKey.substring(DIGITAL_16, DIGITAL_48));
                byte[] seqBytes = encrypt(String.valueOf(RandomUtils.nextInt()).getBytes(StandardCharsets.UTF_8), keys);
    
                // Hanya metode POST yang didukung.
                Request request = new Request(CoAP.Code.POST, CoAP.Type.CON);
    
                // Tentukan opsi.
                OptionSet optionSet = new OptionSet();
                optionSet.addOption(new Option(OptionNumberRegistry.CONTENT_FORMAT, MediaTypeRegistry.APPLICATION_JSON));
                optionSet.addOption(new Option(OptionNumberRegistry.ACCEPT, MediaTypeRegistry.APPLICATION_JSON));
                optionSet.addOption(new Option(COAP2_OPTION_TOKEN, token));
                optionSet.addOption(new Option(COAP2_OPTION_SEQ, seqBytes));
                request.setOptions(optionSet);
    
                // Tentukan titik akhir topik.
                request.setURI(uri);
    
                // Tentukan parameter payload.
                request.setPayload(encrypt(payload, keys));
    
                // Kirim pesan.
                CoapResponse response = coapClient.advanced(request);
                System.out.println(Utils.prettyPrint(response));
    
                // Analisis hasil.
                String result = null;
                if (response.getPayload() != null) {
                    result = new String(decrypt(response.getPayload(), keys));
                }
                System.out.println("payload: " + result);
                System.out.println();
            } catch (ConnectorException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            } catch (DecoderException e) {
                e.printStackTrace();
            }
        }
    
        /**
         * Hasilkan parameter yang diperlukan untuk autentikasi.
         *
         * @param productKey: ProductKey produk tempat perangkat Anda termasuk.
         * @param deviceName: DeviceName perangkat.
         * @param deviceSecret: DeviceSecret perangkat.
         * @return: permintaan autentikasi.
         */
        private String authBody(String productKey, String deviceName, String deviceSecret) {
    
            // Buat permintaan autentikasi.
            JSONObject body = new JSONObject();
            body.put("productKey", productKey);
            body.put("deviceName", deviceName);
            body.put("clientId", productKey + "." + deviceName);
            body.put("timestamp", String.valueOf(System.currentTimeMillis()));
            body.put("signmethod", HMAC_ALGORITHM);
            body.put("seq", DIGITAL_16);
            body.put("sign", sign(body, deviceSecret));
    
            System.out.println("----- auth body -----");
            System.out.println(body.toJSONString());
    
            return body.toJSONString();
        }
    
        /**
         * Hasilkan tanda tangan untuk perangkat.
         *
         * @param params: parameter yang diperlukan untuk menghasilkan tanda tangan.
         * @param deviceSecret: DeviceSecret perangkat.
         * @return: string tanda tangan heksadesimal.
         */
        private String sign(JSONObject params, String deviceSecret) {
    
            // Urutkan parameter permintaan secara alfabetis.
            Set<String> keys = getSortedKeys(params);
    
            // Hapus parameter sign, signmethod, version, dan resources.
            keys.remove("sign");
            keys.remove("signmethod");
            keys.remove("version");
            keys.remove("resources");
    
            // Dapatkan plaintext tanda tangan.
            StringBuffer content = new StringBuffer();
            for (String key : keys) {
                content.append(key);
                content.append(params.getString(key));
            }
    
            // Hasilkan tanda tangan.
            String sign = encrypt(content.toString(), deviceSecret);
            System.out.println("sign content=" + content);
            System.out.println("sign result=" + sign);
    
            return sign;
        }
    
        /**
         * Urutkan kunci objek JSON secara alfabetis.
         *
         * @param json: objek JSON yang ingin Anda urutkan kuncinya.
         * @return: set kunci yang diurutkan secara alfabetis.
         */
        private Set<String> getSortedKeys(JSONObject json) {
            SortedMap<String, String> map = new TreeMap<String, String>();
            for (String key : json.keySet()) {
                String value = json.getString(key);
                map.put(key, value);
            }
            return map.keySet();
        }
    
        /**
         * Tentukan algoritma enkripsi menggunakan parameter HMAC_ALGORITHM.
         *
         * @param content: plaintext
         * @param secret: kunci enkripsi
         * @return: ciphertext
         */
        private String encrypt(String content, String secret) {
            try {
                byte[] text = content.getBytes(StandardCharsets.UTF_8);
                byte[] key = secret.getBytes(StandardCharsets.UTF_8);
                SecretKeySpec secretKey = new SecretKeySpec(key, HMAC_ALGORITHM);
                Mac mac = Mac.getInstance(secretKey.getAlgorithm());
                mac.init(secretKey);
                return Hex.encodeHexString(mac.doFinal(text));
            } catch (Exception e) {
                e.printStackTrace();
                return null;
            }
        }
    
        /**
         * SHA-256
         *
         * @param str: pesan yang ingin Anda enkripsi.
         */
        private String encod(String str) {
            MessageDigest messageDigest;
            String encdeStr = "";
            try {
                messageDigest = MessageDigest.getInstance(SHA_256);
                byte[] hash = messageDigest.digest(str.getBytes(StandardCharsets.UTF_8));
                encdeStr = Hex.encodeHexString(hash);
            } catch (NoSuchAlgorithmException e) {
                System.out.println(String.format("Exception@encod: str=%s;", str));
                e.printStackTrace();
                return null;
            }
            return encdeStr;
        }
    
        // Enkripsi dan dekripsi data menggunakan algoritma AES.
        private static final String IV = "543yhjy97ae7fyfg";
        private static final String TRANSFORM = "AES/CBC/PKCS5Padding";
        private static final String ALGORITHM = "AES";
    
        /**
         * panjang kunci = 16 bit
         */
        private byte[] encrypt(byte[] content, byte[] key) {
            return encrypt(content, key, IV);
        }
    
        /**
         * panjang kunci = 16 bit
         */
        private byte[] decrypt(byte[] content, byte[] key) {
            return decrypt(content, key, IV);
        }
    
        /**
         * aes 128 cbc panjang kunci = 16 bit
         */
        private byte[] encrypt(byte[] content, byte[] key, String ivContent) {
            try {
                SecretKeySpec keySpec = new SecretKeySpec(key, ALGORITHM);
                Cipher cipher = Cipher.getInstance(TRANSFORM);
                IvParameterSpec iv = new IvParameterSpec(ivContent.getBytes(StandardCharsets.UTF_8));
                cipher.init(Cipher.ENCRYPT_MODE, keySpec, iv);
                return cipher.doFinal(content);
            } catch (Exception ex) {
                System.out.println(
                        String.format("AES encrypt error, %s, %s, %s", content, Hex.encodeHex(key), ex.getMessage()));
                return null;
            }
        }
    
        /**
         * aes 128 cbc panjang kunci = 16 bit
         */
        private byte[] decrypt(byte[] content, byte[] key, String ivContent) {
            try {
                SecretKeySpec keySpec = new SecretKeySpec(key, ALGORITHM);
                Cipher cipher = Cipher.getInstance(TRANSFORM);
                IvParameterSpec iv = new IvParameterSpec(ivContent.getBytes(StandardCharsets.UTF_8));
                cipher.init(Cipher.DECRYPT_MODE, keySpec, iv);
                return cipher.doFinal(content);
            } catch (Exception ex) {
                System.out.println(String.format("AES decrypt error, %s, %s, %s", Hex.encodeHex(content),
                        Hex.encodeHex(key), ex.getMessage()));
                return null;
            }
        }
    
        public static void main(String[] args) throws InterruptedException {
            IotCoapClientWithAes client = new IotCoapClientWithAes();
            client.connect(productKey, deviceName, deviceSecret);
            client.publish(updateTopic, "hello coap".getBytes(StandardCharsets.UTF_8));
            client.publish(updateTopic, new byte[] { 0x01, 0x02, 0x03, 0x05 });
        }
    }
  4. Tentukan parameter berikut.
    ParameterDeskripsi
    regionIdID wilayah tempat IoT Platform berada.

    Anda dapat melihat wilayah tersebut di pojok kiri atas konsol IoT Platform.

    Untuk informasi lebih lanjut tentang ID wilayah, lihat Wilayah.

    productKeyInformasi sertifikat perangkat yang dapat Anda peroleh setelah menambahkan perangkat ke konsol IoT Platform.

    Anda dapat melihat informasi tersebut di halaman Device Details di konsol IoT Platform.

    deviceName
    deviceSecret
    serverURI Titik akhir yang digunakan untuk menghubungkan perangkat ke IoT Platform melalui CoAP. Untuk informasi lebih lanjut, lihat Kelola titik akhir sebuah instans.
  5. Jalankan program IotCoapClientWithAes.java.
    Berikut ini adalah contoh kode yang menunjukkan hasil eksekusi. Perangkat dapat berkomunikasi dengan IoT Platform setelah perangkat diautentikasi.
    sign content=clientIda1****RK0.devicedeviceNamedeviceproductKeya1OX****K0seq16timestamp1658909565141
    sign result=7f3b76dc21e7******fec424838d1858
    ----- auth body -----
    {"clientId":"a1OXp8sXRK0.device","signmethod":"hmacsha1","sign":"7f3b76dc21e7******fec424838d1858","productKey":"a1OX****K0","deviceName":"device","seq":16,"timestamp":"1658909565141"}
    ==[ CoAP Response ]============================================
    MID    : 37682
    Token  : 6E1F******6B91
    Type   : ACK
    Status : 2.05 - CONTENT
    Options: {}
    RTT    : 116 ms
    Payload: 85 Bytes
    ---------------------------------------------------------------
    {"random":"a25******6d44","seqOffset":1,"token":"mnx4OF0b******R000000.5ac7"}
    ===============================================================
    
    ==[ CoAP Response ]============================================
    MID    : 37683
    Token  : AC60******106E7
    Type   : ACK
    Status : 2.05 - CONTENT
    Options: {"Unknown (2090)":0x158a******6aa00}
    RTT    : 118 ms
    Payload: 0 Bytes
    ===============================================================
    payload: null
    
    ==[ CoAP Response ]============================================
    MID    : 37684
    Token  : AA9******EFCC
    Type   : ACK
    Status : 2.05 - CONTENT
    Options: {"Unknown (2090)":0x158a******f600}
    RTT    : 103 ms
    Payload: 0 Bytes
    ===============================================================
    payload: null