EMQX使用文档

EMQX安装文档

下载安装

选择开源版本的centos版本amd的rpm

https://www.emqx.com/zh/downloads-and-install/broker?os=RHEL

命令行下载安装

登录linux服务器,使用命令行下载安装emqx

#进入opt目录,将文件下载到此目录下
cd /opt
#使用官方文档命令行下载安装
wget https://www.emqx.com/zh/downloads/broker/5.7.0/emqx-5.7.0-el7-amd64.rpm
sudo yum install emqx-5.7.0-el7-amd64.rpm -y
#启动
sudo systemctl start emqx
#打开防火墙端口号
firewall-cmd --zone=public --add-port=1883/tcp --permanent
firewall-cmd --zone=public --add-port=8080/tcp --permanent
firewall-cmd --zone=public --add-port=8083/tcp --permanent
firewall-cmd --zone=public --add-port=8084/tcp --permanent
firewall-cmd --zone=public --add-port=8883/tcp --permanent
firewall-cmd --zone=public --add-port=18083/tcp --permanent
# 防火墙配置立即生效
firewall-cmd --reload
阿里云开放端口

阿里云安全组开放端口号1883,8080,8083,8084,8883,18083

在这里插入图片描述

使用

使用外网访问

http://服务器公网IP地址:18083/

默认账户:admin

默认密码:public

下载客户端软件

https://mqttx.app/zh/downloads

在这里插入图片描述

客户端连接

在这里插入图片描述

连接成功

设置连接客户端认证方式
配置内置服务器

目前为止,连接服务器的MQTT服务,是没有做校验的,输入任何客户端名称和密码都可以连接。但对于产品来言,这种认证方式是不安全的。最开始安装emqx时,我们先使用内置服务器做一个简单的连接测试。
在这里插入图片描述
在这里插入图片描述

选择内置数据库的方式
在这里插入图片描述

选择clinetnId的方式

在这里插入图片描述

点击用户管理。添加可以连接的客户端用户

在这里插入图片描述

此时不输入密码和clientId就无法连接,重新输入信息再次连接

在这里插入图片描述

连接成功

配置MySQL连接方式

正式使用时,使用数据库连接的方式

在这里插入图片描述

新建数据库mqtt_user并创建表和插入数据

#mqtt_user数据库中创建表mqtt_user
CREATE TABLE `mqtt_user` (
  `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
  `username` varchar(100) DEFAULT NULL,
  `password_hash` varchar(100) DEFAULT NULL,
  `salt` varchar(35) DEFAULT NULL,
  `is_superuser` tinyint(1) DEFAULT 0,
  `created` datetime DEFAULT NULL,
  PRIMARY KEY (`id`),
  UNIQUE KEY `mqtt_username` (`username`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

#插入第一个客户端用户 ,用户名emqx_u,密码public
INSERT INTO mqtt_user(username, password_hash, salt, is_superuser) VALUES ('emqx_u', SHA2(concat('public', 'slat_foo123'), 256), 'slat_foo123', 1);
Query OK, 1 row affected (0,01 sec)

#插入第二个客户端用户 ,用户名emqx_u1,密码public
INSERT INTO mqtt_user(username, password_hash, salt, is_superuser) VALUES ('emqx_u1', SHA2(concat('public', 'slat_foo123'), 256), 'slat_foo123', 1);
Query OK, 1 row affected (0,01 sec)

配置成功

在这里插入图片描述

使用MQTTX客户端连接

在这里插入图片描述

连接成功

编码实现设备上下线和消息接收功能

引入依赖
				<!--integration用于在 Spring Boot 项目中集成 MQTT(消息队列遥测传输)协议-->
                <dependency>
                    <groupId>org.springframework.integration</groupId>
                    <artifactId>spring-integration-mqtt</artifactId>
                </dependency>
                <!--用于Java的MQTT(消息队列遥测传输)客户端库依赖-->
                <dependency>
                    <groupId>org.eclipse.paho</groupId>
                    <artifactId>org.eclipse.paho.client.mqttv3</artifactId>
                    <version>1.2.5</version>
                </dependency>
配置客户端信息
mqtt:
  brokerUrl: tcp://服务器公网IP地址:1883
  clientId:  emqx_u
  clientName: emqx_u
  password: public
  topics: AAA/#,BBB/#,$SYS/brokers/+/clients/#

配置

import org.eclipse.paho.client.mqttv3.MqttConnectOptions;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.integration.annotation.IntegrationComponentScan;
import org.springframework.integration.channel.DirectChannel;
import org.springframework.integration.core.MessageProducer;
import org.springframework.integration.mqtt.core.DefaultMqttPahoClientFactory;
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;

@Configuration
@IntegrationComponentScan
public class MqttConfig {

    @Value("${mqtt.brokerUrl}")
    private String brokerUrl;

    @Value("${mqtt.clientId}")
    private String clientId;

    @Value("${mqtt.clientName}")
    private String clientName;

    @Value("${mqtt.password}")
    private String password;

    @Value("${mqtt.topics}")
    private String topics;

    /**
     * 创建并注册一个名为 mqttInputChannel 的消息通道,该通道允许消息在发送者和接收者之间进行直接、同步的传递。这个通道随后会被用于处理从 MQTT 代理接收到的消息。
     * @Author Hootin
     * @return
     */
    @Bean
    public MessageChannel mqttInputChannel() {
        return new DirectChannel();
    }

    //创建MQTT客户端的工厂类
    @Bean
    public MqttPahoClientFactory mqttClientFactory() {
        DefaultMqttPahoClientFactory factory = new DefaultMqttPahoClientFactory();
        MqttConnectOptions options = new MqttConnectOptions();
        // 设置连接选项,如用户名、密码、超时等(如果需要)
        options.setUserName(clientName);
        options.setPassword(password.toCharArray());

        factory.setConnectionOptions(options);
        return factory;
    }

    @Bean
    public MessageProducer inbound() {
        /**
         * MqttPahoMessageDrivenChannelAdapter是Spring Integration 提供的 MQTT 入站通道适配器(inbound channel adapter)。
         * 它负责连接到 MQTT 代理,并监听指定的 MQTT 主题(topics)上的消息。
         * 当消息到达时,它将这些消息转换为 Spring Integration 消息,并发送到与适配器关联的输入通道(input channel)。
         */
        MqttPahoMessageDrivenChannelAdapter adapter =
                new MqttPahoMessageDrivenChannelAdapter(brokerUrl,clientId(), mqttClientFactory(), topics().split(","));
        adapter.setCompletionTimeout(5000);
        adapter.setConverter(new DefaultPahoMessageConverter());
        adapter.setQos(1);
        adapter.setOutputChannel(mqttInputChannel());
        return adapter;
    }

    @Bean
    public String clientId() {
        return clientId;
    }

    @Bean
    public String topics() {
        return topics;
    }

}
监听
import cn.hutool.json.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.springframework.integration.annotation.ServiceActivator;
import org.springframework.messaging.Message;
import org.springframework.stereotype.Service;

import java.text.SimpleDateFormat;
import java.util.Date;

@Service
@Slf4j
public class MqttMessageHandler {

    /**
     * @ServiceActivator 是 Spring Integration 中的一个注解,用于定义消息处理流程中的一个步骤。当消息到达指定的通道(channel)时,由该注解标记的方法将被调用以处理该消息。
     * inputChannel = "mqttInputChannel":这个属性指定了该方法应该监听哪个输入通道。
     * 因此,当 mqttInputChannel 上有消息到达时,这个被 @ServiceActivator 标记的方法将被调用。
     * 消息处理:在该注解下的方法定义如何处理从 mqttInputChannel 接收到的消息。
     * @param message
     */
    @ServiceActivator(inputChannel = "mqttInputChannel")
    public void handleMessage(Message<?> message) {
        String payload = (String) message.getPayload(); // 假设消息是String类型
        JSONObject jsonObject = new JSONObject(payload);
        // 这里可以根据payload内容判断是上线还是下线,并执行相应的逻辑
        if (isOfflineMessage(payload)) {
            // 处理设备离线逻辑
            //获取24小时制格式的离线时间字符串
            String disconnected_at = strConvertFormattedDate(String.valueOf(jsonObject.get("disconnected_at")));
            String connected_at = strConvertFormattedDate(String.valueOf(jsonObject.get("connected_at")));
            //打印客户端ID,上线时间,离线时间
            log.info("设备{}在{}离线,上线时间为{}",jsonObject.get("clientid").toString(),disconnected_at,connected_at);
        } else {
            // 处理设备上线逻辑(注意:上线通常不是通过LWT消息来识别的)
            //获取上线时间和设备客户端ID打印
            if (payload.contains("connected_at")){
                String connected_at = strConvertFormattedDate(String.valueOf(jsonObject.get("connected_at")));
                log.info("设备{}上线,上线时间为{}",jsonObject.get("clientid").toString(),connected_at);
            }else {
                log.info("设备发送消息"+payload);
            }
        }
    }

    private boolean isOfflineMessage(String payload) {
        // 根据LWT消息内容来判断是否是离线消息,如果信息包含断开连接时间,就说明这条消息是离线消息
        return payload.contains("disconnected_at");
    }

    public Date strConvertDate(String str){
        return new Date(Long.valueOf(str));
    }

    //将时间戳字符串转换为24小时制格式的时间字符串
    public String strConvertFormattedDate(String str){
        Date date = new Date(Long.valueOf(str));
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        return simpleDateFormat.format(date);
    }
}
MQTTX测试

客户端填写信息:

使用添加的第二个客户端,第一个客户端用于编码时使用

Name:emqx_u1

Client ID: emqx_u1

Host:mqtt://服务器公网IP地址

Port:1883

Username:emqx_u1

password:public

在这里插入图片描述

连接

发送消息

下线

控制台输出

2024-06-27T11:25:00.389+08:00 INFO 3032 — [wjzb-car-manager-mqtt] [TT Call: emqx_u] c.wjzb.mqtt.service.MqttMessageHandler : 设备emqx_u1上线,上线时间为2024-06-27 11:24:57
2024-06-27T11:25:03.749+08:00 INFO 3032 — [wjzb-car-manager-mqtt] [TT Call: emqx_u] c.wjzb.mqtt.service.MqttMessageHandler : 设备发送消息{
“msg”: “hello”
}
2024-06-27T11:25:05.104+08:00 INFO 3032 — [wjzb-car-manager-mqtt] [TT Call: emqx_u] c.wjzb.mqtt.service.MqttMessageHandler : 设备emqx_u1在2024-06-27 11:25:02离线,上线时间为2024-06-27 11:24:57
-27T11:25:03.749+08:00 INFO 3032 — [wjzb-car-manager-mqtt] [TT Call: emqx_u] c.wjzb.mqtt.service.MqttMessageHandler : 设备发送消息{
“msg”: “hello”
}
2024-06-27T11:25:05.104+08:00 INFO 3032 — [wjzb-car-manager-mqtt] [TT Call: emqx_u] c.wjzb.mqtt.service.MqttMessageHandler : 设备emqx_u1在2024-06-27 11:25:02离线,上线时间为2024-06-27 11:24:57

  • 27
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值