128 lines
5.5 KiB
C++
128 lines
5.5 KiB
C++
#pragma once
|
|
|
|
/**
|
|
* @file BleManager.h
|
|
* @brief BLE Central (client) manager using NimBLE-Arduino.
|
|
*
|
|
* Responsibilities:
|
|
* - Scan for the Marine Gateway peripheral ("MarineGateway")
|
|
* - Establish a secure, bonded connection (passkey entry via Serial/Web)
|
|
* - Subscribe to all five NOTIFY characteristics and parse incoming JSON
|
|
* - Provide thread-safe access to the aggregated BoatState
|
|
* - Send autopilot and admin commands
|
|
* - Manage automatic reconnection
|
|
*/
|
|
|
|
#include "Config.h"
|
|
#include <NimBLEDevice.h>
|
|
|
|
class BleManager : public NimBLEClientCallbacks,
|
|
public NimBLEScanCallbacks {
|
|
public:
|
|
/**
|
|
* @brief Initialise the NimBLE stack and start scanning.
|
|
* Must be called once from setup().
|
|
*/
|
|
void begin();
|
|
|
|
/**
|
|
* @brief Call from loop() — handles reconnect scheduling and
|
|
* dispatches any pending state changes.
|
|
*/
|
|
void update();
|
|
|
|
// ── Data access (thread-safe) ─────────────────────────────────────────────
|
|
|
|
/**
|
|
* @brief Copy the current BoatState snapshot into @p dst.
|
|
* Protected by an internal mutex.
|
|
*/
|
|
void getBoatState(BoatState& dst) const;
|
|
|
|
/** @brief Returns true when actively connected to the gateway. */
|
|
bool isConnected() const;
|
|
|
|
/** @brief Current BLE status for status LED / UI. */
|
|
AppState::BleStatus status() const { return _status; }
|
|
|
|
// ── Command senders ───────────────────────────────────────────────────────
|
|
|
|
/** @brief Send an autopilot command (e.g. "adjust+1"). */
|
|
bool sendAutopilotCmd(const char* command);
|
|
|
|
/** @brief Send a raw admin JSON command string. */
|
|
bool sendAdminCmd(const char* jsonCmd);
|
|
|
|
// Convenience admin helpers
|
|
bool sendRestart();
|
|
bool sendWifiSta(const char* ssid, const char* password);
|
|
bool sendWifiAp(const char* ssid, const char* password);
|
|
|
|
// ── Passkey (pairing) ─────────────────────────────────────────────────────
|
|
|
|
/**
|
|
* @brief Provide the passkey entered by the user.
|
|
* Called by the WiFi web UI when the user submits the PIN.
|
|
*/
|
|
void providePasskey(uint32_t pin);
|
|
|
|
private:
|
|
// BLE callback trampolines declared in BleManager.cpp
|
|
friend void navNotifyCB(NimBLERemoteCharacteristic*, uint8_t*, size_t, bool);
|
|
friend void windNotifyCB(NimBLERemoteCharacteristic*, uint8_t*, size_t, bool);
|
|
friend void autopilotNotifyCB(NimBLERemoteCharacteristic*, uint8_t*, size_t, bool);
|
|
friend void perfNotifyCB(NimBLERemoteCharacteristic*, uint8_t*, size_t, bool);
|
|
friend void adminNotifyCB(NimBLERemoteCharacteristic*, uint8_t*, size_t, bool);
|
|
|
|
// ── NimBLEClientCallbacks ─────────────────────────────────────────────────
|
|
void onConnect(NimBLEClient* pClient) override;
|
|
void onDisconnect(NimBLEClient* pClient, int reason) override;
|
|
void onConfirmPasskey(NimBLEConnInfo& connInfo, uint32_t pin) override;
|
|
void onAuthenticationComplete(NimBLEConnInfo& connInfo) override;
|
|
|
|
// ── NimBLEScanCallbacks ───────────────────────────────────────────────────
|
|
void onResult(const NimBLEAdvertisedDevice* device) override;
|
|
void onScanEnd(const NimBLEScanResults& results, int reason) override;
|
|
|
|
// ── Internal helpers ──────────────────────────────────────────────────────
|
|
bool _connectToServer(const NimBLEAddress& addr);
|
|
bool _subscribeAll();
|
|
void _startScan();
|
|
void _scheduleReconnect();
|
|
|
|
// Notification callbacks (one per characteristic)
|
|
void _onNavNotify (NimBLERemoteCharacteristic*, uint8_t*, size_t, bool);
|
|
void _onWindNotify (NimBLERemoteCharacteristic*, uint8_t*, size_t, bool);
|
|
void _onAutopilotNotify(NimBLERemoteCharacteristic*, uint8_t*, size_t, bool);
|
|
void _onPerfNotify (NimBLERemoteCharacteristic*, uint8_t*, size_t, bool);
|
|
void _onAdminNotify (NimBLERemoteCharacteristic*, uint8_t*, size_t, bool);
|
|
|
|
// JSON parsers
|
|
void _parseNav (const char* json);
|
|
void _parseWind (const char* json);
|
|
void _parseAutopilot(const char* json);
|
|
void _parsePerf (const char* json);
|
|
void _parseAdmin (const char* json);
|
|
|
|
// ── State ─────────────────────────────────────────────────────────────────
|
|
NimBLEClient* _pClient = nullptr;
|
|
NimBLEAddress _targetAddr;
|
|
bool _targetFound = false;
|
|
bool _doConnect = false;
|
|
bool _subscribePending = false;
|
|
bool _subscribed = false;
|
|
uint32_t _reconnectAt = 0; ///< millis() when next reconnect is due
|
|
|
|
AppState::BleStatus _status = AppState::BleStatus::IDLE;
|
|
|
|
mutable portMUX_TYPE _mux = portMUX_INITIALIZER_UNLOCKED;
|
|
BoatState _state;
|
|
|
|
// Pending passkey from the web UI
|
|
volatile bool _passkeyPending = false;
|
|
volatile uint32_t _passkey = 0;
|
|
};
|
|
|
|
// Singleton accessor
|
|
extern BleManager bleManager;
|