MQTT on Unity

In this post I explain how to install an MQTT library in Unity with SSL enabled.

In my current job, I’m using Unity to show the datas we are gathering from probes, I’m using MQTT as communication, in the first version, I didn’t use any security but in this iteration I have to secure the communication with SSL and username and password.

I found a library named M2MQTT, unfortunately this library was not working with the Mono version provided with Unity.

I found a way to use this library with some limitation, only the TLSv1 is usable and I’m not validating the certificate.

So here is what I had to do to get it working on Unity v.2017.1.0f3, I’m on MacOS Sierra 10.12.6.

Library build

Clone the git repo

1
git clone https://github.com/eclipse/paho.mqtt.m2mqtt

Open the project M2Mqtt.sln with Visual Studio Community or Visual Studio Code.

Define in the target platform of the M2Mqtt.net the .NET framework 4.0 as in this picture:

If you build the project you’ll have compilation error on the line 444 and 446 of the file MqttNetworkChannel.cs.

Just comment out the line and rebuild M2Mqtt.Net.

Depending the configuration of the Compiler (Debug or Release) you’ll found the library M2Mqtt.Net.dll under bin/Release/M2Mqtt.Net

Import on Unity

To import the DLL into Unity, just Drag and drop the M2Mqtt.Net.dll into the Assets folder in the Project tab of Unity.

If you click on the DLL and look at the inspector, it should looks like :

Code in Unity

It’s time to use MQTT in Unity, to do so, create a new Empty GameObject GameObject -> CreateEmpty

Named it for example MQTT.

On this GameObject, create a new component to add a new C# Script named for eg mqtt.cs.

In this script use the following properties:

1
2
3
4
5
6
7
8
9
10
11
12
//http://tdoc.info/blog/2014/11/10/mqtt_csharp.html
private MqttClient client;
// The connection information
public string brokerHostname = "ec2-11-111-11.us-west-2.compute.amazonaws.com";
public int brokerPort = 8883;
public string userName = "test";
public string password = "test";
public TextAsset certificate;
// listen on all the Topic
static string subTopic = "#";

Now, the inspector of the MQTT component should looks like:

And the initialization should be something like:

1
2
3
4
5
6
7
8
9
10
11
12
// Use this for initialization
void Start()
{
if (brokerHostname != null && userName != null && password != null)
{
Debug.Log("connecting to " + brokerHostname + ":" + brokerPort);
Connect();
client.MqttMsgPublishReceived += client_MqttMsgPublishReceived;
byte[] qosLevels = { MqttMsgBase.QOS_LEVEL_AT_LEAST_ONCE };
client.Subscribe(new string[] { subTopic }, qosLevels);
}
}

The connect method:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
private void Connect()
{
Debug.Log("about to connect on '" + brokerHostname + "'");
// Forming a certificate based on a TextAsset
X509Certificate cert = new X509Certificate();
cert.Import(certificate.bytes);
Debug.Log("Using the certificate '" + cert + "'");
client = new MqttClient(brokerHostname, brokerPort, true, cert, null, MqttSslProtocols.TLSv1_0, MyRemoteCertificateValidationCallback);
string clientId = Guid.NewGuid().ToString();
Debug.Log("About to connect using '" + userName + "' / '" + password + "'");
try
{
client.Connect(clientId, userName, password);
}
catch (Exception e)
{
Debug.LogError("Connection error: " + e);
}
}

As I do not want to validate the certificate, I’m using this certification method:

1
2
3
4
public static bool MyRemoteCertificateValidationCallback(System.Object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors)
{
return true;
}

The receive method:

1
2
3
4
5
void client_MqttMsgPublishReceived(object sender, MqttMsgPublishEventArgs e)
{
string msg = System.Text.Encoding.UTF8.GetString(e.Message);
Debug.Log ("Received message from " + e.Topic + " : " + msg);
}

And finally to publish message:

1
2
3
4
5
6
private void Publish(string _topic, string msg)
{
client.Publish(
_topic, Encoding.UTF8.GetBytes(msg),
MqttMsgBase.QOS_LEVEL_AT_MOST_ONCE, false);
}

If you run the project, in the console you should have:

Contents
  1. 1. Library build
  2. 2. Import on Unity
  3. 3. Code in Unity
|