diff --git a/components/base_nodemcu/include/lextra.h b/components/base_nodemcu/include/lextra.h new file mode 100644 index 00000000..c76b0f90 --- /dev/null +++ b/components/base_nodemcu/include/lextra.h @@ -0,0 +1,42 @@ +/* + * Copyright 2016 Dius Computing Pty Ltd. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the + * distribution. + * - Neither the name of the copyright holders nor the names of + * its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * + * @author Johny Mattsson + */ + +#ifndef _NODEMCU_LEXTRA_H_ +#define _NODEMCU_LEXTRA_H_ + +#include "lua.h" +#include + +bool luaL_optbool (lua_State *L, int idx, bool def); + +#endif diff --git a/components/base_nodemcu/lextra.c b/components/base_nodemcu/lextra.c new file mode 100644 index 00000000..2ccb5127 --- /dev/null +++ b/components/base_nodemcu/lextra.c @@ -0,0 +1,41 @@ +/* + * Copyright 2016 Dius Computing Pty Ltd. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the + * distribution. + * - Neither the name of the copyright holders nor the names of + * its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * + * @author Johny Mattsson + */ +#include "lextra.h" + +bool luaL_optbool (lua_State *L, int idx, bool def) +{ + if (lua_isboolean (L, idx)) + return lua_toboolean (L, idx); + else + return def; +} diff --git a/components/modules/Kconfig b/components/modules/Kconfig index 859287d0..411e086a 100644 --- a/components/modules/Kconfig +++ b/components/modules/Kconfig @@ -19,6 +19,12 @@ config LUA_MODULE_ENCODER Includes the encoder module. This provides hex and base64 encoding and decoding functionality. +config LUA_MODULE_WIFI + bool "WiFi module" + default "y" + help + Includes the WiFi module (recommended). + config LUA_MODULE_BTHCI bool "BlueTooth HCI interface module" default "n" diff --git a/components/modules/component.mk b/components/modules/component.mk index f326ec1c..f816862b 100644 --- a/components/modules/component.mk +++ b/components/modules/component.mk @@ -10,4 +10,10 @@ MODULE_NAMES:=$(call uppercase,$(subst .c,,$(wildcard *.c))) FORCE_LINK:=$(foreach mod,$(MODULE_NAMES),$(if $(CONFIG_LUA_MODULE_$(mod)), -u $(mod)_module_selected1)) COMPONENT_ADD_LDFLAGS=$(FORCE_LINK) -lmodules $(if $(CONFIG_LUA_MODULE_BTHCI),-lbtdm_app) +# These are disabled by default in the IDF, so switch them back on +CFLAGS += \ + -Werror=unused-function \ + -Werror=unused-but-set-variable \ + -Werror=unused-variable \ + include $(IDF_PATH)/make/component_common.mk diff --git a/components/modules/wifi.c b/components/modules/wifi.c new file mode 100644 index 00000000..355c0660 --- /dev/null +++ b/components/modules/wifi.c @@ -0,0 +1,98 @@ +/* + * Copyright 2016 Dius Computing Pty Ltd. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the + * distribution. + * - Neither the name of the copyright holders nor the names of + * its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * + * @author Johny Mattsson + */ +#include "module.h" +#include "lauxlib.h" +#include "lextra.h" +#include "esp_wifi.h" +#include "wifi_common.h" +#include + + +static int wifi_setmode (lua_State *L) +{ + int mode = luaL_checkinteger (L, 1); + bool save = luaL_optbool (L, 2, DEFAULT_SAVE); + SET_SAVE_MODE(save); + esp_err_t err; + switch (mode) + { + case WIFI_MODE_NULL: + case WIFI_MODE_STA: + case WIFI_MODE_AP: + case WIFI_MODE_APSTA: + return ((err = esp_wifi_set_mode (mode)) == ESP_OK) ? + 0 : luaL_error (L, "failed to set mode, code %d", err); + default: + return luaL_error (L, "invalid wifi mode %d", mode); + } +} + + +static int wifi_start (lua_State *L) +{ + esp_err_t err = esp_wifi_start (); + return (err == ESP_OK) ? + 0 : luaL_error(L, "failed to start wifi, code %d", err); +} + + +static int wifi_init (lua_State *L) +{ + wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT(); + esp_err_t err = esp_wifi_init (&cfg); + return (err == ESP_OK) ? + 0 : luaL_error (L, "failed to init wifi, code %d", err); +} + + +extern const LUA_REG_TYPE wifi_sta_map[]; +extern const LUA_REG_TYPE wifi_ap_map[]; + +static const LUA_REG_TYPE wifi_map[] = +{ + { LSTRKEY( "setmode" ), LFUNCVAL( wifi_setmode ) }, + { LSTRKEY( "start" ), LFUNCVAL( wifi_start ) }, + + { LSTRKEY( "sta" ), LROVAL( wifi_sta_map ) }, + { LSTRKEY( "ap" ), LROVAL( wifi_ap_map ) }, + + + { LSTRKEY( "NULLMODE" ), LNUMVAL( WIFI_MODE_NULL ) }, + { LSTRKEY( "STATION" ), LNUMVAL( WIFI_MODE_STA ) }, + { LSTRKEY( "SOFTAP" ), LNUMVAL( WIFI_MODE_AP ) }, + { LSTRKEY( "STATIONAP" ), LNUMVAL( WIFI_MODE_APSTA ) }, + + { LNILKEY, LNILVAL } +}; + +NODEMCU_MODULE(WIFI, "wifi", wifi_map, wifi_init); diff --git a/components/modules/wifi_ap.c b/components/modules/wifi_ap.c new file mode 100644 index 00000000..7681fb98 --- /dev/null +++ b/components/modules/wifi_ap.c @@ -0,0 +1,103 @@ +/* + * Copyright 2016 Dius Computing Pty Ltd. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the + * distribution. + * - Neither the name of the copyright holders nor the names of + * its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * + * @author Johny Mattsson + */ +#include "module.h" +#include "lauxlib.h" +#include "lextra.h" +#include "wifi_common.h" +#include "esp_wifi.h" +#include + + +#define DEFAULT_AP_CHANNEL 11 +#define DEFAULT_AP_MAXCONNS 4 +#define DEFAULT_AP_BEACON 100 + +static int wifi_ap_config (lua_State *L) +{ + luaL_checkanytable (L, 1); + bool save = luaL_optbool (L, 2, DEFAULT_SAVE); + + wifi_config_t cfg; + memset (&cfg, 0, sizeof (cfg)); + + lua_getfield (L, 1, "ssid"); + size_t len; + const char *str = luaL_checklstring (L, -1, &len); + if (len > sizeof (cfg.ap.ssid)) + len = sizeof (cfg.ap.ssid); + strncpy (cfg.ap.ssid, str, len); + cfg.ap.ssid_len = len; + + lua_getfield (L, 1, "pwd"); + str = luaL_optlstring (L, -1, "", &len); + if (len > sizeof (cfg.ap.password)) + len = sizeof (cfg.ap.password); + strncpy (cfg.ap.password, str, len); + + lua_getfield (L, 1, "auth"); + int authmode = luaL_optint (L, -1, WIFI_AUTH_WPA2_PSK); + if (authmode < 0 || authmode >= WIFI_AUTH_MAX) + return luaL_error (L, "unknown auth mode %d", authmode); + cfg.ap.authmode = authmode; + + lua_getfield (L, 1, "channel"); + cfg.ap.channel = luaL_optint (L, -1, DEFAULT_AP_CHANNEL); + + lua_getfield (L, 1, "hidden"); + cfg.ap.ssid_hidden = luaL_optbool (L, -1, false); + + lua_getfield (L, 1, "max"); + cfg.ap.max_connection = luaL_optint (L, -1, DEFAULT_AP_MAXCONNS); + + lua_getfield (L, 1, "beacon"); + cfg.ap.beacon_interval = luaL_optint (L, -1, DEFAULT_AP_BEACON); + + SET_SAVE_MODE(save); + esp_err_t err = esp_wifi_set_config (WIFI_IF_AP, &cfg); + return (err == ESP_OK) ? + 0 : luaL_error (L, "failed to set wifi config, code %d", err); +} + + +const LUA_REG_TYPE wifi_ap_map[] = +{ + { LSTRKEY( "config" ), LFUNCVAL( wifi_ap_config ) }, + + { LSTRKEY( "AUTH_OPEN" ), LNUMVAL( WIFI_AUTH_OPEN ) }, + { LSTRKEY( "AUTH_WEP" ), LNUMVAL( WIFI_AUTH_WEP ) }, + { LSTRKEY( "AUTH_WPA_PSK" ), LNUMVAL( WIFI_AUTH_WPA_PSK ) }, + { LSTRKEY( "AUTH_WPA2_PSK" ), LNUMVAL( WIFI_AUTH_WPA2_PSK ) }, + { LSTRKEY( "AUTH_WPA_WPA2_PSK" ), LNUMVAL( WIFI_AUTH_WPA_WPA2_PSK ) }, + + { LNILKEY, LNILVAL } +}; diff --git a/components/modules/wifi_common.h b/components/modules/wifi_common.h new file mode 100644 index 00000000..6aac7cb3 --- /dev/null +++ b/components/modules/wifi_common.h @@ -0,0 +1,48 @@ +/* + * Copyright 2016 Dius Computing Pty Ltd. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the + * distribution. + * - Neither the name of the copyright holders nor the names of + * its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * + * @author Johny Mattsson + */ +#ifndef _NODEMCU_WIFI_H_ +#define _NODEMCU_WIFI_H_ + +// Shared sta/ap macros + +#define DEFAULT_SAVE false +#define SET_SAVE_MODE(save) \ + do { esp_err_t storage_err = \ + esp_wifi_set_storage (save ? WIFI_STORAGE_FLASH : WIFI_STORAGE_RAM); \ + if (storage_err != ESP_OK) \ + return luaL_error (L, "failed to update wifi storage, code %d", \ + storage_err); \ + } while(0) + + +#endif diff --git a/components/modules/wifi_sta.c b/components/modules/wifi_sta.c new file mode 100644 index 00000000..b278b336 --- /dev/null +++ b/components/modules/wifi_sta.c @@ -0,0 +1,113 @@ +/* + * Copyright 2016 Dius Computing Pty Ltd. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the + * distribution. + * - Neither the name of the copyright holders nor the names of + * its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * + * @author Johny Mattsson + */ +#include "module.h" +#include "lauxlib.h" +#include "lextra.h" +#include "nodemcu_esp_event.h" +#include "wifi_common.h" +#include "esp_wifi.h" +#include + + +static void do_connect (const system_event_t *evt) +{ + (void)evt; + esp_wifi_connect (); +} + + +static int wifi_sta_config (lua_State *L) +{ + luaL_checkanytable (L, 1); + bool save = luaL_optbool (L, 2, DEFAULT_SAVE); + lua_settop (L, 1); + + wifi_config_t cfg; + memset (&cfg, 0, sizeof (cfg)); + + lua_getfield (L, 1, "ssid"); + size_t len; + const char *str = luaL_checklstring (L, -1, &len); + if (len > sizeof (cfg.sta.ssid)) + len = sizeof (cfg.sta.ssid); + strncpy (cfg.sta.ssid, str, len); + + lua_getfield (L, 1, "pwd"); + str = luaL_optlstring (L, -1, "", &len); + if (len > sizeof (cfg.sta.password)) + len = sizeof (cfg.sta.password); + strncpy (cfg.sta.password, str, len); + + lua_getfield (L, 1, "bssid"); + cfg.sta.bssid_set = false; + if (lua_isstring (L, -1)) + { + const char *bssid = luaL_checklstring (L, -1, &len); + const char *fmts[] = { + "%hhx%hhx%hhx%hhx%hhx%hhx", + "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx", + "%hhx-%hhx-%hhx-%hhx-%hhx-%hhx", + "%hhx %hhx %hhx %hhx %hhx %hhx", + NULL + }; + for (unsigned i = 0; fmts[i]; ++i) + { + if (sscanf (bssid, fmts[i], + &cfg.sta.bssid[0], &cfg.sta.bssid[1], &cfg.sta.bssid[2], + &cfg.sta.bssid[3], &cfg.sta.bssid[4], &cfg.sta.bssid[5]) == 6) + { + cfg.sta.bssid_set = true; + break; + } + } + if (!cfg.sta.bssid_set) + return luaL_error (L, "invalid BSSID: %s", bssid); + } + + SET_SAVE_MODE(save); + esp_err_t err = esp_wifi_set_config (WIFI_IF_STA, &cfg); + return (err == ESP_OK) ? + 0 : luaL_error (L, "failed to set wifi config, code %d", err); +} + + +const LUA_REG_TYPE wifi_sta_map[] = { + { LSTRKEY( "config" ), LFUNCVAL( wifi_sta_config ) }, + + { LNILKEY, LNILVAL } +}; + + +// Currently no auto-connect, so do that in response to events +NODEMCU_ESP_EVENT(SYSTEM_EVENT_STA_START, do_connect); +NODEMCU_ESP_EVENT(SYSTEM_EVENT_STA_DISCONNECTED, do_connect);