#include <Arduino.h>
#include <WiFi.h>
#include <Firebase_ESP_Client.h>
#include "addons/TokenHelper.h"
#include "addons/RTDBHelper.h"
// Configuration structure
struct Config {
// WiFi credentials
const char* ssid = "ZTE_2.4G_PRT6gv";
const char* password = "12345678";
// Firebase configuration
const char* apiKey = "MY_API_KEY"; // ACTUAL API KEY
const char* databaseUrl = "MY_DATABASE_URL"; // ACTUAL DATABASE URL
// Device configuration (UNIQUE PER DEVICE)
const char* deviceId = "ESP1";
const int firstSlotNumber = 1;
const char* parkingZone = "parking";
// Sensor settings
const float maxDetectionDistance = 30.0; // cm
const unsigned long measurementInterval = 1000; // ms
};
Config config;
// Define Firebase objects
FirebaseData fbdo;
FirebaseAuth auth;
FirebaseConfig firebaseConfig;
// Sensor configuration
struct Sensor {
int trigPin;
int echoPin;
int occupiedLED;
int availableLED;
int slotOffset; // 0 or 1 (for first or second sensor)
bool lastState;
unsigned long lastUpdateTime;
};
// Array of sensors (same pin layout for all ESP32s)
Sensor sensors[2] = {
{19, 21, 2, 12, 0, false, 0}, // First sensor (Parking X)
{22, 23, 4, 14, 1, false, 0} // Second sensor (Parking X+1)
};
// Constants
const float SOUND_SPEED = 0.034; // cm/μs
const unsigned long WIFI_RETRY_INTERVAL = 30000; // 30 seconds
const unsigned long FIREBASE_RETRY_INTERVAL = 60000; // 60 seconds
// Variables
unsigned long lastWifiRetry = 0;
unsigned long lastFirebaseRetry = 0;
bool firebaseConnected = false;
void setup() {
Serial.begin(115200);
// Initialize all sensor pins
for (auto &sensor : sensors) {
pinMode(sensor.trigPin, OUTPUT);
pinMode(sensor.echoPin, INPUT);
pinMode(sensor.occupiedLED, OUTPUT);
pinMode(sensor.availableLED, OUTPUT);
digitalWrite(sensor.occupiedLED, LOW);
digitalWrite(sensor.availableLED, HIGH);
}
// Print device configuration
Serial.printf("\nDevice ID: %s\n", config.deviceId);
Serial.printf("Monitoring Parking Slots: %d and %d\n",
config.firstSlotNumber,
config.firstSlotNumber + 1);
connectToWiFi();
initializeFirebase();
}
void loop() {
// Maintain WiFi connection
if (WiFi.status() != WL_CONNECTED && millis() - lastWifiRetry > WIFI_RETRY_INTERVAL) {
Serial.println("WiFi connection lost. Reconnecting...");
connectToWiFi();
lastWifiRetry = millis();
}
// Maintain Firebase connection
if (!firebaseConnected && millis() - lastFirebaseRetry > FIREBASE_RETRY_INTERVAL) {
Serial.println("Attempting Firebase reconnection...");
initializeFirebase();
lastFirebaseRetry = millis();
}
// Process each sensor
for (auto &sensor : sensors) {
if (millis() - sensor.lastUpdateTime >= config.measurementInterval) {
bool currentState = measureDistance(sensor);
// Only update Firebase if state changed or periodically
if (currentState != sensor.lastState ||
sensor.lastUpdateTime % (10 * config.measurementInterval) == 0) {
if (firebaseConnected) {
updateFirebase(sensor, currentState);
}
sensor.lastState = currentState;
}
sensor.lastUpdateTime = millis();
}
}
delay(10); // Small delay to prevent watchdog issues
}
void connectToWiFi() {
Serial.printf("Connecting to WiFi: %s\n", config.ssid);
WiFi.begin(config.ssid, config.password);
unsigned long startTime = millis();
while (WiFi.status() != WL_CONNECTED && millis() - startTime < 20000) {
Serial.print(".");
delay(500);
}
if (WiFi.status() == WL_CONNECTED) {
Serial.println("\nConnected!");
Serial.print("IP Address: ");
Serial.println(WiFi.localIP());
Serial.printf("WiFi RSSI: %d dBm\n", WiFi.RSSI()); // Signal strength
} else {
Serial.println("\nFailed to connect to WiFi");
}
}
void initializeFirebase() {
// Verify credentials before proceeding
if (strlen(config.apiKey) == 0 || strlen(config.databaseUrl) == 0) {
Serial.println("ERROR: Firebase credentials not configured!");
while(1) { delay(1000); } // Halt execution
}
Serial.println("Initializing Firebase...");
firebaseConfig.api_key = config.apiKey;
firebaseConfig.database_url = config.databaseUrl;
firebaseConfig.token_status_callback = tokenStatusCallback;
Firebase.reconnectWiFi(true);
Serial.println("Attempting to begin Firebase connection...");
Firebase.begin(&firebaseConfig, &auth);
// Wait for authentication to complete
unsigned long authStart = millis();
while (!Firebase.ready() && millis() - authStart < 10000) {
Serial.print(".");
delay(100);
}
if (Firebase.ready()) {
firebaseConnected = true;
Serial.println("\nFirebase connected successfully!");
Serial.print("Auth token: ");
Serial.println(Firebase.authToken().c_str());
} else {
firebaseConnected = false;
Serial.println("\nFirebase connection failed");
Serial.print("Error: ");
Serial.println(Firebase.errorReason().c_str());
// More detailed error information
if (Firebase.getLastError().code == -127) {
Serial.println("Specific solution for error -127:");
Serial.println("1. Verify your API key is correct");
Serial.println("2. Check your database URL format (must include https://)");
Serial.println("3. Ensure your project has Realtime Database enabled");
Serial.println("4. Make sure your WiFi connection is stable (RSSI > -70)");
}
}
}
bool measureDistance(Sensor &sensor) {
digitalWrite(sensor.trigPin, LOW);
delayMicroseconds(2);
digitalWrite(sensor.trigPin, HIGH);
delayMicroseconds(10);
digitalWrite(sensor.trigPin, LOW);
long duration = pulseIn(sensor.echoPin, HIGH);
float distanceCm = duration * SOUND_SPEED / 2;
int parkingNumber = config.firstSlotNumber + sensor.slotOffset;
Serial.printf("Parking %d: Distance %.2f cm\n", parkingNumber, distanceCm);
bool isAvailable = distanceCm > config.maxDetectionDistance;
updateLEDs(sensor, isAvailable);
return isAvailable;
}
void updateLEDs(Sensor &sensor, bool isAvailable) {
digitalWrite(sensor.occupiedLED, isAvailable ? LOW : HIGH);
digitalWrite(sensor.availableLED, isAvailable ? HIGH : LOW);
}
void updateFirebase(Sensor &sensor, bool isAvailable) {
int parkingNumber = config.firstSlotNumber + sensor.slotOffset;
String path = String(config.parkingZone) + "/Parking_" + parkingNumber + "/status";
if (Firebase.RTDB.setBool(&fbdo, path.c_str(), isAvailable)) {
Serial.printf("Updated Parking %d: %s\n",
parkingNumber,
isAvailable ? "Available" : "Occupied");
} else {
Serial.printf("Failed to update Parking %d: %s\n",
parkingNumber,
fbdo.errorReason().c_str());
firebaseConnected = false;
}
}
Show the verbose error log in code tags.
Token info: type = undefined, status = error
Token error: code: -127, message: missing required credentials e.g., database URL, host and tokens.
Connecting to Firebase...
....................................................................................................
Firebase connection failed
Error code: 0
Error reason: missing required credentials e.g., database URL, host and tokens.
Ok, I have never worked with this particular API, but I have others. Did you not get the credentials info in the docs?
I see apiKey is not supplied in your sketch as well as databaseUrl.
I have used the correct credentials needed that's why I am confused why it said that I am missing those details.
The log shows the error before trying to actually connect.
Given the error, the library has plenty (too many) examples for Authentication. Since you have an API key, that's used for only some of those
$ rg config.api_key examples/Authentications/
examples/Authentications/SignInAsUser/CustomTokenFile/CustomTokenFile.ino
124: config.api_key = API_KEY;
examples/Authentications/SignInAsUser/EmailPassword/EmailPassword.ino
126: config.api_key = API_KEY;
examples/Authentications/SignInAsUser/CustomToken/CustomToken.ino
176: config.api_key = API_KEY;
examples/Authentications/ReAuthenticate/ReAuthenticate.ino
125: config.api_key = API_KEY;
examples/Authentications/SignInWithIDToken/SignInWithIDToken.ino
101: config.api_key = API_KEY;
examples/Authentications/SignInWithCustomToken/SignInWithCustomToken.ino
101: config.api_key = API_KEY;
examples/Authentications/SignInWithRefreshIDToken/SignInWithRefreshIDToken.ino
103: config.api_key = API_KEY;
examples/Authentications/UserManagement/Signup/Signup.ino
107: config.api_key = API_KEY;
examples/Authentications/UserManagement/ResetPassword/ResetPassword.ino
91: config.api_key = API_KEY;
examples/Authentications/UserManagement/SendVerification/SendVerification.ino
115: config.api_key = API_KEY;
examples/Authentications/SignInAsGuest/AnonymousSignin/AnonymousSignin.ino
111: config.api_key = API_KEY;
So you can determine which way works with what you have available, and follow that example. Glancing at a few of them, at least one step is missing in your sketch.
Also, the Firebase_ESP_Client.h (and similar FirebaseESP32.h) library is deprecated. Its successor, GitHub - mobizt/FirebaseClient: 🔥Fast and reliable async Firebase client library for Arduino. might be easier to use.