MQTT question

Hi!

I'm trying to use MQTT to send 2 states, when there is activity from a PIR (my front door) and then after one minute I'm trying to send a message to tell that nobody is at the front door, so far I'm successful to send the message that the PIR had triggered but then after that the other message can't be broadcast...here is my code

Any cue would be really appreciated... I've tryed a bunch of things and I can't figure it out...

#include <ESP8266WiFi.h>
#include <PubSubClient.h>

//////////////////////////
// Hardware Definitions //
//////////////////////////
#define PIR_DOUT 4   // PIR digital output on D2
#define LED_PIN  5  // LED to illuminate on motion
#define RELAY_PIN_1 13  //pin for relay #1 (Smoke Machine)

#define PRINT_TIME 100 // Rate of serial printouts
unsigned long lastPrint = 0; // Keep track of last serial out

boolean trigger = false; // boolean to keep trigger

//MQTT settings
char message_buff[100];
int motionStatus = 0;
char* presence[]={"nobody...","Halloween!"};

const char *ssid =  "my network";   // cannot be longer than 32 characters!
const char *pass =  "my password";  

// Update these with values suitable for your network.
IPAddress server(10, 0, 1, 101);

WiFiClient wclient;
PubSubClient client(wclient, server);

// Callback function
void callback(const MQTT::Publish& pub) {
  // In order to republish this payload, a copy must be made
  // as the orignal payload buffer will be overwritten whilst
  // constructing the PUBLISH packet.

  // Copy the payload to a new message
  MQTT::Publish newpub("outTopic", pub.payload(), pub.payload_len());
  client.publish(newpub); 
}

void setup() 
{
  Serial.begin(115200);  // Serial is used to view Analog out
  // Analog and digital pins should both be set as inputs:
 // pinMode(PIR_AOUT, INPUT);
  pinMode(PIR_DOUT, INPUT);
  pinMode(RELAY_PIN_1, OUTPUT);
  digitalWrite(RELAY_PIN_1, LOW);

  // Configure the motion indicator LED pin as an output
  pinMode(LED_PIN, OUTPUT);
  digitalWrite(LED_PIN, LOW); // Turn the LED off
}

void loop() 
{
  if (WiFi.status() != WL_CONNECTED) {
    Serial.print("Connecting to ");
    Serial.print(ssid);
    Serial.println("...");
    WiFi.begin(ssid, pass);

    if (WiFi.waitForConnectResult() != WL_CONNECTED)
      return;
    Serial.println("WiFi connected");
  }

if (WiFi.status() == WL_CONNECTED) {
    if (!client.connected()) {
      if (client.connect("arduinoClient")) {
  client.set_callback(callback);

      }
    }

  // Read OUT pin, and set onboard LED to mirror output
  readDigitalValue(); 
  
if (client.connected())
      client.loop();
}
}
void readDigitalValue()
{
  // The OpenPIR's digital output is active high
  int motionStatus = digitalRead(PIR_DOUT);

  // If motion is detected, turn the onboard LED on:
  if (motionStatus == HIGH){
    motionStatus = 1;
    //Serial.print(motionStatus);
    digitalWrite(LED_PIN, HIGH);
    digitalWrite(RELAY_PIN_1, HIGH);
    //Sending value to OpenHab with MQTT
   Serial.print("The value of motionStatus is: ");
   Serial.println(motionStatus);
   Serial.print("Sending PIR state ");
   Serial.println(presence[motionStatus]);
   String pubString = String(presence[motionStatus]);
   pubString.toCharArray(message_buff, pubString.length()+1);
   client.publish("Boubounouche/Halloween/PIR", message_buff);
   
    delay (10000); // Smoke Machine ON
    //trigger = !trigger; // trigger is true
    digitalWrite(LED_PIN, LOW);
    digitalWrite(RELAY_PIN_1, LOW);
    motionStatus = 0;
     //Sending value to OpenHab with MQTT
   Serial.print("The value of motionStatus is: ");
   Serial.println(motionStatus);
   Serial.print("Sending PIR state ");
   Serial.println(presence[motionStatus]);
   pubString = String(presence[motionStatus]);
   pubString.toCharArray(message_buff, pubString.length()+1);
   client.publish("Boubounouche/Halloween/PIR", message_buff);
   delay(10000);
  }
  else // Otherwise turn the LED off:
  {
    digitalWrite(LED_PIN, LOW);
    digitalWrite(RELAY_PIN_1, LOW);
  }
}

As written your code should send two messages (one on, one off) 10 seconds apart and repeated for as long as the motion sensor input is high. Is this what happens? Perhaps you can post a snippet from your serial monitor window that shows the debugging output while the program runs?

Yes it is what I want to do so far, if movement turn a relay on for 10 sec, send a MQTT message to tell me there is someone at the door then after send me a message that nobody is at the door and then I will put a delay of 1min before re-checking my PIR.

My serial monitor looks like this:

Connecting to Boubounouche Network...
WiFi connected
The value of motionStatus is: 1
Sending PIR state Halloween!
The value of motionStatus is: 0
Sending PIR state nobody...

But when I check with MQTT.fx I only receive the message "Halloween!" not the "Nobody..." message...

First step is saving the return code from client.publish() and printing it out afterwards to see if it succeeded or not

status=client.publish("Boubounouche/Halloween/PIR", message_buff);
Serial.print("MQQT publish returned");
Serial.println(status);

But I'm wondering if you do not call client.loop() often enough to maintain a connection? If you reduce the 10 second delay to 0.1 second does the second message get through?

Ideally your program will avoid delay() entirely. See the Doing several things at once sticky or study the arduino "Blink without delay" example to learn about ways to better handle this.

If you only intend to publish, and dont wish to get anything back from the MQTT broker then you can simply check and reconnect before you publish each time.

if (! client. connected() ) { client.connect(); }
client.publish()

You got it RW!!!!!

The delay was the problem, so instead of putting the 2nd message after the delay I've put it in my else loop and it's working now!!!!

// If motion is detected, turn the onboard LED on:
  if (motionStatus == HIGH){
    motionStatus = 1;
    //Serial.print(motionStatus);
    digitalWrite(LED_PIN, HIGH);
    digitalWrite(RELAY_PIN_1, HIGH);
    //Sending value to OpenHab with MQTT
   Serial.print("The value of motionStatus is: ");
   Serial.println(motionStatus);
   Serial.print("Sending PIR state ");
   Serial.println(presence[motionStatus]);
   String pubString = String(presence[motionStatus]);
   pubString.toCharArray(message_buff, pubString.length()+1);
   client.publish("Boubounouche/Halloween/PIR", message_buff);
   
    delay (10000); // Smoke Machine ON
    trigger = !trigger; // trigger is true
    digitalWrite(LED_PIN, LOW);
    digitalWrite(RELAY_PIN_1, LOW);
    
   
   delay(10000);
  }
  else // Otherwise send MQTT nobody message and turn off relay
  {
    if (trigger == true){
      motionStatus =0;   
      //Sending value to OpenHab with MQTT
      Serial.print("The value of motionStatus is: ");
      Serial.println(motionStatus);
      Serial.print("Sending PIR state ");
      Serial.println(presence[motionStatus]);
      String pubString = String(presence[motionStatus]);
      pubString.toCharArray(message_buff, pubString.length()+1);
      client.publish("Boubounouche/Halloween/PIR", message_buff);
      trigger = !trigger; // trigger is false
    }
    digitalWrite(LED_PIN, LOW);
    digitalWrite(RELAY_PIN_1, LOW);
  }
}