-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #9 from etienne1911/websockets
Websockets
- Loading branch information
Showing
12 changed files
with
344 additions
and
119 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
#include <FirmwareModule.h> | ||
#include <WebSocketService.h> | ||
|
||
class CamControls : FirmwareModule, WebSocketService | ||
{ | ||
public: | ||
CamControls() : FirmwareModule("CamControls"), WebSocketService("camcontrols"){}; | ||
|
||
void process() | ||
{ | ||
Serial.println("[CamControls] process message"); | ||
// Most of the time, you can rely on the implicit casts. | ||
// In other case, you can do doc["time"].as<long>(); | ||
// const char *service = jsonMsg["service"]; | ||
int count = jsonMsg["counter"]; | ||
|
||
// Print values. | ||
Serial.println(count); | ||
} | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,23 +1,49 @@ | ||
# esp32-toolkit-lib | ||
ESP32 firmware building lib | ||
ESP32 firmware build lib | ||
|
||
## Purpose | ||
Aim is to provide core features to quickly develop ESP32 firmware for various diy projects, as well as a modular architecture to extend firmware's features . | ||
|
||
Aim is to provide useful features commonly used in ESP32 firmware development and a flexible architecture to develop custom firmware modules. | ||
# Quick start | ||
|
||
Several other benefits among which: | ||
- no boilerplate code | ||
- entirely automated build process | ||
- ready to use workspace dev environment | ||
- easy to maintain and evolve | ||
- Grab a workspace artifact which includes source and project configuration | ||
- Customize wifi settings in `network-module.h`. | ||
- Build one of the default firmware available in exemples by linking main.cpp to the chosen firmware source file. | ||
- Upload to the board using serial interface. | ||
|
||
## Key features: | ||
|
||
## Included frameworks, librairies | ||
The lib makes use of the following libs: | ||
- latest [arduino-esp32](https://github.com/espressif/arduino-esp32) framework ([docs](https://docs.espressif.com/projects/arduino-esp32/en/latest/)): mandatory to use littleFS (not available to date in PIO) | ||
- `littleFS` filesystem with strong advantage (over SPIFFS) to support directories. | ||
- `ArduinoJson`: provide support for JSON | ||
|
||
# Architecture | ||
|
||
The firmware architecture is made of different modules and services. | ||
A module inherits the `FirmwareModule` class and can overrides `setup`, `loop` methods to provide its own implementation. | ||
In a similar way, a service provides a custom implementation of another service such as `WebSocketService`. | ||
|
||
|
||
## Core modules | ||
The firmware can embedd several core modules which implements main device features: | ||
|
||
- network: provides wifi connectivity in both AP (Access Point) and STA (Client) modes | ||
- filesystem: LittleFS | ||
- webserver | ||
- WebSockets Service | ||
- OTA service | ||
|
||
## Custom modules | ||
On top of these core modules, firmware can be easily extended through custom modules to provide additional features (such as specific sensor support, ...). | ||
To get included in the main update loop, a custom module inherits the `FirmwareModule` class. | ||
As C++ allows multiple inheritance, it can also inherit a service to make use of it. | ||
|
||
For instance a module requiring acceess to websockets, will inherit both `FirmwareModule` and `WebSocketService` which will forward | ||
received message to process them. | ||
|
||
## Predefined firmwares | ||
A set of predefined firmwares is ready to be used: | ||
# Purpose of this project | ||
|
||
- mini version | ||
- base version: mini version + network + filesys + web server + web sockets + OTA | ||
- full version: base version + json + | ||
- as less as boilerplate code possible | ||
- fully automated build process | ||
- ready to code workspace (available as build artifacts) | ||
- easy to maintain and customize |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
#include <FirmwareModule.h> | ||
#include <WebSocketService.h> | ||
|
||
class RovControl : FirmwareModule, WebSocketService | ||
{ | ||
public: | ||
RovControl() : FirmwareModule("RovControl"), WebSocketService("rovcontrol"){}; | ||
|
||
void process() | ||
{ | ||
Serial.println("[RoverControl] process message"); | ||
// Most of the time, you can rely on the implicit casts. | ||
// In other case, you can do doc["time"].as<long>(); | ||
int time = jsonMsg["counter"]; | ||
|
||
// Print values. | ||
// Serial.println(service); | ||
Serial.println(time); | ||
} | ||
}; |
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,123 @@ | ||
#include <WebSocketService.h> | ||
#include <string> | ||
AsyncWebSocket WebSocketService::aws("/ws"); | ||
std::vector<WebSocketService *> *WebSocketService::instances = new std::vector<WebSocketService *>(); | ||
|
||
// Allocate the JSON document | ||
// | ||
// Inside the brackets, 200 is the capacity of the memory pool in bytes. | ||
// Don't forget to change this value to match your JSON document. | ||
// Use arduinojson.org/v6/assistant to compute the capacity. | ||
// StaticJsonDocument<200> doc; | ||
|
||
// StaticJsonDocument<N> allocates memory on the stack, it can be | ||
// replaced by DynamicJsonDocument which allocates in the heap. | ||
// | ||
// DynamicJsonDocument doc(200); | ||
StaticJsonDocument<200> WebSocketService::jsonMsg; | ||
|
||
// JSON stub string. | ||
// | ||
// Using a char[], as shown here, enables the "zero-copy" mode. This mode uses | ||
// the minimal amount of memory because the JsonDocument stores pointers to | ||
// the input buffer. | ||
// If you use another type of input, ArduinoJson must copy the strings from | ||
// the input to the JsonDocument, so you need to increase the capacity of the | ||
// JsonDocument. | ||
char jsonDataStub[] = "{\"sensor\":\"gps\",\"time\":1351824120,\"data\":[48.756080,2.302038]}"; | ||
|
||
WebSocketService::WebSocketService(std::string name) : name(name) | ||
{ | ||
// register service instance | ||
WebSocketService::instances->push_back(this); | ||
} | ||
|
||
void WebSocketService::dispatch(void *arg, uint8_t *data, size_t len) | ||
{ | ||
AwsFrameInfo *info = (AwsFrameInfo *)arg; | ||
if (info->final && info->index == 0 && info->len == len && info->opcode == WS_TEXT) | ||
{ | ||
data[len] = 0; | ||
// convert raw data input | ||
std::string clientMsg(data, data + len); | ||
std::string serverMsg(""); | ||
|
||
// convert to a json object | ||
DeserializationError error = deserializeJson(jsonMsg, clientMsg); | ||
|
||
// Test if parsing succeeds. | ||
if (!error) | ||
{ | ||
// JsonObject jsonObj = jsonMsg.as<JsonObject>(); | ||
|
||
// for (JsonPair kv : jsonObj) | ||
// { | ||
// std::string serviceName(kv.key().c_str()); | ||
// JsonObject serviceData = kv.value().as<JsonObject>(); | ||
|
||
// } | ||
// dispatch message to corresponding service | ||
std::string serviceName = jsonMsg["service"]; | ||
Serial.println(serviceName.c_str()); | ||
for (auto service : *WebSocketService::instances) | ||
{ | ||
Serial.println(service->name.c_str()); | ||
// match service name | ||
if (service->name.compare(serviceName) == 0) | ||
{ | ||
std::string log = "[WebSocket] message routed to service " + serviceName; | ||
Serial.println(log.c_str()); | ||
service->process(); | ||
} | ||
} | ||
|
||
serverMsg.append(clientMsg); | ||
} | ||
else | ||
{ | ||
Serial.print(F("deserializeJson() failed: ")); | ||
Serial.println(error.f_str()); | ||
} | ||
|
||
// notify server response to all clients | ||
String dataOut(serverMsg.c_str()); | ||
aws.textAll(dataOut); | ||
} | ||
} | ||
|
||
void WebSocketService::eventHandler(AsyncWebSocket *server, AsyncWebSocketClient *client, AwsEventType type, | ||
void *arg, uint8_t *data, size_t len) | ||
{ | ||
switch (type) | ||
{ | ||
case WS_EVT_CONNECT: | ||
Serial.printf("[WebSocket] client #%u connected from %s\n", client->id(), client->remoteIP().toString().c_str()); | ||
break; | ||
case WS_EVT_DISCONNECT: | ||
Serial.printf("[WebSocket] client #%u disconnected\n", client->id()); | ||
break; | ||
case WS_EVT_DATA: | ||
Serial.println("[WebSocket] Data received"); | ||
dispatch(arg, data, len); | ||
break; | ||
case WS_EVT_PONG: | ||
case WS_EVT_ERROR: | ||
break; | ||
} | ||
} | ||
|
||
void WebSocketService::process() | ||
{ | ||
// Most of the time, you can rely on the implicit casts. | ||
// In other case, you can do doc["time"].as<long>(); | ||
const char *sensor = jsonMsg["sensor"]; | ||
long time = jsonMsg["time"]; | ||
double latitude = jsonMsg["data"][0]; | ||
double longitude = jsonMsg["data"][1]; | ||
|
||
// Print values. | ||
Serial.println(sensor); | ||
Serial.println(time); | ||
Serial.println(latitude, 6); | ||
Serial.println(longitude, 6); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
#pragma once | ||
|
||
#include <ESPAsyncWebServer.h> | ||
#include <ArduinoJson.h> | ||
#include <string> | ||
|
||
class WebSocketService | ||
{ | ||
public: | ||
static AsyncWebSocket aws; | ||
static std::vector<WebSocketService *> *instances; // the components that will process json message | ||
static StaticJsonDocument<200> jsonMsg; | ||
std::string name = ""; | ||
|
||
// WebSocketImpl(string awsUrl) : FirmwareModule("WebSocket") | ||
// { | ||
// Serial.printf("[WebSocket] creation"); | ||
// aws = new AsyncWebSocket(awsUrl.c_str()); | ||
// } | ||
WebSocketService(std::string name = "defaultservice"); | ||
|
||
static void eventHandler(AsyncWebSocket *server, AsyncWebSocketClient *client, AwsEventType type, | ||
void *arg, uint8_t *data, size_t len); | ||
|
||
static void dispatch(void *arg, uint8_t *data, size_t len); | ||
|
||
static void parseJson(std::string jsonStr); | ||
|
||
virtual void process(); | ||
}; |
Oops, something went wrong.