Merge branch 'development' into development

This commit is contained in:
Theo Arends 2020-04-18 15:17:39 +02:00 committed by GitHub
commit 7dc0b153c4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
46 changed files with 1362 additions and 926 deletions

View File

@ -52,7 +52,7 @@ The following binary downloads have been compiled with ESP8266/Arduino library c
## Changelog
### Version 8.2.0.3
### Version 8.2.0.4
- Change HM-10 sensor type detection and add features (#7962)
- Change light scheme 2,3,4 cycle time speed from 24,48,72,... seconds to 4,6,12,24,36,48,... seconds (#8034)

View File

@ -20,18 +20,44 @@
#include <rom/rtc.h>
#include <ESP8266WiFi.h>
#include "esp8266toEsp32.h"
// ESP Stuff
struct rst_info resetInfo;
String ESP32GetResetReason(uint32_t cpu_no)
{
// tools\sdk\include\esp32\rom\rtc.h
switch (rtc_get_reset_reason( (RESET_REASON) cpu_no)) {
case POWERON_RESET : return F("Vbat power on reset"); // 1
case SW_RESET : return F("Software reset digital core"); // 3
case OWDT_RESET : return F("Legacy watch dog reset digital core"); // 4
case DEEPSLEEP_RESET : return F("Deep Sleep reset digital core"); // 5
case SDIO_RESET : return F("Reset by SLC module, reset digital core"); // 6
case TG0WDT_SYS_RESET : return F("Timer Group0 Watch dog reset digital core"); // 7
case TG1WDT_SYS_RESET : return F("Timer Group1 Watch dog reset digital core"); // 8
case RTCWDT_SYS_RESET : return F("RTC Watch dog Reset digital core"); // 9
case INTRUSION_RESET : return F("Instrusion tested to reset CPU"); // 10
case TGWDT_CPU_RESET : return F("Time Group reset CPU"); // 11
case SW_CPU_RESET : return F("Software reset CPU"); // 12
case RTCWDT_CPU_RESET : return F("RTC Watch dog Reset CPU"); // 13
case EXT_CPU_RESET : return F("or APP CPU, reseted by PRO CPU"); // 14
case RTCWDT_BROWN_OUT_RESET : return F("Reset when the vdd voltage is not stable"); // 15
case RTCWDT_RTC_RESET : return F("RTC Watch dog reset digital core and rtc module"); // 16
default : return F("NO_MEAN"); // 0
}
}
String ESP_getResetReason(void)
{
// CPU 0
return String(rtc_get_reset_reason(0));
return ESP32GetResetReason(0); // CPU 0
}
String ESP_getResetInfo(void)
uint32_t ESP_ResetInfoReason(void)
{
return String(PSTR("0"));
RESET_REASON reason = rtc_get_reset_reason(0);
if (POWERON_RESET == reason) { return REASON_DEFAULT_RST; }
if (SW_CPU_RESET == reason) { return REASON_SOFT_RESTART; }
if (DEEPSLEEP_RESET == reason) { return REASON_DEEP_SLEEP_AWAKE; }
if (SW_RESET == reason) { return REASON_EXT_SYS_RST; }
}
uint32_t ESP_getBootVersion(void)
@ -74,11 +100,6 @@ String String_ESP_getChipId()
return String(uint32_t(mac >> 32)) + String(uint32_t(mac));
}
uint32_t ESP_getFlashChipRealSize()
{
return ESP.getFlashChipSize();
}
uint32_t ESP_getSketchSize(void)
{
static uint32_t sketchsize = 0;
@ -88,3 +109,12 @@ uint32_t ESP_getSketchSize(void)
}
return sketchsize;
}
#include "soc/soc.h"
#include "soc/rtc_cntl_reg.h"
void DisableBrownout(void)
{
// https://github.com/espressif/arduino-esp32/issues/863#issuecomment-347179737
WRITE_PERI_REG(RTC_CNTL_BROWN_OUT_REG, 0); // Disable brownout detector
}

View File

@ -34,16 +34,16 @@
#define ESP_flashReadHeader(offset, data, size) ESP32_flashRead(offset, data, size)
#define ESP_flashRead(offset, data, size) ESP32_flashRead(offset, data, size)
String ESP_getResetReason(void);
uint32_t ESP_ResetInfoReason(void);
uint32_t ESP_getBootVersion(void);
bool ESP_rtcUserMemoryWrite(uint32_t offset, uint32_t *data, size_t size);
bool ESP_rtcUserMemoryRead(uint32_t offset, uint32_t *data, size_t size);
void ESP_reset();
String ESP_getResetInfo(void);
uint32_t ESP_getFlashChipId();
uint32_t ESP_getChipId();
String String_ESP_getChipId();
uint32_t ESP_getFlashChipRealSize();
uint32_t ESP_getSketchSize();
void DisableBrownout(void);
// Analog
inline void analogWrite(uint8_t pin, int val)
@ -67,7 +67,6 @@ typedef double real64_t;
#define ETS_UART_INTR_DISABLE()
#define ETS_UART_INTR_ENABLE()
#define getChipId() getEfuseMac()
#define ESPhttpUpdate httpUpdate
#define getFlashChipRealSize() getFlashChipSize()
@ -92,14 +91,13 @@ typedef int SerialConfig;
#undef LWIP_IPV6
struct rst_info
{
int reason;
};
#define REASON_DEFAULT_RST 1
#define REASON_EXT_SYS_RST 2
#define REASON_DEEP_SLEEP_AWAKE 3
#define REASON_DEFAULT_RST 0 // "Power on" normal startup by power on
#define REASON_WDT_RST 1 // "Hardware Watchdog" hardware watch dog reset
#define REASON_EXCEPTION_RST 2 // "Exception" exception reset, GPIO status wont change
#define REASON_SOFT_WDT_RST 3 // "Software Watchdog" software watch dog reset, GPIO status wont change
#define REASON_SOFT_RESTART 4 // "Software/System restart" software restart ,system_restart , GPIO status wont change
#define REASON_DEEP_SLEEP_AWAKE 5 // "Deep-Sleep Wake" wake up from deep-sleep
#define REASON_EXT_SYS_RST 6 // "External System" external system reset
// memmove ...
#define memcpy_P memcpy

View File

@ -28,6 +28,7 @@ def bin_map_copy(source, target, env):
shutil.copy(str(target[0]), bin_file)
# copy firmware.map to map/<variant>.map
shutil.copy("firmware.map", map_file)
if os.path.isfile("firmware.map"):
shutil.move("firmware.map", map_file)
env.AddPostAction("$BUILD_DIR/${PROGNAME}.bin", [bin_map_copy])

View File

@ -87,17 +87,21 @@ extra_scripts = pio/strip-floats.py
pio/name-firmware.py
pio/gzip-firmware.py
[esp82xx_defaults]
build_flags = -D NDEBUG
-mtarget-align
-Wl,-Map,firmware.map
-DFP_IN_IROM
; new mechanism to set the IRremoteESP8266 supported protocols: none except HASH, NEC, RC5, RC6
-D_IR_ENABLE_DEFAULT_=false
[esp_defaults]
build_flags = -D_IR_ENABLE_DEFAULT_=false
-DDECODE_HASH=true -DDECODE_NEC=true -DSEND_NEC=true
-DDECODE_RC5=true -DSEND_RC5=true -DDECODE_RC6=true -DSEND_RC6=true
; new mechanism to set the IRremoteESP8266 supported protocols: none except HASH, NEC, RC5, RC6
[irremoteesp8266_full]
[esp82xx_defaults]
build_flags = ${esp_defaults.build_flags}
-Wl,-Map,firmware.map
-D NDEBUG
-mtarget-align
-DFP_IN_IROM
[irremoteesp_full]
build_flags = -DUSE_IR_REMOTE_FULL
-U_IR_ENABLE_DEFAULT_
-DDECODE_PRONTO=false -DSEND_PRONTO=false

View File

@ -12,6 +12,7 @@
[platformio]
extra_configs = platformio_tasmota_env32.ini
platformio_tasmota_cenv.ini
; *** Build/upload environment
default_envs =
@ -54,7 +55,7 @@ build_flags = ${core_active.build_flags}
upload_port = COM5
extra_scripts = ${scripts_defaults.extra_scripts}
pio/obj-dump.py
; pio/obj-dump.py
; *** Upload file to OTA server using SCP
;upload_port = user@host:/path
@ -227,7 +228,7 @@ build_type = debug
[common32]
platform = espressif32@1.12.0
platform_packages =
platform_packages = tool-esptoolpy@1.20800.0
board = wemos_d1_mini32
board_build.ldscript = esp32_out.ld
board_build.partitions = esp32_partition_app1984k_spiffs64k.csv
@ -240,7 +241,7 @@ upload_resetmethod = ${common.upload_resetmethod}
upload_speed = 921600
extra_scripts = ${common.extra_scripts}
build_flags =
build_flags = ${esp_defaults.build_flags}
-D BUFFER_LENGTH=128
-D MQTT_MAX_PACKET_SIZE=1200
-D uint32=uint32_t

View File

@ -32,10 +32,10 @@ build_flags = ${common.build_flags} -DFIRMWARE_SENSORS
build_flags = ${common.build_flags} -DFIRMWARE_DISPLAYS
[env:tasmota-ir]
build_flags = ${common.build_flags} ${irremoteesp8266_full.build_flags} -DFIRMWARE_IR
build_flags = ${common.build_flags} ${irremoteesp_full.build_flags} -DFIRMWARE_IR
[env:tasmota-ircustom]
build_flags = ${common.build_flags} ${irremoteesp8266_full.build_flags}
build_flags = ${common.build_flags} ${irremoteesp_full.build_flags}
[env:tasmota-BG]
build_flags = ${common.build_flags} -DMY_LANGUAGE=bg-BG

View File

@ -129,7 +129,7 @@ extra_scripts = ${common32.extra_scripts}
lib_extra_dirs = ${common32.lib_extra_dirs}
lib_ignore = ${common32.lib_ignore}
build_unflags = ${common32.build_unflags}
build_flags = ${common32.build_flags} ${irremoteesp8266_full.build_flags} -DFIRMWARE_IR
build_flags = ${common32.build_flags} ${irremoteesp_full.build_flags} -DFIRMWARE_IR
[env:tasmota32-ircustom]
framework = ${common.framework}
@ -148,7 +148,7 @@ extra_scripts = ${common32.extra_scripts}
lib_extra_dirs = ${common32.lib_extra_dirs}
lib_ignore = ${common32.lib_ignore}
build_unflags = ${common32.build_unflags}
build_flags = ${common32.build_flags} ${irremoteesp8266_full.build_flags}
build_flags = ${common32.build_flags} ${irremoteesp_full.build_flags}
[env:tasmota32-BG]
framework = ${common.framework}

View File

@ -1,5 +1,10 @@
## Unreleased (development)
### 8.2.0.4 20200417
- Add config version tag
- Fix Zigbee DimmerUp/DimmerDown malformed
### 8.2.0.3 20200329
- Change light scheme 2,3,4 cycle time speed from 24,48,72,... seconds to 4,6,12,24,36,48,... seconds (#8034)

View File

@ -19,6 +19,8 @@
Modified 8 May 2015 by Hristo Gochkov (proper post and file upload handling)
*/
#ifdef ESP8266
// Use patched Parsing.cpp to fix ALEXA parsing issue in v2.4.2
#include <core_version.h>
#if defined(ARDUINO_ESP8266_RELEASE_2_4_2)
@ -620,4 +622,6 @@ bool ESP8266WebServer::_parseFormUploadAborted(){
return false;
}
#endif // ARDUINO_ESP8266_RELEASE
#endif // ARDUINO_ESP8266_RELEASE
#endif // ESP8266

View File

@ -297,6 +297,7 @@
#define D_CMND_DEVGROUP_NAME "DevGroupName"
#define D_CMND_DEVGROUP_SEND "DevGroupSend"
#define D_CMND_DEVGROUP_SHARE "DevGroupShare"
#define D_CMND_DEVGROUPSTATUS "DevGroupStatus"
#define D_CMND_SERIALSEND "SerialSend"
#define D_CMND_SERIALDELIMITER "SerialDelimiter"
#define D_CMND_BAUDRATE "Baudrate"

View File

@ -567,8 +567,8 @@
#define D_SENSOR_SPI_MOSI "SPI - MOSI"
#define D_SENSOR_SPI_CLK "SPI - CLK"
#define D_SENSOR_BACKLIGHT "Retroilluminazione"
#define D_SENSOR_PMS5003_TX "PMS5003 Tx"
#define D_SENSOR_PMS5003_RX "PMS5003 Rx"
#define D_SENSOR_PMS5003_TX "PMS5003 - TX"
#define D_SENSOR_PMS5003_RX "PMS5003 - RX"
#define D_SENSOR_SDS0X1_RX "SDS0X1 - RX"
#define D_SENSOR_SDS0X1_TX "SDS0X1 - TX"
#define D_SENSOR_HPMA_RX "HPMA - RX"

View File

@ -391,7 +391,7 @@
#define SUNRISE_DAWN_ANGLE DAWN_NORMAL // Select desired Dawn Angle from (DAWN_NORMAL, DAWN_CIVIL, DAWN_NAUTIC, DAWN_ASTRONOMIC)
// -- Ping ----------------------------------------
// #define USE_PING // Enable Ping command (+3k code)
// #define USE_PING // Enable Ping command (+2k code)
// -- Rules or Script ----------------------------
// Select none or only one of the below defines

View File

@ -86,7 +86,7 @@ typedef union { // Restricted by MISRA-C Rule 18.4 bu
uint32_t energy_weekend : 1; // bit 20 (v6.6.0.8) - CMND_TARIFF
uint32_t dds2382_model : 1; // bit 21 (v6.6.0.14) - SetOption71 - Select different Modbus registers for Active Energy (#6531)
uint32_t hardware_energy_total : 1; // bit 22 (v6.6.0.15) - SetOption72 - Enable hardware energy total counter as reference (#6561)
uint32_t mqtt_buttons : 1; // bit 23 (v8.2.0.3) - SetOption73 - Detach buttons from relays and enable MQTT action state for multipress
uint32_t mqtt_buttons : 1; // bit 23 (v8.2.0.3) - SetOption73 - Detach buttons from relays and enable MQTT action state for multipress
uint32_t ds18x20_internal_pullup : 1; // bit 24 (v7.0.0.1) - SetOption74 - Enable internal pullup for single DS18x20 sensor
uint32_t grouptopic_mode : 1; // bit 25 (v7.0.0.1) - SetOption75 - GroupTopic replaces %topic% (0) or fixed topic cmnd/grouptopic (1)
uint32_t bootcount_update : 1; // bit 26 (v7.0.0.4) - SetOption76 - Enable incrementing bootcount when deepsleep is enabled
@ -245,7 +245,7 @@ typedef struct {
} EnergyUsage;
typedef struct PACKED {
typedef struct {
uint8_t fnid = 0;
uint8_t dpid = 0;
} TuyaFnidDpidMap;
@ -253,7 +253,7 @@ typedef struct PACKED {
const uint32_t settings_text_size = 699; // Settings.text_pool[size] = Settings.display_model (2D2) - Settings.text_pool (017)
const uint8_t MAX_TUYA_FUNCTIONS = 16;
struct PACKED SYSCFG {
struct SYSCFG {
uint16_t cfg_holder; // 000 v6 header
uint16_t cfg_size; // 002
unsigned long save_flag; // 004
@ -369,7 +369,13 @@ struct PACKED SYSCFG {
uint8_t module; // 474
uint8_t ws_color[4][3]; // 475
uint8_t ws_width[3]; // 481
myio my_gp; // 484
#ifdef ESP8266
myio my_gp; // 484 - 17 bytes (ESP8266)
#else // ESP32
uint8_t free_esp32_484[17]; // 484
#endif // ESP8266 - ESP32
uint8_t my_adc0; // 495
uint16_t light_pixels; // 496
uint8_t light_color[5]; // 498
@ -397,7 +403,14 @@ struct PACKED SYSCFG {
uint32_t ip_address[4]; // 544
unsigned long energy_kWhtotal; // 554
#ifdef ESP8266
char ex_mqtt_fulltopic[100]; // 558
#else // ESP32
myio my_gp; // 558 - 40 bytes (ESP32)
mytmplt user_template; // 580 - 35 bytes (ESP32)
uint8_t free_esp32_5a3[25]; // 5A3
#endif // ESP8266 - ESP32
SysBitfield2 flag2; // 5BC
unsigned long pulse_counter[MAX_COUNTERS]; // 5C0
@ -423,7 +436,12 @@ struct PACKED SYSCFG {
char user_template_name[15]; // 720 15 bytes - Backward compatibility since v8.2.0.3
mytmplt user_template; // 72F 14 bytes
#ifdef ESP8266
mytmplt user_template; // 72F 14 bytes (ESP8266)
#else // ESP32
uint8_t free_esp32_72f[14]; // 72F
#endif // ESP8266 - ESP32
uint8_t novasds_startingoffset; // 73D
uint8_t web_color[18][3]; // 73E
uint16_t display_width; // 774
@ -506,9 +524,11 @@ struct PACKED SYSCFG {
uint8_t zb_channel; // F32
uint8_t zb_free_byte; // F33
uint16_t pms_wake_interval; // F34
uint8_t config_version; // F36
uint8_t free_f36[130]; // F36
uint8_t free_f37[129]; // F37 - Decrement if adding new Setting variables just above and below
// Only 32 bit boundary variables below
uint16_t pulse_counter_debounce_low; // FB8
uint16_t pulse_counter_debounce_high; // FBA
uint32_t keeloq_master_msb; // FBC

View File

@ -1337,6 +1337,15 @@ void SettingsDelta(void)
}
#endif // ESP8266
if (Settings.version < 0x08020004) {
#ifdef ESP8266
Settings.config_version = 0; // ESP8266 (Has been 0 for long time)
#endif // ESP8266
#ifdef ESP32
Settings.config_version = 1; // ESP32
#endif // ESP32
}
Settings.version = VERSION;
SettingsSave(1);
}

View File

@ -99,7 +99,11 @@ uint32_t ResetReason(void)
REASON_DEEP_SLEEP_AWAKE = 5, // "Deep-Sleep Wake" wake up from deep-sleep
REASON_EXT_SYS_RST = 6 // "External System" external system reset
*/
#ifdef ESP8266
return resetInfo.reason;
#else
return ESP_ResetInfoReason();
#endif
}
String GetResetReason(void)
@ -1127,7 +1131,11 @@ void ModuleGpios(myio *gp)
if (USER_MODULE == Settings.module) {
memcpy(&src, &Settings.user_template.gp, sizeof(mycfgio));
} else {
#ifdef ESP8266
memcpy_P(&src, &kModules[Settings.module].gp, sizeof(mycfgio));
#else // ESP32
memcpy_P(&src, &kModules.gp, sizeof(mycfgio));
#endif // ESP8266 - ESP32
}
// 11 85 00 85 85 00 00 00 15 38 85 00 00 81
@ -1138,10 +1146,9 @@ void ModuleGpios(myio *gp)
#ifdef ESP8266
if (6 == i) { j = 9; }
if (8 == i) { j = 12; }
#endif // ESP8266
#ifdef ESP32
#else // ESP32
if (6 == i) { j = 12; }
#endif // ESP32
#endif // ESP8266 - ESP32
dest[j] = src[i];
j++;
}
@ -1154,11 +1161,24 @@ gpio_flag ModuleFlag(void)
{
gpio_flag flag;
#ifdef ESP8266
if (USER_MODULE == Settings.module) {
flag = Settings.user_template.flag;
} else {
memcpy_P(&flag, &kModules[Settings.module].flag, sizeof(gpio_flag));
}
#else // ESP32
if (USER_MODULE == Settings.module) {
/*
gpio_flag gpio_adc0;
memcpy_P(&gpio_adc0, &Settings.user_template.gp + ADC0_PIN - MIN_FLASH_PINS, sizeof(gpio_flag));
flag = Settings.user_template.flag.data + gpio_adc0.data;
*/
memcpy_P(&flag, &Settings.user_template.gp + ADC0_PIN - MIN_FLASH_PINS, sizeof(gpio_flag));
} else {
memcpy_P(&flag, &kModules.gp + ADC0_PIN - MIN_FLASH_PINS, sizeof(gpio_flag));
}
#endif // ESP8266 - ESP32
return flag;
}
@ -1169,7 +1189,11 @@ void ModuleDefault(uint32_t module)
Settings.user_template_base = module;
char name[TOPSZ];
SettingsUpdateText(SET_TEMPLATE_NAME, GetTextIndexed(name, sizeof(name), module, kModuleNames));
#ifdef ESP8266
memcpy_P(&Settings.user_template, &kModules[module], sizeof(mytmplt));
#else // ESP32
memcpy_P(&Settings.user_template, &kModules, sizeof(mytmplt));
#endif // ESP8266 - ESP32
}
void SetModuleType(void)

View File

@ -1,7 +1,7 @@
/*
support_button.ino - button support for Tasmota
support_button_v2.ino - button support for Tasmota
Copyright (C) 2020 Theo Arends
Copyright (C) 2020 Federico Leoni and Theo Arends
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -23,12 +23,8 @@
* Button support
\*********************************************************************************************/
#define MAX_BUTTON_COMMANDS_V2 3 // Max number of button commands supported
#define MAX_RELAY_BUTTON1 4 // Max number of relay controlled by button1
const char kCommands[] PROGMEM =
D_CMND_WIFICONFIG " 2|" D_CMND_RESTART " 1|" D_CMND_UPGRADE " 1";
//D_CMND_WIFICONFIG " 2|" D_CMND_WIFICONFIG " 2|" D_CMND_WIFICONFIG " 2|" D_CMND_RESTART " 1|" D_CMND_UPGRADE " 1";
const char kMultiPress[] PROGMEM =
"|SINGLE|DOUBLE|TRIPLE|QUAD|PENTA|";
@ -107,7 +103,6 @@ uint8_t ButtonSerial(uint8_t serial_in_byte)
* SetOption11 (0) - If set perform single press action on double press and reverse
* SetOption13 (0) - If set act on single press only
* SetOption32 (40) - Max button hold time in Seconds
* SetOption40 (0) - Number of 0.1 seconds until hold is discarded if SetOption1 1 and SetOption13 0
* SetOption73 (0) - Decouple button from relay and send just mqtt topic
\*********************************************************************************************/
@ -177,16 +172,19 @@ void ButtonHandler(void)
if (!Button.hold_timer[button_index]) { button_pressed = true; } // Do not allow within 1 second
}
if (button_pressed) {
if (!SendKey(KEY_BUTTON, button_index +1, POWER_TOGGLE)) { // Execute Toggle command via MQTT if ButtonTopic is set
ExecuteCommandPower(button_index +1, POWER_TOGGLE, SRC_BUTTON); // Execute Toggle command internally
}
if (!Settings.flag3.mqtt_buttons) {
if (!SendKey(KEY_BUTTON, button_index +1, POWER_TOGGLE)) { // Execute Toggle command via MQTT if ButtonTopic is set
ExecuteCommandPower(button_index +1, POWER_TOGGLE, SRC_BUTTON); // Execute Toggle command internally
} else {
MqttButtonTopic(button_index +1, 1, 0); // SetOption73 (0) - Decouple button from relay and send just mqtt topic }
}
}
}
}
#endif // ESP8266
else {
if ((PRESSED == button) && (NOT_PRESSED == Button.last_state[button_index])) {
if (((PRESSED == button) && (NOT_PRESSED == Button.last_state[button_index]) && !Button.inverted_mask) ||
((NOT_PRESSED == button) && (PRESSED == Button.last_state[button_index]) && Button.inverted_mask)) {
if (Settings.flag.button_single) { // SetOption13 (0) - Allow only single button press for immediate action, SetOption73 (0) - Decouple button from relay and send just mqtt topic
if (!Settings.flag3.mqtt_buttons) {
@ -203,9 +201,9 @@ void ButtonHandler(void)
Button.window_timer[button_index] = loops_per_second / 2; // 0.5 second multi press window
}
blinks = 201;
}
}
if (NOT_PRESSED == button) {
if (((NOT_PRESSED == button) && !Button.inverted_mask) || ((PRESSED == button) && Button.inverted_mask)) {
Button.hold_timer[button_index] = 0;
} else {
Button.hold_timer[button_index]++;
@ -223,11 +221,11 @@ void ButtonHandler(void)
SendKey(KEY_BUTTON, button_index +1, POWER_HOLD); // Execute Hold command via MQTT if ButtonTopic is set
}
} else {
if (Button.hold_timer[button_index] == loops_per_second * hold_time_extent * Settings.param[P_HOLD_TIME] / 10) { // SetOption32 (40) - Button held for factor times longer
if ((Button.hold_timer[button_index] == loops_per_second * hold_time_extent * Settings.param[P_HOLD_TIME] / 10)) { // SetOption32 (40) - Button held for factor times longer
Button.press_counter[button_index] = 0;
snprintf_P(scmnd, sizeof(scmnd), PSTR(D_CMND_RESET " 1"));
ExecuteCommand(scmnd, SRC_BUTTON);
}
}
}
}
}
@ -236,7 +234,9 @@ void ButtonHandler(void)
if (Button.window_timer[button_index]) {
Button.window_timer[button_index]--;
} else {
if (!restart_flag && !Button.hold_timer[button_index] && (Button.press_counter[button_index] > 0) && (Button.press_counter[button_index] < MAX_BUTTON_COMMANDS_V2 +6)) {
// if (!restart_flag && !Button.hold_timer[button_index] && (Button.press_counter[button_index] > 0) && (Button.press_counter[button_index] < MAX_BUTTON_COMMANDS_V2 +6)) {
if (!restart_flag && !Button.hold_timer[button_index] && (Button.press_counter[button_index] > 0) && (Button.press_counter[button_index] < 7)) {
bool single_press = false;
if (Button.press_counter[button_index] < 3) { // Single or Double press
#ifdef ESP8266
@ -280,8 +280,12 @@ void ButtonHandler(void)
}
}
}
} else { // 6 - 8 press are used to send commands
GetTextIndexed(scmnd, sizeof(scmnd), Button.press_counter[button_index] -6, kCommands);
// } else { // 6 - 8 press are used to send commands
// GetTextIndexed(scmnd, sizeof(scmnd), Button.press_counter[button_index] -6, kCommands);
// ExecuteCommand(scmnd, SRC_BUTTON);
// }
} else { // 6 press start wificonfig 2
snprintf_P(scmnd, sizeof(scmnd), PSTR(D_CMND_WIFICONFIG " 2"));
ExecuteCommand(scmnd, SRC_BUTTON);
}
if (Settings.flag3.mqtt_buttons) { // SetOption73 (0) - Decouple button from relay and send just mqtt topic

View File

@ -36,7 +36,7 @@ const char kTasmotaCommands[] PROGMEM = "|" // No prefix
#ifdef USE_DEVICE_GROUPS_SEND
D_CMND_DEVGROUP_SEND "|"
#endif // USE_DEVICE_GROUPS_SEND
D_CMND_DEVGROUP_SHARE "|"
D_CMND_DEVGROUP_SHARE "|" D_CMND_DEVGROUPSTATUS "|"
#endif // USE_DEVICE_GROUPS
D_CMND_SENSOR "|" D_CMND_DRIVER;
@ -59,7 +59,7 @@ void (* const TasmotaCommand[])(void) PROGMEM = {
#ifdef USE_DEVICE_GROUPS_SEND
&CmndDevGroupSend,
#endif // USE_DEVICE_GROUPS_SEND
&CmndDevGroupShare,
&CmndDevGroupShare, &CmndDevGroupStatus,
#endif // USE_DEVICE_GROUPS
&CmndSensor, &CmndDriver };
@ -448,7 +448,7 @@ void CmndStatus(void)
D_JSON_PROGRAMFLASHSIZE "\":%d,\"" D_JSON_FLASHSIZE "\":%d,\"" D_JSON_FLASHCHIPID "\":\"%06X\",\"" D_JSON_FLASHMODE "\":%d,\""
D_JSON_FEATURES "\":[\"%08X\",\"%08X\",\"%08X\",\"%08X\",\"%08X\",\"%08X\",\"%08X\"]"),
ESP_getSketchSize()/1024, ESP.getFreeSketchSpace()/1024, ESP.getFreeHeap()/1024,
ESP.getFlashChipSize()/1024, ESP_getFlashChipRealSize()/1024, ESP_getFlashChipId(), ESP.getFlashChipMode(),
ESP.getFlashChipSize()/1024, ESP.getFlashChipRealSize()/1024, ESP_getFlashChipId(), ESP.getFlashChipMode(),
LANGUAGE_LCID, feature_drv1, feature_drv2, feature_sns1, feature_sns2, feature5, feature6);
XsnsDriverState();
ResponseAppend_P(PSTR(",\"Sensors\":"));
@ -1117,10 +1117,9 @@ void CmndTemplate(void)
#ifdef ESP8266
if (6 == i) { j = 9; }
if (8 == i) { j = 12; }
#endif // ESP8266
#ifdef ESP32
#else // ESP32
if (6 == i) { j = 12; }
#endif // ESP32
#endif // ESP8266 - ESP32
if (my_module.io[j] > GPIO_NONE) {
Settings.user_template.gp.io[i] = my_module.io[j];
}
@ -1793,6 +1792,11 @@ void CmndDevGroupShare(void)
Settings.device_group_share_out = parm[1];
Response_P(PSTR("{\"" D_CMND_DEVGROUP_SHARE "\":{\"In\":\"%X\",\"Out\":\"%X\"}}"), Settings.device_group_share_in, Settings.device_group_share_out);
}
void CmndDevGroupStatus(void)
{
DeviceGroupStatus((XdrvMailbox.usridx ? XdrvMailbox.index - 1 : 0));
}
#endif // USE_DEVICE_GROUPS
void CmndSensor(void)

View File

@ -34,6 +34,7 @@ struct device_group_member {
IPAddress ip_address;
uint16_t received_sequence;
uint16_t acked_sequence;
uint32_t unicast_count;
};
struct device_group {
@ -48,7 +49,6 @@ struct device_group {
bool local;
char group_name[TOPSZ];
char message[128];
uint8_t group_member_count;
struct device_group_member * device_group_members;
#ifdef USE_DEVICE_GROUPS_SEND
uint8_t values_8bit[DGR_ITEM_LAST_8BIT];
@ -77,7 +77,7 @@ void DeviceGroupsInit(void)
// Initialize the device information for each device group.
device_groups = (struct device_group *)calloc(device_group_count, sizeof(struct device_group));
if (device_groups == nullptr) {
AddLog_P2(LOG_LEVEL_ERROR, PSTR("DGR: error allocating %u-element device group array"), device_group_count);
AddLog_P2(LOG_LEVEL_ERROR, PSTR("DGR: Error allocating %u-element device group array"), device_group_count);
device_groups_initialization_failed = true;
return;
}
@ -169,7 +169,7 @@ void SendDeviceGroupPacket(IPAddress ip, char * packet, int len, const char * la
}
delay(10);
}
AddLog_P2(LOG_LEVEL_ERROR, PSTR("DGR: error sending %s packet"), label);
AddLog_P2(LOG_LEVEL_ERROR, PSTR("DGR: Error sending %s packet"), label);
}
void _SendDeviceGroupMessage(uint8_t device_group_index, DevGroupMessageType message_type, ...)
@ -184,7 +184,7 @@ void _SendDeviceGroupMessage(uint8_t device_group_index, DevGroupMessageType mes
if (processing_remote_device_message && message_type != DGR_MSGTYPE_UPDATE_COMMAND) return;
// Get a pointer to the device information for this device.
device_group * device_group = &device_groups[device_group_index];
struct device_group * device_group = &device_groups[device_group_index];
// If we're still sending initial status requests, ignore this request.
if (device_group->initial_status_requests_remaining) return;
@ -551,7 +551,7 @@ void _SendDeviceGroupMessage(uint8_t device_group_index, DevGroupMessageType mes
// Multicast the packet.
#ifdef DEVICE_GROUPS_DEBUG
AddLog_P2(LOG_LEVEL_DEBUG, PSTR("DGR: sending %u-byte device group %s packet via multicast, sequence=%u"), device_group->message_length, device_group->group_name, device_group->message[device_group->message_header_length] | device_group->message[device_group->message_header_length + 1] << 8);
AddLog_P2(LOG_LEVEL_DEBUG, PSTR("DGR: Sending %u-byte device group %s packet via multicast, sequence=%u"), device_group->message_length, device_group->group_name, device_group->message[device_group->message_header_length] | device_group->message[device_group->message_header_length + 1] << 8);
#endif // DEVICE_GROUPS_DEBUG
SendDeviceGroupPacket(IPAddress(0,0,0,0), device_group->message, device_group->message_length, PSTR("Multicast"));
@ -598,12 +598,10 @@ void ProcessDeviceGroupMessage(char * packet, int packet_length)
if (!device_group_member) {
device_group_member = (struct device_group_member *)calloc(1, sizeof(struct device_group_member));
if (device_group_member == nullptr) {
AddLog_P2(LOG_LEVEL_ERROR, PSTR("DGR: error allocating device group member block"));
AddLog_P2(LOG_LEVEL_ERROR, PSTR("DGR: Error allocating device group member block"));
return;
}
#ifdef DEVICE_GROUPS_DEBUG
AddLog_P2(LOG_LEVEL_DEBUG, PSTR("DGR: adding member %s (%p)"), IPAddressToString(remote_ip), device_group_member);
#endif // DEVICE_GROUPS_DEBUG
AddLog_P2(LOG_LEVEL_DEBUG, PSTR("DGR: Adding member %s"), IPAddressToString(remote_ip));
device_group_member->ip_address = remote_ip;
*flink = device_group_member;
break;
@ -720,7 +718,7 @@ void ProcessDeviceGroupMessage(char * packet, int packet_length)
case DGR_ITEM_LIGHT_CHANNELS:
break;
default:
AddLog_P2(LOG_LEVEL_ERROR, PSTR("DGR: ********** invalid item=%u received from device group %s member %s"), item, device_group->group_name, IPAddressToString(remote_ip));
AddLog_P2(LOG_LEVEL_ERROR, PSTR("DGR: ********** Invalid item=%u received from device group %s member %s"), item, device_group->group_name, IPAddressToString(remote_ip));
}
#endif // DEVICE_GROUPS_DEBUG
@ -802,13 +800,28 @@ void ProcessDeviceGroupMessage(char * packet, int packet_length)
return;
badmsg:
AddLog_P2(LOG_LEVEL_ERROR, PSTR("DGR: malformed message received from %s"), IPAddressToString(remote_ip));
AddLog_P2(LOG_LEVEL_ERROR, PSTR("DGR: Malformed message received from %s"), IPAddressToString(remote_ip));
#ifdef DEVICE_GROUPS_DEBUG
AddLog_P2(LOG_LEVEL_DEBUG, PSTR("packet_length=%u, offset=%u"), packet_length, message_ptr - packet);
#endif // DEVICE_GROUPS_DEBUG
processing_remote_device_message = false;
}
void DeviceGroupStatus(uint8_t device_group_index)
{
if (Settings.flag4.device_groups_enabled && device_group_index < device_group_count) {
char buffer[1024];
int member_count = 0;
struct device_group * device_group = &device_groups[device_group_index];
buffer[0] = buffer[1] = 0;
for (struct device_group_member * device_group_member = device_group->device_group_members; device_group_member; device_group_member = device_group_member->flink) {
snprintf(buffer, sizeof(buffer), PSTR("%s,{\"IPAddress\":\"%s\",\"ResendCount\":%u,\"LastRcvdSeq\":%u,\"LastAckedSeq\":%u}"), buffer, IPAddressToString(device_group_member->ip_address), device_group_member->unicast_count, device_group_member->received_sequence, device_group_member->acked_sequence);
member_count++;
}
Response_P(PSTR("{\"" D_CMND_DEVGROUPSTATUS "\":{\"Index\":%u,\"GroupName\":\"%s\",\"MessageSeq\":%u,\"MemberCount\":%d,\"Members\":[%s]}"), device_group_index, device_group->group_name, outgoing_sequence, member_count, &buffer[1]);
}
}
void DeviceGroupsLoop(void)
{
if (!Settings.flag4.device_groups_enabled) return;
@ -822,16 +835,16 @@ void DeviceGroupsLoop(void)
if (!device_groups_initialized) DeviceGroupsInit();
if (device_groups_initialization_failed) return;
// Load the status request message for all device groups. This message will be multicast 5
// times.
// Load the status request message for all device groups. This message will be multicast 10
// times at 200ms intervals.
next_check_time = now + 3000;
for (uint32_t device_group_index = 0; device_group_index < device_group_count; device_group_index++) {
device_group * device_group = &device_groups[device_group_index];
device_group->message_length = BeginDeviceGroupMessage(device_group, DGR_FLAG_RESET | DGR_FLAG_STATUS_REQUEST) - device_group->message;
device_group->initial_status_requests_remaining = 5;
device_group->initial_status_requests_remaining = 10;
device_group->next_ack_check_time = next_check_time;
}
AddLog_P2(LOG_LEVEL_DEBUG, PSTR("DGR: (Re)discovering device groups"));
}
if (device_groups_initialization_failed) return;
@ -856,15 +869,15 @@ AddLog_P2(LOG_LEVEL_DEBUG, PSTR("DGR: Ckecking next_check_time=%u, now=%u"), nex
if (device_group->initial_status_requests_remaining) {
if (--device_group->initial_status_requests_remaining) {
#ifdef DEVICE_GROUPS_DEBUG
AddLog_P2(LOG_LEVEL_DEBUG, PSTR("DGR: sending initial status request for group %s"), device_group->group_name);
AddLog_P2(LOG_LEVEL_DEBUG, PSTR("DGR: Sending initial status request for group %s"), device_group->group_name);
#endif // DEVICE_GROUPS_DEBUG
SendDeviceGroupPacket(IPAddress(0,0,0,0), device_group->message, device_group->message_length, PSTR("Initial"));
device_group->message[device_group->message_header_length + 2] = DGR_FLAG_STATUS_REQUEST; // The reset flag is on only for the first packet - turn it off now
device_group->next_ack_check_time = now + 200;
}
// If we've sent the initial status request message 5 times, send our status to all
// the members.
// If we've sent the initial status request message the set number of times, send our
// status to all the members.
else {
device_group->next_ack_check_time = 0;
_SendDeviceGroupMessage(device_group_index, DGR_MSGTYP_FULL_STATUS);
@ -874,7 +887,7 @@ AddLog_P2(LOG_LEVEL_DEBUG, PSTR("DGR: Ckecking next_check_time=%u, now=%u"), nex
// If we're done initializing, iterate through the group memebers, ...
else {
#ifdef DEVICE_GROUPS_DEBUG
AddLog_P2(LOG_LEVEL_DEBUG, PSTR("DGR: checking for ack's"));
AddLog_P2(LOG_LEVEL_DEBUG, PSTR("DGR: Checking for ack's"));
#endif // DEVICE_GROUPS_DEBUG
bool acked = true;
struct device_group_member ** flink = &device_group->device_group_members;
@ -887,9 +900,7 @@ AddLog_P2(LOG_LEVEL_DEBUG, PSTR("DGR: Ckecking next_check_time=%u, now=%u"), nex
// If we haven't receive an ack from this member in DGR_MEMBER_TIMEOUT ms, assume
// they're offline and remove them from the group.
if (device_group->member_timeout_time < now) {
#ifdef DEVICE_GROUPS_DEBUG
AddLog_P2(LOG_LEVEL_DEBUG, PSTR("DGR: removing member %s (%p)"), IPAddressToString(device_group_member->ip_address), device_group_member);
#endif // DEVICE_GROUPS_DEBUG
AddLog_P2(LOG_LEVEL_DEBUG, PSTR("DGR: Removing member %s"), IPAddressToString(device_group_member->ip_address));
*flink = device_group_member->flink;
free(device_group_member);
}
@ -897,9 +908,10 @@ AddLog_P2(LOG_LEVEL_DEBUG, PSTR("DGR: Ckecking next_check_time=%u, now=%u"), nex
// Otherwise, unicast the last message directly to this member.
else {
#ifdef DEVICE_GROUPS_DEBUG
AddLog_P2(LOG_LEVEL_DEBUG, PSTR("DGR: sending %u-byte device group %s packet via unicast to %s, sequence %u, last message acked=%u"), device_group->message_length, device_group->group_name, IPAddressToString(device_group_member->ip_address), outgoing_sequence, device_group_member->acked_sequence);
AddLog_P2(LOG_LEVEL_DEBUG, PSTR("DGR: Sending %u-byte device group %s packet via unicast to %s, sequence %u, last message acked=%u"), device_group->message_length, device_group->group_name, IPAddressToString(device_group_member->ip_address), outgoing_sequence, device_group_member->acked_sequence);
#endif // DEVICE_GROUPS_DEBUG
SendDeviceGroupPacket(device_group_member->ip_address, device_group->message, device_group->message_length, PSTR("Unicast"));
device_group_member->unicast_count++;
acked = false;
flink = &device_group_member->flink;
}
@ -940,7 +952,7 @@ AddLog_P2(LOG_LEVEL_DEBUG, PSTR("DGR: Ckecking next_check_time=%u, now=%u"), nex
#endif // DEVICE_GROUPS_DEBUG
if (device_group->next_announcement_time <= now) {
#ifdef DEVICE_GROUPS_DEBUG
AddLog_P2(LOG_LEVEL_DEBUG, PSTR("DGR: sending device group %s announcement"), device_group->group_name);
AddLog_P2(LOG_LEVEL_DEBUG, PSTR("DGR: Sending device group %s announcement"), device_group->group_name);
#endif // DEVICE_GROUPS_DEBUG
SendDeviceGroupPacket(IPAddress(0,0,0,0), device_group->message, BeginDeviceGroupMessage(device_group, DGR_FLAG_ANNOUNCEMENT, true) - device_group->message, PSTR("Announcement"));
device_group->next_announcement_time = now + DGR_ANNOUNCEMENT_INTERVAL + random(10000);

View File

@ -371,13 +371,13 @@ void FLOG::stopRecording(void){
*
* @param size: size of the data entry/record in bytes, i.e. sizeof(myStruct)
* @param sendHeader: should implement at least something like:
* @example WebServer->setContentLength(CONTENT_LENGTH_UNKNOWN); // This is very likely unknown!!
* WebServer->sendHeader(F("Content-Disposition"), F("attachment; filename=myfile.txt"));
* @example Webserver->setContentLength(CONTENT_LENGTH_UNKNOWN); // This is very likely unknown!!
* Webserver->sendHeader(F("Content-Disposition"), F("attachment; filename=myfile.txt"));
* @param sendRecord: will receive the memory address as "uint8_t* addr" and should consume the current entry/record
* @example myStruct_t *entry = (myStruct_t*)addr;
* Then make useful Strings and send it, i.e.: WebServer->sendContent_P(myString);
* Then make useful Strings and send it, i.e.: Webserver->sendContent_P(myString);
* @param sendFooter: finish the download, should implement at least:
* @example WebServer->sendContent("");
* @example Webserver->sendContent("");
*/
void FLOG::startDownload(size_t size, CallbackNoArgs sendHeader, CallbackWithArgs sendRecord, CallbackNoArgs sendFooter){

View File

@ -192,6 +192,12 @@ void setup(void)
{
global_state.data = 3; // Init global state (wifi_down, mqtt_down) to solve possible network issues
#ifdef ESP32
#ifdef DISABLE_BROWNOUT
DisableBrownout();
#endif
#endif
RtcRebootLoad();
if (!RtcRebootValid()) {
RtcReboot.fast_reboot_count = 0;

View File

@ -17,7 +17,6 @@
#define ESP_reset() ESP.reset()
#define ESP_getBootVersion() ESP.getBootVersion()
#define ESP_getFlashChipId() ESP.getFlashChipId()
#define ESP_getFlashChipRealSize() ESP.getFlashChipRealSize()
#define ESP_getSketchSize() ESP.getSketchSize()
#define ESP_getChipId() ESP.getChipId()
//

View File

@ -45,106 +45,61 @@
/********************************************************************************************/
// Supported hardware modules
enum SupportedModules {
WEMOS,
ESP32_CAM,
MAXMODULE
};
WEMOS, ESP32_CAM_AITHINKER,
MAXMODULE};
const char kModuleNames[] PROGMEM =
"WeMos D1 ESP32|ESP32 CAM|"
;
"ESP32-DevKit|ESP32 Cam AiThinker";
// Default module settings
const uint8_t kModuleNiceList[MAXMODULE] PROGMEM = {
WEMOS,
ESP32_CAM
ESP32_CAM_AITHINKER
};
const mytmplt kModules[MAXMODULE] PROGMEM = {
{ // "WeMos D1 ESP32", // Any ESP32 device like WeMos and NodeMCU hardware (ESP32)
GPIO_USER, //0 (I)O GPIO0, ADC2_CH1, TOUCH1, RTC_GPIO11, CLK_OUT1, EMAC_TX_CLK
GPIO_USER, //1 IO TXD0 GPIO1, U0TXD, CLK_OUT3, EMAC_RXD2
GPIO_USER, //2 IO GPIO2, ADC2_CH2, TOUCH2, RTC_GPIO12, HSPIWP, HS2_DATA0, SD_DATA0
GPIO_USER, //3 IO RXD0 GPIO3, U0RXD, CLK_OUT2
GPIO_USER, //4 IO GPIO4, ADC2_CH0, TOUCH0, RTC_GPIO10, HSPIHD, HS2_DATA1, SD_DATA1, EMAC_TX_ER
GPIO_USER, //5 IO GPIO5, VSPICS0, HS1_DATA6, EMAC_RX_CLK
// 0, //6
// 0, //7
// 0, //8
// 0, //9
// 0, //10
// 0, //11
GPIO_USER, //12 (I)O GPIO12, ADC2_CH5, TOUCH5, RTC_GPIO15, MTDI, HSPIQ, HS2_DATA2, SD_DATA2, EMAC_TXD3 (If driven High, flash voltage (VDD_SDIO) is 1.8V not default 3.3V. Has internal pull-down, so unconnected = Low = 3.3V. May prevent flashing and/or booting if 3.3V flash is connected and pulled high. See ESP32 datasheet for more details.)
GPIO_USER, //13 IO GPIO13, ADC2_CH4, TOUCH4, RTC_GPIO14, MTCK, HSPID, HS2_DATA3, SD_DATA3, EMAC_RX_ER
GPIO_USER, //14 IO GPIO14, ADC2_CH6, TOUCH6, RTC_GPIO16, MTMS, HSPICLK, HS2_CLK, SD_CLK, EMAC_TXD2
GPIO_USER, //15 (I)O GPIO15, ADC2_CH3, TOUCH3, MTDO, HSPICS0, RTC_GPIO13, HS2_CMD, SD_CMD, EMAC_RXD3 (If driven Low, silences boot messages from normal boot. Has internal pull-up, so unconnected = High = normal output.)
GPIO_USER, //16 IO GPIO16, HS1_DATA4, U2RXD, EMAC_CLK_OUT
GPIO_USER, //17 IO GPIO17, HS1_DATA5, U2TXD, EMAC_CLK_OUT_180
GPIO_USER, //18 IO GPIO18, VSPICLK, HS1_DATA7
GPIO_USER, //19 IO GPIO19, VSPIQ, U0CTS, EMAC_TXD0
0, //20
0, //21 IO GPIO21, VSPIHD, EMAC_TX_EN
GPIO_USER, //22 IO LED GPIO22, VSPIWP, U0RTS, EMAC_TXD1
GPIO_USER, //23 IO GPIO23, VSPID, HS1_STROBE
0, //24
GPIO_USER, //25 IO GPIO25, DAC_1, ADC2_CH8, RTC_GPIO6, EMAC_RXD0
GPIO_USER, //26 IO GPIO26, DAC_2, ADC2_CH9, RTC_GPIO7, EMAC_RXD1
GPIO_USER, //27 IO GPIO27, ADC2_CH7, TOUCH7, RTC_GPIO17, EMAC_RX_DV
0, //28
0, //29
0, //30
0, //31
GPIO_USER, //32 IO GPIO32, XTAL_32K_P (32.768 kHz crystal oscillator input), ADC1_CH4, TOUCH9, RTC_GPIO9
GPIO_USER, //33 IO GPIO33, XTAL_32K_N (32.768 kHz crystal oscillator output), ADC1_CH5, TOUCH8, RTC_GPIO8
GPIO_USER, //34 I NO PULLUP GPIO34, ADC1_CH6, RTC_GPIO4
GPIO_USER, //35 I NO PULLUP GPIO35, ADC1_CH7, RTC_GPIO5
GPIO_USER, //36 I NO PULLUP GPIO36, SENSOR_VP, ADC_H, ADC1_CH0, RTC_GPIO0
0, //37 NO PULLUP
0, //38 NO PULLUP
GPIO_USER //39 I NO PULLUP GPIO39, SENSOR_VN, ADC1_CH3, ADC_H, RTC_GPIO3
},
{ //"ESP32 CAM",
GPIO_USER, //0 (I)O GPIO0, ADC2_CH1, TOUCH1, RTC_GPIO11, CLK_OUT1, EMAC_TX_CLK
GPIO_USER, //1 IO TXD0 GPIO1, U0TXD, CLK_OUT3, EMAC_RXD2
GPIO_USER, //2 IO GPIO2, ADC2_CH2, TOUCH2, RTC_GPIO12, HSPIWP, HS2_DATA0, SD_DATA0
GPIO_USER, //3 IO RXD0 GPIO3, U0RXD, CLK_OUT2
GPIO_USER, //4 IO GPIO4, ADC2_CH0, TOUCH0, RTC_GPIO10, HSPIHD, HS2_DATA1, SD_DATA1, EMAC_TX_ER
GPIO_USER, //5 IO GPIO5, VSPICS0, HS1_DATA6, EMAC_RX_CLK
// 0, //6
// 0, //7
// 0, //8
// 0, //9
// 0, //10
// 0, //11
GPIO_USER, //12 (I)O GPIO12, ADC2_CH5, TOUCH5, RTC_GPIO15, MTDI, HSPIQ, HS2_DATA2, SD_DATA2, EMAC_TXD3 (If driven High, flash voltage (VDD_SDIO) is 1.8V not default 3.3V. Has internal pull-down, so unconnected = Low = 3.3V. May prevent flashing and/or booting if 3.3V flash is connected and pulled high. See ESP32 datasheet for more details.)
GPIO_USER, //13 IO GPIO13, ADC2_CH4, TOUCH4, RTC_GPIO14, MTCK, HSPID, HS2_DATA3, SD_DATA3, EMAC_RX_ER
GPIO_USER, //14 IO GPIO14, ADC2_CH6, TOUCH6, RTC_GPIO16, MTMS, HSPICLK, HS2_CLK, SD_CLK, EMAC_TXD2
GPIO_USER, //15 (I)O GPIO15, ADC2_CH3, TOUCH3, MTDO, HSPICS0, RTC_GPIO13, HS2_CMD, SD_CMD, EMAC_RXD3 (If driven Low, silences boot messages from normal boot. Has internal pull-up, so unconnected = High = normal output.)
GPIO_USER, //16 IO GPIO16, HS1_DATA4, U2RXD, EMAC_CLK_OUT
GPIO_USER, //17 IO GPIO17, HS1_DATA5, U2TXD, EMAC_CLK_OUT_180
GPIO_USER, //18 IO GPIO18, VSPICLK, HS1_DATA7
GPIO_USER, //19 IO GPIO19, VSPIQ, U0CTS, EMAC_TXD0
0, //20
0, //21 IO GPIO21, VSPIHD, EMAC_TX_EN
GPIO_USER, //22 IO LED GPIO22, VSPIWP, U0RTS, EMAC_TXD1
GPIO_USER, //23 IO GPIO23, VSPID, HS1_STROBE
0, //24
GPIO_USER, //25 IO GPIO25, DAC_1, ADC2_CH8, RTC_GPIO6, EMAC_RXD0
GPIO_USER, //26 IO GPIO26, DAC_2, ADC2_CH9, RTC_GPIO7, EMAC_RXD1
GPIO_USER, //27 IO GPIO27, ADC2_CH7, TOUCH7, RTC_GPIO17, EMAC_RX_DV
0, //28
0, //29
0, //30
0, //31
GPIO_USER, //32 IO GPIO32, XTAL_32K_P (32.768 kHz crystal oscillator input), ADC1_CH4, TOUCH9, RTC_GPIO9
GPIO_USER, //33 IO GPIO33, XTAL_32K_N (32.768 kHz crystal oscillator output), ADC1_CH5, TOUCH8, RTC_GPIO8
GPIO_USER, //34 I NO PULLUP GPIO34, ADC1_CH6, RTC_GPIO4
GPIO_USER, //35 I NO PULLUP GPIO35, ADC1_CH7, RTC_GPIO5
GPIO_USER, //36 I NO PULLUP GPIO36, SENSOR_VP, ADC_H, ADC1_CH0, RTC_GPIO0
0, //37 NO PULLUP
0, //38 NO PULLUP
GPIO_USER //39 I NO PULLUP GPIO39, SENSOR_VN, ADC1_CH3, ADC_H, RTC_GPIO3
}
const mytmplt kModules PROGMEM =
{ // WEMOS - Espressif ESP32-DevKitC - Any ESP32 device like WeMos and NodeMCU hardware (ESP32)
GPIO_USER, //0 (I)O GPIO0, ADC2_CH1, TOUCH1, RTC_GPIO11, CLK_OUT1, EMAC_TX_CLK
GPIO_USER, //1 IO TXD0 GPIO1, U0TXD, CLK_OUT3, EMAC_RXD2
GPIO_USER, //2 IO GPIO2, ADC2_CH2, TOUCH2, RTC_GPIO12, HSPIWP, HS2_DATA0, SD_DATA0
GPIO_USER, //3 IO RXD0 GPIO3, U0RXD, CLK_OUT2
GPIO_USER, //4 IO GPIO4, ADC2_CH0, TOUCH0, RTC_GPIO10, HSPIHD, HS2_DATA1, SD_DATA1, EMAC_TX_ER
GPIO_USER, //5 IO GPIO5, VSPICS0, HS1_DATA6, EMAC_RX_CLK
//6 IO GPIO6, Flash CLK
//7 IO GPIO7, Flash D0
//8 IO GPIO8, Flash D1
//9 IO GPIO9, Flash D2
//10 IO GPIO10, Flash D3
//11 IO GPIO11, Flash CMD
GPIO_USER, //12 (I)O GPIO12, ADC2_CH5, TOUCH5, RTC_GPIO15, MTDI, HSPIQ, HS2_DATA2, SD_DATA2, EMAC_TXD3 (If driven High, flash voltage (VDD_SDIO) is 1.8V not default 3.3V. Has internal pull-down, so unconnected = Low = 3.3V. May prevent flashing and/or booting if 3.3V flash is connected and pulled high. See ESP32 datasheet for more details.)
GPIO_USER, //13 IO GPIO13, ADC2_CH4, TOUCH4, RTC_GPIO14, MTCK, HSPID, HS2_DATA3, SD_DATA3, EMAC_RX_ER
GPIO_USER, //14 IO GPIO14, ADC2_CH6, TOUCH6, RTC_GPIO16, MTMS, HSPICLK, HS2_CLK, SD_CLK, EMAC_TXD2
GPIO_USER, //15 (I)O GPIO15, ADC2_CH3, TOUCH3, MTDO, HSPICS0, RTC_GPIO13, HS2_CMD, SD_CMD, EMAC_RXD3 (If driven Low, silences boot messages from normal boot. Has internal pull-up, so unconnected = High = normal output.)
GPIO_USER, //16 IO GPIO16, HS1_DATA4, U2RXD, EMAC_CLK_OUT
GPIO_USER, //17 IO GPIO17, HS1_DATA5, U2TXD, EMAC_CLK_OUT_180
GPIO_USER, //18 IO GPIO18, VSPICLK, HS1_DATA7
GPIO_USER, //19 IO GPIO19, VSPIQ, U0CTS, EMAC_TXD0
0, //20
GPIO_USER, //21 IO GPIO21, VSPIHD, EMAC_TX_EN
GPIO_USER, //22 IO LED GPIO22, VSPIWP, U0RTS, EMAC_TXD1
GPIO_USER, //23 IO GPIO23, VSPID, HS1_STROBE
0, //24
GPIO_USER, //25 IO GPIO25, DAC_1, ADC2_CH8, RTC_GPIO6, EMAC_RXD0
GPIO_USER, //26 IO GPIO26, DAC_2, ADC2_CH9, RTC_GPIO7, EMAC_RXD1
GPIO_USER, //27 IO GPIO27, ADC2_CH7, TOUCH7, RTC_GPIO17, EMAC_RX_DV
0, //28
0, //29
0, //30
0, //31
GPIO_USER, //32 IO GPIO32, XTAL_32K_P (32.768 kHz crystal oscillator input), ADC1_CH4, TOUCH9, RTC_GPIO9
GPIO_USER, //33 IO GPIO33, XTAL_32K_N (32.768 kHz crystal oscillator output), ADC1_CH5, TOUCH8, RTC_GPIO8
GPIO_USER, //34 I NO PULLUP GPIO34, ADC1_CH6, RTC_GPIO4
GPIO_USER, //35 I NO PULLUP GPIO35, ADC1_CH7, RTC_GPIO5
GPIO_USER, //36 I NO PULLUP GPIO36, SENSOR_VP, ADC_H, ADC1_CH0, RTC_GPIO0
0, //37 NO PULLUP
0, //38 NO PULLUP
GPIO_USER, //39 I NO PULLUP GPIO39, SENSOR_VN, ADC1_CH3, ADC_H, RTC_GPIO3
0 // Flag
};
#endif // ESP32

View File

@ -20,7 +20,7 @@
#ifndef _TASMOTA_VERSION_H_
#define _TASMOTA_VERSION_H_
const uint32_t VERSION = 0x08020003;
const uint32_t VERSION = 0x08020004;
// Lowest compatible version
const uint32_t VERSION_COMPATIBLE = 0x07010006;

View File

@ -109,7 +109,7 @@ const char HTTP_SCRIPT_ROOT[] PROGMEM =
"}"
"};"
"if (rfsh) {"
"x.open('GET','.?m=1'+a,true);" // ?m related to WebServer->hasArg("m")
"x.open('GET','.?m=1'+a,true);" // ?m related to Webserver->hasArg("m")
"x.send();"
"lt=setTimeout(la,%d);" // Settings.web_refresh
"}"
@ -146,7 +146,7 @@ const char HTTP_SCRIPT_ROOT[] PROGMEM =
"eb('l1').innerHTML=s;"
"}"
"};"
"x.open('GET','.?m=1'+a,true);" // ?m related to WebServer->hasArg("m")
"x.open('GET','.?m=1'+a,true);" // ?m related to Webserver->hasArg("m")
"x.send();"
"lt=setTimeout(la,%d);" // Settings.web_refresh
"}";
@ -205,7 +205,7 @@ const char HTTP_SCRIPT_CONSOL[] PROGMEM =
"sn=t.scrollTop;"
"}"
"};"
"x.open('GET','cs?c2='+id+o,true);" // Related to WebServer->hasArg("c2") and WebGetArg("c2", stmp, sizeof(stmp))
"x.open('GET','cs?c2='+id+o,true);" // Related to Webserver->hasArg("c2") and WebGetArg("c2", stmp, sizeof(stmp))
"x.send();"
"}"
"lt=setTimeout(l,%d);"
@ -261,21 +261,18 @@ const char HTTP_SCRIPT_TEMPLATE[] PROGMEM =
"as=o.shift();" // Complete ADC0 list
"g=o.shift().split(',');" // Array separator
"j=0;"
// "for(i=0;i<13;i++){" // Supports 13 GPIOs
"for(i=0;i<" STR(MAX_USER_PINS) ";i++){" // Supports 13 GPIOs
#ifdef ESP8266
"if(6==i){j=9;}"
"if(8==i){j=12;}"
#endif
#ifdef ESP32
#else // ESP32
"if(6==i){j=12;}"
#endif
#endif // ESP8266 - ESP32
"sk(g[i],j);" // Set GPIO
"j++;"
"}"
"g=o.shift();" // FLAG
"os=as;"
// "sk(g&15,17);" // Set ADC0
"sk(g&15," STR(ADC0_PIN) ");" // Set ADC0
"g>>=4;"
"for(i=0;i<" STR(GPIO_FLAG_USED) ";i++){"
@ -295,16 +292,15 @@ const char HTTP_SCRIPT_TEMPLATE[] PROGMEM =
"function x2(a){"
"os=a.responseText;"
// "sk(17,99);" // 17 = WEMOS
"sk(" STR(WEMOS_MODULE) ",99);" // 17 = WEMOS
"st(" STR(USER_MODULE) ");"
"}"
#ifdef USE_JAVASCRIPT_ES6
"sl=()=>ld('tp?m=1',x2);" // ?m related to WebServer->hasArg("m")
"sl=()=>ld('tp?m=1',x2);" // ?m related to Webserver->hasArg("m")
#else
"function sl(){"
"ld('tp?m=1',x2);" // ?m related to WebServer->hasArg("m")
"ld('tp?m=1',x2);" // ?m related to Webserver->hasArg("m")
"}"
#endif
@ -321,15 +317,13 @@ const char HTTP_SCRIPT_MODULE2[] PROGMEM =
"}"
"function x3(a){" // ADC0
"os=a.responseText;"
// "sk(%d,17);"
"sk(%d," STR(ADC0_PIN) ");"
"}"
"function sl(){"
"ld('md?m=1',x1);" // ?m related to WebServer->hasArg("m")
"ld('md?g=1',x2);" // ?g related to WebServer->hasArg("g")
// "if(eb('g17')){"
"ld('md?m=1',x1);" // ?m related to Webserver->hasArg("m")
"ld('md?g=1',x2);" // ?g related to Webserver->hasArg("g")
"if(eb('g" STR(ADC0_PIN) "')){"
"ld('md?a=1',x3);" // ?a related to WebServer->hasArg("a")
"ld('md?a=1',x3);" // ?a related to Webserver->hasArg("a")
"}"
"}"
"wl(sl);";
@ -544,7 +538,7 @@ const uint16_t DNS_PORT = 53;
enum HttpOptions {HTTP_OFF, HTTP_USER, HTTP_ADMIN, HTTP_MANAGER, HTTP_MANAGER_RESET_ONLY};
DNSServer *DnsServer;
ESP8266WebServer *WebServer;
ESP8266WebServer *Webserver;
struct WEB {
String chunk_buffer = ""; // Could be max 2 * CHUNKED_BUFFER_SIZE
@ -561,7 +555,7 @@ struct WEB {
// Helper function to avoid code duplication (saves 4k Flash)
static void WebGetArg(const char* arg, char* out, size_t max)
{
String s = WebServer->arg(arg);
String s = Webserver->arg(arg);
strlcpy(out, s.c_str(), max);
// out[max-1] = '\0'; // Ensure terminating NUL
}
@ -574,7 +568,7 @@ void ShowWebSource(uint32_t source)
{
if ((source > 0) && (source < SRC_MAX)) {
char stemp1[20];
AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SRC: %s from %s"), GetTextIndexed(stemp1, sizeof(stemp1), source, kCommandSource), WebServer->client().remoteIP().toString().c_str());
AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SRC: %s from %s"), GetTextIndexed(stemp1, sizeof(stemp1), source, kCommandSource), Webserver->client().remoteIP().toString().c_str());
}
}
@ -589,28 +583,28 @@ void StartWebserver(int type, IPAddress ipweb)
{
if (!Settings.web_refresh) { Settings.web_refresh = HTTP_REFRESH_TIME; }
if (!Web.state) {
if (!WebServer) {
WebServer = new ESP8266WebServer((HTTP_MANAGER == type || HTTP_MANAGER_RESET_ONLY == type) ? 80 : WEB_PORT);
WebServer->on("/", HandleRoot);
WebServer->onNotFound(HandleNotFound);
WebServer->on("/up", HandleUpgradeFirmware);
WebServer->on("/u1", HandleUpgradeFirmwareStart); // OTA
WebServer->on("/u2", HTTP_POST, HandleUploadDone, HandleUploadLoop);
WebServer->on("/u2", HTTP_OPTIONS, HandlePreflightRequest);
WebServer->on("/cs", HTTP_GET, HandleConsole);
WebServer->on("/cs", HTTP_OPTIONS, HandlePreflightRequest);
WebServer->on("/cm", HandleHttpCommand);
if (!Webserver) {
Webserver = new ESP8266WebServer((HTTP_MANAGER == type || HTTP_MANAGER_RESET_ONLY == type) ? 80 : WEB_PORT);
Webserver->on("/", HandleRoot);
Webserver->onNotFound(HandleNotFound);
Webserver->on("/up", HandleUpgradeFirmware);
Webserver->on("/u1", HandleUpgradeFirmwareStart); // OTA
Webserver->on("/u2", HTTP_POST, HandleUploadDone, HandleUploadLoop);
Webserver->on("/u2", HTTP_OPTIONS, HandlePreflightRequest);
Webserver->on("/cs", HTTP_GET, HandleConsole);
Webserver->on("/cs", HTTP_OPTIONS, HandlePreflightRequest);
Webserver->on("/cm", HandleHttpCommand);
#ifndef FIRMWARE_MINIMAL
WebServer->on("/cn", HandleConfiguration);
WebServer->on("/md", HandleModuleConfiguration);
WebServer->on("/wi", HandleWifiConfiguration);
WebServer->on("/lg", HandleLoggingConfiguration);
WebServer->on("/tp", HandleTemplateConfiguration);
WebServer->on("/co", HandleOtherConfiguration);
WebServer->on("/dl", HandleBackupConfiguration);
WebServer->on("/rs", HandleRestoreConfiguration);
WebServer->on("/rt", HandleResetConfiguration);
WebServer->on("/in", HandleInformation);
Webserver->on("/cn", HandleConfiguration);
Webserver->on("/md", HandleModuleConfiguration);
Webserver->on("/wi", HandleWifiConfiguration);
Webserver->on("/lg", HandleLoggingConfiguration);
Webserver->on("/tp", HandleTemplateConfiguration);
Webserver->on("/co", HandleOtherConfiguration);
Webserver->on("/dl", HandleBackupConfiguration);
Webserver->on("/rs", HandleRestoreConfiguration);
Webserver->on("/rt", HandleResetConfiguration);
Webserver->on("/in", HandleInformation);
XdrvCall(FUNC_WEB_ADD_HANDLER);
XsnsCall(FUNC_WEB_ADD_HANDLER);
#endif // Not FIRMWARE_MINIMAL
@ -619,9 +613,9 @@ void StartWebserver(int type, IPAddress ipweb)
// Collect User-Agent for Alexa Hue Emulation
// This is used in xdrv_20_hue.ino in function findEchoGeneration()
WebServer->collectHeaders(HEADER_KEYS, sizeof(HEADER_KEYS)/sizeof(char*));
Webserver->collectHeaders(HEADER_KEYS, sizeof(HEADER_KEYS)/sizeof(char*));
WebServer->begin(); // Web server start
Webserver->begin(); // Web server start
}
if (Web.state != type) {
#if LWIP_IPV6
@ -639,7 +633,7 @@ void StartWebserver(int type, IPAddress ipweb)
void StopWebserver(void)
{
if (Web.state) {
WebServer->close();
Webserver->close();
Web.state = HTTP_OFF;
AddLog_P(LOG_LEVEL_INFO, PSTR(D_LOG_HTTP D_WEBSERVER_STOPPED));
}
@ -684,7 +678,7 @@ void WifiManagerBegin(bool reset_only)
void PollDnsWebserver(void)
{
if (DnsServer) { DnsServer->processNextRequest(); }
if (WebServer) { WebServer->handleClient(); }
if (Webserver) { Webserver->handleClient(); }
}
/*********************************************************************************************/
@ -692,7 +686,7 @@ void PollDnsWebserver(void)
bool WebAuthenticate(void)
{
if (strlen(SettingsText(SET_WEBPWD)) && (HTTP_MANAGER_RESET_ONLY != Web.state)) {
return WebServer->authenticate(WEB_USERNAME, SettingsText(SET_WEBPWD));
return Webserver->authenticate(WEB_USERNAME, SettingsText(SET_WEBPWD));
} else {
return true;
}
@ -705,7 +699,7 @@ bool HttpCheckPriviledgedAccess(bool autorequestauth = true)
return false;
}
if (autorequestauth && !WebAuthenticate()) {
WebServer->requestAuthentication();
Webserver->requestAuthentication();
return false;
}
return true;
@ -714,15 +708,15 @@ bool HttpCheckPriviledgedAccess(bool autorequestauth = true)
void HttpHeaderCors(void)
{
if (strlen(SettingsText(SET_CORS))) {
WebServer->sendHeader(F("Access-Control-Allow-Origin"), SettingsText(SET_CORS));
Webserver->sendHeader(F("Access-Control-Allow-Origin"), SettingsText(SET_CORS));
}
}
void WSHeaderSend(void)
{
WebServer->sendHeader(F("Cache-Control"), F("no-cache, no-store, must-revalidate"));
WebServer->sendHeader(F("Pragma"), F("no-cache"));
WebServer->sendHeader(F("Expires"), F("-1"));
Webserver->sendHeader(F("Cache-Control"), F("no-cache, no-store, must-revalidate"));
Webserver->sendHeader(F("Pragma"), F("no-cache"));
Webserver->sendHeader(F("Expires"), F("-1"));
HttpHeaderCors();
}
@ -733,7 +727,7 @@ void WSHeaderSend(void)
void WSSend(int code, int ctype, const String& content)
{
char ct[25]; // strlen("application/octet-stream") +1 = Longest Content type string
WebServer->send(code, GetTextIndexed(ct, sizeof(ct), ctype, kContentTypes), content);
Webserver->send(code, GetTextIndexed(ct, sizeof(ct), ctype, kContentTypes), content);
}
/**********************************************************************************************
@ -742,13 +736,13 @@ void WSSend(int code, int ctype, const String& content)
void WSContentBegin(int code, int ctype)
{
WebServer->client().flush();
Webserver->client().flush();
WSHeaderSend();
#ifdef ARDUINO_ESP8266_RELEASE_2_3_0
WebServer->sendHeader(F("Accept-Ranges"),F("none"));
WebServer->sendHeader(F("Transfer-Encoding"),F("chunked"));
Webserver->sendHeader(F("Accept-Ranges"),F("none"));
Webserver->sendHeader(F("Transfer-Encoding"),F("chunked"));
#endif
WebServer->setContentLength(CONTENT_LENGTH_UNKNOWN);
Webserver->setContentLength(CONTENT_LENGTH_UNKNOWN);
WSSend(code, ctype, ""); // Signal start of chunked content
Web.chunk_buffer = "";
}
@ -761,9 +755,9 @@ void _WSContentSend(const String& content) // Low level sendContent for a
const char * footer = "\r\n";
char chunk_size[11];
sprintf(chunk_size, "%x\r\n", len);
WebServer->sendContent(String() + chunk_size + content + footer);
Webserver->sendContent(String() + chunk_size + content + footer);
#else
WebServer->sendContent(content);
Webserver->sendContent(content);
#endif
#ifdef USE_DEBUG_DRIVER
@ -849,8 +843,8 @@ void WSContentSend_PD(const char* formatP, ...) // Content send snprintf_P ch
void WSContentStart_P(const char* title, bool auth)
{
if (auth && strlen(SettingsText(SET_WEBPWD)) && !WebServer->authenticate(WEB_USERNAME, SettingsText(SET_WEBPWD))) {
return WebServer->requestAuthentication();
if (auth && strlen(SettingsText(SET_WEBPWD)) && !Webserver->authenticate(WEB_USERNAME, SettingsText(SET_WEBPWD))) {
return Webserver->requestAuthentication();
}
WSContentBegin(200, CT_HTML);
@ -961,7 +955,7 @@ void WSContentEnd(void)
{
WSContentFlush(); // Flush chunk buffer
_WSContentSend(""); // Signal end of chunked content
WebServer->client().stop();
Webserver->client().stop();
}
void WSContentStop(void)
@ -1043,17 +1037,17 @@ void HandleRoot(void)
{
if (CaptivePortal()) { return; } // If captive portal redirect instead of displaying the page.
if (WebServer->hasArg("rst")) {
if (Webserver->hasArg("rst")) {
WebRestart(0);
return;
}
if (WifiIsInManagerMode()) {
#ifndef FIRMWARE_MINIMAL
if (strlen(SettingsText(SET_WEBPWD)) && !(WebServer->hasArg("USER1")) && !(WebServer->hasArg("PASS1")) && HTTP_MANAGER_RESET_ONLY != Web.state) {
if (strlen(SettingsText(SET_WEBPWD)) && !(Webserver->hasArg("USER1")) && !(Webserver->hasArg("PASS1")) && HTTP_MANAGER_RESET_ONLY != Web.state) {
HandleWifiLogin();
} else {
if (!strlen(SettingsText(SET_WEBPWD)) || (((WebServer->arg("USER1") == WEB_USERNAME ) && (WebServer->arg("PASS1") == SettingsText(SET_WEBPWD) )) || HTTP_MANAGER_RESET_ONLY == Web.state)) {
if (!strlen(SettingsText(SET_WEBPWD)) || (((Webserver->arg("USER1") == WEB_USERNAME ) && (Webserver->arg("PASS1") == SettingsText(SET_WEBPWD) )) || HTTP_MANAGER_RESET_ONLY == Web.state)) {
HandleWifiConfiguration();
} else {
// wrong user and pass
@ -1243,11 +1237,11 @@ void HandleRoot(void)
bool HandleRootStatusRefresh(void)
{
if (!WebAuthenticate()) {
WebServer->requestAuthentication();
Webserver->requestAuthentication();
return true;
}
if (!WebServer->hasArg("m")) { // Status refresh requested
if (!Webserver->hasArg("m")) { // Status refresh requested
return false;
}
@ -1429,7 +1423,7 @@ void HandleTemplateConfiguration(void)
{
if (!HttpCheckPriviledgedAccess()) { return; }
if (WebServer->hasArg("save")) {
if (Webserver->hasArg("save")) {
TemplateSaveSettings();
WebRestart(1);
return;
@ -1437,7 +1431,7 @@ void HandleTemplateConfiguration(void)
char stemp[30]; // Template number and Sensor name
if (WebServer->hasArg("m")) {
if (Webserver->hasArg("m")) {
WSContentBegin(200, CT_PLAIN);
for (uint32_t i = 0; i < sizeof(kModuleNiceList); i++) { // "}2'%d'>%s (%d)}3" - "}2'0'>Sonoff Basic (1)}3"
uint32_t midx = pgm_read_byte(kModuleNiceList + i);
@ -1532,10 +1526,9 @@ void TemplateSaveSettings(void)
#ifdef ESP8266
if (6 == i) { j = 9; }
if (8 == i) { j = 12; }
#endif // ESP8266
#ifdef ESP32
#else // ESP32
if (6 == i) { j = 12; }
#endif // ESP32
#endif // ESP8266 - ESP32
snprintf_P(webindex, sizeof(webindex), PSTR("g%d"), j);
WebGetArg(webindex, tmp, sizeof(tmp)); // GPIO
uint8_t gpio = atoi(tmp);
@ -1543,12 +1536,11 @@ void TemplateSaveSettings(void)
j++;
}
// WebGetArg("g17", tmp, sizeof(tmp)); // FLAG - ADC0
WebGetArg("g" STR(ADC0_PIN), tmp, sizeof(tmp)); // FLAG - ADC0
uint32_t flag = atoi(tmp);
for (uint32_t i = 0; i < GPIO_FLAG_USED; i++) {
snprintf_P(webindex, sizeof(webindex), PSTR("c%d"), i);
uint32_t state = WebServer->hasArg(webindex) << i +4; // FLAG
uint32_t state = Webserver->hasArg(webindex) << i +4; // FLAG
flag += state;
}
WebGetArg("g99", tmp, sizeof(tmp)); // BASE
@ -1564,7 +1556,7 @@ void HandleModuleConfiguration(void)
{
if (!HttpCheckPriviledgedAccess()) { return; }
if (WebServer->hasArg("save")) {
if (Webserver->hasArg("save")) {
ModuleSaveSettings();
WebRestart(1);
return;
@ -1575,7 +1567,7 @@ void HandleModuleConfiguration(void)
myio cmodule;
ModuleGpios(&cmodule);
if (WebServer->hasArg("m")) {
if (Webserver->hasArg("m")) {
WSContentBegin(200, CT_PLAIN);
uint32_t vidx = 0;
for (uint32_t i = 0; i <= sizeof(kModuleNiceList); i++) { // "}2'%d'>%s (%d)}3" - "}2'255'>UserTemplate (0)}3" - "}2'0'>Sonoff Basic (1)}3"
@ -1592,7 +1584,7 @@ void HandleModuleConfiguration(void)
return;
}
if (WebServer->hasArg("g")) {
if (Webserver->hasArg("g")) {
WSContentBegin(200, CT_PLAIN);
for (uint32_t j = 0; j < sizeof(kGpioNiceList); j++) {
midx = pgm_read_byte(kGpioNiceList + j);
@ -1605,7 +1597,7 @@ void HandleModuleConfiguration(void)
}
#ifndef USE_ADC_VCC
if (WebServer->hasArg("a")) {
if (Webserver->hasArg("a")) {
WSContentBegin(200, CT_PLAIN);
for (uint32_t j = 0; j < ADC0_END; j++) {
WSContentSend_P(HTTP_MODULE_TEMPLATE_REPLACE, j, GetTextIndexed(stemp, sizeof(stemp), j, kAdc0Names), j);
@ -1675,17 +1667,28 @@ void ModuleSaveSettings(void)
if (ValidGPIO(i, cmodule.io[i])) {
snprintf_P(webindex, sizeof(webindex), PSTR("g%d"), i);
WebGetArg(webindex, tmp, sizeof(tmp));
Settings.my_gp.io[i] = (!strlen(tmp)) ? 0 : atoi(tmp);
gpios += F(", " D_GPIO ); gpios += String(i); gpios += F(" "); gpios += String(Settings.my_gp.io[i]);
uint8_t value = (!strlen(tmp)) ? 0 : atoi(tmp);
#ifdef ESP8266
Settings.my_gp.io[i] = value;
#else // ESP32
if (i == ADC0_PIN) {
Settings.my_adc0 = value;
} else {
Settings.my_gp.io[i] = value;
}
#endif // ESP8266 - ESP32
gpios += F(", " D_GPIO ); gpios += String(i); gpios += F(" "); gpios += String(value);
}
}
}
#ifdef ESP8266
#ifndef USE_ADC_VCC
// WebGetArg("g17", tmp, sizeof(tmp));
WebGetArg("g" STR(ADC0_PIN), tmp, sizeof(tmp));
Settings.my_adc0 = (!strlen(tmp)) ? 0 : atoi(tmp);
gpios += F(", " D_ADC "0 "); gpios += String(Settings.my_adc0);
#endif // USE_ADC_VCC
#endif // ESP8266
AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_MODULE "%s " D_CMND_MODULE "%s"), ModuleName().c_str(), gpios.c_str());
}
@ -1720,7 +1723,7 @@ void HandleWifiConfiguration(void)
AddLog_P(LOG_LEVEL_DEBUG, S_LOG_HTTP, S_CONFIGURE_WIFI);
if (WebServer->hasArg("save") && HTTP_MANAGER_RESET_ONLY != Web.state) {
if (Webserver->hasArg("save") && HTTP_MANAGER_RESET_ONLY != Web.state) {
WifiSaveSettings();
WebRestart(2);
return;
@ -1731,7 +1734,7 @@ void HandleWifiConfiguration(void)
WSContentSendStyle();
if (HTTP_MANAGER_RESET_ONLY != Web.state) {
if (WebServer->hasArg("scan")) {
if (Webserver->hasArg("scan")) {
#ifdef USE_EMULATION
UdpDisconnect();
#endif // USE_EMULATION
@ -1844,7 +1847,7 @@ void HandleLoggingConfiguration(void)
AddLog_P(LOG_LEVEL_DEBUG, S_LOG_HTTP, S_CONFIGURE_LOGGING);
if (WebServer->hasArg("save")) {
if (Webserver->hasArg("save")) {
LoggingSaveSettings();
HandleConfiguration();
return;
@ -1909,7 +1912,7 @@ void HandleOtherConfiguration(void)
AddLog_P(LOG_LEVEL_DEBUG, S_LOG_HTTP, S_CONFIGURE_OTHER);
if (WebServer->hasArg("save")) {
if (Webserver->hasArg("save")) {
OtherSaveSettings();
WebRestart(1);
return;
@ -1973,7 +1976,7 @@ void OtherSaveSettings(void)
WebGetArg("wp", tmp, sizeof(tmp));
SettingsUpdateText(SET_WEBPWD, (!strlen(tmp)) ? "" : (strchr(tmp,'*')) ? SettingsText(SET_WEBPWD) : tmp);
Settings.flag.mqtt_enabled = WebServer->hasArg("b1"); // SetOption3 - Enable MQTT
Settings.flag.mqtt_enabled = Webserver->hasArg("b1"); // SetOption3 - Enable MQTT
#ifdef USE_EMULATION
UdpDisconnect();
#if defined(USE_EMULATION_WEMO) || defined(USE_EMULATION_HUE)
@ -1994,7 +1997,7 @@ void OtherSaveSettings(void)
/*
// This sometimes provides intermittent watchdog
bool template_activate = WebServer->hasArg("t2"); // Try this to tackle intermittent watchdog after execution of Template command
bool template_activate = Webserver->hasArg("t2"); // Try this to tackle intermittent watchdog after execution of Template command
WebGetArg("t1", tmp, sizeof(tmp));
if (strlen(tmp)) { // {"NAME":"12345678901234","GPIO":[255,255,255,255,255,255,255,255,255,255,255,255,255],"FLAG":255,"BASE":255}
char svalue[128];
@ -2010,7 +2013,7 @@ void OtherSaveSettings(void)
*/
WebGetArg("t1", tmp, sizeof(tmp));
if (strlen(tmp)) { // {"NAME":"12345678901234","GPIO":[255,255,255,255,255,255,255,255,255,255,255,255,255],"FLAG":255,"BASE":255}
snprintf_P(message, sizeof(message), PSTR(D_CMND_BACKLOG " " D_CMND_TEMPLATE " %s%s"), tmp, (WebServer->hasArg("t2")) ? "; " D_CMND_MODULE " 0" : "");
snprintf_P(message, sizeof(message), PSTR(D_CMND_BACKLOG " " D_CMND_TEMPLATE " %s%s"), tmp, (Webserver->hasArg("t2")) ? "; " D_CMND_MODULE " 0" : "");
ExecuteWebCommand(message, SRC_WEBGUI);
}
}
@ -2025,8 +2028,8 @@ void HandleBackupConfiguration(void)
if (!SettingsBufferAlloc()) { return; }
WiFiClient myClient = WebServer->client();
WebServer->setContentLength(sizeof(Settings));
WiFiClient myClient = Webserver->client();
Webserver->setContentLength(sizeof(Settings));
char attachment[TOPSZ];
@ -2036,7 +2039,7 @@ void HandleBackupConfiguration(void)
char hostname[sizeof(my_hostname)];
snprintf_P(attachment, sizeof(attachment), PSTR("attachment; filename=Config_%s_%s.dmp"), NoAlNumToUnderscore(hostname, my_hostname), my_version);
WebServer->sendHeader(F("Content-Disposition"), attachment);
Webserver->sendHeader(F("Content-Disposition"), attachment);
WSSend(200, CT_STREAM, "");
@ -2202,7 +2205,7 @@ void HandleInformation(void)
WSContentSend_P(PSTR("}1}2&nbsp;")); // Empty line
WSContentSend_P(PSTR("}1" D_ESP_CHIP_ID "}2%d"), ESP_getChipId());
WSContentSend_P(PSTR("}1" D_FLASH_CHIP_ID "}20x%06X"), ESP_getFlashChipId());
WSContentSend_P(PSTR("}1" D_FLASH_CHIP_SIZE "}2%dkB"), ESP_getFlashChipRealSize() / 1024);
WSContentSend_P(PSTR("}1" D_FLASH_CHIP_SIZE "}2%dkB"), ESP.getFlashChipRealSize() / 1024);
WSContentSend_P(PSTR("}1" D_PROGRAM_FLASH_SIZE "}2%dkB"), ESP.getFlashChipSize() / 1024);
WSContentSend_P(PSTR("}1" D_PROGRAM_SIZE "}2%dkB"), ESP_getSketchSize() / 1024);
WSContentSend_P(PSTR("}1" D_FREE_PROGRAM_SPACE "}2%dkB"), ESP.getFreeSketchSpace() / 1024);
@ -2336,7 +2339,7 @@ void HandleUploadLoop(void)
return;
}
HTTPUpload& upload = WebServer->upload();
HTTPUpload& upload = Webserver->upload();
if (UPLOAD_FILE_START == upload.status) {
restart_flag = 60;
@ -2498,6 +2501,16 @@ void HandleUploadLoop(void)
} else {
valid_settings = (settings_buffer[0] == CONFIG_FILE_SIGN);
}
if (valid_settings) {
#ifdef ESP8266
valid_settings = (0 == settings_buffer[0xF36]); // Settings.config_version
#endif // ESP8266
#ifdef ESP32
valid_settings = (1 == settings_buffer[0xF36]); // Settings.config_version
#endif // ESP32
}
if (valid_settings) {
SettingsDefaultSet2();
memcpy((char*)&Settings +16, settings_buffer +16, sizeof(Settings) -16);
@ -2549,8 +2562,8 @@ void HandleUploadLoop(void)
void HandlePreflightRequest(void)
{
HttpHeaderCors();
WebServer->sendHeader(F("Access-Control-Allow-Methods"), F("GET, POST"));
WebServer->sendHeader(F("Access-Control-Allow-Headers"), F("authorization"));
Webserver->sendHeader(F("Access-Control-Allow-Methods"), F("GET, POST"));
Webserver->sendHeader(F("Access-Control-Allow-Headers"), F("authorization"));
WSSend(200, CT_HTML, "");
}
@ -2562,54 +2575,54 @@ void HandleHttpCommand(void)
AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_HTTP D_COMMAND));
bool valid = true;
if (strlen(SettingsText(SET_WEBPWD))) {
char tmp1[33];
WebGetArg("user", tmp1, sizeof(tmp1));
char tmp2[strlen(SettingsText(SET_WEBPWD)) +1];
WebGetArg("password", tmp2, sizeof(tmp2));
if (!(!strcmp(tmp1, WEB_USERNAME) && !strcmp(tmp2, SettingsText(SET_WEBPWD)))) { valid = false; }
if (!(!strcmp(tmp1, WEB_USERNAME) && !strcmp(tmp2, SettingsText(SET_WEBPWD)))) {
WSContentBegin(401, CT_JSON);
WSContentSend_P(PSTR("{\"" D_RSLT_WARNING "\":\"" D_NEED_USER_AND_PASSWORD "\"}"));
WSContentEnd();
return;
}
}
WSContentBegin(200, CT_JSON);
if (valid) {
uint32_t curridx = web_log_index;
String svalue = WebServer->arg("cmnd");
if (svalue.length() && (svalue.length() < MQTT_MAX_PACKET_SIZE)) {
ExecuteWebCommand((char*)svalue.c_str(), SRC_WEBCOMMAND);
if (web_log_index != curridx) {
uint32_t counter = curridx;
WSContentSend_P(PSTR("{"));
bool cflg = false;
do {
char* tmp;
size_t len;
GetLog(counter, &tmp, &len);
if (len) {
// [14:49:36 MQTT: stat/wemos5/RESULT = {"POWER":"OFF"}] > [{"POWER":"OFF"}]
char* JSON = (char*)memchr(tmp, '{', len);
if (JSON) { // Is it a JSON message (and not only [15:26:08 MQT: stat/wemos5/POWER = O])
size_t JSONlen = len - (JSON - tmp);
if (JSONlen > sizeof(mqtt_data)) { JSONlen = sizeof(mqtt_data); }
char stemp[JSONlen];
strlcpy(stemp, JSON +1, JSONlen -2);
WSContentSend_P(PSTR("%s%s"), (cflg) ? "," : "", stemp);
cflg = true;
}
uint32_t curridx = web_log_index;
String svalue = Webserver->arg("cmnd");
if (svalue.length() && (svalue.length() < MQTT_MAX_PACKET_SIZE)) {
ExecuteWebCommand((char*)svalue.c_str(), SRC_WEBCOMMAND);
if (web_log_index != curridx) {
uint32_t counter = curridx;
WSContentSend_P(PSTR("{"));
bool cflg = false;
do {
char* tmp;
size_t len;
GetLog(counter, &tmp, &len);
if (len) {
// [14:49:36 MQTT: stat/wemos5/RESULT = {"POWER":"OFF"}] > [{"POWER":"OFF"}]
char* JSON = (char*)memchr(tmp, '{', len);
if (JSON) { // Is it a JSON message (and not only [15:26:08 MQT: stat/wemos5/POWER = O])
size_t JSONlen = len - (JSON - tmp);
if (JSONlen > sizeof(mqtt_data)) { JSONlen = sizeof(mqtt_data); }
char stemp[JSONlen];
strlcpy(stemp, JSON +1, JSONlen -2);
WSContentSend_P(PSTR("%s%s"), (cflg) ? "," : "", stemp);
cflg = true;
}
counter++;
counter &= 0xFF;
if (!counter) counter++; // Skip 0 as it is not allowed
} while (counter != web_log_index);
WSContentSend_P(PSTR("}"));
} else {
WSContentSend_P(PSTR("{\"" D_RSLT_WARNING "\":\"" D_ENABLE_WEBLOG_FOR_RESPONSE "\"}"));
}
}
counter++;
counter &= 0xFF;
if (!counter) counter++; // Skip 0 as it is not allowed
} while (counter != web_log_index);
WSContentSend_P(PSTR("}"));
} else {
WSContentSend_P(PSTR("{\"" D_RSLT_WARNING "\":\"" D_ENTER_COMMAND " cmnd=\"}"));
WSContentSend_P(PSTR("{\"" D_RSLT_WARNING "\":\"" D_ENABLE_WEBLOG_FOR_RESPONSE "\"}"));
}
} else {
WSContentSend_P(PSTR("{\"" D_RSLT_WARNING "\":\"" D_NEED_USER_AND_PASSWORD "\"}"));
WSContentSend_P(PSTR("{\"" D_RSLT_WARNING "\":\"" D_ENTER_COMMAND " cmnd=\"}"));
}
WSContentEnd();
}
@ -2620,7 +2633,7 @@ void HandleConsole(void)
{
if (!HttpCheckPriviledgedAccess()) { return; }
if (WebServer->hasArg("c2")) { // Console refresh requested
if (Webserver->hasArg("c2")) { // Console refresh requested
HandleConsoleRefresh();
return;
}
@ -2640,7 +2653,7 @@ void HandleConsoleRefresh(void)
bool cflg = true;
uint32_t counter = 0; // Initial start, should never be 0 again
String svalue = WebServer->arg("c1");
String svalue = Webserver->arg("c1");
if (svalue.length() && (svalue.length() < MQTT_MAX_PACKET_SIZE)) {
AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_COMMAND "%s"), svalue.c_str());
ExecuteWebCommand((char*)svalue.c_str(), SRC_WEBCONSOLE);
@ -2685,13 +2698,13 @@ void HandleConsoleRefresh(void)
void HandleNotFound(void)
{
// AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_HTTP "Not found (%s)"), WebServer->uri().c_str());
// AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_HTTP "Not found (%s)"), Webserver->uri().c_str());
if (CaptivePortal()) { return; } // If captive portal redirect instead of displaying the error page.
#ifdef USE_EMULATION
#ifdef USE_EMULATION_HUE
String path = WebServer->uri();
String path = Webserver->uri();
if ((EMUL_HUE == Settings.flag2.emulation) && (path.startsWith("/api"))) {
HandleHueApi(&path);
} else
@ -2699,9 +2712,9 @@ void HandleNotFound(void)
#endif // USE_EMULATION
{
WSContentBegin(404, CT_PLAIN);
WSContentSend_P(PSTR(D_FILE_NOT_FOUND "\n\nURI: %s\nMethod: %s\nArguments: %d\n"), WebServer->uri().c_str(), (WebServer->method() == HTTP_GET) ? "GET" : "POST", WebServer->args());
for (uint32_t i = 0; i < WebServer->args(); i++) {
WSContentSend_P(PSTR(" %s: %s\n"), WebServer->argName(i).c_str(), WebServer->arg(i).c_str());
WSContentSend_P(PSTR(D_FILE_NOT_FOUND "\n\nURI: %s\nMethod: %s\nArguments: %d\n"), Webserver->uri().c_str(), (Webserver->method() == HTTP_GET) ? "GET" : "POST", Webserver->args());
for (uint32_t i = 0; i < Webserver->args(); i++) {
WSContentSend_P(PSTR(" %s: %s\n"), Webserver->argName(i).c_str(), Webserver->arg(i).c_str());
}
WSContentEnd();
}
@ -2711,12 +2724,12 @@ void HandleNotFound(void)
bool CaptivePortal(void)
{
// Possible hostHeader: connectivitycheck.gstatic.com or 192.168.4.1
if ((WifiIsInManagerMode()) && !ValidIpAddress(WebServer->hostHeader().c_str())) {
if ((WifiIsInManagerMode()) && !ValidIpAddress(Webserver->hostHeader().c_str())) {
AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_HTTP D_REDIRECTED));
WebServer->sendHeader(F("Location"), String("http://") + WebServer->client().localIP().toString(), true);
Webserver->sendHeader(F("Location"), String("http://") + Webserver->client().localIP().toString(), true);
WSSend(302, CT_PLAIN, ""); // Empty content inhibits Content-length header so we have to close the socket ourselves.
WebServer->client().stop(); // Stop is needed because we sent no content length
Webserver->client().stop(); // Stop is needed because we sent no content length
return true;
}
return false;

View File

@ -1252,7 +1252,7 @@ void HandleMqttConfiguration(void)
AddLog_P(LOG_LEVEL_DEBUG, S_LOG_HTTP, S_CONFIGURE_MQTT);
if (WebServer->hasArg("save")) {
if (Webserver->hasArg("save")) {
MqttSaveSettings();
WebRestart(1);
return;
@ -1334,7 +1334,7 @@ bool Xdrv02(uint8_t function)
WSContentSend_P(HTTP_BTN_MENU_MQTT);
break;
case FUNC_WEB_ADD_HANDLER:
WebServer->on("/" WEB_HANDLE_MQTT, HandleMqttConfiguration);
Webserver->on("/" WEB_HANDLE_MQTT, HandleMqttConfiguration);
break;
#endif // USE_WEBSERVER
case FUNC_COMMAND:

View File

@ -1985,6 +1985,17 @@ bool isChannelGammaCorrected(uint32_t channel) {
return true;
}
// is the channel a regular PWM or ColorTemp control
bool isChannelCT(uint32_t channel) {
#ifdef ESP8266
if (PHILIPS == my_module_type) {
if ((LST_COLDWARM == Light.subtype) && (1 == channel)) { return true; } // PMW reserved for CT
if ((LST_RGBCW == Light.subtype) && (4 == channel)) { return true; } // PMW reserved for CT
}
#endif // ESP8266
return false;
}
// Calculate the Gamma correction, if any, for fading, using the fast Gamma curve (10 bits in+out)
uint16_t fadeGamma(uint32_t channel, uint16_t v) {
if (isChannelGammaCorrected(channel)) {
@ -2106,7 +2117,9 @@ void LightSetOutputs(const uint16_t *cur_col_10) {
if (pin[GPIO_PWM1 +i] < 99) {
//AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_APPLICATION "Cur_Col%d 10 bits %d"), i, cur_col_10[i]);
uint16_t cur_col = cur_col_10[i + Light.pwm_offset];
cur_col = cur_col > 0 ? changeUIntScale(cur_col, 0, Settings.pwm_range, Light.pwm_min, Light.pwm_max) : 0; // shrink to the range of pwm_min..pwm_max
if (!isChannelCT(i)) { // if CT don't use pwm_min and pwm_max
cur_col = cur_col > 0 ? changeUIntScale(cur_col, 0, Settings.pwm_range, Light.pwm_min, Light.pwm_max) : 0; // shrink to the range of pwm_min..pwm_max
}
analogWrite(pin[GPIO_PWM1 +i], bitRead(pwm_inverted, i) ? Settings.pwm_range - cur_col : cur_col);
}
}

View File

@ -559,7 +559,7 @@ void HandleDomoticzConfiguration(void)
AddLog_P(LOG_LEVEL_DEBUG, S_LOG_HTTP, S_CONFIGURE_DOMOTICZ);
if (WebServer->hasArg("save")) {
if (Webserver->hasArg("save")) {
DomoticzSaveSettings();
WebRestart(1);
return;
@ -651,7 +651,7 @@ bool Xdrv07(uint8_t function)
WSContentSend_P(HTTP_BTN_MENU_DOMOTICZ);
break;
case FUNC_WEB_ADD_HANDLER:
WebServer->on("/" WEB_HANDLE_DOMOTICZ, HandleDomoticzConfiguration);
Webserver->on("/" WEB_HANDLE_DOMOTICZ, HandleDomoticzConfiguration);
break;
#endif // USE_WEBSERVER
case FUNC_MQTT_SUBSCRIBE:

View File

@ -702,7 +702,7 @@ void HandleTimerConfiguration(void)
AddLog_P(LOG_LEVEL_DEBUG, S_LOG_HTTP, S_CONFIGURE_TIMER);
if (WebServer->hasArg("save")) {
if (Webserver->hasArg("save")) {
TimerSaveSettings();
HandleConfiguration();
return;
@ -740,7 +740,7 @@ void TimerSaveSettings(void)
char message[LOGSZ];
Timer timer;
Settings.flag3.timers_enable = WebServer->hasArg("e0"); // CMND_TIMERS
Settings.flag3.timers_enable = Webserver->hasArg("e0"); // CMND_TIMERS
WebGetArg("t0", tmp, sizeof(tmp));
char *p = tmp;
snprintf_P(message, sizeof(message), PSTR(D_LOG_MQTT D_CMND_TIMERS " %d"), Settings.flag3.timers_enable); // CMND_TIMERS
@ -781,7 +781,7 @@ bool Xdrv09(uint8_t function)
#endif // USE_RULES
break;
case FUNC_WEB_ADD_HANDLER:
WebServer->on("/" WEB_HANDLE_TIMER, HandleTimerConfiguration);
Webserver->on("/" WEB_HANDLE_TIMER, HandleTimerConfiguration);
break;
#endif // USE_TIMERS_WEB
#endif // USE_WEBSERVER

View File

@ -65,6 +65,35 @@ keywords if then else endif, or, and are better readable for beginners (others m
uint32_t EncodeLightId(uint8_t relay_id);
uint32_t DecodeLightId(uint32_t hue_id);
#if defined(ESP32) && defined(ESP32_SCRIPT_SIZE) && !defined(USE_24C256) && !defined(USE_SCRIPT_FATFS)
#include "FS.h"
#include "SPIFFS.h"
void SaveFile(const char *name,const uint8_t *buf,uint32_t len) {
File file = SPIFFS.open(name, FILE_WRITE);
if (!file) return;
file.write(buf, len);
file.close();
}
#define FORMAT_SPIFFS_IF_FAILED true
uint8_t spiffs_mounted=0;
void LoadFile(const char *name,uint8_t *buf,uint32_t len) {
if (!spiffs_mounted) {
if(!SPIFFS.begin(FORMAT_SPIFFS_IF_FAILED)){
//Serial.println("SPIFFS Mount Failed");
return;
}
spiffs_mounted=1;
}
File file = SPIFFS.open(name);
if (!file) return;
file.read(buf, len);
file.close();
}
#endif
// offsets epoch readings by 1.1.2019 00:00:00 to fit into float with second resolution
#define EPOCH_OFFSET 1546300800
@ -3341,8 +3370,8 @@ void Script_FileUploadConfiguration(void)
if (!HttpCheckPriviledgedAccess()) { return; }
if (WebServer->hasArg("download")) {
String stmp = WebServer->arg("download");
if (Webserver->hasArg("download")) {
String stmp = Webserver->arg("download");
char *cp=(char*)stmp.c_str();
if (DownloadFile(cp)) {
// is directory
@ -3386,7 +3415,7 @@ void script_upload(void) {
//AddLog_P(LOG_LEVEL_INFO, PSTR("HTP: file upload"));
HTTPUpload& upload = WebServer->upload();
HTTPUpload& upload = Webserver->upload();
if (upload.status == UPLOAD_FILE_START) {
char npath[48];
sprintf(npath,"%s/%s",path,upload.filename.c_str());
@ -3402,7 +3431,7 @@ void script_upload(void) {
}
} else {
Web.upload_error=1;
WebServer->send(500, "text/plain", "500: couldn't create file");
Webserver->send(500, "text/plain", "500: couldn't create file");
}
}
@ -3428,8 +3457,8 @@ uint8_t DownloadFile(char *file) {
uint32_t flen=download_file.size();
download_Client = WebServer->client();
WebServer->setContentLength(flen);
download_Client = Webserver->client();
Webserver->setContentLength(flen);
char attachment[100];
char *cp;
@ -3440,7 +3469,7 @@ uint8_t DownloadFile(char *file) {
}
}
snprintf_P(attachment, sizeof(attachment), PSTR("attachment; filename=%s"),cp);
WebServer->sendHeader(F("Content-Disposition"), attachment);
Webserver->sendHeader(F("Content-Disposition"), attachment);
WSSend(200, CT_STREAM, "");
uint8_t buff[512];
@ -3472,7 +3501,7 @@ uint8_t DownloadFile(char *file) {
void HandleScriptTextareaConfiguration(void) {
if (!HttpCheckPriviledgedAccess()) { return; }
if (WebServer->hasArg("save")) {
if (Webserver->hasArg("save")) {
ScriptSaveSettings();
HandleConfiguration();
return;
@ -3486,13 +3515,13 @@ void HandleScriptConfiguration(void) {
AddLog_P(LOG_LEVEL_DEBUG, S_LOG_HTTP, S_CONFIGURE_SCRIPT);
#ifdef USE_SCRIPT_FATFS
if (WebServer->hasArg("d1")) {
if (Webserver->hasArg("d1")) {
DownloadFile(glob_script_mem.flink[0]);
}
if (WebServer->hasArg("d2")) {
if (Webserver->hasArg("d2")) {
DownloadFile(glob_script_mem.flink[1]);
}
if (WebServer->hasArg("upl")) {
if (Webserver->hasArg("upl")) {
Script_FileUploadConfiguration();
}
#endif
@ -3532,14 +3561,14 @@ void HandleScriptConfiguration(void) {
void ScriptSaveSettings(void) {
if (WebServer->hasArg("c1")) {
if (Webserver->hasArg("c1")) {
bitWrite(Settings.rule_enabled,0,1);
} else {
bitWrite(Settings.rule_enabled,0,0);
}
String str = WebServer->arg("t1");
String str = Webserver->arg("t1");
if (*str.c_str()) {
@ -3597,6 +3626,11 @@ void ScriptSaveSettings(void) {
}
#endif
#if defined(ESP32) && defined(ESP32_SCRIPT_SIZE) && !defined(USE_24C256) && !defined(USE_SCRIPT_FATFS)
if (glob_script_mem.flags&1) {
SaveFile("/script.txt",(uint8_t*)glob_script_mem.script_ram,ESP32_SCRIPT_SIZE);
}
#endif
}
if (glob_script_mem.script_mem) {
@ -3990,11 +4024,11 @@ void Script_Handle_Hue(String *path) {
uint8_t device = DecodeLightId(atoi(path->c_str()));
uint8_t index = device-devices_present-1;
if (WebServer->args()) {
if (Webserver->args()) {
response = "[";
StaticJsonBuffer<400> jsonBuffer;
JsonObject &hue_json = jsonBuffer.parseObject(WebServer->arg((WebServer->args())-1));
JsonObject &hue_json = jsonBuffer.parseObject(Webserver->arg((Webserver->args())-1));
if (hue_json.containsKey("on")) {
response += FPSTR(sHUE_LIGHT_RESPONSE_JSON);
@ -4436,8 +4470,8 @@ void Script_Check_HTML_Setvars(void) {
if (!HttpCheckPriviledgedAccess()) { return; }
if (WebServer->hasArg("sv")) {
String stmp = WebServer->arg("sv");
if (Webserver->hasArg("sv")) {
String stmp = Webserver->arg("sv");
char cmdbuf[64];
memset(cmdbuf,0,sizeof(cmdbuf));
char *cp=cmdbuf;
@ -4820,6 +4854,13 @@ bool Xdrv10(uint8_t function)
switch (function) {
case FUNC_PRE_INIT:
/*
#ifdef USE_WEBCAM
if (Settings.module==ESP32_CAM_AITHINKER) {
webcam_setup();
}
#endif
*/
// set defaults to rules memory
glob_script_mem.script_ram=Settings.rules[0];
glob_script_mem.script_size=MAX_SCRIPT_SIZE;
@ -4889,6 +4930,21 @@ bool Xdrv10(uint8_t function)
}
#endif
#if defined(ESP32) && defined(ESP32_SCRIPT_SIZE) && !defined(USE_24C256) && !defined(USE_SCRIPT_FATFS)
char *script;
script=(char*)calloc(ESP32_SCRIPT_SIZE+4,1);
if (!script) break;
LoadFile("/script.txt",(uint8_t*)script,ESP32_SCRIPT_SIZE);
glob_script_mem.script_ram=script;
glob_script_mem.script_size=ESP32_SCRIPT_SIZE;
script[ESP32_SCRIPT_SIZE-1]=0;
// use rules storage for permanent vars
glob_script_mem.script_pram=(uint8_t*)Settings.rules[0];
glob_script_mem.script_pram_size=MAX_SCRIPT_SIZE;
glob_script_mem.flags=1;
#endif
// assure permanent memory is 4 byte aligned
{ uint32_t ptr=(uint32_t)glob_script_mem.script_pram;
ptr&=0xfffffffc;
@ -4932,13 +4988,13 @@ bool Xdrv10(uint8_t function)
WSContentSend_P(HTTP_BTN_MENU_RULES);
break;
case FUNC_WEB_ADD_HANDLER:
WebServer->on("/" WEB_HANDLE_SCRIPT, HandleScriptConfiguration);
WebServer->on("/ta",HTTP_POST, HandleScriptTextareaConfiguration);
Webserver->on("/" WEB_HANDLE_SCRIPT, HandleScriptConfiguration);
Webserver->on("/ta",HTTP_POST, HandleScriptTextareaConfiguration);
#ifdef USE_SCRIPT_FATFS
WebServer->on("/u3", HTTP_POST,[]() { WebServer->sendHeader("Location","/u3");WebServer->send(303);},script_upload);
WebServer->on("/u3", HTTP_GET,ScriptFileUploadSuccess);
WebServer->on("/upl", HTTP_GET,Script_FileUploadConfiguration);
Webserver->on("/u3", HTTP_POST,[]() { Webserver->sendHeader("Location","/u3");Webserver->send(303);},script_upload);
Webserver->on("/u3", HTTP_GET,ScriptFileUploadSuccess);
Webserver->on("/upl", HTTP_GET,Script_FileUploadConfiguration);
#endif
break;
#endif // USE_WEBSERVER

View File

@ -809,22 +809,22 @@ void HandleKNXConfiguration(void)
char tmp[100];
String stmp;
if ( WebServer->hasArg("save") ) {
if ( Webserver->hasArg("save") ) {
KNX_Save_Settings();
HandleConfiguration();
}
else
{
if ( WebServer->hasArg("btn_add") ) {
if ( WebServer->arg("btn_add") == "1" ) {
if ( Webserver->hasArg("btn_add") ) {
if ( Webserver->arg("btn_add") == "1" ) {
stmp = WebServer->arg("GAop"); //option selected
stmp = Webserver->arg("GAop"); //option selected
uint8_t GAop = stmp.toInt();
stmp = WebServer->arg("GA_FNUM");
stmp = Webserver->arg("GA_FNUM");
uint8_t GA_FNUM = stmp.toInt();
stmp = WebServer->arg("GA_AREA");
stmp = Webserver->arg("GA_AREA");
uint8_t GA_AREA = stmp.toInt();
stmp = WebServer->arg("GA_FDEF");
stmp = Webserver->arg("GA_FDEF");
uint8_t GA_FDEF = stmp.toInt();
if (GAop) {
@ -834,13 +834,13 @@ void HandleKNXConfiguration(void)
else
{
stmp = WebServer->arg("CBop"); //option selected
stmp = Webserver->arg("CBop"); //option selected
uint8_t CBop = stmp.toInt();
stmp = WebServer->arg("CB_FNUM");
stmp = Webserver->arg("CB_FNUM");
uint8_t CB_FNUM = stmp.toInt();
stmp = WebServer->arg("CB_AREA");
stmp = Webserver->arg("CB_AREA");
uint8_t CB_AREA = stmp.toInt();
stmp = WebServer->arg("CB_FDEF");
stmp = Webserver->arg("CB_FDEF");
uint8_t CB_FDEF = stmp.toInt();
if (CBop) {
@ -848,19 +848,19 @@ void HandleKNXConfiguration(void)
}
}
}
else if ( WebServer->hasArg("btn_del_ga") )
else if ( Webserver->hasArg("btn_del_ga") )
{
stmp = WebServer->arg("btn_del_ga");
stmp = Webserver->arg("btn_del_ga");
uint8_t GA_NUM = stmp.toInt();
KNX_DEL_GA(GA_NUM);
}
else if ( WebServer->hasArg("btn_del_cb") )
else if ( Webserver->hasArg("btn_del_cb") )
{
stmp = WebServer->arg("btn_del_cb");
stmp = Webserver->arg("btn_del_cb");
uint8_t CB_NUM = stmp.toInt();
KNX_DEL_CB(CB_NUM);
@ -954,16 +954,16 @@ void KNX_Save_Settings(void)
String stmp;
address_t KNX_addr;
Settings.flag.knx_enabled = WebServer->hasArg("b1");
Settings.flag.knx_enable_enhancement = WebServer->hasArg("b2");
Settings.flag.knx_enabled = Webserver->hasArg("b1");
Settings.flag.knx_enable_enhancement = Webserver->hasArg("b2");
AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_KNX D_ENABLED ": %d, " D_KNX_ENHANCEMENT ": %d"),
Settings.flag.knx_enabled, Settings.flag.knx_enable_enhancement );
stmp = WebServer->arg("area");
stmp = Webserver->arg("area");
KNX_addr.pa.area = stmp.toInt();
stmp = WebServer->arg("line");
stmp = Webserver->arg("line");
KNX_addr.pa.line = stmp.toInt();
stmp = WebServer->arg("member");
stmp = Webserver->arg("member");
KNX_addr.pa.member = stmp.toInt();
Settings.knx_physsical_addr = KNX_addr.value;
knx.physical_address_set( KNX_addr ); // Set Physical KNX Address of the device
@ -1224,7 +1224,7 @@ bool Xdrv11(uint8_t function)
WSContentSend_P(HTTP_BTN_MENU_KNX);
break;
case FUNC_WEB_ADD_HANDLER:
WebServer->on("/kn", HandleKNXConfiguration);
Webserver->on("/kn", HandleKNXConfiguration);
break;
#endif // USE_KNX_WEB_MENU
#endif // USE_WEBSERVER

View File

@ -448,7 +448,7 @@ static const char * FIRST_GEN_UA[] = { // list of User-Agents signature
// Check if the Echo device is of 1st generation, which triggers different results
uint32_t findEchoGeneration(void) {
// result is 1 for 1st gen, 2 for 2nd gen and further
String user_agent = WebServer->header("User-Agent");
String user_agent = Webserver->header("User-Agent");
uint32_t gen = 2;
for (uint32_t i = 0; i < sizeof(FIRST_GEN_UA)/sizeof(char*); i++) {
@ -521,11 +521,11 @@ void HueLightsCommand(uint8_t device, uint32_t device_id, String &response) {
const size_t buf_size = 100;
char * buf = (char*) malloc(buf_size);
if (WebServer->args()) {
if (Webserver->args()) {
response = "[";
StaticJsonBuffer<300> jsonBuffer;
JsonObject &hue_json = jsonBuffer.parseObject(WebServer->arg((WebServer->args())-1));
JsonObject &hue_json = jsonBuffer.parseObject(Webserver->arg((Webserver->args())-1));
if (hue_json.containsKey("on")) {
on = hue_json["on"];
snprintf_P(buf, buf_size,
@ -542,6 +542,7 @@ void HueLightsCommand(uint8_t device, uint32_t device_id, String &response) {
}
} else {
#endif
/*
switch(on)
{
case false : ExecuteCommandPower(device, POWER_OFF, SRC_HUE);
@ -549,6 +550,8 @@ void HueLightsCommand(uint8_t device, uint32_t device_id, String &response) {
case true : ExecuteCommandPower(device, POWER_ON, SRC_HUE);
break;
}
*/
ExecuteCommandPower(device, (on) ? POWER_ON : POWER_OFF, SRC_HUE);
response += buf;
resp = true;
#ifdef USE_SHUTTER
@ -827,8 +830,8 @@ void HandleHueApi(String *path)
path->remove(0, 4); // remove /api
uint16_t apilen = path->length();
AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR(D_LOG_HTTP D_HUE_API " (%s)"), path->c_str()); // HTP: Hue API (//lights/1/state
for (args = 0; args < WebServer->args(); args++) {
String json = WebServer->arg(args);
for (args = 0; args < Webserver->args(); args++) {
String json = Webserver->arg(args);
AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR(D_LOG_HTTP D_HUE_POST_ARGS " (%s)"), json.c_str()); // HTP: Hue POST args ({"on":false})
}
@ -861,7 +864,7 @@ bool Xdrv20(uint8_t function)
#endif
switch (function) {
case FUNC_WEB_ADD_HANDLER:
WebServer->on(F("/description.xml"), HandleUpnpSetupHue);
Webserver->on(F("/description.xml"), HandleUpnpSetupHue);
break;
}
}

View File

@ -198,7 +198,7 @@ void HandleUpnpEvent(void)
AddLog_P(LOG_LEVEL_DEBUG, S_LOG_HTTP, PSTR(D_WEMO_BASIC_EVENT));
char event[500];
strlcpy(event, WebServer->arg(0).c_str(), sizeof(event));
strlcpy(event, Webserver->arg(0).c_str(), sizeof(event));
// AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR("\n%s"), event);
@ -259,10 +259,10 @@ bool Xdrv21(uint8_t function)
if (devices_present && (EMUL_WEMO == Settings.flag2.emulation)) {
switch (function) {
case FUNC_WEB_ADD_HANDLER:
WebServer->on("/upnp/control/basicevent1", HTTP_POST, HandleUpnpEvent);
WebServer->on("/eventservice.xml", HandleUpnpService);
WebServer->on("/metainfoservice.xml", HandleUpnpMetaService);
WebServer->on("/setup.xml", HandleUpnpSetupWemo);
Webserver->on("/upnp/control/basicevent1", HTTP_POST, HandleUpnpEvent);
Webserver->on("/eventservice.xml", HandleUpnpService);
Webserver->on("/metainfoservice.xml", HandleUpnpMetaService);
Webserver->on("/setup.xml", HandleUpnpSetupWemo);
break;
}
}

View File

@ -25,15 +25,15 @@ void ZigbeeZCLSend_Raw(uint16_t dtsAddr, uint16_t groupaddr, uint16_t clusterId,
// Get an JSON attribute, with case insensitive key search
JsonVariant &getCaseInsensitive(const JsonObject &json, const char *needle) {
const JsonVariant &getCaseInsensitive(const JsonObject &json, const char *needle) {
// key can be in PROGMEM
if ((nullptr == &json) || (nullptr == needle) || (0 == pgm_read_byte(needle))) {
return *(JsonVariant*)nullptr;
}
for (auto kv : json) {
const char *key = kv.key;
JsonVariant &value = kv.value;
for (JsonObject::const_iterator it=json.begin(); it!=json.end(); ++it) {
const char *key = it->key;
const JsonVariant &value = it->value;
if (0 == strcasecmp_P(key, needle)) {
return value;

View File

@ -65,7 +65,7 @@ typedef int32_t (*Z_DeviceTimer)(uint16_t shortaddr, uint16_t groupaddr, uint16_
typedef enum Z_Def_Category {
Z_CAT_NONE = 0, // no category, it will happen anyways
Z_CAT_READ_ATTR, // Attribute reporting, either READ_ATTRIBUTE or REPORT_ATTRIBUTE, we coalesce all attributes reported if we can
Z_CAT_VIRTUAL_ATTR, // Creation of a virtual attribute, typically after a time-out. Ex: Aqara presence sensor
Z_CAT_VIRTUAL_OCCUPANCY, // Creation of a virtual attribute, typically after a time-out. Ex: Aqara presence sensor
Z_CAT_REACHABILITY, // timer set to measure reachability of device, i.e. if we don't get an answer after 1s, it is marked as unreachable (for Alexa)
Z_CAT_READ_0006, // Read 0x0006 cluster
Z_CAT_READ_0008, // Read 0x0008 cluster

View File

@ -190,23 +190,21 @@ void ZigbeeHandleHue(uint16_t shortaddr, uint32_t device_id, String &response) {
const size_t buf_size = 100;
char * buf = (char*) malloc(buf_size);
if (WebServer->args()) {
if (Webserver->args()) {
response = "[";
StaticJsonBuffer<300> jsonBuffer;
JsonObject &hue_json = jsonBuffer.parseObject(WebServer->arg((WebServer->args())-1));
JsonObject &hue_json = jsonBuffer.parseObject(Webserver->arg((Webserver->args())-1));
if (hue_json.containsKey("on")) {
on = hue_json["on"];
snprintf_P(buf, buf_size,
PSTR("{\"success\":{\"/lights/%d/state/on\":%s}}"),
device_id, on ? "true" : "false");
switch(on)
{
case false : ZigbeeHuePower(shortaddr, 0x00);
break;
case true : ZigbeeHuePower(shortaddr, 0x01);
break;
if (on) {
ZigbeeHuePower(shortaddr, 0x01);
} else {
ZigbeeHuePower(shortaddr, 0x00);
}
response += buf;
resp = true;

File diff suppressed because it is too large Load Diff

View File

@ -53,7 +53,7 @@ ZF(DimmerMove) ZF(DimmerStep)
ZF(HueMove) ZF(HueStep) ZF(SatMove) ZF(SatStep) ZF(ColorMove) ZF(ColorStep)
ZF(ArrowClick) ZF(ArrowHold) ZF(ArrowRelease) ZF(ZoneStatusChange)
ZF(xxxx00) ZF(xxxx) ZF(01xxxx) ZF(00) ZF(01) ZF() ZF(xxxxyy) ZF(001902) ZF(011902) ZF(xxyyyy) ZF(xx)
ZF(xxxx00) ZF(xxxx) ZF(01xxxx) ZF(00) ZF(01) ZF() ZF(xxxxyy) ZF(00190200) ZF(01190200) ZF(xxyyyy) ZF(xx)
ZF(xx000A00) ZF(xx0A00) ZF(xxyy0A00) ZF(xxxxyyyy0A00) ZF(xxxx0A00) ZF(xx0A)
ZF(xx190A00) ZF(xx19) ZF(xx190A) ZF(xxxxyyyy) ZF(xxxxyyzz) ZF(xxyyzzzz) ZF(xxyyyyzz)
@ -82,8 +82,8 @@ const Z_CommandConverter Z_Commands[] PROGMEM = {
// Light & Shutter commands
{ Z(Power), 0x0006, 0xFF, 0x01, Z() }, // 0=Off, 1=On, 2=Toggle
{ Z(Dimmer), 0x0008, 0x04, 0x01, Z(xx0A00) }, // Move to Level with On/Off, xx=0..254 (255 is invalid)
{ Z(DimmerUp), 0x0008, 0x06, 0x01, Z(001902) }, // Step up by 10%, 0.2 secs
{ Z(DimmerDown), 0x0008, 0x06, 0x01, Z(011902) }, // Step down by 10%, 0.2 secs
{ Z(DimmerUp), 0x0008, 0x06, 0x01, Z(00190200) }, // Step up by 10%, 0.2 secs
{ Z(DimmerDown), 0x0008, 0x06, 0x01, Z(01190200) }, // Step down by 10%, 0.2 secs
{ Z(DimmerStop), 0x0008, 0x03, 0x01, Z() }, // Stop any Dimmer animation
{ Z(ResetAlarm), 0x0009, 0x00, 0x01, Z(xxyyyy) }, // Reset alarm (alarm code + cluster identifier)
{ Z(ResetAllAlarms), 0x0009, 0x01, 0x01, Z() }, // Reset all alarms

View File

@ -534,7 +534,9 @@ void Z_AqaraOccupancy(uint16_t shortaddr, uint16_t cluster, uint8_t endpoint, co
uint32_t occupancy = strToUInt(val_endpoint);
if (occupancy) {
zigbee_devices.setTimer(shortaddr, 0 /* groupaddr */, OCCUPANCY_TIMEOUT, cluster, endpoint, Z_CAT_VIRTUAL_ATTR, 0, &Z_OccupancyCallback);
zigbee_devices.setTimer(shortaddr, 0 /* groupaddr */, OCCUPANCY_TIMEOUT, cluster, endpoint, Z_CAT_VIRTUAL_OCCUPANCY, 0, &Z_OccupancyCallback);
} else {
zigbee_devices.resetTimersForDevice(shortaddr, 0 /* groupaddr */, Z_CAT_VIRTUAL_OCCUPANCY);
}
}
}

View File

@ -160,7 +160,7 @@ void HandlePcf8574(void)
AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_HTTP D_CONFIGURE_PCF8574));
if (WebServer->hasArg("save")) {
if (Webserver->hasArg("save")) {
Pcf8574SaveSettings();
WebRestart(1);
return;
@ -193,9 +193,9 @@ void Pcf8574SaveSettings(void)
char stemp[7];
char tmp[100];
//AddLog_P(LOG_LEVEL_DEBUG, PSTR("PCF: Start working on Save arguements: inverted:%d")), WebServer->hasArg("b1");
//AddLog_P(LOG_LEVEL_DEBUG, PSTR("PCF: Start working on Save arguements: inverted:%d")), Webserver->hasArg("b1");
Settings.flag3.pcf8574_ports_inverted = WebServer->hasArg("b1"); // SetOption81 - Invert all ports on PCF8574 devices
Settings.flag3.pcf8574_ports_inverted = Webserver->hasArg("b1"); // SetOption81 - Invert all ports on PCF8574 devices
for (byte idx = 0; idx < Pcf8574.max_devices; idx++) {
byte count=0;
byte n = Settings.pcf8574_config[idx];
@ -248,7 +248,7 @@ bool Xdrv28(uint8_t function)
WSContentSend_P(HTTP_BTN_MENU_PCF8574);
break;
case FUNC_WEB_ADD_HANDLER:
WebServer->on("/" WEB_HANDLE_PCF8574, HandlePcf8574);
Webserver->on("/" WEB_HANDLE_PCF8574, HandlePcf8574);
break;
#endif // USE_WEBSERVER
}

View File

@ -21,7 +21,10 @@
#define XDRV_38 38
#include <ping.h>
#include "lwip/icmp.h"
#include "lwip/inet_chksum.h"
#include "lwip/raw.h"
#include "lwip/timeouts.h"
const char kPingCommands[] PROGMEM = "|" // no prefix
D_CMND_PING
@ -31,119 +34,291 @@ void (* const PingCommand[])(void) PROGMEM = {
&CmndPing,
};
// inspired by https://github.com/dancol90/ESP8266Ping
typedef struct Ping_t {
uint16_t total_count; // total count if packets sent
uint16_t timeout_count; // time-outs (no responses)
uint32_t min_time; // minimum time in ms for a successful response
uint32_t max_time; // maximum time in ms for a successful response
uint32_t sum_time; // cumulated time in ms for all successful responses (used to compute the average)
bool busy; // is ping on-going
bool done; // indicates the ping campaign is finished
} Ping_t;
ping_option ping_opt;
Ping_t ping;
extern "C" {
// callbacks for ping
extern uint32 system_relative_time(uint32 time);
extern void ets_bzero(void *s, size_t n);
// called after a ping response is received or time-out
void ICACHE_RAM_ATTR ping_recv_cb(ping_option *popt, struct ping_resp *p_resp) {
// If successful
if (p_resp->ping_err >= 0) {
uint32_t resp_time = p_resp->resp_time;
ping.sum_time += resp_time;
if (resp_time < ping.min_time) { ping.min_time = resp_time; }
if (resp_time > ping.max_time) { ping.max_time = resp_time; }
const uint16_t Ping_ID = 0xAFAF; // PING packet ID
const size_t Ping_data_size = 32; // default packet size
const uint32_t Ping_timeout_ms = 1000; // default time-out of 1 second, which is enough for LAN/WIFI
const uint32_t Ping_coarse = 1000; // interval between sending packets, 1 packet every second
typedef struct Ping_t {
uint32 ip; // target IPv4 address
Ping_t *next; // next object in linked list
uint16_t seq_num; // next sequence number
uint16_t seqno; // reject a packet already received
uint8_t success_count; // sucessful responses received
uint8_t timeout_count; // time-outs (no responses)
uint8_t to_send_count; // number of packets remaining to send
uint32_t ping_time_sent; // timestamp when the packet was sent
uint32_t min_time; // minimum time in ms for a successful response
uint32_t max_time; // maximum time in ms for a successful response
uint32_t sum_time; // cumulated time in ms for all successful responses (used to compute the average)
bool done; // indicates the ping campaign is finished
bool fast; // fast mode, i.e. stop pings when first successful response
} Ping_t;
// globals
Ping_t *ping_head = nullptr; // head of the Linked List for ping objects
struct raw_pcb *t_ping_pcb = nullptr; // registered with first ping, deregistered after last ping, the same pcb is used for all packets
// ================================================================================
// Find the Ping object indexed by IP address
// ================================================================================
//
// find the ping structure corresponding to the specified IP, or nullptr if not found
//
Ping_t ICACHE_FLASH_ATTR * t_ping_find(uint32_t ip) {
Ping_t *ping = ping_head;
while (ping != nullptr) {
if (ping->ip == ip) {
return ping;
}
ping = ping->next;
}
return nullptr;
}
// ================================================================================
// Timer called a packet response is in time-out
// ================================================================================
//
// called after the ICMP timeout occured
// we never received the packet, increase the timeout count
//
void ICACHE_FLASH_ATTR t_ping_timeout(void* arg) {
Ping_t *ping = (Ping_t*) arg;
ping->timeout_count++;
}
// ================================================================================
// Send ICMP packet
// ================================================================================
// Prepare a echo ICMP request
//
void ICACHE_FLASH_ATTR t_ping_prepare_echo(struct icmp_echo_hdr *iecho, uint16_t len, Ping_t *ping) {
size_t data_len = len - sizeof(struct icmp_echo_hdr);
ICMPH_TYPE_SET(iecho, ICMP_ECHO);
ICMPH_CODE_SET(iecho, 0);
iecho->chksum = 0;
iecho->id = Ping_ID;
ping->seq_num++;
if (ping->seq_num == 0x7fff) { ping->seq_num = 0; }
iecho->seqno = htons(ping->seq_num); // TODO
/* fill the additional data buffer with some data */
for (uint32_t i = 0; i < data_len; i++) {
((char*)iecho)[sizeof(struct icmp_echo_hdr) + i] = (char)i;
}
iecho->chksum = inet_chksum(iecho, len);
}
//
// send the ICMP packet
//
void ICACHE_FLASH_ATTR t_ping_send(struct raw_pcb *raw, Ping_t *ping) {
struct pbuf *p;
uint16_t ping_size = sizeof(struct icmp_echo_hdr) + Ping_data_size;
ping->ping_time_sent = system_get_time();
p = pbuf_alloc(PBUF_IP, ping_size, PBUF_RAM);
if (!p) { return; }
if ((p->len == p->tot_len) && (p->next == nullptr)) {
ip_addr_t ping_target;
struct icmp_echo_hdr *iecho;
ping_target.addr = ping->ip;
iecho = (struct icmp_echo_hdr *) p->payload;
t_ping_prepare_echo(iecho, ping_size, ping);
raw_sendto(raw, p, &ping_target);
}
pbuf_free(p);
}
// ================================================================================
// Timer called when it's time to send next packet, of when finished
// ================================================================================
// this timer is called every x seconds to send a new packet, whatever happened to the previous packet
static void ICACHE_FLASH_ATTR t_ping_coarse_tmr(void *arg) {
Ping_t *ping = (Ping_t*) arg;
if (ping->to_send_count > 0) {
ping->to_send_count--;
// have we sent all packets?
t_ping_send(t_ping_pcb, ping);
sys_timeout(Ping_timeout_ms, t_ping_timeout, ping);
sys_timeout(Ping_coarse, t_ping_coarse_tmr, ping);
} else {
sys_untimeout(t_ping_coarse_tmr, ping);
ping->done = true;
}
}
// called after the ping campaign is finished
void ICACHE_RAM_ATTR ping_sent_cb(ping_option *popt, struct ping_resp *p_resp) {
// copy counters to build the MQTT response
ping.total_count = p_resp->total_count;
ping.timeout_count = p_resp->timeout_count;
ping.done = true;
// ================================================================================
// Callback: a packet response was received
// ================================================================================
//
// Reveived packet
//
static uint8_t ICACHE_FLASH_ATTR t_ping_recv(void *arg, struct raw_pcb *pcb, struct pbuf *p, const ip_addr_t *addr) {
Ping_t *ping = t_ping_find(addr->addr);
if (nullptr == ping) { // unknown source address
return 0; // don't eat the packet and ignore it
}
if (pbuf_header( p, -PBUF_IP_HLEN)==0) {
struct icmp_echo_hdr *iecho;
iecho = (struct icmp_echo_hdr *)p->payload;
if ((iecho->id == Ping_ID) && (iecho->seqno == htons(ping->seq_num)) && iecho->type == ICMP_ER) {
if (iecho->seqno != ping->seqno){ // debounce already received packet
/* do some ping result processing */
sys_untimeout(t_ping_timeout, ping); // remove time-out handler
uint32_t delay = system_relative_time(ping->ping_time_sent);
delay /= 1000;
ping->sum_time += delay;
if (delay < ping->min_time) { ping->min_time = delay; }
if (delay > ping->max_time) { ping->max_time = delay; }
ping->success_count++;
ping->seqno = iecho->seqno;
if (ping->fast) { // if fast mode, abort further pings when first successful response is received
sys_untimeout(t_ping_coarse_tmr, ping);
ping->done = true;
ping->to_send_count = 0;
}
}
pbuf_free(p);
return 1; /* eat the packet */
}
}
return 0; /* don't eat the packet */
}
// ================================================================================
// Internal structure PCB management
// ================================================================================
// we are going to send a packet, make sure pcb is initialized
void t_ping_register_pcb(void) {
if (nullptr == t_ping_pcb) {
t_ping_pcb = raw_new(IP_PROTO_ICMP);
raw_recv(t_ping_pcb, t_ping_recv, nullptr); // we cannot register data structure here as we can only register one
raw_bind(t_ping_pcb, IP_ADDR_ANY);
}
}
// we have finsihed a ping series, deallocated if no more ongoing
void t_ping_deregister_pcb(void) {
if (nullptr == ping_head) { // deregister only if no ping is flying
raw_remove(t_ping_pcb);
t_ping_pcb = nullptr;
}
}
// ================================================================================
// Start pings
// ================================================================================
bool t_ping_start(uint32_t ip, uint32_t count) {
// check if pings are already ongoing for this IP
if (t_ping_find(ip)) {
return false;
}
Ping_t *ping = new Ping_t();
if (0 == count) {
count = 4;
ping->fast = true;
}
ping->min_time = UINT32_MAX;
ping->ip = ip;
ping->to_send_count = count - 1;
// add to Linked List from head
ping->next = ping_head;
ping_head = ping; // insert at head
t_ping_register_pcb();
t_ping_send(t_ping_pcb, ping);
// set timers for time-out and cadence
sys_timeout(Ping_timeout_ms, t_ping_timeout, ping);
sys_timeout(Ping_coarse, t_ping_coarse_tmr, ping);
}
}
// Check if any ping requests is completed, and publish the results
void PingResponsePoll(void) {
if (ping.done) {
uint32_t success = ping.total_count - ping.timeout_count;
uint32_t ip = ping_opt.ip;
Ping_t *ping = ping_head;
Ping_t **prev_link = &ping_head; // previous link pointer (used to remove en entry)
// Serial.printf(
// "DEBUG ping_sent_cb: ping reply\n"
// "\tsuccess_count = %d \n"
// "\ttimeout_count = %d \n"
// "\tmin_time = %d \n"
// "\tmax_time = %d \n"
// "\tavg_time = %d \n",
// success, ping.timeout_count,
// ping.min_time, ping.max_time,
// success ? ping.sum_time / success : 0
// );
while (ping != nullptr) {
if (ping->done) {
uint32_t success = ping->success_count;
uint32_t ip = ping->ip;
Response_P(PSTR("{\"" D_JSON_PING "\":{\"%d.%d.%d.%d\":{"
"\"Reachable\":%s"
",\"Success\":%d"
",\"Timeout\":%d"
",\"MinTime\":%d"
",\"MaxTime\":%d"
",\"AvgTime\":%d"
"}}}"),
ip & 0xFF, (ip >> 8) & 0xFF, (ip >> 16) & 0xFF, ip >> 24,
success ? "true" : "false",
success, ping.timeout_count,
ping.min_time, ping.max_time,
success ? ping.sum_time / success : 0
);
MqttPublishPrefixTopic_P(RESULT_OR_TELE, PSTR(D_JSON_PING));
XdrvRulesProcess();
ping.done = false;
ping.busy = false;
Response_P(PSTR("{\"" D_JSON_PING "\":{\"%d.%d.%d.%d\":{"
"\"Reachable\":%s"
",\"Success\":%d"
",\"Timeout\":%d"
",\"MinTime\":%d"
",\"MaxTime\":%d"
",\"AvgTime\":%d"
"}}}"),
ip & 0xFF, (ip >> 8) & 0xFF, (ip >> 16) & 0xFF, ip >> 24,
success ? "true" : "false",
success, ping->timeout_count,
success ? ping->min_time : 0, ping->max_time,
success ? ping->sum_time / success : 0
);
MqttPublishPrefixTopic_P(RESULT_OR_TELE, PSTR(D_JSON_PING));
XdrvRulesProcess();
// remove from linked list
*prev_link = ping->next;
// don't increment prev_link
Ping_t *ping_to_delete = ping;
ping = ping->next; // move to next before deleting the object
delete ping_to_delete; // free memory allocated
} else {
prev_link = &ping->next;
ping = ping->next;
}
}
}
/*********************************************************************************************\
* Ping Command
\*********************************************************************************************/
void CmndPing(void) {
uint32_t count = XdrvMailbox.index;
IPAddress ip;
RemoveSpace(XdrvMailbox.data);
if (count > 8) { count = 8; }
if (ping.busy) {
ResponseCmndChar_P(PSTR("Ping busy"));
return;
}
if (count > 10) { count = 8; } // max 8 seconds
if (WiFi.hostByName(XdrvMailbox.data, ip)) {
memset(&ping_opt, 0, sizeof(ping_opt));
memset(&ping, 0, sizeof(ping));
ping.min_time = UINT32_MAX;
ping_opt.count = count;
ping_opt.coarse_time = 1; // wait 1 second between messages
ping_opt.ip = ip;
// callbacks
ping_opt.recv_function = (ping_recv_function) ping_recv_cb; // at each response or time-out
ping_opt.sent_function = (ping_sent_function) ping_sent_cb; // when all packets have been sent and reveived
ping.busy = true;
if (ping_start(&ping_opt)) {
bool ok = t_ping_start(ip, count);
if (ok) {
ResponseCmndDone();
} else {
ResponseCmndChar_P(PSTR("Unable to send Ping"));
ping.busy = false;
ResponseCmndChar_P(PSTR("Ping already ongoing for this IP"));
}
} else {
ResponseCmndChar_P(PSTR("Unable to resolve IP address"));
}
}
@ -157,7 +332,7 @@ bool Xdrv38(uint8_t function)
switch (function) {
case FUNC_EVERY_250_MSECOND:
PingResponsePoll();
PingResponsePoll(); // TODO
break;
case FUNC_COMMAND:
result = DecodeCommand(kPingCommands, PingCommand);
@ -166,4 +341,4 @@ bool Xdrv38(uint8_t function)
return result;
}
#endif // USE_PING
#endif // USE_PING

View File

@ -172,11 +172,11 @@ void CpuLoadLoop(void)
CPU_loops ++;
if ((CPU_last_millis + (CPU_load_check *1000)) <= CPU_last_loop_time) {
#if defined(F_CPU) && (F_CPU == 160000000L)
int CPU_load = 100 - ( (CPU_loops*(1 + 30*sleep)) / (CPU_load_check *800) );
int CPU_load = 100 - ( (CPU_loops*(1 + 30*ssleep)) / (CPU_load_check *800) );
CPU_loops = CPU_loops / CPU_load_check;
AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_DEBUG "FreeRam %d, CPU %d%%(160MHz), Loops/sec %d"), ESP.getFreeHeap(), CPU_load, CPU_loops);
#else
int CPU_load = 100 - ( (CPU_loops*(1 + 30*sleep)) / (CPU_load_check *400) );
int CPU_load = 100 - ( (CPU_loops*(1 + 30*ssleep)) / (CPU_load_check *400) );
CPU_loops = CPU_loops / CPU_load_check;
AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_DEBUG "FreeRam %d, CPU %d%%(80MHz), Loops/sec %d"), ESP.getFreeHeap(), CPU_load, CPU_loops);
#endif
@ -188,6 +188,7 @@ void CpuLoadLoop(void)
/*******************************************************************************************/
#ifdef ESP8266
#if defined(ARDUINO_ESP8266_RELEASE_2_3_0) || defined(ARDUINO_ESP8266_RELEASE_2_4_0) || defined(ARDUINO_ESP8266_RELEASE_2_4_1)
// All version before core 2.4.2
// https://github.com/esp8266/Arduino/issues/2557
@ -224,10 +225,22 @@ void DebugFreeMem(void)
#endif // ARDUINO_ESP8266_RELEASE_2_x_x
#else // ESP32
void DebugFreeMem(void)
{
register uint8_t *sp asm("a1");
AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_DEBUG "FreeRam %d, FreeStack %d (%s)"), ESP.getFreeHeap(), sp - pxTaskGetStackStart(NULL), XdrvMailbox.data);
}
#endif // ESP8266 - ESP32
/*******************************************************************************************/
void DebugRtcDump(char* parms)
{
#ifdef ESP8266
#define CFG_COLS 16
uint16_t idx;
@ -283,6 +296,7 @@ void DebugRtcDump(char* parms)
snprintf_P(log_data, sizeof(log_data), PSTR("%s|"), log_data);
AddLog(LOG_LEVEL_INFO);
}
#endif // ESP8266
}
/*******************************************************************************************/
@ -385,6 +399,7 @@ void DebugCfgPoke(char* parms)
void SetFlashMode(uint8_t mode)
{
#ifdef ESP8266
uint8_t *_buffer;
uint32_t address;
@ -400,6 +415,7 @@ void SetFlashMode(uint8_t mode)
}
}
delete[] _buffer;
#endif // ESP8266
}
/*********************************************************************************************\
@ -503,6 +519,7 @@ uint32_t DebugSwap32(uint32_t x) {
void CmndFlashDump(void)
{
#ifdef ESP8266
// FlashDump
// FlashDump 0xFF000
// FlashDump 0xFC000 10
@ -533,6 +550,7 @@ void CmndFlashDump(void)
DebugSwap32(values[4]), DebugSwap32(values[5]), DebugSwap32(values[6]), DebugSwap32(values[7]));
}
ResponseCmndDone();
#endif // ESP8266
}
#ifdef USE_I2C
@ -600,10 +618,12 @@ void CmndI2cRead(void)
void CmndI2cStretch(void)
{
#ifdef ESP8266
if (i2c_flg && (XdrvMailbox.payload > 0)) {
Wire.setClockStretchLimit(XdrvMailbox.payload);
}
ResponseCmndDone();
#endif // ESP8266
}
void CmndI2cClock(void)

View File

@ -32,40 +32,39 @@
#define XSNS_22 22
uint8_t sr04_type = 1;
int sr04_echo_pin = 0;
int sr04_trig_pin = 0;
real64_t distance;
NewPing* sonar = nullptr;
TasmotaSerial* sonar_serial = nullptr;
uint8_t Sr04TModeDetect(void)
{
sr04_type = 0;
if (pin[GPIO_SR04_ECHO]>=99) return sr04_type;
if (99 == pin[GPIO_SR04_ECHO]) { return sr04_type; }
sr04_echo_pin = pin[GPIO_SR04_ECHO];
sr04_trig_pin = (pin[GPIO_SR04_TRIG] < 99) ? pin[GPIO_SR04_TRIG] : pin[GPIO_SR04_ECHO]; // if GPIO_SR04_TRIG is not configured use single PIN mode with GPIO_SR04_ECHO only
int sr04_echo_pin = pin[GPIO_SR04_ECHO];
int sr04_trig_pin = (pin[GPIO_SR04_TRIG] < 99) ? pin[GPIO_SR04_TRIG] : pin[GPIO_SR04_ECHO]; // if GPIO_SR04_TRIG is not configured use single PIN mode with GPIO_SR04_ECHO only
sonar_serial = new TasmotaSerial(sr04_echo_pin, sr04_trig_pin, 1);
if (sonar_serial->begin(9600,1)) {
DEBUG_SENSOR_LOG(PSTR("SR04: Detect mode"));
if (sr04_trig_pin!=-1) {
sr04_type = (Sr04TMiddleValue(Sr04TMode3Distance(),Sr04TMode3Distance(),Sr04TMode3Distance())!=NO_ECHO)?3:1;
if (sr04_trig_pin != -1) {
sr04_type = (Sr04TMiddleValue(Sr04TMode3Distance(), Sr04TMode3Distance(), Sr04TMode3Distance()) != NO_ECHO) ? 3 : 1;
} else {
sr04_type = 2;
sr04_type = 2;
}
} else {
sr04_type = 1;
}
if (sr04_type < 2) {
delete sonar_serial;
sonar_serial = nullptr;
sonar = new NewPing(sr04_trig_pin, sr04_echo_pin, 300);
delete sonar_serial;
sonar_serial = nullptr;
if (-1 == sr04_trig_pin) {
sr04_trig_pin = pin[GPIO_SR04_ECHO]; // if GPIO_SR04_TRIG is not configured use single PIN mode with GPIO_SR04_ECHO only
}
sonar = new NewPing(sr04_trig_pin, sr04_echo_pin, 300);
} else {
if (sonar_serial->hardwareSerial()) {
ClaimSerial();

View File

@ -494,7 +494,7 @@ void HandleHxAction(void)
AddLog_P(LOG_LEVEL_DEBUG, S_LOG_HTTP, S_CONFIGURE_HX711);
if (WebServer->hasArg("save")) {
if (Webserver->hasArg("save")) {
HxSaveSettings();
HandleConfiguration();
return;
@ -502,7 +502,7 @@ void HandleHxAction(void)
char stemp1[20];
if (WebServer->hasArg("reset")) {
if (Webserver->hasArg("reset")) {
snprintf_P(stemp1, sizeof(stemp1), PSTR("Sensor34 1")); // Reset
ExecuteWebCommand(stemp1, SRC_WEBGUI);
@ -510,7 +510,7 @@ void HandleHxAction(void)
return;
}
if (WebServer->hasArg("calibrate")) {
if (Webserver->hasArg("calibrate")) {
WebGetArg("p1", stemp1, sizeof(stemp1));
Settings.weight_reference = (!strlen(stemp1)) ? 0 : (unsigned long)(CharToFloat(stemp1) * 1000);
@ -593,7 +593,7 @@ bool Xsns34(uint8_t function)
WSContentSend_P(HTTP_BTN_MENU_HX711);
break;
case FUNC_WEB_ADD_HANDLER:
WebServer->on("/" WEB_HANDLE_HX711, HandleHxAction);
Webserver->on("/" WEB_HANDLE_HX711, HandleHxAction);
break;
#endif // USE_HX711_GUI
#endif // USE_WEBSERVER

View File

@ -98,7 +98,7 @@ The serial pins are GPS_RX and GPS_TX, no further installation steps needed. To
set latitude and longitude in settings
+ sensor60 14
open virtual serial port over TCP, usable for u-center
open virtual serial port over TCP, usable for u-center
+ sensor60 15
pause virtual serial port over TCP
@ -137,7 +137,7 @@ const char kUBXTypes[] PROGMEM = "UBX";
#define UBX_SERIAL_BUFFER_SIZE 256
#define UBX_TCP_PORT 1234
#define NTP_MILLIS_OFFSET 50 // estimated latency in milliseconds
#define NTP_MILLIS_OFFSET 50 // estimated latency in milliseconds
/********************************************************************************************\
| *globals
@ -504,8 +504,8 @@ uint32_t UBXprocessGPS()
#ifdef USE_FLOG
void UBXsendHeader(void)
{
WebServer->setContentLength(CONTENT_LENGTH_UNKNOWN);
WebServer->sendHeader(F("Content-Disposition"), F("attachment; filename=TASMOTA.gpx"));
Webserver->setContentLength(CONTENT_LENGTH_UNKNOWN);
Webserver->sendHeader(F("Content-Disposition"), F("attachment; filename=TASMOTA.gpx"));
WSSend(200, CT_STREAM, F(
"<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\" ?>\r\n"
"<GPX version=\"1.1\" creator=\"TASMOTA\" xmlns=\"http://www.topografix.com/GPX/1/1\" \r\n"
@ -526,13 +526,13 @@ void UBXsendRecord(uint8_t *buf)
dtostrfd((double)entry->lon/10000000.0f,7,lon);
snprintf_P(record, sizeof(record),PSTR("<trkpt\n\t lat=\"%s\" lon=\"%s\">\n\t<time>%s</time>\n</trkpt>\n"),lat ,lon, stime);
// DEBUG_SENSOR_LOG(PSTR("FLOG: DL %u %u"), Flog->sector.dword_buffer[k+j],Flog->sector.dword_buffer[k+j+1]);
WebServer->sendContent_P(record);
Webserver->sendContent_P(record);
}
void UBXsendFooter(void)
{
WebServer->sendContent(F("</trkseg>\n</trk>\n</gpx>"));
WebServer->sendContent("");
Webserver->sendContent(F("</trkseg>\n</trk>\n</gpx>"));
Webserver->sendContent("");
Rtc.user_time_entry = false; // we have blocked the main loop and want a new valid time
}
@ -707,7 +707,7 @@ void UBXHandleTIME()
if (UBX.mode.forceUTCupdate || Rtc.user_time_entry == false){
AddLog_P(LOG_LEVEL_INFO, PSTR("UBX: UTC-Time is valid, set system time"));
Rtc.utc_time = UBX.rec_buffer.values.time;
}
}
Rtc.user_time_entry = true;
}
}
@ -928,7 +928,7 @@ bool Xsns60(uint8_t function)
break;
#ifdef USE_FLOG
case FUNC_WEB_ADD_HANDLER:
WebServer->on("/UBX", UBXsendFile);
Webserver->on("/UBX", UBXsendFile);
break;
#endif //USE_FLOG
case FUNC_JSON_APPEND:

View File

@ -90,7 +90,7 @@ bool Xsns91(uint8_t function)
switch (function) {
case FUNC_WEB_ADD_HANDLER:
WebServer->on("/metrics", HandleMetrics);
Webserver->on("/metrics", HandleMetrics);
break;
}
return result;