Trigger on ESP8266 MQTT Device Not Working


I have a digital PIR sensor attached to a NodeMCU ESP8266 Dev. board (physical pin 2) with a Digital Sensor assigned to virtual pin 3.

Per request to convert to MQTT format, I have followed the instructions on converting my Arduino based ESP8266 to MQTT. Now the SMS trigger does not fire when the motion sensor goes HIGH. The trigger did work flawlessly on my same ESP8266 when configured as an Arduino. Looking at my Arduino IDE, it is confirming that Cayenne sees the virtual pin go HIGH and LOW. The code I am using is below, Any help/advice is greatly appreciated.

Arduino IDE Output
[1100331] Connection ok
[1100331] Publish: topic 1, channel 3, value 1, subkey d, key digital_sensor
[1110558] Connection ok
[1110558] Publish: topic 1, channel 3, value 0, subkey d, key digital_sensor


#include <CayenneMQTTESP8266.h>

const int SENSOR_PIN = D2;  // Physical pin motion sensor is connected to (the "D" is required for NODEMCU boards)
const int motionStateVPin = 3; // Virtual Pin for motion sensor widget

int motionCurrentState = 0;
int motionPreviousState = 0;

unsigned long previousMillis = -1;
unsigned long lastMillis = -1;

void setup() {
  Cayenne.begin(username, password, clientID, ssid, wifiPassword);

void loop() {

  //Publish data every 5 seconds (5000 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);

  // CHECK MOTION SENSOR FOR CHANGES AND UPDATE SENSOR WIDGET ------------------------------------------------

  if (motionCurrentState != motionPreviousState) {
  Cayenne.virtualWrite(motionStateVPin, motionCurrentState, "digital_sensor", "d");
  //--END MOTION SENSOR UPDATE--------------------------------------------------------------------------------

void checkSensor(int motionStateVPin) {
  unsigned long currentMillis = millis();
  // Check sensor data every 250 milliseconds
  if (currentMillis - previousMillis >= 250) {
  motionPreviousState = motionCurrentState;

  // Get the current motion sensor state...
  motionCurrentState = digitalRead(SENSOR_PIN);
  previousMillis = currentMillis;

// 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_LOG("Channel %u, value %s",, getValue.asString());
  //Process message here. If there is an error set an error message using getValue.setError(), e.g getValue.setError("Error message");


are you able to see the state change on dashboard and can you post the trigger screenshot.


Hi, yes, the widget in the dashboard reflects changes as it should. However, the trigger does not fire. After posting this item, I did some more testing and discovered a possible workaround. I changed the Cayenne.virtualWrite type from a “digital_sensor” type to a “digital_actuator” type. I then deleted the widget in the dashboard that was created automatically by Cayenne as a sensor widget type and manually created a custom widget of a button type to that channel. After deleting the initial Trigger I had set up for it, I created a new one that was linked to the new digital actuator widget and channel. The Trigger then fired! I will do more testing tomorrow…

If this continues to work, it will be doable for me. However, the ideal would be that any widget type would be functional with triggers. If not, it would be very helpful to the user community for there to be some documentation of what types are usable and not. Hope this into helps others… :slight_smile:

Here is screenshot of the trigger set up for the original digital_sensor channel/widget:


Thanks for posting your solution!