Controlling Yoctopuce modules from MQTT

Controlling Yoctopuce modules from MQTT

YoctoHubs can automatically publish sensor values on a MQTT broker, as we illustrated in a previous post on this topic. However, for scalability and security reasons, YoctoHubs cannot use MQTT messages to drive connected modules. There are however circumstances where it might be desirable to integrade Yoctopuce command devices in an existing MQTT architecture. In this case, it is enough to use a small gateway between the MQTT protocol and the Yoctopuce modules. This is what we are going to do this week.

To represent an existing MQTT infrastructure, we used a Raspberry Pi 3 on which we installed the mosquitto MQTT broker. To send MQTT messages, we used the IoT MQTT Dashboard running on an Android smart phone. While perhaps not very realistic, this configuration is very easy to set up and allows us to illustrate the use of each component.

The aim is to add to this architecture a temperature sensor, a relay controlling a fan, and two signaling leds. To do so, we are going to use a Yocto-Temperature, a Yocto-PowerRelay,and a Yocto-Color-V2, everything being connected to a YoctoHub-Ethernet.

The architecture of our system
The architecture of our system

We want to publish the ambient temperature on MQTT under the "temperature" topic. The fan must subscribe to the "fan_control" topic which can take the "on" and "off" values. The leds must subscribe to the "leds_control" topic and the value passed is the RGB value in the #000000 format.

A Java MQTT gateway

We are going to write our gateway in Java because in this way it can be used both as an application and as a WebSocket callback.

The Java application must transmit to the broker the temperature measured by the Yocto-Temperature, listen to the "fan_control" and "leds_control" topics, and send the appropriate commands to the Yocto-Relay and to the Yocto-Color-V2. This Java gateway must simply "translate" the MQTT messages into Yoctopuce commands. The control of the system and the temperature display are managed by the Android application.

To begin, we must add the Paho Java library to our project. As the library is available under Maven, we only need to add the following code to the pom.xml file:


We must also add the Yoctopuce library as described in this previous post.

Setting the connections up

To begin, we must set up the connection with the YoctoHub:

private YAPIContext _yctx;
private String _broker_url;
private MqttClient _sampleClient;
private YRelay _yrelay;
private ArrayList&gt;YColorLed&lt; _yleds = new ArrayList&gt;&lt;();

  // Constructor used for traditional application
  public MQTTBridge(String hub_url, String broker_url) throws YAPI_Exception
    _yctx = new YAPIContext();
    _broker_url = broker_url;

Then, set up the connection with the MQTT broker using the MqttClient class of the Paho library.

  public void run()
    MemoryPersistence persistence = new MemoryPersistence();
    _sampleClient = new MqttClient(_broker_url, "MQTTBridge", persistence);
    MqttConnectOptions connOpts = new MqttConnectOptions();
    System.out.println("Connecting to broker: " + _broker_url);

Subscribing to the "fan_control" and "leds_control" topics

We must subscribe to the "fan_control" and "leds_control" topics and store the references of the YRelay and YColorLeds objects enabling us to control the relay and the leds.

    // subscribes to events from MQTT

    _yrelay = YRelay.FirstRelayInContext(_yctx);
    YColorLed colorLed = YColorLed.FirstColorLedInContext(_yctx);
    while (colorLed != null) {
        colorLed = colorLed.nextColorLed();

Then, we must deal with the incoming MQTT messages in the messsageArrived method. For the "fan_control" topic, we modify the position of the Yocto-PowerRelay with the set_output() method. For the "leds_control" topic, we decode the color and we apply it to all the leds with the set_rgbColor() method.

  public void messageArrived(String topic, MqttMessage mqttMessage)
    byte[] payload = mqttMessage.getPayload();
    String message = new String(payload);
    try {
      switch (topic) {
        case "fan_control":
          int output;
          if ("on".equalsIgnoreCase(message)) {
              output = YRelay.OUTPUT_ON;
          } else {
              output = YRelay.OUTPUT_OFF;
        case "led_test":
          int color = Integer.parseInt(message.replaceFirst("#", ""), 16);
          for (YColorLed colorLed  : _leds){
   } catch (YAPI_Exception e) {

Publishing the temperature

We could be tempted to use and infinite loop and call the get_currentValues() method of the temperature sensor, but it is much more efficient to register a callback each time the sensor value changes.

    YTemperature temperature = YTemperature.FirstTemperatureInContext(_yctx);
    while (true) {

The callback directly receives the new temperature value as a character string and we must simply publish this new value for the "temperature" topic.

    public void yNewValue(YTemperature temperature, String currentValue)
        MqttMessage message = new MqttMessage(currentValue.getBytes());
        try {
            _sampleClient.publish("temperature", message);
        } catch (MqttException e) {

Local network vs. cloud

To be able to use this gateway, we must simply run it on a machine which has access both to the MQTT broker and to the YoctoHub. The simplest location is to put it on the machine hosting the MQTT broker, that is the Raspberry Pi.

This solution works because in our example the MQTT broker and the YoctoHub are connected to the same local network. However, if the MQTT broker is in the cloud and the YoctoHub is behind a DSL router, or on a cellular network, this solution doesn't work anymore. The machine hosting the MQTT broker cannot connect itself directly to the YoctoHub because the router or the cellular network blocks incoming connections.

There are ways to work around this issue, such as opening a port on the DSL router, using a VPN, or hosting the gateway on another machine located on the same network as the YoctoHub. But there is another solution: to convert our Java application into a WebSocket callback.

The gateway as a WebSocket callback

Using a WebSocket callback solves our problem because the connection is set up by the YoctoHub and not by the Java gateway anymore. And if our YoctoHub can connect itself on the Internet, it can connect itself to the gateway as well.

Callbacks work even behind a NAT filter
Callbacks work even behind a NAT filter

If you don't have a Java application server, most of the work is to install an application server such as Tomcat or GlassFish. When this step is done, you must simply create a WebSocket endpoint instantiating the gateway and running the main loop in a thread.

public class YServerWebsocket

    public void onOpen(Session session)
        // registers the YoctoHub/VirtualHub that starts the connection
        try {
          MQTTBridge bridge = new MQTTBridge(session,
        } catch (YAPI_Exception e) {
        Thread thread = new Thread(bridge);


The only modification you must bring to the Java code is to add a constructor taking as parameter the WebSocket session created by the application server instead of the YoctoHub URL. The call to the RegisterHub method is therefore replaced by a call to the PreregisterHubWebSocketCallback() method taking as parameter the WebSocket session. The rest of the code doesn't change.

  public MQTTBridge(Session session, String broker_url) throws YAPI_Exception

    _yctx = new YAPIContext();
  _broker_url = broker_url;

We then only need to configure the YoctoHub to connect itself to our WebSocket endpoint.


As you can see, controlling Yoctopuce modules from a MQTT architecture requires to write a gateway, but the code is relatively simple and short. If you are not confident with Java, you can always start from this example and modify it for your purposes.

The complete code of these two examples is available on our GitHub account:

We also shot a small demo video:


Add a comment No comment yet
Back to blog

Yoctopuce, get your stuff connected.