Skip to content

File espos_ble.h

File List > espos_ble > include > espos_ble.h

Go to the documentation of this file

/*
 * SPDX-FileCopyrightText: 2026 Dirk Wahrheit
 * SPDX-License-Identifier: Apache-2.0
 *
 * espos_ble — BLE gateway: bridges BLE devices to signalk-server's BLE
 * provider API.
 *
 * The device is a dumb, stateless bridge. It does NOT decode sensors and does
 * NOT publish SignalK deltas: raw advertisements and GATT bytes go to the
 * server, and signalk-server (with bt-sensors-plugin-sk) owns all decoding,
 * path naming and units. What each device is, which characteristics to read
 * and what to write arrives at runtime as `gatt_subscribe` commands.
 *
 * Two channels, both authenticated with the token espos_sk already holds:
 *
 *   POST /signalk/v2/api/ble/gateway/advertisements
 *        Batched advertisements, sent periodically.
 *   WS   /signalk/v2/api/ble/gateway/ws   (Authorization: Bearer <jwt>)
 *        Control protocol: hello/status out, gatt_* commands in.
 *
 * Needs espos_config, espos_httpd and espos_sk started first.
 */
#pragma once

#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>

#include "esp_err.h"

#ifdef __cplusplus
extern "C" {
#endif

esp_err_t espos_ble_reserve_controller(void);

esp_err_t espos_ble_start(void);
esp_err_t espos_ble_stop(void);

esp_err_t espos_ble_scan_suspend(const char *reason);

esp_err_t espos_ble_scan_resume(void);

void espos_ble_portal_hold(bool up);

bool espos_ble_scan_is_suspended(void);

typedef struct {
    bool enabled;
    bool scanning;
    /* Scanning was stopped on purpose (see espos_ble_scan_suspend), not
     * because the radio failed. Without this a device showing its setup
     * portal and a broken one produce the same status document. */
    bool scan_suspended;
    char mac[18];             /* controller address, "" if unknown */
    uint32_t scan_hits;       /* advertisements seen by the scanner */
    uint32_t adv_received;    /* handed to the gateway */
    uint32_t adv_posted;      /* accepted by the server */
    uint32_t adv_dropped;     /* shed: buffer full, or ingest lock busy */
    size_t adv_pending;       /* waiting for the next POST */
    uint32_t post_success;
    uint32_t post_fail;
    bool ws_connected;
    uint32_t gatt_sessions;   /* currently active */
    uint32_t gatt_max;        /* concurrent session ceiling */
} espos_ble_status_t;

/* Fills *out with a consistent snapshot.
 *
 * ESP_ERR_TIMEOUT if the advertisement buffer's lock could not be taken:
 * adv_dropped and adv_pending would otherwise be a partial total that no
 * caller could tell from a real one. Callers should surface the failure
 * rather than serve the struct. */
esp_err_t espos_ble_get_status(espos_ble_status_t *out);

esp_err_t espos_ble_status_json(char **out_json);

esp_err_t espos_ble_register_api(void);

#ifdef __cplusplus
}
#endif