freeRTOS didn't alwatys publish sring to MQTT topic

I’m new into freeRTOS and I’m trying to publish string to a topic everytime the visitor count. The visitor count based on the PIR sensor reading and it works perfectly except the part when it should publishes a string to my MQTT broker everytime the visitor count changes. Here’s my full code.

    #include <freertos/FreeRTOS.h>
    #include <WiFi.h>
    #include <PubSubClient.h>
    
    #define OUTER_PIR_PIN 34
    #define INNER_PIR_PIN 33
    
    #define WIFI_SSID "suastuti_3"
    #define WIFI_PASS "notaristutiek"
    
    #define MQTT_BROKER "broker.emqx.io"
    #define MQTT_PORT 1883
    #define MQTT_TOPIC "capstoneA16/visitor"
    
    int outerPirState = 0;
    int innerPirState = 0;
    
    unsigned int outerPirTime = 0;
    unsigned int innerPirTime = 0;
    unsigned int lastOuterPirTime = 0;
    unsigned int lastInnerPirTime = 0;
    
    unsigned int visitorCount = 0;
    unsigned int lastVisitorCount = 0;
    
    bool wifiIndState = false;
    
    WiFiClient espClient;
    PubSubClient client(espClient);
    
    void handleOuterPir(void *parameters)
    {
        for (;;)
        {
            outerPirState = digitalRead(OUTER_PIR_PIN);
    
            if (!outerPirState)
            {
                Serial.println("Motion detected on OUTER SENSOR");
                outerPirTime = millis();
    
                outerPirState = 1;
                vTaskDelay(500);
            }
        }
    }
    
    void handleInnerPir(void *parameters)
    {
        for (;;)
        {
            innerPirState = digitalRead(INNER_PIR_PIN);
    
            if (!innerPirState)
            {
                Serial.println("Motion detected on INNER SENSOR");
                innerPirTime = millis();
    
                innerPirState = 1;
                vTaskDelay(500);
            }
        }
    }
    
    void handleVisitorCount(void *parameters)
    {
        for (;;)
        {
            Serial.print("");
            if (innerPirTime != 0 && outerPirTime != 0)
            {
                int visitorState = innerPirTime - outerPirTime;
                if (visitorState > 0)
                {
                    visitorCount++;
    
                    Serial.print("Visitor count: ");
                    Serial.println(visitorCount);
                    Serial.println("Visitor in");
                }
                else
                {
                    if (visitorCount > 0)
                    {
                        visitorCount--;
    
                        Serial.print("Visitor count: ");
                        Serial.println(visitorCount);
                        Serial.println("Visitor out");
                    }
                }
                vTaskDelay(500);
                innerPirTime = 0;
                outerPirTime = 0;
            }
        }
    }
    
    void publishToTopic(void *parameters)
    {
        for (;;)
        {
            while (!client.connected())
            {
                Serial.print("Attempting MQTT connection...");
                // Attempt to connect
                if (client.connect("ESP8266Client"))
                {
                    if (lastVisitorCount != visitorCount)
                    {
    
                        while (!client.connected())
                        {
                            reconnect();
                        }
                        client.publish("capstoneA16/visitor", "test");
                        vTaskDelay(1000);
                        Serial.println("Published");
                        lastVisitorCount = visitorCount;
                    }
                    Serial.println("connected");
                }
            }
            if (lastVisitorCount != visitorCount)
            {
    
                while (!client.connected())
                {
                    reconnect();
                }
                client.publish("capstoneA16/visitor", "test");
                vTaskDelay(1000);
                Serial.println("Published");
                lastVisitorCount = visitorCount;
            }
        }
    }
    
    void reconnect()
    {
        // Loop until we're reconnected
        while (!client.connected())
        {
            Serial.print("Attempting MQTT connection...");
            // Attempt to connect
            if (client.connect("ESP8266Client"))
            {
                Serial.println("connected");
                // Subscribe
                client.subscribe("esp32/output");
            }
            else
            {
                Serial.print("failed, rc=");
                Serial.print(client.state());
                Serial.println(" try again in 5 seconds");
                // Wait 5 seconds before retrying
                delay(5000);
            }
        }
    }
    
    void callback(char *topic, byte *message, unsigned int length)
    {
        Serial.print("Message arrived on topic: ");
        Serial.print(topic);
        Serial.print(". Message: ");
        String messageTemp;
    }
    
    void setup()
    {
        // put your setup code here, to run once:
        Serial.begin(115200);
        Serial.println("Hello, ESP32!");
    
        pinMode(OUTER_PIR_PIN, INPUT);
        pinMode(INNER_PIR_PIN, INPUT);
    
        pinMode(LED_BUILTIN, OUTPUT);
        //
        //  pinMode(OUTER_PIR_PIN, INPUT);
        //  pinMode(INNER_PIR_PIN, INPUT);
    
        WiFi.begin(WIFI_SSID, WIFI_PASS);
    
        while (WiFi.status() != WL_CONNECTED)
        {
            Serial.print(".");
            wifiIndState = !wifiIndState;
            digitalWrite(LED_BUILTIN, wifiIndState);
            delay(100);
        }
    
        digitalWrite(LED_BUILTIN, HIGH);
    
        client.setServer(MQTT_BROKER, MQTT_PORT);
        client.setCallback(callback);
    
        xTaskCreatePinnedToCore(
            handleOuterPir,
            "Handle outside sensor",
            1000,
            NULL,
            1,
            NULL,
            1);
    
        xTaskCreatePinnedToCore(
            handleInnerPir,
            "Handle inside sensor",
            1000,
            NULL,
            1,
            NULL,
            1);
    
        xTaskCreatePinnedToCore(
            handleVisitorCount,
            "Handle visitor",
            1000,
            NULL,
            1,
            NULL,
            1);
        xTaskCreatePinnedToCore(
            publishToTopic,
            "Send data to mqtt",
            5000,
            NULL,
            1,
            NULL,
            1);
    }
    
    void loop()
    {
    }

The problem is sometimes it publishes to my MQTT topic but sometimes it didn’t. How can I make sure or “force” my program to publishes to the MQTT broker first before continue to the next task?

Hello @airlanggarasyad! Welcome to the forums. I’m going to look into this and get back to you. I want to do a little bit of a deep dive so I give reasonable advice

Do you have logs to suggest that the publishToTopic task is executing but the message is failing to publish? Device logs could be helpful here

Are you expecting messages to be published on a cadence, say every 2 seconds for example?

A couple other things I noticed…

  1. On line 158 you’re calling delay to wait 5 seconds. This delay is happening in the publish task. Meaning if the task is swapped out+in you may have a skew in the overall delay. You could use the vTaskDelay function here which may improve overall timing.

  2. It’s possible to hit the publish on line 116 (the publish within the for + while loop) without being subscribed. I’d recommend having a single point of publishing and a single point of reconnecting in this loop.