4G工业智能网关RS485转MQTT对接EMQX

273 阅读5分钟

image.png

1、Modbus slave设置从机Modbus TCP参数

设置Modbus TCP协议和地址

模拟软件设置的是 当前电脑的,所以后面 配置Modbus TCP的从机时,就要填当前电脑的ip地址,不要写 bl系列设备的ip地址 image.png

设置数据参数

设备地址:22 功能码:04 数据类型:16 起始地址:0 数量:5个 image.png

2、设置BL102将Modbus slave从机数据点映射

设置WAN口为Modbus TCP Master模式

image.png

设置bl102设备和从机同个网段

image.png

添加从机

从机的ip地址,需要填写Modbus slave软件的所在电脑的ip地址,不要填了 bl网关的ip地址 image.png

添加数据点

image.png

设置MQTT broker(MQTT服务器)信息

image.png

查看设备上下行状态

查看下行连接设备和上行连接MQTT服务器状态 image.png

3、MQTT客户端设置订阅

客户端设置连接MQTT服务器参数

服务器ip、端口、ID、心跳等。 image.png

设置订阅BL102设备的主题

刚才设置BL102设备的发布主题是 test,那么订阅也是 test image.png image.png

查看已收到BL102设备的数据

image.png

4、不同编程语言采集数据并写入数据库

以下介绍java和python

Java采集并写入数据库

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.time.LocalDateTime;
import java.util.Random;

import com.google.gson.Gson;
import com.google.gson.JsonObject;

import org.eclipse.paho.client.mqttv3.IMqttClient;
import org.eclipse.paho.client.mqttv3.IMqttDeliveryToken;
import org.eclipse.paho.client.mqttv3.IMqttMessageListener;
import org.eclipse.paho.client.mqttv3.MqttClient;
import org.eclipse.paho.client.mqttv3.MqttConnectOptions;
import org.eclipse.paho.client.mqttv3.MqttException;
import org.eclipse.paho.client.mqttv3.MqttMessage;
import org.eclipse.paho.client.mqttv3.persist.MemoryPersistence;

public class MQTTSubscriber {
    
    private static final String BROKER = "tcp://192.168.1.165:1883"; // MQTT Broker地址
    private static final String TOPIC = "test"; // 订阅主题名称
    private static final String DB_URL = "jdbc:sqlite:plcdata"; // SQLite数据库URL
    
    private static Random random = new Random(); // 用于生成客户端ID的随机数
    
    public static void main(String[] args) throws MqttException {
        String clientId = "java-mqtt-" + random.nextInt(100); // 生成客户端ID
        IMqttClient mqttClient = new MqttClient(BROKER, clientId, new MemoryPersistence());
        
        // 设置MQTT连接选项
        MqttConnectOptions options = new MqttConnectOptions();
        options.setCleanSession(true); // 不保留会话
        options.setAutomaticReconnect(true); // 自动重连
        
        mqttClient.connect(options); // 连接MQTT Broker
        
        // 设置MQTT消息监听器,接收订阅主题的消息
        mqttClient.subscribe(TOPIC, new IMqttMessageListener() {
            @Override
            public void messageArrived(String topic, MqttMessage message) throws Exception {
                LocalDateTime now = LocalDateTime.now();
                System.out.println("当前时间:" + now);
                
                String jsonStr = new String(message.getPayload()); // 将MQTT消息转为JSON字符串
                System.out.println("收到消息:" + jsonStr);
                
                JsonObject jsonObj = new Gson().fromJson(jsonStr, JsonObject.class); // 将JSON字符串解析为JsonObject对象
                
                // 解析sensorDatas数组中的数据
                double lat = 0.0, lng = 0.0;
                int signalStrength = 0, reg001 = 0, reg002 = 0, reg003 = 0, reg004 = 0, reg005 = 0;
                for (var sensorData : jsonObj.get("sensorDatas").getAsJsonArray()) {
                    JsonObject sensorDataObj = sensorData.getAsJsonObject();
                    String flag = sensorDataObj.get("flag").getAsString();
                    if (flag.equals("GPS")) {
                        lat = sensorDataObj.get("lat").getAsDouble();
                        lng = sensorDataObj.get("lng").getAsDouble();
                    } else if (flag.equals("SIGNAL_STRENGTH")) {
                        signalStrength = sensorDataObj.get("value").getAsInt();
                    } else if (flag.equals("REG001")) {
                        reg001 = sensorDataObj.get("value").getAsInt();
                    } else if (flag.equals("REG002")) {
                        reg002 = sensorDataObj.get("value").getAsInt();
                    } else if (flag.equals("REG} else if (flag.equals("REG001")) {
						reg001 = sensorDataObj.get("value").getAsInt();
					} else if (flag.equals("REG002")) {
						reg002 = sensorDataObj.get("value").getAsInt();
					} else if (flag.equals("REG003")) {
						reg003 = sensorDataObj.get("value").getAsInt();
					} else if (flag.equals("REG004")) {
						reg004 = sensorDataObj.get("value").getAsInt();
					} else if (flag.equals("REG005")) {
						reg005 = sensorDataObj.get("value").getAsInt();
					}
该方法用于连接 MQTT 服务器。需要导入java MQTT 客户端库。Java 中有多个可用的 MQTT 客户端库,这里我们将使用 Eclipse Paho Java 客户端库
下面我们将使用 Eclipse Paho Java 客户端库实现 connectMqtt() 方法。首先需要导入相关库:下面我们将使用 Eclipse Paho Java 客户端库实现 connectMqtt() 方法。首先需要导入相关库:

import org.eclipse.paho.client.mqttv3.MqttClient;
import org.eclipse.paho.client.mqttv3.MqttConnectOptions;
import org.eclipse.paho.client.mqttv3.persist.MemoryPersistence;


然后在 MqttController 类中添加以下代码实现 connectMqtt() 方法:


public static MqttClient connectMqtt() throws MqttException {
    // 定义 MQTT 服务器的地址和端口
    String broker = "tcp://192.168.1.165:1883";
    // 定义 MQTT 客户端 ID,可以随机生成
    String clientId = MqttClient.generateClientId();
    // 定义连接选项
    MqttConnectOptions connOpts = new MqttConnectOptions();
    // 设置是否清除会话
    connOpts.setCleanSession(true);
    // 设置心跳间隔时间
    connOpts.setKeepAliveInterval(60);
    // 创建 MQTT 客户端
    MqttClient client = new MqttClient(broker, clientId, new MemoryPersistence());
    // 连接 MQTT 服务器
    client.connect(connOpts);
    return client;
}
该方法首先定义了 MQTT 服务器的地址和端口,然后生成了一个随机的 MQTT 客户端 ID。接着定义了连接选项,其中设置了是否清除会话和心跳间隔时间等参数。最后创建了一个 MQTT 客户端并连接 MQTT 服务器,返回连接成功的 MQTT 客户端对象。

接下来我们需要在 Java 代码中实现 subscribe() 方法,该方法用于订阅主题并接收数据。首先需要导入相关库:

import org.eclipse.paho.client.mqttv3.IMqttMessageListener;
import org.eclipse.paho.client.mqttv3.IMqttToken;
import org.eclipse.paho.client.mqttv3.MqttCallback;
import org.eclipse.paho.client.mqttv3.MqttException;
import org.eclipse.paho.client.mqttv3.MqttMessage;
import org.eclipse.paho.client.mqttv3.Topic;

然后在 MqttController 类中添加以下代码实现 subscribe() 方法:

public static void subscribe(MqttClient client) throws MqttException {
    // 定义订阅主题
    String topic = "test";
    // 订阅主题并设置消息监听器
    client.subscribeWithResponse(topic, new IMqttMessageListener() {
        @Override
        public void messageArrived(String topic, MqttMessage message) throws Exception {
            // 处理接收到的消息
            String jsonStr = new String(message.getPayload(), "UTF-8");
            System.out.println("Received message: " + jsonStr);
            // TODO: 解析 json 数据并插入数据库
        }
    });
}

Python采集并写入数据库

# python3.6
import json
import sqlite3

import random
from datetime import datetime

from paho.mqtt import client as mqtt_client


broker = '192.168.1.165'
#broker = 'broker-cn.emqx.io'
port = 1883
topic = "test"
# generate client ID with pub prefix randomly
client_id = f'python-mqtt-{random.randint(0, 100)}'


def connect_mqtt() -> mqtt_client:
    def on_connect(client, userdata, flags, rc):
        if rc == 0:
            print("Connected to MQTT Broker!")
        else:
            print("Failed to connect, return code %d\n", rc)

    client = mqtt_client.Client(client_id)
    client.on_connect = on_connect
    client.connect(broker, port)
    return client


#将数据出入数据库
def create_table():
    #连接数据库,没有则创建
    conn = sqlite3.connect('plcdata') 
    print('连接数据库成功')
    
    #判断iot表是否存在,不存在则新建。 CREATE TABLE IF NOT EXISTS iot
    try:
        create_tb_cmd='''
        CREATE TABLE IF NOT EXISTS iot
        (lat TEXT,
        lng TEXT,
        signal_strength  INT,
        REG001 INT,
        REG002 INT,
        REG003 INT,
        REG004 INT,
        REG005 INT);
        '''
        #执行创建数据表语句
        conn.execute(create_tb_cmd)
    except:
        print("Create table failed")
        return False
    
    insert_dt_cmd='INSERT INTO iot (lat,lng,signal_strength,REG001,REG002,REG003,REG004,REG005) VALUES '+ strlist + ';'
    print(insert_dt_cmd)
#     insert_dt_cmd='''
#     INSERT INTO iot (lat,lng,signal_strength,REG001,REG002,REG003,REG004,REG005) VALUES (0.000000,0.000000,0,33,8538,234,22,9046);
#     '''
    
    conn.execute(insert_dt_cmd)
    print('写入数据库成功')
    conn.commit()
    conn.close()

strlist = ''
def subscribe(client: mqtt_client):
    def on_message(client, userdata, msg):
        t = datetime.now()
        print('当前时间:',t)
        #print(f"Received `{msg.payload.decode()}` from `{msg.topic}` topic")
        json_data = msg.payload.decode() #解析订阅主题信息,
#         print(type(json_data)) #判断data类型,是json字符串
        dict_json = json.loads(json_data)
        #print(type(dict_json))
        #print(dict_json)
        
        sensordatas = dict_json['sensorDatas']
        list_data =[]
        for i in sensordatas:
            #print(type(i),i)
            #print(i['flag'],type(i['flag']))


            if i['flag'] == 'GPS':
                list_data.append(i['lat'])
                list_data.append(i['lng'])
                #print(list_data)

            else:
                #print(i['flag'],i['value']) 
                list_data.append(i['value'])
                #print(list_data)
        global strlist
        strlist = str(tuple(list_data))
        print(strlist)
        create_table()
        
        
    client.subscribe(topic)
    client.on_message = on_message


def run():
    client = connect_mqtt()
    subscribe(client)
    client.loop_forever()


if __name__ == '__main__':
    run()

其他:python发布和订阅

发布

# python 3.6

import random
import time

from paho.mqtt import client as mqtt_client


#broker = '192.168.1.165'
broker = 'broker-cn.emqx.io'
port = 1883
topic = "test"
# generate client ID with pub prefix randomly
client_id = f'python-mqtt-{random.randint(0, 1000)}'


def connect_mqtt():
    def on_connect(client, userdata, flags, rc):
        if rc == 0:
            print("Connected to MQTT Broker!")
        else:
            print("Failed to connect, return code %d\n", rc)

    client = mqtt_client.Client(client_id)
    client.on_connect = on_connect
    client.connect(broker, port)
    return client


def publish(client):
    msg_count = 0
    while True:
        time.sleep(1)
        msg = f"messages: {msg_count}"
        result = client.publish(topic, msg)
        # result: [0, 1]
        status = result[0]
        if status == 0:
            print(f"Send `{msg}` to topic `{topic}`")
        else:
            print(f"Failed to send message to topic {topic}")
        msg_count += 1


def run():
    client = connect_mqtt()
    client.loop_start()
    publish(client)


if __name__ == '__main__':
    run()

订阅

# python3.6

import random
from datetime import datetime

from paho.mqtt import client as mqtt_client


#broker = '192.168.1.165'
broker = 'broker-cn.emqx.io'
port = 1883
topic = "test"
# generate client ID with pub prefix randomly
client_id = f'python-mqtt-{random.randint(0, 100)}'


def connect_mqtt() -> mqtt_client:
    def on_connect(client, userdata, flags, rc):
        if rc == 0:
            print("Connected to MQTT Broker!")
        else:
            print("Failed to connect, return code %d\n", rc)

    client = mqtt_client.Client(client_id)
    client.on_connect = on_connect
    client.connect(broker, port)
    return client


def subscribe(client: mqtt_client):
    def on_message(client, userdata, msg):
        t = datetime.now()
        print('当前时间:',t)
        print(f"Received `{msg.payload.decode()}` from `{msg.topic}` topic")
        

    client.subscribe(topic)
    client.on_message = on_message


def run():
    client = connect_mqtt()
    subscribe(client)
    client.loop_forever()


if __name__ == '__main__':
    run()