Converting Cayenne Arduino LIbrary sketches to Cayenne MQTT Arduino

MQTT is an exciting technology that’s driving much of the current development of Cayenne and ultimately will be a large part of the future of our platform. At one point Cayenne only had the Cayenne Arduino Library for Arduino connectivity before implementing the Cayenne MQTT Arduino Library for use with our Bring Your Own Thing API.

The purpose of this post is to share a step-by-step way to convert your sketch code from the non-MQTT library to the MQTT one. The intended audience is someone less familiar/comfortable with coding who was attracted to Cayenne for ease of use reasons and might not know where to begin with the MQTT library/API.

Experienced users and developers may find it easier to re-factor their code on their own, but may still find this article useful as a general reference while doing so.

Esp8266 Users: This post applies to you as well if you were connecting your ESP8266 device through our original Arduino option. The only change would be to grab the Cayenne-MQTT-ESP8266 library instead of the Arduino one linked in step #1 below.

Step-by-step conversion

  1. Install the Cayenne MQTT Arduino library by launching the Arduino IDE, then going to Sketch > Include Library > Manage Libraries… and searching for CayenneMQTT. Click “Install” on the entry that appears.

  1. In the Arduino IDE, go to File > Examples > CayenneMQTT > Connections and choose the connection type you were using for your original Arduino sketch. We’ll use this connection sketch as a base for your transition.

  2. Carry over any non-Cayenne connectivity related #include or #define statements from the old sketch into the new one. For example, if transitioning from our legacy DS18B20 sketch, you’d bring across:

    #include <OneWire.h>
    #include <DallasTemperature.h>

    But not:

    #include <CayenneEthernet.h>

    (because this is already replaced with #include <CayenneMQTTEthernet.h> in the new connection sketch)

  3. If you have any #define virtual pin constants, (things like ‘V1’, ‘V9’), we’ll convert them to numeric MQTT Channels, since the MQTT connectivity does not use the concept of virtual pins.

    So something like:
    #define VIRTUAL_PIN V8
    Becomes:
    const int VIRTUAL_PIN = 8;

  4. Replace this legacy authentication section:

    // Cayenne authentication token. This should be obtained from the Cayenne Dashboard.
    char token[] = "AuthenticationToken";

    with this MQTT authentication section:
    // Cayenne authentication info. This should be obtained from the Cayenne Dashboard.
    char username[] = "MQTT_USERNAME";
    char password[] = "MQTT_PASSWORD";
    char clientID[] = "CLIENT_ID";

  5. Carry over any further code that sits outside of the setup() and loop() code blocks.

  6. In the setup() block replace:

    Cayenne.begin(token);
    With:
    Cayenne.begin(username, password, clientID);
    Then carry over any further code in the setup() block.

  7. In the loop() block replace:

    Cayenne.run();
    with:
    Cayenne.loop();

    Then carry over any further code in the loop() block. Add any carried over code into the if statement that maintains publishing timing in the new example sketch:

  8. If you have any CAYENNE_OUT statements, we’ll convert them to uniquely named stand-alone functions that can be called from the loop() function.

    For example, if your sketch has a block like:
    CAYENNE_OUT(VIRTUAL_PIN)
    {
    Your code here
    }

    Change it to:

    void newFunctionName(int VIRTUAL_PIN)
    {
    Your code here
    }

  9. The old system read CAYENNE_OUT functions automatically as part of Cayenne.run() , but the new one does not, so we need to actually call any CAYENNE_OUT functions we renamed in Step #8. You can do this by adding a single line in the body of the if statement in the loop().

    Using the function from Step #8 as an example, we’ll call it like this:
    newFunctionName(VIRTUAL_PIN);

  10. If you have any Cayenne.syncAll() or Cayenne.syncVirtual() functions, these are no longer necessary in the context of the MQTT library and can be removed. They will still compile if you leave them, but won’t do anything.

  11. At this point you should be ready add the device to your Cayenne dashboard. From there, go to Add New > Device/Widget > Bring Your Own Thing. On this page you’ll get the MQTT authentication info (Username, Password, Client ID) that you can use to fill in the section added to your sketch in step #4. You can also (optionally) name your device on this page.

  12. Upload your sketch and upon connection with our servers, the website will advance from the ‘Connect your device’ page to a blank dashboard.

With MQTT, any sensor data published from the sketch file will generate temporary widgets automatically, so there is no need to add them through the Add New menu on the Cayenne dashboard as you have done in the past!

TempWidget

To make the green temporary widgets permanent, just click the + icon in the upper-right corner of the widget.

Any actuators will need still need to be created on the Cayenne dashboard through Add New > Device/Widget > Custom Widgets. If the widget is set to an MQTT channel which matches the pin number of the actual device, there may be no need for additional code. For example, if you have a button widget set to MQTT channel 6 and your relay on physical pin 6, this should automatically be handled by the CAYENNE_IN_DEFAULT() function that is part of the example sketch we used. If you want to use different MQTT channels than pin numbers, or have additional code you’d like to add for a specific actuator, you can address them directly with a function for a specific channel (i.e. CAYENNE_IN(1) will be called when any actuator set to MQTT channel 1 is pressed on the Cayenne Dashboard).

3 Likes

Example sketch conversion

Following is an Cayenne Arduino sketch which drives a TSL2561 luminosity sensor, a DS18B20 temperature sensor, and a LED associated with a Cayenne button actuator widget.

Original Arduino Library Sketch:

#define CAYENNE_PRINT Serial  // Comment this out to disable prints and save space
#include <Wire.h>
#include <Adafruit_Sensor.h>
#include <Adafruit_TSL2561_U.h>
#include <OneWire.h>
#include <DallasTemperature.h>

// If you're not using the Ethernet W5100 shield, change this to match your connection type. See Communications examples.
#include <CayenneEthernet.h>

// Virtual Pin of the TSL2561 widget.
#define VIRTUAL_PIN V1
// Virtual Pin of the DS18B20 widget.
#define VIRTUAL_PINT V8

// Address used to read from the TSL2561. This is determined by the ADDR pin on the TSL2561.
// If ADDR is unconnected it means the sensor will use TSL2561_ADDR_FLOAT (0x39) for the address.  See the TSL2561 datasheet for more info.
const int address = TSL2561_ADDR_FLOAT;

//Physical pin of the DS18B20 sensor
const int tmpPin = 7;

Adafruit_TSL2561_Unified tsl = Adafruit_TSL2561_Unified(address, 12345);
OneWire oneWire(tmpPin);
DallasTemperature sensors(&oneWire);

// Cayenne authentication token. This should be obtained from the Cayenne Dashboard.
char token[] = "YOUR_CAYENNE_TOKEN";

void setup()
{
 Serial.begin(9600);
 Cayenne.begin(token);
 if (!tsl.begin())
 {
    CAYENNE_LOG("No TSL2561 detected");
 }

 tsl.enableAutoRange(true);
 /* Changing the integration time gives you better sensor resolution (402ms = 16-bit data) */
 tsl.setIntegrationTime(TSL2561_INTEGRATIONTIME_13MS);      /* fast but low resolution */
 // tsl.setIntegrationTime(TSL2561_INTEGRATIONTIME_101MS);  /* medium resolution and speed   */
 // tsl.setIntegrationTime(TSL2561_INTEGRATIONTIME_402MS);  /* 16-bit data but slowest conversions */
 sensors.begin();
}

void loop()
{
 Cayenne.run();
}

// This function is called when the Cayenne widget requests data for the Virtual Pin for the TSL2561 Sensor
CAYENNE_OUT(VIRTUAL_PIN)
{
 // Send the command to get luminosity.
 sensors_event_t event;
 tsl.getEvent(&event);

 if (event.light)
 {
    // Send the value to Cayenne in lux.
    Cayenne.luxWrite(VIRTUAL_PIN, event.light);
 }
 else
 {
    /* If event.light = 0 lux the sensor is probably saturated
    and no reliable data could be generated! */
    CAYENNE_LOG("No sensor data");
 }
}

// This function is called when the Cayenne widget requests data for the Virtual Pin for the DS18B20 Sensor
CAYENNE_OUT(VIRTUAL_PINT)
{
 // Send the command to get temperatures.
 sensors.requestTemperatures();
 // This command writes the temperature in Celsius to the Virtual Pin.
 Cayenne.celsiusWrite(VIRTUAL_PINT, sensors.getTempCByIndex(0));
 // To send the temperature in Fahrenheit use the corresponding code below.
 //Cayenne.fahrenheitWrite(VIRTUAL_PIN, sensors.getTempFByIndex(0));
}

Cayenne MQTT Arduino LIbrary sketch:

#define CAYENNE_DEBUG
#define CAYENNE_PRINT Serial
#include <CayenneMQTTEthernet.h>
#include <Wire.h>
#include <Adafruit_Sensor.h>
#include <Adafruit_TSL2561_U.h>
#include <OneWire.h>
#include <DallasTemperature.h>

// Cayenne authentication info. This should be obtained from the Cayenne Dashboard.
char username[] = "YOUR_MQTT_USERNAME";
char password[] = "YOUR_MQTT_PASSWORD";
char clientID[] = "YOUR_MQTT_CLIENT_ID";

unsigned long lastMillis = 0;

// Virtual Pin of the TSL2561 widget.
const int VIRTUAL_PIN = 1;
// Virtual Pin of the DS18B20 widget.
const int VIRTUAL_PINT = 8;

// Address used to read from the TSL2561. This is determined by the ADDR pin on the TSL2561.
// If ADDR is unconnected it means the sensor will use TSL2561_ADDR_FLOAT (0x39) for the address.  See the TSL2561 datasheet for more info.
const int address = TSL2561_ADDR_FLOAT;

//Physical pin of the DS18B20 sensor
const int tmpPin = 7;

Adafruit_TSL2561_Unified tsl = Adafruit_TSL2561_Unified(address, 12345);
OneWire oneWire(tmpPin);
DallasTemperature sensors(&oneWire);

void setup() {
   Serial.begin(9600);
   Cayenne.begin(username, password, clientID);
 if (!tsl.begin())
 {
    CAYENNE_LOG("No TSL2561 detected");
 }

 tsl.enableAutoRange(true);

 tsl.setIntegrationTime(TSL2561_INTEGRATIONTIME_13MS);     
 sensors.begin();
}

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();
       //Write data to Cayenne here. This example just sends the current uptime in milliseconds.
       Cayenne.virtualWrite(0, lastMillis);
    tslfunc(VIRTUAL_PIN);
    ds18b20func(VIRTUAL_PINT);
       //Some examples of other functions you can use to send data.
       //Cayenne.celsiusWrite(1, 22.0);
       //Cayenne.luxWrite(2, 700);
       //Cayenne.virtualWrite(3, 50, TYPE_PROXIMITY, UNIT_CENTIMETER);
   }
}

//Default function for processing actuator commands from the Cayenne Dashboard.
//You can also use functions for specific channels, e.g CAYENNE_IN(1) for channel 1 commands.
CAYENNE_IN_DEFAULT()
{
   CAYENNE_LOG("CAYENNE_IN_DEFAULT(%u) - %s, %s", request.channel, getValue.getId(), getValue.asString());
   //Process message here. If there is an error set an error message using getValue.setError(), e.g getValue.setError("Error message");
}

void ds18b20func(int VIRTUAL_PINT)
{
 // Send the command to get temperatures.
 sensors.requestTemperatures();
 // This command writes the temperature in Celsius to the Virtual Pin.
 Cayenne.celsiusWrite(VIRTUAL_PINT, sensors.getTempCByIndex(0));
 // To send the temperature in Fahrenheit use the corresponding code below.
 //Cayenne.fahrenheitWrite(VIRTUAL_PINT, sensors.getTempFByIndex(0));
}

// This function is called when the Cayenne widget requests data for the Virtual Pin for the TSL2561 Sensor
void tslfunc(int VIRTUAL_PIN)
{
 // Send the command to get luminosity.
 sensors_event_t event;
 tsl.getEvent(&event);

 if (event.light)
 {
    // Send the value to Cayenne in lux.
    Cayenne.luxWrite(VIRTUAL_PIN, event.light);
 }
 else
 {
    CAYENNE_LOG("No sensor data");
 }
}
4 Likes

So many issues with running out of space with conversion! All those bytes chewed up with the huge username/password/device id’s :frowning:The arduino library was great because it was “lite” and actually left some room for code to do things - my app doesnt do a lot and i’m having one hell of a time making it fit!
Just my 2 cents!

What device are you using and how much storage do you have? Generally including libraries is what takes up the most space. You could have a username that is 1024 characters and it would only take up 1KB so definitely not those couple strings taking up your space.

My device is Leonardo/W5200 based - even a simple “connection” example uses 27350 of 28672 max!

By the time I add a few extra virtual writes I’m out of space!
I managed to rewrite most of it to get it down to 30k and fit a 328 withg a bit of room but the Leonardo based devices I dont think its going to work at all
Will post code later

1 Like

Here is my pruned down code - numerous functions commented out that i still need to have function

Currently running at 28602 used of 28672

  • still need to read an analog
  • still need to read/write a value to EEPROM

This worked find with arduino cayenne library with debug ON and room to spare :frowning:
Any suggestions to make this fit would be great! or ways to modify the MQTT library as I don’t want to have to brick a heap of devices!!!

//MQTT Test - Leonardo

//#define CAYENNE_DEBUG         // Uncomment to show debug messages
//#define CAYENNE_PRINT Serial  // Comment this out to disable prints and save space
#include <CayenneMQTTEthernet.h>
//#include <avr/wdt.h>
//#include <avr/pgmspace.h>
//#include <SoftReset.h>
//#include <EEPROMAnything.h>

// Cayenne authentication info. This should be obtained from the Cayenne Dashboard.
char username[] = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
char password[] = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
char clientID[] = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";

#define SONAR_PWR   7

int     i = 0;
int     Sresult = 0;
int     tankLevel = 0;
int     lastLevel = 0;
int     rangePercentage = 0;

double  tankHeight = 240;

boolean stringComplete = false;
boolean rainRESET = false;
boolean sonarPresent = false;

unsigned long  prevMillis = 0;

void setup() {
  Serial1.begin(9600);
  delay(5000);

  pinMode(3,OUTPUT);                                                //RS485 Enable
  pinMode(SONAR_PWR,OUTPUT);
  
//  EEPROM_readAnything(1000,tankHeight);                                       //read current tank height setting from eeprom
 

  //SONAR DETECTION ROUTINE
    digitalWrite(SONAR_PWR,HIGH);
    delay(300);
    if (Serial1.find("Max")){
      sonarPresent = true;
      flushBuffer();
    }
    else {
      sonarPresent = false;
    }
    digitalWrite(SONAR_PWR,LOW);
  //
    
  // Start CAYENNE  
    Cayenne.begin(username, password, clientID);
  //

}


void loop() {
  Cayenne.loop();                                                // Runs main loop
}                                                               // END main loop

CAYENNE_OUT_DEFAULT()
{
  Cayenne.virtualWrite(8,rangePercentage);
  unsigned long currentMillis = millis();
  if (currentMillis - prevMillis >= 60000){
    Cayenne.virtualWrite(5, millis() / 60000);
    Cayenne.virtualWrite(0,sonarPresent);
//    float battVolts = (analogRead(0) * 0.0207);
//    Cayenne.virtualWrite(1,battVolts);
    if (sonarPresent == true){
      if (currentMillis - prevMillis >= 300000){
      sendLevel();  
      }
    }
    prevMillis = currentMillis;
  }
}

CAYENNE_IN(25){
  tankHeight = getValue.asDouble();
//  EEPROM_writeAnything(1000,tankHeight);
}

void sendLevel(){
   digitalWrite(SONAR_PWR,HIGH);
   delay(500);
   flushBuffer();
      //digitalWrite(A5,LOW);
      char SonarData[5];                                          //char array to read data into
      int Sindex = 0;
      flushBuffer();
      delay(100);
      while (stringComplete == false){
        if (Serial1.available()){
          char rByte = Serial1.read();                     //read serial input for "R" to mark start of data
          if(rByte == 'R'){
            while (Sindex < 4){                                  //read next three character for range from sensor
              if (Serial1.available()){
                SonarData[Sindex] = Serial1.read();
                Sindex++;                                       // Increment where to write next
              } 
            }
          SonarData[Sindex] = 0x00;                              //add a padding byte at end for atoi() function
          }
        rByte = 0;                                           //reset the rByte ready for next reading
        Sindex = 0;                                           // Reset index ready for next reading
        stringComplete = true;                               // Set completion of read to true
        Sresult = atoi(SonarData);                               // Changes string data into an integer for use
        }
      }
 
      if(stringComplete){
          stringComplete = false;                                //reset stringComplete ready for next reading
          int range = Sresult;
          if ((range == 0) || (range > 4999) || (range > (tankHeight*10))){            //  fix to filter out readings greater than tank height setting
          rangePercentage = 0;
          }
      else{
          range = range/10;
          range = range - 30;
          tankLevel = tankHeight - range;
          tankLevel = max(tankLevel,0);
          rangePercentage = map(tankLevel,0,tankHeight,0,100);
          }
          Cayenne.virtualWrite(8,rangePercentage);
          //digitalWrite(A5,HIGH);
          digitalWrite(SONAR_PWR,LOW);
      }
}


void flushBuffer(){                                          // flushes serial buffer to avoid buffer overflow
  if (Serial1.available()){
     while (Serial1.available()){
     Serial1.read();
     }
  }
}

Nothing? Looks like i’m bricking all these devices :frowning:

On the prev arduino library i could run full debug, verbose prints, 5 analog reads and a whole heapof other actions. New library I cant even get the bare minimum of functions required to work with all prints and debug OFF :frowning:
I agree the move to MQTT is good but its just alienated a whole range of arduino products!

@adam any ideas??

Would you be able to manually specify the IP for the device? If so, you could try basing your sketch on the ManualConnection example (Cayenne-MQTT-Arduino/ManualConnection.ino at master · myDevicesIoT/Cayenne-MQTT-Arduino · GitHub) which should save some space since it doesn’t need to use DHCP to get the device’s IP address.

Hi to all,
Needed for help to convert my sketch to mqtt sketch.Before upgrade to mgtt previously it worked well. Now I trying convert it by Converting Cayenne Arduino LIbrary sketches to Cayenne MQTT Arduino
but I geting error from ide
Old sketch:

#include <DallasTemperature.h>

#include <OneWire.h>

#include <CayenneEthernet.h>  

#define CAYENNE_PRINT Serial

// Virtual Pin of the DS18B20 widget.

#define VIRTUAL_PIN1 V1
#define VIRTUAL_PIN2 V2
#define VIRTUAL_PIN3 V3
#define VIRTUAL_PIN4 V4
#define VIRTUAL_PIN5 V5
#define VIRTUAL_PIN6 V6
#define VIRTUAL_PIN7 V7
#define VIRTUAL_PIN8 V8
const int tmpPin1 = 2;

OneWire oneWire1(tmpPin1);
OneWire oneWire2(tmpPin1);
OneWire oneWire3(tmpPin1);
OneWire oneWire4(tmpPin1);
OneWire oneWire5(tmpPin1);
OneWire oneWire6(tmpPin1);
OneWire oneWire7(tmpPin1);
OneWire oneWire8(tmpPin1);

DallasTemperature sensors1(&oneWire1);
DallasTemperature sensors2(&oneWire2);
DallasTemperature sensors3(&oneWire3);
DallasTemperature sensors4(&oneWire4);
DallasTemperature sensors5(&oneWire5);
DallasTemperature sensors6(&oneWire6);
DallasTemperature sensors7(&oneWire7);
DallasTemperature sensors8(&oneWire8);

char token[] = "jdpgXXX7";

void setup()
{
Serial.begin(9600);

Cayenne.begin(token);
sensors1.begin();
sensors2.begin();
sensors3.begin();
sensors4.begin();
sensors5.begin();
sensors6.begin();
sensors7.begin();
sensors8.begin();
}

unsigned long lastMillis = 0;

void loop() 
{
     //Needs to run every second or so to keep from missing things
    Cayenne.run();

    //Publish data every 10 seconds (10000 milliseconds). 
    if (millis() - lastMillis > 10000) 
    {
  lastMillis = millis();
  
        //do something
    }
}


// This function is called when the Cayenne widget requests data for the Virtual Pin.
CAYENNE_OUT(VIRTUAL_PIN1)
{
// Send the command to get temperatures.
sensors1.requestTemperatures();
// This command writes the temperature in Celsius to the Virtual Pin.
Cayenne.celsiusWrite(VIRTUAL_PIN1, sensors1.getTempCByIndex(0));
// To send the temperature in Fahrenheit use the corresponding code below.
//Cayenne.fahrenheitWrite(VIRTUAL_PIN, sensors.getTempFByIndex(0));
}
CAYENNE_OUT(VIRTUAL_PIN2)
{
// Send the command to get temperatures.
sensors2.requestTemperatures();
// This command writes the temperature in Celsius to the Virtual Pin.
Cayenne.celsiusWrite(VIRTUAL_PIN2, sensors2.getTempCByIndex(1));
// To send the temperature in Fahrenheit use the corresponding code below.
//Cayenne.fahrenheitWrite(VIRTUAL_PIN, sensors.getTempFByIndex(0));
}
CAYENNE_OUT(VIRTUAL_PIN3)
{
// Send the command to get temperatures.
sensors3.requestTemperatures();
// This command writes the temperature in Celsius to the Virtual Pin.
Cayenne.celsiusWrite(VIRTUAL_PIN3, sensors3.getTempCByIndex(2));
// To send the temperature in Fahrenheit use the corresponding code below.
//Cayenne.fahrenheitWrite(VIRTUAL_PIN, sensors.getTempFByIndex(0));
}
// This function is called when the Cayenne widget requests data for the Virtual Pin.
CAYENNE_OUT(VIRTUAL_PIN4)
{
// Send the command to get temperatures.
sensors4.requestTemperatures();
// This command writes the temperature in Celsius to the Virtual Pin.
Cayenne.celsiusWrite(VIRTUAL_PIN4, sensors4.getTempCByIndex(3));
// To send the temperature in Fahrenheit use the corresponding code below.
//Cayenne.fahrenheitWrite(VIRTUAL_PIN, sensors.getTempFByIndex(0));
}
CAYENNE_OUT(VIRTUAL_PIN5)
{
// Send the command to get temperatures.
sensors5.requestTemperatures();
// This command writes the temperature in Celsius to the Virtual Pin.
Cayenne.celsiusWrite(VIRTUAL_PIN5, sensors5.getTempCByIndex(4));
// To send the temperature in Fahrenheit use the corresponding code below.
//Cayenne.fahrenheitWrite(VIRTUAL_PIN, sensors.getTempFByIndex(0));
}
CAYENNE_OUT(VIRTUAL_PIN6)
{
// Send the command to get temperatures.
sensors6.requestTemperatures();
// This command writes the temperature in Celsius to the Virtual Pin.
Cayenne.celsiusWrite(VIRTUAL_PIN6, sensors6.getTempCByIndex(5));
// To send the temperature in Fahrenheit use the corresponding code below.
//Cayenne.fahrenheitWrite(VIRTUAL_PIN, sensors.getTempFByIndex(0));
}
// This function is called when the Cayenne widget requests data for the Virtual Pin.
CAYENNE_OUT(VIRTUAL_PIN7)
{
// Send the command to get temperatures.
sensors7.requestTemperatures();
// This command writes the temperature in Celsius to the Virtual Pin.
Cayenne.celsiusWrite(VIRTUAL_PIN7, sensors7.getTempCByIndex(6));
// To send the temperature in Fahrenheit use the corresponding code below.
//Cayenne.fahrenheitWrite(VIRTUAL_PIN, sensors.getTempFByIndex(0));
}
CAYENNE_OUT(VIRTUAL_PIN8)
{
// Send the command to get temperatures.
sensors8.requestTemperatures();
// This command writes the temperature in Celsius to the Virtual Pin.
Cayenne.celsiusWrite(VIRTUAL_PIN8, sensors8.getTempCByIndex(7));
// To send the temperature in Fahrenheit use the corresponding code below.
//Cayenne.fahrenheitWrite(VIRTUAL_PIN, sensors.getTempFByIndex(0));
}

New MQTT

#define CAYENNE_DEBUG
#define CAYENNE_PRINT Serial
#include <CayenneMQTTEthernet.h>
#include <Wire.h>
#include <OneWire.h>
#include <DallasTemperature.h>

// Cayenne authentication info. This should be obtained from the Cayenne Dashboard.
char username[] = "0273da50-358c-11e7-8bd2-aXXXXXXXX";
char password[] = "a48d79607f623fe9723aa8bcba402XXXXX8";
char clientID[] = "cefac6e0-1346-11e8-9beb-4dXXXXXXXXXXX";


// Virtual Pin of the DS18B20 widget.
const int VIRTUAL_PINT = 1;
const int VIRTUAL_PINT = 2;
const int VIRTUAL_PINT = 3;
const int VIRTUAL_PINT = 4;
const int VIRTUAL_PINT = 5;
const int VIRTUAL_PINT = 6;
const int VIRTUAL_PINT = 7;
const int VIRTUAL_PINT = 8;

//Physical pin of the DS18B20 sensor
const int tmpPin = 7;

OneWire oneWire1(tmpPin);
OneWire oneWire2(tmpPin);
OneWire oneWire3(tmpPin);
OneWire oneWire4(tmpPin);
OneWire oneWire5(tmpPin);
OneWire oneWire6(tmpPin);
OneWire oneWire7(tmpPin);
OneWire oneWire8(tmpPin);

DallasTemperature sensors1(&oneWire1);
DallasTemperature sensors2(&oneWire2);
DallasTemperature sensors3(&oneWire3);
DallasTemperature sensors4(&oneWire4);
DallasTemperature sensors5(&oneWire5);
DallasTemperature sensors6(&oneWire6);
DallasTemperature sensors7(&oneWire7);
DallasTemperature sensors8(&oneWire8);

void setup() {
   Serial.begin(9600);
   Cayenne.begin(username, password, clientID);

Cayenne.begin(token);
sensors1.begin();
sensors2.begin();
sensors3.begin();
sensors4.begin();
sensors5.begin();
sensors6.begin();
sensors7.begin();
sensors8.begin();
}


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();
       //Write data to Cayenne here. This example just sends the current uptime in milliseconds.
       Cayenne.virtualWrite(0, lastMillis);
        ds18b20func(VIRTUAL_PINT);
       //Some examples of other functions you can use to send data.
       //Cayenne.celsiusWrite(1, 22.0);      
   }
}

//Default function for processing actuator commands from the Cayenne Dashboard.
//You can also use functions for specific channels, e.g CAYENNE_IN(1) for channel 1 commands.
CAYENNE_IN_DEFAULT()
{
   CAYENNE_LOG("CAYENNE_IN_DEFAULT(%u) - %s, %s", request.channel, getValue.getId(), getValue.asString());
   //Process message here. If there is an error set an error message using getValue.setError(), e.g getValue.setError("Error message");
}

void ds18b20func(int VIRTUAL_PINT1)
{
 // Send the command to get temperatures.
 sensors1.requestTemperatures();
 // This command writes the temperature in Celsius to the Virtual Pin.
 Cayenne.celsiusWrite(VIRTUAL_PINT1, sensors1.getTempCByIndex(0));
 // To send the temperature in Fahrenheit use the corresponding code below.
 //Cayenne.fahrenheitWrite(VIRTUAL_PINT, sensors.getTempFByIndex(0));
}
void ds18b20func(int VIRTUAL_PINT2)
{
 // Send the command to get temperatures.
 sensors2.requestTemperatures();
 // This command writes the temperature in Celsius to the Virtual Pin.
 Cayenne.celsiusWrite(VIRTUAL_PINT2, sensors2.getTempCByIndex(0));
 // To send the temperature in Fahrenheit use the corresponding code below.
 //Cayenne.fahrenheitWrite(VIRTUAL_PINT, sensors.getTempFByIndex(0));
}
void ds18b20func(int VIRTUAL_PINT3)
{
 // Send the command to get temperatures.
 sensors3.requestTemperatures();
 // This command writes the temperature in Celsius to the Virtual Pin.
 Cayenne.celsiusWrite(VIRTUAL_PINT3, sensors3.getTempCByIndex(0));
 // To send the temperature in Fahrenheit use the corresponding code below.
 //Cayenne.fahrenheitWrite(VIRTUAL_PINT, sensors.getTempFByIndex(0));
}
void ds18b20func(int VIRTUAL_PINT4)
{
 // Send the command to get temperatures.
 sensors4.requestTemperatures();
 // This command writes the temperature in Celsius to the Virtual Pin.
 Cayenne.celsiusWrite(VIRTUAL_PINT4, sensors4.getTempCByIndex(0));
 // To send the temperature in Fahrenheit use the corresponding code below.
 //Cayenne.fahrenheitWrite(VIRTUAL_PINT, sensors.getTempFByIndex(0));
}
void ds18b20func(int VIRTUAL_PINT5)
{
 // Send the command to get temperatures.
 sensors5.requestTemperatures();
 // This command writes the temperature in Celsius to the Virtual Pin.
 Cayenne.celsiusWrite(VIRTUAL_PINT5, sensors5.getTempCByIndex(0));
 // To send the temperature in Fahrenheit use the corresponding code below.
 //Cayenne.fahrenheitWrite(VIRTUAL_PINT, sensors.getTempFByIndex(0));
}
void ds18b20func(int VIRTUAL_PINT6)
{
 // Send the command to get temperatures.
 sensors6.requestTemperatures();
 // This command writes the temperature in Celsius to the Virtual Pin.
 Cayenne.celsiusWrite(VIRTUAL_PINT6, sensors6.getTempCByIndex(0));
 // To send the temperature in Fahrenheit use the corresponding code below.
 //Cayenne.fahrenheitWrite(VIRTUAL_PINT, sensors.getTempFByIndex(0));
}
void ds18b20func(int VIRTUAL_PINT7)
{
 // Send the command to get temperatures.
 sensors7.requestTemperatures();
 // This command writes the temperature in Celsius to the Virtual Pin.
 Cayenne.celsiusWrite(VIRTUAL_PINT7, sensors7.getTempCByIndex(0));
 // To send the temperature in Fahrenheit use the corresponding code below.
 //Cayenne.fahrenheitWrite(VIRTUAL_PINT, sensors.getTempFByIndex(0));
}
void ds18b20func(int VIRTUAL_PINT8)
{
 // Send the command to get temperatures.
 sensors8.requestTemperatures();
 // This command writes the temperature in Celsius to the Virtual Pin.
 Cayenne.celsiusWrite(VIRTUAL_PINT8, sensors8.getTempCByIndex(0));
 // To send the temperature in Fahrenheit use the corresponding code below.
 //Cayenne.fahrenheitWrite(VIRTUAL_PINT, sensors.getTempFByIndex(0));
}
else
 {
    CAYENNE_LOG("No sensor data");
 }
}

Can You help me in this case?
Thanks,

@ramunas what error are you getting?

Hi shramiksalgaonkar,
Then I paste sketch in ide and push Veryfy I got error mesage:

Arduino: 1.8.5 (Windows 10), Board: “Arduino/Genuino Uno”

In file included from C:\Users\Ramunas\Documents\Arduino\libraries\CayenneMQTT\src/CayenneMQTTEthernetClient.h:21:0,

             from C:\Users\Ramunas\Documents\Arduino\libraries\CayenneMQTT\src/CayenneMQTTEthernet.h:25,

             from C:\Users\Ramunas\Documents\Arduino\naujausias_pagal_konvert\naujausias_pagal_konvert.ino:3:

C:\Users\Ramunas\Documents\Arduino\libraries\CayenneMQTT\src/CayenneArduinoMQTTClient.h: In member function ‘void CayenneArduinoMQTTClient::connect()’:

C:\Users\Ramunas\Documents\Arduino\libraries\CayenneMQTT\src/CayenneArduinoMQTTClient.h:58:63: warning: deprecated conversion from string constant to ‘char*’ [-Wwrite-strings]

if (!NetworkConnect(&_network, CAYENNE_DOMAIN, CAYENNE_PORT)) {

                                                           ^

C:\Users\Ramunas\Documents\Arduino\naujausias_pagal_konvert\naujausias_pagal_konvert.ino: At global scope:

naujausias_pagal_konvert:16: error: redefinition of ‘const int VIRTUAL_PINT’

const int VIRTUAL_PINT = 2;

       ^

C:\Users\Ramunas\Documents\Arduino\naujausias_pagal_konvert\naujausias_pagal_konvert.ino:15:11: note: ‘const int VIRTUAL_PINT’ previously defined here

const int VIRTUAL_PINT = 1;

       ^

naujausias_pagal_konvert:17: error: redefinition of ‘const int VIRTUAL_PINT’

const int VIRTUAL_PINT = 3;

       ^

C:\Users\Ramunas\Documents\Arduino\naujausias_pagal_konvert\naujausias_pagal_konvert.ino:15:11: note: ‘const int VIRTUAL_PINT’ previously defined here

const int VIRTUAL_PINT = 1;

       ^

naujausias_pagal_konvert:18: error: redefinition of ‘const int VIRTUAL_PINT’

const int VIRTUAL_PINT = 4;

       ^

C:\Users\Ramunas\Documents\Arduino\naujausias_pagal_konvert\naujausias_pagal_konvert.ino:15:11: note: ‘const int VIRTUAL_PINT’ previously defined here

const int VIRTUAL_PINT = 1;

       ^

naujausias_pagal_konvert:19: error: redefinition of ‘const int VIRTUAL_PINT’

const int VIRTUAL_PINT = 5;

       ^

C:\Users\Ramunas\Documents\Arduino\naujausias_pagal_konvert\naujausias_pagal_konvert.ino:15:11: note: ‘const int VIRTUAL_PINT’ previously defined here

const int VIRTUAL_PINT = 1;

       ^

naujausias_pagal_konvert:20: error: redefinition of ‘const int VIRTUAL_PINT’

const int VIRTUAL_PINT = 6;

       ^

C:\Users\Ramunas\Documents\Arduino\naujausias_pagal_konvert\naujausias_pagal_konvert.ino:15:11: note: ‘const int VIRTUAL_PINT’ previously defined here

const int VIRTUAL_PINT = 1;

       ^

naujausias_pagal_konvert:21: error: redefinition of ‘const int VIRTUAL_PINT’

const int VIRTUAL_PINT = 7;

       ^

C:\Users\Ramunas\Documents\Arduino\naujausias_pagal_konvert\naujausias_pagal_konvert.ino:15:11: note: ‘const int VIRTUAL_PINT’ previously defined here

const int VIRTUAL_PINT = 1;

       ^

naujausias_pagal_konvert:22: error: redefinition of ‘const int VIRTUAL_PINT’

const int VIRTUAL_PINT = 8;

       ^

C:\Users\Ramunas\Documents\Arduino\naujausias_pagal_konvert\naujausias_pagal_konvert.ino:15:11: note: ‘const int VIRTUAL_PINT’ previously defined here

const int VIRTUAL_PINT = 1;

       ^

C:\Users\Ramunas\Documents\Arduino\naujausias_pagal_konvert\naujausias_pagal_konvert.ino: In function ‘void setup()’:

naujausias_pagal_konvert:49: error: ‘token’ was not declared in this scope

Cayenne.begin(token);

           ^

C:\Users\Ramunas\Documents\Arduino\naujausias_pagal_konvert\naujausias_pagal_konvert.ino: In function ‘void loop()’:

naujausias_pagal_konvert:65: error: ‘lastMillis’ was not declared in this scope

if(millis() - lastMillis > 10000) {

              ^

C:\Users\Ramunas\Documents\Arduino\naujausias_pagal_konvert\naujausias_pagal_konvert.ino: In function ‘void ds18b20func(int)’:

naujausias_pagal_konvert:92: error: redefinition of ‘void ds18b20func(int)’

void ds18b20func(int VIRTUAL_PINT2)

  ^

C:\Users\Ramunas\Documents\Arduino\naujausias_pagal_konvert\naujausias_pagal_konvert.ino:83:6: note: ‘void ds18b20func(int)’ previously defined here

void ds18b20func(int VIRTUAL_PINT1)

  ^

C:\Users\Ramunas\Documents\Arduino\naujausias_pagal_konvert\naujausias_pagal_konvert.ino: In function ‘void ds18b20func(int)’:

naujausias_pagal_konvert:101: error: redefinition of ‘void ds18b20func(int)’

void ds18b20func(int VIRTUAL_PINT3)

  ^

C:\Users\Ramunas\Documents\Arduino\naujausias_pagal_konvert\naujausias_pagal_konvert.ino:83:6: note: ‘void ds18b20func(int)’ previously defined here

void ds18b20func(int VIRTUAL_PINT1)

  ^

C:\Users\Ramunas\Documents\Arduino\naujausias_pagal_konvert\naujausias_pagal_konvert.ino: In function ‘void ds18b20func(int)’:

naujausias_pagal_konvert:110: error: redefinition of ‘void ds18b20func(int)’

void ds18b20func(int VIRTUAL_PINT4)

  ^

C:\Users\Ramunas\Documents\Arduino\naujausias_pagal_konvert\naujausias_pagal_konvert.ino:83:6: note: ‘void ds18b20func(int)’ previously defined here

void ds18b20func(int VIRTUAL_PINT1)

  ^

C:\Users\Ramunas\Documents\Arduino\naujausias_pagal_konvert\naujausias_pagal_konvert.ino: In function ‘void ds18b20func(int)’:

naujausias_pagal_konvert:119: error: redefinition of ‘void ds18b20func(int)’

void ds18b20func(int VIRTUAL_PINT5)

  ^

C:\Users\Ramunas\Documents\Arduino\naujausias_pagal_konvert\naujausias_pagal_konvert.ino:83:6: note: ‘void ds18b20func(int)’ previously defined here

void ds18b20func(int VIRTUAL_PINT1)

  ^

C:\Users\Ramunas\Documents\Arduino\naujausias_pagal_konvert\naujausias_pagal_konvert.ino: In function ‘void ds18b20func(int)’:

naujausias_pagal_konvert:128: error: redefinition of ‘void ds18b20func(int)’

void ds18b20func(int VIRTUAL_PINT6)

  ^

C:\Users\Ramunas\Documents\Arduino\naujausias_pagal_konvert\naujausias_pagal_konvert.ino:83:6: note: ‘void ds18b20func(int)’ previously defined here

void ds18b20func(int VIRTUAL_PINT1)

  ^

C:\Users\Ramunas\Documents\Arduino\naujausias_pagal_konvert\naujausias_pagal_konvert.ino: In function ‘void ds18b20func(int)’:

naujausias_pagal_konvert:137: error: redefinition of ‘void ds18b20func(int)’

void ds18b20func(int VIRTUAL_PINT7)

  ^

C:\Users\Ramunas\Documents\Arduino\naujausias_pagal_konvert\naujausias_pagal_konvert.ino:83:6: note: ‘void ds18b20func(int)’ previously defined here

void ds18b20func(int VIRTUAL_PINT1)

  ^

C:\Users\Ramunas\Documents\Arduino\naujausias_pagal_konvert\naujausias_pagal_konvert.ino: In function ‘void ds18b20func(int)’:

naujausias_pagal_konvert:146: error: redefinition of ‘void ds18b20func(int)’

void ds18b20func(int VIRTUAL_PINT8)

  ^

C:\Users\Ramunas\Documents\Arduino\naujausias_pagal_konvert\naujausias_pagal_konvert.ino:83:6: note: ‘void ds18b20func(int)’ previously defined here

void ds18b20func(int VIRTUAL_PINT1)

  ^

C:\Users\Ramunas\Documents\Arduino\naujausias_pagal_konvert\naujausias_pagal_konvert.ino: At global scope:

naujausias_pagal_konvert:155: error: expected unqualified-id before ‘else’

else

^

exit status 1
redefinition of ‘const int VIRTUAL_PINT’

This report would have more information with
“Show verbose output during compilation”
option enabled in File → Preferences.

try this code, add your MQTT credential and upload it. see if you get any error and device is added to cayenne.

// This example shows how to connect to Cayenne using an Ethernet W5100 shield and send/receive sample data.

#define CAYENNE_DEBUG
#define CAYENNE_PRINT Serial
#include <CayenneMQTTEthernet.h>

// Cayenne authentication info. This should be obtained from the Cayenne Dashboard.
char username[] = "MQTT_USERNAME";
char password[] = "MQTT_PASSWORD";
char clientID[] = "CLIENT_ID";

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();
		//Write data to Cayenne here. This example just sends the current uptime in milliseconds.
		Cayenne.virtualWrite(0, lastMillis);
		//Some examples of other functions you can use to send data.
		//Cayenne.celsiusWrite(1, 22.0);
		//Cayenne.luxWrite(2, 700);
		//Cayenne.virtualWrite(3, 50, TYPE_PROXIMITY, UNIT_CENTIMETER);
	}
}

//Default function for processing actuator commands from the Cayenne Dashboard.
//You can also use functions for specific channels, e.g CAYENNE_IN(1) for channel 1 commands.
CAYENNE_IN_DEFAULT()
{
	CAYENNE_LOG("CAYENNE_IN_DEFAULT(%u) - %s, %s", request.channel, getValue.getId(), getValue.asString());
	//Process message here. If there is an error set an error message using getValue.setError(), e.g getValue.setError("Error message");
}

OK, this code I load in arduino without errors,device is online.
But it is empty. How I can do this to like old sketch with 8 sensors DS18B20?

in MQTT there is simple rule to follow:
example if you have a button connected to your arduino and want to read the status and show the status on you dashboard then first we will read the button state and store it in x,

        int x = digtalRead(btn_pin);

now the value of x can either be 1 or 0.
next we will send this value to cayenne using this:

  Cayenne.virtualWrite(1, x, "digital_sensor", "d");

where 1 is the channel, x is the value, digital sensor is the data type and d is the unit.
this will add a two state widget on your cayenne dashboard showing the 1 or 0 when button is pressed or released.
so the code looks like:

void loop() {
	Cayenne.loop();
        int x = digtalRead(btn_pin);

	if (millis() - lastMillis > 1000) {
		lastMillis = millis();
  Cayenne.virtualWrite(1, x, "digital_sensor", "d");
}

in your case:

void loop() {
	Cayenne.loop();
   sensors1.requestTemperatures();
        int x = sensors1.getTempCByIndex(0);
	if (millis() - lastMillis > 1000) {
		lastMillis = millis();
  Cayenne.virtualWrite(1, x);
}
1 Like

Hope he got it because i cant follow. I have been working on same project just want to add 2 sensors tho I can get one to work with cayenne mqtt sketch but dont know how to add the second sensor been tickering last couple days but no luck. Not a coder

@engeldl which sensor you are using and what error are you getting?

hello, a query, where are the variables “token, ssid and password” in the sketch?

@ricardo_ramos.l token was used for old cayenne library. now it is upgrade to cayenne MQTT library.