머리말
MQTT가 왜 스마트하드웨어의 첫 번째 선택인지 이전에 글을 썼는데 - Nuggets 이번에는 나만의 MQTT 인터랙티브 플랫폼을 구축하고 실전에서 체험해보겠다.
1. 서버 준비
1. 플랫폼 선택
여기서 사용하는 플랫폼은 EMQX Cloud 입니다 . github 계정을 통해 무료로 MQTT 서버를 신청할 수 있습니다. 개인용으로 매우 편리합니다. 동시에 MQTT 클라이언트를 사용하여 MQTT 서비스를 빠르게 테스트하여 모니터링하거나 시뮬레이션합니다. 여기에서 무료로 열기를 선택합니다. 지금 배포를 클릭하고 끝까지 동의하면 완료됩니다.
2. 서비스 시작
설정 후 프로젝트 관리를 클릭하면 방금 신청한 서버가 있을 것이고 입력 후 시작을 클릭하면 서비스를 시작할 수 있습니다.
3. 사용자 생성
인증을 클릭하고 인증을 선택한 다음 오른쪽에 있는 추가를 클릭하여 연결 사용자를 생성합니다.사용자 이름과 암호는 연결을 설정할 때 클라이언트가 필요로 하는 사용자 이름과 암호입니다. 지금까지 연결 코드를 작성하기 위해 클라이언트로 이동할 수 있습니다.
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에 연결하는 방법을 참조하십시오 .코드는 기본적으로 여기에 있으며 프로젝트는 공개되지 않습니다.