MQTT Server

The Tinamous MQTT server provides support for status messages, measurements, alerts as well as pub/sub for your own messages. Status messages, measurements and alerts posted through the web site or REST API are published to the MQTT server and can be subscribed to.

Naturally MQTT doesn't support the full Tinamous API, their is no support for clearing messages, getting historical measurements/status posts or adding users, however it does provide a real time stream of messages, measurements and alerts which is ideal for many small connected devices and saves you having to learn the Tinamous REST API.

The server also does not support the full features of the MQTT protocol, please keep an eye on the Tinamous Trello page for future developments.

Getting started:

  • Use the same account url as you do with the web browser (e.g. use demo.tinamous.com for MQTT and https://demo.tinamous.com for web browser)
  • Port 1883 or 8883 for SSL (our SSL doesn't appear to work for many clients).
  • You can connect using a Tinamous user or device account.
  • Use username and password authentication. The username needs to include your account name as well.
    • e.g. if your Tinamous account is "MyAccount", such that you connect at https://MyAccount.Tinamous.com and your username is "UserName" you need to use "UserName.MyAccount" as your MQTT username
  • Use a different ClientId for different clients (this includes different instances of the same client if you run more than one instance.).
  • Topics are case sensitive.
  • Publishing to a /Tinamous/... topic will not fan out to subscribers as you would normally expect with MQTT. The message is taken in, processed and then pushed out via the appropriate Tinamous topics.
  • It's a very very very early version so may have issues, please let us know if you find problems.
  • Use QOS0 only, other Qos's may not work as expected (or at all!)
Using the Arduino MQTT Library from https://github.com/256dpi/arduino-mqtt
        // -----------------------------------------------------------------
        // Add the Arduino MQTT library from the library manager
        // See https://github.com/256dpi/arduino-mqtt for more details.
        // This example uses the WiFi101 library as well running on 
        // an Arduino MKR 1000
        // -----------------------------------------------------------------
        // Unsecure (port 1833)
        //WiFiClient networkClient; 
        // SSL based connection (port 8883)
        WiFiSSLClient networkClient; 
        // Specify the buffer size as the default is fairly small.
        MQTTClient mqttClient(2048); 

        void setup() {
          // Ensure your network is connected.
          WiFi.begin(ssid, pass);

          // replace 'demo' with your Tinamous account name.
          // Connect on port 1883 for UNSECURE connection
          // or use 8883 for SSL secured if your platform supports it.
          // Note the different WiFiClient needs to be used.
          mqttClient.begin(demo.tinamous.com, 8883, networkClient);

          // If you subscribe to to MQTT topics, add the message handler.
          mqttClient.onMessage(messageReceived);
          connect();
        }

        void connect() {
            // Connect as the device "OfficeFans" to the Tinamous account "demo" 
            // using the "OfficeFansPassword" as the password.
            // Username and password should have been set when adding the device through Tinamous devices page.
            if (mqttClient.connect("ClientId-23", "OfficeFans.demo", "OfficeFansPassword")) { 
                // Connected
                return;
            }

            // Handle connection failure.
            // Error code -10 (LWMQTT_CONNECTION_DENIED) is a username/password error.
            if (mqttClient.lastError() == LWMQTT_CONNECTION_DENIED) {
                Serial.println("Access denied. Check your username and password. Username should be 'DeviceName.AccountName' e.g. MySensor.MyHome"); 
            }
        }
                    

Topics:

  • Device / Usernames do not include the account name in topics. This is needed only for authentication.
  • Wildcards (# and +) are supported for subscriptions on all topics but not on publish.

Status Posts:

Publish
  • Publish to: /Tinamous/V1/Status
    • The data should be the message to post to the timeline (e.g. "Hello World")
    • Do not subscribe to this topic as status posts are not published directly on this.
    • When you publish the message it will not be broadcast to subscribers on the /Tinamous/V1/Status topic but under the sub topic of the user you are connected as (e.g. /Tinamous/V1/Status/Thermistor)
        // Publish status messages.
        unsigned long lastMessageSent = 0;

        void loop() {
            // Once a minute publish a message
            if (millis() - lastMessageSent > 60000) { 
                // Publish a "Hello World" message to the timamous status Timeline
                mqttClient.publish("/Tinamous/V1/Status", "Hello World"); 
                lastMessageSent = millis(); 
            }
        }
        
Subscribe
  • Subscribe to: /Tinamous/V1/Status[/UserName]
    • The UserName is just the device or users user-name, it does not need the account qualifier.
    • Subscribers to this topic will receive status posts published by the user/device specified.
    • You can use wildcards to get status posts sent by all users (e.g. /Tinamous/V1/Status/+).
  • Subscribe to: /Tinamous/V1/Status.To[/UserName]
    • The UserName is just the device or users user-name, it does not need the account qualifier.
    • Subscribers to this topic will receive status posts send to the user specified. (e.g. "@TestUser Hello", but not "Hello @TestUser")
    • You can use wildcards to get status posts mentioning all users (e.g. /Tinamous/V1/Status.To/+).
  • Subscribe to: /Tinamous/V1/Status.Mentions[/UserNane]
    • The UserName is just the device or users user-name, it does not need the account qualifier.
    • Subscribers to this topic will receive status posts that mention the user specified, this includes those send directly to the user (e.g. "@TestUser Hello" and "Hello @TestUser")
    • You can use wildcards to get status posts from all users (e.g. /Tinamous/V1/Status.Mentions/+).
        // Receive status post messages sent To this deivce.
        // To send a message, from the Tinamous Timeline page.
        // enter a message in the "Post a status message... "text box.
        // e.g. "@OfficeFans Turn on the fans!"
        void setup() {
            // ... WiFi and MQTT connect here....
            // Be sure to handle onMessage
            mqttClient.onMessage(messageReceived);
            
            // Subscrie to the status to for messages sent 
            // directly To the device "OfficeFans" (i.e. this device)
            mqttClient.subscribe("/Tinamous/V1/Status.To/OfficeFans"); 
        }

        void messageReceived(String &topic, String &payload) { 
          Serial.println("Message from Tinamous on topic: " + topic + " - " + payload); 
        } 
        

Measurements:

You can publish measurements in different ways, either as a simple measurement value to the appropriate device/channel/field or as a json object with multiple fields.

Publish
  • Publish to: /Tinamous/V1/Measurements
    • Legacy only. Don't use this for new clients. Please use the SenML or Json topics.
    • use a Json object representation of the measurements, this may contain up-to 12 fields and should be formatted as per the REST Measurements API.
  • Publish to: /Tinamous/V1/Measurements/[Channel]/[FieldName]
    • Where channel is typically 0, but may be any user set value as per the api
    • and FieldName is the name of the field as created in the device settings.
    • e.g. /Tinamous/V1/Measurements/0/Temperature
    • The value should be a UTF8 encoded string representation of the value.
  • Publish to: /Tinamous/V1/Measurements/SenML
    • Publish measurements in the SenML Format.
    • n - Field Name.
    • v - Numeric value.
    • sv - String value.
    • bv - Boolean value.
    • t - time (and bt in top level) - this is currently ignored and measurements are time stamped with the time they are received..
        void publishMeasurements() {
            // Make sure that the client was set-up with a decent size buffer
            // as the SenML message can overrin the default 128 bytes quickly.

            // And do one as senml...
            String senml = "{'e':[";
            // First sensor
            senml = senml + "{'n':'Light',";
            senml = senml + "'v':100,";
            senml = senml + "'u':'lux'},";
            // Second sensor
            senml = senml + "{'n':'VOC',";
            senml = senml + "'v':'1001',";
            senml = senml + "'u':'ppm'}";
            senml = senml +  "]}";

            // Senml should look like...
            {'e':[{'n':'Light','v':100,'u':'lux'},{'n':'VOC','v':'1001','u':'ppm'}]}
            mqttClient.publish("/Tinamous/V1/Measurements/SenML", senml); 
        }
        
  • Publish to: /Tinamous/V1/Measurements/Json
    • use a Json object representation of the measurements, fields names are taken from the key and values from the value.
    • Measurements are time stamped with the time they are received..
        void publishMeasurements() {
            // Make sure that the client was set-up with a decent size buffer
            // as the message can overrin the default 128 bytes quickly.

            // Plain old JSON.
            String json = "{'Temperature':";
            json = json + "23.5";
            json = json + ",'Humidity':";
            json = json + "'60'";
            json = json +  "}";

            // json should look like...
            {'Temperature':23.5,'Humidity':'60'}
             mqttClient.publish("/Tinamous/V1/Measurements/Json", json); 
        }
        
Subscribe
  • Subscribe to: /Tinamous/V1/Measurements/[device name]/FieldName
    • Where device User/Login Name is the user or device publishing measurements
    • FieldName is the friendly name configured for the field (Defaults to Field 1, but settable for devices, e.g. Temperature)
    • No channel information is included so if you have the same field name on different channels this will get mixed up
  • Subscribe to: /Tinamous/V1/Measurements/[device name]
    • Rich Json objects of the measurements are published to this topic.

Alerts:

Alerts support 3 levels, "Critical", "Error" and "Warning". With the alert a message is also added.

Publish
  • Publish to: /Tinamous/V1/Alerts/[level]
    • These are not re-published to subscribers on this topic.
    • The message should be the message text to go with the alert (e.g. "Fridge power fail")
Subscribe
  • Subscribe to: /Tinamous/V1/Alerts/[device or username]/[level]
    • Use wildcards to get alerts of certain levels from any user. e.g. /Tinamous/V1/Alerts/+/Critical will capture all Critical alerts from any user.
    • The message will be the simple message text entered for the alert.
  • Subscribe to: /Tinamous/V1/Alerts/[device or username]
    • This publishes a rich json object describing the alert in more details.

Commands:

Commands are instructions to devices to do something, i.e. switch a fan on.

Subscribe
  • Subscribe to: /Tinamous/V1/Commands/[device or username]/[command]/[sub-command]/[sub-command]
    • Subcommands are optional but may be useful (e.g. .../Fans/On and .../Fans/Off).
    • The payload can contain what you wish, e.g. the fan number or the speed desired or something else.
    • No acknowledgement of receipt of execution of the command is supported
    • See Commands for more information.
    • You shouldn't subscribe to a different devices commands (that's just rude).

Your Own Topics:

  • You can publish/subscribe to any topic you wish, however the /Tinamous namespace should not be used as more topics will be added.
  • You will only see published messages from users in your account.