mirror of
https://github.com/esp8266/Arduino.git
synced 2025-08-07 00:04:36 +03:00
Merge branch 'master' into wifi_mesh_update_2.2
This commit is contained in:
@@ -13,8 +13,8 @@
|
||||
#include <ESP8266HTTPClient.h>
|
||||
|
||||
#include <WiFiClientSecureBearSSL.h>
|
||||
// Fingerprint for demo URL, expires on June 2, 2019, needs to be updated well before this date
|
||||
const uint8_t fingerprint[20] = {0x5A, 0xCF, 0xFE, 0xF0, 0xF1, 0xA6, 0xF4, 0x5F, 0xD2, 0x11, 0x11, 0xC6, 0x1D, 0x2F, 0x0E, 0xBC, 0x39, 0x8D, 0x50, 0xE0};
|
||||
// Fingerprint for demo URL, expires on June 2, 2021, needs to be updated well before this date
|
||||
const uint8_t fingerprint[20] = {0x40, 0xaf, 0x00, 0x6b, 0xec, 0x90, 0x22, 0x41, 0x8e, 0xa3, 0xad, 0xfa, 0x1a, 0xe8, 0x25, 0x41, 0x1d, 0x1a, 0x54, 0xb3};
|
||||
|
||||
ESP8266WiFiMulti WiFiMulti;
|
||||
|
||||
|
@@ -225,6 +225,11 @@ bool HTTPClient::begin(String url, String httpsFingerprint)
|
||||
return false;
|
||||
}
|
||||
_transportTraits = TransportTraitsPtr(new TLSTraits(httpsFingerprint));
|
||||
if(!_transportTraits) {
|
||||
DEBUG_HTTPCLIENT("[HTTP-Client][begin] could not create transport traits\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
DEBUG_HTTPCLIENT("[HTTP-Client][begin] httpsFingerprint: %s\n", httpsFingerprint.c_str());
|
||||
return true;
|
||||
}
|
||||
@@ -242,6 +247,11 @@ bool HTTPClient::begin(String url, const uint8_t httpsFingerprint[20])
|
||||
return false;
|
||||
}
|
||||
_transportTraits = TransportTraitsPtr(new BearSSLTraits(httpsFingerprint));
|
||||
if(!_transportTraits) {
|
||||
DEBUG_HTTPCLIENT("[HTTP-Client][begin] could not create transport traits\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
DEBUG_HTTPCLIENT("[HTTP-Client][begin] BearSSL-httpsFingerprint:");
|
||||
for (size_t i=0; i < 20; i++) {
|
||||
DEBUG_HTTPCLIENT(" %02x", httpsFingerprint[i]);
|
||||
@@ -409,7 +419,7 @@ bool HTTPClient::begin(String host, uint16_t port, String uri, const uint8_t htt
|
||||
*/
|
||||
void HTTPClient::end(void)
|
||||
{
|
||||
disconnect();
|
||||
disconnect(false);
|
||||
clear();
|
||||
_redirectCount = 0;
|
||||
}
|
||||
@@ -563,6 +573,7 @@ void HTTPClient::setRedirectLimit(uint16_t limit)
|
||||
void HTTPClient::useHTTP10(bool useHTTP10)
|
||||
{
|
||||
_useHTTP10 = useHTTP10;
|
||||
_reuse = !useHTTP10;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -980,7 +991,7 @@ int HTTPClient::writeToStream(Stream * stream)
|
||||
return returnError(HTTPC_ERROR_ENCODING);
|
||||
}
|
||||
|
||||
disconnect();
|
||||
disconnect(true);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -996,7 +1007,7 @@ const String& HTTPClient::getString(void)
|
||||
|
||||
_payload.reset(new StreamString());
|
||||
|
||||
if(_size) {
|
||||
if(_size > 0) {
|
||||
// try to reserve needed memmory
|
||||
if(!_payload->reserve((_size + 1))) {
|
||||
DEBUG_HTTPCLIENT("[HTTP-Client][getString] not enough memory to reserve a string! need: %d\n", (_size + 1));
|
||||
@@ -1139,7 +1150,11 @@ bool HTTPClient::hasHeader(const char* name)
|
||||
bool HTTPClient::connect(void)
|
||||
{
|
||||
if(connected()) {
|
||||
DEBUG_HTTPCLIENT("[HTTP-Client] connect. already connected, try reuse!\n");
|
||||
if(_reuse) {
|
||||
DEBUG_HTTPCLIENT("[HTTP-Client] connect: already connected, reusing connection\n");
|
||||
} else {
|
||||
DEBUG_HTTPCLIENT("[HTTP-Client] connect: already connected, try reuse!\n");
|
||||
}
|
||||
while(_client->available() > 0) {
|
||||
_client->read();
|
||||
}
|
||||
@@ -1149,6 +1164,10 @@ bool HTTPClient::connect(void)
|
||||
#if HTTPCLIENT_1_1_COMPATIBLE
|
||||
if(!_client && _transportTraits) {
|
||||
_tcpDeprecated = _transportTraits->create();
|
||||
if(!_tcpDeprecated) {
|
||||
DEBUG_HTTPCLIENT("[HTTP-Client] connect: could not create tcp\n");
|
||||
return false;
|
||||
}
|
||||
_client = _tcpDeprecated.get();
|
||||
}
|
||||
#endif
|
||||
@@ -1246,9 +1265,12 @@ int HTTPClient::handleHeaderResponse()
|
||||
return HTTPC_ERROR_NOT_CONNECTED;
|
||||
}
|
||||
|
||||
clear();
|
||||
|
||||
_canReuse = _reuse;
|
||||
|
||||
String transferEncoding;
|
||||
_returnCode = -1;
|
||||
_size = -1;
|
||||
|
||||
_transferEncoding = HTTPC_TE_IDENTITY;
|
||||
unsigned long lastDataTime = millis();
|
||||
|
||||
@@ -1263,6 +1285,9 @@ int HTTPClient::handleHeaderResponse()
|
||||
DEBUG_HTTPCLIENT("[HTTP-Client][handleHeaderResponse] RX: '%s'\n", headerLine.c_str());
|
||||
|
||||
if(headerLine.startsWith("HTTP/1.")) {
|
||||
if(_canReuse) {
|
||||
_canReuse = (headerLine[sizeof "HTTP/1." - 1] != '0');
|
||||
}
|
||||
_returnCode = headerLine.substring(9, headerLine.indexOf(' ', 9)).toInt();
|
||||
} else if(headerLine.indexOf(':')) {
|
||||
String headerName = headerLine.substring(0, headerLine.indexOf(':'));
|
||||
@@ -1273,8 +1298,10 @@ int HTTPClient::handleHeaderResponse()
|
||||
_size = headerValue.toInt();
|
||||
}
|
||||
|
||||
if(headerName.equalsIgnoreCase("Connection")) {
|
||||
_canReuse = headerValue.equalsIgnoreCase("keep-alive");
|
||||
if(_canReuse && headerName.equalsIgnoreCase("Connection")) {
|
||||
if(headerValue.indexOf("close") >= 0 && headerValue.indexOf("keep-alive") < 0) {
|
||||
_canReuse = false;
|
||||
}
|
||||
}
|
||||
|
||||
if(headerName.equalsIgnoreCase("Transfer-Encoding")) {
|
||||
@@ -1429,10 +1456,10 @@ int HTTPClient::writeToStreamDataBlock(Stream * stream, int size)
|
||||
|
||||
free(buff);
|
||||
|
||||
DEBUG_HTTPCLIENT("[HTTP-Client][writeToStreamDataBlock] connection closed or file end (written: %d).\n", bytesWritten);
|
||||
DEBUG_HTTPCLIENT("[HTTP-Client][writeToStreamDataBlock] end of chunk or data (transferred: %d).\n", bytesWritten);
|
||||
|
||||
if((size > 0) && (size != bytesWritten)) {
|
||||
DEBUG_HTTPCLIENT("[HTTP-Client][writeToStreamDataBlock] bytesWritten %d and size %d mismatch!.\n", bytesWritten, size);
|
||||
DEBUG_HTTPCLIENT("[HTTP-Client][writeToStreamDataBlock] transferred size %d and request size %d mismatch!.\n", bytesWritten, size);
|
||||
return HTTPC_ERROR_STREAM_WRITE;
|
||||
}
|
||||
|
||||
|
@@ -235,7 +235,7 @@ protected:
|
||||
/// request handling
|
||||
String _host;
|
||||
uint16_t _port = 0;
|
||||
bool _reuse = false;
|
||||
bool _reuse = true;
|
||||
uint16_t _tcpTimeout = HTTPCLIENT_DEFAULT_TCP_TIMEOUT;
|
||||
bool _useHTTP10 = false;
|
||||
|
||||
|
@@ -42,6 +42,7 @@ hostHeader KEYWORD2
|
||||
#######################################
|
||||
|
||||
HTTP_GET LITERAL1
|
||||
HTTP_HEAD LITERAL1
|
||||
HTTP_POST LITERAL1
|
||||
HTTP_ANY LITERAL1
|
||||
CONTENT_LENGTH_UNKNOWN LITERAL1
|
||||
|
@@ -480,6 +480,7 @@ void ESP8266WebServerTemplate<ServerType>::send(int code, const String& content_
|
||||
|
||||
template <typename ServerType>
|
||||
void ESP8266WebServerTemplate<ServerType>::sendContent(const String& content) {
|
||||
if (_currentMethod == HTTP_HEAD) return;
|
||||
const char * footer = "\r\n";
|
||||
size_t len = content.length();
|
||||
if(_chunked) {
|
||||
@@ -728,6 +729,7 @@ const String ESP8266WebServerTemplate<ServerType>::responseCodeToString(const in
|
||||
case 415: return F("Unsupported Media Type");
|
||||
case 416: return F("Requested range not satisfiable");
|
||||
case 417: return F("Expectation Failed");
|
||||
case 418: return F("I'm a teapot");
|
||||
case 500: return F("Internal Server Error");
|
||||
case 501: return F("Not Implemented");
|
||||
case 502: return F("Bad Gateway");
|
||||
|
@@ -30,7 +30,7 @@
|
||||
#include <FS.h>
|
||||
#include "detail/mimetable.h"
|
||||
|
||||
enum HTTPMethod { HTTP_ANY, HTTP_GET, HTTP_POST, HTTP_PUT, HTTP_PATCH, HTTP_DELETE, HTTP_OPTIONS };
|
||||
enum HTTPMethod { HTTP_ANY, HTTP_GET, HTTP_HEAD, HTTP_POST, HTTP_PUT, HTTP_PATCH, HTTP_DELETE, HTTP_OPTIONS };
|
||||
enum HTTPUploadStatus { UPLOAD_FILE_START, UPLOAD_FILE_WRITE, UPLOAD_FILE_END,
|
||||
UPLOAD_FILE_ABORTED };
|
||||
enum HTTPClientStatus { HC_NONE, HC_WAIT_READ, HC_WAIT_CLOSE };
|
||||
@@ -194,10 +194,10 @@ protected:
|
||||
std::unique_ptr<HTTPUpload> _currentUpload;
|
||||
int _postArgsLen;
|
||||
RequestArgument* _postArgs;
|
||||
|
||||
|
||||
int _headerKeysCount;
|
||||
RequestArgument* _currentHeaders;
|
||||
|
||||
|
||||
size_t _contentLength;
|
||||
String _responseHeaders;
|
||||
|
||||
|
@@ -99,7 +99,9 @@ bool ESP8266WebServerTemplate<ServerType>::_parseRequest(ClientType& client) {
|
||||
_chunked = false;
|
||||
|
||||
HTTPMethod method = HTTP_GET;
|
||||
if (methodStr == F("POST")) {
|
||||
if (methodStr == F("HEAD")) {
|
||||
method = HTTP_HEAD;
|
||||
} else if (methodStr == F("POST")) {
|
||||
method = HTTP_POST;
|
||||
} else if (methodStr == F("DELETE")) {
|
||||
method = HTTP_DELETE;
|
||||
|
@@ -1,4 +1,4 @@
|
||||
#!/usr/bin/python
|
||||
#!/usr/bin/python3
|
||||
|
||||
# This script pulls the list of Mozilla trusted certificate authorities
|
||||
# from the web at the "mozurl" below, parses the file to grab the PEM
|
||||
@@ -7,16 +7,18 @@
|
||||
# and use them for your outgoing SSL connections.
|
||||
#
|
||||
# Script by Earle F. Philhower, III. Released to the public domain.
|
||||
|
||||
from __future__ import print_function
|
||||
import csv
|
||||
import os
|
||||
import sys
|
||||
from subprocess import Popen, PIPE, call
|
||||
import urllib2
|
||||
try:
|
||||
# for Python 2.x
|
||||
from urllib.request import urlopen
|
||||
except:
|
||||
from urllib2 import urlopen
|
||||
try:
|
||||
from StringIO import StringIO
|
||||
except ImportError:
|
||||
# for Python 3.x
|
||||
except:
|
||||
from io import StringIO
|
||||
|
||||
# Mozilla's URL for the CSV file with included PEM certs
|
||||
@@ -25,9 +27,12 @@ mozurl = "https://ccadb-public.secure.force.com/mozilla/IncludedCACertificateRep
|
||||
# Load the manes[] and pems[] array from the URL
|
||||
names = []
|
||||
pems = []
|
||||
response = urllib2.urlopen(mozurl)
|
||||
response = urlopen(mozurl)
|
||||
csvData = response.read()
|
||||
csvReader = csv.reader(StringIO(csvData))
|
||||
if sys.version_info[0] > 2:
|
||||
csvData = csvData.decode('utf-8')
|
||||
csvFile = StringIO(csvData)
|
||||
csvReader = csv.reader(csvFile)
|
||||
for row in csvReader:
|
||||
names.append(row[0]+":"+row[1]+":"+row[2])
|
||||
pems.append(row[30])
|
||||
@@ -46,10 +51,10 @@ idx = 0
|
||||
for i in range(0, len(pems)):
|
||||
certName = "data/ca_%03d.der" % (idx);
|
||||
thisPem = pems[i].replace("'", "")
|
||||
print names[i] + " -> " + certName
|
||||
print(names[i] + " -> " + certName)
|
||||
ssl = Popen(['openssl','x509','-inform','PEM','-outform','DER','-out', certName], shell = False, stdin = PIPE)
|
||||
pipe = ssl.stdin
|
||||
pipe.write(thisPem)
|
||||
pipe.write(thisPem.encode('utf-8'))
|
||||
pipe.close()
|
||||
ssl.wait()
|
||||
if os.path.exists(certName):
|
||||
|
@@ -0,0 +1,97 @@
|
||||
|
||||
// NAPT example released to public domain
|
||||
|
||||
#if LWIP_FEATURES && !LWIP_IPV6
|
||||
|
||||
#define HAVE_NETDUMP 0
|
||||
|
||||
#ifndef STASSID
|
||||
#define STASSID "mynetwork"
|
||||
#define STAPSK "mynetworkpassword"
|
||||
#endif
|
||||
|
||||
#include <ESP8266WiFi.h>
|
||||
#include <lwip/napt.h>
|
||||
#include <lwip/dns.h>
|
||||
#include <dhcpserver.h>
|
||||
|
||||
#define NAPT 1000
|
||||
#define NAPT_PORT 10
|
||||
|
||||
#if HAVE_NETDUMP
|
||||
|
||||
#include <NetDump.h>
|
||||
|
||||
void dump(int netif_idx, const char* data, size_t len, int out, int success) {
|
||||
(void)success;
|
||||
Serial.print(out ? F("out ") : F(" in "));
|
||||
Serial.printf("%d ", netif_idx);
|
||||
|
||||
// optional filter example: if (netDump_is_ARP(data))
|
||||
{
|
||||
netDump(Serial, data, len);
|
||||
//netDumpHex(Serial, data, len);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
void setup() {
|
||||
Serial.begin(115200);
|
||||
Serial.printf("\n\nNAPT Range extender\n");
|
||||
Serial.printf("Heap on start: %d\n", ESP.getFreeHeap());
|
||||
|
||||
#if HAVE_NETDUMP
|
||||
phy_capture = dump;
|
||||
#endif
|
||||
|
||||
// first, connect to STA so we can get a proper local DNS server
|
||||
WiFi.mode(WIFI_STA);
|
||||
WiFi.begin(STASSID, STAPSK);
|
||||
while (WiFi.status() != WL_CONNECTED) {
|
||||
Serial.print('.');
|
||||
delay(500);
|
||||
}
|
||||
Serial.printf("\nSTA: %s (dns: %s / %s)\n",
|
||||
WiFi.localIP().toString().c_str(),
|
||||
WiFi.dnsIP(0).toString().c_str(),
|
||||
WiFi.dnsIP(1).toString().c_str());
|
||||
|
||||
// give DNS servers to AP side
|
||||
dhcps_set_dns(0, WiFi.dnsIP(0));
|
||||
dhcps_set_dns(1, WiFi.dnsIP(1));
|
||||
|
||||
WiFi.softAPConfig( // enable AP, with android-compatible google domain
|
||||
IPAddress(172, 217, 28, 254),
|
||||
IPAddress(172, 217, 28, 254),
|
||||
IPAddress(255, 255, 255, 0));
|
||||
WiFi.softAP(STASSID "extender", STAPSK);
|
||||
Serial.printf("AP: %s\n", WiFi.softAPIP().toString().c_str());
|
||||
|
||||
Serial.printf("Heap before: %d\n", ESP.getFreeHeap());
|
||||
err_t ret = ip_napt_init(NAPT, NAPT_PORT);
|
||||
Serial.printf("ip_napt_init(%d,%d): ret=%d (OK=%d)\n", NAPT, NAPT_PORT, (int)ret, (int)ERR_OK);
|
||||
if (ret == ERR_OK) {
|
||||
ret = ip_napt_enable_no(SOFTAP_IF, 1);
|
||||
Serial.printf("ip_napt_enable_no(SOFTAP_IF): ret=%d (OK=%d)\n", (int)ret, (int)ERR_OK);
|
||||
if (ret == ERR_OK) {
|
||||
Serial.printf("WiFi Network '%s' with same password is now NATed behind '%s'\n", STASSID "extender", STASSID);
|
||||
}
|
||||
}
|
||||
Serial.printf("Heap after napt init: %d\n", ESP.getFreeHeap());
|
||||
if (ret != ERR_OK) {
|
||||
Serial.printf("NAPT initialization failed\n");
|
||||
}
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
void setup() {
|
||||
Serial.begin(115200);
|
||||
Serial.printf("\n\nNAPT not supported in this configuration\n");
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
void loop() {
|
||||
}
|
||||
|
@@ -20,6 +20,7 @@
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include "BearSSLHelpers.h"
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
#include <bearssl/bearssl.h>
|
||||
@@ -28,7 +29,10 @@
|
||||
#include <string.h>
|
||||
#include <Arduino.h>
|
||||
#include <StackThunk.h>
|
||||
#include "BearSSLHelpers.h"
|
||||
#include <Updater_Signing.h>
|
||||
#ifndef ARDUINO_SIGNING
|
||||
#define ARDUINO_SIGNING 0
|
||||
#endif
|
||||
|
||||
namespace brssl {
|
||||
// Code here is pulled from brssl sources, with the copyright and license
|
||||
@@ -901,3 +905,17 @@ make_stack_thunk(br_ssl_engine_sendrec_buf);
|
||||
#endif
|
||||
|
||||
};
|
||||
|
||||
#if ARDUINO_SIGNING
|
||||
namespace {
|
||||
static BearSSL::PublicKey signingPubKey(signing_pubkey);
|
||||
static BearSSL::HashSHA256 __signingHash;
|
||||
static BearSSL::SigningVerifier __signingVerifier(&signingPubKey);
|
||||
};
|
||||
|
||||
namespace esp8266 {
|
||||
UpdaterHashClass& updaterSigningHash = __signingHash;
|
||||
UpdaterVerifyClass& updaterSigningVerifier = __signingVerifier;
|
||||
};
|
||||
#endif
|
||||
|
||||
|
@@ -26,7 +26,6 @@
|
||||
#include <bearssl/bearssl.h>
|
||||
#include <Updater.h>
|
||||
|
||||
|
||||
// Internal opaque structures, not needed by user applications
|
||||
namespace brssl {
|
||||
class public_key;
|
||||
|
@@ -24,6 +24,7 @@
|
||||
|
||||
#include <list>
|
||||
#include <string.h>
|
||||
#include <coredecls.h>
|
||||
#include "ESP8266WiFi.h"
|
||||
#include "ESP8266WiFiGeneric.h"
|
||||
|
||||
@@ -38,12 +39,19 @@ extern "C" {
|
||||
#include "lwip/opt.h"
|
||||
#include "lwip/err.h"
|
||||
#include "lwip/dns.h"
|
||||
#include "lwip/dhcp.h"
|
||||
#include "lwip/init.h" // LWIP_VERSION_
|
||||
#if LWIP_VERSION_MAJOR == 1
|
||||
#include "lwip/sntp.h"
|
||||
#else
|
||||
#include "lwip/apps/sntp.h"
|
||||
#endif
|
||||
}
|
||||
|
||||
#include "WiFiClient.h"
|
||||
#include "WiFiUdp.h"
|
||||
#include "debug.h"
|
||||
#include "include/WiFiState.h"
|
||||
|
||||
extern "C" void esp_schedule();
|
||||
extern "C" void esp_yield();
|
||||
@@ -200,15 +208,15 @@ WiFiEventHandler ESP8266WiFiGenericClass::onSoftAPModeProbeRequestReceived(std::
|
||||
return handler;
|
||||
}
|
||||
|
||||
// WiFiEventHandler ESP8266WiFiGenericClass::onWiFiModeChange(std::function<void(const WiFiEventModeChange&)> f)
|
||||
// {
|
||||
// WiFiEventHandler handler = std::make_shared<WiFiEventHandlerOpaque>(WIFI_EVENT_MODE_CHANGE, [f](System_Event_t* e){
|
||||
// WiFiEventModeChange& dst = *reinterpret_cast<WiFiEventModeChange*>(&e->event_info);
|
||||
// f(dst);
|
||||
// });
|
||||
// sCbEventList.push_back(handler);
|
||||
// return handler;
|
||||
// }
|
||||
WiFiEventHandler ESP8266WiFiGenericClass::onWiFiModeChange(std::function<void(const WiFiEventModeChange&)> f)
|
||||
{
|
||||
WiFiEventHandler handler = std::make_shared<WiFiEventHandlerOpaque>(WIFI_EVENT_MODE_CHANGE, [f](System_Event_t* e){
|
||||
WiFiEventModeChange& dst = *reinterpret_cast<WiFiEventModeChange*>(&e->event_info);
|
||||
f(dst);
|
||||
});
|
||||
sCbEventList.push_back(handler);
|
||||
return handler;
|
||||
}
|
||||
|
||||
/**
|
||||
* callback for WiFi events
|
||||
@@ -386,7 +394,29 @@ bool ESP8266WiFiGenericClass::getPersistent(){
|
||||
* set new mode
|
||||
* @param m WiFiMode_t
|
||||
*/
|
||||
bool ESP8266WiFiGenericClass::mode(WiFiMode_t m) {
|
||||
bool ESP8266WiFiGenericClass::mode(WiFiMode_t m, WiFiState* state) {
|
||||
if (m == WIFI_SHUTDOWN) {
|
||||
return shutdown(0, state);
|
||||
}
|
||||
else if (m == WIFI_RESUME) {
|
||||
return resumeFromShutdown(state);
|
||||
}
|
||||
else if (m & ~(WIFI_STA | WIFI_AP))
|
||||
// any other bits than legacy disallowed
|
||||
return false;
|
||||
|
||||
// m is now WIFI_STA, WIFI_AP or WIFI_AP_STA
|
||||
if (state)
|
||||
{
|
||||
DEBUG_WIFI("core: state is useless without SHUTDOWN or RESUME\n");
|
||||
}
|
||||
|
||||
if (wifi_fpm_get_sleep_type() != NONE_SLEEP_T) {
|
||||
// wifi may have been put asleep by ESP8266WiFiGenericClass::preinitWiFiOff
|
||||
wifi_fpm_do_wakeup();
|
||||
wifi_fpm_close();
|
||||
}
|
||||
|
||||
if(_persistent){
|
||||
if(wifi_get_opmode() == (uint8) m && wifi_get_opmode_default() == (uint8) m){
|
||||
return true;
|
||||
@@ -396,12 +426,6 @@ bool ESP8266WiFiGenericClass::mode(WiFiMode_t m) {
|
||||
}
|
||||
|
||||
bool ret = false;
|
||||
|
||||
if (m != WIFI_STA && m != WIFI_AP_STA)
|
||||
// calls lwIP's dhcp_stop(),
|
||||
// safe to call even if not started
|
||||
wifi_station_dhcpc_stop();
|
||||
|
||||
ETS_UART_INTR_DISABLE();
|
||||
if(_persistent) {
|
||||
ret = wifi_set_opmode(m);
|
||||
@@ -431,15 +455,13 @@ bool ESP8266WiFiGenericClass::enableSTA(bool enable) {
|
||||
WiFiMode_t currentMode = getMode();
|
||||
bool isEnabled = ((currentMode & WIFI_STA) != 0);
|
||||
|
||||
if(isEnabled != enable) {
|
||||
if(enable) {
|
||||
return mode((WiFiMode_t)(currentMode | WIFI_STA));
|
||||
} else {
|
||||
return mode((WiFiMode_t)(currentMode & (~WIFI_STA)));
|
||||
}
|
||||
} else {
|
||||
if (isEnabled == enable)
|
||||
return true;
|
||||
}
|
||||
|
||||
if (enable)
|
||||
return mode((WiFiMode_t)(currentMode | WIFI_STA));
|
||||
|
||||
return mode((WiFiMode_t)(currentMode & (~WIFI_STA)));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -472,16 +494,29 @@ bool ESP8266WiFiGenericClass::enableAP(bool enable){
|
||||
bool ESP8266WiFiGenericClass::forceSleepBegin(uint32 sleepUs) {
|
||||
_forceSleepLastMode = getMode();
|
||||
if(!mode(WIFI_OFF)) {
|
||||
DEBUG_WIFI("core: error with mode(WIFI_OFF)\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
if(sleepUs == 0) {
|
||||
if(sleepUs == 0 || sleepUs > 0xFFFFFFF) {
|
||||
sleepUs = 0xFFFFFFF;
|
||||
}
|
||||
|
||||
wifi_fpm_set_sleep_type(MODEM_SLEEP_T);
|
||||
delay(0);
|
||||
wifi_fpm_open();
|
||||
return (wifi_fpm_do_sleep(sleepUs) == 0);
|
||||
delay(0);
|
||||
auto ret = wifi_fpm_do_sleep(sleepUs);
|
||||
if (ret != 0)
|
||||
{
|
||||
DEBUG_WIFI("core: error %d with wifi_fpm_do_sleep: (-1=sleep status error, -2=force sleep not enabled)\n", ret);
|
||||
return false;
|
||||
}
|
||||
// fpm_is_open() is always 1 here, with or without delay
|
||||
// wifi_fpm_set_wakeup_cb(cb): callback is never called
|
||||
// no power reduction without this delay
|
||||
delay(10);
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -489,8 +524,10 @@ bool ESP8266WiFiGenericClass::forceSleepBegin(uint32 sleepUs) {
|
||||
* @return ok
|
||||
*/
|
||||
bool ESP8266WiFiGenericClass::forceSleepWake() {
|
||||
wifi_fpm_do_wakeup();
|
||||
wifi_fpm_close();
|
||||
if (wifi_fpm_get_sleep_type() != NONE_SLEEP_T) {
|
||||
wifi_fpm_do_wakeup();
|
||||
wifi_fpm_close();
|
||||
}
|
||||
|
||||
// restore last mode
|
||||
if(mode(_forceSleepLastMode)) {
|
||||
@@ -600,7 +637,142 @@ void wifi_dns_found_callback(const char *name, CONST ip_addr_t *ipaddr, void *ca
|
||||
esp_schedule(); // resume the hostByName function
|
||||
}
|
||||
|
||||
//meant to be called from user-defined preinit()
|
||||
uint32_t ESP8266WiFiGenericClass::shutdownCRC (const WiFiState* state)
|
||||
{
|
||||
return state? crc32(&state->state, sizeof(state->state)): 0;
|
||||
}
|
||||
|
||||
bool ESP8266WiFiGenericClass::shutdownValidCRC (const WiFiState* state)
|
||||
{
|
||||
return state && (crc32(&state->state, sizeof(state->state)) == state->crc);
|
||||
}
|
||||
|
||||
bool ESP8266WiFiGenericClass::shutdown (uint32 sleepUs, WiFiState* state)
|
||||
{
|
||||
bool persistent = _persistent;
|
||||
WiFiMode_t before_off_mode = getMode();
|
||||
|
||||
if ((before_off_mode & WIFI_STA) && state)
|
||||
{
|
||||
bool ret = wifi_get_ip_info(STATION_IF, &state->state.ip);
|
||||
if (!ret)
|
||||
{
|
||||
DEBUG_WIFI("core: error with wifi_get_ip_info(STATION_IF)\n");
|
||||
return false;
|
||||
}
|
||||
memset(state->state.fwconfig.bssid, 0xff, 6);
|
||||
ret = wifi_station_get_config(&state->state.fwconfig);
|
||||
if (!ret)
|
||||
{
|
||||
DEBUG_WIFI("core: error with wifi_station_get_config\n");
|
||||
return false;
|
||||
}
|
||||
state->state.channel = wifi_get_channel();
|
||||
}
|
||||
|
||||
// disable persistence in FW so in case of power failure
|
||||
// it doesn't wake up in off mode.
|
||||
// persistence state will be restored on WiFi resume.
|
||||
WiFi.persistent(false);
|
||||
if (!WiFi.forceSleepBegin(sleepUs))
|
||||
{
|
||||
// WIFI_OFF mode set by forceSleepBegin()
|
||||
DEBUG_WIFI("core: error with forceSleepBegin()\n");
|
||||
WiFi.mode(before_off_mode);
|
||||
WiFi.persistent(persistent);
|
||||
return false;
|
||||
}
|
||||
|
||||
// WiFi is now in force-sleep mode
|
||||
|
||||
if (state)
|
||||
{
|
||||
// finish filling state and process crc
|
||||
|
||||
state->state.persistent = persistent;
|
||||
state->state.mode = before_off_mode;
|
||||
uint8_t i = 0;
|
||||
for (auto& ntp: state->state.ntp)
|
||||
{
|
||||
#if LWIP_VERSION_MAJOR == 1
|
||||
ntp = sntp_getserver(i++);
|
||||
#else
|
||||
ntp = *sntp_getserver(i++);
|
||||
#endif
|
||||
}
|
||||
i = 0;
|
||||
for (auto& dns: state->state.dns)
|
||||
dns = WiFi.dnsIP(i++);
|
||||
state->crc = shutdownCRC(state);
|
||||
DEBUG_WIFI("core: state is saved\n");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ESP8266WiFiGenericClass::resumeFromShutdown (WiFiState* state)
|
||||
{
|
||||
if (wifi_fpm_get_sleep_type() != NONE_SLEEP_T) {
|
||||
wifi_fpm_do_wakeup();
|
||||
wifi_fpm_close();
|
||||
}
|
||||
|
||||
if (!state || shutdownCRC(state) != state->crc)
|
||||
{
|
||||
DEBUG_WIFI("core: resume: no state or bad crc\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
persistent(state->state.persistent);
|
||||
|
||||
if (!mode(state->state.mode))
|
||||
{
|
||||
DEBUG_WIFI("core: resume: can't set wifi mode to %d\n", state->state.mode);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (state->state.mode & WIFI_STA)
|
||||
{
|
||||
IPAddress local(state->state.ip.ip);
|
||||
if (local)
|
||||
{
|
||||
DEBUG_WIFI("core: resume: static address '%s'\n", local.toString().c_str());
|
||||
WiFi.config(state->state.ip.ip, state->state.ip.gw, state->state.ip.netmask, state->state.dns[0], state->state.dns[1]);
|
||||
uint8_t i = 0;
|
||||
for (CONST auto& ntp: state->state.ntp)
|
||||
{
|
||||
IPAddress ip(ntp);
|
||||
if (ip.isSet())
|
||||
{
|
||||
DEBUG_WIFI("core: resume: start SNTP, server='%s'\n", ip.toString().c_str());
|
||||
sntp_setserver(i++, &ntp);
|
||||
}
|
||||
}
|
||||
}
|
||||
// state->state.fwconfig.bssid is not real bssid (it's what user may have provided when bssid_set==1)
|
||||
if (WiFi.begin((const char*)state->state.fwconfig.ssid,
|
||||
(const char*)state->state.fwconfig.password,
|
||||
state->state.channel,
|
||||
nullptr/*(const uint8_t*)state->state.fwconfig.bssid*/, // <- try with gw's mac address?
|
||||
true) == WL_CONNECT_FAILED)
|
||||
{
|
||||
DEBUG_WIFI("core: resume: WiFi.begin failed\n");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (state->state.mode & WIFI_AP)
|
||||
{
|
||||
DEBUG_WIFI("core: resume AP mode TODO\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
// success, invalidate saved state
|
||||
state->crc++;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//meant to be called from user-defined ::preinit()
|
||||
void ESP8266WiFiGenericClass::preinitWiFiOff () {
|
||||
// https://github.com/esp8266/Arduino/issues/2111#issuecomment-224251391
|
||||
// WiFi.persistent(false);
|
||||
|
@@ -42,6 +42,8 @@ typedef std::shared_ptr<WiFiEventHandlerOpaque> WiFiEventHandler;
|
||||
|
||||
typedef void (*WiFiEventCb)(WiFiEvent_t);
|
||||
|
||||
struct WiFiState;
|
||||
|
||||
class ESP8266WiFiGenericClass {
|
||||
// ----------------------------------------------------------------------------------------------
|
||||
// -------------------------------------- Generic WiFi function ---------------------------------
|
||||
@@ -62,7 +64,7 @@ class ESP8266WiFiGenericClass {
|
||||
WiFiEventHandler onSoftAPModeStationConnected(std::function<void(const WiFiEventSoftAPModeStationConnected&)>);
|
||||
WiFiEventHandler onSoftAPModeStationDisconnected(std::function<void(const WiFiEventSoftAPModeStationDisconnected&)>);
|
||||
WiFiEventHandler onSoftAPModeProbeRequestReceived(std::function<void(const WiFiEventSoftAPModeProbeRequestReceived&)>);
|
||||
// WiFiEventHandler onWiFiModeChange(std::function<void(const WiFiEventModeChange&)>);
|
||||
WiFiEventHandler onWiFiModeChange(std::function<void(const WiFiEventModeChange&)>);
|
||||
|
||||
int32_t channel(void);
|
||||
|
||||
@@ -79,7 +81,7 @@ class ESP8266WiFiGenericClass {
|
||||
|
||||
void persistent(bool persistent);
|
||||
|
||||
bool mode(WiFiMode_t);
|
||||
bool mode(WiFiMode_t, WiFiState* state = nullptr);
|
||||
WiFiMode_t getMode();
|
||||
|
||||
bool enableSTA(bool enable);
|
||||
@@ -88,6 +90,8 @@ class ESP8266WiFiGenericClass {
|
||||
bool forceSleepBegin(uint32 sleepUs = 0);
|
||||
bool forceSleepWake();
|
||||
|
||||
static uint32_t shutdownCRC (const WiFiState* state);
|
||||
static bool shutdownValidCRC (const WiFiState* state);
|
||||
static void preinitWiFiOff (); //meant to be called in user-defined preinit()
|
||||
|
||||
protected:
|
||||
@@ -96,17 +100,22 @@ class ESP8266WiFiGenericClass {
|
||||
|
||||
static void _eventCallback(void *event);
|
||||
|
||||
// called by WiFi.mode(SHUTDOWN/RESTORE, state)
|
||||
// - sleepUs is WiFi.forceSleepBegin() parameter, 0 = forever
|
||||
// - saveState is the user's state to hold configuration on restore
|
||||
bool shutdown (uint32 sleepUs = 0, WiFiState* stateSave = nullptr);
|
||||
bool resumeFromShutdown (WiFiState* savedState = nullptr);
|
||||
|
||||
// ----------------------------------------------------------------------------------------------
|
||||
// ------------------------------------ Generic Network function --------------------------------
|
||||
// ----------------------------------------------------------------------------------------------
|
||||
|
||||
public:
|
||||
|
||||
int hostByName(const char* aHostname, IPAddress& aResult);
|
||||
int hostByName(const char* aHostname, IPAddress& aResult, uint32_t timeout_ms);
|
||||
bool getPersistent();
|
||||
protected:
|
||||
|
||||
protected:
|
||||
friend class ESP8266WiFiSTAClass;
|
||||
friend class ESP8266WiFiScanClass;
|
||||
friend class ESP8266WiFiAPClass;
|
||||
|
@@ -369,18 +369,24 @@ bool ESP8266WiFiSTAClass::reconnect() {
|
||||
* @return one value of wl_status_t enum
|
||||
*/
|
||||
bool ESP8266WiFiSTAClass::disconnect(bool wifioff) {
|
||||
bool ret;
|
||||
bool ret = false;
|
||||
struct station_config conf;
|
||||
*conf.ssid = 0;
|
||||
*conf.password = 0;
|
||||
|
||||
// API Reference: wifi_station_disconnect() need to be called after system initializes and the ESP8266 Station mode is enabled.
|
||||
if (WiFi.getMode() & WIFI_STA)
|
||||
ret = wifi_station_disconnect();
|
||||
else
|
||||
ret = true;
|
||||
|
||||
ETS_UART_INTR_DISABLE();
|
||||
if(WiFi._persistent) {
|
||||
wifi_station_set_config(&conf);
|
||||
} else {
|
||||
wifi_station_set_config_current(&conf);
|
||||
}
|
||||
ret = wifi_station_disconnect();
|
||||
|
||||
ETS_UART_INTR_ENABLE();
|
||||
|
||||
if(wifioff) {
|
||||
|
@@ -34,7 +34,8 @@
|
||||
|
||||
typedef enum WiFiMode
|
||||
{
|
||||
WIFI_OFF = 0, WIFI_STA = 1, WIFI_AP = 2, WIFI_AP_STA = 3
|
||||
WIFI_OFF = 0, WIFI_STA = 1, WIFI_AP = 2, WIFI_AP_STA = 3,
|
||||
/* these two pseudo modes are experimental: */ WIFI_SHUTDOWN = 4, WIFI_RESUME = 8
|
||||
} WiFiMode_t;
|
||||
|
||||
typedef enum WiFiPhyMode
|
||||
@@ -58,9 +59,10 @@ typedef enum WiFiEvent
|
||||
WIFI_EVENT_SOFTAPMODE_STACONNECTED,
|
||||
WIFI_EVENT_SOFTAPMODE_STADISCONNECTED,
|
||||
WIFI_EVENT_SOFTAPMODE_PROBEREQRECVED,
|
||||
WIFI_EVENT_MODE_CHANGE,
|
||||
WIFI_EVENT_SOFTAPMODE_DISTRIBUTE_STA_IP,
|
||||
WIFI_EVENT_MAX,
|
||||
WIFI_EVENT_ANY = WIFI_EVENT_MAX,
|
||||
WIFI_EVENT_MODE_CHANGE
|
||||
} WiFiEvent_t;
|
||||
|
||||
enum WiFiDisconnectReason
|
||||
|
@@ -32,6 +32,7 @@ extern "C" {
|
||||
}
|
||||
#include "debug.h"
|
||||
#include "ESP8266WiFi.h"
|
||||
#include "PolledTimeout.h"
|
||||
#include "WiFiClient.h"
|
||||
#include "WiFiClientSecureBearSSL.h"
|
||||
#include "StackThunk.h"
|
||||
@@ -437,12 +438,17 @@ int WiFiClientSecure::_run_until(unsigned target, bool blocking) {
|
||||
DEBUG_BSSL("_run_until: Not connected\n");
|
||||
return -1;
|
||||
}
|
||||
for (int no_work = 0; blocking || no_work < 2;) {
|
||||
if (blocking) {
|
||||
// Only for blocking operations can we afford to yield()
|
||||
optimistic_yield(100);
|
||||
|
||||
esp8266::polledTimeout::oneShotMs loopTimeout(_timeout);
|
||||
|
||||
for (int no_work = 0; blocking || no_work < 2;) {
|
||||
optimistic_yield(100);
|
||||
|
||||
if (loopTimeout) {
|
||||
DEBUG_BSSL("_run_until: Timeout\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
int state;
|
||||
state = br_ssl_engine_current_state(_eng);
|
||||
if (state & BR_SSL_CLOSED) {
|
||||
@@ -461,8 +467,19 @@ int WiFiClientSecure::_run_until(unsigned target, bool blocking) {
|
||||
unsigned char *buf;
|
||||
size_t len;
|
||||
int wlen;
|
||||
size_t availForWrite;
|
||||
|
||||
buf = br_ssl_engine_sendrec_buf(_eng, &len);
|
||||
availForWrite = WiFiClient::availableForWrite();
|
||||
|
||||
if (!blocking && len > availForWrite) {
|
||||
/*
|
||||
writes on WiFiClient will block if len > availableForWrite()
|
||||
this is needed to prevent available() calls from blocking
|
||||
on dropped connections
|
||||
*/
|
||||
len = availForWrite;
|
||||
}
|
||||
wlen = WiFiClient::write(buf, len);
|
||||
if (wlen <= 0) {
|
||||
/*
|
||||
|
@@ -193,6 +193,9 @@ class WiFiClientSecure : public WiFiClient {
|
||||
// AxTLS API deprecated section end
|
||||
/////////////////////////////////////
|
||||
|
||||
protected:
|
||||
bool _connectSSL(const char *hostName); // Do initial SSL handshake
|
||||
|
||||
private:
|
||||
void _clear();
|
||||
void _clearAuthenticationSettings();
|
||||
@@ -243,7 +246,6 @@ class WiFiClientSecure : public WiFiClient {
|
||||
size_t _recvapp_len;
|
||||
|
||||
bool _clientConnected(); // Is the underlying socket alive?
|
||||
bool _connectSSL(const char *hostName); // Do initial SSL handshake
|
||||
void _freeSSL();
|
||||
int _run_until(unsigned target, bool blocking = true);
|
||||
size_t _write(const uint8_t *buf, size_t size, bool pmem);
|
||||
|
@@ -128,14 +128,14 @@ public:
|
||||
if (err != ERR_OK) {
|
||||
return 0;
|
||||
}
|
||||
_connect_pending = 1;
|
||||
_connect_pending = true;
|
||||
_op_start_time = millis();
|
||||
// Following delay will be interrupted by connect callback
|
||||
for (decltype(_timeout_ms) i = 0; _connect_pending && i < _timeout_ms; i++) {
|
||||
// Give scheduled functions a chance to run (e.g. Ethernet uses recurrent)
|
||||
delay(1);
|
||||
}
|
||||
_connect_pending = 0;
|
||||
}
|
||||
_connect_pending = false;
|
||||
if (!_pcb) {
|
||||
DEBUGV(":cabrt\r\n");
|
||||
return 0;
|
||||
@@ -433,7 +433,9 @@ protected:
|
||||
void _notify_error()
|
||||
{
|
||||
if (_connect_pending || _send_waiting) {
|
||||
esp_schedule();
|
||||
_send_waiting = false;
|
||||
_connect_pending = false;
|
||||
esp_schedule(); // break current delay()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -464,8 +466,8 @@ protected:
|
||||
// Give scheduled functions a chance to run (e.g. Ethernet uses recurrent)
|
||||
delay(1);
|
||||
}
|
||||
_send_waiting = false;
|
||||
} while(true);
|
||||
_send_waiting = false;
|
||||
|
||||
if (_sync)
|
||||
wait_until_sent();
|
||||
@@ -534,7 +536,7 @@ protected:
|
||||
{
|
||||
if (_send_waiting) {
|
||||
_send_waiting = false;
|
||||
esp_schedule();
|
||||
esp_schedule(); // break current delay()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -608,9 +610,10 @@ protected:
|
||||
(void) err;
|
||||
(void) pcb;
|
||||
assert(pcb == _pcb);
|
||||
assert(_connect_pending);
|
||||
_connect_pending = 0;
|
||||
esp_schedule();
|
||||
if (_connect_pending) {
|
||||
_connect_pending = false;
|
||||
esp_schedule(); // break current delay()
|
||||
}
|
||||
return ERR_OK;
|
||||
}
|
||||
|
||||
@@ -659,7 +662,7 @@ private:
|
||||
uint32_t _timeout_ms = 5000;
|
||||
uint32_t _op_start_time = 0;
|
||||
bool _send_waiting = false;
|
||||
uint8_t _connect_pending = 0;
|
||||
bool _connect_pending = false;
|
||||
|
||||
int8_t _refcnt;
|
||||
ClientContext* _next;
|
||||
|
23
libraries/ESP8266WiFi/src/include/WiFiState.h
Normal file
23
libraries/ESP8266WiFi/src/include/WiFiState.h
Normal file
@@ -0,0 +1,23 @@
|
||||
|
||||
#ifndef WIFISTATE_H_
|
||||
#define WIFISTATE_H_
|
||||
|
||||
#include <user_interface.h>
|
||||
#include <ESP8266WiFiType.h>
|
||||
|
||||
struct WiFiState
|
||||
{
|
||||
uint32_t crc;
|
||||
struct
|
||||
{
|
||||
station_config fwconfig;
|
||||
ip_info ip;
|
||||
ip_addr_t dns[2];
|
||||
ip_addr_t ntp[2];
|
||||
WiFiMode_t mode;
|
||||
uint8_t channel;
|
||||
bool persistent;
|
||||
} state;
|
||||
};
|
||||
|
||||
#endif // WIFISTATE_H_
|
@@ -23,6 +23,7 @@
|
||||
*/
|
||||
|
||||
#include <Schedule.h>
|
||||
#include <AddrList.h>
|
||||
|
||||
#include "LEAmDNS_Priv.h"
|
||||
|
||||
@@ -59,11 +60,11 @@ MDNSResponder::MDNSResponder(void)
|
||||
m_pServiceQueries(0),
|
||||
m_fnServiceTxtCallback(0),
|
||||
#ifdef ENABLE_ESP_MDNS_RESPONDER_PASSIV_MODE
|
||||
m_bPassivModeEnabled(true) {
|
||||
m_bPassivModeEnabled(true),
|
||||
#else
|
||||
m_bPassivModeEnabled(false) {
|
||||
m_bPassivModeEnabled(false),
|
||||
#endif
|
||||
|
||||
m_netif(nullptr) {
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -95,20 +96,74 @@ bool MDNSResponder::begin(const char* p_pcHostname, const IPAddress& p_IPAddress
|
||||
if (0 == m_pUDPContext) {
|
||||
if (_setHostname(p_pcHostname)) {
|
||||
|
||||
m_IPAddress = p_IPAddress;
|
||||
//// select interface
|
||||
|
||||
m_GotIPHandler = WiFi.onStationModeGotIP([this](const WiFiEventStationModeGotIP& pEvent) {
|
||||
(void) pEvent;
|
||||
// Ensure that _restart() runs in USER context
|
||||
schedule_function([this]() { MDNSResponder::_restart(); });
|
||||
});
|
||||
m_netif = nullptr;
|
||||
IPAddress ipAddress = p_IPAddress;
|
||||
|
||||
m_DisconnectedHandler = WiFi.onStationModeDisconnected([this](const WiFiEventStationModeDisconnected& pEvent) {
|
||||
(void) pEvent;
|
||||
// Ensure that _restart() runs in USER context
|
||||
schedule_function([this]() { MDNSResponder::_restart(); });
|
||||
if (!ipAddress.isSet()) {
|
||||
|
||||
IPAddress sta = WiFi.localIP();
|
||||
IPAddress ap = WiFi.softAPIP();
|
||||
|
||||
if (!sta.isSet() && !ap.isSet()) {
|
||||
|
||||
DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] internal interfaces (STA, AP) are not set (none was specified)\n")));
|
||||
return false;
|
||||
}
|
||||
|
||||
if (ap.isSet()) {
|
||||
|
||||
if (sta.isSet())
|
||||
DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] default interface AP selected over STA (none was specified)\n")));
|
||||
else
|
||||
DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] default interface AP selected\n")));
|
||||
ipAddress = ap;
|
||||
|
||||
} else {
|
||||
|
||||
DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] default interface STA selected (none was specified)\n")));
|
||||
ipAddress = sta;
|
||||
|
||||
}
|
||||
|
||||
// continue to ensure interface is UP
|
||||
}
|
||||
|
||||
// check existence of this IP address in the interface list
|
||||
bool found = false;
|
||||
m_netif = nullptr;
|
||||
for (auto a: addrList)
|
||||
if (ipAddress == a.addr()) {
|
||||
if (a.ifUp()) {
|
||||
found = true;
|
||||
m_netif = a.interface();
|
||||
break;
|
||||
}
|
||||
DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] found interface for IP '%s' but it is not UP\n"), ipAddress.toString().c_str()););
|
||||
}
|
||||
if (!found) {
|
||||
DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] interface defined by IP '%s' not found\n"), ipAddress.toString().c_str()););
|
||||
return false;
|
||||
}
|
||||
|
||||
//// done selecting the interface
|
||||
|
||||
if (m_netif->num == STATION_IF) {
|
||||
|
||||
m_GotIPHandler = WiFi.onStationModeGotIP([this](const WiFiEventStationModeGotIP& pEvent) {
|
||||
(void) pEvent;
|
||||
// Ensure that _restart() runs in USER context
|
||||
schedule_function([this]() { MDNSResponder::_restart(); });
|
||||
});
|
||||
|
||||
m_DisconnectedHandler = WiFi.onStationModeDisconnected([this](const WiFiEventStationModeDisconnected& pEvent) {
|
||||
(void) pEvent;
|
||||
// Ensure that _restart() runs in USER context
|
||||
schedule_function([this]() { MDNSResponder::_restart(); });
|
||||
});
|
||||
}
|
||||
|
||||
bResult = _restart();
|
||||
}
|
||||
DEBUG_EX_ERR(if (!bResult) { DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] begin: FAILED for '%s'!\n"), (p_pcHostname ?: "-")); } );
|
||||
@@ -642,7 +697,7 @@ uint32_t MDNSResponder::queryService(const char* p_pcService,
|
||||
}
|
||||
}
|
||||
else {
|
||||
DEBUG_EX_ERR(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] queryService: INVALID input data!\n"), p_pcService, p_pcProtocol););
|
||||
DEBUG_EX_ERR(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] queryService: INVALID input data!\n")););
|
||||
}
|
||||
return u32Result;
|
||||
}
|
||||
|
@@ -1148,7 +1148,7 @@ protected:
|
||||
MDNSDynamicServiceTxtCallbackFunc m_fnServiceTxtCallback;
|
||||
bool m_bPassivModeEnabled;
|
||||
stcProbeInformation m_HostProbeInformation;
|
||||
IPAddress m_IPAddress;
|
||||
CONST netif* m_netif; // network interface to run on
|
||||
|
||||
/** CONTROL **/
|
||||
/* MAINTENANCE */
|
||||
@@ -1203,7 +1203,7 @@ protected:
|
||||
uint16_t p_u16QueryType,
|
||||
stcMDNSServiceQuery::stcAnswer* p_pKnownAnswers = 0);
|
||||
|
||||
const IPAddress& _getResponseMulticastInterface() const { return m_IPAddress; }
|
||||
const IPAddress _getResponseMulticastInterface() const { return IPAddress(m_netif->ip_addr); }
|
||||
|
||||
uint8_t _replyMaskForHost(const stcMDNS_RRHeader& p_RRHeader,
|
||||
bool* p_pbFullNameMatch = 0) const;
|
||||
|
@@ -22,7 +22,6 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#include <arch/cc.h>
|
||||
#include <sys/time.h>
|
||||
#include <IPAddress.h>
|
||||
#include <AddrList.h>
|
||||
@@ -79,10 +78,10 @@ bool MDNSResponder::_process(bool p_bUserContext) {
|
||||
}
|
||||
}
|
||||
else {
|
||||
bResult = ((WiFi.isConnected() || // Either station is connected
|
||||
WiFi.softAPgetStationNum()>0) && // Or AP has stations connected
|
||||
(_updateProbeStatus()) && // Probing
|
||||
(_checkServiceQueryCache())); // Service query cache check
|
||||
bResult = (m_netif != nullptr) &&
|
||||
(m_netif->flags & NETIF_FLAG_UP) && // network interface is up and running
|
||||
_updateProbeStatus() && // Probing
|
||||
_checkServiceQueryCache(); // Service query cache check
|
||||
}
|
||||
return bResult;
|
||||
}
|
||||
@@ -92,53 +91,10 @@ bool MDNSResponder::_process(bool p_bUserContext) {
|
||||
*/
|
||||
bool MDNSResponder::_restart(void) {
|
||||
|
||||
// check m_IPAddress
|
||||
if (!m_IPAddress.isSet()) {
|
||||
|
||||
IPAddress sta = WiFi.localIP();
|
||||
IPAddress ap = WiFi.softAPIP();
|
||||
|
||||
if (!sta.isSet() && !ap.isSet()) {
|
||||
|
||||
DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] internal interfaces (STA, AP) are not set (none was specified)\n")));
|
||||
return false;
|
||||
}
|
||||
|
||||
if (sta.isSet()) {
|
||||
|
||||
if (ap.isSet())
|
||||
DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] default interface STA selected over AP (none was specified)\n")));
|
||||
else
|
||||
DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] default interface STA selected\n")));
|
||||
m_IPAddress = sta;
|
||||
|
||||
} else {
|
||||
|
||||
DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] default interface AP selected (none was specified)\n")));
|
||||
m_IPAddress = ap;
|
||||
|
||||
}
|
||||
|
||||
// continue to ensure interface is UP
|
||||
}
|
||||
|
||||
// check existence of this IP address in the interface list
|
||||
bool found = false;
|
||||
for (auto a: addrList)
|
||||
if (m_IPAddress == a.addr()) {
|
||||
if (a.ifUp()) {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] found interface for IP '%s' but it is not UP\n"), m_IPAddress.toString().c_str()););
|
||||
}
|
||||
if (!found) {
|
||||
DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] interface defined by IP '%s' not found\n"), m_IPAddress.toString().c_str()););
|
||||
return false;
|
||||
}
|
||||
|
||||
return ((_resetProbeStatus(true)) && // Stop and restart probing
|
||||
(_allocUDPContext())); // Restart UDP
|
||||
return ((m_netif != nullptr) &&
|
||||
(m_netif->flags & NETIF_FLAG_UP) && // network interface is up and running
|
||||
(_resetProbeStatus(true)) && // Stop and restart probing
|
||||
(_allocUDPContext())); // Restart UDP
|
||||
}
|
||||
|
||||
|
||||
@@ -798,7 +754,7 @@ bool MDNSResponder::_processPTRAnswer(const MDNSResponder::stcMDNS_RRAnswerPTR*
|
||||
if (p_pPTRAnswer->m_u32TTL) { // Received update message
|
||||
pSQAnswer->m_TTLServiceDomain.set(p_pPTRAnswer->m_u32TTL); // Update TTL tag
|
||||
DEBUG_EX_INFO(
|
||||
DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _processPTRAnswer: Updated TTL(%lu) for "), p_pPTRAnswer->m_u32TTL);
|
||||
DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _processPTRAnswer: Updated TTL(%d) for "), (int)p_pPTRAnswer->m_u32TTL);
|
||||
_printRRDomain(pSQAnswer->m_ServiceDomain);
|
||||
DEBUG_OUTPUT.printf_P(PSTR("\n"));
|
||||
);
|
||||
@@ -852,7 +808,7 @@ bool MDNSResponder::_processSRVAnswer(const MDNSResponder::stcMDNS_RRAnswerSRV*
|
||||
if (p_pSRVAnswer->m_u32TTL) { // First or update message (TTL != 0)
|
||||
pSQAnswer->m_TTLHostDomainAndPort.set(p_pSRVAnswer->m_u32TTL); // Update TTL tag
|
||||
DEBUG_EX_INFO(
|
||||
DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _processSRVAnswer: Updated TTL(%lu) for "), p_pSRVAnswer->m_u32TTL);
|
||||
DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _processSRVAnswer: Updated TTL(%d) for "), (int)p_pSRVAnswer->m_u32TTL);
|
||||
_printRRDomain(pSQAnswer->m_ServiceDomain);
|
||||
DEBUG_OUTPUT.printf_P(PSTR(" host domain and port\n"));
|
||||
);
|
||||
@@ -905,7 +861,7 @@ bool MDNSResponder::_processTXTAnswer(const MDNSResponder::stcMDNS_RRAnswerTXT*
|
||||
if (p_pTXTAnswer->m_u32TTL) { // First or update message
|
||||
pSQAnswer->m_TTLTxts.set(p_pTXTAnswer->m_u32TTL); // Update TTL tag
|
||||
DEBUG_EX_INFO(
|
||||
DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _processTXTAnswer: Updated TTL(%lu) for "), p_pTXTAnswer->m_u32TTL);
|
||||
DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _processTXTAnswer: Updated TTL(%d) for "), (int)p_pTXTAnswer->m_u32TTL);
|
||||
_printRRDomain(pSQAnswer->m_ServiceDomain);
|
||||
DEBUG_OUTPUT.printf_P(PSTR(" TXTs\n"));
|
||||
);
|
||||
@@ -957,7 +913,7 @@ bool MDNSResponder::_processTXTAnswer(const MDNSResponder::stcMDNS_RRAnswerTXT*
|
||||
if (p_pAAnswer->m_u32TTL) { // Valid TTL -> Update answers TTL
|
||||
pIP4Address->m_TTL.set(p_pAAnswer->m_u32TTL);
|
||||
DEBUG_EX_INFO(
|
||||
DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _processAAnswer: Updated TTL(%lu) for "), p_pAAnswer->m_u32TTL);
|
||||
DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _processAAnswer: Updated TTL(%d) for "), (int)p_pAAnswer->m_u32TTL);
|
||||
_printRRDomain(pSQAnswer->m_ServiceDomain);
|
||||
DEBUG_OUTPUT.printf_P(PSTR(" IP4Address (%s)\n"), pIP4Address->m_IPAddress.toString().c_str());
|
||||
);
|
||||
@@ -1124,7 +1080,7 @@ bool MDNSResponder::_updateProbeStatus(void) {
|
||||
|
||||
if (MDNS_ANNOUNCE_COUNT > m_HostProbeInformation.m_u8SentCount) {
|
||||
m_HostProbeInformation.m_Timeout.reset(MDNS_ANNOUNCE_DELAY);
|
||||
DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _updateProbeStatus: Announcing host (%lu).\n\n"), m_HostProbeInformation.m_u8SentCount););
|
||||
DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _updateProbeStatus: Announcing host (%d).\n\n"), m_HostProbeInformation.m_u8SentCount););
|
||||
}
|
||||
else {
|
||||
m_HostProbeInformation.m_Timeout.resetToNeverExpires();
|
||||
@@ -1172,7 +1128,7 @@ bool MDNSResponder::_updateProbeStatus(void) {
|
||||
|
||||
if (MDNS_ANNOUNCE_COUNT > pService->m_ProbeInformation.m_u8SentCount) {
|
||||
pService->m_ProbeInformation.m_Timeout.reset(MDNS_ANNOUNCE_DELAY);
|
||||
DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _updateProbeStatus: Announcing service %s.%s.%s (%lu)\n\n"), (pService->m_pcName ?: m_pcHostname), pService->m_pcService, pService->m_pcProtocol, pService->m_ProbeInformation.m_u8SentCount););
|
||||
DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _updateProbeStatus: Announcing service %s.%s.%s (%d)\n\n"), (pService->m_pcName ?: m_pcHostname), pService->m_pcService, pService->m_pcProtocol, pService->m_ProbeInformation.m_u8SentCount););
|
||||
}
|
||||
else {
|
||||
pService->m_ProbeInformation.m_Timeout.resetToNeverExpires();
|
||||
|
@@ -170,7 +170,7 @@ namespace MDNSImplementation {
|
||||
*/
|
||||
|
||||
bool MDNSResponder::_callProcess(void) {
|
||||
DEBUG_EX_INFO(DEBUG_OUTPUT.printf("[MDNSResponder] _callProcess (%lu, triggered by: %s)\n", millis(), m_pUDPContext->getRemoteAddress().toString().c_str()););
|
||||
DEBUG_EX_INFO(DEBUG_OUTPUT.printf("[MDNSResponder] _callProcess (%lu, triggered by: %s)\n", millis(), IPAddress(m_pUDPContext->getRemoteAddress()).toString().c_str()););
|
||||
|
||||
return _process(false);
|
||||
}
|
||||
@@ -199,7 +199,7 @@ bool MDNSResponder::_allocUDPContext(void) {
|
||||
//TODO: set multicast address (lwip_joingroup() is IPv4 only at the time of writing)
|
||||
multicast_addr.addr = DNS_MQUERY_IPV6_GROUP_INIT;
|
||||
#endif
|
||||
if (ERR_OK == igmp_joingroup(IP4_ADDR_ANY4, ip_2_ip4(&multicast_addr))) {
|
||||
if (ERR_OK == igmp_joingroup(ip_2_ip4(&m_netif->ip_addr), ip_2_ip4(&multicast_addr))) {
|
||||
m_pUDPContext = new UdpContext;
|
||||
m_pUDPContext->ref();
|
||||
|
||||
|
@@ -37,6 +37,9 @@ namespace MDNSImplementation {
|
||||
#define ESP_8266_MDNS_INCLUDE
|
||||
//#define DEBUG_ESP_MDNS_RESPONDER
|
||||
|
||||
#if !defined(DEBUG_ESP_MDNS_RESPONDER) && defined(DEBUG_ESP_MDNS)
|
||||
#define DEBUG_ESP_MDNS_RESPONDER
|
||||
#endif
|
||||
|
||||
#ifndef LWIP_OPEN_SRC
|
||||
#define LWIP_OPEN_SRC
|
||||
|
@@ -212,7 +212,7 @@ void SPIClass::setFrequency(uint32_t freq) {
|
||||
return;
|
||||
}
|
||||
|
||||
const spiClk_t minFreqReg = { 0x7FFFF000 };
|
||||
const spiClk_t minFreqReg = { 0x7FFFF020 };
|
||||
uint32_t minFreq = ClkRegToFreq((spiClk_t*) &minFreqReg);
|
||||
if(freq < minFreq) {
|
||||
// use minimum possible clock
|
||||
|
Submodule libraries/SoftwareSerial updated: 4abc14f429...776d49b2f5
258
libraries/esp8266/examples/WiFiShutdown/WiFiShutdown.ino
Normal file
258
libraries/esp8266/examples/WiFiShutdown/WiFiShutdown.ino
Normal file
@@ -0,0 +1,258 @@
|
||||
|
||||
// demonstrate the use of WiFi.mode(SHUTDOWN/RESUME)
|
||||
// released to public domain
|
||||
|
||||
// current on wemos d1 mini (including: ldo, usbserial chip):
|
||||
// ~85mA during normal operations
|
||||
// ~30mA during wifi shutdown
|
||||
// ~5mA during deepsleep
|
||||
|
||||
#ifndef STASSID
|
||||
#define STASSID "mynetwork"
|
||||
#define STAPSK "mynetworkpasswd"
|
||||
#endif
|
||||
|
||||
#define WAIT_NTP 0 // define this to 1 for NTP check too
|
||||
|
||||
#include <ESP8266WiFi.h>
|
||||
#include <coredecls.h> // crc32()
|
||||
#include <include/WiFiState.h> // WiFiState structure details
|
||||
|
||||
enum state_e {
|
||||
e_initial,
|
||||
e_start_resume,
|
||||
e_start_normal,
|
||||
e_off_restart,
|
||||
e_wait_connected,
|
||||
e_wait_ntp,
|
||||
e_shutdown,
|
||||
e_wait_shutdown,
|
||||
e_wait_off
|
||||
};
|
||||
|
||||
static state_e step = e_initial; // step
|
||||
static int wifi_timeout = 0; // wifi timeout counter
|
||||
static bool time_is_set = false; // WAIT_NTP=1: wait for network - dhcp packet must have ntp server
|
||||
|
||||
// non volatile data
|
||||
struct nv_s {
|
||||
WiFiState wss; // core's wifi save state
|
||||
|
||||
uint32_t crc;
|
||||
struct {
|
||||
int rstcounter[7];
|
||||
} data;
|
||||
};
|
||||
static nv_s* nv = (nv_s*)RTC_USER_MEM; // user non volatile area
|
||||
|
||||
#define SEP "###### "
|
||||
#define EV "!!!!!! "
|
||||
#define NFO "------ "
|
||||
|
||||
void resetUserCrc() {
|
||||
nv->crc = crc32(&nv->data, sizeof(nv->data));
|
||||
}
|
||||
|
||||
void printNv() {
|
||||
Serial.printf(NFO "nfo1/2 wifi-nv-state: valid=%d, "
|
||||
"persistent=%d, "
|
||||
"mode=%d, "
|
||||
"channel=%d, "
|
||||
"ip=%s, "
|
||||
"dns=%s, "
|
||||
"ntp=%s\n",
|
||||
WiFi.shutdownValidCRC(&nv->wss),
|
||||
nv->wss.state.persistent,
|
||||
nv->wss.state.mode,
|
||||
nv->wss.state.channel,
|
||||
IPAddress(&nv->wss.state.ip.ip).toString().c_str(),
|
||||
IPAddress(&nv->wss.state.dns[0]).toString().c_str(),
|
||||
IPAddress(&nv->wss.state.ntp[0]).toString().c_str());
|
||||
|
||||
Serial.printf(NFO "nfo2/2 rst reason counters: default:%d wdt:%d exception:%d softwdt:%d reset:%d deepsleep:%d extsys:%d\n",
|
||||
nv->data.rstcounter[0],
|
||||
nv->data.rstcounter[1],
|
||||
nv->data.rstcounter[2],
|
||||
nv->data.rstcounter[3],
|
||||
nv->data.rstcounter[4],
|
||||
nv->data.rstcounter[5],
|
||||
nv->data.rstcounter[6]);
|
||||
}
|
||||
|
||||
void timeset_cb() {
|
||||
time_is_set = true;
|
||||
|
||||
static bool first = true;
|
||||
if (first) {
|
||||
first = false;
|
||||
}
|
||||
}
|
||||
|
||||
decltype(millis()) startup;
|
||||
|
||||
|
||||
WiFiEventHandler evOff = WiFi.onWiFiModeChange([](const WiFiEventModeChange& event) {
|
||||
Serial.printf(EV "mode changed event: ev:%d->%d getMode=%d\n", event.oldMode, event.newMode, wifi_get_opmode());
|
||||
});
|
||||
|
||||
void preinit() {
|
||||
ESP8266WiFiClass::preinitWiFiOff();
|
||||
}
|
||||
|
||||
void setup() {
|
||||
WiFi.persistent(false);
|
||||
startup = millis();
|
||||
Serial.begin(115200);
|
||||
settimeofday_cb(timeset_cb);
|
||||
|
||||
// prepare non volatile user structure
|
||||
if (crc32(&nv->data, sizeof(nv->data)) != nv->crc) {
|
||||
memset(&nv->data, 0, sizeof(nv->data));
|
||||
Serial.printf(SEP "reset NV user data\n");
|
||||
}
|
||||
// update reset reason
|
||||
nv->data.rstcounter[system_get_rst_info()->reason]++;
|
||||
// recalculate crc
|
||||
resetUserCrc();
|
||||
// nfo
|
||||
printNv();
|
||||
|
||||
Serial.println("setup()");
|
||||
}
|
||||
|
||||
#define TEST(x...) ({ auto v = x; Serial.printf(SEP "'%s': result = %d\n", #x, v); v; })
|
||||
|
||||
void loop() {
|
||||
|
||||
static int prev = 255;
|
||||
if (step != prev) {
|
||||
prev = step;
|
||||
Serial.printf(NFO "step %d - wifi getMode=%d=%d heap=%d freeheap=%d\n",
|
||||
prev,
|
||||
WiFi.getMode(),
|
||||
wifi_get_opmode(),
|
||||
ESP.getFreeHeap(),
|
||||
ESP.getFreeHeap());
|
||||
printNv();
|
||||
}
|
||||
|
||||
switch (step) {
|
||||
|
||||
case e_initial: {
|
||||
if (WiFi.shutdownValidCRC(&nv->wss)) {
|
||||
step = e_start_resume;
|
||||
} else {
|
||||
step = e_start_normal;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
case e_start_resume:
|
||||
Serial.println(SEP "CRC valid => WIFI_RESUME");
|
||||
startup = millis();
|
||||
|
||||
if (!TEST(WiFi.mode(WIFI_RESUME, &nv->wss))) {
|
||||
Serial.printf(SEP "issue resuming WiFi\n");
|
||||
step = e_off_restart;
|
||||
} else {
|
||||
Serial.printf(SEP "waiting for connected\\n");
|
||||
step = e_wait_connected;
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
case e_start_normal:
|
||||
Serial.printf(SEP "CRC NOT valid, begin/WIFI_STA (current mode = %d)\n", wifi_get_opmode());
|
||||
startup = millis();
|
||||
if (!TEST(WiFi.mode(WIFI_STA)) || !TEST(WiFi.begin(STASSID, STAPSK))) {
|
||||
Serial.printf(SEP "issue setting up STA\n");
|
||||
step = e_off_restart;
|
||||
} else {
|
||||
Serial.printf(SEP "waiting for connected\n");
|
||||
step = e_wait_connected;
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
case e_wait_connected:
|
||||
if (WiFi.status() == WL_CONNECTED) {
|
||||
Serial.printf(SEP "connected! ---- startup time: %ld ms ----\n\n\n", millis() - startup);
|
||||
wifi_timeout = 0;
|
||||
if (WAIT_NTP) {
|
||||
step = e_wait_ntp;
|
||||
Serial.printf(SEP "wait for NTP\n");
|
||||
} else {
|
||||
step = e_shutdown;
|
||||
}
|
||||
} else if ((millis() - startup > 10000)) {
|
||||
Serial.printf(SEP "connected TIMEOUT! status=%d\n", WiFi.status());
|
||||
wifi_timeout++;
|
||||
step = e_off_restart;
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
case e_off_restart:
|
||||
Serial.printf(SEP "OFF -> wait 2s\n");
|
||||
(void)TEST(WiFi.mode(WIFI_OFF));
|
||||
delay(2000); // test - mad wifi loop until :oom if delay not there - to verify
|
||||
step = e_initial;
|
||||
break;
|
||||
|
||||
|
||||
case e_wait_ntp:
|
||||
// check when NTP has set time
|
||||
if (time_is_set) {
|
||||
Serial.printf(SEP "NTP is set\n");
|
||||
time_is_set = false;
|
||||
step = e_shutdown;
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
case e_shutdown: {
|
||||
static int deepsleep = 0;
|
||||
switch (++deepsleep) {
|
||||
case 1: {
|
||||
Serial.println(SEP "WIFI_OFF for 5s");
|
||||
TEST(WiFi.mode(WIFI_OFF));
|
||||
step = e_wait_off;
|
||||
break;
|
||||
}
|
||||
case 2: // several loop on shutdown
|
||||
case 3: // to check if it affects
|
||||
case 4: { // reconnection duration
|
||||
Serial.println(SEP "WIFI_SHUTDOWN for 5s");
|
||||
TEST(WiFi.mode(WIFI_SHUTDOWN, &nv->wss));
|
||||
step = e_wait_shutdown;
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
Serial.println(SEP "DEEPSLEEP for 5s (bind GPIO16 <=> RST)");
|
||||
TEST(WiFi.mode(WIFI_SHUTDOWN, &nv->wss));
|
||||
Serial.flush();
|
||||
ESP.deepSleep(5000000);
|
||||
// will reboot, GPIO16 must be connected to reset
|
||||
}
|
||||
}
|
||||
|
||||
startup = millis();
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
case e_wait_shutdown:
|
||||
if (millis() - startup > 5000) {
|
||||
step = e_start_resume;
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
case e_wait_off:
|
||||
if (millis() - startup > 5000) {
|
||||
step = e_start_normal;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
159
libraries/esp8266/examples/arduino_new/arduino_new.ino
Normal file
159
libraries/esp8266/examples/arduino_new/arduino_new.ino
Normal file
@@ -0,0 +1,159 @@
|
||||
|
||||
// show arduino_new benefits
|
||||
// released to public domain
|
||||
// result is below
|
||||
|
||||
class SomeClass {
|
||||
public:
|
||||
SomeClass(const String& s1 = emptyString, const String& s2 = emptyString) {
|
||||
Serial.printf("SomeClass@%p(%s)(%s)\n", this, s1.c_str(), s2.c_str());
|
||||
}
|
||||
|
||||
~SomeClass() {
|
||||
Serial.printf("~ SomeClass @%p\n", this);
|
||||
}
|
||||
};
|
||||
|
||||
class oom {
|
||||
private:
|
||||
char large [65000];
|
||||
public:
|
||||
oom() {
|
||||
Serial.printf("this constructor should not be called\n");
|
||||
}
|
||||
};
|
||||
|
||||
void setup() {
|
||||
|
||||
Serial.begin(115200);
|
||||
Serial.printf("\n\narduino_new benefits\n\n");
|
||||
delay(5000); // avoid too frequent bootloop
|
||||
|
||||
// arduino_new / arduino_newarray api
|
||||
|
||||
Serial.printf("\n----- arduino_new:\n");
|
||||
auto an = arduino_new(SomeClass);
|
||||
delete an;
|
||||
|
||||
Serial.printf("\n----- arduino_new with oom:\n");
|
||||
auto anoom = arduino_new(oom);
|
||||
Serial.printf("nullptr: %p\n", anoom);
|
||||
delete anoom;
|
||||
|
||||
Serial.printf("\n----- arduino_new with constructor parameters:\n");
|
||||
auto ancp = arduino_new(SomeClass, "param1", "param2");
|
||||
delete ancp;
|
||||
|
||||
Serial.printf("\n----- arduino_newarray[2]\n");
|
||||
auto ana2 = arduino_newarray(SomeClass, 2);
|
||||
Serial.printf("@:%p s=%zd s(2)=%zd\n", ana2, sizeof(SomeClass), sizeof(SomeClass[2]));
|
||||
Serial.printf("0: %p\n", &ana2[0]);
|
||||
Serial.printf("1: %p\n", &ana2[1]);
|
||||
delete [] ana2;
|
||||
|
||||
Serial.printf("\n----- arduino_newarray[2] (with constructor parameters)\n");
|
||||
auto ana2cp = arduino_newarray(SomeClass, 2, "param1");
|
||||
Serial.printf("@:%p s=%zd s(2)=%zd\n", ana2cp, sizeof(SomeClass), sizeof(SomeClass[2]));
|
||||
Serial.printf("0: %p\n", &ana2cp[0]);
|
||||
Serial.printf("1: %p\n", &ana2cp[1]);
|
||||
delete [] ana2cp;
|
||||
|
||||
Serial.printf("\n----- arduino_newarray[100000]\n");
|
||||
auto anaX = arduino_newarray(SomeClass, 100000);
|
||||
Serial.printf("@:%p\n", anaX);
|
||||
|
||||
// standard c++ api for new and new[]
|
||||
|
||||
Serial.printf("\n----- new\n");
|
||||
auto sn = new SomeClass;
|
||||
delete sn;
|
||||
|
||||
Serial.printf("\n----- new with oom: (abort() with option 'Exceptions: Disabled (new can abort)'\n");
|
||||
auto snoom = new oom;
|
||||
Serial.printf("nullptr: %p\n", snoom);
|
||||
delete snoom;
|
||||
|
||||
Serial.printf("\n----- new[2]\n");
|
||||
auto sna2 = new SomeClass[2];
|
||||
Serial.printf("@:%p s=%zd s(2)=%zd\n", sna2, sizeof(SomeClass), sizeof(SomeClass[2]));
|
||||
Serial.printf("0: %p\n", &sna2[0]);
|
||||
Serial.printf("1: %p\n", &sna2[1]);
|
||||
delete [] sna2;
|
||||
|
||||
Serial.printf("\n----- new[10000] (badly fails with 'Exceptions: Legacy' or '...Disabled'\n");
|
||||
auto snaX = new SomeClass[100000];
|
||||
Serial.printf("@:%p\n", snaX);
|
||||
}
|
||||
|
||||
void loop() {
|
||||
}
|
||||
|
||||
//////////////////////////////
|
||||
/*
|
||||
|
||||
Result with:
|
||||
Exceptions: Legacy(new can return nullptr)
|
||||
|
||||
//////////////////////////////
|
||||
|
||||
arduino_new benefits
|
||||
|
||||
----- arduino_new:
|
||||
SomeClass@0x3fff1864()()
|
||||
~ SomeClass @0x3fff1864
|
||||
|
||||
----- arduino_new with oom:
|
||||
nullptr: 0
|
||||
|
||||
----- arduino_new with constructor parameters:
|
||||
SomeClass@0x3fff1864(param1)(param2)
|
||||
~ SomeClass @0x3fff1864
|
||||
|
||||
----- arduino_newarray[2]
|
||||
SomeClass@0x3fff1868()()
|
||||
SomeClass@0x3fff1869()()
|
||||
@: 0x3fff1868 s = 1 s(2) = 2
|
||||
0: 0x3fff1868
|
||||
1: 0x3fff1869
|
||||
~ SomeClass @0x3fff1869
|
||||
~ SomeClass @0x3fff1868
|
||||
|
||||
----- arduino_newarray[2](with constructor parameters)
|
||||
SomeClass@0x3fff1868(param1)()
|
||||
SomeClass@0x3fff1869(param1)()
|
||||
@: 0x3fff1868 s = 1 s(2) = 2
|
||||
0: 0x3fff1868
|
||||
1: 0x3fff1869
|
||||
~ SomeClass @0x3fff1869
|
||||
~ SomeClass @0x3fff1868
|
||||
|
||||
----- arduino_newarray[100000]
|
||||
@: 0
|
||||
|
||||
----- new
|
||||
SomeClass@0x3fff1864()()
|
||||
~ SomeClass @0x3fff1864
|
||||
|
||||
----- new with oom: (abort() with option 'Exceptions: Disabled (new can abort)'
|
||||
this constructor should not be called
|
||||
nullptr: 0
|
||||
|
||||
----- new[2]
|
||||
SomeClass@0x3fff1868()()
|
||||
SomeClass@0x3fff1869()()
|
||||
@:0x3fff1868 s = 1 s(2) = 2
|
||||
0: 0x3fff1868
|
||||
1: 0x3fff1869
|
||||
~ SomeClass @0x3fff1869
|
||||
~ SomeClass @0x3fff1868
|
||||
|
||||
----- new[10000](badly fails with 'Exceptions: Legacy' or '...Disabled'
|
||||
|
||||
Exception(29):
|
||||
epc1 = 0x402013de epc2 = 0x00000000 epc3 = 0x00000000 excvaddr = 0x00000000 depc = 0x00000000
|
||||
|
||||
>>> stack >>>
|
||||
...
|
||||
|
||||
*/
|
||||
/////////////////////////////
|
Reference in New Issue
Block a user