10000 Thu Dec 1 11:59:43 CST 2016 · elix22/esp32-snippets@9ce7bdd · GitHub
[go: up one dir, main page]

Skip to content

Commit 9ce7bdd

Browse files
author
kolban
committed
Thu Dec 1 11:59:43 CST 2016
1 parent ac57831 commit 9ce7bdd

File tree

6 files changed

+277
-67
lines changed

6 files changed

+277
-67
lines changed

hardware/neopixels/WS2812.cpp

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
#include <driver/gpio.h>
1111
#include <stdint.h>
1212
#include <driver/rmt.h>
13+
#include <stdlib.h>
1314
#include "sdkconfig.h"
1415

1516
static char tag[] = "WS2812";
@@ -24,6 +25,9 @@ static char tag[] = "WS2812";
2425
*
2526
*/
2627

28+
/**
29+
* Set two levels of RMT output to the Neopixel value for a "1".
30+
*/
2731
static void setItem1(rmt_item32_t *pItem) {
2832
pItem->level0 = 1;
2933
pItem->duration0 = 7;
@@ -32,6 +36,9 @@ static void setItem1(rmt_item32_t *pItem) {
3236
} // setItem1
3337

3438

39+
/**
40+
* Set two levels of RMT output to the Neopixel value for a "0".
41+
*/
3542
static void setItem0(rmt_item32_t *pItem) {
3643
pItem->level0 = 1;
3744
pItem->duration0 = 4;
@@ -43,8 +50,8 @@ static void setItem0(rmt_item32_t *pItem) {
4350
WS2812::WS2812(rmt_channel_t channel, gpio_num_t gpioNum, uint16_t pixelCount) {
4451
this->pixelCount = pixelCount;
4552
this->channel = channel;
46-
this->items = (rmt_item32_t *)malloc(sizeof(rmt_item32_t) * (pixelCount * 24));
47-
this->pixels = (pixel_t *)malloc(sizeof(pixel_t) * pixelCount);
53+
this->items = (rmt_item32_t *)calloc(sizeof(rmt_item32_t), pixelCount * 24);
54+
this->pixels = (pixel_t *)calloc(sizeof(pixel_t),pixelCount);
4855

4956
rmt_config_t config;
5057
config.rmt_mode = RMT_MODE_TX;
@@ -65,6 +72,14 @@ WS2812::WS2812(rmt_channel_t channel, gpio_num_t gpioNum, uint16_t pixelCount) {
6572
} // WS2812
6673

6774

75+
/**
76+
* We loop through our array of pixels. For each pixel we have to add 24
77+
* bits of output. 8 bits for red, 8 bits for green and 8 bits for blue.
78+
* Each bit of neopixel data is two levels of RMT which is one RMT item.
79+
* We determine the bit value of the neopixel and then call either
80+
* setItem1() or setItem0() which sets the corresponding 2 levels of output
81+
* on the next RMT item.
82+
*/
6883
void WS2812::show() {
6984
uint32_t i,j;
7085
rmt_item32_t *pCurrentItem = this->items;

networking/bootwifi/README.md

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,15 +31,19 @@ however, [Cesanta](https://www.cesanta.com/), the makers of Mongoose are still w
3131
port to the ESP32 which is anticipated to be available before 2017 so we should really wait for that
3232
to become available.
3333

34+
##GPIO boot override
35+
To enable the ability to specify a GPIO pin to override known station information, compile
36+
the code with `-DBOOTWIFI_OVERRIDE_GPIO=<num>` when `<num>` is a GPIO pin number. If the
37+
pin is high at startup, then it will override. The pin is configured as pull-down low so
38+
it need not be artificially held low. The default is no override pin.
39+
3440
##Future enhancements
3541
There is always room for enhancements:
3642

3743
* Improve the web page shown to the user - Right now it is pretty basic and ideally could be
3844
dramatically improved. Features to be added include
3945
- listing of available access points for selection
40-
- Responsive visuals for better reading/styling on mobile devices
4146
* Integrate SSL security.
42-
* Configuration of GPIO pin to use (if any) for GPIO over-ride
4347
* NeoPixel support for visualization of connection status:
4448
- Green - connected
4549
- Blue - being an access point

networking/bootwifi/bootwifi.c

Lines changed: 139 additions & 34 deletions
201
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,13 @@
1+
/**
2+
* Bootwifi - Boot the WiFi environment.
3+
*
4+
* Compile with -DBOOTWIFI_OVERRIDE_GPIO=<num> where <num> is a GPIO pin number
5+
* to use a GPIO override.
6+
* See the README.md for full information.
7+
*
8+
*/
9+
#include <freertos/FreeRTOS.h>
10+
#include <freertos/task.h>
111
#include <esp_log.h>
212
#include <esp_err.h>
313
#include <esp_system.h>
@@ -6,42 +16,49 @@
616
#include <esp_wifi.h>
717
#include <nvs.h>
818
#include <nvs_flash.h>
9-
#include <freertos/FreeRTOS.h>
10-
#include <freertos/task.h>
1119
#include <driver/gpio.h>
20+
#include <tcpip_adapter.h>
21+
#include <lwip/sockets.h>
1222
#include <mongoose.h>
1323
#include "bootwifi.h"
1424
#include "sdkconfig.h"
1525
#include "selectAP.h"
16-
// Key used in NVS for connection info
17-
#define KEY_CONNECTION_INFO "connectionInfo"
1826

19-
// Namespace in NVS for bootwifi
20-
#define BOOTWIFI_NAMESPACE "bootwifi"
27+
// If the structure of a record saved for a subsequent reboot changes
28+
// then consider using semver to change the version number or else
29+
// we may try and boot with the wrong data.
30+
#define KEY_VERSION "version"
31+
uint32_t g_version=0x0100;
2132

22-
#define SSID_SIZE (32)
23-
#define PASSWORD_SIZE (64)
24-
25-
#define OVERRIDE_GPIO GPIO_NUM_25
33+
#define KEY_CONNECTION_INFO "connectionInfo" // Key used in NVS for connection info
34+
#define BOOTWIFI_NAMESPACE "bootwifi" // Namespace in NVS for bootwifi
35+
#define SSID_SIZE (32) // Maximum SSID size
36+
#define PASSWORD_SIZE (64) // Maximum password size
2637

2738
typedef struct {
2839
char ssid[SSID_SIZE];
2940
char password[PASSWORD_SIZE];
41+
tcpip_adapter_ip_info_t ipInfo; // Optional static IP information
3042
} connection_info_t;
3143

32-
static char tag[] = "bootwifi";
33-
34-
static bootwifi_callback_t g_callback = NULL;
44+
static bootwifi_callback_t g_callback = NULL; // Callback function to be invoked when we have finished.
3545

3646
static int g_mongooseStarted = 0; // Has the mongoose server started?
3747
static int g_mongooseStopRequest = 0; // Request to stop the mongoose server.
3848

49+
// Forward declarations
3950
static void saveConnectionInfo(connection_info_t *pConnectionInfo);
4051
static void becomeAccessPoint();
4152
static void bootWiFi2();
4253

54+
static char tag[] = "bootwifi";
55+
56+
57+
58+
59+
4360
/**
44-
* Convert a Mongoose event type to a string.
61+
* Convert a Mongoose event type to a string. Used for debugging.
4562
*/
4663
static char *mongoose_eventToString(int ev) {
4764
static char temp[100];
@@ -134,21 +151,52 @@ static void mongoose_event_handler(struct mg_connection *nc, int ev, void *evDat
134151
} if (strcmp(uri, "/") == 0) {
135152
mg_send_head(nc, 200, sizeof(selectAP_html), "Content-Type: text/html");
136153
mg_send(nc, selectAP_html, sizeof(selectAP_html));
137-
} if(strcmp(uri, "/ssidSelected") == 0) {
154+
}
155+
// Handle /ssidSelected
156+
// This is an incoming form with properties:
157+
// * ssid - The ssid of the network to connect against.
158+
// * password - the password to use to connect.
159+
// * ip - Static IP address ... may be empty
160+
// * gw - Static GW address ... may be empty
161+
// * netmask - Static netmask ... may be empty
162+
if(strcmp(uri, "/ssidSelected") == 0) {
138163
// We have received a form page containing the details. The form body will
139164
// contain:
140165
// ssid=<value>&password=<value>
141166
ESP_LOGD(tag, "- body: %.*s", message->body.len, message->body.p);
142167
connection_info_t connectionInfo;
143-
mg_get_http_var(&message->body, "ssid",
144-
connectionInfo.ssid, SSID_SIZE);
145-
mg_get_http_var(&message->body, "password",
146-
connectionInfo.password, PASSWORD_SIZE);
168+
mg_get_http_var(&message->body, "ssid", connectionInfo.ssid, SSID_SIZE);
169+
mg_get_http_var(&message->body, "password", connectionInfo.password, PASSWORD_SIZE);
170+
171+
char ipBuf[20];
172+
if (mg_get_http_var(&message->body, "ip", ipBuf, sizeof(ipBuf)) > 0) {
173+
inet_pton(AF_INET, ipBuf, &connectionInfo.ipInfo.ip);
174+
} else {
175+
connectionInfo.ipInfo.ip.addr = 0;
176+
}
177+
178+
if (mg_get_http_var(&message->body, "gw", ipBuf, sizeof(ipBuf)) > 0) {
179+
inet_pton(AF_INET, ipBuf, &connectionInfo.ipInfo.gw);
180+
}
181+
else {
182+
connectionInfo.ipInfo.gw.addr = 0;
183+
}
184+
185+
if (mg_get_http_var(&message->body, "netmask", ipBuf, sizeof(ipBuf)) > 0) {
186+
inet_pton(AF_INET, ipBuf, &connectionInfo.ipInfo.netmask);
187+
}
188+
else {
189+
connectionInfo.ipInfo.netmask.addr = 0;
190+
}
191+
147192
ESP_LOGD(tag, "ssid: %s, password: %s", connectionInfo.ssid, connectionInfo.password);
193+
148194
mg_send_head(nc, 200, 0, "Content-Type: text/plain");
149195
saveConnectionInfo(&connectionInfo);
150196
bootWiFi2();
151-
} else {
197+
} // url is "/ssidSelected"
198+
// Else ... unknown URL
199+
else {
152200
mg_send_head(nc, 404, 0, "Content-Type: text/plain");
153
}
154202
nc->flags |= MG_F_SEND_AND_CLOSE;
@@ -189,6 +237,11 @@ static void mongooseTask(void *data) {
189237
mg_mgr_free(&mgr);
190238
g_mongooseStarted = 0;
191239

240+
// Since we HAVE ended mongoose, time to invoke the callback.
241+
if (g_callback) {
242+
g_callback(1);
243+
}
244+
192245
ESP_LOGD(tag, "<< mongooseTask");
193246
vTaskDelete(NULL);
194247
return;
@@ -218,18 +271,24 @@ static esp_err_t esp32_wifi_eventHandler(void *ctx, system_event_t *event) {
218271
switch(event->event_id) {
219272
// When we have started being an access point, then start being a web server.
220273
case SYSTEM_EVENT_AP_START: { // Handle the AP start event
221-
ESP_LOGD(tag, "AP started");
274+
tcpip_adapter_ip_info_t ip_info;
275+
tcpip_adapter_get_ip_info(TCPIP_ADAPTER_IF_AP, &ip_info);
276+
ESP_LOGD(tag, "**********************************************");
277+
ESP_LOGD(tag, "* We are now an access point and you can point")
278+
ESP_LOGD(tag, "* your browser to http://" IPSTR, IP2STR(&ip_info.ip));
279+
ESP_LOGD(tag, "**********************************************");
222280
// Start Mongoose ...
223281
if (!g_mongooseStarted)
224282
{
225283
g_mongooseStarted = 1;
226-
xTaskCreatePinnedToCore(&mongooseTask, "mongoose_task", 2048, NULL, 5, NULL, 0);
284+
xTaskCreatePinnedToCore(&mongooseTask, "bootwifi_mongoose_task", 8000, NULL, 5, NULL, 0);
227285
}
228286
break;
229287
} // SYSTEM_EVENT_AP_START
230288

231289
// If we fail to connect to an access point as a station, become an access point.
232290
case SYSTEM_EVENT_STA_DISCONNECTED: {
291+
ESP_LOGD(tag, "Station disconnected started");
233292
// We think we tried to connect as a station and failed! ... become
234293
// an access point.
235294
becomeAccessPoint();
@@ -239,14 +298,18 @@ static esp_err_t esp32_wifi_eventHandler(void *ctx, system_event_t *event) {
239298
// If we connected as a station then we are done and we can stop being a
240299
// web server.
241300
case SYSTEM_EVENT_STA_GOT_IP: {
242-
ESP_LOGD(tag, " *******************************************");
301+
ESP_LOGD(tag, "********************************************");
243302
ESP_LOGD(tag, "* We are now connected and ready to do work!")
244303
ESP_LOGD(tag, "* - Our IP address is: " IPSTR, IP2STR(&event->event_info.got_ip.ip_info.ip));
245-
ESP_LOGD(tag, " *******************************************");
304+
ESP_LOGD(tag, "********************************************");
246305
g_mongooseStopRequest = 1; // Stop mongoose (if it is running).
247-
if (g_callback) {
248-
g_callback(1);
249-
}
306+
// Invoke the callback if Mongoose has NOT been started ... otherwise
307+
// we will invoke the callback when mongoose has ended.
308+
if (!g_mongooseStarted) {
309+
if (g_callback) {
310+
g_callback(1);
311+
}
312+
} // Mongoose was NOT started
250313
break;
251314
} // SYSTEM_EVENT_STA_GOTIP
252315

@@ -265,24 +328,49 @@ static int getConnectionInfo(connection_info_t *pConnectionInfo) {
265328
nvs_handle handle;
266329
size_t size;
267330
esp_err_t err;
331+
uint32_t version;
268332
err = nvs_open(BOOTWIFI_NAMESPACE, NVS_READWRITE, &handle);
269333
if (err != 0) {
270334
ESP_LOGE(tag, "nvs_open: %x", err);
271335
return -1;
272336
}
273337

338+
// Get the version that the data was saved against.
339+
err = nvs_get_u32(handle, KEY_VERSION, &version);
340+
if (err != ESP_OK) {
341+
ESP_LOGD(tag, "No version record found (%d).", err);
342+
nvs_close(handle);
343+
return -1;
344+
}
345+
346+
// Check the versions match
347+
if ((version & 0xff00) != (g_version & 0xff00)) {
348+
ESP_LOGD(tag, "Incompatible versions ... current is %x, found is %x", version, g_version);
349+
nvs_close(handle);
350+
return -1;
351+
}
352+
274353
size = sizeof(connection_info_t);
275354
err = nvs_get_blob(handle, KEY_CONNECTION_INFO, pConnectionInfo, &size);
276-
if (err == ESP_ERR_NVS_NOT_FOUND) {
355+
if (err != ESP_OK) {
356+
ESP_LOGD(tag, "No connection record found (%d).", err);
277357
nvs_close(handle);
278358
return -1;
279359
}
280-
if (err != 0) {
360+
if (err != ESP_OK) {
281361
ESP_LOGE(tag, "nvs_open: %x", err);
282362
nvs_close(handle);
283363
return -1;
284364
}
365+
366+
// Cleanup
285367
nvs_close(handle);
368+
369+
// Do a sanity check on the SSID
370+
if (strlen(pConnectionInfo->ssid) == 0) {
371+
ESP_LOGD(tag, "NULL ssid detected");
372+
return -1;
373+
}
286374
return 0;
287375
} // getConnectionInfo
288376

@@ -295,6 +383,7 @@ static void saveConnectionInfo(connection_info_t *pConnectionInfo) {
295383
ESP_ERROR_CHECK(nvs_open(BOOTWIFI_NAMESPACE, NVS_READWRITE, &handle));
296384
ESP_ERROR_CHECK(nvs_set_blob(handle, KEY_CONNECTION_INFO, pConnectionInfo,
297385
sizeof(connection_info_t)));
386+
ESP_ERROR_CHECK(nvs_set_u32(handle, KEY_VERSION, g_version));
298387
ESP_ERROR_CHECK(nvs_commit(handle));
299388
nvs_close(handle);
300389
} // setConnectionInfo
@@ -304,7 +393,17 @@ static void saveConnectionInfo(connection_info_t *pConnectionInfo) {
304393
* Become a station connecting to an existing access point.
305394
*/
306395
static void becomeStation(connection_info_t *pConnectionInfo) {
307-
ESP_LOGD(tag, "- Connecting to access point %s ...", pConnectionInfo->ssid);
396+
ESP_LOGD(tag, "- Connecting to access point \"%s\" ...", pConnectionInfo->ssid);
397+
assert(strlen(pConnectionInfo->ssid) > 0);
398+
399+
// If we have a static IP address information, use that.
400+
if (pConnectionInfo->ipInfo.ip.addr != 0) {
401+
ESP_LOGD(tag, " - using a static IP address of " IPSTR, IP2STR(&pConnectionInfo->ipInfo.ip));
402+
tcpip_adapter_dhcpc_stop(TCPIP_ADAPTER_IF_STA);
403+
tcpip_adapter_set_ip_info(TCPIP_ADAPTER_IF_STA, &pConnectionInfo->ipInfo);
404+
} else {
405+
tcpip_adapter_dhcpc_start(TCPIP_ADAPTER_IF_STA);
406+
}
308407

309408
ESP_ERROR_CHECK( esp_wifi_set_mode(WIFI_MODE_STA));
310409
wifi_config_t sta_config;
@@ -346,14 +445,20 @@ static void becomeAccessPoint() {
346445
* indicate that we should not attempt to connect to any previously saved
347446
* access point we may know about.
348447
*/
448+
349449
static int checkOverrideGpio() {
350-
gpio_pad_select_gpio(OVERRIDE_GPIO);
351-
gpio_set_direction(OVERRIDE_GPIO, GPIO_MODE_INPUT);
352-
gpio_set_pull_mode(OVERRIDE_GPIO, GPIO_PULLDOWN_ONLY);
353-
return gpio_get_level(OVERRIDE_GPIO);
450+
#ifdef BOOTWIFI_OVERRIDE_GPIO
451+
gpio_pad_select_gpio(BOOTWIFI_OVERRIDE_GPIO);
452+
gpio_set_direction(BOOTWIFI_OVERRIDE_GPIO, GPIO_MODE_INPUT);
453+
gpio_set_pull_mode(BOOTWIFI_OVERRIDE_GPIO, GPIO_PULLDOWN_ONLY);
454+
return gpio_get_level(BOOTWIFI_OVERRIDE_GPIO);
455+
#else
456+
return 0; // If no boot override, return false
457+
#endif
354458
} // checkOverrideGpio
355459

356460

461+
357462
static void bootWiFi2() {
358463
ESP_LOGD(tag, ">> bootWiFi2");
359464
// Check for a GPIO override which occurs when a physical Pin is high

0 commit comments

Comments
 (0)
0