mqtt的使用

案例一、

  <!-- mqtt -->
        <dependency>
            <groupId>org.springframework.integration</groupId>
            <artifactId>spring-integration-stream</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.integration</groupId>
            <artifactId>spring-integration-mqtt</artifactId>
        </dependency>

mqtt:
  enabled: true
  host: tcp://localhost:1883
  username: admin
  pwd: admin
package com.zhk.study.mqtt;

import org.eclipse.paho.client.mqttv3.MqttConnectOptions;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.integration.mqtt.core.DefaultMqttPahoClientFactory;
import org.springframework.integration.mqtt.core.MqttPahoClientFactory;


/**
 * mqtt消息处理配置
 */
@Configuration
@ConditionalOnProperty(value = "mqtt.enabled", havingValue = "true")
public class MqttBaseConfig {
    @Value("${mqtt.host}")
    private String mqttHost;

    @Value("${mqtt.username:}")
    private String mqttUserName;

    @Value("${mqtt.pwd:}")
    private String mqttPwd;

    /**
     * 构造一个默认的mqtt客户端操作bean
     *
     * @return
     */
    @Bean
    public MqttPahoClientFactory factory(){
	  DefaultMqttPahoClientFactory defaultMqttPahoClientFactory = new DefaultMqttPahoClientFactory();
	  MqttConnectOptions mqttConnectOptions = new MqttConnectOptions();
	  mqttConnectOptions.setUserName(mqttUserName);
	  mqttConnectOptions.setPassword(mqttPwd.toCharArray());
	  mqttConnectOptions.setServerURIs(new String[]{mqttHost});
	  defaultMqttPahoClientFactory.setConnectionOptions(mqttConnectOptions);
	  return defaultMqttPahoClientFactory;
    }

}
package com.zhk.study.mqtt;


import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.integration.annotation.ServiceActivator;
import org.springframework.integration.channel.DirectChannel;
import org.springframework.integration.mqtt.core.MqttPahoClientFactory;
import org.springframework.integration.mqtt.outbound.MqttPahoMessageHandler;
import org.springframework.messaging.MessageChannel;
import org.springframework.messaging.MessageHandler;

/**
 * mqtt出站消息处理配置
 */
@Configuration
@ConditionalOnProperty(value = "mqtt.enabled", havingValue = "true")
public class MqttOutConfig {

    /**
     * mqtt消息出站通道,用于发送出站消息
     *
     * @return
     */
    @Bean
    public MessageChannel mqttOutputChannel() {
	  return new DirectChannel();
    }

    /**
     * mqtt消息出站通道默认配置,用于向外发出mqtt消息,当前案例中发到了同一个mqtt服务器
     *
     * @return
     */
    @Bean
    @ServiceActivator(inputChannel = "mqttOutputChannel")
    public MessageHandler mqttOutbound(MqttPahoClientFactory factory) {
	  String clientId = "h-backend-mqtt-out-" + System.currentTimeMillis();
	  MqttPahoMessageHandler messageHandler = new MqttPahoMessageHandler(clientId, factory);
	  messageHandler.setAsync(true);
	  messageHandler.setDefaultQos(2);
	  messageHandler.setDefaultTopic("/crane/mqtt/demo/foo");
	  return messageHandler;
    }
}

package com.zhk.study.mqtt;


import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.integration.mqtt.support.MqttHeaders;
import org.springframework.messaging.Message;
import org.springframework.messaging.MessageHandler;
import org.springframework.messaging.MessagingException;
import org.springframework.stereotype.Component;

/**
 * mqtt订阅消息处理
 */
@Component
@ConditionalOnProperty(value = "mqtt.enabled", havingValue = "true")
public class MqttMessageReceiver implements MessageHandler {
    private Logger logger = LoggerFactory.getLogger(this.getClass());

    @Override
    public void handleMessage(Message<?> message) throws MessagingException {
	  String topic = String.valueOf(message.getHeaders().get(MqttHeaders.RECEIVED_TOPIC));
	  String payload = String.valueOf(message.getPayload());
	  logger.info("接收到 mqtt消息,主题:{} 消息:{}", topic, payload);
    }
}

package com.zhk.study.mqtt;

import lombok.RequiredArgsConstructor;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.integration.annotation.ServiceActivator;
import org.springframework.integration.channel.DirectChannel;
import org.springframework.integration.core.MessageProducer;
import org.springframework.integration.mqtt.core.MqttPahoClientFactory;
import org.springframework.integration.mqtt.inbound.MqttPahoMessageDrivenChannelAdapter;
import org.springframework.integration.mqtt.support.DefaultPahoMessageConverter;
import org.springframework.messaging.MessageChannel;
import org.springframework.messaging.MessageHandler;

@Configuration
@ConditionalOnProperty(value = "mqtt.enabled", havingValue = "true")
@RequiredArgsConstructor
public class MqttInConfig {

    private final MqttMessageReceiver mqttMessageReceiver;

    /**
     * mqtt消息入站通道,订阅消息后消息进入的通道。
     * 可创建多个入站通道,对应多个不同的消息生产者。
     *
     * @return
     */
    @Bean
    public MessageChannel mqttInputChannel() {
        return new DirectChannel();
    }
    /**
     * 对于当前应用来讲,接收的mqtt消息的生产者。将生产者绑定到mqtt入站通道,即通过入站通道进入的消息为生产者生产的消息。
     * 可创建多个消息生产者,对应多个不同的消息入站通道,同时生产者监听不同的topic
     *
     * @return
     */
    @Bean
    public MessageProducer channelInbound(MessageChannel mqttInputChannel, MqttPahoClientFactory factory) {
	  String clientId = "h-backend-mqtt-in-" + System.currentTimeMillis();
	  MqttPahoMessageDrivenChannelAdapter adapter = new MqttPahoMessageDrivenChannelAdapter(clientId, factory, "/crane/mqtt/demo/#");
	  adapter.setCompletionTimeout(5000);
	  adapter.setConverter(new DefaultPahoMessageConverter());
	  adapter.setQos(2);
	  adapter.setOutputChannel(mqttInputChannel);
	  return adapter;
    }
    /**
     * mqtt入站消息处理工具,对于指定消息入站通道接收到生产者生产的消息后处理消息的工具。
     *
     * @return
     */
    @Bean
    @ServiceActivator(inputChannel = "mqttInputChannel")
    public MessageHandler mqttMessageHandler() {
	  return this.mqttMessageReceiver;
    }


}


package com.zhk.study.mqtt;


import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.integration.annotation.MessagingGateway;
import org.springframework.integration.mqtt.support.MqttHeaders;
import org.springframework.messaging.handler.annotation.Header;
import org.springframework.stereotype.Component;

/**
 * mqtt消息发送工具,指定通过某个通道发出消息
 */
@Component
@ConditionalOnProperty(value = "mqtt.enabled", havingValue = "true")
@MessagingGateway(defaultRequestChannel = "mqttOutputChannel")
public interface MqttMessageSender {
    /**
     * 发送信息
     *
     * @param data 发送的消息
     */
    void sendToMqtt(String data);

    /**
     * 指定主题发送消息
     *
     * @param topic   主题
     * @param payload 消息主体
     */
    void sendToMqtt(@Header(MqttHeaders.TOPIC) String topic, String payload);

    /**
     * 指定主题、qos发送消息
     *
     * @param topic   主题
     * @param qos     对消息处理的几种机制。
     *                0 表示的是订阅者没收到消息不会再次发送,消息会丢失。
     *                1 表示的是会尝试重试,一直到接收到消息,但这种情况可能导致订阅者收到多次重复消息。
     *                2 多了一次去重的动作,确保订阅者收到的消息有一次。
     * @param payload 消息主体
     */
    void sendToMqtt(@Header(MqttHeaders.TOPIC) String topic, @Header(MqttHeaders.QOS) int qos, String payload);

}


package com.zhk.study.mqtt;


import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@ConditionalOnProperty(value = "mqtt.enabled", havingValue = "true")
@RequestMapping("/public/mqtt")
public class MqttController {
    private Logger logger = LoggerFactory.getLogger(this.getClass());
    private final MqttMessageSender mqttMessageSender;

    public MqttController(MqttMessageSender mqttMessageSender) {
	  this.mqttMessageSender = mqttMessageSender;
    }

    /**
     * 发送mqtt消息
     *
     * @param topic 消息主题
     * @param data  消息内容
     * @return
     */
    @GetMapping("/send")
    public String send(String topic, String data) {

	  if (StringUtils.isNotBlank(topic)) {
		this.mqttMessageSender.sendToMqtt(topic, data);
	  } else {
		this.mqttMessageSender.sendToMqtt(data);
	  }

	  return "success";
    }
}


疑问点可以直接给博主发消息,看到就回复,此帖转发别人的。注意点这个监听绑定在MqttInConfig中
MqttPahoMessageDrivenChannelAdapter adapter = new MqttPahoMessageDrivenChannelAdapter(clientId, factory, "/crane/mqtt/demo/#");

案例二、

        <dependency>
            <groupId>org.eclipse.paho</groupId>
            <artifactId>org.eclipse.paho.client.mqttv3</artifactId>
            <version>1.2.5</version>
        </dependency>

import org.eclipse.paho.client.mqttv3.*;
import org.eclipse.paho.client.mqttv3.persist.MemoryPersistence;
import org.json.JSONArray;
import org.json.JSONObject;

public class MqttDemo {
    // MQTT 服务器地址
    private static final String MQTT_BROKER = "tcp://iot.modbus.cn:1883";

    // MQTT 客户端 ID
    private static final String MQTT_CLIENT_ID = "4QR8TZ9ThuL4G";

    // MQTT 用户名
    private static final String MQTT_USERNAME = "ceshi";

    // MQTT 密码
    private static final String MQTT_PASSWORD = "Abc123456";

    // 订阅的主题
    private static final String MQTT_TOPIC_SUBSCRIBE = "/server/coo/4QR8TZ9ThuL4G";

    // 发布的主题
    private static final String MQTT_TOPIC_PUBLISH = "/dev/coo/4QR8TZ9ThuL4G";

    // 心跳间隔,单位为秒
    private static final int MQTT_KEEP_ALIVE_INTERVAL = 60;

    public static void main(String[] args) throws MqttException {
        // 创建 MQTT 客户端
        MqttClient mqttClient = new MqttClient(MQTT_BROKER, MQTT_CLIENT_ID, new MemoryPersistence());

        // 设置 MQTT 连接选项
        MqttConnectOptions options = new MqttConnectOptions();
        options.setUserName(MQTT_USERNAME);
        options.setPassword(MQTT_PASSWORD.toCharArray());
        options.setCleanSession(true);
        options.setKeepAliveInterval(MQTT_KEEP_ALIVE_INTERVAL);

        // 设置回调
        mqttClient.setCallback(new MqttCallback() {
            @Override
            public void connectionLost(Throwable cause) {
                System.out.println("连接断开");
            }

            @Override
            public void messageArrived(String topic, MqttMessage message) throws Exception {
                System.out.println("收到消息。主题: " + topic);
                System.out.println("消息: " + new String(message.getPayload()));

                // 将消息转换为字符串
                String msg = new String(message.getPayload());

                // 使用 JSON 工具解析字符串
                JSONArray jsonArray = new JSONArray(msg);

                for (int i = 0; i < jsonArray.length(); i++) {
                    JSONObject jsonObject = jsonArray.getJSONObject(i);
                    int sensor_device_id = jsonObject.getInt("sensor_device_id");
                    int port_id = jsonObject.getInt("port_id");
                    int sdata = jsonObject.getInt("sdata");

                    // 在这里你可以处理接收到的数据
                    System.out.println("设备ID: " + sensor_device_id + ", 端口ID: " + port_id + ", 数据: " + sdata);
                }
            }

            @Override
            public void deliveryComplete(IMqttDeliveryToken token) {
                System.out.println("消息发布完成");
            }
        });

        // 连接到 MQTT 服务器
        mqttClient.connect(options);

        // 订阅主题  //后面的参数qos
        mqttClient.subscribe(MQTT_TOPIC_SUBSCRIBE);

        // 创建消息
        MqttMessage message = new MqttMessage();
        message.setPayload("[{\"sensor_device_id\": 1, \"port_id\": 1, \"sdata\": 66}]".getBytes());

        // 发布消息
        mqttClient.publish(MQTT_TOPIC_PUBLISH, message);
    }
}


评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

张航柯

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值