MQTT实现串口数据的下发和接收(DTU透传)

硬件环境

  1. 任意支持MQTT透传DTU,DTU支持4G、Wifi或网口都可以,只要能和服务器通讯即可。
  2. 串口接Modbus设备,需要知道Modbus设备的设备地址、寄存器地址、串口相关信息。

软件环境

  1. EMQX自建服务器,该项可自行百度搭建方法。
  2. 配置DTU连接MQTT服务器,需要知道MQTT服务器地址、端口、账户、密码、ClientId。
  3. VistualStudio用于编写测试采集程序本次测试采用ModbusRTU报文进行测试。
  4. MQTTX客户端,用于测试报文收发,确认串口能在MQTT上实现数据收发。
  5. 软件库,本人采用了Hsl,只是因为库中既有MQTT又有Modbus比较方便,可以自行选择MQTTnet、NModbus4之类的库。

设计架构

采集程序

完整代码如下:

using HslCommunication.Core.Address;
using HslCommunication.ModBus;
using HslCommunication;
using System;
using System.Text;
using HslCommunication.Core;
using HslCommunication.MQTT;
using System.Linq;
using System.Threading;

class Program
{
    static void Main()
    {
        byte deviceAddress = 0x02; // 设备地址
        ushort registerAddress = 0x000D; // 寄存器地址
        ushort length = 0x0001; // 数据长度
        OperateResult<byte[]> command = ModbusMqtt.BuildReadModbusCommandBytes(registerAddress.ToString(), length, deviceAddress, true, ModbusInfo.ReadRegister, true);
        string hexString = BitConverter.ToString(command.Content).Replace("-", " ");
        Console.WriteLine("MQTT发送ModbusRtu读取指令:" + hexString);
        byte[] byteArray = hexString.Split(' ')
                              .Select(s => Convert.ToByte(s, 16))
                              .ToArray();
        MqttConnectionOptions options = new MqttConnectionOptions
        {
            CleanSession = true,
            IpAddress = "broker.emqx.io",
            Port = 1883,
            ClientId = "MqttTest_1"
        };


        MqttClient mqttClient = new MqttClient(options);
        mqttClient.ConnectServer();
        if (mqttClient.SubscribeMessage("sub").IsSuccess == true && mqttClient.SubscribeMessage("pub").IsSuccess == true)
        {
            Thread.Sleep(1000);
            if (mqttClient.PublishMessage(new MqttApplicationMessage()
            {
                Topic = "sub",
                QualityOfServiceLevel = MqttQualityOfServiceLevel.AtMostOnce,
                Payload = byteArray,
                Retain = false
            }).IsSuccess)
            {
                Console.WriteLine("连接MQTT客户端成功...");
                Console.WriteLine("订阅sub、pub主题成功...");
            }
            Thread.Sleep(1000);
            //订阅MQTT数据接收事件,添加对应事件处理函数
            mqttClient.OnMqttMessageReceived += onMqttMessageReceived;
            Thread.Sleep(Timeout.Infinite);

        }
        mqttClient.ConnectClose();
    }

    private static void onMqttMessageReceived(MqttClient client, string topic, byte[] payload)
    {
        if (topic == "pub")
        {
            // 解析收到的消息
            byte[] receivedData = payload;
            string hexString = BitConverter.ToString(receivedData).Replace("-", "");
            Console.WriteLine("MQTT接收ModbusRtu返回指令:" + hexString);
            short value = ModbusMqtt.ReadShortValue(receivedData);
            Console.WriteLine("点位Short值:" + value);
        }
    }
}

两个红框处为本人修改源码添加的方法,大家也可以自行编写,此处将两个封装方法贴出

        public static OperateResult<byte[]> BuildReadModbusCommandBytes(string address, ushort length, byte station, bool isStartWithZero, byte defaultFunction, bool crcFlag)
        {
            try
            {
                ModbusAddress mAddress = new ModbusAddress(address, station, defaultFunction);
                CheckModbusAddressStart(mAddress, isStartWithZero);
                OperateResult<byte[][]> operateResult = BuildReadModbusCommand(mAddress, length);
                if (operateResult.IsSuccess)
                {
                    if (crcFlag)
                    {
                        byte[] array = CalculateCRC(operateResult.Content[0]);
                        byte[] array2 = new byte[operateResult.Content[0].Length + array.Length];
                        Array.Copy(operateResult.Content[0], array2, operateResult.Content[0].Length);
                        Array.Copy(array, 0, array2, operateResult.Content[0].Length, array.Length);
                        return OperateResult.CreateSuccessResult(array2);
                    }

                    return OperateResult.CreateSuccessResult(operateResult.Content[0]);
                }

                return null;
            }
            catch (Exception ex)
            {
                return new OperateResult<byte[]>(ex.Message);
            }
        }
 public static short ReadShortValue(byte[] data)
        {
            if (data.Length >= 5 && data[1] == 3 && data[2] == 2)
            {
                byte[] array = new byte[2]
                {
                    data[3],
                    data[4]
                };
                string value = BitConverter.ToString(array).Replace("-", "");
                int value2 = Convert.ToInt16(value, 16);
                return Convert.ToInt16(value2);
            }

            throw new ArgumentException("Invalid Modbus RTU read register data");
        }

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值