MQTT는 정말 재미있습니다. 직접 만들 수는 없나요?

머리말

MQTT가 왜 스마트하드웨어의 첫 번째 선택인지 이전에 글을 썼는데 - Nuggets 이번에는 나만의 MQTT 인터랙티브 플랫폼을 구축하고 실전에서 체험해보겠다.

1. 서버 준비

1. 플랫폼 선택

여기서 사용하는 플랫폼은 EMQX Cloud 입니다 . github 계정을 통해 무료로 MQTT 서버를 신청할 수 있습니다. 개인용으로 매우 편리합니다. 동시에 MQTT 클라이언트를 사용하여 MQTT 서비스를 빠르게 테스트하여 모니터링하거나 시뮬레이션합니다. 여기에서 무료로 열기를 선택합니다. 지금 배포를 클릭하고 끝까지 동의하면 완료됩니다.이미지.png

2. 서비스 시작

설정 후 프로젝트 관리를 클릭하면 방금 신청한 서버가 있을 것이고 입력 후 시작을 클릭하면 서비스를 시작할 수 있습니다.이미지.png 이미지.png

3. 사용자 생성

인증을 클릭하고 인증을 선택한 다음 오른쪽에 있는 추가를 클릭하여 연결 사용자를 생성합니다.사용자 이름과 암호는 연결을 설정할 때 클라이언트가 필요로 하는 사용자 이름과 암호입니다. 지금까지 연결 코드를 작성하기 위해 클라이언트로 이동할 수 있습니다.이미지.png

2. 클라이언트 빌드

1. 수입

dependencies {
    implementation 'org.eclipse.paho:org.eclipse.paho.client.mqttv3:1.2.4'
    implementation 'org.eclipse.paho:org.eclipse.paho.android.service:1.1.1' 
}

2. AndroidManifest.xml 구성

<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />

<application
   ...
   <service android:name="org.eclipse.paho.android.service.MqttService" />
</application>

3. MQTT 클라이언트 생성

private static MqttAndroidClient mqttAndroidClient;
private static String mqttUsername = ""; //服务端创建的用户名
private static String mqttPassword = ""; //服务端吧创建的用户名密码
private static String clientId = ""; //唯一标识不可重复
 //接受消息的队列
public static final LinkedBlockingQueue<MyMessage> SERVER_QUEUE = new LinkedBlockingQueue<>(
            200);

//消息订阅的topic,可以自定义
private static final String topic = "/" + mqttUsername + "/" + clientId + "/user/get"; 


public static void initIot() {

        String serverUrl = "服务器地址:端口";

        try {
            mqttAndroidClient = new MqttAndroidClient(context, serverUrl, "clientId");

            mqttAndroidClient.setCallback(new MqttCallback() {
                @Override
                public void connectionLost(Throwable cause) {
                    Log.i(TAG, "连接断开");
                }

                @Override
                public void messageArrived(String topic, MqttMessage message) throws Exception {
                    Log.i(TAG, "收到消息:" + message.toString());

                    //建议使用队列接收
                    MyMessage myMessage = new MyMessage();
                    myMessage.setData(message.getPayload());
                    boolean offer = SERVER_QUEUE.offer(aMessage);
                    if (!offer) {
                        Log.e(TAG, "队列已满,无法接受消息!");
                    }
                }

                @Override
                public void deliveryComplete(IMqttDeliveryToken token) {
                    Log.i(TAG, "deliveryComplete: " + token.toString());

                }
            });

            //建立连接规则
            MqttConnectOptions options = new MqttConnectOptions();
            options.setUserName(mqttUsername);
            options.setPassword(mqttPassword.toCharArray());
            options.setCleanSession(true);
            options.setMqttVersion(MqttConnectOptions.MQTT_VERSION_3_1_1); //MQTT版本
            options.setConnectionTimeout(10); //连接超时时间
            options.setKeepAliveInterval(180); //心跳间隔时间
            options.setMaxInflight(100); //最大请求数,默认10,高流量场景可以增大该值
            options.setAutomaticReconnect(true); //设置自动重新连接

            mqttAndroidClient.connect(options, null, new IMqttActionListener() {
                @Override
                public void onSuccess(IMqttToken asyncActionToken) {
                    Log.i(TAG, "连接成功");
                    //这里订阅消息
                    subscribe();
                }

                @Override
                public void onFailure(IMqttToken asyncActionToken, Throwable exception) {
                    Log.i(TAG, "连接失败" + exception);
                }
            });
        } catch (Exception e) {
            Log.e(TAG, "INIT IOT ERROR!");
        }
    }

public class MyMessage {
    
    public Object data;
    
    public MyMessage() {
    }

    public MyMessage(Object data) {
        this.data = data;
    }
    
    public Object getData() {
        return this.data;
    }
    
    public void setData(Object data) {
        this.data = data;
    }
}

4. 뉴스 구독

private static void subscribe() {
        try {
            mqttAndroidClient.subscribe(topic, 1, null,
                    new IMqttActionListener() {
                        @Override
                        public void onSuccess(IMqttToken asyncActionToken) {
                            Log.i(TAG,
                                    "订阅成功 topic: "
                                            + topic);
                        }

                        @Override
                        public void onFailure(IMqttToken asyncActionToken,
                                              Throwable exception) {
                            Log.e(TAG, "订阅失败!" + exception.getMessage());
                        }
                    });

        } catch (Exception e) {
            Log.e(TAG, "订阅失败!" + e.getMessage());
        }
    }

5. 메시지 게시

//消息发送队列
public static final LinkedBlockingQueue<String> CLIENT_QUEUE = new LinkedBlockingQueue<>(1000);

//发布消息调用这个方法
public static void putQueue(String msg) {
        boolean offer = CLIENT_QUEUE.offer(msg);
        if (!offer) {
            Log.w(TAG, "操作队列已满!");
        }
    }

//使用线程去读取队列,这样可以防止同一时间多处调用,同时也不会让发送事件丢失
static class IotPublishRunnable implements Runnable {

        @Override
        public void run() {
            while (true) {
                try {
                    String msg = CLIENT_QUEUE.take();
                    if (TextUtils.isEmpty(msg)) {
                        continue;
                    }
                    publish(msg);
                    Thread.sleep(300);
                } catch (Exception e) {
                    Log.e(TAG, "处理iot消息失败");
                }

            }
        }
    }

private static void publishNew(String payload) {
        String topic = "/" + mqttUsername + "/" + clientId + "/user/update";
        Integer qos = 1;

        try {
            if (null == mqttAndroidClient || !mqttAndroidClient.isConnected()) {
                Log.w(TAG, "IOT还未初始化!无法发送消息");
                return;
            }
            mqttAndroidClient.publish(topic, payload.getBytes(StandardCharsets.UTF_8), qos, false,
                    null, new IMqttActionListener() {
                        @Override
                        public void onSuccess(IMqttToken asyncActionToken) {

                        }

                        @Override
                        public void onFailure(IMqttToken asyncActionToken, Throwable exception) {
                            String[] topics = asyncActionToken.getTopics();
                            Log.e(TAG, "publish message error! topics: " + Arrays.toString(topics));
                        }
                    });
        } catch (MqttException e) {
            Log.e(TAG, "发送消息失败!");
        } catch (IllegalArgumentException e) {
            Log.e(TAG, "MQTT CLIENT ERROR");
        }
    }

6. 연결 해제

public static void disconnect() {
        if (null == mqttAndroidClient || !mqttAndroidClient.isConnected()) {
            Log.w(TAG, "IOT还未初始化!");
            return;
        }

        try {
            mqttAndroidClient.disconnect().setActionCallback(new IMqttActionListener() {
                @Override
                public void onSuccess(IMqttToken asyncActionToken) {
                    Log.i(TAG, "断开连接成功!");
                }

                @Override
                public void onFailure(IMqttToken asyncActionToken, Throwable exception) {
                    Log.i(TAG, "断开连接失败!");
                }
            });
        } catch (MqttException e) {
            Log.e(TAG, e.getMessage());
        }
    }

위는 클라이언트의 MQTT 코드입니다.저는 Java로 작성했습니다.Kotlin 버전의 경우 Android에서 Kotlin을 사용하여 MQTT에 연결하는 방법을 참조하십시오 .코드는 기본적으로 여기에 있으며 프로젝트는 공개되지 않습니다.

Supongo que te gusta

Origin juejin.im/post/7239715394369847352
Recomendado
Clasificación