mqtt emqx 上下线监听

一、业务场景

好多朋友在咨询如何得知(监测)MQTT客户端状态(在线、离线),或者可以说是监测采集器状态。

其实这个在MQTT协议中已经给出系统主题,MQTT服务端可以知道客户端的任何情况,比如:什么时候上线和下线。

二、解决方案

$SYS/brokers/${node}/clients/${clientid}/connected:上线事件。当某客户端上线时,会向该主题(Topic)发布消息

 $SYS/brokers/${node}/clients/${clientid}/disconnected:掉线事件。当某客户端掉线时,会向该主题(Topic)发布消息

当然在开发的时候我们订阅两个主题比较麻烦,在这里我们可以采用主题通配符模式直接订阅一个主题即可:

$SYS/brokers/+/clients/#

 private void initMonitor() {
        String subTopic = "$SYS/brokers/+/clients/#";
        String clientId = "monitor_mqtt_emqx"+new Date().getTime();
        MemoryPersistence persistence = new MemoryPersistence();

        try {
            MqttClient client = new MqttClient(broker, clientId, persistence);

            // MQTT 连接选项
            MqttConnectOptions connOpts = new MqttConnectOptions();
            connOpts.setUserName("admin");
            connOpts.setPassword("123456".toCharArray());
            // 保留会话
            //connOpts.setCleanSession(true);
            //设置重连
            connOpts.setAutomaticReconnect(true);

            // 设置回调
            client.setCallback(new OnMonitorCallback());

            // 建立连接
            System.out.println("monitor_Connecting to broker: " + broker);
            client.connect(connOpts);

            System.out.println("monitor_Connected");
            //System.out.println("Publishing message: " + content);

            // 订阅
            client.subscribe(subTopic);
        } catch (MqttException me) {
            System.out.println("monitor_reason " + me.getReasonCode());
            System.out.println("monitor_msg " + me.getMessage());
            System.out.println("monitor_loc " + me.getLocalizedMessage());
            System.out.println("monitor_cause " + me.getCause());
            System.out.println("monitor_excep " + me);
            me.printStackTrace();
        }
    }

public class OnMonitorCallback implements MqttCallback {
    public void connectionLost(Throwable cause) {
        // 连接丢失后,一般在这里面进行重连
        System.out.println("连接断开,可以做重连");
    }

    public void messageArrived(String topic, MqttMessage message) throws Exception {
         String msg = new String(message.getPayload());
         try {
             
             String result = new String(message.getPayload());
             Map<String, String> resultMap2 = JsonUtil.jsonToMap(result);
             
             String clientId = String.valueOf(resultMap2.get("clientid"));
             if (topic.endsWith("disconnected")) {
                 System.out.println("客户端已掉线:"+clientId);
             } else {
                 System.out.println("客户端已上线:"+clientId);
             }
         } catch (JSONException e) {
             System.out.println("monitor_JSON Format Parsing Exception : "+msg);
         }
    }

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

三、修改配置文件

修改etc/acl.conf 如果担心其他人非法获取离线消息,可以设置订阅权限
设置allow所有用户订阅$SYS/brokers/+/clients/#主题
 

{allow, {user, "dashboard"}, subscribe, ["$SYS/#"]}.

{allow, {ipaddr, "127.0.0.1"}, pubsub, ["$SYS/#", "#"]}.

{allow, all, subscribe, ["$SYS/brokers/+/clients/#"]}.

{deny, all, subscribe, ["$SYS/#", {eq, "#"}]}.

{allow, all}.

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,下面是Spring Boot整合MQTT EMQX的代码过程: 1. 首先,在pom.xml文件中添加下面的依赖: ``` <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-integration</artifactId> </dependency> <dependency> <groupId>org.springframework.integration</groupId> <artifactId>spring-integration-mqtt</artifactId> <version>5.2.5.RELEASE</version> </dependency> </dependencies> ``` 2. 在application.properties文件中添加EMQX的连接信息: ``` spring.mqtt.username=your_username spring.mqtt.password=your_password spring.mqtt.url=tcp://your_emqx_ip:1883 ``` 3. 创建一个MQTT消息的处理器,代码如下: ``` @Component public class MqttMessageHandler { @ServiceActivator(inputChannel = "mqttInputChannel") public void handleMessage(String message) { System.out.println("Received message: " + message); } } ``` 4. 创建一个MQTT连接的配置类,代码如下: ``` @Configuration @EnableIntegration public class MqttConfig { @Value("${spring.mqtt.username}") private String username; @Value("${spring.mqtt.password}") private String password; @Value("${spring.mqtt.url}") private String url; @Bean public DefaultMqttPahoClientFactory mqttClientFactory() { DefaultMqttPahoClientFactory factory = new DefaultMqttPahoClientFactory(); MqttConnectOptions options = new MqttConnectOptions(); options.setUserName(username); options.setPassword(password.toCharArray()); factory.setConnectionOptions(options); return factory; } @Bean public IntegrationFlow mqttInFlow() { return IntegrationFlows.from( inboundAdapter(), c -> c.poller(Pollers.fixedDelay(1000)) ) .transform(p -> p) .handle("mqttMessageHandler", "handleMessage") .get(); } private MessageProducerSupport inboundAdapter() { MqttPahoMessageDrivenChannelAdapter adapter = new MqttPahoMessageDrivenChannelAdapter(url, "testClient", mqttClientFactory(), "testTopic"); adapter.setCompletionTimeout(5000); adapter.setConverter(new DefaultPahoMessageConverter()); adapter.setQos(1); return adapter; } } ``` 5. 测试代码: ``` @RestController public class TestController { @Autowired private MessageChannel mqttInputChannel; @GetMapping("/send") public void sendMqttMessage() { mqttInputChannel.send(MessageBuilder.withPayload("Hello MQTT").build()); } } ``` 6. 运行Spring Boot应用程序,访问http://localhost:8080/send,可以在控制台上看到接收到的MQTT消息。 注意:在运行代码之前,请确保你已经安装并运行了EMQX,并且已经创建了一个名为“testTopic”的主题。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值