1. 程式人生 > >阿里雲MQTT 客戶端收發 MQTT 訊息(使用一個裝置控制另一個裝置)

阿里雲MQTT 客戶端收發 MQTT 訊息(使用一個裝置控制另一個裝置)

https://help.aliyun.com/document_detail/44874.html?spm=a2c4g.11186623.6.721.qxegRK
1保證只有一組使用者AccessKey,怕衝突其他的可暫時禁用
(踩過的坑:域名必須是這個格式tcp://mqtt-cn-4590pc20t03.mqtt.aliyuncs.com:1883)
(踩過的坑:傳送的訊息分為兩種,一是廣播的方式:一方傳送,多方接收;二是點對點式的(p2p)只能一個裝置控制另一個,不可多個,即三級topic,可使用裝置的實體地址作為區分,保證唯一即可String p2pTopic = topic + “/p2p/

[email protected]@@34:0a:ff:52:01:66”)
最大的一個坑:測試接收訊息的時候發現總是不執行messageArrived,其實應該先點選接收訊息出現messageArrived,此時點擊發送訊息,即可看到接收端的日誌。取出訊息的api是new String(mqttMessage.getPayload())
2 傳送訊息程式碼,acessKey secretKey 並不真實,已做處理。

public class MainActivity extends AppCompatActivity {
    /**
     * 設定當前使用者私有的MQTT的接入點。例如此處示意使用XXX,實際使用請替換使用者自己的接入點。接入點的獲取方法是,在控制檯申請MQTT例項,每個例項都會分配一個接入點域名。
     */
// final String broker ="tcp://XXXX.mqtt.aliyuncs.com:1883"; final String broker = "tcp://mqtt-cn-4590pc20t03.mqtt.aliyuncs.com:1883"; /** * 設定阿里雲的AccessKey,用於鑑權 */ final String acessKey = "LTAI2jtCdfgOCbJaY1"; /** * 設定阿里雲的SecretKey,用於鑑權 */ final String secretKey = "FPqp6oQ2JWCEZ6PlxN9eI42wPfnecLZD32"
; /** * 發訊息使用的一級Topic,需要先在MQ控制檯裡申請 */ final String topic = "wy1"; /** * MQTT的ClientID,一般由兩部分組成,[email protected]@@DeviceID * 其中GroupID在MQ控制檯裡申請 * DeviceID由應用方設定,可能是裝置編號等,需要唯一,否則服務端拒絕重複的ClientID連線 */ // final String clientId ="[email protected]@@ClientID_XXXX"; String clientId; String sign; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); clientId = "[email protected]@@" + getWlanId(); Log.e("1", "clientId: "+ clientId); } private String getWlanId() { WifiManager wm = (WifiManager) getApplicationContext().getSystemService(getApplicationContext().WIFI_SERVICE); String m_szWLANMAC = wm.getConnectionInfo().getMacAddress(); return m_szWLANMAC; } public void send(View mView) { MemoryPersistence persistence = new MemoryPersistence(); try { final MqttClient sampleClient = new MqttClient(broker, clientId, persistence); final MqttConnectOptions connOpts = new MqttConnectOptions(); System.out.println("Connecting to broker: " + broker); /** * 計算簽名,將簽名作為MQTT的password。 * 簽名的計算方法,參考工具類MacSignature,第一個引數是ClientID的前半部分,即GroupID * 第二個引數阿里雲的SecretKey */ sign = MacSignature.macSignature(clientId.split("@@@")[0], secretKey); connOpts.setUserName(acessKey); connOpts.setServerURIs(new String[]{broker}); connOpts.setPassword(sign.toCharArray()); connOpts.setCleanSession(true); connOpts.setKeepAliveInterval(90); connOpts.setMqttVersion(MQTT_VERSION_3_1_1); connOpts.setAutomaticReconnect(true); sampleClient.setCallback(new MqttCallbackExtended() { public void connectComplete(boolean reconnect, String serverURI) { System.out.println("connect success"); //連線成功,需要上傳客戶端所有的訂閱關係 } public void connectionLost(Throwable throwable) { System.out.println("mqtt connection lost"); } public void messageArrived(String topic, MqttMessage mqttMessage) throws Exception { System.out.println("messageArrived:" + topic + "------" + new String(mqttMessage.getPayload())); } public void deliveryComplete(IMqttDeliveryToken iMqttDeliveryToken) { System.out.println("deliveryComplete:" + iMqttDeliveryToken.getMessageId()); } }); sampleClient.connect(connOpts); for (int i = 0; i < 1; i++) { try { // String scontent = new Date() + "MQTT Test body wangyang" + i; String scontent = "MQTT Test body wangyang" + i; //此處訊息體只需要傳入byte陣列即可,對於其他型別的訊息,請自行完成二進位制資料的轉換 final MqttMessage message = new MqttMessage(scontent.getBytes()); message.setQos(0); System.out.println(i + " pushed at " + new Date() + " " + scontent); /** *訊息傳送到某個主題Topic,所有訂閱這個Topic的裝置都能收到這個訊息。 * 遵循MQTT的釋出訂閱規範,Topic也可以是多級Topic。此處設定了傳送到二級Topic */ sampleClient.publish(topic + "/notice/", message); /** * 如果傳送P2P訊息,二級Topic必須是“p2p”,三級Topic是目標的ClientID * 此處設定的三級Topic需要是接收方的ClientID */ // String p2pTopic = topic + "/p2p/[email protected]@@DEVICEID_001"; // String p2pTopic = topic + "/p2p/[email protected]@@34:0a:ff:52:01:66"; // sampleClient.publish(p2pTopic, message); } catch (Exception e) { e.printStackTrace(); } } } catch (Exception me) { me.printStackTrace(); } } }

3接收端程式碼

public class RecvActivity extends Activity {
    /**
     * 設定當前使用者私有的MQTT的接入點。例如此處示意使用XXX,實際使用請替換使用者自己的接入點。接入點的獲取方法是,在控制檯申請MQTT例項,每個例項都會分配一個接入點域名。
     */
//        final String broker ="tcp://XXXX.mqtt.aliyuncs.com:1883";
    final String broker = "tcp://mqtt-cn-4590pc20t03.mqtt.aliyuncs.com:1883";
    /**
     * 設定阿里雲的AccessKey,用於鑑權
     */
    final String acessKey = "LTAI2jtCdfgOCbJaY1";
    /**
     * 設定阿里雲的SecretKey,用於鑑權
     */
    final String secretKey = "FPqp6fgoQ2JWCEZ236PlxN9eIwPfnecLZD";
    /**
     * 發訊息使用的一級Topic,需要先在MQ控制檯裡申請
     */
    final String topic = "wy1";
    /**
     * MQTT的ClientID,一般由兩部分組成,[email protected]@@DeviceID
     * 其中GroupID在MQ控制檯裡申請
     * DeviceID由應用方設定,可能是裝置編號等,需要唯一,否則服務端拒絕重複的ClientID連線
     */
//        final String clientId ="[email protected]@@ClientID_XXXXXX";
    String clientId ;
    String sign;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_recv);
        clientId="[email protected]@@"+getWlanId();
        Log.e("1", "clientId: "+ clientId);
//        recv();
    }
    private String getWlanId() {
        WifiManager wm = (WifiManager) getApplicationContext().getSystemService(getApplicationContext().WIFI_SERVICE);
        String m_szWLANMAC = wm.getConnectionInfo().getMacAddress();
        return m_szWLANMAC;
    }

    public void recv(View mView) {
        MemoryPersistence persistence = new MemoryPersistence();
        try {
            final MqttClient sampleClient = new MqttClient(broker, clientId, persistence);
            final MqttConnectOptions connOpts = new MqttConnectOptions();
            System.out.println("Connecting to broker: " + broker);
            /**
             * 計算簽名,將簽名作為MQTT的password
             * 簽名的計算方法,參考工具類MacSignature,第一個引數是ClientID的前半部分,即GroupID
             * 第二個引數阿里雲的SecretKey
             */
            sign = MacSignature.macSignature(clientId.split("@@@")[0], secretKey);
            /**
             * 設定訂閱方訂閱的Topic集合,此處遵循MQTT的訂閱規則,可以是一級Topic,二級Topic,P2P訊息請訂閱/p2p
             */
            final String[] topicFilters = new String[]{topic + "/notice/", topic + "/p2p"};
            final int[] qos = {0, 0};
            connOpts.setUserName(acessKey);
            connOpts.setServerURIs(new String[]{broker});
            connOpts.setPassword(sign.toCharArray());
            connOpts.setCleanSession(true);
            connOpts.setKeepAliveInterval(90);
            connOpts.setMqttVersion(MQTT_VERSION_3_1_1);
            connOpts.setAutomaticReconnect(true);
            sampleClient.setCallback(new MqttCallbackExtended() {
                public void connectComplete(boolean reconnect, String serverURI) {
                    System.out.println("rev connect success");
                    //連線成功,需要上傳客戶端所有的訂閱關係
                    try {
                        sampleClient.subscribe(topicFilters, qos);
                    } catch (MqttException mE) {
                        mE.printStackTrace();
                    }
                }

                public void connectionLost(Throwable throwable) {
                    System.out.println("mqtt connection lost");
                }

                public void messageArrived(String topic, MqttMessage mqttMessage) throws Exception {
                    System.out.println("接收到訊息:"+new String(mqttMessage.getPayload()));
                    System.out.println("messageArrived  topic:" + topic +"------接收到訊息:" + new String(mqttMessage.getPayload()));
                }

                public void deliveryComplete(IMqttDeliveryToken iMqttDeliveryToken) {
                    System.out.println("deliveryComplete:" + iMqttDeliveryToken.getMessageId());
                }
            });
            //客戶端每次上線都必須上傳自己所有涉及的訂閱關係,否則可能會導致訊息接收延遲
            sampleClient.connect(connOpts);
            //每個客戶端最多允許存在30個訂閱關係,超出限制可能會丟棄導致收不到部分訊息
            sampleClient.subscribe(topicFilters, qos);
            Thread.sleep(Integer.MAX_VALUE);
        } catch (Exception me) {
            me.printStackTrace();
        }
    }
}