Skip to main content

Overview

The Invernaderos API uses EMQX as the MQTT broker for real-time IoT communication. This guide shows you how to connect clients using popular MQTT libraries.
The broker supports MQTT v3.1.1 and v5.0 protocols with WebSocket (WSS) for browser clients.

Connection Parameters

Extract these values from the API configuration:
ParameterValueSource
Broker URLwss://your-broker:8084/mqttMqttConfig.kt:34
Port (MQTT)1883Standard MQTT
Port (WebSocket)8083EMQX Dashboard
Port (Secure WSS)8084Production
UsernameFrom credentialsMqttConfig.kt:37
PasswordFrom credentialsMqttConfig.kt:40
Client ID Prefixgreenhouse-apiMqttConfig.kt:43
Clean SessionfalsePersists session
Keep Alive60 secondsMqttConfig.kt:52
Auto ReconnecttrueMqttConfig.kt:55
QoS0 (default)MqttConfig.kt:70
In production, always use WSS (secure WebSocket) for MQTT connections. Never expose plain MQTT on public networks.

Setup by Library

1
Step 1: Choose Your Client Library
2
Select the appropriate library for your platform:
3
Eclipse Paho (Java/Kotlin)
The official MQTT client used by the Invernaderos API.
build.gradle.kts
dependencies {
    implementation("org.eclipse.paho:org.eclipse.paho.client.mqttv3:1.2.5")
    implementation("org.springframework.integration:spring-integration-mqtt:6.5.3")
}
Configuration Example:
MqttClientSetup.kt
import org.eclipse.paho.client.mqttv3.MqttClient
import org.eclipse.paho.client.mqttv3.MqttConnectOptions
import org.eclipse.paho.client.mqttv3.MqttMessage
import java.util.UUID

class GreenhouseMqttClient {
    private val brokerUrl = "wss://your-broker:8084/mqtt"
    private val clientId = "greenhouse-client-${UUID.randomUUID()}"
    private lateinit var client: MqttClient

    fun connect(username: String, password: String) {
        client = MqttClient(brokerUrl, clientId)

        val options = MqttConnectOptions().apply {
            userName = username
            setPassword(password.toCharArray())
            isCleanSession = false
            connectionTimeout = 10
            keepAliveInterval = 60
            isAutomaticReconnect = true
        }

        client.connect(options)
        println("Connected to MQTT broker: $brokerUrl")
    }

    fun subscribe(topic: String) {
        client.subscribe(topic) { topic, message ->
            println("Message received on $topic: ${String(message.payload)}")
        }
    }

    fun publish(topic: String, payload: String) {
        val message = MqttMessage(payload.toByteArray()).apply {
            qos = 0
            isRetained = false
        }
        client.publish(topic, message)
    }

    fun disconnect() {
        client.disconnect()
    }
}
Usage:
val client = GreenhouseMqttClient()
client.connect("your-username", "your-password")
client.subscribe("GREENHOUSE/SARA")
client.publish("GREENHOUSE/SARA", jsonPayload)
MQTT.js (JavaScript/Node.js)
Popular JavaScript MQTT client for web and Node.js.
npm install mqtt
Configuration Example:
mqttClient.js
const mqtt = require('mqtt');

const options = {
  clientId: `greenhouse-client-${Math.random().toString(16).slice(3)}`,
  username: 'your-username',
  password: 'your-password',
  clean: false,
  keepalive: 60,
  reconnectPeriod: 1000,
  connectTimeout: 10 * 1000,
  queueQoSZero: true
};

const client = mqtt.connect('wss://your-broker:8084/mqtt', options);

client.on('connect', () => {
  console.log('Connected to MQTT broker');
  
  // Subscribe to topics
  client.subscribe('GREENHOUSE/SARA', (err) => {
    if (!err) {
      console.log('Subscribed to GREENHOUSE/SARA');
    }
  });
});

client.on('message', (topic, message) => {
  console.log(`Message on ${topic}: ${message.toString()}`);
  const data = JSON.parse(message.toString());
  // Process sensor data
});

client.on('error', (error) => {
  console.error('Connection error:', error);
});

client.on('reconnect', () => {
  console.log('Reconnecting to broker...');
});

// Publish sensor data
function publishSensorData(tenantId, data) {
  const topic = `GREENHOUSE/${tenantId}`;
  const payload = JSON.stringify(data);
  
  client.publish(topic, payload, { qos: 0, retain: false }, (err) => {
    if (err) {
      console.error('Publish error:', err);
    } else {
      console.log(`Published to ${topic}`);
    }
  });
}
Browser Example (with Webpack/Vite):
import mqtt from 'mqtt/dist/mqtt.min';

const client = mqtt.connect('wss://your-broker:8084/mqtt', {
  clientId: `web-client-${Date.now()}`,
  username: 'your-username',
  password: 'your-password'
});

client.on('connect', () => {
  console.log('WebSocket MQTT connected');
  client.subscribe('GREENHOUSE/+'); // Subscribe to all tenants
});
Paho Python
Python MQTT client for automation scripts and IoT devices.
pip install paho-mqtt
Configuration Example:
mqtt_client.py
import paho.mqtt.client as mqtt
import json
import uuid

class GreenhouseMqttClient:
    def __init__(self, broker_host, broker_port, username, password):
        self.client_id = f"greenhouse-client-{uuid.uuid4()}"
        self.client = mqtt.Client(client_id=self.client_id, clean_session=False)
        
        # Set credentials
        self.client.username_pw_set(username, password)
        
        # Configure callbacks
        self.client.on_connect = self.on_connect
        self.client.on_message = self.on_message
        self.client.on_disconnect = self.on_disconnect
        
        # Connection settings
        self.broker_host = broker_host
        self.broker_port = broker_port

    def on_connect(self, client, userdata, flags, rc):
        if rc == 0:
            print(f"Connected to MQTT broker: {self.broker_host}:{self.broker_port}")
            # Subscribe to topics
            client.subscribe("GREENHOUSE/+", qos=0)
            print("Subscribed to GREENHOUSE/+ (all tenants)")
        else:
            print(f"Connection failed with code: {rc}")

    def on_message(self, client, userdata, msg):
        topic = msg.topic
        payload = msg.payload.decode('utf-8')
        print(f"Message on {topic}: {payload}")
        
        try:
            data = json.loads(payload)
            # Process sensor data
            self.process_sensor_data(data)
        except json.JSONDecodeError as e:
            print(f"Invalid JSON: {e}")

    def on_disconnect(self, client, userdata, rc):
        if rc != 0:
            print(f"Unexpected disconnect. Code: {rc}. Reconnecting...")

    def connect(self):
        try:
            self.client.connect(self.broker_host, self.broker_port, keepalive=60)
            self.client.loop_start()  # Start background thread
        except Exception as e:
            print(f"Connection error: {e}")

    def publish(self, tenant_id, sensor_data):
        topic = f"GREENHOUSE/{tenant_id}"
        payload = json.dumps(sensor_data)
        result = self.client.publish(topic, payload, qos=0, retain=False)
        
        if result.rc == mqtt.MQTT_ERR_SUCCESS:
            print(f"Published to {topic}")
        else:
            print(f"Publish failed: {result.rc}")

    def process_sensor_data(self, data):
        # Implement your data processing logic
        temp = data.get('TEMPERATURA INVERNADERO 01')
        humidity = data.get('HUMEDAD INVERNADERO 01')
        print(f"Temp: {temp}°C, Humidity: {humidity}%")

    def disconnect(self):
        self.client.loop_stop()
        self.client.disconnect()

# Usage
if __name__ == "__main__":
    client = GreenhouseMqttClient(
        broker_host="your-broker.com",
        broker_port=1883,  # Use 8883 for TLS
        username="your-username",
        password="your-password"
    )
    
    client.connect()
    
    # Publish sensor data
    sensor_data = {
        "TEMPERATURA INVERNADERO 01": 25.5,
        "HUMEDAD INVERNADERO 01": 65.2
    }
    client.publish("SARA", sensor_data)
    
    # Keep running
    try:
        while True:
            pass
    except KeyboardInterrupt:
        client.disconnect()
4
Step 2: Configure Connection Options
5
Match these settings from MqttConfig.kt:
6
Kotlin/Spring
val options = MqttConnectOptions().apply {
    serverURIs = arrayOf(brokerUrl)
    userName = username
    password = password.toCharArray()
    isCleanSession = false       // Persist session state
    connectionTimeout = 10       // 10 seconds
    keepAliveInterval = 60       // 60 seconds
    isAutomaticReconnect = true  // Auto-reconnect on disconnect
}
JavaScript
const options = {
  clean: false,
  keepalive: 60,
  reconnectPeriod: 1000,
  connectTimeout: 10000,
  username: 'your-username',
  password: 'your-password'
};
Python
client.username_pw_set(username, password)
client.connect(broker_host, broker_port, keepalive=60)
7
Step 3: Subscribe to Topics
8
The API subscribes to these topic patterns (MqttConfig.kt:140-146):
9
  • GREENHOUSE - Legacy topic (backward compatibility)
  • GREENHOUSE/+ - Multi-tenant pattern (e.g., GREENHOUSE/SARA)
  • greenhouse/+/sensors/# - Sensor-specific data
  • greenhouse/+/actuators/# - Actuator status updates
  • system/events/# - System-level events
  • 10
    Example Subscriptions:
    11
    // Subscribe to specific tenant
    client.subscribe("GREENHOUSE/SARA", 0)
    
    // Subscribe to all tenants (wildcard)
    client.subscribe("GREENHOUSE/+", 0)
    
    // Subscribe to sensor updates
    client.subscribe("greenhouse/+/sensors/#", 0)
    
    12
    Step 4: Test Connection
    13
    Verify your client can connect and receive messages:
    14
    mosquitto_pub/sub
    # Subscribe to all greenhouse topics
    mosquitto_sub -h your-broker -p 1883 \
      -u your-username -P your-password \
      -t "GREENHOUSE/#" -v
    
    # Publish test message
    mosquitto_pub -h your-broker -p 1883 \
      -u your-username -P your-password \
      -t "GREENHOUSE/SARA" \
      -m '{"TEMPERATURA INVERNADERO 01": 25.5}'
    
    MQTT Explorer (GUI)
    1. Download MQTT Explorer
    2. Create connection:
      • Host: your-broker
      • Port: 1883 (or 8883 for TLS)
      • Username: your-username
      • Password: your-password
    3. Subscribe to GREENHOUSE/# to see all messages
    4. Publish test message to GREENHOUSE/SARA

    Advanced Configuration

    TLS/SSL (Production)

    For secure connections, configure TLS:
    import javax.net.ssl.SSLContext
    
    val sslContext = SSLContext.getInstance("TLS")
    val options = MqttConnectOptions().apply {
        socketFactory = sslContext.socketFactory
        serverURIs = arrayOf("ssl://your-broker:8883")
    }
    

    Last Will and Testament (LWT)

    Configure a message sent when client disconnects unexpectedly:
    val options = MqttConnectOptions().apply {
        setWill(
            "system/events/disconnect",
            "Client disconnected".toByteArray(),
            1,  // QoS
            false  // Retain
        )
    }
    

    Connection Pooling

    For high-throughput applications, use connection pooling:
    val factory = DefaultMqttPahoClientFactory()
    factory.connectionOptions = options
    
    // Spring Integration automatically manages connection pool
    

    Troubleshooting

    Cause: Invalid username/passwordSolution:
    • Verify credentials in MqttUsers table (mqtt_users schema)
    • Check ACL permissions in MqttAcl table
    • Ensure user isActive = true
    Cause: Another client connected with same IDSolution:
    • Generate unique client ID: greenhouse-client-${UUID.randomUUID()}
    • Set clean_session = true to force disconnect previous client
    Cause: CORS policy or wrong portSolution:
    • Use WSS port 8084 for secure connections
    • Check EMQX dashboard CORS settings
    • Verify firewall allows outbound connections on port 8084
    Cause: Incorrect topic subscription or QoS mismatchSolution:
    • Verify topic pattern matches published topics
    • Use wildcards: + (single level), # (multi-level)
    • Check QoS level (API uses QoS 0 by default)

    Next Steps

    Message Format

    Learn the JSON payload structure with 22 sensor fields

    Authentication

    Configure MQTT user credentials and ACLs

    Build docs developers (and LLMs) love