SensESP 3.2.2
Universal Signal K sensor toolkit ESP32
Loading...
Searching...
No Matches
signalk_ws_client.h
Go to the documentation of this file.
1#ifndef SENSESP_SRC_SENSESP_SIGNALK_SIGNALK_WS_CLIENT_H_
2#define SENSESP_SRC_SENSESP_SIGNALK_SIGNALK_WS_CLIENT_H_
3
4#include "sensesp.h"
5
6#include <ArduinoJson.h>
7#include <esp_websocket_client.h>
8#include <functional>
9#include <list>
10#include <set>
11
17#include "sensesp_base_app.h"
18
19namespace sensesp {
20
21static const char* NULL_AUTH_TOKEN = "";
22
29
35 virtual public ValueProducer<SKWSConnectionState> {
36 public:
38 // main task methods
39
40 SKWSClient(const String& config_path,
41 std::shared_ptr<SKDeltaQueue> sk_delta_queue,
42 const String& server_address, uint16_t server_port,
43 bool use_mdns = true);
44
45 const String get_server_address() const { return server_address_; }
46 uint16_t get_server_port() const { return server_port_; }
47
48 virtual bool to_json(JsonObject& root) override final;
49 virtual bool from_json(const JsonObject& config) override final;
50
58
67
68 String get_connection_status();
69
71 // SKWSClient task methods
72
73 void on_disconnected();
74 void on_error();
75 void on_connected();
76 void on_receive_delta(uint8_t* payload, size_t length);
77 void on_receive_updates(JsonDocument& message);
78 void on_receive_put(JsonDocument& message);
79 void connect();
80 void loop();
81 bool is_connected();
82 void restart();
83 void send_delta();
84
90 void sendTXT(String& payload);
91
95 bool is_ssl_enabled() const { return ssl_enabled_; }
96
103 void set_ssl_enabled(bool enabled) {
104 ssl_enabled_ = enabled;
105 save();
106 }
107
111 bool is_tofu_enabled() const { return tofu_enabled_; }
112
119 void set_tofu_enabled(bool enabled) {
120 tofu_enabled_ = enabled;
121 save();
122 }
123
127 bool has_tofu_fingerprint() const { return !tofu_fingerprint_.isEmpty(); }
128
132 const String& get_tofu_fingerprint() const { return tofu_fingerprint_; }
133
142 save();
143 }
144
148 void set_tofu_fingerprint(const String& fingerprint) {
149 tofu_fingerprint_ = fingerprint;
150 save();
151 }
152
153 protected:
154 // these are the actually used values
155 String server_address_ = "";
156 uint16_t server_port_ = 80;
157 // these are the hardcoded and/or conf file values
159 uint16_t conf_server_port_ = 0;
160 bool use_mdns_ = true;
161
162 String client_id_ = "";
163 String polling_href_ = "";
164 String auth_token_ = NULL_AUTH_TOKEN;
165 bool server_detected_ = false;
167
168 // SSL/TLS configuration
169 bool ssl_enabled_ = false;
170 bool tofu_enabled_ = true; // TOFU enabled by default
171 String tofu_fingerprint_ = ""; // SHA256 fingerprint in hex (64 chars)
172
175
180
181 esp_websocket_client_handle_t client_ = nullptr;
182 std::shared_ptr<SKDeltaQueue> sk_delta_queue_;
187
188 SemaphoreHandle_t received_updates_semaphore_ =
189 xSemaphoreCreateRecursiveMutex();
190 std::list<JsonDocument> received_updates_{};
191
193 // methods for all tasks
194
195 bool take_received_updates_semaphore(unsigned long int timeout_ms = 0) {
196 if (timeout_ms == 0) {
197 return xSemaphoreTake(received_updates_semaphore_, portMAX_DELAY) ==
198 pdTRUE;
199 } else {
200 return xSemaphoreTake(received_updates_semaphore_, timeout_ms) == pdTRUE;
201 }
202 }
206
208 // main task methods
209
211
213 // SKWSClient task methods
214
215 void connect_loop();
216 void test_token(const String host, const uint16_t port);
217 void send_access_request(const String host, const uint16_t port);
218 void poll_access_request(const String host, const uint16_t port,
219 const String href);
220 void connect_ws(const String& host, const uint16_t port);
221 void subscribe_listeners();
222 bool get_mdns_service(String& server_address, uint16_t& server_port);
223 bool detect_ssl();
224
230};
231
232inline const String ConfigSchema(const SKWSClient& obj) {
233 return "{\"type\":\"object\",\"properties\":{"
234 "\"ssl_enabled\":{\"title\":\"SSL/TLS Enabled\",\"type\":\"boolean\"},"
235 "\"tofu_enabled\":{\"title\":\"TOFU Verification\",\"type\":\"boolean\"},"
236 "\"tofu_fingerprint\":{\"title\":\"Server Fingerprint\",\"type\":\"string\",\"readOnly\":true}"
237 "}}";
238}
239
240inline bool ConfigRequiresRestart(const SKWSClient& obj) { return true; }
241
242} // namespace sensesp
243
244#endif
virtual bool save() override
Save the object to a persistent storage.
Definition saveable.cpp:41
FileSystemSaveable(const String &config_path)
Definition saveable.h:63
Integrator integrates (accumulates) the incoming values.
Definition integrator.h:19
The websocket connection to the Signal K server.
void reset_tofu_fingerprint()
Reset the stored TOFU certificate fingerprint.
std::list< JsonDocument > received_updates_
void poll_access_request(const String host, const uint16_t port, const String href)
SKWSClient(const String &config_path, std::shared_ptr< SKDeltaQueue > sk_delta_queue, const String &server_address, uint16_t server_port, bool use_mdns=true)
void on_receive_delta(uint8_t *payload, size_t length)
Called when the websocket receives a delta.
SemaphoreHandle_t received_updates_semaphore_
void set_tofu_fingerprint(const String &fingerprint)
Set the TOFU fingerprint (called from verify callback).
void process_received_updates()
Loop through the received updates and process them.
void set_ssl_enabled(bool enabled)
Enable or disable SSL/TLS manually.
void connect_ws(const String &host, const uint16_t port)
Integrator< int, int > delta_tx_count_producer_
TaskQueueProducer< SKWSConnectionState > connection_state_
SKWSConnectionState get_connection_state()
void on_receive_put(JsonDocument &message)
Called when a PUT event is received.
void release_received_updates_semaphore()
SKWSConnectionState task_connection_state_
void send_access_request(const String host, const uint16_t port)
Integrator< int, int > delta_rx_count_producer_
virtual bool to_json(JsonObject &root) override final
uint16_t get_server_port() const
esp_websocket_client_handle_t client_
void on_error()
Called when the websocket connection encounters an error.
void sendTXT(String &payload)
Send some processed data to the websocket.
bool get_mdns_service(String &server_address, uint16_t &server_port)
void on_disconnected()
Called when the websocket connection is disconnected.
ValueProducer< int > & get_delta_tx_count_producer()
void subscribe_listeners()
Subscribes the SK delta paths to the websocket.
void on_receive_updates(JsonDocument &message)
Called when a delta update is received.
void test_token(const String host, const uint16_t port)
bool has_tofu_fingerprint() const
Check if a TOFU fingerprint is stored.
void set_connection_state(SKWSConnectionState state)
ValueProducer< int > & get_delta_rx_count_producer()
Get the delta rx count producer object.
bool take_received_updates_semaphore(unsigned long int timeout_ms=0)
virtual bool from_json(const JsonObject &config) override final
void set_tofu_enabled(bool enabled)
Enable or disable TOFU certificate verification.
String get_connection_status()
Get a String representation of the current connection state.
const String get_server_address() const
TaskQueueProducer< int > delta_tx_tick_producer_
Emits the number of deltas sent since last report.
const String & get_tofu_fingerprint() const
Get the stored TOFU fingerprint.
bool is_ssl_enabled() const
Check if SSL/TLS is enabled.
std::shared_ptr< SKDeltaQueue > sk_delta_queue_
void on_connected()
Called when the websocket connection is established.
bool is_tofu_enabled() const
Check if TOFU certificate verification is enabled.
Producer class that works across task boundaries.
const String ConfigSchema(const SmartSwitchController &obj)
std::shared_ptr< reactesp::EventLoop > event_loop()
Definition sensesp.cpp:9
bool ConfigRequiresRestart(const HTTPServer &obj)