Merge branch 'mega' into bugfix/Command-udpport-argument-parsing

This commit is contained in:
Ton Huisman authored and GitHub committed 2026-10-07 21:40:36 +02:00
commit 80ebf9a8b7
17 files changed
+311 -159

No files matched your search

+1 -1
View File
@@ -82,7 +82,7 @@ jobs:
- name: Install dependencies
run: |
uv pip install --system pioarduino
uv pip install --system pygit2>=1.10.1
uv pip install --system -r requirements.txt
- name: Get current date
id: date
run: |
+18 -12
View File
@@ -41,28 +41,34 @@ jobs:
- uses: actions/setup-python@v7
with:
python-version: '3.13'
- name: Dependencies
- name: Install uv
uses: astral-sh/setup-uv@v7
with:
version: "latest"
enable-cache: false
- name: Install dependencies
run: |
sudo apt install binutils build-essential libffi-dev libgit2-dev
pip install uv
uv pip install --system pioarduino
uv pip install --system -r requirements.txt
pio pkg update -e ${{ matrix.env }}
- name: Build and archive
id: build-and-archive
env:
CHIP: ${{ matrix.chip }}
ENV: ${{ matrix.env }}
- name: Get current date
id: date
run: |
python tools/ci/build-and-archive.py
echo "builddate=$(date +'%Y%m%d')" >> $GITHUB_OUTPUT
- name: Run PlatformIO
env:
PYTHONIOENCODING: utf-8
PYTHONUTF8: '1'
run: platformio run -e ${{ matrix.env }}
- id: string
uses: Entepotenz/change-string-case-action-min-dependencies@v1
with:
string: ${{ matrix.chip }}
- uses: actions/upload-artifact@v7
with:
name: Bin-${{ steps.string.outputs.uppercase }}-${{ matrix.env }}
# FIXME Workaround to (temporarily) not use # in the artifact name, see https://github.com/actions/upload-artifact/issues/473
name: Bin-${{ steps.string.outputs.uppercase }}-${{ matrix.env }}-${{ steps.date.outputs.builddate }}_PR_${{ github.event.number }}_${{ github.run_id }} # Sort by ESP type
path: |
bin
./build_output/bin
if-no-files-found: ignore
prepare-dist:
+1 -1
View File
@@ -72,7 +72,7 @@ bool PingClass::ping(IPAddress dest, int16_t count) {
bool PingClass::ping(const char* host, int16_t count) {
IPAddress remote_addr;
if (WiFi.hostByName(host, remote_addr))
if (WiFi.hostByName(host, remote_addr) == 1)
return ping(remote_addr, count);
return false;
+1 -1
View File
@@ -1173,7 +1173,7 @@ bool HTTPClientLight::connect(void)
} else {
IPAddress remote_addr;
// Add include "ESP8266WiFi.h" for this to work
if (!WiFi.hostByName(_host.c_str(), remote_addr)) {
if (Network.hostByName(_host.c_str(), remote_addr) != 1) {
return false;
}
if(!_client->connect(remote_addr, _port, _connectTimeout)) {
@@ -335,7 +335,7 @@ int WiFiClientSecure_light::connect(const char* name, uint16_t port, int32_t tim
DEBUG_BSSL("connect(%s,%d)\n", name, port);
IPAddress remote_addr;
clearLastError();
if (!WiFi.hostByName(name, remote_addr)) {
if (Network.hostByName(name, remote_addr) != 1) {
DEBUG_BSSL("connect: Name loopup failure\n");
setLastError(ERR_CANT_RESOLVE_IP);
return 0;
+2 -3
View File
@@ -191,9 +191,8 @@ extra_scripts = ${esp82xx_common.extra_scripts}
;platform_packages = framework-arduinoespressif32 @ https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/2904-2115-5.5/framework-arduinoespressif32-release_v5.5-f2a3fa2b.tar.xz
platform = https://github.com/Jason2866/platform-espressif32.git#Arduino/IDF55_gcc152
;platform_packages = framework-arduinoespressif32 @ https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1807-0842-5.5/framework-arduinoespressif32-release_v5.5-67336dba.tar.xz
;platform_packages = framework-arduinoespressif32 @ https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/2805-1324-5.5/framework-arduinoespressif32-release_v5.5-f3cdb9d0.tar.xz
platform_packages = framework-arduinoespressif32 @ https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/2708-1939-5.5.5/framework-arduinoespressif32-v5.5.5-a63b839f.tar.xz
;platform_packages = framework-arduinoespressif32 @ https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/2708-1939-5.5.5/framework-arduinoespressif32-v5.5.5-a63b839f.tar.xz
platform_packages =
custom_remove_include = true
@@ -47,11 +47,11 @@ bool WiFi_pre_STA_setup()
void doWiFiDisconnect() {
uint8_t retry = 3;
#ifdef BOARD_HAS_SDIO_ESP_HOSTED
# ifdef BOARD_HAS_SDIO_ESP_HOSTED
bool wifioff = true;
#else
# else
bool wifioff = Settings.WiFiRestart_connection_lost();
#endif
# endif // ifdef BOARD_HAS_SDIO_ESP_HOSTED
while (!WiFi.disconnect(wifioff) && retry) {
--retry;
@@ -402,13 +402,40 @@ WiFiConnectionProtocol doGetConnectionProtocol()
void doSetWiFiTXpower(float& dBm)
{
int8_t power = dBm * 4;
if (WiFi.STA.started() || WiFi.AP.started()) {
constexpr wifi_power_t options[] = {
WIFI_POWER_21dBm,
WIFI_POWER_20_5dBm,
WIFI_POWER_20dBm,
WIFI_POWER_19_5dBm,
WIFI_POWER_19dBm,
WIFI_POWER_18_5dBm,
WIFI_POWER_17dBm,
WIFI_POWER_15dBm,
WIFI_POWER_13dBm,
WIFI_POWER_11dBm,
WIFI_POWER_8_5dBm,
WIFI_POWER_7dBm,
WIFI_POWER_5dBm,
WIFI_POWER_2dBm,
WIFI_POWER_MINUS_1dBm
};
int8_t power = std::min(static_cast<int>(dBm * 4), static_cast<int>(options[0]));
for (size_t i = 0; i < NR_ELEMENTS(options); ++i) {
if (power >= options[i]) {
power = options[i];
esp_wifi_set_max_tx_power(power);
if (esp_wifi_get_max_tx_power(&power) == ESP_OK) {
dBm = static_cast<float>(power) / 4.0f;
}
return;
}
}
}
dBm = 0;
}
float doGetWiFiTXpower()
+10
View File
@@ -39,6 +39,16 @@ To create/register a plugin, you have to :
\******************************************************************************/
// FIXME TD-er: Make useful selections for these pages to be included. (e.g. view only)
// FIXME TD-er: Disable Arduino OTA for now, seems to cause crashes/bootloop on some ESP32-variants (C3/C6, maybe more)
// No idea why, disabled on 2026/09/22
#ifdef FEATURE_ARDUINO_OTA
#undef FEATURE_ARDUINO_OTA
#endif
#define FEATURE_ARDUINO_OTA 0
#ifndef WEBSERVER_CUSTOM_BUILD_DEFINED
#ifndef WEBSERVER_TIMINGSTATS
#define WEBSERVER_TIMINGSTATS
+8
View File
@@ -11,6 +11,7 @@
#include "../ESPEasyCore/ESPEasy_Log.h"
#include "../ESPEasyCore/ESPEasy_backgroundtasks.h"
#include "../Globals/ESPEasy_Scheduler.h"
#include "../Globals/ESPEasy_time.h"
#include "../Globals/EventQueue.h"
#include "../Globals/RTC.h"
#include "../Globals/Settings.h"
@@ -84,6 +85,7 @@ void ESPEasy_loop()
#endif
firstLoop = false;
timerAwakeFromDeepSleep = millis(); // Allow to run for "awake" number of seconds, now we have wifi.
Scheduler.sendGratuitousARP_now();
// schedule_all_task_device_timers(); // Disabled for now, since we are now using queues for controllers.
if (Settings.UseRules && isDeepSleepEnabled())
@@ -103,6 +105,7 @@ void ESPEasy_loop()
#if FEATURE_ESPEASY_P2P
sendSysInfoUDP(1);
#endif
node_time.initTime();
}
setWebserverRunning(ESPEasy::net::NWPluginCall(NWPlugin::Function::NWPLUGIN_WEBSERVER_SHOULD_RUN));
@@ -187,4 +190,9 @@ void ESPEasy_loop()
// deepsleep will never return, its a special kind of reboot
}
if (firstLoopConnectionsEstablished) {
// FIXME TD-er: First NTP call may fail, so we make several here.
node_time.initTime();
}
}
+5 -2
View File
@@ -317,6 +317,8 @@ void ESPEasy_setup()
RTC.bootFailedCount++;
RTC.bootCounter++;
lastMixedSchedulerId_beforereboot.mixed_id = RTC.lastMixedSchedulerId;
node_time.restoreFromRTC();
readUserVarFromRTC();
log = concat(F("INIT : "), getLastBootCauseString()) +
concat(F(" #"), RTC.bootCounter);
@@ -359,6 +361,9 @@ void ESPEasy_setup()
// progMemMD5check();
LoadSettings();
#if FEATURE_EXT_RTC
node_time.restoreFromRTC();
#endif
#if FEATURE_DEFINE_SERIAL_CONSOLE_PORT
ESPEasy_Console.reInit();
#endif // if FEATURE_DEFINE_SERIAL_CONSOLE_PORT
@@ -398,8 +403,6 @@ void ESPEasy_setup()
logMemUsageAfter(F("hardwareInit()"));
#endif // ifndef BUILD_NO_RAM_TRACKER
node_time.restoreFromRTC();
Settings.UseRTOSMultitasking = false; // For now, disable it, we experience heap corruption.
if ((RTC.bootFailedCount > 10) && (RTC.bootCounter > 10)) {
+52 -45
View File
@@ -34,18 +34,18 @@
# endif // ifdef ESP32
# ifndef DALLAS_RESET_RETRIES
# ifndef DALLAS_RETRIES
// Reset may fail if a
# define DALLAS_RESET_RETRIES 3
# endif // ifndef DALLAS_RESET_RETRIES
# define DALLAS_RETRIES 3
# endif // ifndef DALLAS_RETRIES
# include <vector>
unsigned char ROM_NO[8]{ 0 };
uint8_t LastDiscrepancy{};
uint8_t LastFamilyDiscrepancy{};
uint8_t LastDeviceFlag{};
bool LastDeviceFlag{};
int32_t usec_release{};
int32_t presence_start{};
@@ -199,6 +199,28 @@ void Dallas_addr_selector_webform_load(taskIndex_t TaskIndex, int8_t gpio_pin_rx
nrVariables = VARS_PER_TASK;
}
// find all suitable devices
std::vector<uint64_t> scan_res;
std::vector<bool> fixed_res;
for (uint8_t attempt = 0; attempt < DALLAS_RETRIES && scan_res.size() == 0; ++attempt)
{
Dallas_reset_search();
uint8_t tmpAddress[8]{};
while (Dallas_search(tmpAddress, gpio_pin_rx, gpio_pin_tx))
{
scan_res.push_back(Dallas_addr_to_uint64(tmpAddress));
bool hasFixedResolution = false;
Dallas_getResolution(tmpAddress, gpio_pin_rx, gpio_pin_tx, hasFixedResolution);
fixed_res.push_back(hasFixedResolution);
}
if (scan_res.size() == 0) {
delay(5);
}
}
std::map<uint64_t, String> addr_task_map;
for (taskIndex_t task = 0; validTaskIndex(task); ++task) {
@@ -226,20 +248,6 @@ void Dallas_addr_selector_webform_load(taskIndex_t TaskIndex, int8_t gpio_pin_rx
}
}
// find all suitable devices
std::vector<uint64_t> scan_res;
std::vector<bool> fixed_res;
Dallas_reset_search();
uint8_t tmpAddress[8]{};
while (Dallas_search(tmpAddress, gpio_pin_rx, gpio_pin_tx))
{
scan_res.push_back(Dallas_addr_to_uint64(tmpAddress));
bool hasFixedResolution = false;
Dallas_getResolution(tmpAddress, gpio_pin_rx, gpio_pin_tx, hasFixedResolution);
fixed_res.push_back(hasFixedResolution);
}
for (uint8_t var_index = 0; var_index < nrVariables; ++var_index) {
String rowLabel = F("Device Address");
@@ -250,15 +258,21 @@ void Dallas_addr_selector_webform_load(taskIndex_t TaskIndex, int8_t gpio_pin_rx
}
addRowLabel(rowLabel);
addSelector_Head(concat(F("dallas_addr"), static_cast<int>(var_index)));
addSelector_Item(F("- None -"), -1, false); // Empty choice
addSelector_Item(F("- None -"), 0, false); // Empty choice
// get currently saved address
uint64_t saved_addr64{};
{
uint8_t savedAddress[8];
Dallas_plugin_get_addr(savedAddress, TaskIndex, var_index); // Need to fetch only once?
saved_addr64 = Dallas_addr_to_uint64(savedAddress);
}
for (uint8_t index = 0; index < scan_res.size(); ++index) {
const uint64_t scan_addr = scan_res[index];
uint8_t tmpAddress[8]{};
Dallas_uint64_to_addr(scan_res[index], tmpAddress);
Dallas_uint64_to_addr(scan_addr, tmpAddress);
String option;
# ifndef LIMIT_BUILD_SIZE
@@ -270,14 +284,14 @@ void Dallas_addr_selector_webform_load(taskIndex_t TaskIndex, int8_t gpio_pin_rx
}
# endif // ifndef LIMIT_BUILD_SIZE
option += Dallas_format_address(tmpAddress, fixed_res[index]);
auto it = addr_task_map.find(scan_res[index]);
auto it = addr_task_map.find(scan_addr);
if (it != addr_task_map.end()) {
option += it->second;
}
const bool selected = (memcmp(tmpAddress, savedAddress, 8) == 0);
addSelector_Item_index64(option, scan_res[index], selected);
const bool selected = scan_addr == saved_addr64;
addSelector_Item_index64(option, scan_addr, selected);
}
addSelector_Foot();
}
@@ -793,7 +807,7 @@ bool Dallas_setResolution(const uint8_t ROM[8], uint8_t res, int8_t gpio_pin_rx,
\*********************************************************************************************/
uint8_t Dallas_reset(int8_t gpio_pin_rx, int8_t gpio_pin_tx)
{
for (uint8_t attempt = 0; attempt < DALLAS_RESET_RETRIES; ++attempt) {
for (uint8_t attempt = 0; attempt < DALLAS_RETRIES; ++attempt) {
presence_start = 0;
presence_end = 0;
@@ -902,14 +916,12 @@ uint8_t Dallas_reset(int8_t gpio_pin_rx, int8_t gpio_pin_tx)
ISR_interrupts();
}
delay(1);
}
return 0;
}
# define FALSE 0
# define TRUE 1
/*********************************************************************************************\
* Dallas Reset Search
\*********************************************************************************************/
@@ -917,7 +929,7 @@ void Dallas_reset_search()
{
// reset the search state
LastDiscrepancy = 0;
LastDeviceFlag = FALSE;
LastDeviceFlag = false;
LastFamilyDiscrepancy = 0;
for (uint8_t i = 0; i < 8; i++) {
@@ -930,16 +942,14 @@ void Dallas_reset_search()
\*********************************************************************************************/
uint8_t Dallas_search(uint8_t *newAddr, int8_t gpio_pin_rx, int8_t gpio_pin_tx)
{
uint8_t id_bit_number;
uint8_t last_zero, rom_byte_number, search_result;
unsigned char rom_byte_mask, search_direction;
unsigned char search_direction;
// initialize for search
id_bit_number = 1;
last_zero = 0;
rom_byte_number = 0;
rom_byte_mask = 1;
search_result = 0;
uint8_t id_bit_number = 1;
uint8_t last_zero = 0;
uint8_t rom_byte_number = 0;
unsigned char rom_byte_mask = 1;
bool search_result = false;
// if the last call was not the last one
if (!LastDeviceFlag)
@@ -949,9 +959,9 @@ uint8_t Dallas_search(uint8_t *newAddr, int8_t gpio_pin_rx, int8_t gpio_pin_tx)
{
// reset the search
LastDiscrepancy = 0;
LastDeviceFlag = FALSE;
LastDeviceFlag = false;
LastFamilyDiscrepancy = 0;
return FALSE;
return false;
}
// issue the search command
@@ -1035,10 +1045,10 @@ uint8_t Dallas_search(uint8_t *newAddr, int8_t gpio_pin_rx, int8_t gpio_pin_tx)
// check for last device
if (LastDiscrepancy == 0) {
LastDeviceFlag = TRUE;
LastDeviceFlag = true;
}
search_result = TRUE;
search_result = true;
}
}
@@ -1046,9 +1056,9 @@ uint8_t Dallas_search(uint8_t *newAddr, int8_t gpio_pin_rx, int8_t gpio_pin_tx)
if (!search_result || !ROM_NO[0])
{
LastDiscrepancy = 0;
LastDeviceFlag = FALSE;
LastDeviceFlag = false;
LastFamilyDiscrepancy = 0;
search_result = FALSE;
search_result = false;
}
for (int i = 0; i < 8; i++) {
@@ -1058,9 +1068,6 @@ uint8_t Dallas_search(uint8_t *newAddr, int8_t gpio_pin_rx, int8_t gpio_pin_tx)
return search_result;
}
# undef FALSE
# undef TRUE
/*********************************************************************************************\
* Dallas Read byte
\*********************************************************************************************/
+1 -1
View File
@@ -63,7 +63,7 @@ struct Dallas_SensorData {
extern unsigned char ROM_NO[8];
extern uint8_t LastDiscrepancy;
extern uint8_t LastFamilyDiscrepancy;
extern uint8_t LastDeviceFlag;
extern bool LastDeviceFlag;
/*********************************************************************************************\
+2 -5
View File
@@ -1480,17 +1480,14 @@ String LoadTaskSettings(taskIndex_t TaskIndex)
START_TIMER
ExtraTaskSettings.clear();
Cache.clearTaskCache(TaskIndex);
const deviceIndex_t DeviceIndex = getDeviceIndex_from_TaskIndex(TaskIndex);
if (!validDeviceIndex(DeviceIndex)) {
// No need to load from storage, as there is no plugin assigned to this task.
ExtraTaskSettings.TaskIndex = TaskIndex; // Needed when an empty task was requested
// FIXME TD-er: Do we need to keep a cache of an empty task?
// Maybe better to do this?
Cache.clearTaskCache(TaskIndex);
// Cache.updateExtraTaskSettingsCache_afterLoad_Save();
return EMPTY_STRING;
}
#ifndef BUILD_NO_RAM_TRACKER
+42 -6
View File
@@ -30,6 +30,7 @@
#include "../Helpers/Convert.h"
#include "../Helpers/ESPEasyRTC.h"
#include "../Helpers/Hardware.h"
#include "../Helpers/Hardware_I2C.h"
#include "../Helpers/Misc.h"
@@ -45,6 +46,14 @@
# include <RTClib.h>
#endif // if FEATURE_EXT_RTC
#ifndef BUILD_NO_DEBUG
#define ESPEASY_NTP_DEBUG 1
#else
#define ESPEASY_NTP_DEBUG 0
#endif
#define ESPEASY_NTP_TIMEOUT 1000
ESPEasy_time::ESPEasy_time() {
memset(&local_tm, 0, sizeof(tm));
@@ -258,6 +267,7 @@ uint32_t ESPEasy_time::now_() {
_timeSource = extTimeSource;
} else {
if (!isExternalTimeSource(_timeSource)
|| lastSyncTime_ms == 0
|| (timePassedSince(lastSyncTime_ms) > static_cast<long>(1000 * syncInterval)))
{
externalUnixTime_offset_usec = 0;
@@ -439,6 +449,7 @@ uint32_t ESPEasy_time::now_() {
}
RTC.lastSysTime = getUnixTime();
uint32_t localSystime = time_zone.toLocal(RTC.lastSysTime);
saveToRTC();
breakTime(localSystime, local_tm);
calcSunRiseAndSet(timeSynced);
@@ -509,7 +520,7 @@ bool ESPEasy_time::systemTimePresent() const {
bool ESPEasy_time::getNtpTime(double& unixTime_d)
{
if (!Settings.UseNTP() || !ESPEasy::net::NetworkConnected(true)) {
if (!Settings.UseNTP() || !ESPEasy::net::NetworkConnected()) {
return false;
}
@@ -549,7 +560,7 @@ bool ESPEasy_time::getNtpTime(double& unixTime_d)
if (!hostReachable(timeServerIP)) {
log += F(" unreachable");
addLogMove(LOG_LEVEL_INFO, log);
addLogMove(LOG_LEVEL_ERROR, log);
STOP_TIMER(NTP_FAIL);
return false;
}
@@ -557,6 +568,10 @@ bool ESPEasy_time::getNtpTime(double& unixTime_d)
WiFiUDP udp;
if (!beginWiFiUDP_randomPort(udp)) {
#if ESPEASY_NTP_DEBUG
log += F(" failed beginWiFiUDP_randomPort");
addLogMove(LOG_LEVEL_ERROR, log);
#endif
return false;
}
@@ -567,8 +582,8 @@ bool ESPEasy_time::getNtpTime(double& unixTime_d)
addLog(LOG_LEVEL_DEBUG_MORE, log);
#endif // ifndef BUILD_NO_DEBUG
while (udp.parsePacket() > 0) { // discard any previously received packets
}
// while (udp.parsePacket() > 0) { // discard any previously received packets
// }
FeedSW_watchdog();
@@ -576,6 +591,10 @@ bool ESPEasy_time::getNtpTime(double& unixTime_d)
FeedSW_watchdog();
udp.stop();
STOP_TIMER(NTP_FAIL);
#if ESPEASY_NTP_DEBUG
log += F(" failed beginPacket");
addLogMove(LOG_LEVEL_ERROR, log);
#endif
return false;
}
constexpr int NTP_packet_size = sizeof(NTP_packet);
@@ -590,7 +609,7 @@ bool ESPEasy_time::getNtpTime(double& unixTime_d)
addLog(LOG_LEVEL_DEBUG, concat(F("NTP : before\n"), ntp_packet.toDebugString()));
#endif // ifndef BUILD_NO_DEBUG
while (!timeOutReached(beginWait + 1000)) {
while (!timeOutReached(beginWait + ESPEASY_NTP_TIMEOUT)) {
const int size = udp.parsePacket();
const int remotePort = udp.remotePort();
@@ -601,6 +620,10 @@ bool ESPEasy_time::getNtpTime(double& unixTime_d)
#endif // ifndef BUILD_NO_DEBUG
udp.stop();
STOP_TIMER(NTP_FAIL);
#if ESPEASY_NTP_DEBUG
log += concat(F(" Reply from wrong port: "), remotePort);
addLogMove(LOG_LEVEL_ERROR, log);
#endif
return false;
}
udp.read(ntp_packet.data, NTP_packet_size); // read packet into the buffer
@@ -626,6 +649,10 @@ bool ESPEasy_time::getNtpTime(double& unixTime_d)
nextSyncTime = getUptime_in_sec() + 120;
}
STOP_TIMER(NTP_FAIL);
#if ESPEASY_NTP_DEBUG
log += F(" isUnsynchronized");
addLogMove(LOG_LEVEL_ERROR, log);
#endif
return false;
}
@@ -664,6 +691,10 @@ bool ESPEasy_time::getNtpTime(double& unixTime_d)
// or no valid timestamps from the NTP server.
nextSyncTime = getUptime_in_sec() + 60;
STOP_TIMER(NTP_FAIL);
#if ESPEASY_NTP_DEBUG
log += F(" failed compute_usec");
addLogMove(LOG_LEVEL_ERROR, log);
#endif
return false;
}
@@ -707,10 +738,15 @@ bool ESPEasy_time::getNtpTime(double& unixTime_d)
// Timeout.
if (!useNTPpool) {
// Retry again in a minute.
nextSyncTime = getUptime_in_sec() + 60;
nextSyncTime = getUptime_in_sec() + 10;
}
#ifndef BUILD_NO_DEBUG
#if ESPEASY_NTP_DEBUG
log += strformat(F(" No reply, duration: %d ms"), timePassedSince(beginWait));
addLogMove(LOG_LEVEL_ERROR, log);
#endif
addLog(LOG_LEVEL_DEBUG_MORE, F("NTP : No reply"));
#endif // ifndef BUILD_NO_DEBUG
udp.stop();
+21 -5
View File
@@ -1211,7 +1211,7 @@ bool setDNS(int index, const IPAddress& dns) {
bool resolveHostByName(const char *aHostname, IPAddress& aResult, uint32_t timeout_ms) {
START_TIMER;
if (!ESPEasy::net::NetworkConnected(true)) {
if (!ESPEasy::net::NetworkConnected()) {
return false;
}
@@ -1220,17 +1220,33 @@ bool resolveHostByName(const char *aHostname, IPAddress& aResult, uint32_t timeo
// FIXME TD-er: Must try to restore DNS server entries.
scrubDNS();
#if defined(ARDUINO_ESP8266_RELEASE_2_3_0) || defined(ESP32)
bool resolvedIP = WiFi.hostByName(aHostname, aResult) == 1;
bool resolvedIP{};
String host(aHostname);
host.trim();
uint32_t start = millis();
for (int attempt = 0;
attempt < 2 && !resolvedIP && timePassedSince(start) < timeout_ms;
++attempt) {
#if defined(ARDUINO_ESP8266_RELEASE_2_3_0)
resolvedIP = WiFi.hostByName(host.c_str(), aResult) == 1;
#elif defined(ESP32)
resolvedIP = Network.hostByName(host.c_str(), aResult) == 1;
#else // if defined(ARDUINO_ESP8266_RELEASE_2_3_0) || defined(ESP32)
bool resolvedIP = WiFi.hostByName(aHostname, aResult, timeout_ms) == 1;
resolvedIP = WiFi.hostByName(host.c_str(), aResult, timeout_ms) == 1;
#endif // if defined(ARDUINO_ESP8266_RELEASE_2_3_0) || defined(ESP32)
delay(0);
FeedSW_watchdog();
if (!resolvedIP) {
if (!resolvedIP && attempt == 0) {
#ifdef ESP32
dns_clear_cache();
#endif
Scheduler.sendGratuitousARP_now();
}
}
STOP_TIMER(HOST_BY_NAME_STATS);
return resolvedIP;
}
+114 -72
View File
@@ -42,20 +42,18 @@
#ifdef USES_C015
#include "../../ESPEasy_fdwdecl.h"
# include "../../ESPEasy_fdwdecl.h"
#endif
#if FEATURE_MDNS
#include "../Helpers/MDNS_Helper.h"
# include "../Helpers/MDNS_Helper.h"
#endif
#define PLUGIN_ID_MQTT_IMPORT 37
/*********************************************************************************************\
* Tasks that run 50 times per second
* Tasks that run 50 times per second
\*********************************************************************************************/
void run50TimesPerSecond() {
String dummy;
{
@@ -63,18 +61,22 @@ void run50TimesPerSecond() {
// before any controller may need to use the network
#ifdef ESP32
static const NetworkInterface *lastDefaultInterface = nullptr;
NetworkInterface * currentDefaultInterface = Network.getDefaultInterface();
NetworkInterface *currentDefaultInterface = Network.getDefaultInterface();
if (nonDefaultNetworkInterface_gotIP ||
networkConnectionFailed ||
lastDefaultInterface != currentDefaultInterface) {
(lastDefaultInterface != currentDefaultInterface)) {
nonDefaultNetworkInterface_gotIP = false;
// TODO TD-er: Must do something else here on failed connect?
networkConnectionFailed = false;
if (lastDefaultInterface != currentDefaultInterface) {
ESPEasy::net::NWPluginCall(NWPlugin::Function::NWPLUGIN_PRIORITY_ROUTE_CHANGED, 0, dummy);
}
lastDefaultInterface = currentDefaultInterface;
}
#endif
#endif // ifdef ESP32
START_TIMER;
ESPEasy::net::NWPluginCall(NWPlugin::Function::NWPLUGIN_FIFTY_PER_SECOND, 0, dummy);
@@ -98,11 +100,12 @@ void run50TimesPerSecond() {
}
/*********************************************************************************************\
* Tasks that run 10 times per second
* Tasks that run 10 times per second
\*********************************************************************************************/
void run10TimesPerSecond() {
String dummy;
//@giig19767g: WARNING: Monitor10xSec must run before PLUGIN_TEN_PER_SECOND
// @giig19767g: WARNING: Monitor10xSec must run before PLUGIN_TEN_PER_SECOND
{
START_TIMER;
GPIO_Monitor10xSec();
@@ -120,7 +123,8 @@ void run10TimesPerSecond() {
}
{
START_TIMER;
// PluginCall(PLUGIN_UNCONDITIONAL_POLL, 0, dummyString);
// PluginCall(PLUGIN_UNCONDITIONAL_POLL, 0, dummyString);
PluginCall(PLUGIN_MONITOR, 0, dummy);
STOP_TIMER(PLUGIN_CALL_10PSU);
}
@@ -131,10 +135,12 @@ void run10TimesPerSecond() {
}
#ifdef USES_C015
if (ESPEasy::net::NetworkConnected()) {
Blynk_Run_c015();
}
#endif
#endif // ifdef USES_C015
if (!UseRTOSMultitasking &&
(ESPEasy::net::NetworkConnected() || ESPEasy::net::wifi::wifiAPmodeActivelyUsed())) {
// FIXME TD-er: What about client connected via AP?
@@ -144,20 +150,20 @@ void run10TimesPerSecond() {
}
}
/*********************************************************************************************\
* Tasks each second
* Tasks each second
\*********************************************************************************************/
void runOncePerSecond()
{
START_TIMER;
updateLogLevelCache();
dailyResetCounter++;
if (dailyResetCounter > 86400) // 1 day elapsed... //86400
{
RTC.flashDayCounter=0;
RTC.flashDayCounter = 0;
saveToRTC();
dailyResetCounter=0;
dailyResetCounter = 0;
#ifndef LIMIT_BUILD_SIZE
addLog(LOG_LEVEL_INFO, F("SYS : Reset 24h counters"));
#endif
@@ -165,9 +171,12 @@ void runOncePerSecond()
if (Settings.ConnectionFailuresThreshold) {
auto data = ESPEasy::net::getDefaultRoute_NWPluginData_static_runtime();
if (data && data->getConnectionFailures() > Settings.ConnectionFailuresThreshold)
if (data && (data->getConnectionFailures() > Settings.ConnectionFailuresThreshold)) {
delayedReboot(60, IntendedRebootReason_e::DelayedReboot);
}
}
if (cmd_within_mainloop != 0)
{
switch (cmd_within_mainloop)
@@ -185,10 +194,12 @@ void runOncePerSecond()
}
cmd_within_mainloop = 0;
}
// clock events
if (node_time.reportNewMinute()) {
String dummy;
PluginCall(PLUGIN_CLOCK_IN, 0, dummy);
if (Settings.UseRules)
{
// FIXME TD-er: What to do when the system time is not (yet) present?
@@ -203,12 +214,14 @@ void runOncePerSecond()
}
}
// uint32_t start = micros();
// uint32_t start = micros();
String dummy;
PluginCall(PLUGIN_ONCE_A_SECOND, 0, dummy);
// uint32_t elapsed = micros() - start;
// uint32_t elapsed = micros() - start;
#if FEATURE_NETWORK_STATS
for (ESPEasy::net::networkIndex_t x = 0; x < NETWORK_MAX; x++) {
if (Settings.getNetworkEnabled(x)) {
EventStruct tempEvent;
@@ -216,26 +229,28 @@ void runOncePerSecond()
ESPEasy::net::NWPluginCall(NWPlugin::Function::NWPLUGIN_RECORD_STATS, &tempEvent);
}
}
#endif
#endif // if FEATURE_NETWORK_STATS
// I2C Watchdog feed
#if FEATURE_I2C
if (Settings.WDI2CAddress != 0)
{
#if FEATURE_I2C_MULTIPLE
# if FEATURE_I2C_MULTIPLE
I2CSelectHighClockSpeed(Settings.getI2CInterfaceWDT()); // Select bus
#endif // if FEATURE_I2C_MULTIPLE
# endif // if FEATURE_I2C_MULTIPLE
I2C_write8(Settings.WDI2CAddress, 0xA5);
}
#endif
#endif // if FEATURE_I2C
#if FEATURE_MDNS
#ifdef ESP8266
# ifdef ESP8266
// Allow MDNS processing
if (ESPEasy::net::NetworkConnected()) {
MDNS.announce();
}
#endif
# endif // ifdef ESP8266
#endif // if FEATURE_MDNS
#if FEATURE_INTERNAL_TEMPERATURE && defined(ESP32_CLASSIC)
@@ -247,16 +262,17 @@ void runOncePerSecond()
}
/*********************************************************************************************\
* Tasks each 30 seconds
* Tasks each 30 seconds
\*********************************************************************************************/
void runEach30Seconds()
{
#ifndef BUILD_NO_RAM_TRACKER
checkRAMtoLog();
#endif
wdcounter++;
if (loglevelActiveFor(LOG_LEVEL_INFO)) {
auto data = ESPEasy::net::getDefaultRoute_NWPluginData_static_runtime();
if (!data) {
addLogMove(LOG_LEVEL_INFO, strformat(
F("WD : Uptime %d FreeMem %u"),
@@ -270,14 +286,17 @@ void runEach30Seconds()
FreeMem());
bool logWiFiStatus = true;
#if FEATURE_ETHERNET
if(active_network_medium == ESPEasy::net::NetworkMedium_t::Ethernet) {
if (active_network_medium == ESPEasy::net::NetworkMedium_t::Ethernet) {
logWiFiStatus = false;
log += F( " EthSpeedState ");
log += F(" EthSpeedState ");
log += getValue(LabelType::ETH_SPEED_STATE);
// log += F(" ETH status: ");
// log += EthEventData.ESPEasyEthStatusToString();
// log += F(" ETH status: ");
// log += EthEventData.ESPEasyEthStatusToString();
}
#endif // if FEATURE_ETHERNET
if (logWiFiStatus) {
log += strformat(
F(" WiFiStatus: %s ESPeasy internal wifi status: %s (%s)"),
@@ -285,35 +304,41 @@ void runEach30Seconds()
FsP(ESPEasy::net::wifi::toString(ESPEasyWiFi.getState())),
data->statusToString().c_str());
}
// log += F(" ListenInterval ");
// log += WiFi.getListenInterval();
addLogMove(LOG_LEVEL_INFO, log);
#if FEATURE_DEFINE_SERIAL_CONSOLE_PORT
// addLogMove(LOG_LEVEL_INFO, ESPEASY_SERIAL_CONSOLE_PORT.getLogString());
#endif
#endif // if FEATURE_DEFINE_SERIAL_CONSOLE_PORT
}
}
ESPEasy::net::wifi::WiFi_AP_Candidates.purge_expired();
#if FEATURE_ESPEASY_P2P
sendSysInfoUDP(1);
refreshNodeList();
#endif
#endif // if FEATURE_ESPEASY_P2P
// sending $stats to homie controller
CPluginCall(CPlugin::Function::CPLUGIN_INTERVAL, 0);
#if defined(ESP8266)
#if FEATURE_SSDP
if (Settings.UseSSDP)
SSDP_update();
# if FEATURE_SSDP
#endif // if FEATURE_SSDP
#endif
if (Settings.UseSSDP) {
SSDP_update();
}
# endif // if FEATURE_SSDP
#endif // if defined(ESP8266)
#if FEATURE_ADC_VCC
// if (!WiFiEventData.wifiConnectInProgress) {
// if (!WiFiEventData.wifiConnectInProgress) {
vcc = ESP.getVcc() / 1000.0f;
// }
#endif
// }
#endif // if FEATURE_ADC_VCC
#if FEATURE_REPORTING
ReportStatus();
@@ -323,7 +348,6 @@ void runEach30Seconds()
#if FEATURE_MQTT
void scheduleNextMQTTdelayQueue() {
if (MQTTDelayHandler != nullptr) {
Scheduler.scheduleNextDelayQueue(SchedulerIntervalTimer_e::TIMER_MQTT_DELAY_QUEUE, MQTTDelayHandler->getNextScheduleTime());
@@ -334,6 +358,7 @@ void schedule_all_MQTTimport_tasks() {
constexpr pluginID_t PLUGIN_MQTT_IMPORT(PLUGIN_ID_MQTT_IMPORT);
deviceIndex_t DeviceIndex = getDeviceIndex(PLUGIN_MQTT_IMPORT); // Check if P037_MQTTimport is present in the build
if (validDeviceIndex(DeviceIndex)) {
for (taskIndex_t task = 0; task < TASKS_MAX; task++) {
if ((Settings.getPluginID_for_task(task) == PLUGIN_MQTT_IMPORT) &&
@@ -355,6 +380,7 @@ void processMQTTdelayQueue() {
return;
}
runPeriodicalMQTT(); // Update MQTT connected state.
if (!MQTTclient_connected) {
scheduleNextMQTTdelayQueue();
return;
@@ -372,8 +398,8 @@ void processMQTTdelayQueue() {
String dummy;
// FIXME TD-er: Do we need anything from the element in the event?
// TempEvent.String1 = element->_topic;
// TempEvent.String2 = element->_payload;
// TempEvent.String1 = element->_topic;
// TempEvent.String2 = element->_payload;
if (PluginCall(PLUGIN_PROCESS_CONTROLLER_DATA, &TempEvent, dummy)) {
handled = true;
MQTTDelayHandler->markProcessed(true);
@@ -384,13 +410,14 @@ void processMQTTdelayQueue() {
if (!handled) {
if (MQTTclient.publish(element->_topic.c_str(), element->_payload.c_str(), element->_retained)) {
auto data = ESPEasy::net::getDefaultRoute_NWPluginData_static_runtime();
if (data) {
data->markPublishSuccess();
}
MQTTDelayHandler->markProcessed(true);
} else {
MQTTDelayHandler->markProcessed(false);
#ifndef BUILD_NO_DEBUG
# ifndef BUILD_NO_DEBUG
if (loglevelActiveFor(LOG_LEVEL_DEBUG)) {
String log = F("MQTT : process MQTT queue not published, ");
@@ -398,18 +425,21 @@ void processMQTTdelayQueue() {
log += F(" items left in queue");
addLogMove(LOG_LEVEL_DEBUG, log);
}
#endif // ifndef BUILD_NO_DEBUG
# endif // ifndef BUILD_NO_DEBUG
}
}
Scheduler.setIntervalTimerOverride(SchedulerIntervalTimer_e::TIMER_MQTT, 10); // Make sure the MQTT is being processed as soon as possible.
Scheduler.setIntervalTimerOverride(SchedulerIntervalTimer_e::TIMER_MQTT, 10); // Make sure the MQTT is being processed as soon as
// possible.
scheduleNextMQTTdelayQueue();
STOP_TIMER(MQTT_DELAY_QUEUE);
}
void updateMQTTclient_connected() {
const bool actual_MQTTclient_connected = ESPEasy::net::NetworkConnected(true) && MQTTclient.connected();
if (MQTTclient_connected != actual_MQTTclient_connected) {
MQTTclient_connected = actual_MQTTclient_connected;
if (!actual_MQTTclient_connected) {
// Make sure PubSubClient isn't trying to do a graceful disconnect
// FIXME TD-er: This seems to cause a crash on ESP32-xx, though no idea how to fix.
@@ -417,21 +447,24 @@ void updateMQTTclient_connected() {
mqtt.stop();
}
MQTTclient_connected_stats.set(actual_MQTTclient_connected);
if (!MQTTclient_connected) {
if (loglevelActiveFor(LOG_LEVEL_ERROR)) {
String connectionError = F("MQTT : Connection lost, state: ");
connectionError += getMQTT_state();
#ifndef BUILD_NO_DEBUG
# ifndef BUILD_NO_DEBUG
auto duration_ms = MQTTclient_connected_stats.getLastOnDuration_ms();
if (duration_ms > 0) {
connectionError += concat(F(" Connected duration: "), format_msec_duration_HMS(duration_ms));
connectionError += concat(F(" (successful) Reconnect Count: "), MQTTclient_connected_stats.getCycleCount());
}
#endif
# endif // ifndef BUILD_NO_DEBUG
addLogMove(LOG_LEVEL_ERROR, connectionError);
}
MQTTclient_must_send_LWT_connected = false;
}
if (Settings.UseRules) {
if (MQTTclient_connected) {
eventQueue.add(F("MQTT#Connected"));
@@ -439,9 +472,11 @@ void updateMQTTclient_connected() {
eventQueue.add(F("MQTT#Disconnected"));
}
}
// Now schedule all tasks using the MQTT Import plugin.
schedule_all_MQTTimport_tasks();
}
if (!MQTTclient_connected) {
// As suggested here: https://github.com/letscontrolit/ESPEasy/issues/1356
if (timermqtt_interval < 30000) {
@@ -452,36 +487,41 @@ void updateMQTTclient_connected() {
}
Scheduler.setIntervalTimer(SchedulerIntervalTimer_e::TIMER_MQTT);
scheduleNextMQTTdelayQueue();
#if FEATURE_MQTT_CONNECT_BACKGROUND
# if FEATURE_MQTT_CONNECT_BACKGROUND
MQTTConnectInBackground(CONTROLLER_MAX, true); // Report state
#endif // if FEATURE_MQTT_CONNECT_BACKGROUND
# endif // if FEATURE_MQTT_CONNECT_BACKGROUND
}
void runPeriodicalMQTT() {
START_TIMER
// MQTT_KEEPALIVE = 15 seconds.
if (!ESPEasy::net::NetworkConnected()) {
updateMQTTclient_connected();
return;
}
//dont do this in backgroundtasks(), otherwise causes crashes. (https://github.com/letscontrolit/ESPEasy/issues/683)
// dont do this in backgroundtasks(), otherwise causes crashes. (https://github.com/letscontrolit/ESPEasy/issues/683)
controllerIndex_t enabledMqttController = firstEnabledMQTT_ControllerIndex();
if (validControllerIndex(enabledMqttController)) {
if (!MQTTclient.loop()) {
updateMQTTclient_connected();
if (MQTTCheck(enabledMqttController)) {
updateMQTTclient_connected();
}
}
} else {
if (MQTTclient.connected()) {
#if FEATURE_MQTT_CONNECT_BACKGROUND
# if FEATURE_MQTT_CONNECT_BACKGROUND
if (MQTT_task_data.taskHandle) {
vTaskDelete(MQTT_task_data.taskHandle);
MQTT_task_data.taskHandle = NULL;
}
MQTT_task_data.status = MQTT_connect_status_e::Disconnected;
#endif // if FEATURE_MQTT_CONNECT_BACKGROUND
# endif // if FEATURE_MQTT_CONNECT_BACKGROUND
MQTTclient.disconnect();
updateMQTTclient_connected();
}
@@ -489,21 +529,23 @@ void runPeriodicalMQTT() {
STOP_TIMER(PERIODICAL_MQTT);
}
#endif //if FEATURE_MQTT
#endif // if FEATURE_MQTT
void logTimerStatistics() {
// This function is called every 30 seconds.
wdcounter++;
loopCounterLast = loopCounter;
loopCounter = 0;
if (loopCounterLast > loopCounterMax)
if (loopCounterLast > loopCounterMax) {
loopCounterMax = loopCounterLast;
}
Scheduler.updateIdleTimeStats();
#ifndef BUILD_NO_DEBUG
const uint8_t loglevel = LOG_LEVEL_DEBUG;
if (loglevelActiveFor(loglevel)) {
addLogMove(loglevel, strformat(
F("LoopStats: shortest: %u longest: %u avg: %.2f LC_Max: %u LC_Last: %u"),
@@ -516,13 +558,11 @@ void logTimerStatistics() {
F("Scheduler stats: (called/tasks/max_length/idle%) "),
Scheduler.getQueueStats()));
}
#endif
#endif // ifndef BUILD_NO_DEBUG
loop_usec_duration_total = 0;
loopCounter_full = 1;
}
/********************************************************************************************\
Clean up all before going to sleep or reboot.
\*********************************************************************************************/
@@ -530,30 +570,34 @@ void flushAndDisconnectAllClients() {
if (anyControllerEnabled()) {
#if FEATURE_MQTT
bool mqttControllerEnabled = validControllerIndex(firstEnabledMQTT_ControllerIndex());
#endif //if FEATURE_MQTT
#endif // if FEATURE_MQTT
uint32_t timer = millis() + 1000;
while (!timeOutReached(timer)) {
// call to all controllers (delay queue) to flush all data.
CPluginCall(CPlugin::Function::CPLUGIN_FLUSH, 0);
#if FEATURE_MQTT
if (mqttControllerEnabled && MQTTclient.connected()) {
MQTTclient.loop();
}
#endif //if FEATURE_MQTT
#endif // if FEATURE_MQTT
}
#if FEATURE_MQTT
if (mqttControllerEnabled && MQTTclient.connected()) {
#if FEATURE_MQTT_CONNECT_BACKGROUND
# if FEATURE_MQTT_CONNECT_BACKGROUND
if (MQTT_task_data.taskHandle) {
vTaskDelete(MQTT_task_data.taskHandle);
MQTT_task_data.taskHandle = NULL;
}
MQTT_task_data.status = MQTT_connect_status_e::Disconnected;
#endif // if FEATURE_MQTT_CONNECT_BACKGROUND
# endif // if FEATURE_MQTT_CONNECT_BACKGROUND
MQTTclient.disconnect();
updateMQTTclient_connected();
}
#endif //if FEATURE_MQTT
#endif // if FEATURE_MQTT
saveToRTC();
delay(100); // Flush anything in the network buffers.
}
@@ -561,14 +605,13 @@ void flushAndDisconnectAllClients() {
process_serialWriteBuffer();
}
void prepareShutdown(IntendedRebootReason_e reason)
{
#if FEATURE_MDNS
end_mDNS();
#endif
// WiFiEventData.intent_to_reboot = true;
// WiFiEventData.intent_to_reboot = true;
#if FEATURE_MQTT
runPeriodicalMQTT(); // Flush outstanding MQTT messages
#endif // if FEATURE_MQTT
@@ -577,7 +620,8 @@ void prepareShutdown(IntendedRebootReason_e reason)
saveUserVarToRTC();
CPluginCall(CPlugin::Function::CPLUGIN_EXIT_ALL, 0);
ESPEasy::net::NWPluginCall(NWPlugin::Function::NWPLUGIN_EXIT_ALL, 0);
// ESPEasy::net::wifi::setWifiMode(WIFI_OFF);
// ESPEasy::net::wifi::setWifiMode(WIFI_OFF);
ESPEASY_FS.end();
process_serialWriteBuffer();
delay(100); // give the node time to flush all before reboot or sleep
@@ -585,5 +629,3 @@ void prepareShutdown(IntendedRebootReason_e reason)
Scheduler.markIntendedReboot(reason);
saveToRTC();
}
@@ -141,6 +141,7 @@ void ESPEasy_Scheduler::setIntervalTimer(SchedulerIntervalTimer_e intervalTimer,
}
void ESPEasy_Scheduler::sendGratuitousARP_now() {
if (!ESPEasy::net::NetworkConnected(true)) return;
sendGratuitousARP();
if (Settings.gratuitousARP()) {