Offline/Online Mode with FreeRTOS

Hi everyone, I want to implement online/offline mode using the switch button. when in offline mode I don’t want the program to keep checking for connection so I use vTaskSuspend() and vTaskResume() when I switch back to online mode. is this the correct way to archive this?

Here is my code:

#define WIFI_NETWORK "****"
#define WIFI_PASSWORD "****"
#define WIFI_TIMEOUT_MS 10000

#include <WiFi.h>
#include <WiFiClient.h>
#include <JC_Button.h>

TaskHandle_t checkConnection_handler = NULL;
TaskHandle_t timer_hander = NULL;

const byte
    WIFIMODE_PIN(23),
    OFFLINEMODE_PIN(5);

Button wifiModeBtn(WIFIMODE_PIN);
Button offlineModeBtn(OFFLINEMODE_PIN);

bool isOffline = false;
bool offlineHasRun = false;

void keepWiFiAlive(void * parameters) {
  Serial.println("wifi check running");
  for(;;) {
    if (WiFi.status() == WL_CONNECTED) {
      Serial.println("WiFi still connected");
      isOffline = false;
      digitalWrite(connectionLedPin, HIGH);
      vTaskDelay(10000 / portTICK_PERIOD_MS);
      continue;
    }

    Serial.println("WiFi Connecting");
    WiFi.mode(WIFI_STA);
    WiFi.begin(WIFI_NETWORK, WIFI_PASSWORD);

    unsigned long startAttemptTime = millis();

    // keep looping while we not connected and haven't reached the timeout
    while ((WiFi.status() != WL_CONNECTED) && (millis() - startAttemptTime < WIFI_TIMEOUT_MS)) {
      isOffline = true;
    }

      // When we couldn't make a WiFi connection
      if (WiFi.status() != WL_CONNECTED) {
        Serial.println("[WIFI] FAILED");
        digitalWrite(connectionLedPin, LOW);
        vTaskDelay(10000 / portTICK_PERIOD_MS);
      }
      
    Serial.print("[WIFI] Connected: ");
    Serial.println(WiFi.localIP());
  }
}
 
void setup() {
  wifiModeBtn.begin();
  offlineModeBtn.begin(); 
  Serial.begin(115200);

  xTaskCreatePinnedToCore(
    keepWiFiAlive,
    "Keep WiFi alive", 
    5000,
    NULL,
    1,
    &checkConnection_handler,
    ARDUINO_RUNNING_CORE
  );
}

void loop() {
  wifiModeBtn.read();
  offlineModeBtn.read();

  if (wifiModeBtn.isPressed()) {
    // resume wifi task
    vTaskResume(checkConnection_handler);

    // do something....
  } else if (offlineModeBtn.isPressed()) {
    // suspend wifi task vTask
    vTaskSuspend(checkConnection_handler);
    // do offline task
  }
}

It is generally agreed upon that vTaskSuspend and vTaskResume should NOT be used as there is no control whatsoever in what state the task is when being suspended.

In your case, I would recommend adding states to the wifi connection fsm: Cleaning up, dormant and resuming. When the offline button is pressed, the fsm traverses to cleaning up where the connection fsm can actively do everything needed and move to dormant. When the online button is pressed, the fsm can traverse to resuming.

If you simply suspend the fsm task, you give it no control whatsoever about the connection which is a door opener to all kinds of trouble.

I don’t understand about ‘wifi connection fsm’. Can give explain a bit more or link me to the related document?

FSM stands for Finite State Automaton. If you do not knw what that is, read up on it first, it is very very essential.

The infinite loop in your keepWiFiAlive task fn implements a connection fsm for your wifi.