This topic describes how to connect a device to IoT Platform by using HTTP.

You can connect a device to IoT Platform by using HTTP. For more information, see Establish connections over HTTP.

This topic uses a sample code developed based on the device SDK for Java to connect a device with IoT Platform. Before you can establish the connectioin, you must specify the required parameters, such as request parameters and certificate information of the device.

Note This feature is available only in the China (Shanghai) region.

Configure the pom.xml file

Add the following dependency to the pom.xml file to import the Alibaba fastjson package.

<dependency>
  <groupId>com.alibaba</groupId>
  <artifactId>fastjson</artifactId>
  <version>1.2.61</version>
</dependency>

Sample code

The following code shows how to connect a device to IoT Platform and enable data communication.

/*   
 * Copyright © 2019 Alibaba. All rights reserved.
 */
package com.aliyun.iot.demo;

import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.util.Set;
import java.util.SortedMap;
import java.util.TreeMap;

import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import javax.net.ssl.HttpsURLConnection;

import com.alibaba.fastjson.JSONObject;

/**
 * Connect a device to IoT Platform by using HTTP. 
 * For more information about the HTTP protocol, see HTTP standard.
 * For more information about the data format, see Establish connections over HTTP.
 */
public class IotHttpClient {

    // The ID of the region. Only the China (Shanghai) region is available.
    private static String regionId = "cn-shanghai";

    // Specify an encryption algorithm. Set the HMAC_ALGORITHM parameter to hmacsha1 or hmacmd5. The value that you set must be the same as that of the signmethod parameter.
    private static final String HMAC_ALGORITHM = "hmacsha1";

    // The validity period of a token is seven days. After a token expires, you must obtain a new token.
    private String token = null;

    /**
     * Initialize an HTTP client.
     * 
     * @param productKey The key of the product.
     * @param deviceName The name of the device.
     * @param deviceSecret The key of the device.
     */
    public void conenct(String productKey, String deviceName, String deviceSecret) {
        try {
            // The endpoint for authentication.
            URL url = new URL("https://iot-as-http." + regionId + ".aliyuncs.com/auth");

            HttpsURLConnection conn = (HttpsURLConnection) url.openConnection();
            conn.setRequestMethod("POST");
            conn.setRequestProperty("Content-type", "application/json");
            conn.setDoOutput(true);
            conn.setDoInput(true);

            // Obtain the output stream of the URLConnection object.
            PrintWriter out = new PrintWriter(conn.getOutputStream());
            // Send request parameters.
            out.print(authBody(productKey, deviceName, deviceSecret));
            // Print out the contents of the cache.
            out.flush();

            // Obtain the input stream of the URLConnection object.
            BufferedReader in = new BufferedReader(new InputStreamReader(conn.getInputStream()));
            // Obtain responses from the endpoint.
            String result = "";
            String line = "";
            while ((line = in.readLine()) ! = null) {
                result += line;
            }
            System.out.println("----- auth result -----");
            System.out.println(result);

            // Close input and output streams.
            in.close();
            out.close();
            conn.disconnect();

            // Obtain a token.
            JSONObject json = JSONObject.parseObject(result);
            if (json.getIntValue("code") == 0) {
                token = json.getJSONObject("info").getString("token");
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * Send messages.
     * 
     @param topic The topic to which messages are sent.
     * @param payload The contents of messages.
     */
    public void publish(String topic, byte[] payload) {
        try {
            // Specify the endpoint of a topic to which messages are sent.
            URL url = new URL("https://iot-as-http." + regionId + ".aliyuncs.com/topic" + topic);

            HttpsURLConnection conn = (HttpsURLConnection) url.openConnection();
            conn.setRequestMethod("POST");
            conn.setRequestProperty("Content-type", "application/octet-stream");
            conn.setRequestProperty("password", token);
            conn.setDoOutput(true);
            conn.setDoInput(true);

            // Obtain the output stream of the URLConnection object.
            BufferedOutputStream out = new BufferedOutputStream(conn.getOutputStream());
            out.write(payload);
            out.flush();

            // Obtain the input stream of the URLConnection object.
            BufferedReader in = new BufferedReader(new InputStreamReader(conn.getInputStream()));
            // Obtain responses from the endpoint.
            String result = "";
            String line = "";
            while ((line = in.readLine()) ! = null) {
                result += line;
            }
            System.out.println("----- publish result -----");
            System.out.println(result);

            // Close input and output streams.
            in.close();
            out.close();
            conn.disconnect();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * Generate the required parameters for authentication.
     * 
     * @param params The required parameters for authentication.
     * @return A message that includes an authentication request.
     */
    private String authBody(String productKey, String deviceName, String deviceSecret) {

        // Create a authentication request.
        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("version", "default");
        body.put("sign", sign(body, deviceSecret));

        System.out.println("----- auth body -----");
        System.out.println(body.toJSONString());

        return body.toJSONString();
    }

    /**
     * Generate a signature for the device
     * 
     * @param params The required parameters that you can use to generate a signature
     * @param deviceSecret The key of a device
     * @return The signature in the hexadecimal format.
     */
    private String sign(JSONObject params, String deviceSecret) {

        // Sort request parameters in alphbetical order.
        Set<String> keys = getSortedKeys(params);

        // Remove the sign, signmethod, and version parameters.
        keys.remove("sign");
        keys.remove("signmethod");
        keys.remove("version");

        // Obtain the plaintext of the signature
        StringBuffer content = new StringBuffer();
        for (String key : keys) {
            content.append(key);
            content.append(params.getString(key));
        }

        // Generate a signature
        String sign = encrypt(content.toString(), deviceSecret);
        System.out.println("sign content=" + content);
        System.out.println("sign result=" + sign);

        return sign;
    }

    /**
     * Convert a JSON object to a set of key-value pairs.
     * 
     * @param json The JSON object to be converted.
     * @return A set of key-value pairs that are converted from the JSON object.
     */
    private Set<String> getSortedKeys(JSONObject json) {
        SortedMap<String, String> map = new TreeMap<String, String>();
        for (String key : json.keySet()) {
            String vlaue = json.getString(key);
            map.put(key, vlaue);
        }
        return map.keySet();
    }

    /**
     * Specify an encryption method in the HMAC_ALGORITHM parameter.
     * 
     * @param content Plaintext.
     * @param secret An encryption key.
     * @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 byte2hex(mac.doFinal(text));
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    /**
     * Convert a binary array to a hexadecimal string.
     * 
     * @param b The binary array.
     * @return A hexadecimal string.
     */
    private String byte2hex(byte[] b) {
        StringBuffer sb = new StringBuffer();
        for (int n = 0; b ! = null && n < b.length; n++) {
            String stmp = Integer.toHexString(b[n] & 0XFF);
            if (ss.length == 1) {
                sb.append('0');
            }
            sb.append(stmp);
        }
        return sb.toString().toUpperCase();
    }

    public static void main(String[] args) {
        String productKey = "The productKey of your device";
        String deviceName = "The deviceName of your device";
        String deviceSecret = "The deviceSecret of your device";
        IotHttpClient client = new IotHttpClient();
        client.conenct(productKey, deviceName, deviceSecret);
        // The topic to which messages are sent. In the IoT Platform console, you can create a custom topic and grant the publish permission to devices.
        String updateTopic = "/" + productKey + "/" + deviceName + "/user/update";
        client.publish(updateTopic, "hello http".getBytes(StandardCharsets.UTF_8));
        client.publish(updateTopic, new byte[] { 0x01, 0x02, 0x03 });
    }
}