155 lines
4.5 KiB
C++
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; |