Skip to content

Commit 67eb9d4

Browse files
authored
Merge pull request #49 from rjwats/ft_demo_project
Ft demo project
2 parents 2ceb54c + b7b0688 commit 67eb9d4

File tree

82 files changed

+2680
-2128
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

82 files changed

+2680
-2128
lines changed

README.md

Lines changed: 86 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -42,8 +42,9 @@ Resource | Description
4242
---- | -----------
4343
[data/](data) | The file system image directory
4444
[interface/](interface) | React based front end
45-
[src/](src) | C++ back end for the ESP8266 device
45+
[src/](src) | The main.cpp and demo project to get you started
4646
[platformio.ini](platformio.ini) | PlatformIO project configuration file
47+
[lib/framework/](lib/framework) | C++ back end for the ESP8266 device
4748

4849
### Building the firmware
4950

@@ -247,13 +248,92 @@ There is also a manifest file which contains the app name to use when adding the
247248
}
248249
```
249250

250-
## Back End Overview
251+
## Back end overview
251252

252-
The back end is a set of REST endpoints hosted by a [ESPAsyncWebServer](https://github.com/me-no-dev/ESPAsyncWebServer) instance. The source is split up by feature, for example [WiFiScanner.h](src/WiFiScanner.h) implements the end points for scanning for available networks.
253+
The back end is a set of REST endpoints hosted by a [ESPAsyncWebServer](https://github.com/me-no-dev/ESPAsyncWebServer) instance. The ['lib/framework'](lib/framework) directory contains the majority of the back end code. The framework contains of a number of useful utility classes which you can use when extending it. The project also comes with a demo project to give you some help getting started.
253254

254-
There is an abstract class [SettingsService.h](src/SettingsService.h) that provides an easy means of adding configurable services/features to the device. It takes care of writing the settings as JSON to SPIFFS. All you need to do is extend the class with your required configuration and implement the functions which serialize the settings to/from JSON. JSON serialization utilizes the excellent [ArduinoJson](https://github.com/bblanchon/ArduinoJson) library.
255+
The framework's source is split up by feature, for example [WiFiScanner.h](lib/framework/WiFiScanner.h) implements the end points for scanning for available networks where as [WiFiSettingsService.h](lib/framework/WiFiSettingsService.h) handles configuring the WiFi settings and managing the WiFi connection.
255256

256-
Here is a example of a service with username and password settings:
257+
### Initializing the framework
258+
259+
The ['src/main.cpp'](src/main.cpp) file constructs the webserver and initializes the framework. You can add endpoints to the server here to support your IoT project. The main loop is also accessable so you can run your own code easily.
260+
261+
The following code creates the web server, esp8266React framework and the demo project instance:
262+
263+
```cpp
264+
AsyncWebServer server(80);
265+
ESP8266React esp8266React(&server, &SPIFFS);
266+
DemoProject demoProject = DemoProject(&server, &SPIFFS, esp8266React.getSecurityManager());
267+
```
268+
269+
Now in the `setup()` function the initialization is performed:
270+
271+
```cpp
272+
void setup() {
273+
// start serial and filesystem
274+
Serial.begin(SERIAL_BAUD_RATE);
275+
276+
// start the file system (must be done before starting the framework)
277+
SPIFFS.begin();
278+
279+
// start the framework and demo project
280+
esp8266React.begin();
281+
282+
// start the demo project
283+
demoProject.begin();
284+
285+
// start the server
286+
server.begin();
287+
}
288+
```
289+
290+
Finally the loop calls the framework's loop function to service the frameworks features. You can add your own code in here, as shown with the demo project:
291+
292+
```cpp
293+
void loop() {
294+
// run the framework's loop function
295+
esp8266React.loop();
296+
297+
// run the demo project's loop function
298+
demoProject.loop();
299+
}
300+
```
301+
302+
### Adding endpoints
303+
304+
There are some simple classes that support adding configurable services/features to the device:
305+
306+
Class | Description
307+
----- | -----------
308+
[SimpleService.h](lib/framework/SimpleService.h) | Exposes an endpoint to read and write settings as JSON. Extend this class and implement the functions which serialize the settings to/from JSON.
309+
[SettingsService.h](lib/framework/SettingsService.h) | As above, however this class also handles persisting the settings as JSON to the file system.
310+
[AdminSettingsService.h](lib/framework/AdminSettingsService.h) | Extends SettingsService to secure the endpoint to administrators only, the authentication predicate can be overridden if required.
311+
312+
The demo project shows how these can be used, explore the framework classes for more examples.
313+
314+
### Security features
315+
316+
The framework has security features to prevent unauthorized use of the device. This is driven by [SecurityManager.h](lib/framework/SecurityManager.h).
317+
318+
On successful authentication, the /rest/signIn endpoint issues a JWT which is then sent using Bearer Authentication. The framework come with built in predicates for verifying a users access level. The built in AuthenticationPredicates can be found in [SecurityManager.h](lib/framework/SecurityManager.h):
319+
320+
Predicate | Description
321+
-------------------- | -----------
322+
NONE_REQUIRED | No authentication is required.
323+
IS_AUTHENTICATED | Any authenticated principal is permitted.
324+
IS_ADMIN | The authenticated principal must be an admin.
325+
326+
You can use the security manager to wrap any web handler with an authentication predicate:
327+
328+
```cpp
329+
server->on("/rest/someService", HTTP_GET,
330+
_securityManager->wrapRequest(std::bind(&SomeService::someService, this, std::placeholders::_1), AuthenticationPredicates::IS_AUTHENTICATED)
331+
);
332+
```
333+
334+
Alternatively you can extend [AdminSettingsService.h](lib/framework/AdminSettingsService.h) and optionally override `getAuthenticationPredicate()` to secure an endpoint.
335+
336+
## Extending the framework
257337

258338
```cpp
259339
#include <SettingsService.h>
@@ -321,6 +401,7 @@ void reconfigureTheService() {
321401

322402
* [React](https://reactjs.org/)
323403
* [Material-UI](https://material-ui-next.com/)
404+
* [notistack](https://github.com/iamhosseindhv/notistack)
324405
* [Time](https://github.com/PaulStoffregen/Time)
325406
* [NtpClient](https://github.com/gmag11/NtpClient)
326407
* [ArduinoJson](https://github.com/bblanchon/ArduinoJson)

data/config/apSettings.json

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
{
2-
"provision_mode": 0,
3-
"ssid": "ESP8266-React",
4-
"password": "esp-react"
5-
}
2+
"provision_mode": 0,
3+
"ssid": "ESP8266-React",
4+
"password": "esp-react"
5+
}

data/config/demoSettings.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
{
2+
"blink_speed": 100
3+
}

data/config/ntpSettings.json

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
{
2-
"server":"pool.ntp.org",
3-
"interval":3600
4-
}
2+
"server": "pool.ntp.org",
3+
"interval": 3600
4+
}

data/config/otaSettings.json

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
{
2-
"enabled":true,
3-
"port": 8266,
4-
"password": "esp-react"
5-
}
2+
"enabled": true,
3+
"port": 8266,
4+
"password": "esp-react"
5+
}

data/config/securitySettings.json

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,15 @@
11
{
2-
"jwt_secret":"esp8266-react",
3-
"users": [
4-
{
5-
"username": "admin",
6-
"password": "admin",
7-
"admin": true
8-
},
9-
{
10-
"username": "guest",
11-
"password": "guest",
12-
"admin": false
13-
}
14-
]
2+
"jwt_secret": "esp8266-react",
3+
"users": [
4+
{
5+
"username": "admin",
6+
"password": "admin",
7+
"admin": true
8+
},
9+
{
10+
"username": "guest",
11+
"password": "guest",
12+
"admin": false
13+
}
14+
]
1515
}

data/config/wifiSettings.json

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
2-
"ssid":"",
3-
"password":"password",
4-
"hostname":"esp8266-react",
5-
"static_ip_config":false
6-
}
2+
"ssid": "",
3+
"password": "password",
4+
"hostname": "esp8266-react",
5+
"static_ip_config": false
6+
}

interface/.env

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,5 @@
1-
REACT_APP_NAME=ESP8266 React
1+
# This is the name of your project. It appears on the sign-in page and in the menu bar.
2+
REACT_APP_PROJECT_NAME=ESP8266 React
3+
4+
# This is the url path your project will be exposed under.
5+
REACT_APP_PROJECT_PATH=project

interface/.env.development

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,3 @@
1-
REACT_APP_ENDPOINT_ROOT=http://192.168.0.11/rest/
1+
# Change the IP address to that of your ESP device to enable local development of the UI.
2+
# Remember to also enable CORS in platformio.ini before uploading the code to the device.
3+
REACT_APP_ENDPOINT_ROOT=http://192.168.0.20/rest/

0 commit comments

Comments
 (0)