最近项目中有一个需求,要用mqtt协议接收路侧设备的数据到云平台上,所以,研究了一下mqtt客户端的制作方法。
mqtt协议是一个发布订阅模式的协议。
这篇文章主要记录下我搭建mqttbroker和写mqtt客户端的过程,是记录,不是教程,无意教程。
一、下载安装emqx
emqx是一个mqtt的broker软件,这个软件是比较好用的一个broker软件,以前用过mosquitto软件做mqtt的broker,但是mosquitto没有emqx易用,所以就放弃了。
从emqx的官网上下载得到emqx-4.4.1-otp24.1.5-3-el7-amd64.zip,unzip解压出来一个emqx的文件夹。
进入到emqx/bin下执行 emqx start,就将emqx启动起来了。
[root@localhost bin]# ./emqx start
WARNING: There seem to be missing dynamic libs from the OS. Using libs from /root/emqx/dynlibs
EMQ X Broker 4.4.1 is started successfully!
[root@localhost bin]#
查看emqx的运行状态用bin下的emqx_ctl命令。
[root@localhost bin]# ./emqx_ctl status
Node 'emqx@127.0.0.1' 4.4.1 is started
[root@localhost bin]#
经过以上的下载、解压、启动、查看状态四个步骤,就将emqx软件正常运行起来了。
二、mqtt客户端的编写
编写mqtt客户端,是需要eclips的paho库的,这个库是一个mqtt客户端的编程接口库。
在基于maven的java项目中,要增加一个dependency。
<dependency>
<groupId>org.eclipse.paho</groupId>
<artifactId>org.eclipse.paho.client.mqttv3</artifactId>
<version>1.2.2</version>
</dependency>
接下来就是写client的代码了。
下面的代码中有发送消息的代码,也有接收消息的代码,接收消息的代码就是那个OnMessageCallback,有了这个Callback类就可以接收mqtt消息了。
import org.eclipse.paho.client.mqttv3.MqttClient;
import org.eclipse.paho.client.mqttv3.MqttConnectOptions;
import org.eclipse.paho.client.mqttv3.MqttException;
import org.eclipse.paho.client.mqttv3.MqttMessage;
import org.eclipse.paho.client.mqttv3.persist.MemoryPersistence;
import java.nio.charset.StandardCharsets;
public class App {
public static void main(String[] args) {
String subTopic = "testtopic/#";
String pubTopic = "testtopic/1";
String content = "哈哈哈,我又来了。";
int qos = 2;
String broker = "tcp://123.56.182.37:1883"; //这里是broker的地址
String clientId = "emqx_test";
MemoryPersistence persistence = new MemoryPersistence();
try {
MqttClient client = new MqttClient(broker, clientId, persistence);
// MQTT 连接选项
MqttConnectOptions connOpts = new MqttConnectOptions();
connOpts.setUserName("emqx_test");
connOpts.setPassword("emqx_test_password".toCharArray());
// 保留会话
connOpts.setCleanSession(true);
// 设置回调,这个回调类是用来接收mqtt消息的,如果只是想要发布mqtt消息,那么就不需要这个回调了。
// 当然,如果只是想接收mqtt消息,不想发送,那么就只设置这个回调,下面的发送代码也就不需要了
client.setCallback(new OnMessageCallback());
// 建立连接
System.out.println("Connecting to broker: " + broker);
client.connect(connOpts);
System.out.println("Connected");
System.out.println("Publishing message: " + content);
// 订阅
client.subscribe(subTopic);
// 消息发布所需参数
long i = 0;
while (i < 10e10) {
MqttMessage message = new MqttMessage(content.getBytes(StandardCharsets.UTF_8));
message.setQos(qos);
client.publish(pubTopic, message);
Thread.sleep(10000);
i++;
System.out.println("Message published, i = " + i);
}
client.disconnect();
System.out.println("Disconnected");
client.close();
System.exit(0);
} catch (MqttException me) {
System.out.println("reason " + me.getReasonCode());
System.out.println("msg " + me.getMessage());
System.out.println("loc " + me.getLocalizedMessage());
System.out.println("cause " + me.getCause());
System.out.println("excep " + me);
me.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
import org.eclipse.paho.client.mqttv3.IMqttDeliveryToken;
import org.eclipse.paho.client.mqttv3.MqttCallback;
import org.eclipse.paho.client.mqttv3.MqttMessage;
public class OnMessageCallback implements MqttCallback {
public void connectionLost(Throwable cause) {
// 连接丢失后,一般在这里面进行重连
System.out.println("连接断开,可以做重连");
}
public void messageArrived(String topic, MqttMessage message) throws Exception {
// subscribe后得到的消息会执行到这里面
System.out.println("接收消息主题:" + topic);
System.out.println("接收消息Qos:" + message.getQos());
System.out.println("接收消息内容:" + new String(message.getPayload(), "utf-8"));
}
public void deliveryComplete(IMqttDeliveryToken token) {
System.out.println("deliveryComplete---------" + token.isComplete());
}
}
以上两步就可以完成一个具备基本功能的mqtt协议客户端了,这个客户端既可以发布消息,也可以接收消息。当然,如果只想要一个方面的功能,也可以适当裁剪以适应自己的需要。
参考资料:
1、https://www.emqx.io/docs/zh/v4.4/getting-started/install.html