Skip to content

Commit

Permalink
Merge pull request #53 from theelims/messagepack
Browse files Browse the repository at this point in the history
Messagepack Event Socket
  • Loading branch information
theelims committed May 6, 2024
2 parents 1bf5197 + d1f248b commit e2151b6
Show file tree
Hide file tree
Showing 88 changed files with 740 additions and 451 deletions.
24 changes: 22 additions & 2 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,23 +2,43 @@

All notable changes to this project will be documented in this file.

## [WIP] - Current Main
## [0.5.0] - 2024-05-06

Changes the Event Socket System to use a clearer message structure and MessagePack. Brings breaking changes to the `EventSocket.h` API.

Updated daisyUI to v4. This has changes in the colors and switches to OKLCH. Also button groups and input groups have been depreciated in favor of join. This might require changes to custom parts of the code. Please double check all websites if the still have the desired looks.

Updates ArduinoJSON from v6 to v7 to increase the available free heap. If you make use of ArduinoJSON, changes might be required.

### Added

- Debug buildflag to switch between MessagePack and JSON for event messages.
- Show SSID of the current WiFi Station as tooltip of the RSSI icon.

### Changed

- Moved MQTT types to models.ts as well. [#49](https://github.com/theelims/ESP32-sveltekit/pull/49)
- Fixed spelling error in models.tsnpm audit
- Updated daisyUI to 4.10.2 [#48](https://github.com/theelims/ESP32-sveltekit/pull/48)
- Fixed spelling error in models.ts
- Changed ArduinoJson from v6 to v7 increasing the free heap by ~40kb
- Split NotificationService out of EventSocket into own class
- Changed API of EventSocket.h. Now uses `void emitEvent(String event, JsonObject &jsonObject, const char *originId = "", bool onlyToSameOrigin = false);`.
- Changed event socket message format to MessagePack

### Fixed

- Fixes to WiFi.svelte and models.ts to fix type errors and visibility rights.
- Fixes bug in highlighting the menu when navigating with the browser (back/forward)
- Made WiFi connection routine more robust by using BSSID. Ensures that the STA truly connects to the strongest hotspot, even if several hotspots are in reach.

### Removed

- Removed duplicate in ESP32SvelteKit.cpp [#47](https://github.com/theelims/ESP32-sveltekit/pull/47) and WiFi.svelte [#50](https://github.com/theelims/ESP32-sveltekit/pull/50)

### Acknowledgment

Many thanks to @runeharlyk who contributed significantly to the new event socket system and fixed many smaller issues with the front-end.

## [0.4.0] - 2024-04-21

This upgrade might require one minor change as `MqttPubSub.h` and its class had been renamed to `MqttEndpoint.h` and `MqttEndoint` respectively. However, it is strongly advised, that you change all existing WebSocketServer endpoints to the new event socket system.
Expand Down
2 changes: 1 addition & 1 deletion LICENSE
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ under the MIT License.

MIT License

Copyright (c) 2023 theelims
Copyright (C) 2023 - 2024 theelims

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
Expand Down
4 changes: 2 additions & 2 deletions docs/buildprocess.md
Original file line number Diff line number Diff line change
Expand Up @@ -56,12 +56,12 @@ In addition custom features might be added or removed at runtime. See [Custom Fe

## Factory Settings

The framework has built-in factory settings which act as default values for the various configurable services where settings are not saved on the file system. These settings can be overridden using the build flags defined in [factory_settings.ini](https://github.com/theelims/ESP32-sveltekit/blob/main/factory_settings.ini).
The framework has built-in factory settings which act as default values for the various configurable services where settings are not saved on the file system. These settings can be overridden using the build flags defined in [factory_settings.ini](https://github.com/theelims/ESP32-sveltekit/blob/main/factory_settings.ini). All strings entered here must be escaped, especially special characters.

Customize the settings as you see fit, for example you might configure your home WiFi network as the factory default:

```ini
-D FACTORY_WIFI_SSID=\"My Awesome WiFi Network\"
-D FACTORY_WIFI_SSID=\"My\ Awesome\ WiFi\ Network\"
-D FACTORY_WIFI_PASSWORD=\"secret\"
-D FACTORY_WIFI_HOSTNAME=\"awesome_light_controller\"
```
Expand Down
36 changes: 29 additions & 7 deletions docs/statefulservice.md
Original file line number Diff line number Diff line change
Expand Up @@ -303,14 +303,36 @@ The demo project allows the user to modify the MQTT topics via the UI so they ca

Beside RESTful HTTP Endpoints the Event Socket System provides a convenient communication path between the client and the ESP32. It uses a single WebSocket connection to synchronize state and to push realtime data to the client. The client needs to subscribe to the topics he is interested. Only clients who have an active subscription will receive data. Every authenticated client may make use of this system as the security settings are set to `AuthenticationPredicates::IS_AUTHENTICATED`.

### Message Format

The event messages exchanged between the ESP32 and its clients consists of an "event" head and the "data" payload. For the LightState example a message looks like this in JSON representation:

```JSON
{
"event": "led",
"data": {
"led_on": true
}
}
```

To save on bandwidth the event message is encoded as binary [MessagePack](https://msgpack.org/) instead of a JSON.

To subscribe the client has to send the following message (as MessagePack):

```JSON
{
"event": "subscribe",
"data": "analytics"
}
```

### Emit an Event

The Event Socket provides an overloaded `emit()` function to push data to all subscribed clients. This is used by various esp32sveltekit classes to push real time data to the client. First an event must be registered with the Event Socket by calling `_socket.registerEvent("CustomEvent");`. Only then clients may subscribe to this custom event and you're entitled to emit event data:
The Event Socket provides an `emitEvent()` function to push data to all subscribed clients. This is used by various esp32sveltekit classes to push real time data to the client. First an event must be registered with the Event Socket by calling `_socket.registerEvent("CustomEvent");`. Only then clients may subscribe to this custom event and you're entitled to emit event data:

```cpp
void emit(String event, String payload);
void emit(const char *event, const char *payload);
void emit(const char *event, const char *payload, const char *originId, bool onlyToSameOrigin = false);
void emitEvent(String event, JsonObject &jsonObject, const char *originId = "", bool onlyToSameOrigin = false);
```
The latter function allowing a selection of the recipient. If `onlyToSameOrigin = false` the payload is distributed to all subscribed clients, except the `originId`. If `onlyToSameOrigin = true` only the client with `originId` will receive the payload. This is used by the [EventEndpoint](#event-socket-endpoint) to sync the initial state when a new client subscribes.
Expand All @@ -331,7 +353,7 @@ _socket.onEvent("CostumEvent",[&](JsonObject &root, int originId)
Similarly a callback or lambda function may be registered to get notified when a client subscribes to an event:

```cpp
_socket.onEvent("CostumEvent",[&](const String &originId, bool sync)
_socket.onSubscribe("CostumEvent",[&](const String &originId)
{
Serial.println("New Client subscribed: " + originId);
});
Expand All @@ -344,7 +366,7 @@ The boolean parameter provided will always be `true`.
It is possibly to send push notifications to all clients by using the Event Socket. These will be displayed as toasts an the client side. Either directly call

```cpp
esp32sveltekit.getSocket()->pushNotification("Pushed a message!", PUSHINFO);
esp32sveltekit.getNotificationService()->pushNotification("Pushed a message!", PUSHINFO);
```
or keep a local pointer to the `EventSocket` instance. It is possible to send `PUSHINFO`, `PUSHWARNING`, `PUSHERROR` and `PUSHSUCCESS` events to all clients.
Expand Down Expand Up @@ -377,7 +399,7 @@ In case of a websocket connection the JWT token is supplied as a search paramete

## Placeholder substitution

Various settings support placeholder substitution, indicated by comments in [factory_settings.ini](https://github.com/theelims/ESP32-sveltekit/blob/main/factory_settings.ini). This can be particularly useful where settings need to be unique, such as the Access Point SSID or MQTT client id. The following placeholders are supported:
Various settings support placeholder substitution, indicated by comments in [factory_settings.ini](https://github.com/theelims/ESP32-sveltekit/blob/main/factory_settings.ini). This can be particularly useful where settings need to be unique, such as the Access Point SSID or MQTT client id. Strings must be properly escaped in the ini-file. The following placeholders are supported:

| Placeholder | Substituted value |
| ------------ | --------------------------------------------------------------------- |
Expand Down
1 change: 1 addition & 0 deletions docs/stores.md
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ It exposes the following properties you can subscribe to:
| Property | Type | Description |
| ---------------------------------- | --------- | ------------------------------------------- |
| `$telemetry.rssi.rssi` | `Number` | The RSSI signal strength of the WiFi in dBm |
| `$telemetry.rssi.ssid` | `String` | Name of the connected WiFi station |
| `$telemetry.rssi.connected` | `Boolean` | Connection status of the WiFi |
| `$telemetry.battery.soc` | `Number` | Battery state of charge |
| `$telemetry.battery.charging` | `Boolean` | Is battery connected to charger |
Expand Down
2 changes: 0 additions & 2 deletions docs/structure.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,6 @@ The menu consists of an array of menu items. These are defined as follows:
icon: Control,
href: '/demo',
feature: $page.data.features.project,
active: false
},
```

Expand All @@ -68,7 +67,6 @@ export const load = (async ({ fetch }) => {
- `icon` must be an icon component giving the menu items icon.
- `href` is the link to the route the menu item refers to.
- `feature` takes a bool and should be set to `true`. It is used by the [feature selector](#features) to hide a menu entry of it is not present on the back end.
- `active` takes a bool as well and should be set to `false` by default. It is automatically set to `true` to highlight a menu entry as active.

## Advanced Customizations

Expand Down
2 changes: 1 addition & 1 deletion interface/LICENSE
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ under the MIT License.

MIT License

Copyright (c) 2023 theelims
Copyright (C) 2023 - 2024 theelims

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
Expand Down
Loading

0 comments on commit e2151b6

Please sign in to comment.