Compiles in Arduino IDE but fails in platformIO (issue with OTA libraries)

I’m a hobbyist and been using the Arduino IDE for some years (although by no means an expert in C++ coding). I thought I would try out PlatformIO due to it’s debugging capabilities. I was able to get the blink program working so decided to move across a slightly more difficult sketch. After days of attempting to get it to compile, I went back to Arduino and was able to get it to compile in minutes! I’d really like to use the debugging capability, but about to give-up - So, this is one last plea for help!

The problem is with the OTA libraries. The compiler complain about functions that are clearly defined. I am even able to use the “go to definition” in VS code to go to them, but the compiler does not find them. I suspect, it has to do with how I am #Including the relevent files. Whilst I found several discussion on issue with libraries, I could not find a clear concise approach to including them.

I have a separate file with the OTA code to simplify the main line of logic (I’ve used this approach on numerous sketches in Arduino IDE). But also did try using the example OTA code and kept hitting an issue with NetworkUDP.h not being found. I would have thought the IDE would download it automatically.

The compiler log is below:

 *  Executing task in folder Irrigation controller: C:\Users\user\.platformio\penv\Scripts\platformio.exe run 

Processing nodemcu-32s (platform: espressif32; board: nodemcu-32s; framework: arduino)
---------------------------------------------------------------------------------------------------------------------------------------------------------Verbose mode can be enabled via `-v, --verbose` option
CONFIGURATION: https://docs.platformio.org/page/boards/espressif32/nodemcu-32s.html
PLATFORM: Espressif 32 (6.5.0) > NodeMCU-32S
HARDWARE: ESP32 240MHz, 320KB RAM, 4MB Flash
DEBUG: Current (esp-prog) External (cmsis-dap, esp-bridge, esp-prog, iot-bus-jtag, jlink, minimodule, olimex-arm-usb-ocd, olimex-arm-usb-ocd-h, olimex-arm-usb-tiny-h, olimex-jtag-tiny, tumpa)
PACKAGES:
 - framework-arduinoespressif32 @ 3.20014.231204 (2.0.14)
 - tool-esptoolpy @ 1.40501.0 (4.5.1)
 - toolchain-xtensa-esp32 @ 8.4.0+2021r2-patch5
LDF: Library Dependency Finder -> https://bit.ly/configure-pio-ldf
LDF Modes: Finder ~ chain, Compatibility ~ soft
Found 37 compatible libraries
Scanning dependencies...
Dependency Graph
|-- ArduinoJson @ 7.0.0
|-- PubSubClient @ 2.8.0
|-- ArduinoOTA @ 1.1.0
|-- ESPmDNS @ 2.0.0
|-- WiFi @ 2.0.0
|-- Wire @ 2.0.0
Building in release mode
Compiling .pio\build\nodemcu-32s\src\main.cpp.o
In file included from src/main.cpp:24:
.pio/libdeps/nodemcu-32s/ArduinoOTA/src/ArduinoOTA.h:141:22: error: 'WiFiServer' was not declared in this scope
 ArduinoOTAMdnsClass <WiFiServer, WiFiClient, WiFiUDP> ArduinoOTA;
                      ^~~~~~~~~~
.pio/libdeps/nodemcu-32s/ArduinoOTA/src/ArduinoOTA.h:141:22: note: suggested alternative: 'Server'
 ArduinoOTAMdnsClass <WiFiServer, WiFiClient, WiFiUDP> ArduinoOTA;
                      ^~~~~~~~~~
                      Server
.pio/libdeps/nodemcu-32s/ArduinoOTA/src/ArduinoOTA.h:141:34: error: 'WiFiClient' was not declared in this scope
 ArduinoOTAMdnsClass <WiFiServer, WiFiClient, WiFiUDP> ArduinoOTA;
                                  ^~~~~~~~~~
.pio/libdeps/nodemcu-32s/ArduinoOTA/src/ArduinoOTA.h:141:34: note: suggested alternative: 'DNSClient'
 ArduinoOTAMdnsClass <WiFiServer, WiFiClient, WiFiUDP> ArduinoOTA;
                                  ^~~~~~~~~~
                                  DNSClient
.pio/libdeps/nodemcu-32s/ArduinoOTA/src/ArduinoOTA.h:141:53: error: template argument 1 is invalid
 ArduinoOTAMdnsClass <WiFiServer, WiFiClient, WiFiUDP> ArduinoOTA;
                                                     ^
.pio/libdeps/nodemcu-32s/ArduinoOTA/src/ArduinoOTA.h:141:53: error: template argument 2 is invalid
In file included from src/main.cpp:26:
src/OTA.h: In function 'void setupOTA(const char*)':
src/OTA.h:34:14: error: request for member 'setHostname' in 'ArduinoOTA', which is of non-class type 'int'
   ArduinoOTA.setHostname(fullhostname);
              ^~~~~~~~~~~
src/OTA.h:54:14: error: request for member 'onStart' in 'ArduinoOTA', which is of non-class type 'int'
   ArduinoOTA.onStart([]() {
              ^~~~~~~
src/OTA.h: In lambda function:
src/OTA.h:56:20: error: request for member 'getCommand' in 'ArduinoOTA', which is of non-class type 'int'
     if (ArduinoOTA.getCommand() == U_FLASH)
                    ^~~~~~~~~~
src/OTA.h:56:36: error: 'U_FLASH' was not declared in this scope
     if (ArduinoOTA.getCommand() == U_FLASH)
                                    ^~~~~~~
src/OTA.h: In function 'void setupOTA(const char*)':
src/OTA.h:64:14: error: request for member 'onEnd' in 'ArduinoOTA', which is of non-class type 'int'
   ArduinoOTA.onEnd([]() {
              ^~~~~
src/OTA.h:67:14: error: request for member 'onProgress' in 'ArduinoOTA', which is of non-class type 'int'
   ArduinoOTA.onProgress([](unsigned int progress, unsigned int total) {
              ^~~~~~~~~~
src/OTA.h:70:14: error: request for member 'onError' in 'ArduinoOTA', which is of non-class type 'int'
   ArduinoOTA.onError([](ota_error_t error) {
              ^~~~~~~
src/OTA.h:70:25: error: 'ota_error_t' has not been declared
   ArduinoOTA.onError([](ota_error_t error) {
                         ^~~~~~~~~~~
src/OTA.h: In lambda function:
src/OTA.h:72:18: error: 'OTA_AUTH_ERROR' was not declared in this scope
     if (error == OTA_AUTH_ERROR) Serial.println("Auth Failed");
                  ^~~~~~~~~~~~~~
src/OTA.h:72:18: note: suggested alternative: 'UART_NO_ERROR'
     if (error == OTA_AUTH_ERROR) Serial.println("Auth Failed");
                  ^~~~~~~~~~~~~~
                  UART_NO_ERROR
src/OTA.h:73:23: error: 'OTA_BEGIN_ERROR' was not declared in this scope
     else if (error == OTA_BEGIN_ERROR) Serial.println("Begin Failed");
                       ^~~~~~~~~~~~~~~
src/OTA.h:73:23: note: suggested alternative: 'ESP_LOG_ERROR'
     else if (error == OTA_BEGIN_ERROR) Serial.println("Begin Failed");
                       ^~~~~~~~~~~~~~~
                       ESP_LOG_ERROR
src/OTA.h:74:23: error: 'OTA_CONNECT_ERROR' was not declared in this scope
     else if (error == OTA_CONNECT_ERROR) Serial.println("Connect Failed");
                       ^~~~~~~~~~~~~~~~~
src/OTA.h:74:23: note: suggested alternative: 'STA_CONNECTED_BIT'
     else if (error == OTA_CONNECT_ERROR) Serial.println("Connect Failed");
                       ^~~~~~~~~~~~~~~~~
                       STA_CONNECTED_BIT
src/OTA.h:75:23: error: 'OTA_RECEIVE_ERROR' was not declared in this scope
     else if (error == OTA_RECEIVE_ERROR) Serial.println("Receive Failed");
                       ^~~~~~~~~~~~~~~~~
src/OTA.h:76:23: error: 'OTA_END_ERROR' was not declared in this scope
     else if (error == OTA_END_ERROR) Serial.println("End Failed");
                       ^~~~~~~~~~~~~
src/OTA.h:76:23: note: suggested alternative: 'UART_NO_ERROR'
     else if (error == OTA_END_ERROR) Serial.println("End Failed");
                       ^~~~~~~~~~~~~
                       UART_NO_ERROR
src/OTA.h: In function 'void setupOTA(const char*)':
src/OTA.h:79:14: error: request for member 'begin' in 'ArduinoOTA', which is of non-class type 'int'
   ArduinoOTA.begin();
              ^~~~~
In file included from src/switch_panel.h:5,
                 from src/main.cpp:32:
src/switch.h: In member function 'void Switch::publishSwitchState()':
src/switch.h:148:5: warning: 'template<unsigned int N> class ArduinoJson::V700PB2::StaticJsonDocument' is deprecated: use JsonDocument instead [-Wdeprecated-declarations]
     StaticJsonDocument<300> doc;
     ^~~~~~~~~~~~~~~~~~
In file included from .pio/libdeps/nodemcu-32s/ArduinoJson/src/ArduinoJson.hpp:53,
                 from .pio/libdeps/nodemcu-32s/ArduinoJson/src/ArduinoJson.h:9,
                 from src/main.cpp:30:
.pio/libdeps/nodemcu-32s/ArduinoJson/src/ArduinoJson/compatibility.hpp:63:58: note: declared here
 class ARDUINOJSON_DEPRECATED("use JsonDocument instead") StaticJsonDocument
                                                          ^~~~~~~~~~~~~~~~~~
In file included from src/switch_panel.h:5,
                 from src/main.cpp:32:
src/switch.h: In member function 'void Switch::publishSwitchAttributes()':
src/switch.h:174:5: warning: 'template<unsigned int N> class ArduinoJson::V700PB2::StaticJsonDocument' is deprecated: use JsonDocument instead [-Wdeprecated-declarations]
     StaticJsonDocument<300> doc;
     ^~~~~~~~~~~~~~~~~~
In file included from .pio/libdeps/nodemcu-32s/ArduinoJson/src/ArduinoJson.hpp:53,
                 from .pio/libdeps/nodemcu-32s/ArduinoJson/src/ArduinoJson.h:9,
                 from src/main.cpp:30:
.pio/libdeps/nodemcu-32s/ArduinoJson/src/ArduinoJson/compatibility.hpp:63:58: note: declared here
 class ARDUINOJSON_DEPRECATED("use JsonDocument instead") StaticJsonDocument
                                                          ^~~~~~~~~~~~~~~~~~
src/main.cpp: In function 'void reconnect()':
src/main.cpp:165:20: error: request for member 'handle' in 'ArduinoOTA', which is of non-class type 'int'
         ArduinoOTA.handle();
                    ^~~~~~
src/main.cpp: In function 'void loop()':
src/main.cpp:215:14: error: request for member 'handle' in 'ArduinoOTA', which is of non-class type 'int'
   ArduinoOTA.handle();
              ^~~~~~
src/main.cpp: In function 'int timerDuration()':
src/main.cpp:332:3: warning: 'template<unsigned int N> class ArduinoJson::V700PB2::StaticJsonDocument' is deprecated: use JsonDocument instead [-Wdeprecated-declarations]
   StaticJsonDocument<200> doc;
   ^~~~~~~~~~~~~~~~~~
In file included from .pio/libdeps/nodemcu-32s/ArduinoJson/src/ArduinoJson.hpp:53,
                 from .pio/libdeps/nodemcu-32s/ArduinoJson/src/ArduinoJson.h:9,
                 from src/main.cpp:30:
.pio/libdeps/nodemcu-32s/ArduinoJson/src/ArduinoJson/compatibility.hpp:63:58: note: declared here
 class ARDUINOJSON_DEPRECATED("use JsonDocument instead") StaticJsonDocument
                                                          ^~~~~~~~~~~~~~~~~~
src/main.cpp: In function 'void publishLog(String)':
src/main.cpp:353:3: warning: 'template<unsigned int N> class ArduinoJson::V700PB2::StaticJsonDocument' is deprecated: use JsonDocument instead [-Wdeprecated-declarations]
   StaticJsonDocument<200> doc;
   ^~~~~~~~~~~~~~~~~~
In file included from .pio/libdeps/nodemcu-32s/ArduinoJson/src/ArduinoJson.hpp:53,
                 from .pio/libdeps/nodemcu-32s/ArduinoJson/src/ArduinoJson.h:9,
                 from src/main.cpp:30:
.pio/libdeps/nodemcu-32s/ArduinoJson/src/ArduinoJson/compatibility.hpp:63:58: note: declared here
 class ARDUINOJSON_DEPRECATED("use JsonDocument instead") StaticJsonDocument
                                                          ^~~~~~~~~~~~~~~~~~
Compiling .pio\build\nodemcu-32s\FrameworkArduino\esp32-hal-cpu.c.o
*** [.pio\build\nodemcu-32s\src\main.cpp.o] Error 1
============================================================== [FAILED] Took 17.12 seconds ==============================================================
 *  The terminal process "C:\Users\user\.platformio\penv\Scripts\platformio.exe 'run'" terminated with exit code: 1. 
 *  Terminal will be reused by tasks, press any key to close it. 

The sketch mainline.


/****************************************************************
 * This sketch uses a switch panel as an irrigation controller
 * 
 *    
 * 
 ***************************************************************/
#include <Arduino.h>
//#define NUMBER_OF_REGISTERS 2
#define NUMBER_OF_SWITCHES 12
#define CLOCK_PIN 4
#define DATA_PIN 5
#define REVERSE_SWITCH 1          // 1 = true; 0 = false - used for relays that are off on high
#define LED_PIN 2
#define RAIN_SENSOR_PIN 14      //D5 on ESP8266
#define DEVICE_NAME "Irrigation controller"

#include <credentials.h>
//#include <WiFi.h>
//#include "WiFiOTA.h"
//#include <WiFi.h>
//#include <ESPmDNS.h>
//#include <NetworkUdp.h>
#include <ArduinoOTA.h>

#include <OTA.h>
//#include <stdlib.h>
//#include <mqtt_broker.h>
#include <PubSubClient.h>
#include <ArduinoJson.h>
#include <Timer.h>
#include <switch_panel.h>
#include <rain_sensor.h>

int statusUpdateInterval = 1;   // in minutes
int attributeUpdateInterval = 30;  // in secs
int rainSensorUpdateInterval = 60; // in secs

const char *DEVICE_ID = DEVICE_NAME;                 // Name of our device, must be unique (For MQTT and OTA)
const char *PUB_LOG_TOPIC = "home/log";               // Topic for log
const char *SUB_TOPIC = "home/garden/" DEVICE_NAME "/request";     // for device requests
const char *PUB_STATE_TOPIC = "home/garden/" DEVICE_NAME;       // Topic for device

IPAddress broker(192,168,86,234);                      // IP address of your MQTT broker PROD
//IPAddress broker(192,168,86,249);                      // IP address of your MQTT broker TEST

const char *USERNAME = mqttUSERID;
const char *PASSWORD = mqttPASSWORD;

const char *switchName[NUMBER_OF_SWITCHES] {
  "z1 back fence",
  "z2 buxus hedge",
  "z3 back lawn 1",
  "z4 back lawn 2",
  "z5 bbq area",
  "z6 balinese sanctuary",
  "z7 small pond",
  "z8 front lawn",
  "z9 front plants",
  "z10 shrubs around pond",
  "z11 driveway plants",
  "z12 large pond"
};

int maxDurations[NUMBER_OF_SWITCHES] {
  30,
  30,
  20,
  20,
  30,
  30,
  10,
  20,
  30,
  30,
  30,
  10
};


String response;
char* requestTopic;

bool requestArrived = false;

enum State {
  OFF,
  INITIALISING,
  STANDBY,
  IRRIGATION_ON,
  UNAVAILABLE
};

State currentState = OFF;

enum Event {
  INITIALISED,
  REQUEST_ARRIVED
};

Event triggerEvent = INITIALISED;

enum RequestType {
  INVALID,
  TURN_ON,
  TURN_OFF,
  START_TIMER,
  RESET_CONTROLLER
};

RequestType requestType = INVALID;

WiFiClient wclient;

uint16_t keepAlive = 21600;       // mqtt keep connection alive for 6 hours - used in "setup"
PubSubClient mqttClient(wclient);       // MQTT client
//MQTTBroker mqttBrocker(&wclient,),

//SwitchPanel switchPanel(DEVICE_ID, switchName[NUMBER_OF_SWITCHES], maxDurations[NUMBER_OF_SWITCHES], statusUpdateInterval, attributeUpdateInterval, PUB_STATE_TOPIC, &client);

SwitchPanel switchPanel(DEVICE_ID, &switchName[NUMBER_OF_SWITCHES], &maxDurations[NUMBER_OF_SWITCHES], &mqttClient, PUB_STATE_TOPIC, statusUpdateInterval, attributeUpdateInterval);
//const char* _deviceName, const char* _switchName[NUMBER_OF_SWITCHES], int _maxDuration[NUMBER_OF_SWITCHES], PubSubClient* _pubSubClient, const char * _deviceTopic, int _statusUpdateInterval = 1, int _attributeUpdateInterval = 10
RainSensor rainSensor("rain sensor", DEVICE_ID, rainSensorUpdateInterval, PUB_STATE_TOPIC, &mqttClient);

int interval = 2;                 //interval between switching on zones in seconds

Timer wateringDuration;
Timer statusUpdateIntervalTimer;

// Function definitions - the platformIO compiler requires function defintions before referred to
void publishLog(String);
void setRequestType();
void processRequest();
void eventHandler();
int switchIndex();
int timerDuration();
void setup();

///////////////////////////////////// Handle incomming messages from the broker

void callback(char* topic, byte* payload, unsigned int length) {
  //String response;

  for (int i = 0; i < length; i++) {
    response += (char)payload[i];
  }
  requestTopic = topic;
  requestArrived = true;
}

///////////////////////////////////////// Reconnect to client

void reconnect() {
  // Loop until we're reconnected
  while (!mqttClient.connected()) {
    Serial.print("Attempting MQTT connection...");
    // Attempt to connect
    if(mqttClient.connect(DEVICE_ID, USERNAME, PASSWORD)) {
      mqttClient.subscribe(SUB_TOPIC);
      publishLog("MQTT Connection re-established");
    } else {
      Timer timeBetweenAttempts;
      timeBetweenAttempts.start(5000);
      while (!timeBetweenAttempts.timeUp()){
        ArduinoOTA.handle();
      }
    }
  }
}

/////////////////////////////////////setup

void setup(){

  currentState = INITIALISING;

  pinMode(LED_PIN, OUTPUT);       // Configure LED_PIN as an output
  delay(100);
  digitalWrite(LED_PIN, HIGH);
  delay(100);
  pinMode(RAIN_SENSOR_PIN, INPUT_PULLUP);
  delay(100);

  Serial.begin(115200);
  delay(100);
  
  setupOTA(DEVICE_ID);

//************ Setup MQTT server *************
  mqttClient.setServer(broker, 1883);
  mqttClient.setKeepAlive(keepAlive);   // keep mqtt connection alive for x seconds
  mqttClient.setCallback(callback);     // Initialize the callback routine

  switchPanel.turnAllOff();

  currentState = STANDBY;

  for (int i=0; i<5; i++){
    digitalWrite(LED_PIN, LOW);
    delay(250);
    digitalWrite(LED_PIN, HIGH);
    delay(750);
  }
  publishLog("Initialisation complete");

  digitalWrite(LED_PIN, LOW);
  delay(100);

}

////////////////////////////////

void loop() {

  ArduinoOTA.handle();
  delay(20);                // OTA seems to work better when this is at least 20

//  Capture any trigger events

  requestArrived = false;
  if (!mqttClient.connected()){reconnect(); }  // Reconnect if connection is lost
  mqttClient.loop();                          // MQTT subscription read. (see callback)

  if (requestArrived){
     triggerEvent = REQUEST_ARRIVED;
     eventHandler();
     response = "";
     requestArrived = false;
    }

  if (switchPanel.switchesOn()){
    currentState = IRRIGATION_ON;
  } else if (!UNAVAILABLE){  
    currentState = STANDBY;
  }

  yield();
}

//////////////////////////////////////////////////////////////

void eventHandler(){
  delay(10);                  // provide a time lag between readings on sensors
  
  digitalWrite(LED_PIN, LOW); // turn LED ON 
  
  switch (triggerEvent) {
 
    case REQUEST_ARRIVED:
         processRequest();
         break;

  }

  digitalWrite(LED_PIN, HIGH); // turn LED OFF 
}

////////////////////////////////////////////////////////////////////////

void processRequest(){

  publishLog(response);

  setRequestType();
    
  switch(requestType){
    case TURN_ON:
      switchPanel.turnAllOff();
      delay(interval * 1000);
      switchPanel.turnOn(switchIndex());
      currentState = IRRIGATION_ON;
      break;

    case TURN_OFF:
      switchPanel.turnAllOff();
      currentState = STANDBY;
      break;
    
    case START_TIMER:
      switchPanel.startTimer(switchIndex(), timerDuration());
      currentState = STANDBY;
      break;

    case RESET_CONTROLLER:
      ESP.restart();
      break;
    
  }

}

/************************************************************************
 * The request message can be:
 *    1. "on"  Turn switch on
 *    2. "off" Turn switch off
 *    3. {"Timer duration" = nnnn } start timer for specified duration
 * 
 * *********************************************************************/

void setRequestType() {

  if (response == "on"){
    requestType = TURN_ON;
  } else if (response == "off")
  {
    requestType = TURN_OFF;
  } else if ((String)response[0] == "{")
  {
    requestType = START_TIMER; 
  } else if (response == "reset")
  {
    requestType = RESET_CONTROLLER;
  } else 
  {
    requestType = INVALID;
  }
}

int switchIndex(){
  int i = 0;
  for (i=0; i < NUMBER_OF_SWITCHES; i++){
    String switchTopic = "home/garden/" DEVICE_NAME "/" + (String)switchName[i] + "/request";
    if (strcmp(requestTopic, switchTopic.c_str()) == 0){
      break;
    }
  }
  return i;
}

int timerDuration(){

  StaticJsonDocument<200> doc;

  DeserializationError error = deserializeJson(doc, response);

  if (error) {
    Serial.print(F("deserializeJson() failed: "));
    Serial.println(error.f_str());
    return 0;
    }
  
  String timerDuration = doc["Timer duration"];
  int i = timerDuration.toInt();

  return atoi(timerDuration.c_str());

}


void publishLog(String p_message) {
  // create a JSON object
  
  StaticJsonDocument<200> doc;
  
  doc["device"] = DEVICE_ID;
  doc["message"] = p_message;

  serializeJsonPretty(doc, Serial);
  //delay(100);
  Serial.println(" ");
  
  char data[200];
  serializeJson(doc, data, sizeof(data)+ 1);
  
//  doc.printTo(data, doc.measureLength() + 1);

  if (!mqttClient.connected()) {reconnect();}                 // Reconnect if connection to MQTT server is lost
  mqttClient.publish(PUB_LOG_TOPIC, data, true);
  
  yield();
}

The separate code for OTA

#ifndef OTA_H
#define OTA_H

#ifdef ESP32
#include <WiFi.h>
#include <ESPmDNS.h>
#else
#include <ESP8266WiFi.h>
#include <ESP8266mDNS.h>
#endif


#include <WiFiUdp.h>
#include <ArduinoOTA.h>
#include <credentials.h>

const char* ssid = mySSID;
const char* password = myPASSWORD;

#if defined(ESP32_RTOS) && defined(ESP32)
void taskOne( void * parameter )
{
  ArduinoOTA.handle();
  delay(3500);
}
#endif

void setupOTA(const char* nameprefix) {
  const int maxlen = 40;
  char fullhostname[maxlen];
  uint8_t mac[6];
  WiFi.macAddress(mac);
  snprintf(fullhostname, maxlen, "%s-%02x%02x%02x", nameprefix, mac[3], mac[4], mac[5]);
  ArduinoOTA.setHostname(fullhostname);
  
  WiFi.mode(WIFI_STA);
  WiFi.begin(ssid, password);
  while (WiFi.waitForConnectResult() != WL_CONNECTED) {
    Serial.println("Connection Failed! Rebooting...");
    delay(5000);
    ESP.restart();
  }

  // Port defaults to 3232
  // ArduinoOTA.setPort(3232);

  // No authentication by default
  // ArduinoOTA.setPassword("admin");

  // Password can be set with it's md5 value as well
  // MD5(admin) = 21232f297a57a5a743894a0e4a801fc3
  // ArduinoOTA.setPasswordHash("21232f297a57a5a743894a0e4a801fc3");

  ArduinoOTA.onStart([]() {
    String type;
    if (ArduinoOTA.getCommand() == U_FLASH)
      type = "sketch";
    else // U_SPIFFS
      type = "filesystem";

    // NOTE: if updating SPIFFS this would be the place to unmount SPIFFS using SPIFFS.end()
    Serial.println("Start updating " + type);
  });
  ArduinoOTA.onEnd([]() {
    Serial.println("\nEnd");
  });
  ArduinoOTA.onProgress([](unsigned int progress, unsigned int total) {
    Serial.printf("Progress: %u%%\r", (progress / (total / 100)));
  });
  ArduinoOTA.onError([](ota_error_t error) {
    Serial.printf("Error[%u]: ", error);
    if (error == OTA_AUTH_ERROR) Serial.println("Auth Failed");
    else if (error == OTA_BEGIN_ERROR) Serial.println("Begin Failed");
    else if (error == OTA_CONNECT_ERROR) Serial.println("Connect Failed");
    else if (error == OTA_RECEIVE_ERROR) Serial.println("Receive Failed");
    else if (error == OTA_END_ERROR) Serial.println("End Failed");
  });

  ArduinoOTA.begin();

  Serial.println("OTA Initialized");
  Serial.print("IP address: ");
  Serial.println(WiFi.localIP());
  Serial.print("MAC: ");
  Serial.println(WiFi.macAddress());
  Serial.println();

#if defined(ESP32_RTOS) && defined(ESP32)
  xTaskCreate(
    ota_handle,          /* Task function. */
    "OTA_HANDLE",        /* String with name of task. */
    10000,            /* Stack size in bytes. */
    NULL,             /* Parameter passed as input of the task */
    1,                /* Priority of the task. */
    NULL);            /* Task handle. */
#endif
}


#endif

platformIO ini

[env:nodemcu-32s]
platform = espressif32
board = nodemcu-32s
framework = arduino
monitor_speed = 115200
debug_tool = esp-prog
debug_init_break = tbreak setup
lib_deps = 
	bblanchon/ArduinoJson@^7.0.0
	knolleary/PubSubClient@^2.8
	jandrassy/ArduinoOTA@^1.1.0

Any help is much appreciated.

Thanking you in advance.

I can see from your code that it comes from the ArduinoIDE. This accepts a lot of “non-valid C/C++” code in the form of *.ino files, in which you can simply “throw everything in”.
The ArduinoIDE makes things a lot easier for you.

You don’t have this with PlatformIO.
Here you have to write valid C/C++ code.

Some files are not included in your sample code.
I have therefore only created a simple OTA example for you.
This includes the correct separation into header (*.h) and implementation files (*.cpp).

main.cpp:

#include <Arduino.h>
#include "OTA.h"

void setup() {
    Serial.begin(115200);
    setupWiFi();
    setupOTA("myESP32");
    startOTATask();
}

void loop() {
}

credentials.h:

#ifndef CREDENTIALS_H
#define CREDENTIALS_H

extern const char* mySSID;
extern const char* myPASSWORD;

#endif

credentials.cpp:

#include "credentials.h"

const char* mySSID       = "YOUR_SSID_HERE";
const char* myPASSWORD   = "YOUR_PASSWORD_HERE";

OTA.h:

#ifndef OTA_H
#define OTA_H

void setupWiFi();
void setupOTA(const char* nameprefix);
void startOTATask();

#endif

OTA.cpp:

#include "OTA.h"

#include <Arduino.h>
#include <ArduinoOTA.h>
#include <WiFi.h>

#include "credentials.h"

static void otaTask(void* arg) {
    for (;;) {
        ArduinoOTA.handle();
        yield();
    }
}

void startOTATask() {
    xTaskCreate(otaTask, "OTA-TASK", 8192, NULL, 1, NULL);
}

void setupWiFi() {
    WiFi.mode(WIFI_STA);
    WiFi.begin(mySSID, myPASSWORD);
    while (WiFi.waitForConnectResult() != WL_CONNECTED) {
        Serial.println("Connection Failed! Rebooting...");
        delay(5000);
        ESP.restart();
    }
}

void setupOTA(const char* nameprefix) {
    const int maxlen = 40;
    char      fullhostname[maxlen];
    uint8_t   mac[6];
    WiFi.macAddress(mac);
    snprintf(fullhostname, maxlen, "%s-%02x%02x%02x", nameprefix, mac[3], mac[4], mac[5]);
    ArduinoOTA.setHostname(fullhostname);

    ArduinoOTA.onStart([]() {
        String type;
        if (ArduinoOTA.getCommand() == U_FLASH)
            type = "sketch";
        else  // U_SPIFFS
            type = "filesystem";

        // NOTE: if updating SPIFFS this would be the place to unmount SPIFFS using SPIFFS.end()
        Serial.println("Start updating " + type);
    });
    ArduinoOTA.onEnd([]() {
        Serial.println("\nEnd");
    });
    ArduinoOTA.onProgress([](unsigned int progress, unsigned int total) {
        Serial.printf("Progress: %u%%\r", (progress / (total / 100)));
    });
    ArduinoOTA.onError([](ota_error_t error) {
        Serial.printf("Error[%u]: ", error);
        if (error == OTA_AUTH_ERROR)
            Serial.println("Auth Failed");
        else if (error == OTA_BEGIN_ERROR)
            Serial.println("Begin Failed");
        else if (error == OTA_CONNECT_ERROR)
            Serial.println("Connect Failed");
        else if (error == OTA_RECEIVE_ERROR)
            Serial.println("Receive Failed");
        else if (error == OTA_END_ERROR)
            Serial.println("End Failed");
    });

    ArduinoOTA.begin();

    Serial.println("OTA Initialized");
    Serial.print("IP address: ");
    Serial.println(WiFi.localIP());
    Serial.print("MAC: ");
    Serial.println(WiFi.macAddress());
    Serial.println();
}

All files from above are located in src folder.

Main issue
The main issue is this line in your platformio.ini:

lib_deps = jandrassy/ArduinoOTA@^1.1.0

The Espressif32 Arduino Framework has a builtin ArduinoOTA library. Your code matches exact this library. But the library you installed is different!
Solution: Remove jandrassy/ArduinoOTA@^1.1.0 form your lib_deps!

Include instruction
Local header files are included with #include "name.h".
These are located in the src or include folders.

The instruction #include <name.h> is reserved for libraries which are supplied by the framework, or are installed by lib_deps or are located in the libs folder.

ArduinoJson 7.x

You’re using ArduinoJson in Version 7.x.
There have been a change since version 6.
StaticJsondocument and DynamicJsonDocument are deprecated!
There is just JsonDocument.

Code like this:

StaticJsonDocument<200> doc;

becomes to:

JsonDocument doc;

See

Many thanks @sivar2311, for the comprehensive answer including some tips on how the file extensions are used. I do appreciate your time.

Yes, I have only coded in C++ for Arduino sketches so have never had to address the separation of .h and .cpp files. The languages I use more often, do not have this separation.

Thankyou for pointing out the inclusion of the ArduinoOTA file in .ini. I knew that I had many sketches working with that library, so I thought it best that I ensure it used it.

I will take your suggestions and see how I progress.

Once again - many thanks for your assistance.

1 Like

Your code does not match the ArduinoOTA object from this library, but the built-in ArduionOTA Library.
The other way around: The example code of the built-in ArduinoOTA library does not work with jandrassy/ArduinoOTA.

1 Like

Hi,

I spent sometime implementing your suggested changes. Unfortunately, I was unable to get it to work. So I decided to create a project with simply the OTA. If I can get that working I should then be able to work out the rest (fingers crossed).

The Stripped down project still gave errors. I then tried the example project here with no luck!

Stripped down project

Main line

#include <Arduino.h>
#include "OTA.h"

void setup() {
    Serial.begin(115200);
    Serial.println("Serial Initialised");

    Serial.println("Commenced wIFI Initialisation");
    setupWiFi();
    Serial.println("Wifi Initialised");
    
    Serial.println("Commenced OTA Initialisation");
    setupOTA("myESP32");
    Serial.println("OTA Initialised");
    startOTATask();
}

void loop() {
  // not sure if this replaces ArduinoOTA.handle() 
  startOTATask();
  Serial.println("Looping");
  delay(1000);
}

OTA.ccp

#include "OTA.h"

#include <Arduino.h>
#include <ArduinoOTA.h>
#include <WiFi.h>

#include "credentials.h"

static void otaTask(void* arg) {
    for (;;) {
        ArduinoOTA.handle();
        yield();
    }
}

void startOTATask() {
    xTaskCreate(otaTask, "OTA-TASK", 8192, NULL, 1, NULL);
}

void setupWiFi() {
    WiFi.mode(WIFI_STA);
    WiFi.begin(mySSID, myPASSWORD);
    while (WiFi.waitForConnectResult() != WL_CONNECTED) {
        Serial.println("Connection Failed! Rebooting...");
        delay(5000);
        ESP.restart();
    }
}

void setupOTA(const char* nameprefix) {
    const int maxlen = 40;
    char      fullhostname[maxlen];
    uint8_t   mac[6];
    WiFi.macAddress(mac);
    snprintf(fullhostname, maxlen, "%s-%02x%02x%02x", nameprefix, mac[3], mac[4], mac[5]);
    ArduinoOTA.setHostname(fullhostname);

    ArduinoOTA.onStart([]() {
        String type;
        if (ArduinoOTA.getCommand() == U_FLASH)
            type = "sketch";
        else  // U_SPIFFS
            type = "filesystem";

        // NOTE: if updating SPIFFS this would be the place to unmount SPIFFS using SPIFFS.end()
        Serial.println("Start updating " + type);
    });
    ArduinoOTA.onEnd([]() {
        Serial.println("\nEnd");
    });
    ArduinoOTA.onProgress([](unsigned int progress, unsigned int total) {
        Serial.printf("Progress: %u%%\r", (progress / (total / 100)));
    });
    ArduinoOTA.onError([](ota_error_t error) {
        Serial.printf("Error[%u]: ", error);
        if (error == OTA_AUTH_ERROR)
            Serial.println("Auth Failed");
        else if (error == OTA_BEGIN_ERROR)
            Serial.println("Begin Failed");
        else if (error == OTA_CONNECT_ERROR)
            Serial.println("Connect Failed");
        else if (error == OTA_RECEIVE_ERROR)
            Serial.println("Receive Failed");
        else if (error == OTA_END_ERROR)
            Serial.println("End Failed");
    });

    ArduinoOTA.begin();

    Serial.println("OTA Initialized");
    Serial.print("IP address: ");
    Serial.println(WiFi.localIP());
    Serial.print("MAC: ");
    Serial.println(WiFi.macAddress());
    Serial.println();
}

OTA.h

#ifndef OTA_H
#define OTA_H

void setupWiFi();
void setupOTA(const char* nameprefix);
void startOTATask();

#endif

Compiler output

 *  Executing task in folder TestOTA: C:\Users\user\.platformio\penv\Scripts\platformio.exe run --environment nodemcu-32s 

Processing nodemcu-32s (platform: espressif32; board: nodemcu-32s; framework: arduino)
---------------------------------------------------------------------------------------------------------------------------------------------------------Verbose mode can be enabled via `-v, --verbose` option
CONFIGURATION: https://docs.platformio.org/page/boards/espressif32/nodemcu-32s.html
PLATFORM: Espressif 32 (6.5.0) > NodeMCU-32S
HARDWARE: ESP32 240MHz, 320KB RAM, 4MB Flash
DEBUG: Current (cmsis-dap) External (cmsis-dap, esp-bridge, esp-prog, iot-bus-jtag, jlink, minimodule, olimex-arm-usb-ocd, olimex-arm-usb-ocd-h, olimex-arm-usb-tiny-h, olimex-jtag-tiny, tumpa)
PACKAGES:
 - framework-arduinoespressif32 @ 3.20014.231204 (2.0.14)
 - tool-esptoolpy @ 1.40501.0 (4.5.1)
 - toolchain-xtensa-esp32 @ 8.4.0+2021r2-patch5
LDF: Library Dependency Finder -> https://bit.ly/configure-pio-ldf
LDF Modes: Finder ~ chain, Compatibility ~ soft
Found 33 compatible libraries
Scanning dependencies...
Dependency Graph
|-- ArduinoOTA @ 2.0.0
|-- WiFi @ 2.0.0
Building in release mode
Compiling .pio\build\nodemcu-32s\src\OTA.cpp.o
Compiling .pio\build\nodemcu-32s\libc51\ArduinoOTA\ArduinoOTA.cpp.o
In file included from src/OTA.cpp:4:
C:/Users/user/.platformio/packages/framework-arduinoespressif32/libraries/ArduinoOTA/src/ArduinoOTA.h:89:5: error: 'WiFiUDP' does not name a type; did you mean 'WiFi_h'?
     WiFiUDP _udp_ota;
     ^~~~~~~
     WiFi_h
src/OTA.cpp: In lambda function:
src/OTA.cpp:40:40: error: 'U_FLASH' was not declared in this scope
         if (ArduinoOTA.getCommand() == U_FLASH)
                                        ^~~~~~~
Compiling .pio\build\nodemcu-32s\FrameworkArduino\HardwareSerial.cpp.o
*** [.pio\build\nodemcu-32s\src\OTA.cpp.o] Error 1
C:/Users/user/.platformio/packages/framework-arduinoespressif32/libraries/ArduinoOTA/src/ArduinoOTA.cpp: In member function 'void ArduinoOTAClass::begin()':
C:/Users/user/.platformio/packages/framework-arduinoespressif32/libraries/ArduinoOTA/src/ArduinoOTA.cpp:131:9: error: 'WiFi' was not declared in this scope
         WiFi.macAddress(mac);
         ^~~~
C:/Users/user/.platformio/packages/framework-arduinoespressif32/libraries/ArduinoOTA/src/ArduinoOTA.cpp:131:9: note: suggested alternative: 'WiFiUDP'    
         WiFi.macAddress(mac);
         ^~~~
         WiFiUDP
C:/Users/user/.platformio/packages/framework-arduinoespressif32/libraries/ArduinoOTA/src/ArduinoOTA.cpp: In member function 'void ArduinoOTAClass::_runUpdate()':
C:/Users/user/.platformio/packages/framework-arduinoespressif32/libraries/ArduinoOTA/src/ArduinoOTA.cpp:269:5: error: 'WiFiClient' was not declared in this scope
     WiFiClient client;
     ^~~~~~~~~~
C:/Users/user/.platformio/packages/framework-arduinoespressif32/libraries/ArduinoOTA/src/ArduinoOTA.cpp:269:5: note: suggested alternative: 'DNSClient'
     WiFiClient client;
     ^~~~~~~~~~
     DNSClient
C:/Users/user/.platformio/packages/framework-arduinoespressif32/libraries/ArduinoOTA/src/ArduinoOTA.cpp:270:10: error: 'client' was not declared in this 
scope
     if (!client.connect(_ota_ip, _ota_port)) {
          ^~~~~~
C:/Users/user/.platformio/packages/framework-arduinoespressif32/libraries/ArduinoOTA/src/ArduinoOTA.cpp:270:10: note: suggested alternative: 'Client'    
     if (!client.connect(_ota_ip, _ota_port)) {
          ^~~~~~
          Client
C:/Users/user/.platformio/packages/framework-arduinoespressif32/libraries/ArduinoOTA/src/ArduinoOTA.cpp:279:36: error: 'client' was not declared in this 
scope
     while (!Update.isFinished() && client.connected()) {
                                    ^~~~~~
C:/Users/user/.platformio/packages/framework-arduinoespressif32/libraries/ArduinoOTA/src/ArduinoOTA.cpp:279:36: note: suggested alternative: 'Client'    
     while (!Update.isFinished() && client.connected()) {
                                    ^~~~~~
                                    Client
C:/Users/user/.platformio/packages/framework-arduinoespressif32/libraries/ArduinoOTA/src/ArduinoOTA.cpp:338:9: error: 'client' was not declared in this scope
         client.print("OK");
         ^~~~~~
C:/Users/user/.platformio/packages/framework-arduinoespressif32/libraries/ArduinoOTA/src/ArduinoOTA.cpp:338:9: note: suggested alternative: 'Client'     
         client.print("OK");
         ^~~~~~
         Client
C:/Users/user/.platformio/packages/framework-arduinoespressif32/libraries/ArduinoOTA/src/ArduinoOTA.cpp:353:27: error: 'client' was not declared in this 
scope
         Update.printError(client);
                           ^~~~~~
C:/Users/user/.platformio/packages/framework-arduinoespressif32/libraries/ArduinoOTA/src/ArduinoOTA.cpp:353:27: note: suggested alternative: 'Client'    
         Update.printError(client);
                           ^~~~~~
                           Client
*** [.pio\build\nodemcu-32s\libc51\ArduinoOTA\ArduinoOTA.cpp.o] Error 1
============================================================== [FAILED] Took 5.53 seconds ==============================================================

 *  The terminal process "C:\Users\user\.platformio\penv\Scripts\platformio.exe 'run', '--environment', 'nodemcu-32s'" terminated with exit code: 1. 
 *  Terminal will be reused by tasks, press any key to close it. 

platformio.ini

; PlatformIO Project Configuration File
;
;   Build options: build flags, source filter
;   Upload options: custom upload port, speed and extra flags
;   Library options: dependencies, extra library storages
;   Advanced options: extra scripting
;
; Please visit documentation for the other options and examples
; https://docs.platformio.org/page/projectconf.html

[env:nodemcu-32s]
platform = espressif32
board = nodemcu-32s
;board = esp32dev
framework = arduino

ArduinoOTA example

Main line

#include <WiFi.h>
#include <ESPmDNS.h>
#include <NetworkUdp.h>
#include <ArduinoOTA.h>

const char *ssid = "..........";
const char *password = "..........";

void setup() {
  Serial.begin(115200);
  Serial.println("Booting");
  WiFi.mode(WIFI_STA);
  WiFi.begin(ssid, password);
  while (WiFi.waitForConnectResult() != WL_CONNECTED) {
    Serial.println("Connection Failed! Rebooting...");
    delay(5000);
    ESP.restart();
  }

  // Port defaults to 3232
  // ArduinoOTA.setPort(3232);

  // Hostname defaults to esp3232-[MAC]
  // ArduinoOTA.setHostname("myesp32");

  // No authentication by default
  // ArduinoOTA.setPassword("admin");

  // Password can be set with it's md5 value as well
  // MD5(admin) = 21232f297a57a5a743894a0e4a801fc3
  // ArduinoOTA.setPasswordHash("21232f297a57a5a743894a0e4a801fc3");

  ArduinoOTA
    .onStart([]() {
      String type;
      if (ArduinoOTA.getCommand() == U_FLASH) {
        type = "sketch";
      } else {  // U_SPIFFS
        type = "filesystem";
      }

      // NOTE: if updating SPIFFS this would be the place to unmount SPIFFS using SPIFFS.end()
      Serial.println("Start updating " + type);
    })
    .onEnd([]() {
      Serial.println("\nEnd");
    })
    .onProgress([](unsigned int progress, unsigned int total) {
      Serial.printf("Progress: %u%%\r", (progress / (total / 100)));
    })
    .onError([](ota_error_t error) {
      Serial.printf("Error[%u]: ", error);
      if (error == OTA_AUTH_ERROR) {
        Serial.println("Auth Failed");
      } else if (error == OTA_BEGIN_ERROR) {
        Serial.println("Begin Failed");
      } else if (error == OTA_CONNECT_ERROR) {
        Serial.println("Connect Failed");
      } else if (error == OTA_RECEIVE_ERROR) {
        Serial.println("Receive Failed");
      } else if (error == OTA_END_ERROR) {
        Serial.println("End Failed");
      }
    });

  ArduinoOTA.begin();

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

void loop() {
  ArduinoOTA.handle();
}

Terminal log

 *  Executing task in folder OTATest02: C:\Users\user\.platformio\penv\Scripts\platformio.exe run --environment nodemcu-32s 

Processing nodemcu-32s (platform: espressif32; board: esp32dev; framework: arduino)
---------------------------------------------------------------------------------------------------------------------------------------------------------Verbose mode can be enabled via `-v, --verbose` option
CONFIGURATION: https://docs.platformio.org/page/boards/espressif32/esp32dev.html
PLATFORM: Espressif 32 (6.5.0) > Espressif ESP32 Dev Module
HARDWARE: ESP32 240MHz, 320KB RAM, 4MB Flash
DEBUG: Current (cmsis-dap) External (cmsis-dap, esp-bridge, esp-prog, iot-bus-jtag, jlink, minimodule, olimex-arm-usb-ocd, olimex-arm-usb-ocd-h, olimex-arm-usb-tiny-h, olimex-jtag-tiny, tumpa)
PACKAGES:
 - framework-arduinoespressif32 @ 3.20014.231204 (2.0.14)
 - tool-esptoolpy @ 1.40501.0 (4.5.1)
 - toolchain-xtensa-esp32 @ 8.4.0+2021r2-patch5
LDF: Library Dependency Finder -> https://bit.ly/configure-pio-ldf
LDF Modes: Finder ~ chain, Compatibility ~ soft
Found 33 compatible libraries
Scanning dependencies...
Dependency Graph
|-- ArduinoOTA @ 2.0.0
|-- ESPmDNS @ 2.0.0
|-- WiFi @ 2.0.0
Building in release mode
Compiling .pio\build\nodemcu-32s\src\main.cpp.o
Archiving .pio\build\nodemcu-32s\lib152\libWiFi.a
Archiving .pio\build\nodemcu-32s\lib484\libESPmDNS.a
Archiving .pio\build\nodemcu-32s\libbc0\libUpdate.a
src/main.cpp:3:10: fatal error: NetworkUdp.h: No such file or directory

********************************************************************
* Looking for NetworkUdp.h dependency? Check our library registry!
*
* CLI  > platformio lib search "header:NetworkUdp.h"
* Web  > https://registry.platformio.org/search?q=header:NetworkUdp.h
*
********************************************************************

 #include <NetworkUdp.h>
          ^~~~~~~~~~~~~~
compilation terminated.
Compiling .pio\build\nodemcu-32s\libc51\ArduinoOTA\ArduinoOTA.cpp.o
*** [.pio\build\nodemcu-32s\src\main.cpp.o] Error 1
C:/Users/user/.platformio/packages/framework-arduinoespressif32/libraries/ArduinoOTA/src/ArduinoOTA.cpp: In member function 'void ArduinoOTAClass::begin()':
C:/Users/user/.platformio/packages/framework-arduinoespressif32/libraries/ArduinoOTA/src/ArduinoOTA.cpp:131:9: error: 'WiFi' was not declared in this scope
         WiFi.macAddress(mac);
         ^~~~
C:/Users/user/.platformio/packages/framework-arduinoespressif32/libraries/ArduinoOTA/src/ArduinoOTA.cpp:131:9: note: suggested alternative: 'WiFiUDP'    
         WiFi.macAddress(mac);
         ^~~~
         WiFiUDP
C:/Users/user/.platformio/packages/framework-arduinoespressif32/libraries/ArduinoOTA/src/ArduinoOTA.cpp: In member function 'void ArduinoOTAClass::_runUpdate()':
C:/Users/user/.platformio/packages/framework-arduinoespressif32/libraries/ArduinoOTA/src/ArduinoOTA.cpp:269:5: error: 'WiFiClient' was not declared in this scope
     WiFiClient client;
     ^~~~~~~~~~
C:/Users/user/.platformio/packages/framework-arduinoespressif32/libraries/ArduinoOTA/src/ArduinoOTA.cpp:269:5: note: suggested alternative: 'DNSClient'  
     WiFiClient client;
     ^~~~~~~~~~
     DNSClient
C:/Users/user/.platformio/packages/framework-arduinoespressif32/libraries/ArduinoOTA/src/ArduinoOTA.cpp:270:10: error: 'client' was not declared in this 
scope
     if (!client.connect(_ota_ip, _ota_port)) {
          ^~~~~~
C:/Users/user/.platformio/packages/framework-arduinoespressif32/libraries/ArduinoOTA/src/ArduinoOTA.cpp:270:10: note: suggested alternative: 'Client'    
     if (!client.connect(_ota_ip, _ota_port)) {
          ^~~~~~
          Client
C:/Users/user/.platformio/packages/framework-arduinoespressif32/libraries/ArduinoOTA/src/ArduinoOTA.cpp:279:36: error: 'client' was not declared in this 
scope
     while (!Update.isFinished() && client.connected()) {
                                    ^~~~~~
C:/Users/user/.platformio/packages/framework-arduinoespressif32/libraries/ArduinoOTA/src/ArduinoOTA.cpp:279:36: note: suggested alternative: 'Client'    
     while (!Update.isFinished() && client.connected()) {
                                    ^~~~~~
                                    Client
C:/Users/user/.platformio/packages/framework-arduinoespressif32/libraries/ArduinoOTA/src/ArduinoOTA.cpp:338:9: error: 'client' was not declared in this scope
         client.print("OK");
         ^~~~~~
C:/Users/user/.platformio/packages/framework-arduinoespressif32/libraries/ArduinoOTA/src/ArduinoOTA.cpp:338:9: note: suggested alternative: 'Client'     
         client.print("OK");
         ^~~~~~
         Client
C:/Users/user/.platformio/packages/framework-arduinoespressif32/libraries/ArduinoOTA/src/ArduinoOTA.cpp:353:27: error: 'client' was not declared in this 
scope
         Update.printError(client);
                           ^~~~~~
C:/Users/user/.platformio/packages/framework-arduinoespressif32/libraries/ArduinoOTA/src/ArduinoOTA.cpp:353:27: note: suggested alternative: 'Client'    
         Update.printError(client);
                           ^~~~~~
                           Client
*** [.pio\build\nodemcu-32s\libc51\ArduinoOTA\ArduinoOTA.cpp.o] Error 1
============================================================== [FAILED] Took 5.21 seconds ==============================================================

 *  The terminal process "C:\Users\user\.platformio\penv\Scripts\platformio.exe 'run', '--environment', 'nodemcu-32s'" terminated with exit code: 1. 
 *  Terminal will be reused by tasks, press any key to close it. 

Task error message

With both these projects I appear to get a new task error that pops up and I’m not sure what it’s all about!

Error: The PlatformIO task detection didn't contribute a task for the following configuration:
{
    "type": "PlatformIO",
    "task": "Verbose Build",
    "problemMatcher": [
        "$platformio"
    ],
    "label": "PlatformIO: Verbose Build",
    "group": {
        "kind": "build",
        "isDefault": true
    }
}
The task will be ignored.

BTW, do I have to include the PubSubClient or does the environment have that as well?

Your assistance is much appreciated - thank you.

This won’t work because it uses code from Arduino 3.x.x (which is not yet available on PlatformIO).
The correct Basic-OTA example (Arduino 2.x.x) is located here comiples without issues.

Oh no! I just grabbed this up, because there was an attempt in it to do ArduinoOTA.handle() in a seperated task. So the code was not written by you?

There is no need to run this in a seperated task.
As I said, I only did it because it was in your code.

If you’re not familiar about running tasks on an ESP32, leave it out for simplicity and just call ArduinoOTA.handle() inside the loop() function.

Your stripped down files compiling perfect for me.
Tested on Espressif32 @ 6.6.0 (Arduino 2.0.14 - same as yours): platform = Espressif32 @ 6.6.0
as well as Espressif32 @ 6.7.0 (Arduino 2.0.16) platform = Espressif32 @ 6.6.0

Maybe there is an issue with your installed Espressif32 platform.

  • Close VS Code
  • Delete all folders named “espresiff…” from C:\Users\<username>\.platformio\platforms
  • Restart VS Code
  • Wait until all PlatformIO tasks finished (<-- reinstallation of Espressif32 Platform)

Woohooo! It compiled. The re-installation of the Espressiff folder sorted it out. I have loaded the sketch and it runs and I was able to debug. However, I have not tried loading software OTA as yet!

Many thanks for your perseverance - I really do appreciate it.

I did have to include the ArduinoOTA in the main ccp to be able to refer AduinoOTA.Handle() - not sure why.

Next to get the MQTT working. It requires the wifi client and I see that as the next challenge! I’ll play around with it and see how I go before hollowing for help!

Once again, many thanks for your assistance.

Reason: the ArduinoOTA object would not be available to your main.cpp - it is declared in the ArduinoOTA.h header.

1 Like

Hi @sivar2311 - just a quick update.

Going back to my original project sketch I was hitting multiple issues with the Wifi Client etc. What I noticed was that it was still compiling with an older version ArduinoOTA, even though I had removed it from the .ini file.

I then discovered that the library files were still in a folder in .pio/libdeps/nodemcu-32s (along with the other project related libraries). I deleted the folder and the whole project compiled error free! I’m sure there are plenty of bugs to resolve, but that is where platformIO will really prove it’s worth!

Many thanks for your time, again - it certainly will save me heaps of time in the future.

kindest regards.

1 Like