expected primary-expression before '(' token

I am kinda new to ARDUINO

I am sure this topic has been on the board a few times.

I have came cross the same issue and search my code for any missing , or ; etc and it seems to be fine

the Sketch is combination of two example trying to get user to enter parameters for both wifiManager.autoConnect and Adafruit_MQTT_Client

sketch is quite long so I have attached the file.

expected primary-expression before '(' token --- is at line 205

Hope someone can help

You have a brace {} nesting problem, and this problem is caused by you not breaking up your sketch into manageable chunks - subfunctions with meaningful names.

You definetly need to go through the program and check that you have matching opening braces { and closing braces } on functions etc.

I had a good look at the code
found a extra { however that wasn't the problem and still getting same issue

break the long setup to two function

and same issue

I have change the

#define mqtt_serv MQTT_SERV
#define mqtt_port MQTT_PORT

#define mqtt_name MQTT_NAME
#define mqtt_pass MQTT_PASS

to
#define mqtt_serv "io.adafruit.com"
#define mqtt_port 1883

#define mqtt_name "name"
#define mqtt_pass "xxxxxxxxxxx"

Now I get a different issue
'mqtt' was not declared in this scope

in function MQTT_connect

Please post your complete revised program using code tags when you do

See Read this before posting a programming question

This is my 1st time seeking help on line how do I code tags

Ok this is the code part 1

#include <FS.h>                   //this needs to be first, or it all crashes and burns...

#if defined(ESP8266)
#include <ESP8266WiFi.h>          //https://github.com/esp8266/Arduino
#else
#include <WiFi.h>
#endif

//for LED status
#include <Ticker.h>
Ticker ticker;

//needed for library
#include <ESPAsyncWebServer.h>
#include <ESPAsyncWiFiManager.h>         //https://github.com/tzapu/WiFiManager

#include <ArduinoJson.h>          //https://github.com/bblanchon/ArduinoJson

#include "Adafruit_MQTT.h"
#include "Adafruit_MQTT_Client.h"

//define your default values here, if there are different values in config.json, they are overwritten.
//length should be max size + 1
//char mqtt_server[40];
//char mqtt_port[6] = "8080";
//char blynk_token[33] = "YOUR_BLYNK_TOKEN";
char MQTT_SERV[40] = "io.adafruit.com";
char MQTT_PORT_C[6] = "1883";
char MQTT_NAME[20] = "ABC";
char MQTT_PASS[33] = "XXX";
//default custom static IP
char static_ip[16] = "";
char static_gw[16] = "";
char static_sn[16] = "";

#ifndef LED_BUILTIN
#define LED_BUILTIN 13 // ESP32 DOES NOT DEFINE LED_BUILTIN
#endif
int LED = LED_BUILTIN;
int ledPin = 12;
//flag for saving data
bool shouldSaveConfig = false;

void tick()
{
  //toggle state
  digitalWrite(LED, !digitalRead(LED));     // set pin to the opposite state
}
//callback notifying us of the need to save config
void saveConfigCallback () {
  Serial.println("Should save config");
  shouldSaveConfig = true;
}

AsyncWebServer server(80);
DNSServer dns;

Part 2

void Read_Config(){
  if (SPIFFS.begin()) {
    Serial.println("mounted file system");
    if (SPIFFS.exists("/config.json")) {
      //file exists, reading and loading
      Serial.println("reading config file");
      File configFile = SPIFFS.open("/config.json", "r");
      if (configFile) {
        Serial.println("opened config file");
        size_t size = configFile.size();
        // Allocate a buffer to store contents of the file.
        std::unique_ptr<char[]> buf(new char[size]);

        configFile.readBytes(buf.get(), size);
        DynamicJsonBuffer jsonBuffer;
        JsonObject& json = jsonBuffer.parseObject(buf.get());
        json.printTo(Serial);
        if (json.success()) {
          Serial.println("\nparsed json");

          strcpy(MQTT_SERV, json["MQTT_SERV"]);
          strcpy(MQTT_PORT_C, json["MQTT_PORT_C"]);
          strcpy(MQTT_NAME, json["MQTT_NAME"]);
          strcpy(MQTT_PASS, json["MQTT_PASS"]);
          

          if(json["ip"]) {
            Serial.println("setting custom ip from config");
            //static_ip = json["ip"];
            strcpy(static_ip, json["ip"]);
            strcpy(static_gw, json["gateway"]);
            strcpy(static_sn, json["subnet"]);
            //strcat(static_ip, json["ip"]);
            //static_gw = json["gateway"];
            //static_sn = json["subnet"];
            Serial.println(static_ip);
          
/*            Serial.println("converting ip");
            IPAddress ip = ipFromCharArray(static_ip);
            Serial.println(ip);*/
          } else {
            Serial.println("no custom ip in config");
          }
        } else {
          Serial.println("failed to load json config");
        }
        configFile.close();
      }
    }
  } else {
    Serial.println("failed to mount FS");
  }
  //end read
}
void Save_Cust_Para(){
  if (shouldSaveConfig) {
    Serial.println("saving config");
    DynamicJsonBuffer jsonBuffer;
    JsonObject& json = jsonBuffer.createObject();
    json["MQTT_SERV"] = MQTT_SERV;
    json["MQTT_PORT_C"] = MQTT_PORT_C;
    json["MQTT_NAME"] = MQTT_NAME;
    json["MQTT_PASS"] = MQTT_PASS;

    json["ip"] = WiFi.localIP().toString();
    json["gateway"] = WiFi.gatewayIP().toString();
    json["subnet"] = WiFi.subnetMask().toString();

    File configFile = SPIFFS.open("/config.json", "w");
    if (!configFile) {
      Serial.println("failed to open config file for writing");
    }

    json.prettyPrintTo(Serial);
    json.printTo(configFile);
    configFile.close();
    //end save
  }
  
}

Part 3

void setup() {
  // put your setup code here, to run once:
  Serial.begin(115200);
  Serial.println();
 //set led pin as output
  pinMode(LED, OUTPUT);
  // start ticker with 0.5 because we start in AP mode and try to connect
  ticker.attach(0.6, tick);
  
  //clean FS, for testing
  //SPIFFS.format();

  //read configuration from FS json
  Serial.println("mounting FS...");

  Read_Config();
  
  Serial.println(static_ip);
  Serial.println(MQTT_NAME);
  Serial.println(MQTT_SERV);
  Serial.println(MQTT_PASS); 


  // The extra parameters to be configured (can be either global or just in the setup)
  // After connecting, parameter.getValue() will get you the configured value
  // id/name placeholder/prompt default length
  AsyncWiFiManagerParameter custom_MQTT_SERV("server", "mqtt server", MQTT_SERV, 40);
  AsyncWiFiManagerParameter custom_MQTT_PORT_C("port", "mqtt port", MQTT_PORT_C, 6);
  AsyncWiFiManagerParameter custom_MQTT_NAME("name", "mqtt name", MQTT_NAME, 20);
  AsyncWiFiManagerParameter custom_MQTT_PASS("pass", "mqtt pass", MQTT_PASS, 33);

  //WiFiManager
  //Local intialization. Once its business is done, there is no need to keep it around
  AsyncWiFiManager wifiManager(&server,&dns);

  //set config save notify callback
  wifiManager.setSaveConfigCallback(saveConfigCallback);

  //set static ip
  IPAddress _ip,_gw,_sn;
  _ip.fromString(static_ip);
  _gw.fromString(static_gw);
  _sn.fromString(static_sn);

  wifiManager.setSTAStaticIPConfig(_ip, _gw, _sn);

  //add all your parameters here
  wifiManager.addParameter(&custom_MQTT_SERV);
  wifiManager.addParameter(&custom_MQTT_PORT_C);
  wifiManager.addParameter(&custom_MQTT_NAME);
  wifiManager.addParameter(&custom_MQTT_PASS);

  //reset settings - for testing
  //wifiManager.resetSettings();

  //set minimu quality of signal so it ignores AP's under that quality
  //defaults to 8%
  wifiManager.setMinimumSignalQuality();

  //sets timeout until configuration portal gets turned off
  //useful to make it all retry or go to sleep
  //in seconds
  //wifiManager.setTimeout(120);

  //fetches ssid and pass and tries to connect
  //if it does not connect it starts an access point with the specified name
  //here  "AutoConnectAP"
  //and goes into a blocking loop awaiting configuration
  if (!wifiManager.autoConnect("AutoConnectAP", "password")) {
    Serial.println("failed to connect and hit timeout");
    delay(3000);
    //reset and try again, or maybe put it to deep sleep
    ESP.reset();
    delay(5000);
  }

  //if you get here you have connected to the WiFi
  Serial.println("connected...yeey :)");
  ticker.detach();
  //keep LED on
  digitalWrite(LED, LOW);
  
  pinMode(ledPin, OUTPUT);
  //read updated parameters
  strcpy(MQTT_SERV, custom_MQTT_SERV.getValue());
  strcpy(MQTT_PORT_C, custom_MQTT_PORT_C.getValue());
  strcpy(MQTT_NAME, custom_MQTT_NAME.getValue());
  strcpy(MQTT_PASS, custom_MQTT_PASS.getValue());
  unsigned int MQTT_PORT = atoi (MQTT_PORT_C);
  
  /*#define mqtt_serv MQTT_SERV
  #define mqtt_port MQTT_PORT 
  
  #define mqtt_name MQTT_NAME 
  #define mqtt_pass MQTT_PASS */ 
  #define mqtt_serv "io.adafruit.com"
  #define mqtt_port 1883
  
  #define mqtt_name "NAME" 
  #define mqtt_pass "aio_XXXXXXXXXXXXXXXXXXXX"  
  WiFiClient client;  
  Adafruit_MQTT_Client mqtt(&client, mqtt_serv, mqtt_port, mqtt_name, mqtt_pass);

  //Set up the feed you're subscribing to
  Adafruit_MQTT_Subscribe OpenClose = Adafruit_MQTT_Subscribe(&mqtt, mqtt_name "/f/OpenClose");
  
  //save the custom parameters to FS
  Save_Cust_Para();

  Serial.println("local ip");
  Serial.println(WiFi.localIP());
  Serial.println(WiFi.gatewayIP());
  Serial.println(WiFi.subnetMask());

   //Subscribe to the onoff feed
  mqtt.subscribe(&OpenClose);

  pinMode(ledPin, OUTPUT);
  digitalWrite(ledPin, HIGH);
}

void loop()
{
  MQTT_connect();
  
  //Read from our subscription queue until we run out, or
  //wait up to 5 seconds for subscription to update
  Adafruit_MQTT_Subscribe * subscription;
  while ((subscription = mqtt.readSubscription(5000)))
  {
    //If we're in here, a subscription updated...
    if (subscription == &OpenClose)
    {
      //Print the new value to the serial monitor
      Serial.print("openClose: ");
      Serial.println((char*) OpenClose.lastread);
      
      //If the new value is  "ON", turn the light on.
      //Otherwise, turn it off.
      if (!strcmp((char*) OpenClose.lastread, "ON"))
      {
        //Active low logic
        digitalWrite(ledPin, HIGH);
      }
      else
      {
        digitalWrite(ledPin, LOW);
      }
    }
  }

  // ping the server to keep the mqtt connection alive
  if (!mqtt.ping())
  {
    mqtt.disconnect();
  }
}




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!");
}

I think, the problem is mqtt hasn't been declared Globally. and not sure how it can be done

and I still get an error line 241 when I change to
/*#define mqtt_serv MQTT_SERV
#define mqtt_port MQTT_PORT

#define mqtt_name MQTT_NAME
#define mqtt_pass MQTT_PASS */

instead of
#define mqtt_serv "io.adafruit.com"
#define mqtt_port 1883

#define mqtt_name "NAME"
#define mqtt_pass "aio_XXXXXXXXXXXXXXXXXXXX"

Why the heck are your #defines doing slap in the middle of your setup() function?

#defines belong at the top of your program, before your global variable definitions (or at the very least OUTSIDE of any function scope).

You do realise what a #define is, don’t you?

It’s NOT a dynamic runtime expression like a variable. That’s what VARIABLES are for!
#define is a compile time only MACRO definition*. It says to the compiler everywhere you see a certain value, replace that with the given text.

  • it’s a little bit more complex and powerful than that, but that will do for starters.

Regardless there is absolutely nothing you can do with a #define that you couldn’t do by writing the code out longhand and achieve the exact same code as a result.

if i change them to
unsigned int mqtt_port = atoi (MQTT_PORT_C);
char* mqtt_serv = MQTT_SERV;
char* mqtt_name = MQTT_NAME;
char* mqtt_pass = MQTT_PASS;

I get this error

expected primary-expression before '(' token
..

I have checked all bracket and bracing and they all look correct

it is obvious I am missing something but can't find it

So the situation is that the Adafruit_MQTT_Client object needs a bunch of constructor parameters

  Adafruit_MQTT_Client mqtt(&client, mqtt_serv, mqtt_port, mqtt_name, mqtt_pass);

And these are read from a json file /config.json . So you can't simply define mqtt globally. However, the loop() function needs it, so it can't be defined locally in the setup() function.

You have a more serious problen than this: because your mqtt varible is defined locally in setup(), it dissapears once setup() is complete. The memory will be overwritten by subsequent activity, completely scrambling it. If mqtt and client are to have a lifetime beyond the execution of setup(), they need to be static. You can do this by adding the 'static' modifier to the variable declaration, or by declaring them globally, outside the function.

Ordinarily, use of dynamic memory is considered harmful (Goto - Wikipedia) , but here it's warranted. Using dynamic memory is a problem mostly when things are allocated and freed repeatedly, causing the hep to become fragmented. But here, you are only doing it once.

So, add global variables

  WiFiClient client;  
  Adafruit_MQTT_Client *mqtt;

and use the global mqtt rather than redefining it in your function:

  mqtt = new Adafruit_MQTT_Client(&client, mqtt_serv, mqtt_port, mqtt_name, mqtt_pass);

This will mean that all instances of mqtt.something need to be changed to mqtt->something , and all instances of &mqtt change to mqtt (without the ampersand). We no longer need to pass a pointer to mqtt, because mqtt is a pointer.

You will need to do the same thing to OpenClose (incidentally, initial caps are for class names, not variables).

----SNIP! ----
WiFiClient client;  
Adafruit_MQTT_Client *mqtt;
Adafruit_MQTT_Subscribe *openClose;
----SNIP! ----

void setup() {
----SNIP! ----
  // load json, etc
  mqtt = new Adafruit_MQTT_Client(&client, mqtt_serv, mqtt_port, mqtt_name, mqtt_pass);

  //Set up the feed you're subscribing to
  openClose = new Adafruit_MQTT_Subscribe(mqtt, mqtt_name "/f/OpenClose");
  
----SNIP! ----

   //Subscribe to the onoff feed
  mqtt.subscribe(&openClose);

----SNIP! ----
}

void loop() {
----SNIP! ----
  if (!mqtt->ping())
  {
    mqtt->disconnect();
  }
----SNIP! ----
}

And you will also need to change those dots to arrows in MQTT_connect().

Having said all that, I'm surprised that there isn't a null constructor and an init method. Unless, of course, there is. Something like:

----SNIP! ----
WiFiClient client;  
Adafruit_MQTT_Client mqtt;
Adafruit_MQTT_Subscribe openClose;
----SNIP! ----

void setup() {
----SNIP! ----
  // load json, etc
  mqtt.init(&client, mqtt_serv, mqtt_port, mqtt_name, mqtt_pass);

  //Set up the feed you're subscribing to
  openClose.subscribe(&mqtt, mqtt_name "/f/OpenClose");

Read the docs, or at least read the .h file, to find out.

Thank you
You got me in to right directions.
I am working on it still a few issues with declaration but I think I should get it fixed

Hi Paul

I have been trying to make it work and I thought I got it working however

if I do

----SNIP! ----
WiFiClient client; 
Adafruit_MQTT_Client *mqtt;
Adafruit_MQTT_Subscribe *openClose;

void setup() {
----SNIP! ----
unsigned int mqtt_port = atoi (MQTT_PORT_C);
  char* mqtt_serv = MQTT_SERV;
  char* mqtt_name = MQTT_NAME;
  char* mqtt_pass = MQTT_PASS;
  
  
 // load json, etc
  mqtt = new Adafruit_MQTT_Client(&client, mqtt_serv, mqtt_port, mqtt_name, mqtt_pass);

  //Set up the feed you're subscribing to  
  openClose = new Adafruit_MQTT_Subscribe(mqtt, mqtt_name "/f/openClose"); -- this is line 215
----SNIP! ----
/Subscribe to the onoff feed
  mqtt->subscribe(openClose);
----SNIP! ----

I get the same error in line 215
expected ')' before string constant

If I do the following

----SNIP! ----

WiFiClient client; 
Adafruit_MQTT_Client *mqtt;
Adafruit_MQTT_Subscribe *openClose;
----SNIP! ----
#define mqtt_name "my name"
----SNIP! ----

void setup() {
----SNIP! ----

  unsigned int mqtt_port = atoi (MQTT_PORT_C);
  char* mqtt_serv = MQTT_SERV;
  //char* mqtt_name = MQTT_NAME;
  char* mqtt_pass = MQTT_PASS;
  
  
 // load json, etc
  mqtt = new Adafruit_MQTT_Client(&client, mqtt_serv, mqtt_port, mqtt_name, mqtt_pass);

  //Set up the feed you're subscribing to
  openClose = new Adafruit_MQTT_Subscribe(mqtt, mqtt_name "/f/openClose"); -- line 215
----SNIP! ----
//Subscribe to the onoff feed
  mqtt->subscribe(openClose);
----SNIP! ----

void loop()
{
  MQTT_connect();

  //Read from our subscription queue until we run out, or
  //wait up to 5 seconds for subscription to update
  Adafruit_MQTT_Subscribe * subscription;
  while ((subscription = mqtt->readSubscription(5000)))
  {
    //If we're in here, a subscription updated...
    if (subscription == openClose->subscribe)  -- line 269

Compiler will pass line 215 and stops at line 269

exit status 1
'class Adafruit_MQTT_Subscribe' has no member named 'subscribe'

I have two questions

  1. why mqtt = new Adafruit_MQTT_Client(&client, mqtt_serv, mqtt_port, mqtt_name, mqtt_pass); -- doesn't like char* mqtt_name = MQTT_NAME;

I have checked h file and user name is const char* --- same as server name and pass

class Adafruit_MQTT {
public:
  Adafruit_MQTT(const char *server, uint16_t port, const char *cid,
                const char *user, const char *pass);

  Adafruit_MQTT(const char *server, uint16_t port, const char *user = "",
                const char *pass = "");
  1. please help me to understand if (subscription == openClose->subscribe) and its error

I have attached the h file too

one last note
I did try your last suggestion and it didn't like it
error at
Adafruit_MQTT_Client mqtt;

exit status 1
no matching function for call to 'Adafruit_MQTT_Client::Adafruit_MQTT_Client()'

your help much appreciated

Adafruit_MQTT.h (11.4 KB)

I haven't heard from Paul,
does anyone else have an answer please

benmadi:
I haven't heard from Paul,
does anyone else have an answer please

I suspect not when they have to piece together your project from a series of "snippets are us" posts.

If you post a ZIP of your project (assuming it is too large for a single post and you can't be bothered to create a minimum recreate example) then perhaps someone might help.

Forget zip - that discourages people too. You can attach your code to a post, however big it is.

It seems like you are missing a } to close off your setup function. idk if this it it though. I hope this solves your problem!

I have attached modified code.

AutoConnectWithFSParametersAndCustomIP-2.ino (9.38 KB)