Skip to content

MQTT over WebSocket

WebSocket Connection Details

Tendrl supports MQTT connections over WebSockets, providing an alternative connection method for web and browser-based applications.

Connection Specifications

  • Host: https://mqtt-ws.tendrl.com/ws
  • Port: 443 (TLS)
  • Protocol: WebSocket Secure (WSS)

Python WebSocket MQTT Client Example

import paho.mqtt.client as mqtt
import ssl
import json
import time
from datetime import datetime

class TendrlWebSocketMQTTClient:
    def __init__(self, api_key, debug=False):
        """
        Initialize Tendrl MQTT Client with WebSocket connection
        """
        # Fetch entity information from Tendrl API
        self.entity_info = self._fetch_entity_info(api_key)

        # Parse account and region from sub claim
        sub_parts = self.entity_info['sub'].split(':')
        if len(sub_parts) < 3:
            raise ValueError("Invalid sub claim format. Expected 'account:region:prefix'")

        self.account = sub_parts[0]
        self.region = sub_parts[1]

        # MQTT Connection Parameters
        self.client_id = self.entity_info['sub']
        self.username = self.entity_info['jti']
        self.password = api_key

        # WebSocket Broker Configuration
        self.mqtt_host = "mqtt-ws.tendrl.com"
        self.mqtt_port = 443
        self.mqtt_path = "/ws"

        # Topic Configuration
        self.publish_topic = f"{self.account}/{self.region}/{self.username}/publish"
        self.messages_topic = f"{self.account}/{self.region}/{self.username}/messages"

        # Create MQTT Client with WebSocket transport
        self.client = mqtt.Client(
            client_id=self.client_id, 
            transport="websockets"
        )

        # Configure WebSocket TLS
        self.client.tls_set(
            cert_reqs=ssl.CERT_REQUIRED,
            tls_version=ssl.PROTOCOL_TLS
        )

        # Set WebSocket connection parameters
        self.client.ws_set_options(
            path=self.mqtt_path,
            headers=None
        )

        # Set Credentials
        self.client.username_pw_set(username=self.username, password=self.password)

        # Set Callbacks
        self.client.on_connect = self._on_connect
        self.client.on_message = self._on_message

    def connect(self):
        """
        Establish WebSocket connection to MQTT broker
        """
        self.client.connect(self.mqtt_host, self.mqtt_port, keepalive=60)
        self.client.loop_start()

    def publish(self, data, tags=None, entity=None):
        """
        Publish a message to Tendrl MQTT topic

        :param data: Message payload
        :param tags: Optional list of tags
        :param entity: Optional entity identifier
        """
        message = {
            "msg_type": "publish",
            "data": data,
            "tags": tags or [],
            "timestamp": datetime.utcnow().isoformat() + "Z",
            "entity": entity
        }

        self.client.publish(self.publish_topic, json.dumps(message))

    def _on_connect(self, client, userdata, flags, rc):
        """
        Connection callback
        """
        if rc == 0:
            print("Connected successfully")
            # Subscribe to messages topic
            client.subscribe(self.messages_topic)
        else:
            print(f"Connection failed with code {rc}")

    def _on_message(self, client, userdata, message):
        """
        Message receive callback
        """
        try:
            msg = json.loads(message.payload.decode())

            # Example message processing
            if isinstance(msg.get('data'), dict):
                if 'temperature' in msg['data']:
                    self._process_temperature(msg)
        except Exception as e:
            print(f"Message processing error: {e}")

    def _process_temperature(self, message):
        """
        Example temperature message handler
        """
        temp = message['data']['temperature']
        print(f"Temperature reading: {temp}°C")

def main():
    # Replace with your actual Tendrl API key
    API_KEY = "your_tendrl_api_key"

    try:
        # Initialize and connect MQTT client via WebSocket
        mqtt_client = TendrlWebSocketMQTTClient(API_KEY)
        mqtt_client.connect()

        # Publish example sensor data
        mqtt_client.publish(
            data={"temperature": 25.5, "humidity": 60},
            tags=["sensor", "environment"],
            entity="smart_home:living_room:temp_sensor"
        )

        # Keep connection open to receive messages
        try:
            while True:
                time.sleep(1)
        except KeyboardInterrupt:
            print("Stopping MQTT WebSocket client...")

    except Exception as e:
        print(f"MQTT WebSocket Client Error: {e}")

if __name__ == "__main__":
    main()

WebSocket Specific Considerations

  • Transport Method: Uses WebSocket transport instead of traditional TCP
  • Full TLS Encryption: Secured via WSS (WebSocket Secure)
  • Browser Compatibility: Ideal for web and browser-based applications
  • Same Authentication: Uses identical authentication mechanism as TCP MQTT
  • Firewall Friendly: Works through standard HTTPS ports

Dependencies

Install required libraries:

pip install paho-mqtt requests

Choosing Between TCP and WebSocket

  • TCP MQTT:
  • Recommended for desktop and mobile applications
  • Lower overhead
  • Direct network connection

  • WebSocket MQTT:

  • Preferred for web browsers
  • Works through HTTP(S) proxies
  • Easier to implement in web environments

Browser JavaScript Example

For web applications, you can use libraries like paho-mqtt for JavaScript:

import { Client } from 'paho-mqtt';

const client = new Client(
    'mqtt-ws.tendrl.com', 
    443, 
    '/ws', 
    'client_id'
);

// Connection options
const options = {
    useSSL: true,
    userName: 'your_username',
    password: 'your_password',
    onSuccess: () => {
        console.log('Connected to Tendrl MQTT');
        client.subscribe('your/messages/topic');
    },
    onFailure: (error) => {
        console.error('Connection failed', error);
    }
};

// Connect
client.connect(options);

// Message handling
client.onMessageArrived = (message) => {
    const parsedMessage = JSON.parse(message.payloadString);
    // Example of a valid message structure
    const validMessage = {
        msg_type: "publish", // or "heartbeat"
        data: { temperature: 25.5 },
        tags: ["sensor"],
        timestamp: new Date().toISOString()
    };
    console.log('Received message:', parsedMessage);
};