Skip to content

Modbus to MQTT Integration: Developing a C# Gateway Using HiveMQ MQTT Client

by Kudzai Manditereza
(updated on ) 10 min read

This guide will walk you through creating a .Net IoT application that serves as a bridge to transform Modbus data into MQTT messages. This application will read temperature sensor data from an industrial device via the Modbus TCP protocol, convert this data into JSON format, and then use the HiveMQ MQTT Client library for C# to send the data to the HiveMQ Cloud MQTT broker.

Setting up a HiveMQ Cloud MQTT Broker

First, you must set up a HiveMQ Cloud MQTT broker to manage messages for your C# IoT application. Head to the HiveMQ website, chose Platform from the megamenu and choose the HiveMQ Cloud from the left menu.

When you land on the HiveMQ Cloud page, select the ‘Sign up free’ option. A free version of HiveMQ Cloud Serverless allows you to provision two MQTT broker clusters and link up to 100 devices.

For first-time users, you’ll need to input an email address and password. Follow the subsequent steps to verify your email and set up your account.

HiveMQ Cloud Login Page

Once you’ve completed this process, an MQTT broker cluster is automatically created. To let devices connect to your MQTT broker, set up your connection credentials by providing a username and password and then clicking ADD.

HiveMQ Cloud Credentials

By selecting Overview, you can access the connection settings required for linking your C# application to the HiveMQ Cloud MQTT broker cluster. Ensure you record the cluster URL, port number, and your login details for later use.

HiveMQ Cloud Cluster Details

If you ever need to modify your connection details, simply log into your account, choose MANAGE CLUSTER, and then ACCESS MANAGEMENT.

At this stage, your MQTT broker is ready to handle the messaging for your IoT application.

Now you can start building your C# application to act as an MQTT Client, publishing Modbus messages from edge to the HiveMQ Cloud MQTT broker.

Creating C# .Net Console Application

Before you begin coding, you need a suitable development environment. I recommend the Visual Studio IDE for this demonstration, though Visual Studio Code is also a viable option. If you haven’t already, download the free Community edition of Visual Studio from their website and install it.

Visual Studio Webpage

Once installed, launch Visual Studio IDE and select Console App to create a new project. Under the list of project types, pick the C# Console App.

Visual Studio IDE Creating a New Project

Name your project and hit ‘Next’. You can then proceed with the default .Net 6.0 framework selection. With these steps, you’ve created an empty C# Console application.

Create empty C# Console application

The next objective is to equip this application with the ability to collect Modbus data and transmit it to cloud-based apps using MQTT. This is achieved by integrating the HiveMQ C# MQTT client library and a Modbus library.

HiveMQ Client C# Library

Installing HiveMQtt C# MQTT Client Library

The HiveMQ MQTT client for C# is an open-source project available on GitHub and comes with a flexible Apache 2.0 License. The client features full MQTT 5.0 support and is compatible with all major MQTT brokers.

The added advantage is its availability on NuGet.org, allowing for easy installation through the .Net NuGet Package Manager. This package manager streamlines the management of dependencies in .Net projects, ensuring effortless integration of the HiveMQ MQTT client library into your application.

HiveMQtt C# Client NuGet

To add the HiveMQ MQTT client to your application, right-click on your project within the Solution Explorer and select ‘Manage NuGet Packages’.

HiveMQ C# Library Manage NuGet Packages

Navigate to the Browse tab, search for HiveMQtt, select the client from the search results, and finalize the installation.

HiveMQtt Client Demo NuGet

Installing Modbus C# MQTT Client Library

To retrieve data from a Modbus device, you’ll also need to incorporate a Modbus client library for C#. Using the Manage NuGet packages window, look for the NModubus package and install it.

HiveMQtt NModbus

Publishing and Subscribing to MQTT Messages

Now, let’s focus on the C# code that reads the Modbus TCP data and transmits it as MQTT messages to the HiveMQ Cloud MQTT broker using the HiveMQtt MQTT client library.

Begin by incorporating the necessary assembly references to integrate the HiveMQtt client library into your code.

using HiveMQtt.Client;
using HiveMQtt.Client.Options;
using HiveMQtt.MQTT5.ReasonCodes;
using HiveMQtt.MQTT5.Types;
using NModbus;
using NModbus.Device;
using System.Net;
using System.Net.Sockets;
using System.Text.Json;

Follow this by initializing a Modbus client, providing the required connection details, and designating variables to store the returned values.

const string ipAddress = "192.168.0.229";
const int port = 502; // Default Modbus TCP port
const byte slaveId = 21;
const ushort startAddress = 0;
const ushort numRegisters = 2;
TcpClient modbus_client = new TcpClient(ipAddress, port);

Single modbus_value;
UInt16[] modbus_data = new UInt16[2];

Subsequently, create an MQTT client instance by providing your HiveMQ Cloud MQTT broker’s connection details.

var options = new HiveMQClientOptions
{
    Host = "81b8283f2a154f549a4337bd921c5da4.s2.eu.hivemq.cloud",
    Port = 8883,
    UseTLS = true,
    UserName = "username",
    Password = "password",
};

var client = new HiveMQClient(options);

Upon completion, you can establish a connection to your MQTT broker and view your connection status displayed on the console.

Console.WriteLine($"Connecting to {options.Host} on port {options.Port} ...");

// Connect
HiveMQtt.Client.Results.ConnectResult connectResult;
try
{
        connectResult = await client.ConnectAsync().ConfigureAwait(false);
        if (connectResult.ReasonCode == ConnAckReasonCode.Success)
    {
        Console.WriteLine($"Connect successful: {connectResult}");
    }
    else
    {
        // FIXME: Add ToString
        Console.WriteLine($"Connect failed: {connectResult}");
        Environment.Exit(-1);
    }
}
catch (System.Net.Sockets.SocketException e)
{
    Console.WriteLine($"Error connecting to the MQTT Broker with the following socket error: {e.Message}");
    Environment.Exit(-1);
}
catch (Exception e)
{
    Console.WriteLine($"Error connecting to the MQTT Broker with the following message: {e.Message}");
    Environment.Exit(-1);
}

Your next step is to create the main program loop. Within this loop, carry out the following tasks:

  1. Instantiate a Modbus master.

  2. Read temperature data from the Modbus client we created earlier.

  3. Convert the resulting Modbus arrays into a float.

  4. Create the JSON object for the temperature data and additional contextual information.

  5. Publish the JSON object as an MQTT message to a HiveMQ Cloud MQTT broker.

Console.WriteLine("Publishing message...");

while (true)
{

        var factory = new ModbusFactory();
        IModbusMaster master = factory.CreateMaster(modbus_client);

        // Read holding registers
        ushort[] registers = master.ReadHoldingRegisters(slaveId, startAddress, numRegisters);

        modbus_data[0] = registers[0];
        modbus_data[1] = registers[1];
        modbus_value = ModbusWordArrayToFloat(modbus_data);


    var msg = JsonSerializer.Serialize(
        new
        {
            temperature = modbus_value,
            device_type = "modbus",
        });
    //Publish MQTT messages
    var result = await client.PublishAsync("hivemqdemo/telemetry", msg, QualityOfService.AtLeastOnceDelivery).ConfigureAwait(false);

}

Lastly, we have a method that facilitates the conversion of the Modbus array to a float.

/************ ROUTINE TO CONVERT MODBUS 2 BYTES BIG ENDIAN DATA TO SWAPPED FLOAT  **********/
Single ModbusWordArrayToFloat(UInt16[] data)
{
if (data.Length != 2)
throw new ArgumentException("2 words of data required for a float");

    byte[] bData = new byte[4];

    byte[] w1 = BitConverter.GetBytes(data[0]);
    byte[] w2 = BitConverter.GetBytes(data[1]);

    //reverse words
    Array.Copy(w2, 0, bData, 0, 2);
    Array.Copy(w1, 0, bData, 2, 2);

    return BitConverter.ToSingle(bData, 0);
}

When your C# console application is executed, a successful connection to your MQTT broker should be established.

Connection to MQTT broker

To verify that your application is actively transmitting messages to the HiveMQ Cloud MQTT broker, you can employ an MQTT test tool like MQTT.fx. Subscribing to the HiveMQ Cloud MQTT broker will allow you to view the data being published.

Employing MQTT.fx to See the Messages

Conclusion

In conclusion, we’ve successfully created a gateway application that converts Modbus data to MQTT using C#. We invite you to download and explore the HiveMQ C# MQTT client further. Should you have any queries or face challenges, our Community Forum and GitHub repository are at your disposal for assistance.

Implementing your own Modbus to MQTT gateway can be a rewarding but complex task. If you’re seeking a more straightforward solution, you may want to consider HiveMQ Edge. HiveMQ Edge allows you to effortlessly connect your Modbus devices to MQTT infrastructure without the need for coding.

Kudzai Manditereza

Kudzai is a tech influencer and electronic engineer based in Germany. As a Developer Advocate at HiveMQ, he helps developers and architects adopt MQTT and HiveMQ for their IIoT projects. Kudzai runs a popular YouTube channel focused on IIoT and Smart Manufacturing technologies and he has been recognized as one of the Top 100 global influencers talking about Industry 4.0 online.

  • Kudzai Manditereza on LinkedIn
  • Contact Kudzai Manditereza via e-mail

Related content:

HiveMQ logo
Review HiveMQ on G2