Skip to content

Commit bb1c81f

Browse files
committed
continue documenting new features
1 parent fdf676a commit bb1c81f

File tree

6 files changed

+97
-19
lines changed

6 files changed

+97
-19
lines changed

README.md

Lines changed: 61 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -415,12 +415,14 @@ static LightSettingsDeserializer DESERIALIZER;
415415

416416
#### Endpoints
417417

418-
The framework provides a [SettingsEndpoint.h](lib/framework/SettingsEndpoint.h) class which may be used to register GET and POST handlers to read and update the settings over HTTP. You may construct a SettingsEndpoint as a part of the SettingsService or separately if you prefer. The code below demonstrates how to extend the LightSettingsService class to provide an unsecured endpoint:
418+
The framework provides a [SettingsEndpoint.h](lib/framework/SettingsEndpoint.h) class which may be used to register GET and POST handlers to read and update the settings over HTTP. You may construct a SettingsEndpoint as a part of the SettingsService or separately if you prefer.
419+
420+
The code below demonstrates how to extend the LightSettingsService class to provide an unsecured endpoint:
419421

420422
```cpp
421423
class LightSettingsService : public SettingsService<LightSettings> {
422424
public:
423-
LightSettingsService(AsyncWebServer* server, SecurityManager* securityManager) :
425+
LightSettingsService(AsyncWebServer* server) :
424426
_settingsEndpoint(&SERIALIZER, &DESERIALIZER, this, server, "/rest/lightSettings") {
425427
}
426428

@@ -429,28 +431,79 @@ class LightSettingsService : public SettingsService<LightSettings> {
429431
};
430432
```
431433
432-
Endpoint security is provided by authentication predicates which are [documented below](#security-features). A security manager and authentication predicate may be provided if an secure endpoint is required. The demo app shows how endpoints can be secured.
434+
Endpoint security is provided by authentication predicates which are [documented below](#security-features). The SecurityManager and authentication predicate may be provided if a secure endpoint is required. The demo project shows how endpoints can be secured.
433435
434436
#### Persistence
435437
436-
[SettingsPersistence.h](lib/framework/SettingsPersistence.h) allows you to save settings to the filesystem. SettingsPersistence automatically writes changes to the file system when settings are updated. This feature can be disabled by calling `disableAutomatic()` if manual control of persistence is required.
438+
[SettingsPersistence.h](lib/framework/SettingsPersistence.h) allows you to save settings to the filesystem. SettingsPersistence automatically writes changes to the file system when settings are updated. This feature can be disabled by calling `disableUpdateHandler()` if manual control of persistence is required.
437439
438-
As with SettingsEndpoint you may elect to construct this as a part of a SettingsService class or separately. The code below demonstrates how to extend the LightSettingsService class to provide persistence:
440+
The code below demonstrates how to extend the LightSettingsService class to provide persistence:
439441
440442
```cpp
441443
class LightSettingsService : public SettingsService<LightSettings> {
442444
public:
443-
LightSettingsService(AsyncWebServer* server, FS* fs, SecurityManager* securityManager) :
444-
_settingsEndpoint(&SERIALIZER, &DESERIALIZER, this, server, "/rest/lightSettings"),
445+
LightSettingsService(FS* fs) :
445446
_settingsPersistence(&SERIALIZER, &DESERIALIZER, this, fs, "/config/lightSettings.json") {
446447
}
447448
448449
private:
449-
SettingsEndpoint<LightSettings> _settingsEndpoint;
450450
SettingsPersistence<LightSettings> _settingsPersistence;
451451
};
452452
```
453453

454+
#### WebSockets
455+
456+
[SettingsSocket.h](lib/framework/SettingsSocket.h) allows you to read and update settings over a WebSocket connection. SettingsSocket automatically pushes changes to all connected clients when settings are updated.
457+
458+
The code below demonstrates how to extend the LightSettingsService class to provide an unsecured websocket:
459+
460+
```cpp
461+
class LightSettingsService : public SettingsService<LightSettings> {
462+
public:
463+
LightSettingsService(AsyncWebServer* server) :
464+
_settingsSocket(&SERIALIZER, &DESERIALIZER, this, server, "/ws/lightSettings"), {
465+
}
466+
467+
private:
468+
SettingsSocket<LightSettings> _settingsSocket;
469+
};
470+
```
471+
472+
WebSocket security is provided by authentication predicates which are [documented below](#security-features). The SecurityManager and authentication predicate may be provided if a secure WebSocket is required. The demo project shows how WebSockets can be secured.
473+
474+
#### MQTT
475+
476+
The framework includes an MQTT client which can be configured via the UI. MQTT requirements will differ from project to project so the framework exposes the client for you to use as you see fit. The framework does however provide a utility to interface SettingsService to a pair of pub/sub (state/set) topics. This utility can be used to synchronize state with software such as Home Assistant.
477+
478+
[SettingsBroker.h](lib/framework/SettingsBroker.h) allows you to read and update settings over a pair of MQTT topics. SettingsBroker automatically pushes changes to the pub topic and reads updates from the sub topic.
479+
480+
The code below demonstrates how to extend the LightSettingsService class to interface with MQTT:
481+
482+
```cpp
483+
class LightSettingsService : public SettingsService<LightSettings> {
484+
public:
485+
LightSettingsService(AsyncMqttClient* mqttClient) :
486+
_settingsBroker(&SERIALIZER,
487+
&DESERIALIZER,
488+
this,
489+
mqttClient,
490+
"homeassistant/light/my_light/set",
491+
"homeassistant/light/my_light/state") {
492+
}
493+
494+
private:
495+
SettingsBroker<LightSettings> _settingsBroker;
496+
};
497+
```
498+
499+
You can also re-configure the pub/sub topics at runtime as required:
500+
501+
```cpp
502+
_settingsBroker.configureBroker("homeassistant/light/desk_lamp/set", "homeassistant/light/desk_lamp/state");
503+
```
504+
505+
The demo project allows the user to modify the MQTT topics via the UI so they can be changed without re-flashing the firmware.
506+
454507
### Security features
455508

456509
The framework has security features to prevent unauthorized use of the device. This is driven by [SecurityManager.h](lib/framework/SecurityManager.h).

lib/framework/SettingsBroker.h

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,11 +28,15 @@ class SettingsBroker {
2828
SettingsBroker(SettingsSerializer<T>* settingsSerializer,
2929
SettingsDeserializer<T>* settingsDeserializer,
3030
SettingsService<T>* settingsService,
31-
AsyncMqttClient* mqttClient) :
31+
AsyncMqttClient* mqttClient,
32+
String setTopic = "",
33+
String stateTopic = "") :
3234
_settingsSerializer(settingsSerializer),
3335
_settingsDeserializer(settingsDeserializer),
3436
_settingsService(settingsService),
35-
_mqttClient(mqttClient) {
37+
_mqttClient(mqttClient),
38+
_setTopic(setTopic),
39+
_stateTopic(stateTopic) {
3640
_settingsService->addUpdateHandler([&](String originId) { publish(); }, false);
3741
_mqttClient->onConnect(std::bind(&SettingsBroker::configureMQTT, this));
3842
_mqttClient->onMessage(std::bind(&SettingsBroker::onMqttMessage,
@@ -98,7 +102,8 @@ class SettingsBroker {
98102
DeserializationError error = deserializeJson(json, payload, len);
99103
if (!error && json.is<JsonObject>()) {
100104
_settingsService->update(
101-
[&](T& settings) { _settingsDeserializer->deserialize(settings, json.as<JsonObject>()); }, SETTINGS_BROKER_ORIGIN_ID);
105+
[&](T& settings) { _settingsDeserializer->deserialize(settings, json.as<JsonObject>()); },
106+
SETTINGS_BROKER_ORIGIN_ID);
102107
}
103108
}
104109
};

lib/framework/SettingsPersistence.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ class SettingsPersistence {
2727
_settingsService(settingsManager),
2828
_fs(fs),
2929
_filePath(filePath) {
30-
enableAutomatic();
30+
enableUpdateHandler();
3131
}
3232

3333
void readFromFS() {
@@ -71,14 +71,14 @@ class SettingsPersistence {
7171
return true;
7272
}
7373

74-
void disableAutomatic() {
74+
void disableUpdateHandler() {
7575
if (_updateHandlerId) {
7676
_settingsService->removeUpdateHandler(_updateHandlerId);
7777
_updateHandlerId = 0;
7878
}
7979
}
8080

81-
void enableAutomatic() {
81+
void enableUpdateHandler() {
8282
if (!_updateHandlerId) {
8383
_updateHandlerId = _settingsService->addUpdateHandler([&](String originId) { writeToFS(); });
8484
}

platformio.ini

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ default_envs = esp12e
66
build_flags=
77
-D NO_GLOBAL_ARDUINOOTA
88
; Uncomment ENABLE_CORS to enable Cross-Origin Resource Sharing (required for local React development)
9-
-D ENABLE_CORS
9+
;-D ENABLE_CORS
1010
-D CORS_ORIGIN=\"http://localhost:3000\"
1111
; Uncomment PROGMEM_WWW to enable the storage of the WWW data in PROGMEM
1212
;-D PROGMEM_WWW

src/LightBrokerSettingsService.cpp

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,16 @@
33
static LightBrokerSettingsSerializer SERIALIZER;
44
static LightBrokerSettingsDeserializer DESERIALIZER;
55

6-
LightBrokerSettingsService::LightBrokerSettingsService(AsyncWebServer* server, FS* fs, SecurityManager* securityManager) :
7-
_settingsEndpoint(&SERIALIZER, &DESERIALIZER, this, server, LIGHT_BROKER_SETTINGS_PATH, securityManager),
6+
LightBrokerSettingsService::LightBrokerSettingsService(AsyncWebServer* server,
7+
FS* fs,
8+
SecurityManager* securityManager) :
9+
_settingsEndpoint(&SERIALIZER,
10+
&DESERIALIZER,
11+
this,
12+
server,
13+
LIGHT_BROKER_SETTINGS_PATH,
14+
securityManager,
15+
AuthenticationPredicates::IS_AUTHENTICATED),
816
_settingsPersistence(&SERIALIZER, &DESERIALIZER, this, fs, LIGHT_BROKER_SETTINGS_FILE) {
917
}
1018

src/LightSettingsService.cpp

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,21 @@ LightSettingsService::LightSettingsService(AsyncWebServer* server,
1010
SecurityManager* securityManager,
1111
AsyncMqttClient* mqttClient,
1212
LightBrokerSettingsService* lightBrokerSettingsService) :
13-
_settingsEndpoint(&SERIALIZER, &DESERIALIZER, this, server, LIGHT_SETTINGS_ENDPOINT_PATH, securityManager),
13+
_settingsEndpoint(&SERIALIZER,
14+
&DESERIALIZER,
15+
this,
16+
server,
17+
LIGHT_SETTINGS_ENDPOINT_PATH,
18+
securityManager,
19+
AuthenticationPredicates::IS_AUTHENTICATED),
1420
_settingsBroker(&HA_SERIALIZER, &HA_DESERIALIZER, this, mqttClient),
15-
_settingsSocket(&SERIALIZER, &DESERIALIZER, this, server, LIGHT_SETTINGS_SOCKET_PATH, securityManager),
21+
_settingsSocket(&SERIALIZER,
22+
&DESERIALIZER,
23+
this,
24+
server,
25+
LIGHT_SETTINGS_SOCKET_PATH,
26+
securityManager,
27+
AuthenticationPredicates::IS_AUTHENTICATED),
1628
_mqttClient(mqttClient),
1729
_lightBrokerSettingsService(lightBrokerSettingsService) {
1830
// configure blink led to be output

0 commit comments

Comments
 (0)