Complete IoT monitoring platform for Acuvim II power meters via ESP32. Firmware (Phases 1-7): - ESP32-WROVER-B (TTGO T-Call v1.4) with RS485 Modbus RTU - WiFi STA+AP concurrent mode with GSM/GPRS failover - Transport abstraction layer with 4 priority modes - MQTT protocol with 20 commands, LWT, QoS, exponential backoff - SD card offline buffering with JSONL rotation and non-blocking drain - OTA firmware updates with dual partition rollback protection - Watchdog timer, crash loop detection, Acuvim health monitoring - Captive portal provisioning with AP mode Console backend (Phase 8): - .NET 10 minimal API with PostgreSQL + EF Core - JWT authentication, SignalR real-time updates - MQTTnet 5.x bridge service with health monitoring - Device, telemetry, firmware, alert, group management - Rate limiting, security headers, Swagger/OpenAPI Frontend (Phase 9): - React 18 + TypeScript + Vite with Ant Design 5 - ECharts telemetry visualization, TanStack Query - SignalR live updates, device management UI - Dashboard, fleet management, firmware deployment Testing & Production (Phase 10): - 28 firmware unit tests (Modbus, JSON, config, version) - 23 xUnit backend tests (device, telemetry, command, alert) - Docker Compose with nginx, TLS MQTT, PostgreSQL - Production deployment, commissioning, and troubleshooting docs Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
68 lines
1.8 KiB
C++
68 lines
1.8 KiB
C++
#ifndef MQTT_CLIENT_H
|
|
#define MQTT_CLIENT_H
|
|
|
|
#include <Arduino.h>
|
|
#include <PubSubClient.h>
|
|
#include <functional>
|
|
#include "acuvim_registers.h"
|
|
#include "config_manager.h"
|
|
|
|
#define MQTT_BUFFER_SIZE 1024
|
|
#define MQTT_RECONNECT_BASE_MS 10000
|
|
#define MQTT_RECONNECT_MAX_MS 60000
|
|
|
|
class MqttClient {
|
|
public:
|
|
void begin(Client& networkClient);
|
|
void setConfig(const DeviceConfig& config);
|
|
bool connect();
|
|
void disconnect();
|
|
bool isConnected();
|
|
void loop();
|
|
|
|
bool publishTelemetry(const AcuvimData& data, const char* connType, int signal,
|
|
const char* operatorName = nullptr);
|
|
bool publishResponse(const char* requestId, const char* payload);
|
|
bool publish(const char* topic, const char* payload, bool retain = false);
|
|
bool publishBuffered(const char* payload);
|
|
|
|
void onCommand(std::function<void(const String& topic, const String& payload)> callback) {
|
|
_commandCallback = callback;
|
|
}
|
|
|
|
const char* getDeviceId() const { return _deviceId; }
|
|
|
|
private:
|
|
PubSubClient _client;
|
|
char _deviceId[32];
|
|
char _broker[128];
|
|
uint16_t _port;
|
|
char _username[64];
|
|
char _password[64];
|
|
char _topicPrefix[64];
|
|
|
|
char _topicTelemetry[128];
|
|
char _topicHeartbeat[128];
|
|
char _topicCmd[128];
|
|
char _topicResp[128];
|
|
char _topicStatus[128];
|
|
|
|
std::function<void(const String& topic, const String& payload)> _commandCallback;
|
|
|
|
unsigned long _lastReconnectAttemptMs;
|
|
unsigned long _reconnectIntervalMs;
|
|
|
|
void buildTopics();
|
|
bool subscribeToCommands();
|
|
void publishOnlineStatus();
|
|
String buildLwtPayload();
|
|
|
|
static MqttClient* _instance;
|
|
static void mqttCallbackStatic(char* topic, byte* payload, unsigned int length);
|
|
void mqttCallback(char* topic, byte* payload, unsigned int length);
|
|
|
|
uint32_t getEpochTime();
|
|
};
|
|
|
|
#endif
|