MQTT PIR Sensor question

Playing around with esp8266 and a PIR. Flashed it with this code found at the link below.

It says it publishes to outTopic and subscribes to inTopic. outTopic seems to be showing a state of Motion Detected.

I have added the following to configuration.yaml under sensor and binary sensor.

- platform: mqtt
    state_topic: "outTopic"

or

- platform: mqtt
    state_topic: "inTopic"

HA shows it across the top and when configured as a sensor it will say “Motion Detected” inside the sensor circle.

What I am trying to do is configure this as a stand alone PIR sensor to flip a switch on or off when motion is detected.

I’m dangerously close I think but I don’t know enough about MQTT to seal the deal here I think.

Any and all help appreciated.

I think this may be what you’re looking for.

EDIT: More info

Once you have the binary sensor setup you would then use an automation to get the state of the sensor and perform an action based on that state and potentially any conditions.

Edit 2:

Just noticed this [quote=“hagensieker, post:1, topic:13956”]
I have added the following to configuration.yaml under sensor and binary sensor.
[/quote]

Let me know what specifically you’re not sure about I’ll see if I can provide a better answer. :slight_smile:

Many Thanks, I’ve been looking at that for a bit but what I don’t understand is the topics are called inTopic and outTopic. Not sure how to determine the MQTT command for that.

Have you tried something like below? Unfortunately I don’t have any MQTT binary sensors so i can’t test.

binary_sensor:
  - platform: mqtt
    state_topic: "outTopic"
    name: "Motion Sensor 1"
    qos: 0
    payload_on: "Motion Detected"
    payload_off: "0" #<-- This one I'm not sure about.
    device_class: motion

Found this thread. Maybe something helpful in there.

Okay I’m getting a lot closer. I used your code above. When I walk past the sensor it turns from off to on in HA however it never seems to shut off.

On the MQTT server passing this turns it back to off:

mosquitto_pub -h 127.0.0.1 -t outTopic -m "0"

So I don’t quite understand why it doesn’t trigger itself off. With payload_off: “0”

Hi,
not sure, but i think i had the same problem.
The sketch sends only ‘on’, no ‘off’.
I use it without sensor, only the mqtt message as trigger.

  trigger:
    - platform: mqtt
      topic: "outTopic"
      payload: 'Motion Detected'

Maybe this helps.

Are you then able to use it with automation? Will it reset on it’s own?

So you use:

mosquitto_pub -h 127.0.0.1 -t outTopic -m "0"

and

mosquitto_pub -h 127.0.0.1 -t outTopic -m "Motion Detected"

as MQTT triggers? I’m not sure I understand how the PIR then trips a light and then shuts it off.

Here’s my automation.

- alias: motion_detection1
  initial_state: True
  hide_entity: False
  trigger:
    - platform: mqtt
      topic: "home/sensors/ESP8266_1/motion"
      payload: 'on'
  condition:
    condition: or
    conditions:
    - condition: template
      value_template: "{% if (states.sensor.esp8266_1_light.state | float < states.input_slider.motion_light1.state | int)
                          or is_state('input_slider.motion_light1', '0.0') %}true{% endif %}" 
    - condition: state
      entity_id: script.timer_off1
      state: 'on'
  action:
    - service: homeassistant.turn_on
      entity_id: script.timed_switch1

it calls a script, and this script calls a script to reset (from the examples page)

timed_switch1:
  sequence:
    # Cancel ev. old timers
    - service: script.turn_off
      entity_id: script.timer_off1
    # Set new timer
    - service: script.turn_on
      entity_id: script.timer_off1
    - condition: state
      entity_id: switch.milight3
      state: 'off'
    - service: switch.turn_on
      entity_id: switch.milight3

timer_off1:
  sequence:
    - delay: '00:00:{{ states.input_slider.motion_timer1.state | int }}'
    - service: switch.turn_off
      entity_id: switch.milight3
1 Like

Are you using the sketch you linked in your original post? If so, it doesn’t seem to send a ‘no motion detected anymore’ type of message. It only publishes when motion is initially detected.

Yes that is the sketch I’m using. How to overcome? Does HA have to reset the sensor somehow like the other poster VDRainer alluded to?

You need to load a different sketch to your ESP8266. All my PIRs are on arduinos using MySensors protocol, not MQTT so I cannot provide an example. Look at some of the other MQTT examples linked above or search the forum.

The sketch needs to publish the state of PIR to the MQTT server, generally a 0 or a 1 to indicate state.

Ok I found something that is working. This publishes to a topic called ESP-PIR-01/feeds/motion. Payload is ON and OFF

As a binary sensor in configuration.yaml

 - platform: mqtt
    state_topic: "ESP-PIR-01/feeds/motion"
    name: PIR Sensor
    payload_on: "ON"
    payload_off: "OFF"
    qos: 0
    device_class: motion

Arduino sketch. For sure nothing I wrote :slight_smile:

/*
 Basic ESP8266 MQTT PIR sketch

*/

#include <ESP8266WiFi.h>
#include "Adafruit_MQTT.h"
#include "Adafruit_MQTT_Client.h"

// Update these with values suitable for your network.

/************************* WiFi Access Point *********************************/

#define WLAN_SSID       "my router"           // Wi-Fi network name
#define WLAN_PASS       "password"           // Wi-Fi password

/**************************** MQTT Broker ************************************/

#define AIO_SERVER      "192.168.XX.X"  // MQTT broker IP
#define AIO_SERVERPORT  1883             // MQTT broker port
#define AIO_USERNAME    "user"           // MQTT username
#define AIO_KEY         "pass"           // MQTT password
#define AIO_CID         "ESP-PIR-01"     // MQTT client ID


// Start a counter for serial logging and set the initial value to no motion 
int counter = 0;
int previousReading = LOW;

WiFiClient client;
// Setup the MQTT client class by passing in the WiFi client and MQTT server and login details.
Adafruit_MQTT_Client mqtt(&client, AIO_SERVER, AIO_SERVERPORT, AIO_USERNAME, AIO_KEY, AIO_CID);

// Setup publish feeds - define topic name in parenthesis 
Adafruit_MQTT_Publish status  = Adafruit_MQTT_Publish(&mqtt, AIO_CID "/feeds/motion");
Adafruit_MQTT_Publish motion_topic  = Adafruit_MQTT_Publish(&mqtt, AIO_CID "/feeds/motion");

long lastMsg = 0;
char msg[50];
int value = 0;

/////////////////////////////
//VARS
//the time we give the sensor to calibrate (10-60 secs according to the datasheet)
int calibrationTime = 15;        

//the time when the sensor outputs a low impulse
long unsigned int lowIn;         

//the amount of milliseconds the sensor has to be low 
//before we assume all motion has stopped
long unsigned int pause = 5000;  

boolean lockLow = true;
boolean takeLowTime;  

int pirPin = 12;    // the digital pin connected to the PIR sensor's output
int ledPin = 16;    // the digital pin connected to built-in LED


void MQTT_connect();

void setup_wifi() {

  delay(10);
  // We start by connecting to a WiFi network
  Serial.println();
  Serial.print("Connecting to ");
  Serial.println(WLAN_SSID);

  WiFi.begin(WLAN_SSID, WLAN_PASS);
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }

  Serial.println("");
  Serial.println("WiFi connected");
  Serial.println("IP address: ");
  Serial.println(WiFi.localIP());
}

  // Setup a MQTT subscription
void callback(char* topic, byte* payload, unsigned int length) {
  Serial.print("Message arrived [");
  Serial.print(topic);
  Serial.print("] ");
  for (int i = 0; i < length; i++) {
    Serial.print((char)payload[i]);
  }
  Serial.println();

  // Switch on the LED if an 1 was received as first character
  if ((char)payload[0] == '1') {
    digitalWrite(BUILTIN_LED, HIGH);   // Turn the LED on (Note that LOW is the voltage level
    // but actually the LED is on; this is because
    // it is active low on the ESP-01)
  } else {
    digitalWrite(BUILTIN_LED, LOW);  // Turn the LED off by making the voltage HIGH
  }

}

void MQTT_connect() {
  int8_t ret;

  // Stop if already connected.
  if (mqtt.connected()) {
    return;
  }

  Serial.print("Connecting to MQTT... ");

  uint8_t retries = 3;
  while ((ret = mqtt.connect()) != 0) { // connect will return 0 for connected
       Serial.println(mqtt.connectErrorString(ret));
       Serial.println("Retrying MQTT connection in 5 seconds...");
       mqtt.disconnect();
       delay(5000);  // wait 5 seconds
       retries--;
       if (retries == 0) {
         // basically die and wait for WDT to reset me
         while (1);
       }
  }
  Serial.println("MQTT Connected!");
  status.publish("online");
}

void setup() {
  pinMode(BUILTIN_LED, OUTPUT);     // Initialize the BUILTIN_LED pin as an output
  Serial.begin(115200);
  setup_wifi();
  pinMode(pirPin, INPUT);
  pinMode(ledPin, OUTPUT);
  digitalWrite(pirPin, HIGH);

  //give the sensor some time to calibrate
  Serial.print("calibrating sensor ");
    for(int i = 0; i < calibrationTime; i++){
      Serial.print(".");
      delay(500);
      }
  Serial.println(" done");
  Serial.println("SENSOR ACTIVE");
  delay(50);


}

void loop() {
  // Ensure the connection to the MQTT server is alive (this will make the first
  // connection and automatically reconnect when disconnected).  See the MQTT_connect
  // function definition further below.
  MQTT_connect();

     if(digitalRead(pirPin) == HIGH){
       digitalWrite(ledPin, LOW);   //the led visualizes the sensors output pin state
       if(lockLow){  
         motion_topic.publish("ON");  
         //makes sure we wait for a transition to LOW before any further output is made:
         lockLow = false;            
         Serial.println("---");
         Serial.print("motion detected at ");
         Serial.print(millis()/1000);
         Serial.println(" sec"); 
         delay(50);
         }         
         takeLowTime = true;
       }

     if(digitalRead(pirPin) == LOW){       
       digitalWrite(ledPin, HIGH);  //the led visualizes the sensors output pin state

       if(takeLowTime){
        lowIn = millis();          //save the time of the transition from high to LOW
        takeLowTime = false;       //make sure this is only done at the start of a LOW phase
        }
       //if the sensor is low for more than the given pause, 
       //we assume that no more motion is going to happen
       if(!lockLow && millis() - lowIn > pause){  
           motion_topic.publish("OFF");  
           //makes sure this block of code is only executed again after 
           //a new motion sequence has been detected
           lockLow = true;                        
           Serial.print("motion ended at ");      //output
           Serial.print((millis() - pause)/1000);
           Serial.println(" sec");
           delay(50);
           }
       }

}
3 Likes

And here’s an MQTT client showing 10 On Off cycles. Binary sensor in HA follows along perfectly. Now for some automations.

hi @VDRainer I was trying to make this work for me so far I have done this but it does not work

automation

- alias: motion_detection1
  initial_state: True
  hide_entity: False
  trigger:
    - platform: mqtt
      topic: "outTopic"
      payload: 'motion detected'
  condition:
    condition: or
    conditions:
    - condition: template
      value_template: "{% if (states.sensor.esp8266_1_light.state | float < states.input_slider.motion_light1.state | int)
                          or is_state('input_slider.motion_light1', '0.0') %}true{% endif %}" 
    - condition: state
      entity_id: script.timer_off1
      state: 'on'
  action:
    - service: homeassistant.turn_on
      entity_id: script.timed_switch1

script

  timed_switch1:
    sequence:
    # Cancel ev. old timers
      - service: script.turn_off
        entity_id: script.timer_off1
    # Set new timer
      - service: script.turn_on
        entity_id: script.timer_off1
      - condition: state
        entity_id: light.night_light
        state: 'off'
      - service: light.turn_on
        entity_id: light.night_light
 

  timer_off1:
    sequence:
      - delay: '00:00:{{ states.input_slider.motion_timer1.state | int }}'
      - service: light.turn_off
        entity_id: light.night_light

Input_slider

motion_timer1:
  name: motion_timer1
  icon: mdi:timer
  initial: 1
  min: 0
  max: 20
  step: 1

i dont understand these lines in your code please help.

- condition: template
      value_template: "{% if (states.sensor.esp8266_1_light.state | float < states.input_slider.motion_light1.state | int)
                          or is_state('input_slider.motion_light1', '0.0') %}true{% endif %}" 

i’m i doing something wrong?

You can delete the condition, its a light sensor and a second input slider for density.
I think mqtt payload is case sensitiv, please check the payload that is sent in your arduino sketch.

Edit:
Sorry, you can delete the whole condition, so

- alias: motion_detection1
  initial_state: True
  hide_entity: False
  trigger:
    - platform: mqtt
      topic: "outTopic"
      payload: 'motion detected'
  action:
    - service: homeassistant.turn_on
      entity_id: script.timed_switch1

should work.

hi, will you help me with this condition, what I want it to do is when motion detected. IF night light is off AND Boolean if off trigger ACTION OR IF night light is on AND Boolean if on trigger ACTION so far I tried to this, if night light and boolean is OFF then it triggers action but when night light and boolean is ON it does not trigger.

condition:
    condition: and
    conditions:
      - condition: state
        entity_id: light.night_light
        state: 'off'
      - condition: state
        entity_id: input_boolean.nightlightonmotion
        state: 'off'
      - condition: time
        after: '18:00:00'  
        before: '15:00:00' 
      - condition: or
        conditions:
        - condition: state
          entity_id: light.night_light
          state: 'on'
        - condition: state
          entity_id: input_boolean.nightlightonmotion
          state: 'on'
        - condition: time
          after: '18:00:00'  
          before: '15:00:00'

Thank you
Works like a charm ! :smile:

I did need to change it a bit

WiFiClient client;
// Setup the MQTT client class by passing in the WiFi client and MQTT server and login details.
Adafruit_MQTT_Client mqtt(&client, AIO_SERVER, AIO_SERVERPORT, AIO_USERNAME, AIO_KEY, AIO_CID);

I removed the AIO_CID i was getting a error unkown client on broker side and unauthorized on arduino side