部署安装
- 从官网中下载对应版本的emq服务器,对于linux下的部署安装在官方文档中有着资料。
- 下载完成后需进行安装。以下是安装启动步骤(此为在windows下的操作)
2.1 emq代理服务器下的安装

2.2 emq服务器的启动/关闭、及查看

2.3 控制台
控制台地址: http://127.0.0.1:18083,默认用户: admin,密码:public

搭建MQTT客户端(java)
1. 下载MQTT客户端库
MQTT客户端库:https://www.eclipse.org/paho/clients/java/
2.配置MQTT属性
定义mqtt配置属性类:
@Component
@Data
public class Wx2MqttConfig {
@Value("${mqtt.host}")
private String host;
@Value("${mqtt.port}")
private String port;
@Value("${mqtt.username}")
private String username;
@Value("${mqtt.clientId}")
private String clientId;
@Value("${mqtt.password}")
private String password;
}
3. 定义主题类
public class Topic {
//用来分路由处理的:
public static final String DEVICE_ACK_BIND = "device/+/ack/bind";
public static final String DEVICE_ACK_UNBIND = "device/+/ack/unbind";
public static final String DEVICE_ACK_GET = "device/+/ack/get";
public static final String DEVICE_ACK_SET = "device/+/ack/set";
public static final String DEVICE_NOTIFY = "device/+/notify";
//用来publish的(绑定/解绑 & 设置/获取)
public static final String SERVER_BIND_PREFIX = "server/bind/";
public static final String SERVER_UNBIND_PREFIX = "server/unbind/";
public static final String SERVER_SET_PREFIX = "server/set/";
public static final String SERVER_GET_PREFIX = "server/get/";
public static final int[] QOS = {2,2,2,2,2}; //定义消息级别
public static final String[] TOPICS = {
DEVICE_ACK_BIND,
DEVICE_ACK_UNBIND,
DEVICE_ACK_GET,
DEVICE_ACK_SET,
DEVICE_NOTIFY
};
}
4. 实现MqttCallback,实现发布/订阅方法
@Service
public class Wx2MqttService implements MqttCallback {
private final Logger logger = LoggerFactory.getLogger(this.getClass());
private MqttClient client;
@Autowired
private Wx2MqttConfig wx2MqttConfig;
@PostConstruct
public void init(){
logger.info("初始化Wx2MqttService");
//TODO 分出支持tls格式的config。
try {
client = new MqttClient(wx2MqttConfig.getHost() + ":" + wx2MqttConfig.getPort(), wx2MqttConfig.getClientId(), new MemoryPersistence());
reConnect();
} catch (MqttException e) {
e.printStackTrace();
logger.error(e.toString());
}
}
public void reConnect() {
try {
connect();
subscribe();
client.setCallback(this);
} catch (MqttException e) {
e.printStackTrace();
}
}
private void connect() throws MqttException{
//阻塞在此直到连上或超时没连上
logger.info("阻塞在此直到连上或超时没连上");
client.connect(getConnectOptions());
logger.info("阻塞完毕:Connected=" + client.isConnected());
}
private MqttConnectOptions connectOptions = null;
private MqttConnectOptions getConnectOptions() {
if (connectOptions == null) {
connectOptions = new MqttConnectOptions();
connectOptions.setCleanSession(false);
connectOptions.setAutomaticReconnect(true);
connectOptions.setUserName(wx2MqttConfig.getUsername());
connectOptions.setPassword(wx2MqttConfig.getPassword().toCharArray());
// 设置超时时间 TODO 这两个参数设入properties中
connectOptions.setConnectionTimeout(10);
// 设置会话心跳时间
connectOptions.setKeepAliveInterval(20);
}
return connectOptions;
}
//订阅消息(默认主题)
private void subscribe() throws MqttException {
logger.info("初始化订阅消息");
client.subscribe(Topic.TOPICS,Topic.QOS);
}
//订阅特定主题
public void subscribe(String topic) throws MqttException {
logger.info("订阅"+topic+"消息");
this.subscribe(topic,0);
}
//订阅特定主题,附加消息级别
public void subscribe(String topic, int qos) throws MqttException {
logger.info("订阅"+topic+"消息,消息级别为:"+qos);
client.subscribe(topic,qos);
}
//发布消息
public boolean publish(String topic,String message){
MqttMessage mqttMessage = new MqttMessage();
mqttMessage.setQos(2);
mqttMessage.setRetained(true);
mqttMessage.setPayload(message.getBytes());
return this.publish(topic,mqttMessage);
}
public boolean publish(String topic, MqttMessage mqttMessage) {
logger.info("准备publish的topic:" + topic);
logger.info("准备publish的mqttMsg:" + new String(mqttMessage.getPayload()));
if (client == null || !client.isConnected()) {
reConnect();
logger.error("Wx2MqttService未连接上,无法publish");
return false;
}
try {
MqttTopic mqttTopic = client.getTopic(topic);
MqttDeliveryToken token = mqttTopic.publish(mqttMessage);
token.waitForCompletion();
} catch (MqttException e) {
e.printStackTrace();
return false;
}
return true;
}
// 连接丢失后,一般在这里面进行重连
@Override
public void connectionLost(Throwable throwable) {
// TODO - 多次重连不行时发短信等方式通知维护人员(标-的TODO当前并不优先考虑实现)
logger.info("连接断开");
logger.info("连接断开,正在重连");
reConnect();
}
//publish后会执行到这里
@Override
public void deliveryComplete(IMqttDeliveryToken iMqttDeliveryToken) {
logger.info("publish后的deliveryComplete:" + iMqttDeliveryToken.isComplete() + "");
}
//TODO subscribe后得到的消息会执行到这里面
@Override
public void messageArrived(String topic, MqttMessage mqttMessage) throws Exception {
logger.info("\n 【接收到mqtt消息】:[topic=[{}],qos=[{}] mqttMessage=[{}]", topic,mqttMessage.getQos(), mqttMessage);
if (StringUtils.isEmpty(topic)) {
return;
}
String json = new String(mqttMessage.getPayload());
//根据主题及订阅到的数据进行判断,选择对应的操作。。。
}
public WeixinService getWxService(){
return wxService;
}
}
这里用了@PostConstruct,目的在于启动时即能打开客户端与emq服务器的通信,同时也能将客户端进行订阅主题和相应的消息级别。
备注
- 如果需要测试的话,可以下载mqttfx进行MQTT协议调试。下载链接:http://www.jensd.de/apps/mqttfx/1.1.0/
- mqtt协议基于主题(topic)进行发布/订阅,以实现开发者云平台与硬件的通信。其主要在于两边都连接上同一个EMQ代理服务器,EMQ服务器根据MQTT协议中的要求来控制数据的流动。而这里需要注意的概念是,A客户端中的发布主题即是B客户端的订阅主题,相反也是如此。MQTT协议的通信,有点儿类似于socket通信(即是tcp协议通信),它们的类似在于通信是双端的,不同在于mqtt可以定义消息级别来保证消息的传递。
本文档介绍了如何部署安装EMQ MQTT服务器,并详细阐述了在Java环境下搭建MQTT客户端的步骤,包括下载客户端库,配置MQTT属性,定义主题类以及实现MqttCallback接口。此外,还提供了MQTTFX作为测试工具的下载链接,帮助理解MQTT协议基于主题的发布/订阅机制。
1612

被折叠的 条评论
为什么被折叠?



