Files
Vermix-Gate/lib/rpc/rpc.hpp
T
2025-10-06 18:27:50 +02:00

155 lines
4.5 KiB
C++

#pragma once
#include <Arduino.h>
#include <freertos/FreeRTOS.h>
#include <freertos/queue.h>
#include <freertos/task.h>
#include <freertos/semphr.h> // Required for semaphores
#include <vector>
/**
* @struct RpcAccessLogEntry
* @brief Holds a single access log record to be queued for synchronization.
*/
struct RpcAccessLogEntry {
time_t timestamp;
uint32_t rfidId;
};
/**
* @struct HttpResponse
* @brief Encapsulates the result of an HTTP request.
*/
struct HttpResponse {
int httpCode = 0;
std::vector<uint8_t> payload;
};
/**
* @class RPC
* @brief Manages remote procedure calls (RPC) for device synchronization.
* * This class handles queuing access logs, synchronizing them with a server,
* and downloading updated data. It uses a background FreeRTOS task for
* automatic, periodic synchronization.
*/
class RPC {
public:
RPC();
~RPC();
/**
* @brief Performs a full, one-time synchronization cycle.
* @param forceDownload If true, the database will be downloaded even if the
* server reports no pending changes.
* @return true on success, false on failure.
*/
bool sync(bool forceDownload = false);
/**
* @brief Adds an access log entry to the queue for the next sync cycle.
* If the queue reaches a threshold, a sync may be triggered.
* @param rfidId The RFID ID that was accessed.
*/
void addAccessLog(uint32_t rfidId);
/**
* @brief Starts or restarts the automatic background synchronization task.
* @param intervalMs The sync interval in milliseconds.
*/
void startAutoSync(uint32_t intervalMs);
/**
* @brief Stops the automatic synchronization task gracefully.
*/
void stopAutoSync();
/**
* @brief Sets the API key and base URL for server communication.
*/
void setApiKeyAndBaseUrl(const char* apiKey, const char* baseUrl);
/**
* @brief Gets the timestamp (from millis()) of the last successful communication.
* @return The last connection timestamp, or 0 if never connected.
*/
time_t getLastConnectTime() const { return lastSyncConnection; }
/**
* @brief Checks if a sync operation is currently in progress.
* @return true if syncing, false otherwise.
*/
bool isSyncing() const { return isSyncing_; }
/**
* @brief Sets a callback function to get the current time in seconds since epoch.
* This is used to set the lastSync time during sync operations.
* @param callback A function that returns the current time as time_t.
*/
void setNewTimeCallback(std::function<void(time_t)> callback) {
newTimeCallback_ = callback;
}
private:
// --- Member Variables ---
// Configuration
char apiKey_[65]; // 64 chars + 1 null-terminator
char baseUrl_[257]; // 256 chars + 1 null-terminator
// State
time_t lastSyncTime = 0;
time_t lastSyncConnection = 0;
bool isSyncing_ = false;
// FreeRTOS components
QueueHandle_t accessLogQueue = nullptr;
TaskHandle_t autoSyncTaskHandle = nullptr;
SemaphoreHandle_t syncTriggerSemaphore_ = nullptr;
uint32_t syncIntervalMs = 300000; // Default: 5 minutes
bool autoSyncRunning = false;
// Constants
static constexpr uint8_t LOG_SYNC_THRESHOLD = 20;
// --- Private Helper Methods ---
/**
* @brief Sends an HTTP request and returns the full response.
* This method is self-contained and manages the HTTPClient lifecycle.
*/
HttpResponse sendRequest(const String& url, const String& method = "GET",
const uint8_t* payload = nullptr, size_t payloadLen = 0,
const String& contentType = "");
/**
* @brief Streams an HTTP GET response directly to a file on LittleFS.
* This is memory-efficient for large files like a database.
*/
bool downloadDatabaseToFile(const char* filePath);
/**
* @brief Sends queued logs to the server and checks if updates are pending.
* This is the first step in the sync process.
*/
bool syncLogsAndCheckForUpdates(bool* pendingChanges);
/**
* @brief Saves the last successful database download timestamp to flash.
*/
void saveLastSyncTime(time_t timestamp);
/**
* @brief Loads the last successful database download timestamp from flash.
*/
time_t loadLastSyncTime();
/**
* @brief The static function that runs as the FreeRTOS background task.
*/
static void autoSyncTask(void* pvParameters);
std::function<void(time_t)> newTimeCallback_;
};
extern RPC rpc;