File espos_sk.h¶
File List > espos_sk > include > espos_sk.h
Go to the documentation of this file
/*
* SPDX-FileCopyrightText: 2026 Dirk Wahrheit
* SPDX-License-Identifier: Apache-2.0
*
* espos_sk โ SignalK server discovery and access-token management (M3);
* WebSocket delta output and meta reconciliation follow in M4.
*/
#pragma once
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
#include "esp_err.h"
#include "espos_sk_token_sm.h"
#ifdef __cplusplus
extern "C" {
#endif
/* A boat network can carry more SignalK servers than you would guess: a
* plotter, a spare Pi, a laptop running one for development, plus every
* neighbouring vessel in the marina. Measured on one: 9 advertisements.
* When the list is smaller than what is advertised, which entries survive
* depends on mDNS answer order, which is not stable โ so the server the
* device is actually paired with can silently drop out. */
#define ESPOS_SK_MAX_SERVERS 12
typedef struct {
char host[ESPOS_SK_HOST_MAX]; /* IPv4 dotted or hostname */
uint16_t port;
char self[ESPOS_SK_SELF_MAX];
char name[48]; /* mDNS instance name */
char roles[32];
char swname[24];
char swvers[16];
/* The server advertised itself as _signalk-https._tcp rather than
* _signalk-http._tcp. signalk-server publishes one or the other depending
* on its `ssl` setting (src/interfaces/rest.js), so this is the server
* telling us its scheme -- which is what sk.scheme = auto reads. */
bool tls;
uint32_t seen_ms;
} espos_sk_discovered_t;
esp_err_t espos_sk_start(void);
esp_err_t espos_sk_stop(void);
esp_err_t espos_sk_status_json(char **out_json);
esp_err_t espos_sk_servers_json(char **out_json);
/* Commands (thread-safe, queued to the SK task). */
esp_err_t espos_sk_discover_now(void);
esp_err_t espos_sk_request_now(void); /* re-request access (from denied/error) */
esp_err_t espos_sk_set_token(const char *token); /* manual token paste */
esp_err_t espos_sk_forget_token(void); /* drop token + pending, request again */
void espos_sk_report_unauthorized(void);
void espos_sk_report_cert_error(const char *reason);
/* ------------------------------------------------------------ deltas */
esp_err_t espos_sk_publish_number(const char *path, double value);
esp_err_t espos_sk_publish_string(const char *path, const char *value);
esp_err_t espos_sk_publish_bool(const char *path, bool value);
esp_err_t espos_sk_publish_json(const char *path, const char *value_json);
typedef enum {
ESPOS_SK_ALERT_NORMAL = 0, /* condition cleared */
ESPOS_SK_ALERT_WARN,
ESPOS_SK_ALERT_ALARM,
} espos_sk_alert_t;
esp_err_t espos_sk_notify(const char *key, espos_sk_alert_t state, const char *message);
/* The compile-time cap. CONFIG_ESPOS_SK_MAX_META tunes the table the
* implementation actually allocates; this is the number the API promises and
* stays a literal, because a public header that reads a CONFIG_ token gives
* two firmwares built from one header different ABIs. */
#define ESPOS_SK_MAX_META 32
esp_err_t espos_sk_declare_meta(const char *path, const char *meta_json, uint32_t period_ms);
/* ------------------------------------------------------- inbound (M7) */
#include "espos_sk_parse.h"
typedef void (*espos_sk_sub_cb_t)(const espos_sk_update_t *u, void *arg);
#define ESPOS_SK_MAX_SUBS 48
int espos_sk_subscribe(const char *pattern, uint32_t period_ms, espos_sk_sub_cb_t cb, void *arg);
esp_err_t espos_sk_unsubscribe(int handle);
typedef void (*espos_sk_put_cb_t)(const char *request_id, const char *state, int status_code, const char *message, void *arg);
esp_err_t espos_sk_put(const char *path, const char *value_json, espos_sk_put_cb_t cb, void *arg);
esp_err_t espos_sk_send_raw(const char *json);
/* -------------------------------------------------- inbound PUT (control) */
typedef esp_err_t (*espos_sk_put_handler_t)(const char *path, const char *value_json, void *arg);
#define ESPOS_SK_PUT_PENDING 1
#define ESPOS_SK_MAX_PUT_HANDLERS 16
esp_err_t espos_sk_put_handler_register(const char *path, espos_sk_put_handler_t cb, void *arg);
esp_err_t espos_sk_put_handler_unregister(const char *path);
esp_err_t espos_sk_put_respond(const char *request_id, const char *state, int status_code, const char *message);
esp_err_t espos_sk_flush(uint32_t timeout_ms);
typedef struct {
bool enabled;
bool connected;
uint32_t connected_s;
uint32_t reconnects; /* successful connections so far */
uint32_t sent; /* messages sent */
uint32_t send_errors;
uint32_t next_retry_s; /* while disconnected */
char last_error[64];
size_t pending, buffered, buffered_bytes;
uint32_t dropped;
size_t meta_declared, meta_reconciled;
uint32_t received; /* value/meta items delivered to subscribers */
uint32_t frames; /* text frames read */
size_t subs; /* active subscriptions */
size_t puts_pending;
uint32_t puts_sent, puts_failed;
uint32_t puts_in; /* inbound PUT items received from the server */
uint32_t puts_rejected; /* of those, answered 405 (no handler) or 502 */
} espos_sk_ws_status_t;
esp_err_t espos_sk_ws_get_status(espos_sk_ws_status_t *out);
esp_err_t espos_sk_get_token(char *buf, size_t size);
esp_err_t espos_sk_get_server(espos_sk_server_t *out);
const char *espos_sk_client_id(void);
esp_err_t espos_sk_set_app_name(const char *name);
#ifdef __cplusplus
}
#endif