src\main.cpp:31:45: error: ‘callback’ was not declared in this scope
PubSubClient client(mqtt_server, mqtt_port, callback, wifiClient);
The callback
function was not pre-declared. It needs it’s prototype written above the usage of it. It seems that this was originally a .ino
sketch but the conversion to cpp wasn’t one properly in this case.
So, writing
void callback(char* topic, byte* payload, unsigned int length);
above the PubSubClient client
line solves that.
It then says
src\main.cpp:33:65: error: no matching function for call to ‘PubSubClient::PubSubClient(String&, uint16_t&, void (&)(char*, byte*, unsigned int), WiFiClient&)’
PubSubClient client(mqtt_server, mqtt_port, callback, wifiClient);
So you’re trying to call a constructor with the argument types
- String&
- uint16_t&,
- void (&)(char*, byte*, unsigned int),
- WiFiClient&
So let’s see what constructors with what types are available an which are not.
First, you can see that there are no constructors which take a String
or a String&
(reference) – either pure strings (char*
) or IPAddress objects or pointers to the individual bytes of the IP (source).
Thus we rewrite the lines
String mqtt_server = "mqtt.mydomain";
...
PubSubClient client(mqtt_server, mqtt_port, callback, wifiClient);
to
#define MQTT_SERVER "mqtt.mydomain"
..
PubSubClient client(MQTT_SERVER , mqtt_port, callback, wifiClient);
Next up the same thing with the code
if (client.connect(clientId.c_str(),mqtt_user,mqtt_password)) {
thatcomplains
src/main.cpp:213:30: error: no matching function for call to ‘PubSubClient::connect(String&)’
if (client.connect(clientId)) {
.pio/libdeps/esp12e/PubSubClient/src/PubSubClient.h:145:12: note: boolean PubSubClient::connect(const char*)
boolean connect(const char* id);
So you’re again trying to call a function that accepts a C-string char*
with a String
object – the call to c_str()
on the object is missing (or efine it as a pure string in the first place).
I’m not sure about this line since I don’t have the definition of mqtt_user
and mqtt_password
if (client.connect(clientId.c_str(),mqtt_user,mqtt_password)) {
but if these are String
variables, then they also need c_str()
.
And finally
src\main.cpp:203:37: error: no matching function for call to ‘PubSubClient::publish(String&, String&)’
if (client.publish(topic, Jstate)) {
^
src\main.cpp:203:37: note: candidates are:
In file included from src\main.cpp:7:0:
C:\Users\Max.platformio\lib\PubSubClient\src/PubSubClient.h:151:12: note: boolean PubSubClient::publish(const char*, const char*)
boolean publish(const char* topic, const char* payload);
You’re attempgin to call client.publish()
with two String
objects as argument, but it’s only accepting C-strings. Adding c_str()
conversion calls solves that again.
Nitpick: You write in your code
void callback(char* topic, byte* payload, unsigned int length) {
Serial.print("Message arrived [");
Serial.print(topic);
Serial.print("] '");
String pl ="";
for (int i = 0; i < length; i++) {
Serial.print((char)payload[i]);
pl += (char)payload[i];
}
but the for(int i = ..
is wrong when length
is unsigned. i
should be an unsigned int
, too.
So your whole fixed code (while removing the reference to SSID_access.h
and substituting the guesse content) looks like
#include <Arduino.h>
#include <DNSServer.h>
#include <ESP8266WiFi.h>
#include <ESPAsyncTCP.h>
#include <ESPAsyncWebServer.h>
#include <AsyncElegantOTA.h>
#include <PubSubClient.h>
//#include <SSID_access.h>
//assume content like
String mqtt_user = "unknown";
String mqtt_password = "unknown2";
#define MY_SSID "my ssid"
#define SSID_PSW "my_ssid_password"
#define LED 2
#define updated 20210217
String topic = "jlight";
#define MQTT_SERVER "mqtt.mydomain"
uint16_t mqtt_port = 51883;
String Jstate = "off";
String clientId = "ESP"; // IP address added later
int latest = micros();
// reconnect every 5 seconds
long lastReconnectAttempt = 0;
// auto publish every hour
long publishDelay = 3600000;
long lastPublish = -publishDelay;
long publish = 0;
DNSServer dnsServer;
AsyncWebServer server(80);
void callback(char* topic, byte* payload, unsigned int length);
WiFiClient wifiClient;
PubSubClient client(MQTT_SERVER, mqtt_port, callback, wifiClient);
//PubSubClient client(mqtt_server, mqtt_port, wifiClient);
//PubSubClient client(wifiClient);
boolean reconnect() {
Serial.print("Attempting MQTT connection from ");
Serial.print(WiFi.localIP());
Serial.print(" as ");
clientId = "ESP";
clientId += WiFi.localIP().toString();
Serial.println(clientId);
// Attempt to connect
if (client.connect(clientId.c_str(),mqtt_user.c_str(),mqtt_password.c_str())) {
Serial.println("connected");
// Once connected, publish an announcement...
client.publish("jlight", (char*)Jstate.c_str());
// ... and resubscribe
client.subscribe("jlight/#");
}
return client.connected();
}
void callback(char* topic, byte* payload, unsigned int length) {
Serial.print("Message arrived [");
Serial.print(topic);
Serial.print("] '");
String pl ="";
for (unsigned int i = 0; i < length; i++) {
Serial.print((char)payload[i]);
pl += (char)payload[i];
}
Serial.println("'");
// skip this message if triggered too soon.
long now = millis();
if (String(topic) == "j-light/set") {
Serial.print("Set command received: ");
Serial.println(pl);
// skip this message if triggered too soon. .
if ( (now-publish) < 3000 ) {
Serial.print("skipping the process as its been only ");
Serial.print(String(now-lastPublish));
Serial.println(" msec.");
} else {
publish = now;
if (pl == "off"){
Jstate = "off";
} else if (pl == "on") {
Jstate = "on";
}
// force a publish
lastPublish = -publishDelay;
}
}
}
// =============================================================================== //
// HTTP processing //
// =============================================================================== //
String handleJon() {
Jstate = "on";
String page;
page += "<!DOCTYPE html><html><head><title>Johs's ESP8266 server</title>";
page += "<meta http-equiv='refresh' content='2;url=/'/>";
page += "</head><body>";
page += "Turning on the J LED light.</br>";
page += "</body></html>";
return String(page);
}
String handleJoff() {
Jstate = "off";
String page;
page += "<!DOCTYPE html><html><head><title>Johs's ESP8266 server</title>";
page += "<meta http-equiv='refresh' content='2;url=/'/>";
page += "</head><body>";
page += "Turning off the J LED light.</br>";
page += "</body></html>";
return String(page);
}
String handleRoot(){
String JonBC = "off";
String JoffBC = "off";
(Jstate == "on")?JonBC="style='background-color:#0066FF;'":JonBC="";
(Jstate == "off")?JoffBC="style='background-color:#0066FF;'":JoffBC="";
String page = "<!DOCTYPE html><html><head><title>Johs's ESP8266 server</title>"
"<style>.button{background-color: #00b0f0; border: none; color: white; padding: 40px 64px; text-allign: center; text-decoration: none;display: inline-block; font-size:32px;}</style>"
"</head><body>"
"Hi! I am Josh's ESP8266.</p><hr>"
"<a href='j-on' class='button' ";
page += JonBC;
page += ";'>J on</a>"
"<a href='j-off' class='button' ";
page += JoffBC;
page += ";'>J off</a>"
"<hr><p>Got updated OTA! ";
page += updated;
page += "</body></html>";
return String(page);
}
void setup() {
// =============================================================================== //
// setup WIFI //
// =============================================================================== //
Serial.begin(115200);
pinMode(LED,OUTPUT);
WiFi.mode(WIFI_STA);
WiFi.begin(MY_SSID, SSID_PSW);
Serial.println("");
// Wait for connection
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("");
Serial.print("Connected to ");
Serial.println(MY_SSID);
Serial.print("IP address: ");
Serial.println(WiFi.localIP());
// =============================================================================== //
// HTTP processing //
// =============================================================================== //
server.on("/j-on", HTTP_GET, [](AsyncWebServerRequest *request){
request->send(200, "text/html", handleJon());
});
server.on("/j-off", HTTP_GET, [](AsyncWebServerRequest *request) {
request->send(200, "text/html", handleJoff());
});
server.on("/", HTTP_GET, [](AsyncWebServerRequest *request) {
request->send(200, "text/html", handleRoot());
});
AsyncElegantOTA.begin(&server); // Start ElegantOTA
server.begin();
Serial.println("HTTP server started");
// =============================================================================== //
// MQTT processing //
// =============================================================================== //
//client.setServer(mqtt_server, 51883); //mqtt_port);
client.setCallback(callback);
//if (client.connect((char*) clientID.c_str())) {
if (client.connect(clientId.c_str())) {
Serial.println("Connected to MQTT broker");
Serial.print("Topic is: ");
Serial.println(topic);
if (client.publish(topic.c_str(), Jstate.c_str())) {
Serial.println("Publish ok");
}
else {
Serial.println("Publish failed");
}
}
else {
Serial.println("MQTT connect failed");
Serial.println("Will reset and try again...");
abort();
}
}
void loop() {
// put your main code here, to run repeatedly:
// Check MQTT
long now = millis();
if (!client.connected()) {
if (now - lastReconnectAttempt > 5000) {
lastReconnectAttempt = now;
// Attempt to reconnect
if (reconnect()) {
lastReconnectAttempt = 0;
}
}
} else {
// Client connected
client.loop();
}
// changed auto publish time to 1/2 hour infrequent
if ((now - lastPublish) > publishDelay){
boolean retained = true;
if(client.publish("jlight", (char*)Jstate.c_str(),retained)) {
Serial.println("Publish ok");
}
else {
Serial.println("Publish failed");
}
lastPublish = now;
}
// Update LED state
if(Jstate == "off"){
digitalWrite(LED,HIGH);
Serial.print(".");
}
if(Jstate == "on"){
digitalWrite(LED,LOW);
Serial.print("o");
}
// Need to load new config?
AsyncElegantOTA.loop();
}
to me.
Tested with the same libraries as you do, as I can see in
[env:esp12e]
platform = espressif8266
board = esp12e
framework = arduino
lib_deps =
ayushsharma82/AsyncElegantOTA @ ^2.2.5
ottowinter/ESPAsyncTCP-esphome @ ^1.2.3
ottowinter/ESPAsyncWebServer-esphome @ ^1.2.7
knolleary/PubSubClient @ ^2.8
bbx10/DNSServer @ ^1.1.0
which brings us to another problem:
ottowinter/ESPAsyncTCP-esphome @ ^1.2.3
ottowinter/ESPAsyncWebServer-esphome @ ^1.2.7
Why use the esphome
fork libraries here? And not the original
me-no-dev/ESPAsyncTCP @ ^1.2.2
me-no-dev/ESP Async WebServer @ ^1.2.3
the ottowinter
repos (GitHub - OttoWinter/ESPAsyncTCP: Async TCP Library for ESP8266) explicitly say
A fork of the AsyncTCP library by @me-no-dev for ESPHome.
So uhm if you’re not developing for that I’d suggest the normal libaries. Of course they might still work or have project-specific enhancements for it, but if anything doesn’t work, I’d recommend the normal ones.
As a TL;DR: Always read compiler messages fully and try to understand what they’re conveying to you. The error: no matching function for call to xy
are saying “You’re attempting to call a function that doesn’t exist in this version of parameter types” to you already. You can follow the definitions of constructors in the library anytime in VSCode by Ctrl-Clicking on the class name or function name, these are not hiden from you. There you can look at what functions are available and what you’re trying to do.