Skip to content

Commit

Permalink
lws test server integration
Browse files Browse the repository at this point in the history
  • Loading branch information
lws-team committed Mar 11, 2017
1 parent a6cc187 commit 95e3955
Show file tree
Hide file tree
Showing 8 changed files with 424 additions and 101 deletions.
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,6 @@
build/
sdkconfig.old
_sdkconfig
romfs-files/ssl-cert.der
romfs-files/ssl-key.der

15 changes: 14 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,21 @@
# This is a project Makefile. It is assumed the directory this Makefile resides in is a
# project subdirectory.
#
PROJECT_NAME := lws-esp32
SSL_CERT_PEM:=${PWD}/build/libwebsockets/libwebsockets-test-server
SSL_KEY_PEM:=${PWD}/build/libwebsockets/libwebsockets-test-server.key

PROJECT_NAME := app-template
export SSL_CERT_PEM
export SSL_KEY_PEM

include $(IDF_PATH)/make/project.mk
include sdkconfig
# stick the romfs filesystem in its own romfs part
flash-romfs:
$(IDF_PATH)/components/esptool_py/esptool/esptool.py \
--chip esp32 \
--port $(CONFIG_ESPTOOLPY_PORT) \
--baud $(CONFIG_ESPTOOLPY_BAUD) \
write_flash 0x310000 build/main/romfs.img


125 changes: 125 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
lws-esp32
=========

## Status

- Station mode provides the full lws test server on port 443 over htps, all working

- ESP32 becomes an AP and serves dynamic websocket-based scan / config page,
so you can set up your AP and password. Initially comes up in this since
the AP details are not set yet.

![lws AP mode config page](https://libwebsockets.org/lws-esp32-ap.png)

- Integration to new projects hugely simplified by moving common lws support code
into lws directly. Non-library parts licensed are CC0.


## Customizing to your build setup

### 0) Set the right serial device in menuconfig

### 1) Patch esp-idf

You can either use the already-patched esp-idf at

$ git clone --init --recursive https://github.com/lws-team/lws-esp-idf

or you can apply this patch to your own esp-idf

```diff
Apply this patch on esp-idf, then


diff --git a/.gitmodules b/.gitmodules
index 6a6af0e..897992d 100644
--- a/.gitmodules
+++ b/.gitmodules
@@ -13,3 +13,7 @@
[submodule "components/coap/libcoap"]
path = components/coap/libcoap
url = https://github.com/obgm/libcoap.git
+[submodule "components/libwebsockets"]
+ path = components/libwebsockets
+ url = https://[email protected]/warmcat/libwebsockets
+ branch=master
diff --git a/components/libwebsockets b/components/libwebsockets
new file mode 160000
index 0000000..3a09c3b
--- /dev/null
+++ b/components/libwebsockets
@@ -0,0 +1 @@
+Subproject commit 102d40e6b6486076f37a46708604ec387834f16c
```

and then do

```
$ git submodules update --recursive
```

from the esp-idf

### 2) Partitioning the device

Clear down the partitioning since we write a custom table and the bootloader
will choke if the OTA parts are not initialized like this

```
$ make erase_flash
```

## Writing the ROMFS to flash

A ROMFS contains the files to be served, stored at a partition at the end
of the flash.

There's currently space for ~900KiB there.

The ROMFS is generated automatically from files in `./romfs-files` every make.

Write it and update it in the flash like this:

```
$ make all flash-romfs
```

## General build and flash

```
$ make all flash monitor
```

## Using the AP config

- connect your wifi to the ap "lws-config-...."

- In a browser, go to https://192.168.4.1

- set a serial number, like 1234

- Select your normal AP from the list

- Give the AP password and click the button

- Your ESP32 resets into Station mode and associates with the AP

## Using the lws test apps

See what IP your ESP32 got from your AP, the visit it in your browser
using, eg https://192.168.2.249

If your dhcp server provides your dns, you can also reach the device
using lws-serial, eg, https://lws-1234

- dumb increment should be updating at ~20Hz

- mirror should let you draw in the canvas... open a second browser
instance and they should be able to see each other's drawings

- close testing should work

- server info should reflect browsers open on the site dynamically

- POST tests should pass the string and upload the file if one given

12 changes: 0 additions & 12 deletions README.rst

This file was deleted.

22 changes: 14 additions & 8 deletions main/component.mk
Original file line number Diff line number Diff line change
@@ -1,8 +1,14 @@
#
# Main component makefile.
#
# This Makefile can be left empty. By default, it will take the sources in the
# src/ directory, compile them and link them into lib(subdirectory_name).a
# in the build directory. This behaviour is entirely configurable,
# please read the ESP-IDF documents if you need to do this.
#
#COMPONENT_EXTRA_CLEAN := logo.h
main.o: prepare

.PHONY: prepare
prepare:
tail -n +2 $(SSL_CERT_PEM).pem | \
head -n -1 | base64 -d - \
> $(COMPONENT_PATH)/../romfs-files/ssl-cert.der
tail -n +2 $(SSL_KEY_PEM).pem | \
head -n -1 | base64 -d - \
> $(COMPONENT_PATH)/../romfs-files/ssl-key.der
genromfs -f romfs.img -d $(COMPONENT_PATH)/../romfs-files


184 changes: 150 additions & 34 deletions main/main.c
Original file line number Diff line number Diff line change
@@ -1,42 +1,158 @@
#include "freertos/FreeRTOS.h"
#include "esp_wifi.h"
#include "esp_system.h"
#include "esp_event.h"
#include "esp_event_loop.h"
#include "nvs_flash.h"
#include "driver/gpio.h"
/*
* Example ESP32 app code using Libwebsockets
*
* Copyright (C) 2017 Andy Green <[email protected]>
*
* This file is made available under the Creative Commons CC0 1.0
* Universal Public Domain Dedication.
*
* The person who associated a work with this deed has dedicated
* the work to the public domain by waiving all of his or her rights
* to the work worldwide under copyright law, including all related
* and neighboring rights, to the extent allowed by law. You can copy,
* modify, distribute and perform the work, even for commercial purposes,
* all without asking permission.
*
* The test apps are intended to be adapted for use in your code, which
* may be proprietary. So unlike the library itself, they are licensed
* Public Domain.
*
*/
#include <libwebsockets.h>
#include <nvs_flash.h>

/* replace this with the model name of your device, eg "Bogotron 9000" */
char lws_esp32_model[16] = "lws";

/*
* where the ROMFS start in your partition table...
* this already matches the provided partition table
*/
#define ROMFS_START_IN_FLASH 0x310000

/*
* Configuration for normal station website
*
* We implement the generic lws test server features using
* generic plugin code from lws. Normally these plugins
* are dynamically loaded at runtime, but we use them by
* statically including them.
*
* To customize for your own device, you would remove these
* and put your own plugin include here
*/
#include "plugins/protocol_dumb_increment.c"
#include "plugins/protocol_lws_mirror.c"
#include "plugins/protocol_post_demo.c"
#include "plugins/protocol_lws_status.c"

static const struct lws_protocols protocols_station[] = {
{
"http-only",
lws_callback_http_dummy,
0,
900, 0, NULL
},
LWS_PLUGIN_PROTOCOL_DUMB_INCREMENT, /* demo... */
LWS_PLUGIN_PROTOCOL_MIRROR, /* replace with */
LWS_PLUGIN_PROTOCOL_POST_DEMO, /* your own */
LWS_PLUGIN_PROTOCOL_LWS_STATUS, /* plugin protocol */
{ NULL, NULL, 0, 0, 0, NULL } /* terminator */
};

/*
* this makes a special URL "/formtest" which gets passed to
* the "protocol-post-demo" plugin protocol for handling
*/
static const struct lws_http_mount mount_station_post = {
.mountpoint = "/formtest",
.origin = "protocol-post-demo",
.origin_protocol = LWSMPRO_CALLBACK,
.mountpoint_len = 9,
};

/*
* this serves "/station/..." in the romfs at "/" in the URL namespace
*/
static const struct lws_http_mount mount_station = {
.mount_next = &mount_station_post,
.mountpoint = "/",
.origin = "/station",
.def = "test.html",
.origin_protocol = LWSMPRO_FILE,
.mountpoint_len = 1,
};

esp_err_t event_handler(void *ctx, system_event_t *event)
{
return ESP_OK;
/* deal with your own user events here first */

return lws_esp32_event_passthru(ctx, event);
}

void app_main(void)
/*
* This is called to find out if we should boot into AP / config mode.
*
* If the nvs setup data is missing, we always go into AP / config mode.
*
* But there should also be a device-specific way to hold down a
* key at boot or whatever to force it, for example if he changes his
* location or AP and can no longer connect normally.
*/
int
lws_esp32_is_booting_in_ap_mode(void)
{
nvs_flash_init();
tcpip_adapter_init();
ESP_ERROR_CHECK( esp_event_loop_init(event_handler, NULL) );
wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
ESP_ERROR_CHECK( esp_wifi_init(&cfg) );
ESP_ERROR_CHECK( esp_wifi_set_storage(WIFI_STORAGE_RAM) );
ESP_ERROR_CHECK( esp_wifi_set_mode(WIFI_MODE_STA) );
wifi_config_t sta_config = {
.sta = {
.ssid = "access_point_name",
.password = "password",
.bssid_set = false
}
};
ESP_ERROR_CHECK( esp_wifi_set_config(WIFI_IF_STA, &sta_config) );
ESP_ERROR_CHECK( esp_wifi_start() );
ESP_ERROR_CHECK( esp_wifi_connect() );

gpio_set_direction(GPIO_NUM_4, GPIO_MODE_OUTPUT);
int level = 0;
while (true) {
gpio_set_level(GPIO_NUM_4, level);
level = !level;
vTaskDelay(300 / portTICK_PERIOD_MS);
}
/* return 1 to force entry to AP mode */
// return 1;

return 0;
}

/*
* This is called when the user asks to "Identify physical device"
* he is configuring, by pressing the Identify button on the AP
* setup page for the device.
*
* It should do something device-specific that
* makes it easy to identify which physical device is being
* addressed, like flash an LED on the device on a timer for a
* few seconds.
*/
void
lws_esp32_identify_physical_device(void)
{
lwsl_notice("%s\n", __func__);
}

void app_main(void)
{
static struct lws_context_creation_info info;
struct lws_context *context;

memset(&info, 0, sizeof(info));

info.port = 443;
info.fd_limit_per_thread = 30;
info.max_http_header_pool = 3;
info.max_http_header_data = 512;
info.pt_serv_buf_size = 900;
info.keepalive_timeout = 5;
info.options = LWS_SERVER_OPTION_EXPLICIT_VHOSTS |
LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT;

info.ssl_cert_filepath = "/ssl-cert.der";
info.ssl_private_key_filepath = "/ssl-key.der";

info.vhost_name = "station";
info.protocols = protocols_station;
info.mounts = &mount_station;

nvs_flash_init();
lws_esp32_wlan_config();
ESP_ERROR_CHECK( esp_event_loop_init(event_handler, NULL));
lws_esp32_wlan_start();
context = lws_esp32_init(&info, ROMFS_START_IN_FLASH);

while (!lws_service(context, 50))
vTaskDelay(1);
}
10 changes: 10 additions & 0 deletions partitions.csv
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
# Espressif ESP32 Partition Table
# Name, Type, SubType, Offset, Size
nvs, data, nvs, 0x9000, 0x4000
otadata, data, ota, 0xd000, 0x2000
phy_init, data, phy, 0xf000, 0x1000
factory, 0, 0, 0x10000, 1M
ota_0, 0, ota_0, , 1M
ota_1, 0, ota_1, , 1M
romfs, data, 0x80, 0x310000, 0xf0000

Loading

0 comments on commit 95e3955

Please sign in to comment.