Sending MQTT messages within rate limits

Cayenne MQTT messages are currently rate limited to 60 messages each minute. If your client code sends messages at a higher rate it will have messages dropped and if it continues to send messages above the limit can run the risk of being disconnected or blocked.

In order to keep your client sending messages below the limits make sure you only send data at intervals. For embedded devices like Arduino this means you should not send data by just using a virtualWrite() call within the main loop(). Doing this will result in the function being called to send data every time through the loop() which can cause thousands of messages being sent each minute. In order to send messages at intervals there a few methods you can use:

  1. The built-in CAYENNE_OUT_DEFAULT() and CAYENNE_OUT() functions.
    This method is probably the simplest since these functions are designed to automatically run at intervals (currently every 15 seconds). To use them just declare them in your program and include a write function to send data to Cayenne:

    CAYENNE_OUT_DEFAULT()
    { 
       Cayenne.virtualWrite(0, millis());
    }
    

    CAYENNE_OUT_DEFAULT() can be used for most situations but if you want to use specific functions for different channels you can use CAYENNE_OUT(channel) functions instead.

  2. Manually calculating the interval to send data.
    This method allows you to determine the intervals yourself rather than using the set interval the CAYENNE_OUT functions use. To do this with Arduino you can just use the built-in millis() function to check the elapsed time and send data at the required interval:

    unsigned long lastMillis = 0;
    
    void setup() {
       Serial.begin(9600);
       Cayenne.begin(username, password, clientID);
    }
    
    void loop() {
       Cayenne.loop();
       
       //Publish data every 10 seconds (10000 milliseconds). Change this value to publish at a different interval.
       if(millis() - lastMillis > 10000) {
          lastMillis = millis();
          Cayenne.virtualWrite(0, lastMillis);
       }
    }
    
  3. A timer function.
    This method requires including a timer class in your code to run a function at the specified interval. For an example showing how to use a timer class see the SendDataOnTimer example sketch: https://github.com/myDevicesIoT/Cayenne-MQTT-Arduino/blob/master/examples/Basics/SendDataOnTimer/SendDataOnTimer.ino.

  4. Only send data when it changes.
    This method can be used for sensors that have values that do not change very often. In that case you can just send the data when it changes and prevent a lot of unnecessary messages. Though that may affect the graph display so if you plan to use graphing for the sensor you may want to use one of the other methods to send data at regular intervals. If you don’t care about regular data points though you can just keep track of the previous state of the sensor and update it when it changes:

    int previousState = -1;
    int currentState = -1;
    
    void setup()
    {
    	Serial.begin(9600);
    	Cayenne.begin(username, password, clientID);
    }
    
    void loop()
    {
    	Cayenne.loop();
    
    	// Check the sensor state and send data when it changes.
    	currentState = digitalRead(4);
    	if (currentState != previousState) {
    		Cayenne.virtualWrite(0, currentState);
    		previousState = currentState;
    	}
    }
    

When sending data make sure you keep it within the current limit of 60 messages per minute if you don’t want data dropped or your client disconnected. This means that if, for instance, you wanted to send data for 10 different sensors you should either send each sensor’s data separately at most each second or if you want to send them all at once make sure you only do it at most every 10 seconds.

The examples above are based on the Cayenne MQTT Arduino library but the same rate limits apply for any other clients, like the Cayenne MQTT Python library or any third party MQTT libraries used to connect to Cayenne. So if using those you should also make sure that data is sent at appropriate intervals.

6 Likes
Rate Limits Question
Use Cayenne at a one second pace
Speeds
Slow Updating of received serial data to Dashboard
I need helps
I need help and am new to Arduino
15 second delay
Esp8266 wifi and ds18b20
Problem in sending data to Cayenne using Uno with ESP8266-01
Number of devices in Cayenne
Arduino MQTT lots of bugs
MQTT data slow
Sensor limit
The output data from the device
Temperature measurement
Turn on LED with one button
Daily graph
Arduino cannot connect to Cayenne Cloud
Problem Dht22 + esp8266
Dashboard issues on Web and iOS
Long term plans - costs?
Platform costs or plans?
Open/Close Widget (gate remote control)
DS1302 Setup
Raspberry Pi update interval
ESP8266 + ds18b20+Display+ Problems
Dashboard connection timeouts
Trying understand mqtt comands
Cayenne Plugin for OPC DA Client
Arduino cannot connect to Cayenne Cloud
Sharp GP2Y1010AU0F - dust sensor
How can i include cayenne functionality in an sketch that already has WiFi running?
ESP8266 (Cayenne) - Problem with data of sensor
ESP8266 (Cayenne) - Problem with data of sensor
ESP32 LoRA SIM800 TinyGSM board connection to Cayenne
Relay control connected to the Arduino Mega
Cayenne - missing communication channels in browser
Triggers and Limits
Sensor values take too much to update
Simple issue with programming
30 seconds delay of sending data from arduino to daschbord cayenne
Communication
30 seconds delay of sending data from arduino to daschbord cayenne
Trigger settings don't save
Reading Data from Device in every 30 minutes
Simple Channel Input Question
Problem Graphing data
Problem Graphing data
Data logging - Day view
Cayenne Dashboard
Rate Limits Question
Cayenne refuse the conection?
Any possibility of sending more messages using MQTT
MQTT data slow
Ds18b20 issues
Display RPM using an IR proximity sensor
It is OK to use watchdog on mqtt arduino?
Dashboard Widgets Stop Updating After Two Days
Arduino uno and Shield W5100 events not working
SolArduino - Camping solar heater panels control with Arduino
Data storage period
How to use ClientID, Username, Password?

How can we check if our device has been disconnected or blocked?

1 Like

Right now you can only tell if it’s blocked if you are unable to connect to the server within the 10 minute period. That should only happen if you’ve disconnected/reconnected 50 times within 10 minutes. I believe the plan is to add some notification in the UI but I’m not sure when that will be implemented.

1 Like

Can’t we just add for example delay(10000); ?

Hi I ‘think’ you could in theory now on the MQTT, (on the old Arduino version I think it caused issue/instability with disconnects) but in reality even though it ‘could’ work now it would be a really bad idea - putting a 10 second delay in your main loop will slow you loop down terribly, as the delay will prevent the code moving forward. Learning how to use millis() is a really worthwhile thing, as once you ‘get it’ it will allow you to do so much more, trust me I spent months avoiding it and now I can use it, things are so much better.

The examples /methods given above are the best explanations I have seen so far.

2 Likes

Yes, @paulminize’s answer is correct. The last time I was playing with it if you go over 2 seconds you start to get disconnects from the server.

Hi
This has resolved the issue with monitoring a door sensor and sending an immediate state change to the Dashboard, but how can I push a button state change from the Dashboard to the Arduino to cause an immediate (under one second delay) activation of a relay?