From 8b50d99b38fb9e1710f43236941a71828cc178e7 Mon Sep 17 00:00:00 2001 From: tyeth <tyethgundry@googlemail.com> Date: Wed, 29 May 2024 16:06:15 +0100 Subject: [PATCH 1/9] Add reset before connect for AIRLIFT/WIFININA --- .../Wippersnapper_AIRLIFT.h | 582 +++++++++--------- .../Wippersnapper_WIFININA.h | 564 ++++++++--------- 2 files changed, 588 insertions(+), 558 deletions(-) diff --git a/src/network_interfaces/Wippersnapper_AIRLIFT.h b/src/network_interfaces/Wippersnapper_AIRLIFT.h index ce39590b9..dbd8bc2f2 100644 --- a/src/network_interfaces/Wippersnapper_AIRLIFT.h +++ b/src/network_interfaces/Wippersnapper_AIRLIFT.h @@ -1,285 +1,299 @@ -/*! - * @file Wippersnapper_AIRLIFT.h - * - * This is a driver for using the Adafruit AirLift - * ESP32 Co-Processor's network interface with Wippersnapper. - * - * The ESP32 AirLift uses SPI to communicate. Three lines (CS, ACK, RST) are - * required to communicate with the ESP32 AirLift. - * - * Adafruit invests time and resources providing this open source code, - * please support Adafruit and open-source hardware by purchasing - * products from Adafruit! - * - * Copyright (c) Brent Rubell 2020-2021 for Adafruit Industries. - * - * MIT license, all text here must be included in any redistribution. - * - */ - -#ifndef WIPPERSNAPPER_AIRLIFT_H -#define WIPPERSNAPPER_AIRLIFT_H - -#include "Adafruit_MQTT.h" -#include "Adafruit_MQTT_Client.h" -#include "Arduino.h" -#include "SPI.h" -#include "WiFiNINA.h" -#include "Wippersnapper.h" - -#define NINAFWVER \ - "1.6.0" /*!< min. nina-fw version compatible with this library. */ - -#define SPIWIFI SPI /*!< Instance of SPI interface used by an AirLift. */ - -extern Wippersnapper WS; -/****************************************************************************/ -/*! - @brief Class for using the AirLift Co-Processor network iface. -*/ -/****************************************************************************/ -class Wippersnapper_AIRLIFT : public Wippersnapper { - -public: - /**************************************************************************/ - /*! - @brief Initializes the Adafruit IO class for AirLift devices. - */ - /**************************************************************************/ - Wippersnapper_AIRLIFT() : Wippersnapper() { - _ssPin = 10; - _ackPin = 7; - _rstPin = 5; - _gpio0Pin = -1; - _wifi = &SPIWIFI; - _ssid = 0; - _pass = 0; - _mqtt_client = new WiFiSSLClient; - - // setup ESP32 co-processor pins during init. - WiFi.setPins(_ssPin, _ackPin, _rstPin, _gpio0Pin, _wifi); - } - - /**************************************************************************/ - /*! - @brief Destructor for the Adafruit IO AirLift class. - */ - /**************************************************************************/ - ~Wippersnapper_AIRLIFT() { - if (_mqtt) - delete _mqtt; - } - - /**********************************************************/ - /*! - @brief Sets the WiFi client's ssid and password. - @param ssid - Wireless network's SSID. - @param ssidPassword - Wireless network's password. - */ - /**********************************************************/ - void set_ssid_pass(const char *ssid, const char *ssidPassword) { - _ssid = ssid; - _pass = ssidPassword; - } - - /**********************************************************/ - /*! - @brief Sets the WiFi client's ssid and password from the - secrets.json provisioning file. - */ - /**********************************************************/ - void set_ssid_pass() { - _ssid = WS._config.network.ssid; - _pass = WS._config.network.pass; - } - - /***********************************************************/ - /*! - @brief Performs a scan of local WiFi networks. - @returns True if `_network_ssid` is found, False otherwise. - */ - /***********************************************************/ - bool check_valid_ssid() { - // Disconnect WiFi from an AP if it was previously connected - WiFi.disconnect(); - delay(100); - - // Perform a network scan - int n = WiFi.scanNetworks(); - if (n == 0) { - WS_DEBUG_PRINTLN("ERROR: No WiFi networks found!"); - return false; - } - - // Was the network within secrets.json found? - for (int i = 0; i < n; ++i) { - if (strcmp(_ssid, WiFi.SSID(i)) == 0) - return true; - } - - // User-set network not found, print scan results to serial console - WS_DEBUG_PRINTLN("ERROR: Your requested WiFi network was not found!"); - WS_DEBUG_PRINTLN("WipperSnapper found these WiFi networks: "); - for (int i = 0; i < n; ++i) { - WS_DEBUG_PRINT(WiFi.SSID(i)); - WS_DEBUG_PRINT(" "); - WS_DEBUG_PRINT(WiFi.RSSI(i)); - WS_DEBUG_PRINTLN("dB"); - } - - return false; - } - - /********************************************************/ - /*! - @brief Sets the WiFi client. - @param wifi - Instance of SPIClass. - */ - /********************************************************/ - void set_wifi(SPIClass *wifi) { - _wifi = wifi; - _mqtt_client = new WiFiSSLClient; - } - - /********************************************************/ - /*! - @brief Configures ESP32 "AirLift" pins. - @param ssPin - ESP32 S.S. pin. - @param ackPin - ESP32 ACK pin. - @param rstPin - ESP32 RST pin. - @param gpio0Pin - ESP32 GPIO0 pin. - */ - /********************************************************/ - void set_airlift_pins(int ssPin, int ackPin, int rstPin, int gpio0Pin) { - _ssPin = ssPin; - _ackPin = ackPin; - _rstPin = rstPin; - _gpio0Pin = gpio0Pin; - } - - /********************************************************/ - /*! - @brief Checks the version of an ESP32 module running - nina-fw. - @returns True if matches min. required to run - WipperSnapper, False otherwise. - */ - /********************************************************/ - bool firmwareCheck() { - _fv = WiFi.firmwareVersion(); - if (_fv < NINAFWVER) - return false; - return true; - } - - /********************************************************/ - /*! - @brief Gets the ESP32's unique client identifier. - @note For the ESP32, the UID is the MAC address. - */ - /********************************************************/ - void getMacAddr() { - uint8_t mac[6] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; - WiFi.macAddress(mac); - memcpy(WS._macAddr, mac, sizeof(mac)); - } - - /********************************************************/ - /*! - @brief Initializes the MQTT client. - @param clientID - MQTT client identifier - */ - /********************************************************/ - void setupMQTTClient(const char *clientID) { - WS._mqtt = new Adafruit_MQTT_Client( - _mqtt_client, WS._config.aio_url, WS._config.io_port, clientID, - WS._config.aio_user, WS._config.aio_key); - } - - /********************************************************/ - /*! - @brief Returns the network status of an ESP32 module. - @return ws_status_t - */ - /********************************************************/ - ws_status_t networkStatus() { - switch (WiFi.status()) { - case WL_CONNECTED: - return WS_NET_CONNECTED; - case WL_CONNECT_FAILED: - return WS_NET_CONNECT_FAILED; - case WL_IDLE_STATUS: - return WS_IDLE; - default: - return WS_NET_DISCONNECTED; - } - } - - /*******************************************************************/ - /*! - @brief Returns the type of network connection used by Wippersnapper - @return AIRLIFT - */ - /*******************************************************************/ - const char *connectionType() { return "AIRLIFT"; } - -protected: - const char *_ssid; /*!< Network SSID. */ - const char *_pass; /*!< Network password. */ - String _fv; /*!< nina-fw firmware version. */ - int _ssPin = -1; /*!< SPI S.S. pin. */ - int _ackPin = -1; /*!< SPI ACK pin. */ - int _rstPin = -1; /*!< SPI RST pin. */ - int _gpio0Pin = -1; /*!< SPI GPIO0 pin, unused. */ - WiFiSSLClient *_mqtt_client; /*!< Instance of a secure WiFi client. */ - SPIClass *_wifi; /*!< Instance of the SPI bus used by the AirLift. */ - - /**************************************************************************/ - /*! - @brief Establishes a connection with the wireless network. - */ - /**************************************************************************/ - void _connect() { - if (strlen(_ssid) == 0) { - _status = WS_SSID_INVALID; - } else { - - // validate co-processor is physically connected connection - if (WiFi.status() == WL_NO_MODULE) { - WS_DEBUG_PRINT("No ESP32 module detected!"); - return; - } - - // validate co-processor's firmware version - if (!firmwareCheck()) - WS_DEBUG_PRINTLN("Please upgrade the firmware on the ESP module to the " - "latest version."); - - // disconnect from possible previous connection - _disconnect(); - - WiFi.begin(_ssid, _pass); - _status = WS_NET_DISCONNECTED; - } - } - - /**************************************************************************/ - /*! - @brief Disconnects from the wireless network. - */ - /**************************************************************************/ - void _disconnect() { - WiFi.disconnect(); - delay(500); - } -}; - +/*! + * @file Wippersnapper_AIRLIFT.h + * + * This is a driver for using the Adafruit AirLift + * ESP32 Co-Processor's network interface with Wippersnapper. + * + * The ESP32 AirLift uses SPI to communicate. Three lines (CS, ACK, RST) are + * required to communicate with the ESP32 AirLift. + * + * Adafruit invests time and resources providing this open source code, + * please support Adafruit and open-source hardware by purchasing + * products from Adafruit! + * + * Copyright (c) Brent Rubell 2020-2021 for Adafruit Industries. + * + * MIT license, all text here must be included in any redistribution. + * + */ + +#ifndef WIPPERSNAPPER_AIRLIFT_H +#define WIPPERSNAPPER_AIRLIFT_H + +#include "Adafruit_MQTT.h" +#include "Adafruit_MQTT_Client.h" +#include "Arduino.h" +#include "SPI.h" +#include "WiFiNINA.h" +#include "Wippersnapper.h" + +#define NINAFWVER \ + "1.6.0" /*!< min. nina-fw version compatible with this library. */ + +#define SPIWIFI SPI /*!< Instance of SPI interface used by an AirLift. */ + +extern Wippersnapper WS; +/****************************************************************************/ +/*! + @brief Class for using the AirLift Co-Processor network iface. +*/ +/****************************************************************************/ +class Wippersnapper_AIRLIFT : public Wippersnapper { + +public: + /**************************************************************************/ + /*! + @brief Initializes the Adafruit IO class for AirLift devices. + */ + /**************************************************************************/ + Wippersnapper_AIRLIFT() : Wippersnapper() { + _ssPin = 10; + _ackPin = 7; + _rstPin = 5; + _gpio0Pin = -1; + _wifi = &SPIWIFI; + _ssid = 0; + _pass = 0; + _mqtt_client = new WiFiSSLClient; + + // setup ESP32 co-processor pins during init. + WiFi.setPins(_ssPin, _ackPin, _rstPin, _gpio0Pin, _wifi); + } + + /**************************************************************************/ + /*! + @brief Destructor for the Adafruit IO AirLift class. + */ + /**************************************************************************/ + ~Wippersnapper_AIRLIFT() { + if (_mqtt) + delete _mqtt; + } + + /**********************************************************/ + /*! + @brief Sets the WiFi client's ssid and password. + @param ssid + Wireless network's SSID. + @param ssidPassword + Wireless network's password. + */ + /**********************************************************/ + void set_ssid_pass(const char *ssid, const char *ssidPassword) { + _ssid = ssid; + _pass = ssidPassword; + } + + /**********************************************************/ + /*! + @brief Sets the WiFi client's ssid and password from the + secrets.json provisioning file. + */ + /**********************************************************/ + void set_ssid_pass() { + _ssid = WS._config.network.ssid; + _pass = WS._config.network.pass; + } + + /***********************************************************/ + /*! + @brief Performs a scan of local WiFi networks. + @returns True if `_network_ssid` is found, False otherwise. + */ + /***********************************************************/ + bool check_valid_ssid() { + // Disconnect WiFi from an AP if it was previously connected + WiFi.disconnect(); + delay(100); + + // Perform a network scan + int n = WiFi.scanNetworks(); + if (n == 0) { + WS_DEBUG_PRINTLN("ERROR: No WiFi networks found!"); + return false; + } + + // Was the network within secrets.json found? + for (int i = 0; i < n; ++i) { + if (strcmp(_ssid, WiFi.SSID(i)) == 0) + return true; + } + + // User-set network not found, print scan results to serial console + WS_DEBUG_PRINTLN("ERROR: Your requested WiFi network was not found!"); + WS_DEBUG_PRINTLN("WipperSnapper found these WiFi networks: "); + for (int i = 0; i < n; ++i) { + WS_DEBUG_PRINT(WiFi.SSID(i)); + WS_DEBUG_PRINT(" "); + WS_DEBUG_PRINT(WiFi.RSSI(i)); + WS_DEBUG_PRINTLN("dB"); + } + + return false; + } + + /********************************************************/ + /*! + @brief Sets the WiFi client. + @param wifi + Instance of SPIClass. + */ + /********************************************************/ + void set_wifi(SPIClass *wifi) { + _wifi = wifi; + _mqtt_client = new WiFiSSLClient; + } + + /********************************************************/ + /*! + @brief Configures ESP32 "AirLift" pins. + @param ssPin + ESP32 S.S. pin. + @param ackPin + ESP32 ACK pin. + @param rstPin + ESP32 RST pin. + @param gpio0Pin + ESP32 GPIO0 pin. + */ + /********************************************************/ + void set_airlift_pins(int ssPin, int ackPin, int rstPin, int gpio0Pin) { + _ssPin = ssPin; + _ackPin = ackPin; + _rstPin = rstPin; + _gpio0Pin = gpio0Pin; + } + + /********************************************************/ + /*! + @brief Checks the version of an ESP32 module running + nina-fw. + @returns True if matches min. required to run + WipperSnapper, False otherwise. + */ + /********************************************************/ + bool firmwareCheck() { + _fv = WiFi.firmwareVersion(); + if (_fv < NINAFWVER) + return false; + return true; + } + + /********************************************************/ + /*! + @brief Gets the ESP32's unique client identifier. + @note For the ESP32, the UID is the MAC address. + */ + /********************************************************/ + void getMacAddr() { + uint8_t mac[6] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + WiFi.macAddress(mac); + memcpy(WS._macAddr, mac, sizeof(mac)); + } + + /********************************************************/ + /*! + @brief Initializes the MQTT client. + @param clientID + MQTT client identifier + */ + /********************************************************/ + void setupMQTTClient(const char *clientID) { + WS._mqtt = new Adafruit_MQTT_Client( + _mqtt_client, WS._config.aio_url, WS._config.io_port, clientID, + WS._config.aio_user, WS._config.aio_key); + } + + /********************************************************/ + /*! + @brief Returns the network status of an ESP32 module. + @return ws_status_t + */ + /********************************************************/ + ws_status_t networkStatus() { + switch (WiFi.status()) { + case WL_CONNECTED: + return WS_NET_CONNECTED; + case WL_CONNECT_FAILED: + return WS_NET_CONNECT_FAILED; + case WL_IDLE_STATUS: + return WS_IDLE; + default: + return WS_NET_DISCONNECTED; + } + } + + /*******************************************************************/ + /*! + @brief Returns the type of network connection used by Wippersnapper + @return AIRLIFT + */ + /*******************************************************************/ + const char *connectionType() { return "AIRLIFT"; } + +protected: + const char *_ssid; /*!< Network SSID. */ + const char *_pass; /*!< Network password. */ + String _fv; /*!< nina-fw firmware version. */ + int _ssPin = -1; /*!< SPI S.S. pin. */ + int _ackPin = -1; /*!< SPI ACK pin. */ + int _rstPin = -1; /*!< SPI RST pin. */ + int _gpio0Pin = -1; /*!< SPI GPIO0 pin, unused. */ + WiFiSSLClient *_mqtt_client; /*!< Instance of a secure WiFi client. */ + SPIClass *_wifi; /*!< Instance of the SPI bus used by the AirLift. */ + + /**************************************************************************/ + /*! + @brief Establishes a connection with the wireless network. + */ + /**************************************************************************/ + void _connect() { + if (strlen(_ssid) == 0) { + _status = WS_SSID_INVALID; + } else { + + // validate co-processor is physically connected connection + if (WiFi.status() == WL_NO_MODULE) { + WS_DEBUG_PRINT("No ESP32 module detected!"); + return; + } + + // validate co-processor's firmware version + if (!firmwareCheck()) + WS_DEBUG_PRINTLN("Please upgrade the firmware on the ESP module to the " + "latest version."); + + // disconnect from possible previous connection + _disconnect(); + + // reset the esp32 if possible + if (_rstPin != -1) { + WS_DEBUG("Resetting ESP32..."); + pinMode(_rstPin, OUTPUT); + digitalWrite(_rstPin, LOW); + delay(10); + digitalWrite(_rstPin, HIGH); + delay(10); + } + // wait for the ESP32 to boot + delay(1000); + + WS_DEBUG_PRINT("Connecting to "); + WS_DEBUG_PRINTLN(_ssid); + WiFi.begin(_ssid, _pass); + _status = WS_NET_DISCONNECTED; + } + } + + /**************************************************************************/ + /*! + @brief Disconnects from the wireless network. + */ + /**************************************************************************/ + void _disconnect() { + WiFi.disconnect(); + delay(500); + } +}; + #endif // WIPPERSNAPPER_AIRLIFT_H \ No newline at end of file diff --git a/src/network_interfaces/Wippersnapper_WIFININA.h b/src/network_interfaces/Wippersnapper_WIFININA.h index aa56c3b40..9b618143f 100644 --- a/src/network_interfaces/Wippersnapper_WIFININA.h +++ b/src/network_interfaces/Wippersnapper_WIFININA.h @@ -1,275 +1,291 @@ -/*! - * @file Wippersnapper_WIFININA.h - * - * Network interface for the ublox wifi module on the - * Arduino MKR WiFi 1010, Arduino Nano 33 IoT and Arduino UNO WiFi Rev.2. - * - * Adafruit invests time and resources providing this open source code, - * please support Adafruit and open-source hardware by purchasing - * products from Adafruit! - * - * Copyright (c) Brent Rubell 2021 for Adafruit Industries. - * - * MIT license, all text here must be included in any redistribution. - * - */ - -#ifndef WIPPERSNAPPER_WIFININA_H -#define WIPPERSNAPPER_WIFININA_H -#include <Adafruit_MQTT.h> -#include <Adafruit_MQTT_Client.h> -#include <Arduino.h> -#include <SPI.h> -#include <WiFiNINA.h> - -#include "Wippersnapper.h" - -#define SPIWIFI \ - SPI /*!< Instance of SPI interface used by an external uBlox module. */ - -extern Wippersnapper WS; -/****************************************************************************/ -/*! - @brief Class for using the AirLift Co-Processor network iface. -*/ -/****************************************************************************/ -class Wippersnapper_WIFININA : public Wippersnapper { - -public: - /**************************************************************************/ - /*! - @brief Initializes the Adafruit IO class for ublox devices. - @param aioUsername - Adafruit IO username - @param aioKey - Adafruit IO key - @param netSSID - Wireless Network SSID - @param netPass - Wireless Network password - */ - /**************************************************************************/ - Wippersnapper_WIFININA(const char *aioUsername, const char *aioKey, - const char *netSSID, const char *netPass) - : Wippersnapper() { - _ssid = netSSID; - _pass = netPass; - _username = aioUsername; - _key = aioKey; - - _wifi = &SPIWIFI; - _mqtt_client = new WiFiSSLClient; - } - - /**************************************************************************/ - /*! - @brief Destructor for the Adafruit IO ublox class. - */ - /**************************************************************************/ - ~Wippersnapper_WIFININA() { - if (_mqtt) - delete _mqtt; - } - - /****************************************************************************/ - /*! - @brief Configures the device's Adafruit IO credentials. This method - should be used only if filesystem-backed provisioning is - not avaliable. - */ - /****************************************************************************/ - void set_user_key() { - strlcpy(WS._config.aio_user, _username, sizeof(WS._config.aio_user)); - strlcpy(WS._config.aio_key, _key, sizeof(WS._config.aio_key)); - } - - /**********************************************************/ - /*! - @brief Sets the WiFi client's ssid and password. - @param ssid - Wireless network's SSID. - @param ssidPassword - Wireless network's password. - */ - /**********************************************************/ - void set_ssid_pass(const char *ssid, const char *ssidPassword) { - strlcpy(WS._config.network.ssid, ssid, sizeof(WS._config.network.ssid)); - strlcpy(WS._config.network.pass, ssidPassword, - sizeof(WS._config.network.pass)); - } - - /**********************************************************/ - /*! - @brief Sets the WiFi client's ssid and password from the - header file's credentials. - */ - /**********************************************************/ - void set_ssid_pass() { - strlcpy(WS._config.network.ssid, _ssid, sizeof(WS._config.network.ssid)); - strlcpy(WS._config.network.pass, _pass, sizeof(WS._config.network.pass)); - } - - /***********************************************************/ - /*! - @brief Performs a scan of local WiFi networks. - @returns True if `_network_ssid` is found, False otherwise. - */ - /***********************************************************/ - bool check_valid_ssid() { - // Set WiFi to station mode and disconnect from an AP if it was previously - // connected - WiFi.disconnect(); - delay(100); - - // Perform a network scan - int n = WiFi.scanNetworks(); - if (n == 0) { - WS_DEBUG_PRINTLN("ERROR: No WiFi networks found!"); - return false; - } - - // Was the network within secrets.json found? - for (int i = 0; i < n; ++i) { - if (strcmp(_ssid, WiFi.SSID(i)) == 0) - return true; - } - - // User-set network not found, print scan results to serial console - WS_DEBUG_PRINTLN("ERROR: Your requested WiFi network was not found!"); - WS_DEBUG_PRINTLN("WipperSnapper found these WiFi networks: "); - for (int i = 0; i < n; ++i) { - WS_DEBUG_PRINT(WiFi.SSID(i)); - WS_DEBUG_PRINT(" "); - WS_DEBUG_PRINT(WiFi.RSSI(i)); - WS_DEBUG_PRINTLN("dB"); - } - - return false; - } - - /********************************************************/ - /*! - @brief Sets the WiFi client. - @param wifi - Instance of SPIClass. - */ - /********************************************************/ - void set_wifi(SPIClass *wifi) { - _wifi = wifi; - _mqtt_client = new WiFiSSLClient; - } - - /***********************************************************/ - /*! - @brief Checks the nina-fw version on the module. - @return True if firmware on the ublox module matches - the latest version of the library, False otherwise. - */ - /***********************************************************/ - bool firmwareCheck() { - String fv = WiFi.firmwareVersion(); - if (fv < WIFI_FIRMWARE_LATEST_VERSION) - return false; - return true; - } - - /********************************************************/ - /*! - @brief Gets the ESP32's unique client identifier. - @note For the ESP32, the UID is the MAC address. - */ - /********************************************************/ - void getMacAddr() { - uint8_t mac[6] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; - WiFi.macAddress(mac); - memcpy(WS._macAddr, mac, sizeof(mac)); - } - - /********************************************************/ - /*! - @brief Initializes the MQTT client. - @param clientID - MQTT client identifier - */ - /********************************************************/ - void setupMQTTClient(const char *clientID) { - WS._mqtt = new Adafruit_MQTT_Client( - _mqtt_client, WS._config.aio_url, WS._config.io_port, clientID, - WS._config.aio_user, WS._config.aio_key); - } - - /********************************************************/ - /*! - @brief Returns the network status of an ESP32 module. - @return ws_status_t - */ - /********************************************************/ - ws_status_t networkStatus() { - switch (WiFi.status()) { - case WL_CONNECTED: - return WS_NET_CONNECTED; - case WL_CONNECT_FAILED: - return WS_NET_CONNECT_FAILED; - case WL_IDLE_STATUS: - return WS_IDLE; - default: - return WS_NET_DISCONNECTED; - } - } - - /*******************************************************************/ - /*! - @brief Returns the type of network connection used by Wippersnapper - @return AIRLIFT - */ - /*******************************************************************/ - const char *connectionType() { return "AIRLIFT"; } - -protected: - const char *_ssid; /*!< Network SSID. */ - const char *_pass; /*!< Network password. */ - const char *_username; /*!< Adafruit IO username. */ - const char *_key; /*!< Adafruit IO key. */ - - WiFiSSLClient *_mqtt_client; /*!< Instance of a secure WiFi client. */ - SPIClass *_wifi; /*!< Instance of the SPI bus used by the ublox. */ - - /**************************************************************************/ - /*! - @brief Establishes a connection with the wireless network. - */ - /**************************************************************************/ - void _connect() { - - // check if co-processor connected first - if (WiFi.status() == WL_NO_MODULE) - errorWriteHang("No WiFi Module Detected!"); - - // validate the nina-fw version - if (!firmwareCheck()) - errorWriteHang("Please upgrade the firmware on the ESP module to the " - "latest version."); - - if (strlen(_ssid) == 0) { - _status = WS_SSID_INVALID; - } else { - // disconnect from possible previous connection - _disconnect(); - - WiFi.begin(_ssid, _pass); - _status = WS_NET_DISCONNECTED; - } - } - - /**************************************************************************/ - /*! - @brief Disconnects from the wireless network. - */ - /**************************************************************************/ - void _disconnect() { - WiFi.disconnect(); - delay(500); - } -}; - +/*! + * @file Wippersnapper_WIFININA.h + * + * Network interface for the ublox wifi module on the + * Arduino MKR WiFi 1010, Arduino Nano 33 IoT and Arduino UNO WiFi Rev.2. + * + * Adafruit invests time and resources providing this open source code, + * please support Adafruit and open-source hardware by purchasing + * products from Adafruit! + * + * Copyright (c) Brent Rubell 2021 for Adafruit Industries. + * + * MIT license, all text here must be included in any redistribution. + * + */ + +#ifndef WIPPERSNAPPER_WIFININA_H +#define WIPPERSNAPPER_WIFININA_H +#include <Adafruit_MQTT.h> +#include <Adafruit_MQTT_Client.h> +#include <Arduino.h> +#include <SPI.h> +#include <WiFiNINA.h> + +#include "Wippersnapper.h" + +#define SPIWIFI \ + SPI /*!< Instance of SPI interface used by an external uBlox module. */ + +extern Wippersnapper WS; +/****************************************************************************/ +/*! + @brief Class for using the AirLift Co-Processor network iface. +*/ +/****************************************************************************/ +class Wippersnapper_WIFININA : public Wippersnapper { + +public: + /**************************************************************************/ + /*! + @brief Initializes the Adafruit IO class for ublox devices. + @param aioUsername + Adafruit IO username + @param aioKey + Adafruit IO key + @param netSSID + Wireless Network SSID + @param netPass + Wireless Network password + */ + /**************************************************************************/ + Wippersnapper_WIFININA(const char *aioUsername, const char *aioKey, + const char *netSSID, const char *netPass) + : Wippersnapper() { + _ssid = netSSID; + _pass = netPass; + _username = aioUsername; + _key = aioKey; + + _wifi = &SPIWIFI; + _mqtt_client = new WiFiSSLClient; + } + + /**************************************************************************/ + /*! + @brief Destructor for the Adafruit IO ublox class. + */ + /**************************************************************************/ + ~Wippersnapper_WIFININA() { + if (_mqtt) + delete _mqtt; + } + + /****************************************************************************/ + /*! + @brief Configures the device's Adafruit IO credentials. This method + should be used only if filesystem-backed provisioning is + not avaliable. + */ + /****************************************************************************/ + void set_user_key() { + strlcpy(WS._config.aio_user, _username, sizeof(WS._config.aio_user)); + strlcpy(WS._config.aio_key, _key, sizeof(WS._config.aio_key)); + } + + /**********************************************************/ + /*! + @brief Sets the WiFi client's ssid and password. + @param ssid + Wireless network's SSID. + @param ssidPassword + Wireless network's password. + */ + /**********************************************************/ + void set_ssid_pass(const char *ssid, const char *ssidPassword) { + strlcpy(WS._config.network.ssid, ssid, sizeof(WS._config.network.ssid)); + strlcpy(WS._config.network.pass, ssidPassword, + sizeof(WS._config.network.pass)); + } + + /**********************************************************/ + /*! + @brief Sets the WiFi client's ssid and password from the + header file's credentials. + */ + /**********************************************************/ + void set_ssid_pass() { + strlcpy(WS._config.network.ssid, _ssid, sizeof(WS._config.network.ssid)); + strlcpy(WS._config.network.pass, _pass, sizeof(WS._config.network.pass)); + } + + /***********************************************************/ + /*! + @brief Performs a scan of local WiFi networks. + @returns True if `_network_ssid` is found, False otherwise. + */ + /***********************************************************/ + bool check_valid_ssid() { + // Set WiFi to station mode and disconnect from an AP if it was previously + // connected + WiFi.disconnect(); + delay(100); + + // Perform a network scan + int n = WiFi.scanNetworks(); + if (n == 0) { + WS_DEBUG_PRINTLN("ERROR: No WiFi networks found!"); + return false; + } + + // Was the network within secrets.json found? + for (int i = 0; i < n; ++i) { + if (strcmp(_ssid, WiFi.SSID(i)) == 0) + return true; + } + + // User-set network not found, print scan results to serial console + WS_DEBUG_PRINTLN("ERROR: Your requested WiFi network was not found!"); + WS_DEBUG_PRINTLN("WipperSnapper found these WiFi networks: "); + for (int i = 0; i < n; ++i) { + WS_DEBUG_PRINT(WiFi.SSID(i)); + WS_DEBUG_PRINT(" "); + WS_DEBUG_PRINT(WiFi.RSSI(i)); + WS_DEBUG_PRINTLN("dB"); + } + + return false; + } + + /********************************************************/ + /*! + @brief Sets the WiFi client. + @param wifi + Instance of SPIClass. + */ + /********************************************************/ + void set_wifi(SPIClass *wifi) { + _wifi = wifi; + _mqtt_client = new WiFiSSLClient; + } + + /***********************************************************/ + /*! + @brief Checks the nina-fw version on the module. + @return True if firmware on the ublox module matches + the latest version of the library, False otherwise. + */ + /***********************************************************/ + bool firmwareCheck() { + String fv = WiFi.firmwareVersion(); + if (fv < WIFI_FIRMWARE_LATEST_VERSION) + return false; + return true; + } + + /********************************************************/ + /*! + @brief Gets the ESP32's unique client identifier. + @note For the ESP32, the UID is the MAC address. + */ + /********************************************************/ + void getMacAddr() { + uint8_t mac[6] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + WiFi.macAddress(mac); + memcpy(WS._macAddr, mac, sizeof(mac)); + } + + /********************************************************/ + /*! + @brief Initializes the MQTT client. + @param clientID + MQTT client identifier + */ + /********************************************************/ + void setupMQTTClient(const char *clientID) { + WS._mqtt = new Adafruit_MQTT_Client( + _mqtt_client, WS._config.aio_url, WS._config.io_port, clientID, + WS._config.aio_user, WS._config.aio_key); + } + + /********************************************************/ + /*! + @brief Returns the network status of an ESP32 module. + @return ws_status_t + */ + /********************************************************/ + ws_status_t networkStatus() { + switch (WiFi.status()) { + case WL_CONNECTED: + return WS_NET_CONNECTED; + case WL_CONNECT_FAILED: + return WS_NET_CONNECT_FAILED; + case WL_IDLE_STATUS: + return WS_IDLE; + default: + return WS_NET_DISCONNECTED; + } + } + + /*******************************************************************/ + /*! + @brief Returns the type of network connection used by Wippersnapper + @return AIRLIFT + */ + /*******************************************************************/ + const char *connectionType() { return "AIRLIFT"; } + +protected: + const char *_ssid; /*!< Network SSID. */ + const char *_pass; /*!< Network password. */ + const char *_username; /*!< Adafruit IO username. */ + const char *_key; /*!< Adafruit IO key. */ + + WiFiSSLClient *_mqtt_client; /*!< Instance of a secure WiFi client. */ + SPIClass *_wifi; /*!< Instance of the SPI bus used by the ublox. */ + + /**************************************************************************/ + /*! + @brief Establishes a connection with the wireless network. + */ + /**************************************************************************/ + void _connect() { + + // check if co-processor connected first + if (WiFi.status() == WL_NO_MODULE) + errorWriteHang("No WiFi Module Detected!"); + + // validate the nina-fw version + if (!firmwareCheck()) + errorWriteHang("Please upgrade the firmware on the ESP module to the " + "latest version."); + + if (strlen(_ssid) == 0) { + _status = WS_SSID_INVALID; + } else { + // disconnect from possible previous connection + _disconnect(); + +#if defined(ESP32_RESETN) + // reset the esp32 if possible, better if we didn't do this first time + if (ESP32_RESETN != -1) { + WS_DEBUG("Resetting ESP32..."); + pinMode(ESP32_RESETN, OUTPUT); + digitalWrite(ESP32_RESETN, LOW); + delay(10); + digitalWrite(ESP32_RESETN, HIGH); + delay(10); + } + // wait for the ESP32 to boot + delay(1000); +#endif + + WS_DEBUG_PRINT("Connecting to "); + WS_DEBUG_PRINTLN(_ssid); + WiFi.begin(_ssid, _pass); + _status = WS_NET_DISCONNECTED; + } + } + + /**************************************************************************/ + /*! + @brief Disconnects from the wireless network. + */ + /**************************************************************************/ + void _disconnect() { + WiFi.disconnect(); + delay(500); + } +}; + #endif // WIPPERSNAPPER_WIFININA_H \ No newline at end of file From d624e80780742f1d182e124c1dfa8ad6e9744bff Mon Sep 17 00:00:00 2001 From: tyeth <tyethgundry@googlemail.com> Date: Wed, 29 May 2024 16:23:04 +0100 Subject: [PATCH 2/9] Correct WIFININA reset pin name inline with Arduino Nano_33_iot/MkrWifi1010 --- .../Wippersnapper_WIFININA.h | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/src/network_interfaces/Wippersnapper_WIFININA.h b/src/network_interfaces/Wippersnapper_WIFININA.h index 9b618143f..87de9087f 100644 --- a/src/network_interfaces/Wippersnapper_WIFININA.h +++ b/src/network_interfaces/Wippersnapper_WIFININA.h @@ -256,14 +256,23 @@ class Wippersnapper_WIFININA : public Wippersnapper { // disconnect from possible previous connection _disconnect(); -#if defined(ESP32_RESETN) +// no clear recommendation, all three defined for both boards, future-proofing +#if defined(NINA_RESETN) +#define NINA_RESET_PIN NINA_RESETN +#elif defined(SPIWIFI_RESET) +#define NINA_RESET_PIN SPIWIFI_RESET +#elif defined(ESP32_RESETN) +#define NINA_RESET_PIN ESP32_RESETN +#endif + +#if defined(NINA_RESET_PIN) // reset the esp32 if possible, better if we didn't do this first time - if (ESP32_RESETN != -1) { + if (NINA_RESET_PIN != -1) { WS_DEBUG("Resetting ESP32..."); - pinMode(ESP32_RESETN, OUTPUT); - digitalWrite(ESP32_RESETN, LOW); + pinMode(NINA_RESET_PIN, OUTPUT); + digitalWrite(NINA_RESET_PIN, LOW); delay(10); - digitalWrite(ESP32_RESETN, HIGH); + digitalWrite(NINA_RESET_PIN, HIGH); delay(10); } // wait for the ESP32 to boot From 3883b66feb819cde258c19424bdfc5f757d78d87 Mon Sep 17 00:00:00 2001 From: Tyeth Gundry <tyethgundry@googlemail.com> Date: Thu, 30 May 2024 18:01:59 +0100 Subject: [PATCH 3/9] WIP: use SS/GPIO0 pins for reset too --- .../Wippersnapper_AIRLIFT.h | 651 ++++++++++-------- .../Wippersnapper_WIFININA.h | 13 +- src/network_interfaces/ws_networking_pico.h | 3 + 3 files changed, 366 insertions(+), 301 deletions(-) diff --git a/src/network_interfaces/Wippersnapper_AIRLIFT.h b/src/network_interfaces/Wippersnapper_AIRLIFT.h index dbd8bc2f2..d9a4fc422 100644 --- a/src/network_interfaces/Wippersnapper_AIRLIFT.h +++ b/src/network_interfaces/Wippersnapper_AIRLIFT.h @@ -1,299 +1,354 @@ -/*! - * @file Wippersnapper_AIRLIFT.h - * - * This is a driver for using the Adafruit AirLift - * ESP32 Co-Processor's network interface with Wippersnapper. - * - * The ESP32 AirLift uses SPI to communicate. Three lines (CS, ACK, RST) are - * required to communicate with the ESP32 AirLift. - * - * Adafruit invests time and resources providing this open source code, - * please support Adafruit and open-source hardware by purchasing - * products from Adafruit! - * - * Copyright (c) Brent Rubell 2020-2021 for Adafruit Industries. - * - * MIT license, all text here must be included in any redistribution. - * - */ - -#ifndef WIPPERSNAPPER_AIRLIFT_H -#define WIPPERSNAPPER_AIRLIFT_H - -#include "Adafruit_MQTT.h" -#include "Adafruit_MQTT_Client.h" -#include "Arduino.h" -#include "SPI.h" -#include "WiFiNINA.h" -#include "Wippersnapper.h" - -#define NINAFWVER \ - "1.6.0" /*!< min. nina-fw version compatible with this library. */ - -#define SPIWIFI SPI /*!< Instance of SPI interface used by an AirLift. */ - -extern Wippersnapper WS; -/****************************************************************************/ -/*! - @brief Class for using the AirLift Co-Processor network iface. -*/ -/****************************************************************************/ -class Wippersnapper_AIRLIFT : public Wippersnapper { - -public: - /**************************************************************************/ - /*! - @brief Initializes the Adafruit IO class for AirLift devices. - */ - /**************************************************************************/ - Wippersnapper_AIRLIFT() : Wippersnapper() { - _ssPin = 10; - _ackPin = 7; - _rstPin = 5; - _gpio0Pin = -1; - _wifi = &SPIWIFI; - _ssid = 0; - _pass = 0; - _mqtt_client = new WiFiSSLClient; - - // setup ESP32 co-processor pins during init. - WiFi.setPins(_ssPin, _ackPin, _rstPin, _gpio0Pin, _wifi); - } - - /**************************************************************************/ - /*! - @brief Destructor for the Adafruit IO AirLift class. - */ - /**************************************************************************/ - ~Wippersnapper_AIRLIFT() { - if (_mqtt) - delete _mqtt; - } - - /**********************************************************/ - /*! - @brief Sets the WiFi client's ssid and password. - @param ssid - Wireless network's SSID. - @param ssidPassword - Wireless network's password. - */ - /**********************************************************/ - void set_ssid_pass(const char *ssid, const char *ssidPassword) { - _ssid = ssid; - _pass = ssidPassword; - } - - /**********************************************************/ - /*! - @brief Sets the WiFi client's ssid and password from the - secrets.json provisioning file. - */ - /**********************************************************/ - void set_ssid_pass() { - _ssid = WS._config.network.ssid; - _pass = WS._config.network.pass; - } - - /***********************************************************/ - /*! - @brief Performs a scan of local WiFi networks. - @returns True if `_network_ssid` is found, False otherwise. - */ - /***********************************************************/ - bool check_valid_ssid() { - // Disconnect WiFi from an AP if it was previously connected - WiFi.disconnect(); - delay(100); - - // Perform a network scan - int n = WiFi.scanNetworks(); - if (n == 0) { - WS_DEBUG_PRINTLN("ERROR: No WiFi networks found!"); - return false; - } - - // Was the network within secrets.json found? - for (int i = 0; i < n; ++i) { - if (strcmp(_ssid, WiFi.SSID(i)) == 0) - return true; - } - - // User-set network not found, print scan results to serial console - WS_DEBUG_PRINTLN("ERROR: Your requested WiFi network was not found!"); - WS_DEBUG_PRINTLN("WipperSnapper found these WiFi networks: "); - for (int i = 0; i < n; ++i) { - WS_DEBUG_PRINT(WiFi.SSID(i)); - WS_DEBUG_PRINT(" "); - WS_DEBUG_PRINT(WiFi.RSSI(i)); - WS_DEBUG_PRINTLN("dB"); - } - - return false; - } - - /********************************************************/ - /*! - @brief Sets the WiFi client. - @param wifi - Instance of SPIClass. - */ - /********************************************************/ - void set_wifi(SPIClass *wifi) { - _wifi = wifi; - _mqtt_client = new WiFiSSLClient; - } - - /********************************************************/ - /*! - @brief Configures ESP32 "AirLift" pins. - @param ssPin - ESP32 S.S. pin. - @param ackPin - ESP32 ACK pin. - @param rstPin - ESP32 RST pin. - @param gpio0Pin - ESP32 GPIO0 pin. - */ - /********************************************************/ - void set_airlift_pins(int ssPin, int ackPin, int rstPin, int gpio0Pin) { - _ssPin = ssPin; - _ackPin = ackPin; - _rstPin = rstPin; - _gpio0Pin = gpio0Pin; - } - - /********************************************************/ - /*! - @brief Checks the version of an ESP32 module running - nina-fw. - @returns True if matches min. required to run - WipperSnapper, False otherwise. - */ - /********************************************************/ - bool firmwareCheck() { - _fv = WiFi.firmwareVersion(); - if (_fv < NINAFWVER) - return false; - return true; - } - - /********************************************************/ - /*! - @brief Gets the ESP32's unique client identifier. - @note For the ESP32, the UID is the MAC address. - */ - /********************************************************/ - void getMacAddr() { - uint8_t mac[6] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; - WiFi.macAddress(mac); - memcpy(WS._macAddr, mac, sizeof(mac)); - } - - /********************************************************/ - /*! - @brief Initializes the MQTT client. - @param clientID - MQTT client identifier - */ - /********************************************************/ - void setupMQTTClient(const char *clientID) { - WS._mqtt = new Adafruit_MQTT_Client( - _mqtt_client, WS._config.aio_url, WS._config.io_port, clientID, - WS._config.aio_user, WS._config.aio_key); - } - - /********************************************************/ - /*! - @brief Returns the network status of an ESP32 module. - @return ws_status_t - */ - /********************************************************/ - ws_status_t networkStatus() { - switch (WiFi.status()) { - case WL_CONNECTED: - return WS_NET_CONNECTED; - case WL_CONNECT_FAILED: - return WS_NET_CONNECT_FAILED; - case WL_IDLE_STATUS: - return WS_IDLE; - default: - return WS_NET_DISCONNECTED; - } - } - - /*******************************************************************/ - /*! - @brief Returns the type of network connection used by Wippersnapper - @return AIRLIFT - */ - /*******************************************************************/ - const char *connectionType() { return "AIRLIFT"; } - -protected: - const char *_ssid; /*!< Network SSID. */ - const char *_pass; /*!< Network password. */ - String _fv; /*!< nina-fw firmware version. */ - int _ssPin = -1; /*!< SPI S.S. pin. */ - int _ackPin = -1; /*!< SPI ACK pin. */ - int _rstPin = -1; /*!< SPI RST pin. */ - int _gpio0Pin = -1; /*!< SPI GPIO0 pin, unused. */ - WiFiSSLClient *_mqtt_client; /*!< Instance of a secure WiFi client. */ - SPIClass *_wifi; /*!< Instance of the SPI bus used by the AirLift. */ - - /**************************************************************************/ - /*! - @brief Establishes a connection with the wireless network. - */ - /**************************************************************************/ - void _connect() { - if (strlen(_ssid) == 0) { - _status = WS_SSID_INVALID; - } else { - - // validate co-processor is physically connected connection - if (WiFi.status() == WL_NO_MODULE) { - WS_DEBUG_PRINT("No ESP32 module detected!"); - return; - } - - // validate co-processor's firmware version - if (!firmwareCheck()) - WS_DEBUG_PRINTLN("Please upgrade the firmware on the ESP module to the " - "latest version."); - - // disconnect from possible previous connection - _disconnect(); - - // reset the esp32 if possible - if (_rstPin != -1) { - WS_DEBUG("Resetting ESP32..."); - pinMode(_rstPin, OUTPUT); - digitalWrite(_rstPin, LOW); - delay(10); - digitalWrite(_rstPin, HIGH); - delay(10); - } - // wait for the ESP32 to boot - delay(1000); - - WS_DEBUG_PRINT("Connecting to "); - WS_DEBUG_PRINTLN(_ssid); - WiFi.begin(_ssid, _pass); - _status = WS_NET_DISCONNECTED; - } - } - - /**************************************************************************/ - /*! - @brief Disconnects from the wireless network. - */ - /**************************************************************************/ - void _disconnect() { - WiFi.disconnect(); - delay(500); - } -}; - +/*! + * @file Wippersnapper_AIRLIFT.h + * + * This is a driver for using the Adafruit AirLift + * ESP32 Co-Processor's network interface with Wippersnapper. + * + * The ESP32 AirLift uses SPI to communicate. Three lines (CS, ACK, RST) are + * required to communicate with the ESP32 AirLift. + * + * Adafruit invests time and resources providing this open source code, + * please support Adafruit and open-source hardware by purchasing + * products from Adafruit! + * + * Copyright (c) Brent Rubell 2020-2021 for Adafruit Industries. + * + * MIT license, all text here must be included in any redistribution. + * + */ + +#ifndef WIPPERSNAPPER_AIRLIFT_H +#define WIPPERSNAPPER_AIRLIFT_H + +#include "Adafruit_MQTT.h" +#include "Adafruit_MQTT_Client.h" +#include "Arduino.h" +#include "SPI.h" +#include "WiFiNINA.h" +#include "Wippersnapper.h" + +#define NINAFWVER \ + "1.7.7" /*!< min. nina-fw version compatible with this library. */ + +#define SPIWIFI SPI /*!< Instance of SPI interface used by an AirLift. */ + +extern Wippersnapper WS; +/****************************************************************************/ +/*! + @brief Class for using the AirLift Co-Processor network iface. +*/ +/****************************************************************************/ +class Wippersnapper_AIRLIFT : public Wippersnapper { + +public: + /**************************************************************************/ + /*! + @brief Initializes the Adafruit IO class for AirLift devices. + */ + /**************************************************************************/ + Wippersnapper_AIRLIFT() : Wippersnapper() { + _ssPin = SPIWIFI_SS; // 10; + _ackPin = SPIWIFI_ACK; //7; + _rstPin = SPIWIFI_RESET; // 5; // should be 7 on PyPortals + #ifdef ESP32_GPIO0 + _gpio0Pin = ESP32_GPIO0; + #else + _gpio0Pin = -1; + #endif + _wifi = &SPIWIFI; + _ssid = 0; + _pass = 0; + _mqtt_client = new WiFiSSLClient; + + // setup ESP32 co-processor pins during init. + WiFi.setPins(_ssPin, _ackPin, _rstPin, _gpio0Pin, _wifi); + delay(1000); + } + + /**************************************************************************/ + /*! + @brief Destructor for the Adafruit IO AirLift class. + */ + /**************************************************************************/ + ~Wippersnapper_AIRLIFT() { + if (_mqtt) + delete _mqtt; + } + + /**********************************************************/ + /*! + @brief Sets the WiFi client's ssid and password. + @param ssid + Wireless network's SSID. + @param ssidPassword + Wireless network's password. + */ + /**********************************************************/ + void set_ssid_pass(const char *ssid, const char *ssidPassword) { + _ssid = ssid; + _pass = ssidPassword; + } + + /**********************************************************/ + /*! + @brief Sets the WiFi client's ssid and password from the + secrets.json provisioning file. + */ + /**********************************************************/ + void set_ssid_pass() { + _ssid = WS._config.network.ssid; + _pass = WS._config.network.pass; + } + + /***********************************************************/ + /*! + @brief Performs a scan of local WiFi networks. + @returns True if `_network_ssid` is found, False otherwise. + */ + /***********************************************************/ + bool check_valid_ssid() { + // Disconnect WiFi from an AP if it was previously connected + WiFi.disconnect(); + delay(100); + + // Perform a network scan + int n = WiFi.scanNetworks(); + if (n == 0) { + WS_DEBUG_PRINTLN("ERROR: No WiFi networks found!"); + return false; + } + + // Was the network within secrets.json found? + for (int i = 0; i < n; ++i) { + if (strcmp(_ssid, WiFi.SSID(i)) == 0) + return true; + } + + // User-set network not found, print scan results to serial console + WS_DEBUG_PRINTLN("ERROR: Your requested WiFi network was not found!"); + WS_DEBUG_PRINTLN("WipperSnapper found these WiFi networks: "); + for (int i = 0; i < n; ++i) { + WS_DEBUG_PRINT(WiFi.SSID(i)); + WS_DEBUG_PRINT(" "); + WS_DEBUG_PRINT(WiFi.RSSI(i)); + WS_DEBUG_PRINTLN("dB"); + } + + return false; + } + + /********************************************************/ + /*! + @brief Sets the WiFi client. + @param wifi + Instance of SPIClass. + */ + /********************************************************/ + void set_wifi(SPIClass *wifi) { + _wifi = wifi; + _mqtt_client = new WiFiSSLClient; + } + + /********************************************************/ + /*! + @brief Configures ESP32 "AirLift" pins. + @param ssPin + ESP32 S.S. pin. + @param ackPin + ESP32 ACK pin. + @param rstPin + ESP32 RST pin. + @param gpio0Pin + ESP32 GPIO0 pin. + */ + /********************************************************/ + void set_airlift_pins(int ssPin, int ackPin, int rstPin, int gpio0Pin) { + _ssPin = ssPin; + _ackPin = ackPin; + _rstPin = rstPin; + _gpio0Pin = gpio0Pin; + } + + /********************************************************/ + /*! + @brief Checks the version of an ESP32 module running + nina-fw. + @returns True if matches min. required to run + WipperSnapper, False otherwise. + */ + /********************************************************/ + bool firmwareCheck() { + _fv = WiFi.firmwareVersion(); + return compareVersions(_fv, NINAFWVER); + } + + /********************************************************/ + /*! + @brief Compares two version strings. + @param currentVersion + Current version string. + @param requiredVersion + Required version string. + @returns True if the current version is greater than or + equal to the required version, False otherwise. + */ + /********************************************************/ + bool compareVersions(const String& currentVersion, const String& requiredVersion) { + int curMajor, curMinor, curPatch; + int reqMajor, reqMinor, reqPatch; + int per_major, per_minor, per_patch; + + sscanf(currentVersion.c_str(), "%d.%d.%d", &curMajor, &curMinor, &curPatch); + sscanf(requiredVersion.c_str(), "%d.%d.%d", &reqMajor, &reqMinor, &reqPatch); + + if (curMajor != reqMajor) return curMajor > reqMajor; + if (curMinor != reqMinor) return curMinor > reqMinor; + return curPatch >= reqPatch; + } + + /********************************************************/ + /*! + @brief Gets the ESP32's unique client identifier. + @note For the ESP32, the UID is the MAC address. + */ + /********************************************************/ + void getMacAddr() { + uint8_t mac[6] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + WiFi.macAddress(mac); + memcpy(WS._macAddr, mac, sizeof(mac)); + } + + /********************************************************/ + /*! + @brief Initializes the MQTT client. + @param clientID + MQTT client identifier + */ + /********************************************************/ + void setupMQTTClient(const char *clientID) { + WS._mqtt = new Adafruit_MQTT_Client( + _mqtt_client, WS._config.aio_url, WS._config.io_port, clientID, + WS._config.aio_user, WS._config.aio_key); + } + + /********************************************************/ + /*! + @brief Returns the network status of an ESP32 module. + @return ws_status_t + */ + /********************************************************/ + ws_status_t networkStatus() { + switch (WiFi.status()) { + case WL_CONNECTED: + return WS_NET_CONNECTED; + case WL_CONNECT_FAILED: + return WS_NET_CONNECT_FAILED; + case WL_IDLE_STATUS: + return WS_IDLE; + default: + return WS_NET_DISCONNECTED; + } + } + + /*******************************************************************/ + /*! + @brief Returns the type of network connection used by Wippersnapper + @return AIRLIFT + */ + /*******************************************************************/ + const char *connectionType() { return "AIRLIFT"; } + +protected: + const char *_ssid; /*!< Network SSID. */ + const char *_pass; /*!< Network password. */ + String _fv; /*!< nina-fw firmware version. */ + int _ssPin = -1; /*!< SPI S.S. pin. */ + int _ackPin = -1; /*!< SPI ACK pin. */ + int _rstPin = -1; /*!< SPI RST pin. */ + int _gpio0Pin = -1; /*!< SPI GPIO0 pin, unused. */ + WiFiSSLClient *_mqtt_client; /*!< Instance of a secure WiFi client. */ + SPIClass *_wifi; /*!< Instance of the SPI bus used by the AirLift. */ + + /**************************************************************************/ + /*! + @brief Establishes a connection with the wireless network. + */ + /**************************************************************************/ + void _connect() { + if (strlen(_ssid) == 0) { + _status = WS_SSID_INVALID; // possibly unneccesary as already checking elsewhere + } else { + // disconnect from possible previous connection + _disconnect(); + feedWDT(); + WS_DEBUG_PRINT("Reset Pin: "); + WS_DEBUG_PRINTLN(_rstPin); + // reset the esp32 if possible + if (_rstPin != -1) { + WS_DEBUG_PRINTLN("Resetting ESP32..."); + WS_PRINTER.flush(); + // Chip select for esp32 + pinMode(_ssPin, OUTPUT); + digitalWrite(_ssPin, HIGH); + // Do we need to set SS low again? + if (_gpio0Pin != -1) { + pinMode(_gpio0Pin, OUTPUT); + digitalWrite(_gpio0Pin, LOW); + } + pinMode(_rstPin, OUTPUT); + digitalWrite(_rstPin, LOW); + delay(50); + digitalWrite(_rstPin, HIGH); + delay(10); + if (_gpio0Pin != -1) { + pinMode(_gpio0Pin, INPUT); + } + // wait for the ESP32 to boot + delay(1000); + } + feedWDT(); + // WS_DEBUG_PRINT("ESP32 booted, version: "); + // WS_PRINTER.flush(); + // WS_DEBUG_PRINTLN(WiFi.firmwareVersion()); + // WS_PRINTER.flush(); + // feedWDT(); + + // // validate co-processor is physically connected connection + // if (WiFi.status() == WL_NO_MODULE) { + // WS_DEBUG_PRINT("No ESP32 module detected!"); + // WS_DEBUG_PRINT("Current Module Status:"); + // WS_DEBUG_PRINTLN(WiFi.status()); + // return; + // } + + // validate co-processor's firmware version + if (!firmwareCheck()) + WS_DEBUG_PRINTLN("Please upgrade the firmware on the ESP module to the " + "latest version."); + + WS_DEBUG_PRINT("Connecting to "); + WS_DEBUG_PRINTLN(_ssid); + WS_PRINTER.flush(); + feedWDT(); + WiFi.begin(_ssid, _pass); + _status = WS_NET_DISCONNECTED; + feedWDT(); + delay(5000); + feedWDT(); + delay(5000); + feedWDT(); + } + } + + /**************************************************************************/ + /*! + @brief Disconnects from the wireless network. + */ + /**************************************************************************/ + void _disconnect() { + WiFi.disconnect(); + delay(500); + } +}; + #endif // WIPPERSNAPPER_AIRLIFT_H \ No newline at end of file diff --git a/src/network_interfaces/Wippersnapper_WIFININA.h b/src/network_interfaces/Wippersnapper_WIFININA.h index 87de9087f..d7cd2eec8 100644 --- a/src/network_interfaces/Wippersnapper_WIFININA.h +++ b/src/network_interfaces/Wippersnapper_WIFININA.h @@ -268,21 +268,28 @@ class Wippersnapper_WIFININA : public Wippersnapper { #if defined(NINA_RESET_PIN) // reset the esp32 if possible, better if we didn't do this first time if (NINA_RESET_PIN != -1) { - WS_DEBUG("Resetting ESP32..."); + WS_DEBUG_PRINTLN("Resetting ESP32..."); + WS_PRINTER.flush(); pinMode(NINA_RESET_PIN, OUTPUT); digitalWrite(NINA_RESET_PIN, LOW); - delay(10); + delay(50); digitalWrite(NINA_RESET_PIN, HIGH); delay(10); } // wait for the ESP32 to boot - delay(1000); + delay(2000); + feedWDT(); #endif WS_DEBUG_PRINT("Connecting to "); WS_DEBUG_PRINTLN(_ssid); WiFi.begin(_ssid, _pass); _status = WS_NET_DISCONNECTED; + feedWDT(); + delay(5000); + feedWDT(); + delay(5000); + feedWDT(); } } diff --git a/src/network_interfaces/ws_networking_pico.h b/src/network_interfaces/ws_networking_pico.h index c2a8d556c..c9733368e 100644 --- a/src/network_interfaces/ws_networking_pico.h +++ b/src/network_interfaces/ws_networking_pico.h @@ -282,6 +282,9 @@ class ws_networking_pico : public Wippersnapper { } } _status = WS_NET_DISCONNECTED; + WS.feedWDT(); + delay(5000); + WS.feedWDT(); } } From 4f672fccb41a80d85efa37390f6e35c4bf1c15c4 Mon Sep 17 00:00:00 2001 From: tyeth <tyethgundry@googlemail.com> Date: Thu, 30 May 2024 18:16:21 +0100 Subject: [PATCH 4/9] WIP: end wifi object before restart --- src/network_interfaces/Wippersnapper_AIRLIFT.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/network_interfaces/Wippersnapper_AIRLIFT.h b/src/network_interfaces/Wippersnapper_AIRLIFT.h index d9a4fc422..458a40750 100644 --- a/src/network_interfaces/Wippersnapper_AIRLIFT.h +++ b/src/network_interfaces/Wippersnapper_AIRLIFT.h @@ -280,6 +280,7 @@ class Wippersnapper_AIRLIFT : public Wippersnapper { } else { // disconnect from possible previous connection _disconnect(); + WiFi.end(); feedWDT(); WS_DEBUG_PRINT("Reset Pin: "); WS_DEBUG_PRINTLN(_rstPin); @@ -289,8 +290,7 @@ class Wippersnapper_AIRLIFT : public Wippersnapper { WS_PRINTER.flush(); // Chip select for esp32 pinMode(_ssPin, OUTPUT); - digitalWrite(_ssPin, HIGH); - // Do we need to set SS low again? + digitalWrite(_ssPin, HIGH); // Do we need to set SS low again? if (_gpio0Pin != -1) { pinMode(_gpio0Pin, OUTPUT); digitalWrite(_gpio0Pin, LOW); @@ -304,7 +304,7 @@ class Wippersnapper_AIRLIFT : public Wippersnapper { pinMode(_gpio0Pin, INPUT); } // wait for the ESP32 to boot - delay(1000); + delay(2000); } feedWDT(); // WS_DEBUG_PRINT("ESP32 booted, version: "); From 1cb35d3cabe803e4fbeb67a8e947357d3cbc3343 Mon Sep 17 00:00:00 2001 From: tyeth <tyethgundry@googlemail.com> Date: Thu, 30 May 2024 18:50:14 +0100 Subject: [PATCH 5/9] WIP: restart SPI after wifi end/deinit --- src/network_interfaces/Wippersnapper_AIRLIFT.h | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/src/network_interfaces/Wippersnapper_AIRLIFT.h b/src/network_interfaces/Wippersnapper_AIRLIFT.h index 458a40750..8a8a2727f 100644 --- a/src/network_interfaces/Wippersnapper_AIRLIFT.h +++ b/src/network_interfaces/Wippersnapper_AIRLIFT.h @@ -280,7 +280,10 @@ class Wippersnapper_AIRLIFT : public Wippersnapper { } else { // disconnect from possible previous connection _disconnect(); + delay(100); WiFi.end(); + delay(100); + _wifi->begin(); feedWDT(); WS_DEBUG_PRINT("Reset Pin: "); WS_DEBUG_PRINTLN(_rstPin); @@ -307,11 +310,11 @@ class Wippersnapper_AIRLIFT : public Wippersnapper { delay(2000); } feedWDT(); - // WS_DEBUG_PRINT("ESP32 booted, version: "); - // WS_PRINTER.flush(); - // WS_DEBUG_PRINTLN(WiFi.firmwareVersion()); - // WS_PRINTER.flush(); - // feedWDT(); + WS_DEBUG_PRINT("ESP32 booted, version: "); + WS_PRINTER.flush(); + WS_DEBUG_PRINTLN(WiFi.firmwareVersion()); + WS_PRINTER.flush(); + feedWDT(); // // validate co-processor is physically connected connection // if (WiFi.status() == WL_NO_MODULE) { From 2d83f9c9aef84dab179c6e46f59d097e5d4ee312 Mon Sep 17 00:00:00 2001 From: tyeth <tyethgundry@googlemail.com> Date: Thu, 30 May 2024 19:29:57 +0100 Subject: [PATCH 6/9] WIP: end and begin SPIWIFI --- src/network_interfaces/Wippersnapper_AIRLIFT.h | 1 + 1 file changed, 1 insertion(+) diff --git a/src/network_interfaces/Wippersnapper_AIRLIFT.h b/src/network_interfaces/Wippersnapper_AIRLIFT.h index 8a8a2727f..45b3e2705 100644 --- a/src/network_interfaces/Wippersnapper_AIRLIFT.h +++ b/src/network_interfaces/Wippersnapper_AIRLIFT.h @@ -282,6 +282,7 @@ class Wippersnapper_AIRLIFT : public Wippersnapper { _disconnect(); delay(100); WiFi.end(); + _wifi->end(); delay(100); _wifi->begin(); feedWDT(); From b042c258077fc2ba0ae80d4a7e69e8d6a2fce8c0 Mon Sep 17 00:00:00 2001 From: tyeth <tyethgundry@googlemail.com> Date: Thu, 30 May 2024 20:51:54 +0100 Subject: [PATCH 7/9] clang format --- .../Wippersnapper_AIRLIFT.h | 39 +++++++++++-------- 1 file changed, 22 insertions(+), 17 deletions(-) diff --git a/src/network_interfaces/Wippersnapper_AIRLIFT.h b/src/network_interfaces/Wippersnapper_AIRLIFT.h index 45b3e2705..5e95eb0a8 100644 --- a/src/network_interfaces/Wippersnapper_AIRLIFT.h +++ b/src/network_interfaces/Wippersnapper_AIRLIFT.h @@ -47,14 +47,14 @@ class Wippersnapper_AIRLIFT : public Wippersnapper { */ /**************************************************************************/ Wippersnapper_AIRLIFT() : Wippersnapper() { - _ssPin = SPIWIFI_SS; // 10; - _ackPin = SPIWIFI_ACK; //7; + _ssPin = SPIWIFI_SS; // 10; + _ackPin = SPIWIFI_ACK; // 7; _rstPin = SPIWIFI_RESET; // 5; // should be 7 on PyPortals - #ifdef ESP32_GPIO0 +#ifdef ESP32_GPIO0 _gpio0Pin = ESP32_GPIO0; - #else +#else _gpio0Pin = -1; - #endif +#endif _wifi = &SPIWIFI; _ssid = 0; _pass = 0; @@ -193,17 +193,21 @@ class Wippersnapper_AIRLIFT : public Wippersnapper { equal to the required version, False otherwise. */ /********************************************************/ - bool compareVersions(const String& currentVersion, const String& requiredVersion) { - int curMajor, curMinor, curPatch; - int reqMajor, reqMinor, reqPatch; - int per_major, per_minor, per_patch; - - sscanf(currentVersion.c_str(), "%d.%d.%d", &curMajor, &curMinor, &curPatch); - sscanf(requiredVersion.c_str(), "%d.%d.%d", &reqMajor, &reqMinor, &reqPatch); - - if (curMajor != reqMajor) return curMajor > reqMajor; - if (curMinor != reqMinor) return curMinor > reqMinor; - return curPatch >= reqPatch; + bool compareVersions(const String ¤tVersion, + const String &requiredVersion) { + int curMajor, curMinor, curPatch; + int reqMajor, reqMinor, reqPatch; + int per_major, per_minor, per_patch; + + sscanf(currentVersion.c_str(), "%d.%d.%d", &curMajor, &curMinor, &curPatch); + sscanf(requiredVersion.c_str(), "%d.%d.%d", &reqMajor, &reqMinor, + &reqPatch); + + if (curMajor != reqMajor) + return curMajor > reqMajor; + if (curMinor != reqMinor) + return curMinor > reqMinor; + return curPatch >= reqPatch; } /********************************************************/ @@ -276,7 +280,8 @@ class Wippersnapper_AIRLIFT : public Wippersnapper { /**************************************************************************/ void _connect() { if (strlen(_ssid) == 0) { - _status = WS_SSID_INVALID; // possibly unneccesary as already checking elsewhere + _status = WS_SSID_INVALID; // possibly unneccesary as already checking + // elsewhere } else { // disconnect from possible previous connection _disconnect(); From a6f50ce7db733389c0104f37dca78a67ac734f9e Mon Sep 17 00:00:00 2001 From: tyeth <tyethgundry@googlemail.com> Date: Thu, 30 May 2024 23:55:35 +0100 Subject: [PATCH 8/9] Fix: runNetFSM if ping fails --- src/Wippersnapper.cpp | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/Wippersnapper.cpp b/src/Wippersnapper.cpp index d702b9158..fa67eb152 100644 --- a/src/Wippersnapper.cpp +++ b/src/Wippersnapper.cpp @@ -2527,9 +2527,15 @@ void Wippersnapper::pingBroker() { // ping within keepalive-10% to keep connection open if (millis() > (_prv_ping + (WS_KEEPALIVE_INTERVAL_MS - (WS_KEEPALIVE_INTERVAL_MS * 0.10)))) { - WS_DEBUG_PRINTLN("PING!"); + WS_DEBUG_PRINT("PING!"); // TODO: Add back, is crashing currently - WS._mqtt->ping(); + if (WS._mqtt->ping()) { + WS_DEBUG_PRINTLN("SUCCESS!"); + } else { + WS_DEBUG_PRINTLN("FAILURE! Running network FSM..."); + WS._mqtt->disconnect(); + runNetFSM(); + } _prv_ping = millis(); } // blink status LED every STATUS_LED_KAT_BLINK_TIME millis From d2cb47d52f391bb18c926adbd9e86bd5d435076a Mon Sep 17 00:00:00 2001 From: tyeth <tyethgundry@googlemail.com> Date: Fri, 14 Jun 2024 09:19:08 +0100 Subject: [PATCH 9/9] Relabel PING to MQTT PING --- src/Wippersnapper.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Wippersnapper.cpp b/src/Wippersnapper.cpp index fa67eb152..45331083f 100644 --- a/src/Wippersnapper.cpp +++ b/src/Wippersnapper.cpp @@ -2527,7 +2527,7 @@ void Wippersnapper::pingBroker() { // ping within keepalive-10% to keep connection open if (millis() > (_prv_ping + (WS_KEEPALIVE_INTERVAL_MS - (WS_KEEPALIVE_INTERVAL_MS * 0.10)))) { - WS_DEBUG_PRINT("PING!"); + WS_DEBUG_PRINT("MQTT PING: "); // TODO: Add back, is crashing currently if (WS._mqtt->ping()) { WS_DEBUG_PRINTLN("SUCCESS!");