Skip to main content
Kinematrix provides three generations of Firebase integration, each offering different capabilities and architectural approaches. Choose the version that best fits your project requirements.

Version Overview

Firebase V1

Legacy ImplementationComplete wrapper with callbacks
Contains hardcoded credentials

Firebase V2

RecommendedSimplified service-specific classesReal-time streaming support

Firebase V3

EnterpriseSingleton architectureAdvanced Firestore features

Feature Comparison

FeatureV1V2V3
Realtime Database
Firestore CRUD
Firestore Advanced*
Cloud Storage
Cloud Messaging (FCM)
Real-time Streaming
Batch Operations
Database Admin
Service Account Auth⚠️
Singleton Pattern
*Advanced: Queries, field transforms, index management, database creation

Dependencies

Add to your platformio.ini:
lib_deps = 
  # For Firebase V1
  https://github.com/mobizt/Firebase-ESP-Client.git
  
  # For Firebase V2 and V3
  https://github.com/mobizt/FirebaseClient.git
  
  # Common dependencies
  bblanchon/ArduinoJson@^6.21.3

Simplified, service-specific implementation ideal for most projects.

Realtime Database (RTDB)

Enable Module

#define ENABLE_MODULE_FIREBASE_RTDB_V2
#include "Kinematrix.h"

Basic Usage

#include <WiFi.h>
FirebaseV2RTDB rtdb;
WiFiClient client;

void setup() {
  Serial.begin(115200);
  WiFi.begin("SSID", "password");
  while (WiFi.status() != WL_CONNECTED) delay(100);
  
  // Initialize with user authentication
  bool success = rtdb.begin(
    client,
    "https://your-project.firebaseio.com",
    "YOUR_API_KEY",
    "[email protected]",
    "password"
  );
  
  if (success && rtdb.ready()) {
    Serial.println("Firebase connected!");
  }
}

Write Data

// Write different data types
rtdb.set("/sensors/temperature", 25.5);
rtdb.set("/sensors/humidity", 60);
rtdb.set("/status/online", true);
rtdb.set("/device/name", "ESP32-Sensor");

// Write JSON
const char* json = "{\"temp\":25.5,\"hum\":60}";
rtdb.set("/sensors/data", json);

Read Data

float temp = rtdb.getFloat("/sensors/temperature");
int humidity = rtdb.getInt("/sensors/humidity");
bool online = rtdb.getBool("/status/online");
String name = rtdb.getString("/device/name");
String jsonData = rtdb.getJSON("/sensors/data");

Serial.println("Temperature: " + String(temp));

Push Data (Auto-generated Keys)

// Push creates unique key for each entry
String key1 = rtdb.push("/logs", "System started");
String key2 = rtdb.push("/logs", "Sensor reading: 25.5");

Serial.println("Log ID: " + key1);

Update and Delete

// Update multiple fields
const char* updates = "{\"temp\":26.0,\"updated\":1234567890}";
rtdb.update("/sensors", updates);

// Delete path
rtdb.remove("/logs/old_data");

// Check if path exists
if (rtdb.exists("/sensors/temperature")) {
  Serial.println("Temperature sensor exists");
}

Real-time Streaming

WiFiClient streamClient;

void setup() {
  // ... WiFi and RTDB initialization ...
  
  // Start streaming from path
  rtdb.beginStream(streamClient, "/sensors");
}

void loop() {
  rtdb.loop();
  
  if (rtdb.hasStreamData()) {
    String data = rtdb.getStreamData();
    String path = rtdb.getStreamPath();
    String event = rtdb.getStreamEvent();
    
    Serial.println("Event: " + event);
    Serial.println("Path: " + path);
    Serial.println("Data: " + data);
  }
  
  if (rtdb.hasError()) {
    Serial.println("Error: " + rtdb.getError());
  }
}

Firestore Database

Enable Module

#define ENABLE_MODULE_FIREBASE_FIRESTORE_V2
#include "Kinematrix.h"

Basic Usage

FirebaseV2Firestore firestore;

void setup() {
  Serial.begin(115200);
  WiFi.begin("SSID", "password");
  while (WiFi.status() != WL_CONNECTED) delay(100);
  
  // Initialize with user authentication
  firestore.begin(
    "YOUR_API_KEY",
    "[email protected]",
    "password",
    "your-project-id"
  );
  
  // Wait for ready
  while (!firestore.isReady()) {
    firestore.loop();
    delay(100);
  }
}

Create Documents

// Firestore requires specific JSON format
String createSensorDoc(float temp, float humidity) {
  char json[256];
  snprintf(json, sizeof(json), 
    "{"
      "\"fields\": {"
        "\"temperature\": {\"doubleValue\": %.2f},"
        "\"humidity\": {\"doubleValue\": %.2f},"
        "\"timestamp\": {\"integerValue\": %ld}"
      "}"
    "}",
    temp, humidity, time(nullptr)
  );
  return String(json);
}

void loop() {
  firestore.loop();
  
  float temp = 25.5;
  float humidity = 60.0;
  String data = createSensorDoc(temp, humidity);
  
  // Create document
  firestore.createDocument(
    "sensors/sensor1",  // Document path
    data,               // JSON data
    false               // Don't wait for completion
  );
  
  // Check result
  if (firestore.isResultReady()) {
    String result = firestore.getLastPayload();
    if (result.indexOf("error") >= 0) {
      Serial.println("Error: " + result);
    } else {
      Serial.println("Document created!");
    }
  }
}

Read Documents

firestore.getDocument("sensors/sensor1", "", false);

while (!firestore.isResultReady()) {
  firestore.loop();
  delay(10);
}

String document = firestore.getLastPayload();
Serial.println(document);

Update and Delete

// Update document
String updateData = 
  "{"
    "\"fields\": {"
      "\"temperature\": {\"doubleValue\": 26.5}"
    "}"
  "}";

firestore.updateDocument(
  "sensors/sensor1",
  updateData,
  "temperature",  // Update mask (which fields to update)
  false
);

// Delete document
firestore.deleteDocument("sensors/old_sensor", false);

List Documents

// List all documents in collection
firestore.listDocuments(
  "sensors",  // Collection path
  10,         // Page size
  "",         // Field mask (empty = all fields)
  false
);

while (!firestore.isResultReady()) {
  firestore.loop();
  delay(10);
}

String documents = firestore.getLastPayload();
Serial.println(documents);

Practical Example: Sensor Logger

#include <WiFi.h>
#define ENABLE_MODULE_FIREBASE_FIRESTORE_V2
#include "Kinematrix.h"

FirebaseV2Firestore firestore;
unsigned long lastUpload = 0;
String deviceId;

void setup() {
  Serial.begin(115200);
  
  // Connect WiFi
  WiFi.begin("SSID", "password");
  while (WiFi.status() != WL_CONNECTED) delay(100);
  
  // Generate device ID from MAC
  deviceId = "ESP32_" + WiFi.macAddress();
  deviceId.replace(":", "");
  
  // Initialize Firestore
  firestore.begin("API_KEY", "[email protected]", "password", "project-id");
  
  while (!firestore.isReady()) {
    firestore.loop();
    delay(100);
  }
  Serial.println("Firestore ready!");
}

void loop() {
  firestore.loop();
  
  // Upload every 60 seconds
  if (millis() - lastUpload >= 60000) {
    lastUpload = millis();
    
    // Read sensors
    float temp = readTemperature();
    float hum = readHumidity();
    
    // Create document
    char json[512];
    snprintf(json, sizeof(json),
      "{"
        "\"fields\": {"
          "\"temperature\": {\"doubleValue\": %.2f},"
          "\"humidity\": {\"doubleValue\": %.2f},"
          "\"deviceId\": {\"stringValue\": \"%s\"},"
          "\"timestamp\": {\"integerValue\": %ld}"
        "}"
      "}",
      temp, hum, deviceId.c_str(), time(nullptr)
    );
    
    String docPath = "sensor_data/" + deviceId + "_" + String(time(nullptr));
    firestore.createDocument(docPath, json, false);
    
    Serial.println("Data uploaded: " + String(temp) + "C, " + String(hum) + "%");
  }
}

Cloud Storage

Enable Module

#define ENABLE_MODULE_FIREBASE_STORAGE_V2
#include "Kinematrix.h"

Basic Usage

FirebaseV2Storage storage;

void setup() {
  Serial.begin(115200);
  WiFi.begin("SSID", "password");
  while (WiFi.status() != WL_CONNECTED) delay(100);
  
  // Initialize storage
  storage.begin(
    "API_KEY",
    "[email protected]",
    "password",
    "project-id",
    "project-id.appspot.com"  // Bucket ID
  );
  
  while (!storage.isReady()) {
    storage.loop();
    delay(100);
  }
}

Upload Files

// Upload file from SD card or SPIFFS
storage.uploadFile(
  "/data/sensor_log.csv",    // Local file
  "logs/sensor_log.csv",     // Storage path
  "text/csv",                // MIME type
  false                      // Async upload
);

// Check upload progress
while (!storage.isResultReady()) {
  storage.loop();
  int progress = storage.getUploadProgress();
  Serial.println("Upload: " + String(progress) + "%");
  delay(100);
}

Download Files

storage.downloadFile(
  "logs/sensor_log.csv",     // Storage path
  "/data/downloaded.csv",    // Local path
  false
);

while (!storage.isResultReady()) {
  storage.loop();
  int progress = storage.getDownloadProgress();
  Serial.println("Download: " + String(progress) + "%");
  delay(100);
}

File Management

// Get file metadata
String metadata = storage.getFileMetadata("logs/sensor_log.csv", true);
Serial.println(metadata);

// List files with prefix
String fileList = storage.listFiles("logs/", 50, true);
Serial.println(fileList);

// Delete file
storage.deleteFile("logs/old_data.csv", true);

OTA Updates

// Perform OTA update from storage
bool success = storage.performOTA(
  "firmware/device_v1.2.bin",
  true  // Wait for completion
);

if (success) {
  Serial.println("OTA successful, restarting...");
  ESP.restart();
} else {
  Serial.println("OTA failed: " + storage.getLastError());
}

Cloud Messaging (FCM)

Enable Module

#define ENABLE_MODULE_FIREBASE_MESSAGING_V2
#include "Kinematrix.h"

Send to Token

FirebaseV2Messaging messaging;

void setup() {
  Serial.begin(115200);
  WiFi.begin("SSID", "password");
  while (WiFi.status() != WL_CONNECTED) delay(100);
  
  messaging.begin("API_KEY", "[email protected]", "password", "project-id");
  
  while (!messaging.isReady()) {
    messaging.loop();
    delay(100);
  }
}

void sendNotification(String deviceToken) {
  messaging.setToken(deviceToken);
  messaging.setNotification(
    "Sensor Alert",
    "Temperature exceeded threshold: 30C"
  );
  
  String messageId = messaging.sendMessage(false);
  
  while (!messaging.isResultReady()) {
    messaging.loop();
    delay(10);
  }
  
  String result = messaging.getLastPayload();
  Serial.println("Message sent: " + result);
}

Send to Topic

messaging.setTopic("sensor_alerts");
messaging.setNotification(
  "System Alert",
  "Multiple sensors offline"
);
messaging.sendMessage(false);

Send with Data Payload

messaging.setToken(deviceToken);
messaging.setNotification("Alert", "Check sensor");

// Add custom data
messaging.addData("sensor_id", "temp_01");
messaging.addData("value", "32.5");
messaging.addData("threshold", "30.0");

messaging.sendMessage(false);

Platform-Specific Configuration

// Android settings
messaging.setAndroidPriority(true);  // High priority
messaging.setAndroidNotificationPriority(4);  // MAX priority (0-4)

// iOS settings
messaging.addApnsHeader("apns-priority", "10");

messaging.sendMessage(false);

Firebase V3 (Enterprise)

Singleton architecture with advanced features for production applications.

Architecture

V3 uses a centralized FirebaseV3Application singleton for authentication, which all services share.
#define ENABLE_MODULE_FIREBASE_APPLICATION_V3
#define ENABLE_MODULE_FIREBASE_FIRESTORE_V3
#include "Kinematrix.h"

Initialize Application

FirebaseV3Application* app = FirebaseV3Application::getInstance();

void setup() {
  Serial.begin(115200);
  WiFi.begin("SSID", "password");
  while (WiFi.status() != WL_CONNECTED) delay(100);
  
  // Initialize with user auth
  app->begin(
    "API_KEY",
    "[email protected]",
    "password",
    "project-id"
  );
  
  while (!app->isReady()) {
    app->loop();
    delay(100);
  }
  Serial.println("Firebase V3 ready!");
}

void loop() {
  app->loop();  // Keep authentication alive
}

Service Account Authentication

const char* clientEmail = "[email protected]";
const char* privateKey = "-----BEGIN PRIVATE KEY-----\n...\n-----END PRIVATE KEY-----\n";

app->begin(
  clientEmail,
  "project-id",
  privateKey
);

Advanced Firestore

Initialize Service

FirebaseV3Application* app = FirebaseV3Application::getInstance();
FirebaseV3Firestore firestore(app);  // Pass shared app

void setup() {
  // ... initialize app ...
  
  // Firestore automatically uses app's authentication
}

Database Administration

// Create new database
String dbId = firestore.createDatabase(
  "production-db",
  "us-central",
  true  // Wait for completion
);

// List all databases
String databases = firestore.listDatabases(true);
Serial.println(databases);

// Update database settings
firestore.updateDatabase(
  "production-db",
  true,  // Enable point-in-time recovery
  true
);

// Delete database
firestore.deleteDatabase("old-db", true);

Index Management

// Create index for queries
String indexId = firestore.createDatabaseIndex(
  "sensors",         // Collection
  "timestamp",       // Field 1
  "temperature",     // Field 2
  true
);

// List indexes
String indexes = firestore.listDatabaseIndexes(true);

// Delete index
firestore.deleteDatabaseIndex(indexId, true);

Batch Operations

// Create batch write
Writes writes;

// Add multiple operations to batch
firestore.batchWrite(writes, false);

// Batch get multiple documents
firestore.batchGet("sensors/sensor1,sensors/sensor2", "", false);

Advanced Queries

// Run structured query
const char* query = 
  "{"
    "\"structuredQuery\": {"
      "\"from\": [{\"collectionId\": \"sensors\"}],"
      "\"where\": {"
        "\"fieldFilter\": {"
          "\"field\": {\"fieldPath\": \"temperature\"},"
          "\"op\": \"GREATER_THAN\","
          "\"value\": {\"doubleValue\": 25.0}"
        "}"
      "},"
      "\"orderBy\": [{"
        "\"field\": {\"fieldPath\": \"timestamp\"},"
        "\"direction\": \"DESCENDING\""
      "}],"
      "\"limit\": 10"
    "}"
  "}";

firestore.runQuery("sensors", query, false);

Field Transforms

// Increment field value
firestore.incrementFieldValue(
  "counters/page_views",
  "count",
  1,      // Increment by 1
  false
);

// Set server timestamp
firestore.setServerTimestamp(
  "sensors/sensor1",
  "last_updated",
  false
);

// Append to array
Values::ArrayValue newValues;
firestore.appendArray(
  "sensors/sensor1",
  "readings",
  newValues,
  false
);

Import/Export

// Export collection to Cloud Storage
firestore.exportDocuments(
  "sensors",                    // Collection ID
  "project-id.appspot.com",    // Bucket
  "backups/2024-03-03/",       // Storage path
  true
);

// Import from Cloud Storage
firestore.importDocuments(
  "sensors",
  "project-id.appspot.com",
  "backups/2024-03-03/",
  true
);

Authentication Methods

User Email/Password

// V2
rtdb.begin(client, "db-url", "api-key", "[email protected]", "password");

// V3
app->begin("api-key", "[email protected]", "password", "project-id");

Service Account

// V2 Firestore
firestore.begin(
  "[email protected]",
  "project-id",
  "-----BEGIN PRIVATE KEY-----\n...\n-----END PRIVATE KEY-----\n"
);

// V3
app->begin(clientEmail, "project-id", privateKey);

Anonymous

// V2 RTDB only
rtdb.beginAnonymous(client, "https://project.firebaseio.com");

// V3
app->beginAnonymous("project-id");

Best Practices

Never hardcode credentials in production code. Use environment variables or secure storage.
Always call loop() in your main loop to process Firebase events and maintain authentication.
Choose the right version:
  • V2 for most projects (recommended)
  • V3 for enterprise features (batch, queries, admin)
  • Avoid V1 (security risks)

Error Handling

void loop() {
  firestore.loop();
  
  if (firestore.isResultReady()) {
    String payload = firestore.getLastPayload();
    
    // Check for errors in response
    if (payload.indexOf("\"error\":") >= 0) {
      Serial.println("Firebase Error: " + payload);
      
      // Parse error for specific handling
      if (payload.indexOf("PERMISSION_DENIED") >= 0) {
        Serial.println("Check Firestore security rules");
      }
    } else {
      // Success
      Serial.println("Operation successful");
    }
  }
  
  if (firestore.hasError()) {
    Serial.println("Connection error: " + firestore.getLastError());
  }
}

Migration Guide

V1 to V2

// V1
FirebaseModule firebase;
firebase.addData("value", "/path");
firebase.sendDataAsyncFloat(2000);

// V2
FirebaseV2RTDB rtdb;
rtdb.set("/path", value);

V2 to V3

// V2 - Each service has its own auth
FirebaseV2Firestore firestore;
firestore.begin(apiKey, email, password, projectId);

// V3 - Centralized authentication
FirebaseV3Application* app = FirebaseV3Application::getInstance();
app->begin(apiKey, email, password, projectId);
FirebaseV3Firestore firestore(app);

Next Steps

MQTT Communication

Set up MQTT for real-time device messaging

Cloud Integrations

Connect to Google Sheets, Telegram, WhatsApp

Build docs developers (and LLMs) love