EMQTT使用随笔

EMQTT使用随笔

    • 服务器配置与准备工作
    • 部署EMQTT
    • 登录WEB 管理后台---配置MQTT服务参数
    • 编码实现[java]
        • 导入依赖
            • 相关MQTT参数使用参考: [MQTT学习笔记](https://blog.csdn.net/uaime/article/details/96424908)
            • 至于具体的EMQTT服务器的参数配置:[EMQ官方文档](https://www.emqx.io/cn/)

服务器配置与准备工作

由于emqttd是用Erlang语言编写的,所以,在Linux下安装时,需要先安装Erlang。
安装-配置命令如下:
一、安装依赖库
sudo yum -y install make gcc gcc-c++ kernel-devel m4 ncurses-devel openssl-devel
二、获取源码包
wget http://www.erlang.org/download/otp_src_R13B04.tar.gz
三、解压、编译、安装
tar xfvz otp_src_R13B04.tar.gz
cd otp_src_R13B04/
./configure --with-ssl
sudo make install
此时配置EMQTT的环境已搭建好

部署EMQTT

一、下载EMQTT安装包

【各版本下载地址:https://www.emqx.io/downloads/broker/?osType=Linux,我所使用的是3.2.3版】

由于服务器是Linux所以下载的Linux通用安装包: 

https://www.emqx.io/downloads/broker/v3.2.3/emqx-centos6-v3.2.3.zip

然后将下载的zip文件解压,并放到服务器下【我的:opt/emqx】

二、调用命令启动EMQTT
cd /opt/emqx/bin
./emqx console
提示若没有权限,逐级获取权限【命令 chmod u+x * 我是获取了三次不同目录的权限】
直到调用 ./emqx console 命令有以下提示
EMQTT使用随笔_第1张图片
Ctrl + C 退出 并调用 ./emqx start 启动 MQTT服务 有以下提示标识启动成功
在这里插入图片描述
ps -ef|grep emqx 可以查看当前的 emqtt服务

登录WEB 管理后台—配置MQTT服务参数

地址: http://localhost:18083 ,缺省用户名/密码: admin/public
EMQTT使用随笔_第2张图片
设置语言为中文
EMQTT使用随笔_第3张图片
设置用户名 与 密码【重要】
EMQTT使用随笔_第4张图片

编码实现[java]

导入依赖


    
        org.eclipse.paho
        org.eclipse.paho.client.mqttv3
        1.2.0
    

/**
 * MQTT静态参数常量类
 */
public class MqttConstant {

    //MQTT 服务器基础配置
    /**
     * MQTT服务器IP、端口  
     */
    public final static String MQTT_IP_PORT = "tcp://test:1883";
    /**
     * MQTT服务器登录 用户名  elinker
     */
    public final static String MQTT_USERNAME = "username";
    /**
     * MQTT服务器登录 密码
     */
    public final static String MQTT_PASSWORD = "password";
    /**
     * MQTT客户端【应用程序】   ID【自定义】
     */
    public final static String MQTT_CLIENTID = "pubClient";
    /**
     * MQTT客户端【应用程序】  订阅主题【自定义】
     */
    public final static String MQTT_TOPIC = "web/pubClient";



   //消息发送的类型
    /**
     *  尽力而为。消息发送者会想尽办法发送消息,但是遇到意外并不会重试
     */
    public final static int QOS_UNRELIABLE = 0;
    /**
     *  至少一次。消息接收者如果没有知会或者知会本身丢失,消息发送者会再次发送以保证消息接收者至少会收到一次,当然可能造成重复消息。
     */
    public final static int QOS_REPEAT = 1;
    /**
     *  恰好一次。保证这种语义肯待会减少并发或者增加延时,不过丢失或者重复消息是不可接受的时候,级别2是最合适的。
     */
    public final static int QOS_JUST = 2;

}
/**
 * 服务器【应用程序】Mqtt消息推送工具类
 */
public class MqttPushUtil {

    public static Logger logger = Logger.getLogger(MqttPushUtil.class);

    public static MqttClient mqttClient;

    public static MqttConnectOptions mqttConnectOptions;

    static {
        try{
            //创建客户端
            mqttClient = new MqttClient(MqttConstant.MQTT_IP_PORT, MqttConstant.MQTT_CLIENTID, new MemoryPersistence());
            //创建链接参数
            mqttConnectOptions = new MqttConnectOptions();
            //在客户端断开连接时是否缓存 订阅消息
            mqttConnectOptions.setCleanSession(true);
            //设置连接的用户名
            mqttConnectOptions.setUserName(MqttConstant.MQTT_USERNAME);
            //设置连接的密码
            mqttConnectOptions.setPassword(MqttConstant.MQTT_PASSWORD.toCharArray());
            //开启自动重连
            mqttConnectOptions.setAutomaticReconnect(true);
            //设置超时时间  单位为秒
            mqttConnectOptions.setConnectionTimeout(30);
            //设置会话心跳时间  单位为秒 服务器会每隔1.5*20秒的时间向客户端发送个消息判断客户端是否在线,但这个方法并没有重连的机制
            mqttConnectOptions.setKeepAliveInterval(20);

//            MqttPushServerUtil.setClient(mqttClient);


            mqttClient.connect(mqttConnectOptions);
        }catch (Exception e){
            e.printStackTrace();
            logger.error("连接MQTT服务器发生异常", e);
            try{
                mqttClient.disconnect();;
                mqttClient.close();
            }catch (MqttException el){
                e.printStackTrace();
                logger.error("连接异常时-----》断开与MQTT服务器连接操作发生异常", el);
            }
        }
    }

    public static void receiveSubscription(){
       try{
           mqttClient.setCallback(new MqttCallback() {
               /**
                *检测到断开连接
                * @param throwable
                */
               @Override
               public void connectionLost(Throwable throwable) {
                   //MQTT客户端断线重连
                   reconnection();
               }

               /**
                * 接收订阅消息处理
                * @param topic
                * @param mqttMessage
                * @throws Exception
                */
               @Override
               public void messageArrived(String topic, MqttMessage mqttMessage) throws Exception {
                   System.out.println("topic:"+topic);
                   System.out.println("Qos:"+mqttMessage.getQos());
                   System.out.println("message content:"+new String(mqttMessage.getPayload()));
               }

               /**
                * 消息发布结果
                * @param iMqttDeliveryToken
                */
               @Override
               public void deliveryComplete(IMqttDeliveryToken iMqttDeliveryToken) {
                   logger.info("MQTT消息发布的结果:---------"+ iMqttDeliveryToken.isComplete());
               }
           });

           mqttClient.subscribe(MqttConstant.MQTT_TOPIC, MqttConstant.QOS_JUST);
       }catch (Exception e){
           e.printStackTrace();
           logger.error("MQTT客户端---公租房系统:接收消息时发生异常!", e);
       }
    }

    /**
     * MQTT客户端断线重连
     */
    public static void reconnection(){
        logger.error("与MQTT服务器断开连接,尝试重新连接!");
        try {
            if(!mqttConnectOptions.isAutomaticReconnect()){
                mqttClient.reconnect();
            }
        }catch (MqttException e){
            logger.error("MQTT重新连接发生异常!", e);
        }
    }

    /**
     * 发布非可靠的消息【消息服务质量:0】
     * @param topic   发布主题
     * @param pushMessage  消息内容
     */
    public static boolean publishUnreliable(String topic, String pushMessage) {
        return publish(MqttConstant.QOS_UNRELIABLE, topic, pushMessage);
    }

    /**
     * 以至少收到一次的模式发送消息【可能重复,消息服务质量:1】
     * @param topic  发布主题
     * @param pushMessage  消息内容
     */
    public static boolean publishLeastOnce(String topic, String pushMessage) {
        return publish(MqttConstant.QOS_REPEAT, topic, pushMessage);
    }

    /**
     * 发送可靠的保证 能且只能收到一次的消息【消息服务质量:2】
     * @param topic
     * @param pushMessage
     */
    public static boolean publishReliable(String topic, String pushMessage) {
        return publish(MqttConstant.QOS_JUST, topic, pushMessage);
    }

    /**
     * 发布主题和消息队列
     * @param qos
     * @param topic
     * @param pushMessage
     * @return
     */
    public static boolean publish(int qos, String topic, String pushMessage) {
        try {
            // 创建消息
            MqttMessage message = new MqttMessage(pushMessage.getBytes());
            // 设置消息的服务质量
            message.setQos(qos);
            // 发布消息
            mqttClient.publish(topic, message);

        } catch (MqttException e) {
            logger.error("发布消息时发生异常!",e);
            return false;
        }
        return true;
    }
}
/**
* 测试类
*/
public class MqttPushClientUtil {


    public static void main(String[] args) throws MqttException {
        String HOST = MqttConstant.MQTT_IP_PORT;
        String[] TOPIC = {"dev/mac/0000a4010101", "dev/village/123"};
        int[] qos = new int[]{2, 2};
        String clientid = "subClient";
        String userName = "username";
        String passWord = "password";
        try {
            // host为主机名,subClient为clientid即连接MQTT的客户端ID,一般以客户端唯一标识符表示,MemoryPersistence设置clientid的保存形式,默认为以内存保存
            MqttClient client = new MqttClient(HOST, clientid, new MemoryPersistence());
            // MQTT的连接设置
            MqttConnectOptions options = new MqttConnectOptions();
            // 设置是否清空session,这里如果设置为false表示服务器会保留客户端的连接记录,这里设置为true表示每次连接到服务器都以新的身份连接
            options.setCleanSession(true);
            // 设置连接的用户名
            options.setUserName(userName);
            // 设置连接的密码
            options.setPassword(passWord.toCharArray());
            // 设置超时时间 单位为秒
            options.setConnectionTimeout(10);
            // 设置会话心跳时间 单位为秒 服务器会每隔1.5*20秒的时间向客户端发送个消息判断客户端是否在线,但这个方法并没有重连的机制
            options.setKeepAliveInterval(20);
            // 设置回调函数
            client.setCallback(new MqttCallback() {

                @Override
                public void connectionLost(Throwable cause) {
                    System.out.println("connectionLost");
                }

                @Override
                public void messageArrived(String topic, MqttMessage message) throws Exception {
                    System.out.println("topic:"+topic);
                    System.out.println("Qos:"+message.getQos());
                    System.out.println("message content:"+new String(message.getPayload()));

                }

                @Override
                public void deliveryComplete(IMqttDeliveryToken token) {
                    System.out.println("deliveryComplete---------"+ token.isComplete());
                }

            });
            client.connect(options);
            //订阅消息
            client.subscribe(TOPIC, qos);
        } catch (Exception e) {
            e.printStackTrace();
        }


        Map<String, Object> map = new HashMap<>();
        map.put("index", 1);
        map.put("text", "设备信息");
        MqqtPushServiceUtil.pushDeviceMsg("00:00:a4:01:01:01", "12", map);
        try{
            Thread.sleep(5000);
        }catch (Exception e){
            e.printStackTrace();
        }

        map.put("index", 2);
        map.put("text", "小区信息");
        MqqtPushServiceUtil.pushVillageMsg(123, "12", map);
    }

}

import com.alibaba.fastjson.JSONObject;
import com.framework.common.mqtt.MqttPushUtil;
import com.framework.common.utils.StringUtil;

import java.util.HashMap;
import java.util.Map;

/**
 * MQTT消息推送业务工具类
 */
public class MqttPushServiceUtil {

   //
   //主要用来参考  具体规则与接受端约定
   //MqttPushConstant.VILLAGE_PUSH_TOPIC+villageId 指约定订阅的标题    map.toString()  json格式的字符串
/*---------------------------------------------------------------------------------------------------------------------------------------*/
    /**
     * 推送设备消息
     * @param mac
     * @param type
     * @return
     */
    public static boolean pushDeviceMsg(String mac, String type){
        if(StringUtil.isBlank(mac)){
            return false;
        }
        Map map = new JSONObject();
        map.put("type", type);
        return MqttPushUtil.publishLeastOnce(MqttPushConstant.DEVICE_PUSH_TOPIC+mac.replace(":", ""), map.toString());
    }

    /**
     * 推送设备消息
     * @param mac 设备mac
     * @param type  消息类型【自定义】
     * @param pubshMsg  消息内容
     * @return
     */
    public static boolean pushDeviceMsg(String mac, String type, Map pubshMsg){
        if(StringUtil.isBlank(mac)){
            return false;
        }
        Map map = new JSONObject();
        map.put("type", type);
        map.put("msg", new JSONObject(pubshMsg).toJSONString());
        return MqttPushUtil.publishReliable(MqttPushConstant.DEVICE_PUSH_TOPIC+mac.replace(":", ""), map.toString());
    }

    /**
     * 推送小区消息
     * @param villageId  小区ID
     * @param type  消息类型【自定义】
     * @param pubshMsg  消息内容
     * @return
     */
    public static boolean pushVillageMsg(int villageId, String type, Map pubshMsg){
        if(villageId <= 0){
            return false;
        }
        Map map = new JSONObject();
        map.put("type", type);
        map.put("msg", new JSONObject(pubshMsg).toJSONString());
        return MqttPushUtil.publishReliable(MqttPushConstant.VILLAGE_PUSH_TOPIC+villageId, map.toString());
    }

}
相关MQTT参数使用参考: MQTT学习笔记
至于具体的EMQTT服务器的参数配置:EMQ官方文档

你可能感兴趣的:(java)