mirror of https://github.com/arendst/Tasmota.git
Merge remote-tracking branch 'upstream/development' into development
Merge all recent changes into my branch
This commit is contained in:
commit
f0dde50f39
|
@ -0,0 +1,86 @@
|
|||
## Sonoff-Tasmota template information
|
||||
Sonoff-Tasmota uses Device or Module information to control peripherals connected to GPIOs. This information is stored in the ``sonoff_template.h`` file as a device specific template. The template contains information about what GPIO should be connected to what peripheral and what GPIO may be configured online using the ``GPIO`` command or GUI Configure Module menu. In addition a device may need specific coding to process the data from these peripherals. The module number as provided by the ``Modules`` command is used to select this coding.
|
||||
|
||||
Starting with version 6.4.1.16 Sonoff-Tasmota Modules can be extended by users online using a template. To provide easy processing by Sonoff-Tasmota a user template is written as JSON text and could look like this:
|
||||
|
||||
{"NAME":"UserModule1","GPIO":[17,148,29,149,7,255,255,255,138,255,139,255,255],"FLAG":0,"BASE":18}
|
||||
|
||||
The four properties with UPPERCASE property names have the following functionality:
|
||||
|
||||
Property name | Property value description
|
||||
--------------|-------------------------------------------------------------------------------------------------------------------
|
||||
NAME | Up to 14 characters for the Module name
|
||||
GPIO | Up to 13 decimal numbers from 0 to 255 representing GPIO0 to GPIO5, GPIO09, GPIO10 and GPIO12 to GPIO16
|
||||
FLAG | 8 bit mask flag register
|
||||
BASE | Module number of a hard-coded device to be used when device specific functionality is needed
|
||||
|
||||
The above example, based on the Generic Module does not allow ADC0 input.
|
||||
|
||||
## GPIO functionality
|
||||
The GPIO functionality numbers are the same is shown by command ``GPIOs``. In addition code 255 is added to select a GPIO as user configurable via the GUI Configure Module menu.
|
||||
|
||||
## FLAG functionality
|
||||
The FLAG value is an 8-bit mask where each bit controls a features. Add FLAG values to set multiple bits.
|
||||
|
||||
FLAG | Mask | Feature description
|
||||
-----|----------|------------------------------
|
||||
1 | xxxxxxx1 | Allowing to use Analog0 (ADC0) as input if define USE_ADC_VCC in ``my_user_config.h`` is disabled
|
||||
2 | xxxxxx1x | Enable GUI pull-up control message
|
||||
4 | xxxxx1xx | Not used
|
||||
8 | xxxx1xxx | Not used
|
||||
16 | xxx1xxxx | Not used
|
||||
32 | xx1xxxxx | Not used
|
||||
64 | x1xxxxxx | Not used
|
||||
128 | 1xxxxxxx | Not used
|
||||
|
||||
## BASE functionality
|
||||
The following table lists hard-coded device specific functionality. Notice that not all device modules need special handling.
|
||||
|
||||
BASE | Module | Description
|
||||
-----|----------------|----------------------------------------------
|
||||
4 | Sonoff Dual | Process relay and button via hardware serial interface using GPIO01 and GPIO03. Change baudrate to 19200 bps. Process buttons as single press only
|
||||
9 | Sonoff Touch | Invert ledstate 1 functionality
|
||||
10 | Sonoff LED | Set light type to 2 PWM channels disregarding SetOption15. Fix device specific LED instabilities by disabling GPIO04, GPIO5 and GPIO14
|
||||
12 | 4 Channel | See 4
|
||||
13 | Motor C/AC | Force all relays ON at Power On and disable command ``PowerOnState``
|
||||
15 | EXS Relay(s) | Enable pulse latching using even/odd numbered relay pairs
|
||||
18 | Generic | Show Wemos specific pin information in GUI
|
||||
19 | H801 | Change hardware UART Tx from GPIO01 to GPIO02
|
||||
20 | Sonoff SC | Enable and Process data via hardware serial interface using GPIO01 and GPIO03. Change baudrate to 19200 bps
|
||||
21 | Sonoff BN-SZ | Set light type to 1 PWM channel disregarding SetOption15
|
||||
22 | Sonoff 4CH Pro | Button handling disregarding SetOption13 only allowing single press to enable RF learning while holding the button
|
||||
24 | Sonoff Bridge | Enable and Process data via hardware serial interface using GPIO01 and GPIO03. Change baudrate to 19200 bps. Process 16 buttons in web GUI. Enable EFM8BB1 firmware upload
|
||||
25 | Sonoff B1 | Set light type to RGBWC using MY92x1
|
||||
26 | AiLight | Set light type to RGBW using MY92x1
|
||||
27 | Sonoff T1 1CH | See 9
|
||||
28 | Sonoff T1 2CH | See 9
|
||||
29 | Sonoff T1 3CH | See 9
|
||||
38 | Sonoff Dual R2 | Process buttons as single press only
|
||||
43 | Sonoff iFan02 | Enable command ``Fanspeed``. Disable Interlock and PulseTime. Tune status information, MQTT data and GUI. Sync with microcontroller. Process Domoticz Fan state
|
||||
47 | Xiaomi Philips | Process Color Temperature using PWM2 and Intensity using PWM1
|
||||
53 | Tuya Dimmer | Enable and Process data via software or hardware serial interface using GPIO 148 and 149 or forced GPIO01 and GPIO03. Change baudrate to 9600 bps. Process all Buttons
|
||||
55 | ARMTR Dimmer | Enable and Process data via software or hardware serial interface using GPIO 148 and 149. Change baudrate to 115200 bps.
|
||||
57 | PS-16-DZ | Enable and Process data via software or hardware serial interface using GPIO 148 and 149. Change baudrate to 19200 bps.
|
||||
61 | YTF IR Bridge | Disable serial interface to stop loopback
|
||||
65 | Mi Desk Lamp | Process rotary and Button1 data specific to this device
|
||||
|
||||
## Usage
|
||||
A user provided template can be stored in Sonoff-Tasmota using the ``Template`` command. It has the following options.
|
||||
|
||||
Command | Payload | Description
|
||||
---------|----------|---------------------------------------
|
||||
Template | | Show current user template
|
||||
Template | 0 | Copy active module template to user template
|
||||
Template | 1 .. 69 | Copy hard-coded module template to user template
|
||||
|
||||
The following command will store a complete template based on the Generic module
|
||||
``Template {"NAME":"UserModule1","GPIO":[17,148,29,149,7,255,255,255,138,255,139,255,255],"FLAG":0,"BASE":18}``
|
||||
|
||||
The following command will update the name of a stored template
|
||||
``Template {"NAME":"UserModule2"}``
|
||||
|
||||
The following command will update the flag of a stored template
|
||||
``Template {"FLAG":1}``
|
||||
|
||||
The following command will update the base of a stored template to Generic
|
||||
``Template {"BASE":0}``
|
File diff suppressed because it is too large
Load Diff
|
@ -1,156 +0,0 @@
|
|||
|
||||
# ESP8266 platform
|
||||
# ------------------------------
|
||||
|
||||
# For more info:
|
||||
# https://github.com/arduino/Arduino/wiki/Arduino-IDE-1.5---3rd-party-Hardware-specification
|
||||
|
||||
name=ESP8266 Boards (2.5.0-beta2)
|
||||
version=2.5.0-beta2
|
||||
|
||||
|
||||
|
||||
runtime.tools.signing={runtime.platform.path}/tools/signing.py
|
||||
|
||||
compiler.warning_flags=-w
|
||||
compiler.warning_flags.none=-w
|
||||
compiler.warning_flags.default=
|
||||
compiler.warning_flags.more=-Wall
|
||||
compiler.warning_flags.all=-Wall -Wextra
|
||||
|
||||
build.lwip_lib=-llwip_gcc
|
||||
build.lwip_include=lwip/include
|
||||
build.lwip_flags=-DLWIP_OPEN_SRC
|
||||
|
||||
build.vtable_flags=-DVTABLES_IN_FLASH
|
||||
|
||||
#build.exception_flags=-fexceptions
|
||||
build.exception_flags=-fno-exceptions
|
||||
#build.stdcpp_lib=-lstdc++
|
||||
build.stdcpp_lib=-lstdc++-nox
|
||||
|
||||
#build.float=-u _printf_float -u _scanf_float
|
||||
build.float=
|
||||
build.led=
|
||||
|
||||
compiler.path={runtime.tools.xtensa-lx106-elf-gcc.path}/bin/
|
||||
compiler.sdk.path={runtime.platform.path}/tools/sdk
|
||||
compiler.libc.path={runtime.platform.path}/tools/sdk/libc/xtensa-lx106-elf
|
||||
compiler.cpreprocessor.flags=-D__ets__ -DICACHE_FLASH -U__STRICT_ANSI__ "-I{compiler.sdk.path}/include" "-I{compiler.sdk.path}/{build.lwip_include}" "-I{compiler.libc.path}/include" "-I{build.path}/core"
|
||||
|
||||
compiler.c.cmd=xtensa-lx106-elf-gcc
|
||||
compiler.c.flags=-c {compiler.warning_flags} -Os -g -Wpointer-arith -Wno-implicit-function-declaration -Wl,-EL -fno-inline-functions -nostdlib -mlongcalls -mtext-section-literals -falign-functions=4 -MMD -std=gnu99 {build.exception_flags} -ffunction-sections -fdata-sections {build.exception_flags}
|
||||
|
||||
compiler.S.cmd=xtensa-lx106-elf-gcc
|
||||
compiler.S.flags=-c -g -x assembler-with-cpp -MMD -mlongcalls
|
||||
|
||||
compiler.c.elf.flags=-g {compiler.warning_flags} -Os -nostdlib -Wl,--no-check-sections -u app_entry {build.float} -Wl,-static "-L{compiler.sdk.path}/lib" "-L{compiler.sdk.path}/ld" "-L{compiler.libc.path}/lib" "-T{build.flash_ld}" -Wl,--gc-sections -Wl,-wrap,system_restart_local -Wl,-wrap,spi_flash_read
|
||||
|
||||
compiler.c.elf.cmd=xtensa-lx106-elf-gcc
|
||||
compiler.c.elf.libs=-lhal -lphy -lpp -lnet80211 {build.lwip_lib} -lwpa -lcrypto -lmain -lwps -lbearssl -laxtls -lespnow -lsmartconfig -lairkiss -lwpa2 {build.stdcpp_lib} -lm -lc -lgcc
|
||||
|
||||
compiler.cpp.cmd=xtensa-lx106-elf-g++
|
||||
compiler.cpp.flags=-c {compiler.warning_flags} -Os -g -mlongcalls -mtext-section-literals -fno-rtti -falign-functions=4 -std=c++11 -MMD -ffunction-sections -fdata-sections {build.exception_flags}
|
||||
|
||||
compiler.as.cmd=xtensa-lx106-elf-as
|
||||
|
||||
compiler.ar.cmd=xtensa-lx106-elf-ar
|
||||
compiler.ar.flags=cru
|
||||
|
||||
compiler.elf2hex.cmd=esptool
|
||||
compiler.elf2hex.flags=
|
||||
|
||||
compiler.size.cmd=xtensa-lx106-elf-size
|
||||
|
||||
compiler.esptool.cmd=esptool
|
||||
compiler.esptool.cmd.windows=esptool.exe
|
||||
|
||||
# This can be overriden in boards.txt
|
||||
build.extra_flags=-DESP8266
|
||||
|
||||
# These can be overridden in platform.local.txt
|
||||
compiler.c.extra_flags=
|
||||
compiler.c.elf.extra_flags=
|
||||
compiler.S.extra_flags=
|
||||
compiler.cpp.extra_flags=
|
||||
compiler.ar.extra_flags=
|
||||
compiler.objcopy.eep.extra_flags=
|
||||
compiler.elf2hex.extra_flags=
|
||||
|
||||
## generate file with git version number
|
||||
## needs bash, git, and echo
|
||||
recipe.hooks.core.prebuild.1.pattern=python "{runtime.tools.signing}" --mode header --publickey "{build.source.path}/public.key" --out "{build.path}/core/Updater_Signing.h"
|
||||
|
||||
|
||||
|
||||
## windows-compatible version without git
|
||||
recipe.hooks.core.prebuild.1.pattern.windows=cmd.exe /c rem cannot sign on windows
|
||||
|
||||
|
||||
|
||||
## Build the app.ld linker file
|
||||
recipe.hooks.linking.prelink.1.pattern="{compiler.path}{compiler.c.cmd}" -CC -E -P {build.vtable_flags} "{runtime.platform.path}/tools/sdk/ld/eagle.app.v6.common.ld.h" -o "{build.path}/local.eagle.app.v6.common.ld"
|
||||
|
||||
## Compile c files
|
||||
recipe.c.o.pattern="{compiler.path}{compiler.c.cmd}" {compiler.cpreprocessor.flags} {compiler.c.flags} -DF_CPU={build.f_cpu} {build.lwip_flags} {build.debug_port} {build.debug_level} -DARDUINO={runtime.ide.version} -DARDUINO_{build.board} -DARDUINO_ARCH_{build.arch} -DARDUINO_BOARD="{build.board}" {build.led} {compiler.c.extra_flags} {build.extra_flags} {includes} "{source_file}" -o "{object_file}"
|
||||
|
||||
## Compile c++ files
|
||||
recipe.cpp.o.pattern="{compiler.path}{compiler.cpp.cmd}" {compiler.cpreprocessor.flags} {compiler.cpp.flags} -DF_CPU={build.f_cpu} {build.lwip_flags} {build.debug_port} {build.debug_level} -DARDUINO={runtime.ide.version} -DARDUINO_{build.board} -DARDUINO_ARCH_{build.arch} -DARDUINO_BOARD="{build.board}" {build.led} {compiler.cpp.extra_flags} {build.extra_flags} {includes} "{source_file}" -o "{object_file}"
|
||||
|
||||
## Compile S files
|
||||
recipe.S.o.pattern="{compiler.path}{compiler.c.cmd}" {compiler.cpreprocessor.flags} {compiler.S.flags} -DF_CPU={build.f_cpu} {build.lwip_flags} {build.debug_port} {build.debug_level} -DARDUINO={runtime.ide.version} -DARDUINO_{build.board} -DARDUINO_ARCH_{build.arch} -DARDUINO_BOARD="{build.board}" {build.led} {compiler.c.extra_flags} {build.extra_flags} {includes} "{source_file}" -o "{object_file}"
|
||||
|
||||
## Create archives
|
||||
recipe.ar.pattern="{compiler.path}{compiler.ar.cmd}" {compiler.ar.flags} {compiler.ar.extra_flags} "{archive_file_path}" "{object_file}"
|
||||
|
||||
## Combine gc-sections, archives, and objects
|
||||
recipe.c.combine.pattern="{compiler.path}{compiler.c.elf.cmd}" -Wl,-Map "-Wl,{build.path}/{build.project_name}.map" {compiler.c.elf.flags} {compiler.c.elf.extra_flags} -o "{build.path}/{build.project_name}.elf" -Wl,--start-group {object_files} "{archive_file_path}" {compiler.c.elf.libs} -Wl,--end-group "-L{build.path}"
|
||||
|
||||
## Create eeprom
|
||||
recipe.objcopy.eep.pattern=
|
||||
|
||||
## Create hex
|
||||
#recipe.objcopy.hex.pattern="{compiler.path}{compiler.elf2hex.cmd}" {compiler.elf2hex.flags} {compiler.elf2hex.extra_flags} "{build.path}/{build.project_name}.elf" "{build.path}/{build.project_name}.hex"
|
||||
|
||||
recipe.objcopy.hex.1.pattern="{runtime.tools.esptool.path}/{compiler.esptool.cmd}" -eo "{runtime.platform.path}/bootloaders/eboot/eboot.elf" -bo "{build.path}/{build.project_name}.bin" -bm {build.flash_mode} -bf {build.flash_freq} -bz {build.flash_size} -bs .text -bp 4096 -ec -eo "{build.path}/{build.project_name}.elf" -bs .irom0.text -bs .text -bs .data -bs .rodata -bc -ec
|
||||
recipe.objcopy.hex.2.pattern=python "{runtime.tools.signing}" --mode sign --privatekey "{build.source.path}/private.key" --bin "{build.path}/{build.project_name}.bin" --out "{build.path}/{build.project_name}.bin.signed"
|
||||
|
||||
# No signing on Windows
|
||||
recipe.objcopy.hex.1.pattern.windows="{runtime.tools.esptool.path}/{compiler.esptool.cmd}" -eo "{runtime.platform.path}/bootloaders/eboot/eboot.elf" -bo "{build.path}/{build.project_name}.bin" -bm {build.flash_mode} -bf {build.flash_freq} -bz {build.flash_size} -bs .text -bp 4096 -ec -eo "{build.path}/{build.project_name}.elf" -bs .irom0.text -bs .text -bs .data -bs .rodata -bc -ec
|
||||
recipe.objcopy.hex.2.pattern.windows=
|
||||
|
||||
## Save hex
|
||||
recipe.output.tmp_file={build.project_name}.bin
|
||||
recipe.output.save_file={build.project_name}.{build.variant}.bin
|
||||
|
||||
## Compute size
|
||||
recipe.size.pattern="{compiler.path}{compiler.size.cmd}" -A "{build.path}/{build.project_name}.elf"
|
||||
recipe.size.regex=^(?:\.irom0\.text|\.text|\.data|\.rodata|)\s+([0-9]+).*
|
||||
recipe.size.regex.data=^(?:\.data|\.rodata|\.bss)\s+([0-9]+).*
|
||||
#recipe.size.regex.eeprom=^(?:\.eeprom)\s+([0-9]+).*
|
||||
|
||||
# ------------------------------
|
||||
|
||||
tools.esptool.cmd=esptool
|
||||
tools.esptool.cmd.windows=esptool.exe
|
||||
tools.esptool.path={runtime.tools.esptool.path}
|
||||
tools.esptool.network_cmd=python
|
||||
tools.esptool.network_cmd.windows=python.exe
|
||||
|
||||
tools.esptool.upload.protocol=esp
|
||||
tools.esptool.upload.params.verbose=-vv
|
||||
tools.esptool.upload.params.quiet=
|
||||
tools.esptool.upload.pattern="{path}/{cmd}" {upload.verbose} -cd {upload.resetmethod} -cb {upload.speed} -cp "{serial.port}" {upload.erase_cmd} -ca 0x00000 -cf "{build.path}/{build.project_name}.bin"
|
||||
tools.esptool.upload.network_pattern="{network_cmd}" "{runtime.platform.path}/tools/espota.py" -i "{serial.port}" -p "{network.port}" "--auth={network.password}" -f "{build.path}/{build.project_name}.bin"
|
||||
|
||||
tools.mkspiffs.cmd=mkspiffs
|
||||
tools.mkspiffs.cmd.windows=mkspiffs.exe
|
||||
tools.mkspiffs.path={runtime.tools.mkspiffs.path}
|
||||
|
||||
tools.espupload.cmd=python
|
||||
tools.espupload.cmd.windows=python.exe
|
||||
tools.espupload.path={runtime.platform.path}/tools
|
||||
tools.espupload.upload.protocol=espupload
|
||||
tools.espupload.upload.params.verbose=
|
||||
tools.espupload.upload.params.quiet=
|
||||
tools.espupload.upload.pattern="{cmd}" "{path}/espupload.py" -f "{build.path}/{build.project_name}.bin"
|
|
@ -1330,8 +1330,8 @@ cw01.upload.resetmethod=nodemcu
|
|||
cw01.menu.CrystalFreq.26=26 MHz
|
||||
cw01.menu.CrystalFreq.40=40 MHz
|
||||
cw01.menu.CrystalFreq.40.build.extra_flags=-DF_CRYSTAL=40000000 -DESP8266
|
||||
cw01.build.flash_mode=qio
|
||||
cw01.build.flash_flags=-DFLASHMODE_QIO
|
||||
cw01.build.flash_mode=dio
|
||||
cw01.build.flash_flags=-DFLASHMODE_DIO
|
||||
cw01.build.flash_freq=40
|
||||
cw01.menu.eesz.4M=4M (no SPIFFS)
|
||||
cw01.menu.eesz.4M.build.flash_size=4M
|
||||
|
@ -6119,4 +6119,3 @@ espectro.menu.baud.512000.windows=512000
|
|||
espectro.menu.baud.512000.upload.speed=512000
|
||||
espectro.menu.baud.921600=921600
|
||||
espectro.menu.baud.921600.upload.speed=921600
|
||||
|
|
@ -1,154 +1,155 @@
|
|||
|
||||
# ESP8266 platform
|
||||
# ------------------------------
|
||||
|
||||
# For more info:
|
||||
# https://github.com/arduino/Arduino/wiki/Arduino-IDE-1.5---3rd-party-Hardware-specification
|
||||
|
||||
name=ESP8266 Boards (2.5.0-beta3)
|
||||
version=2.5.0-beta3
|
||||
|
||||
|
||||
|
||||
runtime.tools.signing={runtime.platform.path}/tools/signing.py
|
||||
|
||||
compiler.warning_flags=-w
|
||||
compiler.warning_flags.none=-w
|
||||
compiler.warning_flags.default=
|
||||
compiler.warning_flags.more=-Wall
|
||||
compiler.warning_flags.all=-Wall -Wextra
|
||||
|
||||
build.lwip_lib=-llwip_gcc
|
||||
build.lwip_include=lwip/include
|
||||
build.lwip_flags=-DLWIP_OPEN_SRC
|
||||
|
||||
build.vtable_flags=-DVTABLES_IN_FLASH
|
||||
|
||||
build.exception_flags=-fno-exceptions
|
||||
build.stdcpp_lib=-lstdc++
|
||||
|
||||
#build.float=-u _printf_float -u _scanf_float
|
||||
build.float=
|
||||
build.led=
|
||||
|
||||
compiler.path={runtime.tools.xtensa-lx106-elf-gcc.path}/bin/
|
||||
compiler.sdk.path={runtime.platform.path}/tools/sdk
|
||||
compiler.libc.path={runtime.platform.path}/tools/sdk/libc/xtensa-lx106-elf
|
||||
compiler.cpreprocessor.flags=-D__ets__ -DICACHE_FLASH -U__STRICT_ANSI__ "-I{compiler.sdk.path}/include" "-I{compiler.sdk.path}/{build.lwip_include}" "-I{compiler.libc.path}/include" "-I{build.path}/core"
|
||||
|
||||
compiler.c.cmd=xtensa-lx106-elf-gcc
|
||||
compiler.c.flags=-c {compiler.warning_flags} -Os -g -Wpointer-arith -Wno-implicit-function-declaration -Wl,-EL -fno-inline-functions -nostdlib -mlongcalls -mtext-section-literals -falign-functions=4 -MMD -std=gnu99 -ffunction-sections -fdata-sections {build.exception_flags}
|
||||
|
||||
compiler.S.cmd=xtensa-lx106-elf-gcc
|
||||
compiler.S.flags=-c -g -x assembler-with-cpp -MMD -mlongcalls
|
||||
|
||||
compiler.c.elf.flags=-g {compiler.warning_flags} -Os -nostdlib -Wl,--no-check-sections -u app_entry {build.float} -Wl,-static "-L{compiler.sdk.path}/lib" "-L{compiler.sdk.path}/ld" "-L{compiler.libc.path}/lib" "-T{build.flash_ld}" -Wl,--gc-sections -Wl,-wrap,system_restart_local -Wl,-wrap,spi_flash_read
|
||||
|
||||
compiler.c.elf.cmd=xtensa-lx106-elf-gcc
|
||||
compiler.c.elf.libs=-lhal -lphy -lpp -lnet80211 {build.lwip_lib} -lwpa -lcrypto -lmain -lwps -lbearssl -laxtls -lespnow -lsmartconfig -lairkiss -lwpa2 {build.stdcpp_lib} -lm -lc -lgcc
|
||||
|
||||
compiler.cpp.cmd=xtensa-lx106-elf-g++
|
||||
compiler.cpp.flags=-c {compiler.warning_flags} -Os -g -mlongcalls -mtext-section-literals -fno-rtti -falign-functions=4 -std=c++11 -MMD -ffunction-sections -fdata-sections {build.exception_flags}
|
||||
|
||||
compiler.as.cmd=xtensa-lx106-elf-as
|
||||
|
||||
compiler.ar.cmd=xtensa-lx106-elf-ar
|
||||
compiler.ar.flags=cru
|
||||
|
||||
compiler.elf2hex.cmd=esptool
|
||||
compiler.elf2hex.flags=
|
||||
|
||||
compiler.size.cmd=xtensa-lx106-elf-size
|
||||
|
||||
compiler.esptool.cmd=esptool
|
||||
compiler.esptool.cmd.windows=esptool.exe
|
||||
|
||||
# This can be overriden in boards.txt
|
||||
build.extra_flags=-DESP8266
|
||||
|
||||
# These can be overridden in platform.local.txt
|
||||
compiler.c.extra_flags=
|
||||
compiler.c.elf.extra_flags=
|
||||
compiler.S.extra_flags=
|
||||
compiler.cpp.extra_flags=
|
||||
compiler.ar.extra_flags=
|
||||
compiler.objcopy.eep.extra_flags=
|
||||
compiler.elf2hex.extra_flags=
|
||||
|
||||
## generate file with git version number
|
||||
## needs bash, git, and echo
|
||||
recipe.hooks.core.prebuild.1.pattern=python "{runtime.tools.signing}" --mode header --publickey "{build.source.path}/public.key" --out "{build.path}/core/Updater_Signing.h"
|
||||
|
||||
|
||||
|
||||
## windows-compatible version without git
|
||||
recipe.hooks.core.prebuild.1.pattern.windows=cmd.exe /c rem cannot sign on windows
|
||||
|
||||
|
||||
|
||||
## Build the app.ld linker file
|
||||
recipe.hooks.linking.prelink.1.pattern="{compiler.path}{compiler.c.cmd}" -CC -E -P {build.vtable_flags} "{runtime.platform.path}/tools/sdk/ld/eagle.app.v6.common.ld.h" -o "{build.path}/local.eagle.app.v6.common.ld"
|
||||
|
||||
## Compile c files
|
||||
recipe.c.o.pattern="{compiler.path}{compiler.c.cmd}" {compiler.cpreprocessor.flags} {compiler.c.flags} -DF_CPU={build.f_cpu} {build.lwip_flags} {build.debug_port} {build.debug_level} -DARDUINO={runtime.ide.version} -DARDUINO_{build.board} -DARDUINO_ARCH_{build.arch} -DARDUINO_BOARD="{build.board}" {build.led} {build.flash_flags} {compiler.c.extra_flags} {build.extra_flags} {includes} "{source_file}" -o "{object_file}"
|
||||
|
||||
## Compile c++ files
|
||||
recipe.cpp.o.pattern="{compiler.path}{compiler.cpp.cmd}" {compiler.cpreprocessor.flags} {compiler.cpp.flags} -DF_CPU={build.f_cpu} {build.lwip_flags} {build.debug_port} {build.debug_level} -DARDUINO={runtime.ide.version} -DARDUINO_{build.board} -DARDUINO_ARCH_{build.arch} -DARDUINO_BOARD="{build.board}" {build.led} {build.flash_flags} {compiler.cpp.extra_flags} {build.extra_flags} {includes} "{source_file}" -o "{object_file}"
|
||||
|
||||
## Compile S files
|
||||
recipe.S.o.pattern="{compiler.path}{compiler.c.cmd}" {compiler.cpreprocessor.flags} {compiler.S.flags} -DF_CPU={build.f_cpu} {build.lwip_flags} {build.debug_port} {build.debug_level} -DARDUINO={runtime.ide.version} -DARDUINO_{build.board} -DARDUINO_ARCH_{build.arch} -DARDUINO_BOARD="{build.board}" {build.led} {build.flash_flags} {compiler.c.extra_flags} {build.extra_flags} {includes} "{source_file}" -o "{object_file}"
|
||||
|
||||
## Create archives
|
||||
recipe.ar.pattern="{compiler.path}{compiler.ar.cmd}" {compiler.ar.flags} {compiler.ar.extra_flags} "{archive_file_path}" "{object_file}"
|
||||
|
||||
## Combine gc-sections, archives, and objects
|
||||
recipe.c.combine.pattern="{compiler.path}{compiler.c.elf.cmd}" {build.exception_flags} -Wl,-Map "-Wl,{build.path}/{build.project_name}.map" {compiler.c.elf.flags} {compiler.c.elf.extra_flags} -o "{build.path}/{build.project_name}.elf" -Wl,--start-group {object_files} "{archive_file_path}" {compiler.c.elf.libs} -Wl,--end-group "-L{build.path}"
|
||||
|
||||
## Create eeprom
|
||||
recipe.objcopy.eep.pattern=
|
||||
|
||||
## Create hex
|
||||
#recipe.objcopy.hex.pattern="{compiler.path}{compiler.elf2hex.cmd}" {compiler.elf2hex.flags} {compiler.elf2hex.extra_flags} "{build.path}/{build.project_name}.elf" "{build.path}/{build.project_name}.hex"
|
||||
|
||||
recipe.objcopy.hex.1.pattern="{runtime.tools.esptool.path}/{compiler.esptool.cmd}" -eo "{runtime.platform.path}/bootloaders/eboot/eboot.elf" -bo "{build.path}/{build.project_name}.bin" -bm {build.flash_mode} -bf {build.flash_freq} -bz {build.flash_size} -bs .text -bp 4096 -ec -eo "{build.path}/{build.project_name}.elf" -bs .irom0.text -bs .text -bs .data -bs .rodata -bc -ec
|
||||
recipe.objcopy.hex.2.pattern=python "{runtime.tools.signing}" --mode sign --privatekey "{build.source.path}/private.key" --bin "{build.path}/{build.project_name}.bin" --out "{build.path}/{build.project_name}.bin.signed"
|
||||
|
||||
# No signing on Windows
|
||||
recipe.objcopy.hex.1.pattern.windows="{runtime.tools.esptool.path}/{compiler.esptool.cmd}" -eo "{runtime.platform.path}/bootloaders/eboot/eboot.elf" -bo "{build.path}/{build.project_name}.bin" -bm {build.flash_mode} -bf {build.flash_freq} -bz {build.flash_size} -bs .text -bp 4096 -ec -eo "{build.path}/{build.project_name}.elf" -bs .irom0.text -bs .text -bs .data -bs .rodata -bc -ec
|
||||
recipe.objcopy.hex.2.pattern.windows=
|
||||
|
||||
## Save hex
|
||||
recipe.output.tmp_file={build.project_name}.bin
|
||||
recipe.output.save_file={build.project_name}.{build.variant}.bin
|
||||
|
||||
## Compute size
|
||||
recipe.size.pattern="{compiler.path}{compiler.size.cmd}" -A "{build.path}/{build.project_name}.elf"
|
||||
recipe.size.regex=^(?:\.irom0\.text|\.text|\.data|\.rodata|)\s+([0-9]+).*
|
||||
recipe.size.regex.data=^(?:\.data|\.rodata|\.bss)\s+([0-9]+).*
|
||||
#recipe.size.regex.eeprom=^(?:\.eeprom)\s+([0-9]+).*
|
||||
|
||||
# ------------------------------
|
||||
|
||||
tools.esptool.cmd=esptool
|
||||
tools.esptool.cmd.windows=esptool.exe
|
||||
tools.esptool.path={runtime.tools.esptool.path}
|
||||
tools.esptool.network_cmd=python
|
||||
tools.esptool.network_cmd.windows=python.exe
|
||||
|
||||
tools.esptool.upload.protocol=esp
|
||||
tools.esptool.upload.params.verbose=-vv
|
||||
tools.esptool.upload.params.quiet=
|
||||
tools.esptool.upload.pattern="{path}/{cmd}" {upload.verbose} -cd {upload.resetmethod} -cb {upload.speed} -cp "{serial.port}" {upload.erase_cmd} -ca 0x00000 -cf "{build.path}/{build.project_name}.bin"
|
||||
tools.esptool.upload.network_pattern="{network_cmd}" "{runtime.platform.path}/tools/espota.py" -i "{serial.port}" -p "{network.port}" "--auth={network.password}" -f "{build.path}/{build.project_name}.bin"
|
||||
|
||||
tools.mkspiffs.cmd=mkspiffs
|
||||
tools.mkspiffs.cmd.windows=mkspiffs.exe
|
||||
tools.mkspiffs.path={runtime.tools.mkspiffs.path}
|
||||
|
||||
tools.espupload.cmd=python
|
||||
tools.espupload.cmd.windows=python.exe
|
||||
tools.espupload.path={runtime.platform.path}/tools
|
||||
tools.espupload.upload.protocol=espupload
|
||||
tools.espupload.upload.params.verbose=
|
||||
tools.espupload.upload.params.quiet=
|
||||
tools.espupload.upload.pattern="{cmd}" "{path}/espupload.py" -f "{build.path}/{build.project_name}.bin"
|
||||
|
||||
# ESP8266 platform
|
||||
# ------------------------------
|
||||
|
||||
# For more info:
|
||||
# https://github.com/arduino/Arduino/wiki/Arduino-IDE-1.5---3rd-party-Hardware-specification
|
||||
|
||||
name=ESP8266 Boards (2.5.0)
|
||||
version=2.5.0
|
||||
|
||||
runtime.tools.xtensa-lx106-elf-gcc.path={runtime.platform.path}/tools/xtensa-lx106-elf
|
||||
runtime.tools.esptool.path={runtime.platform.path}/tools/esptool
|
||||
runtime.tools.signing={runtime.platform.path}/tools/signing.py
|
||||
|
||||
compiler.warning_flags=-w
|
||||
compiler.warning_flags.none=-w
|
||||
compiler.warning_flags.default=
|
||||
compiler.warning_flags.more=-Wall
|
||||
compiler.warning_flags.all=-Wall -Wextra
|
||||
|
||||
build.lwip_lib=-llwip_gcc
|
||||
build.lwip_include=lwip/include
|
||||
build.lwip_flags=-DLWIP_OPEN_SRC
|
||||
|
||||
build.vtable_flags=-DVTABLES_IN_FLASH
|
||||
|
||||
build.exception_flags=-fno-exceptions
|
||||
build.stdcpp_lib=-lstdc++
|
||||
|
||||
#build.float=-u _printf_float -u _scanf_float
|
||||
build.float=
|
||||
build.led=
|
||||
|
||||
compiler.path={runtime.tools.xtensa-lx106-elf-gcc.path}/bin/
|
||||
compiler.sdk.path={runtime.platform.path}/tools/sdk
|
||||
compiler.libc.path={runtime.platform.path}/tools/sdk/libc/xtensa-lx106-elf
|
||||
compiler.cpreprocessor.flags=-D__ets__ -DICACHE_FLASH -U__STRICT_ANSI__ "-I{compiler.sdk.path}/include" "-I{compiler.sdk.path}/{build.lwip_include}" "-I{compiler.libc.path}/include" "-I{build.path}/core"
|
||||
|
||||
compiler.c.cmd=xtensa-lx106-elf-gcc
|
||||
compiler.c.flags=-c {compiler.warning_flags} -Os -g -Wpointer-arith -Wno-implicit-function-declaration -Wl,-EL -fno-inline-functions -nostdlib -mlongcalls -mtext-section-literals -falign-functions=4 -MMD -std=gnu99 -ffunction-sections -fdata-sections {build.exception_flags}
|
||||
|
||||
compiler.S.cmd=xtensa-lx106-elf-gcc
|
||||
compiler.S.flags=-c -g -x assembler-with-cpp -MMD -mlongcalls
|
||||
|
||||
compiler.c.elf.flags=-g {compiler.warning_flags} -Os -nostdlib -Wl,--no-check-sections -u app_entry {build.float} -Wl,-static "-L{compiler.sdk.path}/lib" "-L{compiler.sdk.path}/ld" "-L{compiler.libc.path}/lib" "-T{build.flash_ld}" -Wl,--gc-sections -Wl,-wrap,system_restart_local -Wl,-wrap,spi_flash_read
|
||||
|
||||
compiler.c.elf.cmd=xtensa-lx106-elf-gcc
|
||||
compiler.c.elf.libs=-lhal -lphy -lpp -lnet80211 {build.lwip_lib} -lwpa -lcrypto -lmain -lwps -lbearssl -laxtls -lespnow -lsmartconfig -lairkiss -lwpa2 {build.stdcpp_lib} -lm -lc -lgcc
|
||||
|
||||
compiler.cpp.cmd=xtensa-lx106-elf-g++
|
||||
compiler.cpp.flags=-c {compiler.warning_flags} -Os -g -mlongcalls -mtext-section-literals -fno-rtti -falign-functions=4 -std=c++11 -MMD -ffunction-sections -fdata-sections {build.exception_flags}
|
||||
|
||||
compiler.as.cmd=xtensa-lx106-elf-as
|
||||
|
||||
compiler.ar.cmd=xtensa-lx106-elf-ar
|
||||
compiler.ar.flags=cru
|
||||
|
||||
compiler.elf2hex.cmd=esptool
|
||||
compiler.elf2hex.flags=
|
||||
|
||||
compiler.size.cmd=xtensa-lx106-elf-size
|
||||
|
||||
compiler.esptool.cmd=esptool
|
||||
compiler.esptool.cmd.windows=esptool.exe
|
||||
|
||||
# This can be overriden in boards.txt
|
||||
build.extra_flags=-DESP8266
|
||||
|
||||
# These can be overridden in platform.local.txt
|
||||
compiler.c.extra_flags=
|
||||
compiler.c.elf.extra_flags=
|
||||
compiler.S.extra_flags=
|
||||
compiler.cpp.extra_flags=
|
||||
compiler.ar.extra_flags=
|
||||
compiler.objcopy.eep.extra_flags=
|
||||
compiler.elf2hex.extra_flags=
|
||||
|
||||
## generate file with git version number
|
||||
## needs bash, git, and echo
|
||||
recipe.hooks.core.prebuild.1.pattern=python "{runtime.tools.signing}" --mode header --publickey "{build.source.path}/public.key" --out "{build.path}/core/Updater_Signing.h"
|
||||
recipe.hooks.core.prebuild.2.pattern=bash -c "mkdir -p {build.path}/core && echo \#define ARDUINO_ESP8266_GIT_VER 0x`git --git-dir {runtime.platform.path}/.git rev-parse --short=8 HEAD 2>/dev/null || echo ffffffff` >{build.path}/core/core_version.h"
|
||||
recipe.hooks.core.prebuild.3.pattern=bash -c "mkdir -p {build.path}/core && echo \#define ARDUINO_ESP8266_GIT_DESC `cd "{runtime.platform.path}"; git describe --tags 2>/dev/null || echo unix-{version}` >>{build.path}/core/core_version.h"
|
||||
|
||||
## windows-compatible version without git
|
||||
recipe.hooks.core.prebuild.1.pattern.windows=cmd.exe /c rem cannot sign on windows
|
||||
recipe.hooks.core.prebuild.2.pattern.windows=cmd.exe /c mkdir {build.path}\core & (echo #define ARDUINO_ESP8266_GIT_VER 0x00000000 & echo #define ARDUINO_ESP8266_GIT_DESC win-{version} ) > {build.path}\core\core_version.h
|
||||
recipe.hooks.core.prebuild.3.pattern.windows=cmd.exe /c if exist {build.source.path}\public.key echo #error Cannot automatically build signed binaries on Windows > {build.path}\core\Updater_Signing.h
|
||||
|
||||
## Build the app.ld linker file
|
||||
recipe.hooks.linking.prelink.1.pattern="{compiler.path}{compiler.c.cmd}" -CC -E -P {build.vtable_flags} "{runtime.platform.path}/tools/sdk/ld/eagle.app.v6.common.ld.h" -o "{build.path}/local.eagle.app.v6.common.ld"
|
||||
|
||||
## Compile c files
|
||||
recipe.c.o.pattern="{compiler.path}{compiler.c.cmd}" {compiler.cpreprocessor.flags} {compiler.c.flags} -DF_CPU={build.f_cpu} {build.lwip_flags} {build.debug_port} {build.debug_level} -DARDUINO={runtime.ide.version} -DARDUINO_{build.board} -DARDUINO_ARCH_{build.arch} -DARDUINO_BOARD="{build.board}" {build.led} {build.flash_flags} {compiler.c.extra_flags} {build.extra_flags} {includes} "{source_file}" -o "{object_file}"
|
||||
|
||||
## Compile c++ files
|
||||
recipe.cpp.o.pattern="{compiler.path}{compiler.cpp.cmd}" {compiler.cpreprocessor.flags} {compiler.cpp.flags} -DF_CPU={build.f_cpu} {build.lwip_flags} {build.debug_port} {build.debug_level} -DARDUINO={runtime.ide.version} -DARDUINO_{build.board} -DARDUINO_ARCH_{build.arch} -DARDUINO_BOARD="{build.board}" {build.led} {build.flash_flags} {compiler.cpp.extra_flags} {build.extra_flags} {includes} "{source_file}" -o "{object_file}"
|
||||
|
||||
## Compile S files
|
||||
recipe.S.o.pattern="{compiler.path}{compiler.c.cmd}" {compiler.cpreprocessor.flags} {compiler.S.flags} -DF_CPU={build.f_cpu} {build.lwip_flags} {build.debug_port} {build.debug_level} -DARDUINO={runtime.ide.version} -DARDUINO_{build.board} -DARDUINO_ARCH_{build.arch} -DARDUINO_BOARD="{build.board}" {build.led} {build.flash_flags} {compiler.c.extra_flags} {build.extra_flags} {includes} "{source_file}" -o "{object_file}"
|
||||
|
||||
## Create archives
|
||||
recipe.ar.pattern="{compiler.path}{compiler.ar.cmd}" {compiler.ar.flags} {compiler.ar.extra_flags} "{archive_file_path}" "{object_file}"
|
||||
|
||||
## Combine gc-sections, archives, and objects
|
||||
recipe.c.combine.pattern="{compiler.path}{compiler.c.elf.cmd}" {build.exception_flags} -Wl,-Map "-Wl,{build.path}/{build.project_name}.map" {compiler.c.elf.flags} {compiler.c.elf.extra_flags} -o "{build.path}/{build.project_name}.elf" -Wl,--start-group {object_files} "{archive_file_path}" {compiler.c.elf.libs} -Wl,--end-group "-L{build.path}"
|
||||
|
||||
## Create eeprom
|
||||
recipe.objcopy.eep.pattern=
|
||||
|
||||
## Create hex
|
||||
#recipe.objcopy.hex.pattern="{compiler.path}{compiler.elf2hex.cmd}" {compiler.elf2hex.flags} {compiler.elf2hex.extra_flags} "{build.path}/{build.project_name}.elf" "{build.path}/{build.project_name}.hex"
|
||||
|
||||
recipe.objcopy.hex.1.pattern="{runtime.tools.esptool.path}/{compiler.esptool.cmd}" -eo "{runtime.platform.path}/bootloaders/eboot/eboot.elf" -bo "{build.path}/{build.project_name}.bin" -bm {build.flash_mode} -bf {build.flash_freq} -bz {build.flash_size} -bs .text -bp 4096 -ec -eo "{build.path}/{build.project_name}.elf" -bs .irom0.text -bs .text -bs .data -bs .rodata -bc -ec
|
||||
recipe.objcopy.hex.2.pattern=python "{runtime.tools.signing}" --mode sign --privatekey "{build.source.path}/private.key" --bin "{build.path}/{build.project_name}.bin" --out "{build.path}/{build.project_name}.bin.signed"
|
||||
|
||||
# No signing on Windows
|
||||
recipe.objcopy.hex.1.pattern.windows="{runtime.tools.esptool.path}/{compiler.esptool.cmd}" -eo "{runtime.platform.path}/bootloaders/eboot/eboot.elf" -bo "{build.path}/{build.project_name}.bin" -bm {build.flash_mode} -bf {build.flash_freq} -bz {build.flash_size} -bs .text -bp 4096 -ec -eo "{build.path}/{build.project_name}.elf" -bs .irom0.text -bs .text -bs .data -bs .rodata -bc -ec
|
||||
recipe.objcopy.hex.2.pattern.windows=
|
||||
|
||||
## Save hex
|
||||
recipe.output.tmp_file={build.project_name}.bin
|
||||
recipe.output.save_file={build.project_name}.{build.variant}.bin
|
||||
|
||||
## Compute size
|
||||
recipe.size.pattern="{compiler.path}{compiler.size.cmd}" -A "{build.path}/{build.project_name}.elf"
|
||||
recipe.size.regex=^(?:\.irom0\.text|\.text|\.data|\.rodata|)\s+([0-9]+).*
|
||||
recipe.size.regex.data=^(?:\.data|\.rodata|\.bss)\s+([0-9]+).*
|
||||
#recipe.size.regex.eeprom=^(?:\.eeprom)\s+([0-9]+).*
|
||||
|
||||
# ------------------------------
|
||||
|
||||
tools.esptool.cmd=esptool
|
||||
tools.esptool.cmd.windows=esptool.exe
|
||||
tools.esptool.path={runtime.tools.esptool.path}
|
||||
tools.esptool.network_cmd=python
|
||||
tools.esptool.network_cmd.windows=python.exe
|
||||
|
||||
tools.esptool.upload.protocol=esp
|
||||
tools.esptool.upload.params.verbose=-vv
|
||||
tools.esptool.upload.params.quiet=
|
||||
tools.esptool.upload.pattern="{path}/{cmd}" {upload.verbose} -cd {upload.resetmethod} -cb {upload.speed} -cp "{serial.port}" {upload.erase_cmd} -ca 0x00000 -cf "{build.path}/{build.project_name}.bin"
|
||||
tools.esptool.upload.network_pattern="{network_cmd}" "{runtime.platform.path}/tools/espota.py" -i "{serial.port}" -p "{network.port}" "--auth={network.password}" -f "{build.path}/{build.project_name}.bin"
|
||||
|
||||
tools.mkspiffs.cmd=mkspiffs
|
||||
tools.mkspiffs.cmd.windows=mkspiffs.exe
|
||||
tools.mkspiffs.path={runtime.tools.mkspiffs.path}
|
||||
|
||||
tools.espupload.cmd=python
|
||||
tools.espupload.cmd.windows=python.exe
|
||||
tools.espupload.path={runtime.platform.path}/tools
|
||||
tools.espupload.upload.protocol=espupload
|
||||
tools.espupload.upload.params.verbose=
|
||||
tools.espupload.upload.params.quiet=
|
||||
tools.espupload.upload.pattern="{cmd}" "{path}/espupload.py" -f "{build.path}/{build.project_name}.bin"
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2015 Ivan Seidel
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
|
@ -0,0 +1,325 @@
|
|||
/*
|
||||
LinkedList.h - V1.1 - Generic LinkedList implementation
|
||||
Works better with FIFO, because LIFO will need to
|
||||
search the entire List to find the last one;
|
||||
|
||||
For instructions, go to https://github.com/ivanseidel/LinkedList
|
||||
|
||||
Created by Ivan Seidel Gomes, March, 2013.
|
||||
Released into the public domain.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef LinkedList_h
|
||||
#define LinkedList_h
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
template<class T>
|
||||
struct ListNode
|
||||
{
|
||||
T data;
|
||||
ListNode<T> *next;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
class LinkedList{
|
||||
|
||||
protected:
|
||||
int _size;
|
||||
ListNode<T> *root;
|
||||
ListNode<T> *last;
|
||||
|
||||
// Helps "get" method, by saving last position
|
||||
ListNode<T> *lastNodeGot;
|
||||
int lastIndexGot;
|
||||
// isCached should be set to FALSE
|
||||
// everytime the list suffer changes
|
||||
bool isCached;
|
||||
|
||||
ListNode<T>* getNode(int index);
|
||||
|
||||
public:
|
||||
LinkedList();
|
||||
~LinkedList();
|
||||
|
||||
/*
|
||||
Returns current size of LinkedList
|
||||
*/
|
||||
virtual int size();
|
||||
/*
|
||||
Adds a T object in the specified index;
|
||||
Unlink and link the LinkedList correcly;
|
||||
Increment _size
|
||||
*/
|
||||
virtual bool add(int index, T);
|
||||
/*
|
||||
Adds a T object in the end of the LinkedList;
|
||||
Increment _size;
|
||||
*/
|
||||
virtual bool add(T);
|
||||
/*
|
||||
Adds a T object in the start of the LinkedList;
|
||||
Increment _size;
|
||||
*/
|
||||
virtual bool unshift(T);
|
||||
/*
|
||||
Set the object at index, with T;
|
||||
Increment _size;
|
||||
*/
|
||||
virtual bool set(int index, T);
|
||||
/*
|
||||
Remove object at index;
|
||||
If index is not reachable, returns false;
|
||||
else, decrement _size
|
||||
*/
|
||||
virtual T remove(int index);
|
||||
/*
|
||||
Remove last object;
|
||||
*/
|
||||
virtual T pop();
|
||||
/*
|
||||
Remove first object;
|
||||
*/
|
||||
virtual T shift();
|
||||
/*
|
||||
Get the index'th element on the list;
|
||||
Return Element if accessible,
|
||||
else, return false;
|
||||
*/
|
||||
virtual T get(int index);
|
||||
|
||||
/*
|
||||
Clear the entire array
|
||||
*/
|
||||
virtual void clear();
|
||||
|
||||
};
|
||||
|
||||
// Initialize LinkedList with false values
|
||||
template<typename T>
|
||||
LinkedList<T>::LinkedList()
|
||||
{
|
||||
root=NULL;
|
||||
last=NULL;
|
||||
_size=0;
|
||||
|
||||
lastNodeGot = root;
|
||||
lastIndexGot = 0;
|
||||
isCached = false;
|
||||
}
|
||||
|
||||
// Clear Nodes and free Memory
|
||||
template<typename T>
|
||||
LinkedList<T>::~LinkedList()
|
||||
{
|
||||
ListNode<T>* tmp;
|
||||
while(root!=NULL)
|
||||
{
|
||||
tmp=root;
|
||||
root=root->next;
|
||||
delete tmp;
|
||||
}
|
||||
last = NULL;
|
||||
_size=0;
|
||||
isCached = false;
|
||||
}
|
||||
|
||||
/*
|
||||
Actualy "logic" coding
|
||||
*/
|
||||
|
||||
template<typename T>
|
||||
ListNode<T>* LinkedList<T>::getNode(int index){
|
||||
|
||||
int _pos = 0;
|
||||
ListNode<T>* current = root;
|
||||
|
||||
// Check if the node trying to get is
|
||||
// immediatly AFTER the previous got one
|
||||
if(isCached && lastIndexGot <= index){
|
||||
_pos = lastIndexGot;
|
||||
current = lastNodeGot;
|
||||
}
|
||||
|
||||
while(_pos < index && current){
|
||||
current = current->next;
|
||||
|
||||
_pos++;
|
||||
}
|
||||
|
||||
// Check if the object index got is the same as the required
|
||||
if(_pos == index){
|
||||
isCached = true;
|
||||
lastIndexGot = index;
|
||||
lastNodeGot = current;
|
||||
|
||||
return current;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
int LinkedList<T>::size(){
|
||||
return _size;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
bool LinkedList<T>::add(int index, T _t){
|
||||
|
||||
if(index >= _size)
|
||||
return add(_t);
|
||||
|
||||
if(index == 0)
|
||||
return unshift(_t);
|
||||
|
||||
ListNode<T> *tmp = new ListNode<T>(),
|
||||
*_prev = getNode(index-1);
|
||||
tmp->data = _t;
|
||||
tmp->next = _prev->next;
|
||||
_prev->next = tmp;
|
||||
|
||||
_size++;
|
||||
isCached = false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
bool LinkedList<T>::add(T _t){
|
||||
|
||||
ListNode<T> *tmp = new ListNode<T>();
|
||||
tmp->data = _t;
|
||||
tmp->next = NULL;
|
||||
|
||||
if(root){
|
||||
// Already have elements inserted
|
||||
last->next = tmp;
|
||||
last = tmp;
|
||||
}else{
|
||||
// First element being inserted
|
||||
root = tmp;
|
||||
last = tmp;
|
||||
}
|
||||
|
||||
_size++;
|
||||
isCached = false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
bool LinkedList<T>::unshift(T _t){
|
||||
|
||||
if(_size == 0)
|
||||
return add(_t);
|
||||
|
||||
ListNode<T> *tmp = new ListNode<T>();
|
||||
tmp->next = root;
|
||||
tmp->data = _t;
|
||||
root = tmp;
|
||||
|
||||
_size++;
|
||||
isCached = false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
bool LinkedList<T>::set(int index, T _t){
|
||||
// Check if index position is in bounds
|
||||
if(index < 0 || index >= _size)
|
||||
return false;
|
||||
|
||||
getNode(index)->data = _t;
|
||||
return true;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
T LinkedList<T>::pop(){
|
||||
if(_size <= 0)
|
||||
return T();
|
||||
|
||||
isCached = false;
|
||||
|
||||
if(_size >= 2){
|
||||
ListNode<T> *tmp = getNode(_size - 2);
|
||||
T ret = tmp->next->data;
|
||||
delete(tmp->next);
|
||||
tmp->next = NULL;
|
||||
last = tmp;
|
||||
_size--;
|
||||
return ret;
|
||||
}else{
|
||||
// Only one element left on the list
|
||||
T ret = root->data;
|
||||
delete(root);
|
||||
root = NULL;
|
||||
last = NULL;
|
||||
_size = 0;
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
T LinkedList<T>::shift(){
|
||||
if(_size <= 0)
|
||||
return T();
|
||||
|
||||
if(_size > 1){
|
||||
ListNode<T> *_next = root->next;
|
||||
T ret = root->data;
|
||||
delete(root);
|
||||
root = _next;
|
||||
_size --;
|
||||
isCached = false;
|
||||
|
||||
return ret;
|
||||
}else{
|
||||
// Only one left, then pop()
|
||||
return pop();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
T LinkedList<T>::remove(int index){
|
||||
if (index < 0 || index >= _size)
|
||||
{
|
||||
return T();
|
||||
}
|
||||
|
||||
if(index == 0)
|
||||
return shift();
|
||||
|
||||
if (index == _size-1)
|
||||
{
|
||||
return pop();
|
||||
}
|
||||
|
||||
ListNode<T> *tmp = getNode(index - 1);
|
||||
ListNode<T> *toDelete = tmp->next;
|
||||
T ret = toDelete->data;
|
||||
tmp->next = tmp->next->next;
|
||||
delete(toDelete);
|
||||
_size--;
|
||||
isCached = false;
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
template<typename T>
|
||||
T LinkedList<T>::get(int index){
|
||||
ListNode<T> *tmp = getNode(index);
|
||||
|
||||
return (tmp ? tmp->data : T());
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void LinkedList<T>::clear(){
|
||||
while(size() > 0)
|
||||
shift();
|
||||
}
|
||||
|
||||
#endif
|
|
@ -0,0 +1,171 @@
|
|||
# LinkedList
|
||||
|
||||
This library was developed targeting **`Arduino`** applications. However, works just great with any C++.
|
||||
|
||||
Implementing a buffer for objects takes time. If we are not in the mood, we just create an `array[1000]` with enough size.
|
||||
|
||||
The objective of this library is to create a pattern for projects.
|
||||
If you need to use a List of: `int`, `float`, `objects`, `Lists` or `Wales`. **This is what you are looking for.**
|
||||
|
||||
With a simple but powerful caching algorithm, you can get subsequent objects much faster than usual. Tested without any problems with Lists bigger than 2000 members.
|
||||
|
||||
## Installation
|
||||
|
||||
1. [Download](https://github.com/ivanseidel/LinkedList/archive/master.zip) the Latest release from gitHub.
|
||||
2. Unzip and modify the Folder name to "LinkedList" (Remove the '-version')
|
||||
3. Paste the modified folder on your Library folder (On your `Libraries` folder inside Sketchbooks or Arduino software).
|
||||
4. Reopen the Arduino software.
|
||||
|
||||
**If you are here, because another Library requires this class, just don't waste time reading bellow. Install and ready.**
|
||||
|
||||
-------------------------
|
||||
|
||||
## Getting started
|
||||
|
||||
### The `LinkedList` class
|
||||
|
||||
In case you don't know what a LinkedList is and what it's used for, take a quick look at [Wikipedia::LinkedList](https://en.wikipedia.org/wiki/Linked_list) before continuing.
|
||||
|
||||
#### To declare a LinkedList object
|
||||
```c++
|
||||
// Instantiate a LinkedList that will hold 'integer'
|
||||
LinkedList<int> myLinkedList = LinkedList<int>();
|
||||
|
||||
// Or just this
|
||||
LinkedList<int> myLinkedList;
|
||||
|
||||
// But if you are instantiating a pointer LinkedList...
|
||||
LinkedList<int> *myLinkedList = new LinkedList<int>();
|
||||
|
||||
// If you want a LinkedList with any other type such as 'MyClass'
|
||||
// Make sure you call delete(MyClass) when you remove!
|
||||
LinkedList<MyClass> *myLinkedList = new LinkedList<MyClass>();
|
||||
```
|
||||
|
||||
#### Getting the size of the linked list
|
||||
```c++
|
||||
// To get the size of a linked list, make use of the size() method
|
||||
int theSize = myList.size();
|
||||
|
||||
// Notice that if it's pointer to the linked list, you should use -> instead
|
||||
int theSize = myList->size();
|
||||
```
|
||||
|
||||
#### Adding elements
|
||||
|
||||
```c++
|
||||
// add(obj) method will insert at the END of the list
|
||||
myList.add(myObject);
|
||||
|
||||
// add(index, obj) method will try to insert the object at the specified index
|
||||
myList.add(0, myObject); // Add at the beginning
|
||||
myList.add(3, myObject); // Add at index 3
|
||||
|
||||
// unshift(obj) method will insert the object at the beginning
|
||||
myList.unshift(myObject);
|
||||
```
|
||||
|
||||
#### Getting elements
|
||||
|
||||
```c++
|
||||
// get(index) will return the element at index
|
||||
// (notice that the start element is 0, not 1)
|
||||
|
||||
// Get the FIRST element
|
||||
myObject = myList.get(0);
|
||||
|
||||
// Get the third element
|
||||
myObject = myList.get(2);
|
||||
|
||||
// Get the LAST element
|
||||
myObject = myList.get(myList.size() - 1);
|
||||
```
|
||||
|
||||
#### Changing elements
|
||||
```c++
|
||||
// set(index, obj) method will change the object at index to obj
|
||||
|
||||
// Change the first element to myObject
|
||||
myList.set(0, myObject);
|
||||
|
||||
// Change the third element to myObject
|
||||
myList.set(2, myObject);
|
||||
|
||||
// Change the LAST element of the list
|
||||
myList.set(myList.size() - 1, myObject);
|
||||
```
|
||||
|
||||
#### Removing elements
|
||||
```c++
|
||||
// remove(index) will remove and return the element at index
|
||||
|
||||
// Remove the first object
|
||||
myList.remove(0);
|
||||
|
||||
// Get and Delete the third element
|
||||
myDeletedObject = myList.remove(2);
|
||||
|
||||
// pop() will remove and return the LAST element
|
||||
myDeletedObject = myList.pop();
|
||||
|
||||
// shift() will remove and return the FIRST element
|
||||
myDeletedObject = myList.shift();
|
||||
|
||||
// clear() will erase the entire list, leaving it with 0 elements
|
||||
// NOTE: Clear wont DELETE/FREE memory from Pointers, if you
|
||||
// are using Classes/Poiners, manualy delete and free those.
|
||||
myList.clear();
|
||||
```
|
||||
|
||||
------------------------
|
||||
|
||||
## Library Reference
|
||||
|
||||
### `ListNode` struct
|
||||
|
||||
- `T` `ListNode::data` - The object data
|
||||
|
||||
- `ListNode<T>` `*next` - Pointer to the next Node
|
||||
|
||||
### `LinkedList` class
|
||||
|
||||
**`boolean` methods returns if succeeded**
|
||||
|
||||
- `LinkedList<T>::LinkedList()` - Constructor.
|
||||
|
||||
- `LinkedList<T>::~LinkedList()` - Destructor. Clear Nodes to minimize memory. Does not free pointer memory.
|
||||
|
||||
- `int` `LinkedList<T>::size()` - Returns the current size of the list.
|
||||
|
||||
- `bool` `LinkedList<T>::add(T)` - Add element T at the END of the list.
|
||||
|
||||
- `bool` `LinkedList<T>::add(int index, T)` - Add element T at `index` of the list.
|
||||
|
||||
- `bool` `LinkedList<T>::unshift(T)` - Add element T at the BEGINNING of the list.
|
||||
|
||||
- `bool` `LinkedList<T>::set(int index, T)` - Set the element at `index` to T.
|
||||
|
||||
- `T` `LinkedList<T>::remove(int index)` - Remove element at `index`. Return the removed element. Does not free pointer memory
|
||||
|
||||
- `T` `LinkedList<T>::pop()` - Remove the LAST element. Return the removed element.
|
||||
|
||||
- `T` `LinkedList<T>::shift()` - Remove the FIRST element. Return the removed element.
|
||||
|
||||
- `T` `LinkedList<T>::get(int index)` - Return the element at `index`.
|
||||
|
||||
- `void` `LinkedList<T>::clear()` - Removes all elements. Does not free pointer memory.
|
||||
|
||||
- **protected** `int` `LinkedList<T>::_size` - Holds the cached size of the list.
|
||||
|
||||
- **protected** `ListNode<T>` `LinkedList<T>::*root` - Holds the root node of the list.
|
||||
|
||||
- **protected** `ListNode<T>` `LinkedList<T>::*last` - Holds the last node of the list.
|
||||
|
||||
- **protected** `ListNode<T>*` `LinkedList<T>::getNode(int index)` - Returns the `index` node of the list.
|
||||
|
||||
### Version History
|
||||
|
||||
* `1.1 (2013-07-20)`: Cache implemented. Getting subsequent objects is now O(N). Before, O(N^2).
|
||||
* `1.0 (2013-07-20)`: Original release
|
||||
|
||||
![LinkedList](https://d2weczhvl823v0.cloudfront.net/ivanseidel/LinkedList/trend.png)
|
|
@ -0,0 +1,81 @@
|
|||
/*
|
||||
LinkedList Example
|
||||
Link: http://github.com/ivanseidel/LinkedList
|
||||
|
||||
Example Created by
|
||||
Tom Stewart, github.com/tastewar
|
||||
|
||||
Edited by:
|
||||
Ivan Seidel, github.com/ivanseidel
|
||||
*/
|
||||
|
||||
#include <LinkedList.h>
|
||||
|
||||
// Let's define a new class
|
||||
class Animal {
|
||||
public:
|
||||
char *name;
|
||||
bool isMammal;
|
||||
};
|
||||
|
||||
char catname[]="kitty";
|
||||
char dogname[]="doggie";
|
||||
char emuname[]="emu";
|
||||
|
||||
LinkedList<Animal*> myAnimalList = LinkedList<Animal*>();
|
||||
|
||||
void setup()
|
||||
{
|
||||
|
||||
Serial.begin(9600);
|
||||
Serial.println("Hello!" );
|
||||
|
||||
// Create a Cat
|
||||
Animal *cat = new Animal();
|
||||
cat->name = catname;
|
||||
cat->isMammal = true;
|
||||
|
||||
// Create a dog
|
||||
Animal *dog = new Animal();
|
||||
dog->name = dogname;
|
||||
dog->isMammal = true;
|
||||
|
||||
// Create a emu
|
||||
Animal *emu = new Animal();
|
||||
emu->name = emuname;
|
||||
emu->isMammal = false; // just an example; no offense to pig lovers
|
||||
|
||||
// Add animals to list
|
||||
myAnimalList.add(cat);
|
||||
myAnimalList.add(emu);
|
||||
myAnimalList.add(dog);
|
||||
}
|
||||
|
||||
void loop() {
|
||||
|
||||
Serial.print("There are ");
|
||||
Serial.print(myAnimalList.size());
|
||||
Serial.print(" animals in the list. The mammals are: ");
|
||||
|
||||
int current = 0;
|
||||
Animal *animal;
|
||||
for(int i = 0; i < myAnimalList.size(); i++){
|
||||
|
||||
// Get animal from list
|
||||
animal = myAnimalList.get(i);
|
||||
|
||||
// If its a mammal, then print it's name
|
||||
if(animal->isMammal){
|
||||
|
||||
// Avoid printing spacer on the first element
|
||||
if(current++)
|
||||
Serial.print(", ");
|
||||
|
||||
// Print animal name
|
||||
Serial.print(animal->name);
|
||||
}
|
||||
}
|
||||
Serial.println(".");
|
||||
|
||||
while (true); // nothing else to do, loop forever
|
||||
}
|
|
@ -0,0 +1,58 @@
|
|||
/*
|
||||
LinkedList Example
|
||||
Link: http://github.com/ivanseidel/LinkedList
|
||||
|
||||
Example Created by
|
||||
Tom Stewart, github.com/tastewar
|
||||
|
||||
Edited by:
|
||||
Ivan Seidel, github.com/ivanseidel
|
||||
*/
|
||||
#include <LinkedList.h>
|
||||
|
||||
LinkedList<int> myList = LinkedList<int>();
|
||||
|
||||
void setup()
|
||||
{
|
||||
|
||||
Serial.begin(9600);
|
||||
Serial.println("Hello!");
|
||||
|
||||
// Add some stuff to the list
|
||||
int k = -240,
|
||||
l = 123,
|
||||
m = -2,
|
||||
n = 222;
|
||||
myList.add(n);
|
||||
myList.add(0);
|
||||
myList.add(l);
|
||||
myList.add(17);
|
||||
myList.add(k);
|
||||
myList.add(m);
|
||||
}
|
||||
|
||||
void loop() {
|
||||
|
||||
int listSize = myList.size();
|
||||
|
||||
Serial.print("There are ");
|
||||
Serial.print(listSize);
|
||||
Serial.print(" integers in the list. The negative ones are: ");
|
||||
|
||||
// Print Negative numbers
|
||||
for (int h = 0; h < listSize; h++) {
|
||||
|
||||
// Get value from list
|
||||
int val = myList.get(h);
|
||||
|
||||
// If the value is negative, print it
|
||||
if (val < 0) {
|
||||
Serial.print(" ");
|
||||
Serial.print(val);
|
||||
}
|
||||
}
|
||||
|
||||
while (true); // nothing else to do, loop forever
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,28 @@
|
|||
#######################################
|
||||
# Syntax Coloring
|
||||
#######################################
|
||||
|
||||
#######################################
|
||||
# Datatypes (KEYWORD1)
|
||||
#######################################
|
||||
|
||||
LinkedList KEYWORD1
|
||||
ListNode KEYWORD1
|
||||
|
||||
#######################################
|
||||
# Methods and Functions (KEYWORD2)
|
||||
#######################################
|
||||
|
||||
size KEYWORD2
|
||||
add KEYWORD2
|
||||
unshift KEYWORD2
|
||||
set KEYWORD2
|
||||
remove KEYWORD2
|
||||
pop KEYWORD2
|
||||
shift KEYWORD2
|
||||
get KEYWORD2
|
||||
clear KEYWORD2
|
||||
|
||||
#######################################
|
||||
# Constants (LITERAL1)
|
||||
#######################################
|
|
@ -0,0 +1,12 @@
|
|||
{
|
||||
"name": "LinkedList",
|
||||
"keywords": "pattern",
|
||||
"description": "A fully implemented LinkedList (int, float, objects, Lists or Wales) made to work with Arduino projects",
|
||||
"repository":
|
||||
{
|
||||
"type": "git",
|
||||
"url": "https://github.com/ivanseidel/LinkedList.git"
|
||||
},
|
||||
"frameworks": "arduino",
|
||||
"platforms": "*"
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
name=LinkedList
|
||||
version=1.2.3
|
||||
author=Ivan Seidel <ivanseidel@gmail.com>
|
||||
maintainer=Ivan Seidel <ivanseidel@gmail.com>
|
||||
sentence=A fully implemented LinkedList made to work with Arduino projects
|
||||
paragraph=The objective of this library is to create a pattern for projects. If you need to use a List of: int, float, objects, Lists or Wales. This is what you are looking for.
|
||||
category=Data Processing
|
||||
url=https://github.com/ivanseidel/LinkedList
|
||||
architectures=*
|
|
@ -65,8 +65,8 @@ build_flags = ${esp82xx_defaults.build_flags}
|
|||
-DVTABLES_IN_FLASH
|
||||
|
||||
[core_2_5_0]
|
||||
; *** Esp8266 core for Arduino version 2.5.0 release (still not available via platformio)
|
||||
platform = https://github.com/Jason2866/platform-espressif8266.git#Tasmota
|
||||
; *** Esp8266 core for Arduino version 2.5.0
|
||||
platform = espressif8266@2.0.0
|
||||
build_flags = ${esp82xx_defaults.build_flags}
|
||||
-Wl,-Teagle.flash.1m.ld
|
||||
; lwIP 1.4 (Default)
|
||||
|
|
|
@ -1,5 +1,26 @@
|
|||
/* 6.4.1.16 20190211
|
||||
* Initial support for online template change using command Template (#5177)
|
||||
/* 6.4.1.18 20191221
|
||||
* Fix some exceptions and watchdogs due to lack of stack space - part 1 (#5215)
|
||||
* Fix some exceptions and watchdogs due to lack of stack space - part 2
|
||||
* Add command SetOption62 0/1 to disable retain on Button or Swith hold messages (#5299)
|
||||
* Add option WifiConfig 7 to allow reset of device in AP mode without admin password (#5297)
|
||||
* Fix command WebSend when using a port number as regression from 6.4.1.17 (#5304)
|
||||
*
|
||||
* 6.4.1.17 20190214
|
||||
* Change template update by removing possibility to add user module config keeping template as defined (#5222)
|
||||
* Fix regression from 6.4.1.16 where GPIO9 and GPIO10 connected devices did not work (#5197)
|
||||
* Fix GUI wifi password acception starting with asteriks (*) (#5231, #5242)
|
||||
* Add rule expression enabled by define USE_EXPRESSION in my_user_config.h (#5210)
|
||||
* Add Configure Template menu option to GUI (#5222)
|
||||
* Remove command SetOption62 as it's functionality is replaced by user changing the device template (#5255)
|
||||
* Add property LinkCount to state and status 11 message representing number of Wifi Link re-connections
|
||||
* Add property MqttCount to status 6 message representing number of Mqtt re-connections
|
||||
* Add property Downtime to state and status 11 message representing the duration of wifi connection loss
|
||||
* Fix command WebSend intermittent results (#5273)
|
||||
*
|
||||
* 6.4.1.16 20190211
|
||||
* Initial support for online template change using command Template or GUI Configure Other (#5177)
|
||||
* Add parameter CFG_HOLDER to status 1 message (#5206)
|
||||
* Update GUI
|
||||
*
|
||||
* 6.4.1.15 20190208
|
||||
* Change image name BE_MINIMAL to FIRMWARE_MINIMAL (#5106)
|
||||
|
|
|
@ -44,6 +44,7 @@
|
|||
#define D_JSON_CHANNEL "Channel"
|
||||
#define D_JSON_CO2 "CarbonDioxide"
|
||||
#define D_JSON_COMMAND "Command"
|
||||
#define D_JSON_CONFIG_HOLDER "CfgHolder"
|
||||
#define D_JSON_CONNECT_FAILED "Connect failed"
|
||||
#define D_JSON_COREVERSION "Core"
|
||||
#define D_JSON_COUNT "Count"
|
||||
|
@ -53,6 +54,7 @@
|
|||
#define D_JSON_DISTANCE "Distance"
|
||||
#define D_JSON_DNSSERVER "DNSServer"
|
||||
#define D_JSON_DONE "Done"
|
||||
#define D_JSON_DOWNTIME "Downtime"
|
||||
#define D_JSON_ECO2 "eCO2"
|
||||
#define D_JSON_EMPTY "Empty"
|
||||
#define D_JSON_ENDDST "EndDST" // End Daylight Savings Time
|
||||
|
@ -88,12 +90,14 @@
|
|||
#define D_JSON_INFRARED "Infrared"
|
||||
#define D_JSON_UNKNOWN "Unknown"
|
||||
#define D_JSON_LIGHT "Light"
|
||||
#define D_JSON_LINK_COUNT "LinkCount"
|
||||
#define D_JSON_LOCAL_TIME "Local"
|
||||
#define D_JSON_LOW "Low"
|
||||
#define D_JSON_MAC "Mac"
|
||||
#define D_JSON_MASK "Mask"
|
||||
#define D_JSON_MINIMAL "minimal"
|
||||
#define D_JSON_MODEL "Model"
|
||||
#define D_JSON_MQTT_COUNT "MqttCount"
|
||||
#define D_JSON_NO "No"
|
||||
#define D_JSON_NOISE "Noise"
|
||||
#define D_JSON_NONE "None"
|
||||
|
@ -244,6 +248,7 @@
|
|||
#define D_WCFG_4_RETRY "Retry"
|
||||
#define D_WCFG_5_WAIT "Wait"
|
||||
#define D_WCFG_6_SERIAL "Serial"
|
||||
#define D_WCFG_7_WIFIMANAGER_RESET_ONLY "ManagerRst"
|
||||
#define D_CMND_FRIENDLYNAME "FriendlyName"
|
||||
#define D_CMND_SWITCHMODE "SwitchMode"
|
||||
#define D_CMND_INTERLOCK "Interlock"
|
||||
|
@ -418,6 +423,7 @@
|
|||
/********************************************************************************************/
|
||||
|
||||
#define D_ASTERIX "********"
|
||||
#define D_ASTERISK_PWD "****"
|
||||
|
||||
#ifndef MY_LANGUAGE
|
||||
#include "language/en-GB.h"
|
||||
|
@ -535,7 +541,8 @@ const char kWifiConfig[MAX_WIFI_OPTION][WCFG_MAX_STRING_LENGTH] PROGMEM = {
|
|||
D_WCFG_3_WPSCONFIG,
|
||||
D_WCFG_4_RETRY,
|
||||
D_WCFG_5_WAIT,
|
||||
D_WCFG_6_SERIAL };
|
||||
D_WCFG_6_SERIAL,
|
||||
D_WCFG_7_WIFIMANAGER_RESET_ONLY };
|
||||
const char kPrefixes[3][PRFX_MAX_STRING_LENGTH] PROGMEM = {
|
||||
D_CMND,
|
||||
D_STAT,
|
||||
|
@ -567,6 +574,7 @@ const char HTTP_SNS_CO2[] PROGMEM = "%s{s}%s " D_CO2 "{m}%d " D_UNIT_PARTS_PER_M
|
|||
|
||||
const char S_MAIN_MENU[] PROGMEM = D_MAIN_MENU;
|
||||
const char S_CONFIGURATION[] PROGMEM = D_CONFIGURATION;
|
||||
const char S_CONFIGURE_TEMPLATE[] PROGMEM = D_CONFIGURE_TEMPLATE;
|
||||
const char S_CONFIGURE_MODULE[] PROGMEM = D_CONFIGURE_MODULE;
|
||||
const char S_CONFIGURE_WIFI[] PROGMEM = D_CONFIGURE_WIFI;
|
||||
const char S_NO_NETWORKS_FOUND[] PROGMEM = D_NO_NETWORKS_FOUND;
|
||||
|
|
|
@ -28,7 +28,7 @@
|
|||
* Use online command StateText to translate ON, OFF, HOLD and TOGGLE.
|
||||
* Use online command Prefix to translate cmnd, stat and tele.
|
||||
*
|
||||
* Updated until v6.4.0.1
|
||||
* Updated until v6.4.1.17 (up to commit 590c883b)
|
||||
\*********************************************************************/
|
||||
|
||||
//#define LANGUAGE_MODULE_NAME // Enable to display "Module Generic" (ie Spanish), Disable to display "Generic Module" (ie English)
|
||||
|
@ -253,7 +253,7 @@
|
|||
|
||||
#define D_MODULE_PARAMETERS "Параметри на модула"
|
||||
#define D_MODULE_TYPE "Тип на модула"
|
||||
#define D_PULLUP_ENABLE "No Button/Switch pull-up"
|
||||
#define D_PULLUP_ENABLE "Без pull-up за бутон/ключ"
|
||||
#define D_GPIO "GPIO"
|
||||
#define D_SERIAL_IN "Сериен вход"
|
||||
#define D_SERIAL_OUT "Сериен изход"
|
||||
|
@ -288,6 +288,8 @@
|
|||
#define D_TELEMETRY_PERIOD "Период на телеметрия"
|
||||
|
||||
#define D_OTHER_PARAMETERS "Други параметри"
|
||||
#define D_TEMPLATE "Модел"
|
||||
#define D_ACTIVATE "Активирай"
|
||||
#define D_WEB_ADMIN_PASSWORD "Парола на уеб администратора"
|
||||
#define D_MQTT_ENABLE "Активиране на MQTT"
|
||||
#define D_FRIENDLY_NAME "Приятелско име"
|
||||
|
@ -296,6 +298,14 @@
|
|||
#define D_SINGLE_DEVICE "Единично"
|
||||
#define D_MULTI_DEVICE "Мулти"
|
||||
|
||||
#define D_CONFIGURE_TEMPLATE "Конфигуриране на модел"
|
||||
#define D_TEMPLATE_PARAMETERS "Параметри на модел"
|
||||
#define D_TEMPLATE_NAME "Име"
|
||||
#define D_BASE_TYPE "Базиран на"
|
||||
#define D_TEMPLATE_FLAGS "Флагове"
|
||||
#define D_ALLOW_ADC0 "ADC0 вход"
|
||||
#define D_ALLOW_PULLUP "Потребителски избор на pull-up"
|
||||
|
||||
#define D_SAVE_CONFIGURATION "Запазване на конфигурацията"
|
||||
#define D_CONFIGURATION_SAVED "Конфигурацията е запазена"
|
||||
#define D_CONFIGURATION_RESET "Конфигурацията е изчистена"
|
||||
|
@ -483,6 +493,7 @@
|
|||
|
||||
// sonoff_template.h - keep them as short as possible to be able to fit them in GUI drop down box
|
||||
#define D_SENSOR_NONE "Няма"
|
||||
#define D_SENSOR_USER "Потребит."
|
||||
#define D_SENSOR_DHT11 "DHT11"
|
||||
#define D_SENSOR_AM2301 "AM2301"
|
||||
#define D_SENSOR_SI7021 "SI7021"
|
||||
|
|
|
@ -288,6 +288,8 @@
|
|||
#define D_TELEMETRY_PERIOD "Interval telemetrie"
|
||||
|
||||
#define D_OTHER_PARAMETERS "Další nastavení"
|
||||
#define D_TEMPLATE "Template"
|
||||
#define D_ACTIVATE "Activate"
|
||||
#define D_WEB_ADMIN_PASSWORD "Heslo Web administrátora"
|
||||
#define D_MQTT_ENABLE "MQTT aktivní"
|
||||
#define D_FRIENDLY_NAME "Friendly Name"
|
||||
|
@ -296,6 +298,14 @@
|
|||
#define D_SINGLE_DEVICE "single device"
|
||||
#define D_MULTI_DEVICE "multi device"
|
||||
|
||||
#define D_CONFIGURE_TEMPLATE "Configure Template"
|
||||
#define D_TEMPLATE_PARAMETERS "Template parameters"
|
||||
#define D_TEMPLATE_NAME "Name"
|
||||
#define D_BASE_TYPE "Based on"
|
||||
#define D_TEMPLATE_FLAGS "Options"
|
||||
#define D_ALLOW_ADC0 "ADC0 input"
|
||||
#define D_ALLOW_PULLUP "User pull-up selection"
|
||||
|
||||
#define D_SAVE_CONFIGURATION "Ulož nastavení"
|
||||
#define D_CONFIGURATION_SAVED "Nastavení uloženo"
|
||||
#define D_CONFIGURATION_RESET "Nastavení resetováno"
|
||||
|
@ -483,6 +493,7 @@
|
|||
|
||||
// sonoff_template.h - keep them as short as possible to be able to fit them in GUI drop down box
|
||||
#define D_SENSOR_NONE "Není"
|
||||
#define D_SENSOR_USER "User"
|
||||
#define D_SENSOR_DHT11 "DHT11"
|
||||
#define D_SENSOR_AM2301 "AM2301"
|
||||
#define D_SENSOR_SI7021 "SI7021"
|
||||
|
|
|
@ -28,7 +28,7 @@
|
|||
* Use online command StateText to translate ON, OFF, HOLD and TOGGLE.
|
||||
* Use online command Prefix to translate cmnd, stat and tele.
|
||||
*
|
||||
* Updated until v6.3.0.17
|
||||
* Updated until v6.4.1.17
|
||||
\*********************************************************************/
|
||||
|
||||
//#define LANGUAGE_MODULE_NAME // Enable to display "Module Generic" (ie Spanish), Disable to display "Generic Module" (ie English)
|
||||
|
@ -288,6 +288,8 @@
|
|||
#define D_TELEMETRY_PERIOD "Telemetrieperiode"
|
||||
|
||||
#define D_OTHER_PARAMETERS "Sonstige Einstellungen"
|
||||
#define D_TEMPLATE "Vorlage"
|
||||
#define D_ACTIVATE "Aktivieren"
|
||||
#define D_WEB_ADMIN_PASSWORD "Passwort für Web Oberfläche"
|
||||
#define D_MQTT_ENABLE "MQTT aktivieren"
|
||||
#define D_FRIENDLY_NAME "Name [friendly name]"
|
||||
|
@ -296,6 +298,14 @@
|
|||
#define D_SINGLE_DEVICE "Einzelnes Gerät"
|
||||
#define D_MULTI_DEVICE "Mehrfachgerät"
|
||||
|
||||
#define D_CONFIGURE_TEMPLATE "Vorlage konfigurieren"
|
||||
#define D_TEMPLATE_PARAMETERS "Vorlage Parameter"
|
||||
#define D_TEMPLATE_NAME "Name"
|
||||
#define D_BASE_TYPE "basiert auf"
|
||||
#define D_TEMPLATE_FLAGS "Options"
|
||||
#define D_ALLOW_ADC0 "ADC0 input"
|
||||
#define D_ALLOW_PULLUP "Nutzer pull-up Auswahl"
|
||||
|
||||
#define D_SAVE_CONFIGURATION "Konfiguration speichern"
|
||||
#define D_CONFIGURATION_SAVED "Konfiguration gespeichert"
|
||||
#define D_CONFIGURATION_RESET "Konfiguration zurücksetzen"
|
||||
|
@ -483,6 +493,7 @@
|
|||
|
||||
// sonoff_template.h - keep them as short as possible to be able to fit them in GUI drop down box
|
||||
#define D_SENSOR_NONE "None"
|
||||
#define D_SENSOR_USER "User"
|
||||
#define D_SENSOR_DHT11 "DHT11"
|
||||
#define D_SENSOR_AM2301 "AM2301"
|
||||
#define D_SENSOR_SI7021 "SI7021"
|
||||
|
|
|
@ -288,6 +288,8 @@
|
|||
#define D_TELEMETRY_PERIOD "Περίοδος τηλεμετρίας"
|
||||
|
||||
#define D_OTHER_PARAMETERS "Άλλες παράμετροι"
|
||||
#define D_TEMPLATE "Template"
|
||||
#define D_ACTIVATE "Activate"
|
||||
#define D_WEB_ADMIN_PASSWORD "Κωδικός διαχειριστή"
|
||||
#define D_MQTT_ENABLE "Ενεργοποίηση MQTT"
|
||||
#define D_FRIENDLY_NAME "Φιλική ονομασία"
|
||||
|
@ -296,6 +298,14 @@
|
|||
#define D_SINGLE_DEVICE "μονή συσκευή"
|
||||
#define D_MULTI_DEVICE "πολλαπλές συσκευές"
|
||||
|
||||
#define D_CONFIGURE_TEMPLATE "Configure Template"
|
||||
#define D_TEMPLATE_PARAMETERS "Template parameters"
|
||||
#define D_TEMPLATE_NAME "Name"
|
||||
#define D_BASE_TYPE "Based on"
|
||||
#define D_TEMPLATE_FLAGS "Options"
|
||||
#define D_ALLOW_ADC0 "ADC0 input"
|
||||
#define D_ALLOW_PULLUP "User pull-up selection"
|
||||
|
||||
#define D_SAVE_CONFIGURATION "Αποθήκευση ρυθμίσεων"
|
||||
#define D_CONFIGURATION_SAVED "Οι ρυθμίσεις αποθηκεύτηκαν"
|
||||
#define D_CONFIGURATION_RESET "Επαναφορά ρυθμίσεων"
|
||||
|
@ -483,6 +493,7 @@
|
|||
|
||||
// sonoff_template.h - keep them as short as possible to be able to fit them in GUI drop down box
|
||||
#define D_SENSOR_NONE "Κανένα"
|
||||
#define D_SENSOR_USER "User"
|
||||
#define D_SENSOR_DHT11 "DHT11"
|
||||
#define D_SENSOR_AM2301 "AM2301"
|
||||
#define D_SENSOR_SI7021 "SI7021"
|
||||
|
|
|
@ -288,6 +288,8 @@
|
|||
#define D_TELEMETRY_PERIOD "Telemetry period"
|
||||
|
||||
#define D_OTHER_PARAMETERS "Other parameters"
|
||||
#define D_TEMPLATE "Template"
|
||||
#define D_ACTIVATE "Activate"
|
||||
#define D_WEB_ADMIN_PASSWORD "Web Admin Password"
|
||||
#define D_MQTT_ENABLE "MQTT enable"
|
||||
#define D_FRIENDLY_NAME "Friendly Name"
|
||||
|
@ -296,6 +298,14 @@
|
|||
#define D_SINGLE_DEVICE "single device"
|
||||
#define D_MULTI_DEVICE "multi device"
|
||||
|
||||
#define D_CONFIGURE_TEMPLATE "Configure Template"
|
||||
#define D_TEMPLATE_PARAMETERS "Template parameters"
|
||||
#define D_TEMPLATE_NAME "Name"
|
||||
#define D_BASE_TYPE "Based on"
|
||||
#define D_TEMPLATE_FLAGS "Options"
|
||||
#define D_ALLOW_ADC0 "ADC0 input"
|
||||
#define D_ALLOW_PULLUP "User pull-up selection"
|
||||
|
||||
#define D_SAVE_CONFIGURATION "Save configuration"
|
||||
#define D_CONFIGURATION_SAVED "Configuration saved"
|
||||
#define D_CONFIGURATION_RESET "Configuration reset"
|
||||
|
@ -483,6 +493,7 @@
|
|||
|
||||
// sonoff_template.h - keep them as short as possible to be able to fit them in GUI drop down box
|
||||
#define D_SENSOR_NONE "None"
|
||||
#define D_SENSOR_USER "User"
|
||||
#define D_SENSOR_DHT11 "DHT11"
|
||||
#define D_SENSOR_AM2301 "AM2301"
|
||||
#define D_SENSOR_SI7021 "SI7021"
|
||||
|
|
|
@ -288,6 +288,8 @@
|
|||
#define D_TELEMETRY_PERIOD "Período de Telemetría"
|
||||
|
||||
#define D_OTHER_PARAMETERS "Otros parámetros"
|
||||
#define D_TEMPLATE "Template"
|
||||
#define D_ACTIVATE "Activate"
|
||||
#define D_WEB_ADMIN_PASSWORD "Clave Administrador Web"
|
||||
#define D_MQTT_ENABLE "Habilitar MQTT"
|
||||
#define D_FRIENDLY_NAME "Nombre Amigable"
|
||||
|
@ -296,6 +298,14 @@
|
|||
#define D_SINGLE_DEVICE "dispositivo simple"
|
||||
#define D_MULTI_DEVICE "dispositivo múltiple"
|
||||
|
||||
#define D_CONFIGURE_TEMPLATE "Configure Template"
|
||||
#define D_TEMPLATE_PARAMETERS "Template parameters"
|
||||
#define D_TEMPLATE_NAME "Name"
|
||||
#define D_BASE_TYPE "Based on"
|
||||
#define D_TEMPLATE_FLAGS "Options"
|
||||
#define D_ALLOW_ADC0 "ADC0 input"
|
||||
#define D_ALLOW_PULLUP "User pull-up selection"
|
||||
|
||||
#define D_SAVE_CONFIGURATION "Grabar configuración"
|
||||
#define D_CONFIGURATION_SAVED "Configuración grabada"
|
||||
#define D_CONFIGURATION_RESET "Configuración restablecida"
|
||||
|
@ -483,6 +493,7 @@
|
|||
|
||||
// sonoff_template.h - keep them as short as possible to be able to fit them in GUI drop down box
|
||||
#define D_SENSOR_NONE "Ninguno"
|
||||
#define D_SENSOR_USER "User"
|
||||
#define D_SENSOR_DHT11 "DHT11"
|
||||
#define D_SENSOR_AM2301 "AM2301"
|
||||
#define D_SENSOR_SI7021 "SI7021"
|
||||
|
|
|
@ -28,7 +28,7 @@
|
|||
* Use online command StateText to translate ON, OFF, HOLD and TOGGLE.
|
||||
* Use online command Prefix to translate cmnd, stat and tele.
|
||||
*
|
||||
* Updated until v6.3.0.17
|
||||
* Updated until v6.4.1.17
|
||||
\*********************************************************************/
|
||||
|
||||
#define LANGUAGE_MODULE_NAME // Enable to display "Module Generic" (ie Spanish), Disable to display "Generic Module" (ie English)
|
||||
|
@ -98,8 +98,8 @@
|
|||
#define D_GAS "Gaz"
|
||||
#define D_GATEWAY "Passerelle"
|
||||
#define D_GROUP "Groupe"
|
||||
#define D_HOST "Host"
|
||||
#define D_HOSTNAME "Hostname"
|
||||
#define D_HOST "Hôte"
|
||||
#define D_HOSTNAME "Nom d'Hôte"
|
||||
#define D_HUMIDITY "Humidité"
|
||||
#define D_ILLUMINANCE "Éclairement"
|
||||
#define D_IMMEDIATE "immédiat" // Button immediate
|
||||
|
@ -138,7 +138,7 @@
|
|||
#define D_RESTARTING "Redémarre"
|
||||
#define D_RESTART_REASON "Raison du redémarrage"
|
||||
#define D_RESTORE "restaurer"
|
||||
#define D_RETAINED "retenu"
|
||||
#define D_RETAINED "persistant" // MQTT
|
||||
#define D_RULE "Règle"
|
||||
#define D_SAVE "Enregistrer"
|
||||
#define D_SENSOR "Capteur"
|
||||
|
@ -184,7 +184,7 @@
|
|||
#define D_LEVEL_10 "level 1-0"
|
||||
#define D_LEVEL_01 "level 0-1"
|
||||
#define D_SERIAL_LOGGING_DISABLED "Journalisation série désactivée"
|
||||
#define D_SYSLOG_LOGGING_REENABLED "Jounalisation syslog réactivée"
|
||||
#define D_SYSLOG_LOGGING_REENABLED "Jounalisation SysLog réactivée"
|
||||
|
||||
#define D_SET_BAUDRATE_TO "Définir le débit à"
|
||||
#define D_RECEIVED_TOPIC "Topic reçu" // Terme MQTT
|
||||
|
@ -209,7 +209,7 @@
|
|||
#define D_QUERY_DONE "Requête terminée. Services MQTT trouvés"
|
||||
#define D_MQTT_SERVICE_FOUND "Service MQTT trouvé sur"
|
||||
#define D_FOUND_AT "trouvé à"
|
||||
#define D_SYSLOG_HOST_NOT_FOUND "Host syslog introuvable"
|
||||
#define D_SYSLOG_HOST_NOT_FOUND "Hôte SysLog introuvable"
|
||||
|
||||
// settings.ino
|
||||
#define D_SAVED_TO_FLASH_AT "Enregistré en flash à"
|
||||
|
@ -253,7 +253,7 @@
|
|||
|
||||
#define D_MODULE_PARAMETERS "Paramètres module"
|
||||
#define D_MODULE_TYPE "Type de module"
|
||||
#define D_PULLUP_ENABLE "No Button/Switch pull-up"
|
||||
#define D_PULLUP_ENABLE "Inter. sans pull-up"
|
||||
#define D_GPIO "GPIO"
|
||||
#define D_SERIAL_IN "Entrée série"
|
||||
#define D_SERIAL_OUT "Sortie série"
|
||||
|
@ -281,13 +281,15 @@
|
|||
#define D_LOGGING_PARAMETERS "Paramètres du journal"
|
||||
#define D_SERIAL_LOG_LEVEL "Niveau de journalisation série"
|
||||
#define D_WEB_LOG_LEVEL "Niveau de journalisation web"
|
||||
#define D_SYS_LOG_LEVEL "Niveau Syslog"
|
||||
#define D_SYS_LOG_LEVEL "Niveau SysLog"
|
||||
#define D_MORE_DEBUG "Plus de debug"
|
||||
#define D_SYSLOG_HOST "Hôte Syslog"
|
||||
#define D_SYSLOG_PORT "Port Syslog"
|
||||
#define D_SYSLOG_HOST "Hôte SysLog"
|
||||
#define D_SYSLOG_PORT "Port SysLog"
|
||||
#define D_TELEMETRY_PERIOD "Période télémétrie"
|
||||
|
||||
#define D_OTHER_PARAMETERS "Autres paramètres"
|
||||
#define D_TEMPLATE "Modèle"
|
||||
#define D_ACTIVATE "Activer"
|
||||
#define D_WEB_ADMIN_PASSWORD "Mot de passe Web Admin"
|
||||
#define D_MQTT_ENABLE "MQTT activé"
|
||||
#define D_FRIENDLY_NAME "Surnom"
|
||||
|
@ -296,6 +298,14 @@
|
|||
#define D_SINGLE_DEVICE "module unique"
|
||||
#define D_MULTI_DEVICE "multi module"
|
||||
|
||||
#define D_CONFIGURE_TEMPLATE "Configuration du modèle"
|
||||
#define D_TEMPLATE_PARAMETERS "Paramètres du modèle"
|
||||
#define D_TEMPLATE_NAME "Nom"
|
||||
#define D_BASE_TYPE "Basé sur"
|
||||
#define D_TEMPLATE_FLAGS "Options"
|
||||
#define D_ALLOW_ADC0 "Entrée ADC0"
|
||||
#define D_ALLOW_PULLUP "Choix de pull-up utilisateur"
|
||||
|
||||
#define D_SAVE_CONFIGURATION "Enregistrer la configuration"
|
||||
#define D_CONFIGURATION_SAVED "Configuration enregistrée"
|
||||
#define D_CONFIGURATION_RESET "Configuration réinitialisée"
|
||||
|
@ -331,7 +341,7 @@
|
|||
#define D_UPLOAD_ERR_3 "L'octet magique n'est pas 0xE9"
|
||||
#define D_UPLOAD_ERR_4 "La taille du programme à flasher est plus grande que la taille réelle de la mémoire flash"
|
||||
#define D_UPLOAD_ERR_5 "Erreur de comparaison du buffer de téléchargement"
|
||||
#define D_UPLOAD_ERR_6 "Téléchargement échoué. Activer Weblog 3"
|
||||
#define D_UPLOAD_ERR_6 "Téléchargement échoué. Activer WebLog 3"
|
||||
#define D_UPLOAD_ERR_7 "Téléchargement annulé"
|
||||
#define D_UPLOAD_ERR_8 "Fichier invalide"
|
||||
#define D_UPLOAD_ERR_9 "Fichier trop grand"
|
||||
|
@ -342,7 +352,7 @@
|
|||
#define D_UPLOAD_ERROR_CODE "Code d'erreur téléchargement"
|
||||
|
||||
#define D_ENTER_COMMAND "Saisir une commande"
|
||||
#define D_ENABLE_WEBLOG_FOR_RESPONSE "Activer Weblog 2 si une réponse est attendue"
|
||||
#define D_ENABLE_WEBLOG_FOR_RESPONSE "Activer WebLog 2 si une réponse est attendue"
|
||||
#define D_NEED_USER_AND_PASSWORD "Nécessite utilisateur=<username>&password=<password>"
|
||||
|
||||
// xdrv_01_mqtt.ino
|
||||
|
@ -483,6 +493,7 @@
|
|||
|
||||
// sonoff_template.h - keep them as short as possible to be able to fit them in GUI drop down box
|
||||
#define D_SENSOR_NONE "Aucun"
|
||||
#define D_SENSOR_USER "Utilisateur"
|
||||
#define D_SENSOR_DHT11 "DHT11"
|
||||
#define D_SENSOR_AM2301 "AM2301"
|
||||
#define D_SENSOR_SI7021 "SI7021"
|
||||
|
|
|
@ -288,6 +288,8 @@
|
|||
#define D_TELEMETRY_PERIOD "Telemetry period"
|
||||
|
||||
#define D_OTHER_PARAMETERS "פרמטרים שונים"
|
||||
#define D_TEMPLATE "Template"
|
||||
#define D_ACTIVATE "Activate"
|
||||
#define D_WEB_ADMIN_PASSWORD "סיסמת מנהל - אתר"
|
||||
#define D_MQTT_ENABLE "MQTT אפשר"
|
||||
#define D_FRIENDLY_NAME "שם ידידותי"
|
||||
|
@ -296,6 +298,14 @@
|
|||
#define D_SINGLE_DEVICE "התקן בודד"
|
||||
#define D_MULTI_DEVICE "התקנים"
|
||||
|
||||
#define D_CONFIGURE_TEMPLATE "Configure Template"
|
||||
#define D_TEMPLATE_PARAMETERS "Template parameters"
|
||||
#define D_TEMPLATE_NAME "Name"
|
||||
#define D_BASE_TYPE "Based on"
|
||||
#define D_TEMPLATE_FLAGS "Options"
|
||||
#define D_ALLOW_ADC0 "ADC0 input"
|
||||
#define D_ALLOW_PULLUP "User pull-up selection"
|
||||
|
||||
#define D_SAVE_CONFIGURATION "שמירת הגדרות"
|
||||
#define D_CONFIGURATION_SAVED "הגדרות נשמרו"
|
||||
#define D_CONFIGURATION_RESET "איפוס הגדרות"
|
||||
|
@ -483,6 +493,7 @@
|
|||
|
||||
// sonoff_template.h - keep them as short as possible to be able to fit them in GUI drop down box
|
||||
#define D_SENSOR_NONE "None"
|
||||
#define D_SENSOR_USER "User"
|
||||
#define D_SENSOR_DHT11 "DHT11"
|
||||
#define D_SENSOR_AM2301 "AM2301"
|
||||
#define D_SENSOR_SI7021 "SI7021"
|
||||
|
|
|
@ -288,6 +288,8 @@
|
|||
#define D_TELEMETRY_PERIOD "Telemetria (mp.)"
|
||||
|
||||
#define D_OTHER_PARAMETERS "Egyéb beállítások"
|
||||
#define D_TEMPLATE "Template"
|
||||
#define D_ACTIVATE "Activate"
|
||||
#define D_WEB_ADMIN_PASSWORD "Web admin jelszó"
|
||||
#define D_MQTT_ENABLE "MQTT engedélyezése"
|
||||
#define D_FRIENDLY_NAME "Név"
|
||||
|
@ -296,6 +298,14 @@
|
|||
#define D_SINGLE_DEVICE "single device"
|
||||
#define D_MULTI_DEVICE "multi device"
|
||||
|
||||
#define D_CONFIGURE_TEMPLATE "Configure Template"
|
||||
#define D_TEMPLATE_PARAMETERS "Template parameters"
|
||||
#define D_TEMPLATE_NAME "Name"
|
||||
#define D_BASE_TYPE "Based on"
|
||||
#define D_TEMPLATE_FLAGS "Options"
|
||||
#define D_ALLOW_ADC0 "ADC0 input"
|
||||
#define D_ALLOW_PULLUP "User pull-up selection"
|
||||
|
||||
#define D_SAVE_CONFIGURATION "Beállítások mentése"
|
||||
#define D_CONFIGURATION_SAVED "Beállítások elmentve"
|
||||
#define D_CONFIGURATION_RESET "Beállítások visszaállítása"
|
||||
|
@ -483,6 +493,7 @@
|
|||
|
||||
// sonoff_template.h - keep them as short as possible to be able to fit them in GUI drop down box
|
||||
#define D_SENSOR_NONE "Nincs"
|
||||
#define D_SENSOR_USER "User"
|
||||
#define D_SENSOR_DHT11 "DHT11"
|
||||
#define D_SENSOR_AM2301 "AM2301"
|
||||
#define D_SENSOR_SI7021 "SI7021"
|
||||
|
|
|
@ -288,6 +288,8 @@
|
|||
#define D_TELEMETRY_PERIOD "Periodo Telemetria"
|
||||
|
||||
#define D_OTHER_PARAMETERS "Altri parametri"
|
||||
#define D_TEMPLATE "Template"
|
||||
#define D_ACTIVATE "Activate"
|
||||
#define D_WEB_ADMIN_PASSWORD "Password Amministratore Web"
|
||||
#define D_MQTT_ENABLE "Abilita MQTT"
|
||||
#define D_FRIENDLY_NAME "Nome confidenziale"
|
||||
|
@ -296,6 +298,14 @@
|
|||
#define D_SINGLE_DEVICE "dispositivo singolo"
|
||||
#define D_MULTI_DEVICE "dispositivo multiplo"
|
||||
|
||||
#define D_CONFIGURE_TEMPLATE "Configure Template"
|
||||
#define D_TEMPLATE_PARAMETERS "Template parameters"
|
||||
#define D_TEMPLATE_NAME "Name"
|
||||
#define D_BASE_TYPE "Based on"
|
||||
#define D_TEMPLATE_FLAGS "Options"
|
||||
#define D_ALLOW_ADC0 "ADC0 input"
|
||||
#define D_ALLOW_PULLUP "User pull-up selection"
|
||||
|
||||
#define D_SAVE_CONFIGURATION "Salva configurazione"
|
||||
#define D_CONFIGURATION_SAVED "Configurazione salvata"
|
||||
#define D_CONFIGURATION_RESET "Configurazione azzerata"
|
||||
|
@ -483,6 +493,7 @@
|
|||
|
||||
// sonoff_template.h - keep them as short as possible to be able to fit them in GUI drop down box
|
||||
#define D_SENSOR_NONE "Nessuno"
|
||||
#define D_SENSOR_USER "User"
|
||||
#define D_SENSOR_DHT11 "DHT11"
|
||||
#define D_SENSOR_AM2301 "AM2301"
|
||||
#define D_SENSOR_SI7021 "SI7021"
|
||||
|
|
|
@ -288,6 +288,8 @@
|
|||
#define D_TELEMETRY_PERIOD "Telemetry periode"
|
||||
|
||||
#define D_OTHER_PARAMETERS "Overige parameters"
|
||||
#define D_TEMPLATE "Template"
|
||||
#define D_ACTIVATE "Activate"
|
||||
#define D_WEB_ADMIN_PASSWORD "Web Admin Wachtwoord"
|
||||
#define D_MQTT_ENABLE "MQTT ingeschakeld"
|
||||
#define D_FRIENDLY_NAME "Beschrijvende naam"
|
||||
|
@ -296,6 +298,14 @@
|
|||
#define D_SINGLE_DEVICE "een apparaat"
|
||||
#define D_MULTI_DEVICE "meer apparaten"
|
||||
|
||||
#define D_CONFIGURE_TEMPLATE "Configure Template"
|
||||
#define D_TEMPLATE_PARAMETERS "Template parameters"
|
||||
#define D_TEMPLATE_NAME "Name"
|
||||
#define D_BASE_TYPE "Based on"
|
||||
#define D_TEMPLATE_FLAGS "Options"
|
||||
#define D_ALLOW_ADC0 "ADC0 input"
|
||||
#define D_ALLOW_PULLUP "User pull-up selection"
|
||||
|
||||
#define D_SAVE_CONFIGURATION "Bewaar configuratie"
|
||||
#define D_CONFIGURATION_SAVED "Configuratie opgeslagen"
|
||||
#define D_CONFIGURATION_RESET "Configuratie ge-reset"
|
||||
|
@ -483,6 +493,7 @@
|
|||
|
||||
// sonoff_template.h - keep them as short as possible to be able to fit them in GUI drop down box
|
||||
#define D_SENSOR_NONE "Geen"
|
||||
#define D_SENSOR_USER "Gebruiker"
|
||||
#define D_SENSOR_DHT11 "DHT11"
|
||||
#define D_SENSOR_AM2301 "AM2301"
|
||||
#define D_SENSOR_SI7021 "SI7021"
|
||||
|
|
|
@ -288,6 +288,8 @@
|
|||
#define D_TELEMETRY_PERIOD "Okres telemetrii"
|
||||
|
||||
#define D_OTHER_PARAMETERS "Inne parametry"
|
||||
#define D_TEMPLATE "Template"
|
||||
#define D_ACTIVATE "Activate"
|
||||
#define D_WEB_ADMIN_PASSWORD "Hasło administratora Web"
|
||||
#define D_MQTT_ENABLE "MQTT aktywne"
|
||||
#define D_FRIENDLY_NAME "Twoja nazwa"
|
||||
|
@ -296,6 +298,14 @@
|
|||
#define D_SINGLE_DEVICE "single device"
|
||||
#define D_MULTI_DEVICE "multi device"
|
||||
|
||||
#define D_CONFIGURE_TEMPLATE "Configure Template"
|
||||
#define D_TEMPLATE_PARAMETERS "Template parameters"
|
||||
#define D_TEMPLATE_NAME "Name"
|
||||
#define D_BASE_TYPE "Based on"
|
||||
#define D_TEMPLATE_FLAGS "Options"
|
||||
#define D_ALLOW_ADC0 "ADC0 input"
|
||||
#define D_ALLOW_PULLUP "User pull-up selection"
|
||||
|
||||
#define D_SAVE_CONFIGURATION "Zapisz ustawienia"
|
||||
#define D_CONFIGURATION_SAVED "Ustawienia zapisane"
|
||||
#define D_CONFIGURATION_RESET "Ustawienia zresetowane"
|
||||
|
@ -483,6 +493,7 @@
|
|||
|
||||
// sonoff_template.h - keep them as short as possible to be able to fit them in GUI drop down box
|
||||
#define D_SENSOR_NONE "Brak"
|
||||
#define D_SENSOR_USER "User"
|
||||
#define D_SENSOR_DHT11 "DHT11"
|
||||
#define D_SENSOR_AM2301 "AM2301"
|
||||
#define D_SENSOR_SI7021 "SI7021"
|
||||
|
|
|
@ -288,6 +288,8 @@
|
|||
#define D_TELEMETRY_PERIOD "Período de telemetria"
|
||||
|
||||
#define D_OTHER_PARAMETERS "Outros parâmetros"
|
||||
#define D_TEMPLATE "Template"
|
||||
#define D_ACTIVATE "Activate"
|
||||
#define D_WEB_ADMIN_PASSWORD "Senha de WEB Admin"
|
||||
#define D_MQTT_ENABLE "MQTT habilitado"
|
||||
#define D_FRIENDLY_NAME "Nome amigável"
|
||||
|
@ -296,6 +298,14 @@
|
|||
#define D_SINGLE_DEVICE "Dispositivo único"
|
||||
#define D_MULTI_DEVICE "Múltiplos dispositivos"
|
||||
|
||||
#define D_CONFIGURE_TEMPLATE "Configure Template"
|
||||
#define D_TEMPLATE_PARAMETERS "Template parameters"
|
||||
#define D_TEMPLATE_NAME "Name"
|
||||
#define D_BASE_TYPE "Based on"
|
||||
#define D_TEMPLATE_FLAGS "Options"
|
||||
#define D_ALLOW_ADC0 "ADC0 input"
|
||||
#define D_ALLOW_PULLUP "User pull-up selection"
|
||||
|
||||
#define D_SAVE_CONFIGURATION "Gravar configuração"
|
||||
#define D_CONFIGURATION_SAVED "Configuração gravada"
|
||||
#define D_CONFIGURATION_RESET "Reinicialização da configuração"
|
||||
|
@ -483,6 +493,7 @@
|
|||
|
||||
// sonoff_template.h - keep them as short as possible to be able to fit them in GUI drop down box
|
||||
#define D_SENSOR_NONE "Nenhum"
|
||||
#define D_SENSOR_USER "User"
|
||||
#define D_SENSOR_DHT11 "DHT11"
|
||||
#define D_SENSOR_AM2301 "AM2301"
|
||||
#define D_SENSOR_SI7021 "SI7021"
|
||||
|
|
|
@ -288,6 +288,8 @@
|
|||
#define D_TELEMETRY_PERIOD "Periodo de Telemetria"
|
||||
|
||||
#define D_OTHER_PARAMETERS "Outros parametros"
|
||||
#define D_TEMPLATE "Template"
|
||||
#define D_ACTIVATE "Activate"
|
||||
#define D_WEB_ADMIN_PASSWORD "Palavra Chave de WEB Admin"
|
||||
#define D_MQTT_ENABLE "MQTT habilitado"
|
||||
#define D_FRIENDLY_NAME "Nome amigável"
|
||||
|
@ -296,6 +298,14 @@
|
|||
#define D_SINGLE_DEVICE "dispositivo único"
|
||||
#define D_MULTI_DEVICE "multiplos dispositivos"
|
||||
|
||||
#define D_CONFIGURE_TEMPLATE "Configure Template"
|
||||
#define D_TEMPLATE_PARAMETERS "Template parameters"
|
||||
#define D_TEMPLATE_NAME "Name"
|
||||
#define D_BASE_TYPE "Based on"
|
||||
#define D_TEMPLATE_FLAGS "Options"
|
||||
#define D_ALLOW_ADC0 "ADC0 input"
|
||||
#define D_ALLOW_PULLUP "User pull-up selection"
|
||||
|
||||
#define D_SAVE_CONFIGURATION "Salvar configuração"
|
||||
#define D_CONFIGURATION_SAVED "Configuração guardada"
|
||||
#define D_CONFIGURATION_RESET "Reinicialização da configuração"
|
||||
|
@ -483,6 +493,7 @@
|
|||
|
||||
// sonoff_template.h - keep them as short as possible to be able to fit them in GUI drop down box
|
||||
#define D_SENSOR_NONE "Nenhum"
|
||||
#define D_SENSOR_USER "User"
|
||||
#define D_SENSOR_DHT11 "DHT11"
|
||||
#define D_SENSOR_AM2301 "AM2301"
|
||||
#define D_SENSOR_SI7021 "SI7021"
|
||||
|
|
|
@ -288,6 +288,8 @@
|
|||
#define D_TELEMETRY_PERIOD "Период телеметрии"
|
||||
|
||||
#define D_OTHER_PARAMETERS "Параметры Прочие"
|
||||
#define D_TEMPLATE "Template"
|
||||
#define D_ACTIVATE "Activate"
|
||||
#define D_WEB_ADMIN_PASSWORD "Пароль Web администратора"
|
||||
#define D_MQTT_ENABLE "MQTT активен"
|
||||
#define D_FRIENDLY_NAME "Дружественное Имя"
|
||||
|
@ -296,6 +298,14 @@
|
|||
#define D_SINGLE_DEVICE "одиночное"
|
||||
#define D_MULTI_DEVICE "мульти"
|
||||
|
||||
#define D_CONFIGURE_TEMPLATE "Configure Template"
|
||||
#define D_TEMPLATE_PARAMETERS "Template parameters"
|
||||
#define D_TEMPLATE_NAME "Name"
|
||||
#define D_BASE_TYPE "Based on"
|
||||
#define D_TEMPLATE_FLAGS "Options"
|
||||
#define D_ALLOW_ADC0 "ADC0 input"
|
||||
#define D_ALLOW_PULLUP "User pull-up selection"
|
||||
|
||||
#define D_SAVE_CONFIGURATION "Сохранить конфигурацию"
|
||||
#define D_CONFIGURATION_SAVED "Конфигурация сохранена "
|
||||
#define D_CONFIGURATION_RESET "Конфигурация сброшена"
|
||||
|
@ -483,6 +493,7 @@
|
|||
|
||||
// sonoff_template.h - keep them as short as possible to be able to fit them in GUI drop down box
|
||||
#define D_SENSOR_NONE "-нет-"
|
||||
#define D_SENSOR_USER "User"
|
||||
#define D_SENSOR_DHT11 "DHT11"
|
||||
#define D_SENSOR_AM2301 "AM2301"
|
||||
#define D_SENSOR_SI7021 "SI7021"
|
||||
|
|
|
@ -288,6 +288,8 @@
|
|||
#define D_TELEMETRY_PERIOD "Interval telemetrie"
|
||||
|
||||
#define D_OTHER_PARAMETERS "Ostatné nastavenia"
|
||||
#define D_TEMPLATE "Template"
|
||||
#define D_ACTIVATE "Activate"
|
||||
#define D_WEB_ADMIN_PASSWORD "Heslo Web administrátora"
|
||||
#define D_MQTT_ENABLE "MQTT aktívne"
|
||||
#define D_FRIENDLY_NAME "Friendly Name"
|
||||
|
@ -296,6 +298,14 @@
|
|||
#define D_SINGLE_DEVICE "single device"
|
||||
#define D_MULTI_DEVICE "multi device"
|
||||
|
||||
#define D_CONFIGURE_TEMPLATE "Configure Template"
|
||||
#define D_TEMPLATE_PARAMETERS "Template parameters"
|
||||
#define D_TEMPLATE_NAME "Name"
|
||||
#define D_BASE_TYPE "Based on"
|
||||
#define D_TEMPLATE_FLAGS "Options"
|
||||
#define D_ALLOW_ADC0 "ADC0 input"
|
||||
#define D_ALLOW_PULLUP "User pull-up selection"
|
||||
|
||||
#define D_SAVE_CONFIGURATION "Ulož nastavenia"
|
||||
#define D_CONFIGURATION_SAVED "Nastavenia uložené"
|
||||
#define D_CONFIGURATION_RESET "Nastavenia resetované"
|
||||
|
@ -483,6 +493,7 @@
|
|||
|
||||
// sonoff_template.h - keep them as short as possible to be able to fit them in GUI drop down box
|
||||
#define D_SENSOR_NONE "Žiaden"
|
||||
#define D_SENSOR_USER "User"
|
||||
#define D_SENSOR_DHT11 "DHT11"
|
||||
#define D_SENSOR_AM2301 "AM2301"
|
||||
#define D_SENSOR_SI7021 "SI7021"
|
||||
|
|
|
@ -288,6 +288,8 @@
|
|||
#define D_TELEMETRY_PERIOD "Telemetriperiod"
|
||||
|
||||
#define D_OTHER_PARAMETERS "Andra parametrar"
|
||||
#define D_TEMPLATE "Template"
|
||||
#define D_ACTIVATE "Activate"
|
||||
#define D_WEB_ADMIN_PASSWORD "Webbadmin-lösenord"
|
||||
#define D_MQTT_ENABLE "MQTT aktivera"
|
||||
#define D_FRIENDLY_NAME "Läsbart namn"
|
||||
|
@ -296,6 +298,14 @@
|
|||
#define D_SINGLE_DEVICE "soloenhet"
|
||||
#define D_MULTI_DEVICE "multienhet"
|
||||
|
||||
#define D_CONFIGURE_TEMPLATE "Configure Template"
|
||||
#define D_TEMPLATE_PARAMETERS "Template parameters"
|
||||
#define D_TEMPLATE_NAME "Name"
|
||||
#define D_BASE_TYPE "Based on"
|
||||
#define D_TEMPLATE_FLAGS "Options"
|
||||
#define D_ALLOW_ADC0 "ADC0 input"
|
||||
#define D_ALLOW_PULLUP "User pull-up selection"
|
||||
|
||||
#define D_SAVE_CONFIGURATION "Spara konfiguration"
|
||||
#define D_CONFIGURATION_SAVED "Konfiguration sparad"
|
||||
#define D_CONFIGURATION_RESET "Konfiguration nollställd"
|
||||
|
@ -483,6 +493,7 @@
|
|||
|
||||
// sonoff_template.h - keep them as short as possible to be able to fit them in GUI drop down box
|
||||
#define D_SENSOR_NONE "Ingen"
|
||||
#define D_SENSOR_USER "User"
|
||||
#define D_SENSOR_DHT11 "DHT11"
|
||||
#define D_SENSOR_AM2301 "AM2301"
|
||||
#define D_SENSOR_SI7021 "SI7021"
|
||||
|
|
|
@ -288,6 +288,8 @@
|
|||
#define D_TELEMETRY_PERIOD "Telemetri peryodu"
|
||||
|
||||
#define D_OTHER_PARAMETERS "Diğer parametreler"
|
||||
#define D_TEMPLATE "Template"
|
||||
#define D_ACTIVATE "Activate"
|
||||
#define D_WEB_ADMIN_PASSWORD "Web Yönetici Şifresi"
|
||||
#define D_MQTT_ENABLE "MQTT aktif"
|
||||
#define D_FRIENDLY_NAME "Kullanıcı Dostu İsim"
|
||||
|
@ -296,6 +298,14 @@
|
|||
#define D_SINGLE_DEVICE "tekli cihaz"
|
||||
#define D_MULTI_DEVICE "çoklu cihaz"
|
||||
|
||||
#define D_CONFIGURE_TEMPLATE "Configure Template"
|
||||
#define D_TEMPLATE_PARAMETERS "Template parameters"
|
||||
#define D_TEMPLATE_NAME "Name"
|
||||
#define D_BASE_TYPE "Based on"
|
||||
#define D_TEMPLATE_FLAGS "Options"
|
||||
#define D_ALLOW_ADC0 "ADC0 input"
|
||||
#define D_ALLOW_PULLUP "User pull-up selection"
|
||||
|
||||
#define D_SAVE_CONFIGURATION "Ayarları Kaydet"
|
||||
#define D_CONFIGURATION_SAVED "Ayarlar kaydedildi"
|
||||
#define D_CONFIGURATION_RESET "Ayarlar resetlendi"
|
||||
|
@ -483,6 +493,7 @@
|
|||
|
||||
// sonoff_template.h - keep them as short as possible to be able to fit them in GUI drop down box
|
||||
#define D_SENSOR_NONE "None"
|
||||
#define D_SENSOR_USER "User"
|
||||
#define D_SENSOR_DHT11 "DHT11"
|
||||
#define D_SENSOR_AM2301 "AM2301"
|
||||
#define D_SENSOR_SI7021 "SI7021"
|
||||
|
|
|
@ -288,6 +288,8 @@
|
|||
#define D_TELEMETRY_PERIOD "Період телеметрії"
|
||||
|
||||
#define D_OTHER_PARAMETERS "Параметри Інше"
|
||||
#define D_TEMPLATE "Template"
|
||||
#define D_ACTIVATE "Activate"
|
||||
#define D_WEB_ADMIN_PASSWORD "Гасло Web адміністратора"
|
||||
#define D_MQTT_ENABLE "MQTT активний"
|
||||
#define D_FRIENDLY_NAME "Дружнє Ім'я"
|
||||
|
@ -296,6 +298,14 @@
|
|||
#define D_SINGLE_DEVICE "одиночне"
|
||||
#define D_MULTI_DEVICE "мульти"
|
||||
|
||||
#define D_CONFIGURE_TEMPLATE "Configure Template"
|
||||
#define D_TEMPLATE_PARAMETERS "Template parameters"
|
||||
#define D_TEMPLATE_NAME "Name"
|
||||
#define D_BASE_TYPE "Based on"
|
||||
#define D_TEMPLATE_FLAGS "Options"
|
||||
#define D_ALLOW_ADC0 "ADC0 input"
|
||||
#define D_ALLOW_PULLUP "User pull-up selection"
|
||||
|
||||
#define D_SAVE_CONFIGURATION "Зберегти конфігурацію"
|
||||
#define D_CONFIGURATION_SAVED "Конфігурація збережена "
|
||||
#define D_CONFIGURATION_RESET "Конфігурація скинута"
|
||||
|
@ -483,6 +493,7 @@
|
|||
|
||||
// sonoff_template.h - keep them as short as possible to be able to fit them in GUI drop down box
|
||||
#define D_SENSOR_NONE "-відсутньо-"
|
||||
#define D_SENSOR_USER "User"
|
||||
#define D_SENSOR_DHT11 "DHT11"
|
||||
#define D_SENSOR_AM2301 "AM2301"
|
||||
#define D_SENSOR_SI7021 "SI7021"
|
||||
|
|
|
@ -288,6 +288,8 @@
|
|||
#define D_TELEMETRY_PERIOD "上报周期"
|
||||
|
||||
#define D_OTHER_PARAMETERS "其他设置"
|
||||
#define D_TEMPLATE "Template"
|
||||
#define D_ACTIVATE "Activate"
|
||||
#define D_WEB_ADMIN_PASSWORD "WEB 管理密码"
|
||||
#define D_MQTT_ENABLE "启用MQTT"
|
||||
#define D_FRIENDLY_NAME "昵称"
|
||||
|
@ -296,6 +298,14 @@
|
|||
#define D_SINGLE_DEVICE "单设备"
|
||||
#define D_MULTI_DEVICE "多设备"
|
||||
|
||||
#define D_CONFIGURE_TEMPLATE "Configure Template"
|
||||
#define D_TEMPLATE_PARAMETERS "Template parameters"
|
||||
#define D_TEMPLATE_NAME "Name"
|
||||
#define D_BASE_TYPE "Based on"
|
||||
#define D_TEMPLATE_FLAGS "Options"
|
||||
#define D_ALLOW_ADC0 "ADC0 input"
|
||||
#define D_ALLOW_PULLUP "User pull-up selection"
|
||||
|
||||
#define D_SAVE_CONFIGURATION "保存设置"
|
||||
#define D_CONFIGURATION_SAVED "设置已保存"
|
||||
#define D_CONFIGURATION_RESET "设置已重置"
|
||||
|
@ -483,6 +493,7 @@
|
|||
|
||||
// sonoff_template.h - keep them as short as possible to be able to fit them in GUI drop down box
|
||||
#define D_SENSOR_NONE "无"
|
||||
#define D_SENSOR_USER "User"
|
||||
#define D_SENSOR_DHT11 "DHT11"
|
||||
#define D_SENSOR_AM2301 "AM2301"
|
||||
#define D_SENSOR_SI7021 "SI7021"
|
||||
|
|
|
@ -288,6 +288,8 @@
|
|||
#define D_TELEMETRY_PERIOD "上報周期"
|
||||
|
||||
#define D_OTHER_PARAMETERS "其他設置"
|
||||
#define D_TEMPLATE "Template"
|
||||
#define D_ACTIVATE "Activate"
|
||||
#define D_WEB_ADMIN_PASSWORD "WEB管理密碼"
|
||||
#define D_MQTT_ENABLE "啟用MQTT"
|
||||
#define D_FRIENDLY_NAME "昵稱"
|
||||
|
@ -296,6 +298,14 @@
|
|||
#define D_SINGLE_DEVICE "單設備"
|
||||
#define D_MULTI_DEVICE "多設備"
|
||||
|
||||
#define D_CONFIGURE_TEMPLATE "Configure Template"
|
||||
#define D_TEMPLATE_PARAMETERS "Template parameters"
|
||||
#define D_TEMPLATE_NAME "Name"
|
||||
#define D_BASE_TYPE "Based on"
|
||||
#define D_TEMPLATE_FLAGS "Options"
|
||||
#define D_ALLOW_ADC0 "ADC0 input"
|
||||
#define D_ALLOW_PULLUP "User pull-up selection"
|
||||
|
||||
#define D_SAVE_CONFIGURATION "保存設置"
|
||||
#define D_CONFIGURATION_SAVED "設置已保存"
|
||||
#define D_CONFIGURATION_RESET "設置已重置"
|
||||
|
@ -483,6 +493,7 @@
|
|||
|
||||
// sonoff_template.h - keep them as short as possible to be able to fit them in GUI drop down box
|
||||
#define D_SENSOR_NONE "None"
|
||||
#define D_SENSOR_USER "User"
|
||||
#define D_SENSOR_DHT11 "DHT11"
|
||||
#define D_SENSOR_AM2301 "AM2301"
|
||||
#define D_SENSOR_SI7021 "SI7021"
|
||||
|
|
|
@ -122,6 +122,7 @@
|
|||
|
||||
// -- MQTT - Telemetry ----------------------------
|
||||
#define TELE_PERIOD 300 // [TelePeriod] Telemetry (0 = disable, 10 - 3600 seconds)
|
||||
#define TELE_ON_POWER 0 // [SetOption59] send tele/STATE together with stat/RESULT (0 = Disable, 1 = Enable)
|
||||
|
||||
// -- MQTT - Domoticz -----------------------------
|
||||
#define DOMOTICZ_UPDATE_TIMER 0 // [DomoticzUpdateTimer] Send relay status (0 = disable, 1 - 3600 seconds)
|
||||
|
@ -278,6 +279,7 @@
|
|||
|
||||
// -- Rules ---------------------------------------
|
||||
#define USE_RULES // Add support for rules (+4k4 code)
|
||||
#define USE_EXPRESSION // Add support for expression evaluation in rules (+3k2 code, +64 bytes mem)
|
||||
|
||||
// -- Internal Analog input -----------------------
|
||||
#define USE_ADC_VCC // Display Vcc in Power status. Disable for use as Analog input on selected devices
|
||||
|
|
|
@ -75,7 +75,7 @@ typedef union { // Restricted by MISRA-C Rule 18.4 bu
|
|||
uint32_t hass_tele_on_power : 1; // bit 9 (v6.3.0.13)
|
||||
uint32_t sleep_normal : 1; // bit 10 (v6.3.0.15) - SetOption60 - Enable normal sleep instead of dynamic sleep
|
||||
uint32_t button_switch_force_local : 1;// bit 11 (v6.3.0.16) - SetOption61 - Force local operation when button/switch topic is set
|
||||
uint32_t no_pullup : 1; // bit 12 (v6.4.1.7) - SetOption62 - Force no pull-up (0 = (no)pull-up, 1 = no pull-up)
|
||||
uint32_t no_hold_retain : 1; // bit 12 (v6.4.1.19) - SetOption62 - Don't use retain flag on HOLD messages
|
||||
uint32_t spare13 : 1;
|
||||
uint32_t spare14 : 1;
|
||||
uint32_t spare15 : 1;
|
||||
|
|
|
@ -661,6 +661,7 @@ void SettingsDefaultSet2(void)
|
|||
Settings.flag.mqtt_button_retain = MQTT_BUTTON_RETAIN;
|
||||
Settings.flag.mqtt_switch_retain = MQTT_SWITCH_RETAIN;
|
||||
Settings.flag3.button_switch_force_local = MQTT_BUTTON_SWITCH_FORCE_LOCAL;
|
||||
Settings.flag3.hass_tele_on_power = TELE_ON_POWER;
|
||||
// Settings.flag.mqtt_sensor_retain = 0;
|
||||
// Settings.flag.mqtt_offline = 0;
|
||||
// Settings.flag.mqtt_serial = 0;
|
||||
|
|
|
@ -104,6 +104,7 @@ typedef unsigned long power_t; // Power (Relay) type
|
|||
#define PWM_MIN 100 // [PWM_MIN] Minimum frequency - Default: 100
|
||||
// For Dimmers use double of your mains AC frequecy (100 for 50Hz and 120 for 60Hz)
|
||||
// For Controlling Servos use 50 and also set PWM_FREQ as 50 (DO NOT USE THESE VALUES FOR DIMMERS)
|
||||
//#define PWM_LIGHTSCHEME0_IGNORE_SLEEP // Do not change sleep value for LightAnimate() scheme 0
|
||||
|
||||
#define DEFAULT_POWER_DELTA 80 // Power change percentage
|
||||
#define MAX_POWER_HOLD 10 // Time in SECONDS to allow max agreed power
|
||||
|
@ -211,7 +212,7 @@ enum GetDateAndTimeOptions { DT_LOCAL, DT_UTC, DT_RESTART, DT_ENERGY };
|
|||
|
||||
enum LoggingLevels {LOG_LEVEL_NONE, LOG_LEVEL_ERROR, LOG_LEVEL_INFO, LOG_LEVEL_DEBUG, LOG_LEVEL_DEBUG_MORE, LOG_LEVEL_ALL};
|
||||
|
||||
enum WifiConfigOptions {WIFI_RESTART, WIFI_SMARTCONFIG, WIFI_MANAGER, WIFI_WPSCONFIG, WIFI_RETRY, WIFI_WAIT, WIFI_SERIAL, MAX_WIFI_OPTION};
|
||||
enum WifiConfigOptions {WIFI_RESTART, WIFI_SMARTCONFIG, WIFI_MANAGER, WIFI_WPSCONFIG, WIFI_RETRY, WIFI_WAIT, WIFI_SERIAL, WIFI_MANAGER_RESET_ONLY, MAX_WIFI_OPTION};
|
||||
|
||||
enum SwitchModeOptions {TOGGLE, FOLLOW, FOLLOW_INV, PUSHBUTTON, PUSHBUTTON_INV, PUSHBUTTONHOLD, PUSHBUTTONHOLD_INV, PUSHBUTTON_TOGGLE, MAX_SWITCH_OPTION};
|
||||
|
||||
|
|
|
@ -776,9 +776,6 @@ void MqttDataHandler(char* topic, uint8_t* data, unsigned int data_len)
|
|||
if (10 == pindex) { // SetOption60 enable or disable traditional sleep
|
||||
WiFiSetSleepMode(); // Update WiFi sleep mode accordingly
|
||||
}
|
||||
if ((12 == pindex) && (my_module_flag.pullup)) { // SetOption62 change input pull-up
|
||||
restart_flag = 2; // Only restart if module supports it
|
||||
}
|
||||
}
|
||||
}
|
||||
else { // SetOption32 .. 49
|
||||
|
@ -869,9 +866,7 @@ void MqttDataHandler(char* topic, uint8_t* data, unsigned int data_len)
|
|||
}
|
||||
restart_flag = 2;
|
||||
}
|
||||
uint8_t module = Settings.module;
|
||||
if (USER_MODULE == Settings.module) { module = 0; } else { module++; }
|
||||
snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_NVALUE_SVALUE, command, module, ModuleName().c_str());
|
||||
snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_NVALUE_SVALUE, command, ModuleNr(), ModuleName().c_str());
|
||||
}
|
||||
else if (CMND_MODULES == command_code) {
|
||||
for (uint8_t i = 0; i <= MAXMODULE; i++) {
|
||||
|
@ -952,85 +947,29 @@ void MqttDataHandler(char* topic, uint8_t* data, unsigned int data_len)
|
|||
mqtt_data[0] = '\0';
|
||||
}
|
||||
else if (CMND_TEMPLATE == command_code) {
|
||||
// {"NAME":"Generic","GPIO":[17,254,29,254,7,254,254,254,138,254,139,254,254],"FLAG":1,"TYPE":255}
|
||||
// {"NAME":"Generic","GPIO":[17,254,29,254,7,254,254,254,138,254,139,254,254],"FLAG":1,"BASE":255}
|
||||
bool error = false;
|
||||
|
||||
if (!strstr(dataBuf, "{")) { // If no JSON it must be parameter
|
||||
bool update = false;
|
||||
if ((payload > 0) && (payload <= MAXMODULE)) {
|
||||
ModuleDefault(payload -1); // Copy template module
|
||||
if (USER_MODULE == Settings.module) { restart_flag = 2; }
|
||||
}
|
||||
else if (0 == payload) { // Copy current module with user configured GPIO
|
||||
if (Settings.module < USER_MODULE) {
|
||||
if (Settings.module != USER_MODULE) {
|
||||
ModuleDefault(Settings.module);
|
||||
update = true;
|
||||
}
|
||||
}
|
||||
if (USER_MODULE == Settings.module) { // Update with latest changes
|
||||
update = true;
|
||||
}
|
||||
if (update) {
|
||||
uint8_t src = 0;
|
||||
for (uint8_t dst = 0; dst < sizeof(mycfgio); dst++) {
|
||||
if (6 == dst) { src = 9; }
|
||||
if (8 == dst) { src = 12; }
|
||||
if (Settings.my_gp.io[src] > GPIO_NONE) {
|
||||
if (Settings.user_template.gp.io[dst] != Settings.my_gp.io[src]) {
|
||||
Settings.user_template.gp.io[dst] = Settings.my_gp.io[src];
|
||||
if (USER_MODULE == Settings.module) { restart_flag = 2; }
|
||||
}
|
||||
}
|
||||
src++;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (data_len > 9) { // Workaround exception if empty JSON like {} - Needs checks
|
||||
StaticJsonBuffer<350> jb; // 331 from https://arduinojson.org/v5/assistant/
|
||||
JsonObject& obj = jb.parseObject(dataBuf);
|
||||
if (!obj.success()) {
|
||||
else if (data_len > 9) { // Workaround exception if empty JSON like {} - Needs checks
|
||||
if (JsonTemplate(dataBuf)) { // Free 336 bytes StaticJsonBuffer stack space by moving code to function
|
||||
if (USER_MODULE == Settings.module) { restart_flag = 2; }
|
||||
} else {
|
||||
snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_SVALUE, command, D_JSON_INVALID_JSON);
|
||||
error = true;
|
||||
} else {
|
||||
// All parameters are optional allowing for partial changes
|
||||
const char* name = obj[D_JSON_NAME];
|
||||
if (name != nullptr) {
|
||||
strlcpy(Settings.user_template.name, name, sizeof(Settings.user_template.name));
|
||||
}
|
||||
if (obj[D_JSON_GPIO].success()) {
|
||||
for (uint8_t i = 0; i < sizeof(mycfgio); i++) {
|
||||
Settings.user_template.gp.io[i] = obj[D_JSON_GPIO][i] | 0;
|
||||
}
|
||||
}
|
||||
if (obj[D_JSON_FLAG].success()) {
|
||||
uint8_t flag = obj[D_JSON_FLAG] | 0;
|
||||
memcpy(&Settings.user_template.flag, &flag, sizeof(gpio_flag));
|
||||
}
|
||||
if (obj[D_JSON_BASE].success()) {
|
||||
uint8_t base = obj[D_JSON_BASE];
|
||||
if ((0 == base) || (base >= MAXMODULE)) { base = 17; } else { base--; }
|
||||
Settings.user_template_base = base; // Default WEMOS
|
||||
}
|
||||
|
||||
// Validate GPIO
|
||||
// for (uint8_t i = 0; i < sizeof(mycfgio); i++) {
|
||||
// For now do not allow non-user configurable GPIO
|
||||
// if ((Settings.user_template.gp.io[i] > GPIO_FIX_START) && (Settings.user_template.gp.io[i] < GPIO_USER)) {
|
||||
// Settings.user_template.gp.io[i] = GPIO_NONE;
|
||||
// };
|
||||
// }
|
||||
if (USER_MODULE == Settings.module) { restart_flag = 2; }
|
||||
}
|
||||
}
|
||||
if (!error) {
|
||||
snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_JSON_NAME "\":\"%s\",\"" D_JSON_GPIO "\":["), Settings.user_template.name);
|
||||
for (uint8_t i = 0; i < sizeof(Settings.user_template.gp); i++) {
|
||||
snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s%s%d"), mqtt_data, (i>0)?",":"", Settings.user_template.gp.io[i]);
|
||||
}
|
||||
// snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s],\"" D_JSON_FLAG "\":%d,\"" D_JSON_BASE "\":\"%d (%s)\"}"),
|
||||
// mqtt_data, Settings.user_template.flag, Settings.user_template_base +1, AnyModuleName(Settings.user_template_base).c_str());
|
||||
snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s],\"" D_JSON_FLAG "\":%d,\"" D_JSON_BASE "\":%d}"),
|
||||
mqtt_data, Settings.user_template.flag, Settings.user_template_base +1);
|
||||
}
|
||||
if (!error) { TemplateJson(); }
|
||||
}
|
||||
else if ((CMND_PWM == command_code) && pwm_present && (index > 0) && (index <= MAX_PWMS)) {
|
||||
if ((payload >= 0) && (payload <= Settings.pwm_range) && (pin[GPIO_PWM1 + index -1] < 99)) {
|
||||
|
@ -1203,7 +1142,7 @@ void MqttDataHandler(char* topic, uint8_t* data, unsigned int data_len)
|
|||
snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_INDEX_SVALUE, command, index, Settings.sta_ssid[index -1]);
|
||||
}
|
||||
else if ((CMND_PASSWORD == command_code) && (index > 0) && (index <= 2)) {
|
||||
if ((data_len > 0) && (data_len < sizeof(Settings.sta_pwd[0]))) {
|
||||
if ((data_len > 4 || SC_CLEAR == Shortcut(dataBuf) || SC_DEFAULT == Shortcut(dataBuf)) && (data_len < sizeof(Settings.sta_pwd[0]))) {
|
||||
strlcpy(Settings.sta_pwd[index -1], (SC_CLEAR == Shortcut(dataBuf)) ? "" : (SC_DEFAULT == Shortcut(dataBuf)) ? (1 == index) ? STA_PASS1 : STA_PASS2 : dataBuf, sizeof(Settings.sta_pwd[0]));
|
||||
Settings.sta_active = index -1;
|
||||
restart_flag = 2;
|
||||
|
@ -1336,10 +1275,7 @@ void MqttDataHandler(char* topic, uint8_t* data, unsigned int data_len)
|
|||
restart_flag = 211;
|
||||
snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_SVALUE, command , D_JSON_RESET_AND_RESTARTING);
|
||||
break;
|
||||
case 2:
|
||||
case 3:
|
||||
case 4:
|
||||
case 5:
|
||||
case 2 ... 6:
|
||||
restart_flag = 210 + payload;
|
||||
snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_CMND_RESET "\":\"" D_JSON_ERASE ", " D_JSON_RESET_AND_RESTARTING "\"}"));
|
||||
break;
|
||||
|
@ -1496,10 +1432,10 @@ bool SendKey(uint8_t key, uint8_t device, uint8_t state)
|
|||
}
|
||||
#ifdef USE_DOMOTICZ
|
||||
if (!(DomoticzSendKey(key, device, state, strlen(mqtt_data)))) {
|
||||
MqttPublishDirect(stopic, (key) ? Settings.flag.mqtt_switch_retain : Settings.flag.mqtt_button_retain);
|
||||
MqttPublishDirect(stopic, ((key) ? Settings.flag.mqtt_switch_retain : Settings.flag.mqtt_button_retain) && (state != 3 || !Settings.flag3.no_hold_retain));
|
||||
}
|
||||
#else
|
||||
MqttPublishDirect(stopic, (key) ? Settings.flag.mqtt_switch_retain : Settings.flag.mqtt_button_retain);
|
||||
MqttPublishDirect(stopic, ((key) ? Settings.flag.mqtt_switch_retain : Settings.flag.mqtt_button_retain) && (state != 3 || !Settings.flag3.no_hold_retain));
|
||||
#endif // USE_DOMOTICZ
|
||||
result = !Settings.flag3.button_switch_force_local;
|
||||
} else {
|
||||
|
@ -1628,8 +1564,6 @@ void StopAllPowerBlink(void)
|
|||
|
||||
void ExecuteCommand(char *cmnd, int source)
|
||||
{
|
||||
char stopic[CMDSZ];
|
||||
char svalue[INPUT_BUFFER_SIZE];
|
||||
char *start;
|
||||
char *token;
|
||||
|
||||
|
@ -1641,9 +1575,13 @@ void ExecuteCommand(char *cmnd, int source)
|
|||
start = strrchr(token, '/'); // Skip possible cmnd/sonoff/ preamble
|
||||
if (start) { token = start +1; }
|
||||
}
|
||||
uint16_t size = (token != NULL) ? strlen(token) : 0;
|
||||
char stopic[size +2]; // / + \0
|
||||
snprintf_P(stopic, sizeof(stopic), PSTR("/%s"), (token == NULL) ? "" : token);
|
||||
|
||||
token = strtok(NULL, "");
|
||||
// snprintf_P(svalue, sizeof(svalue), (token == NULL) ? "" : token); // Fails with command FullTopic home/%prefix%/%topic% as it processes %p of %prefix%
|
||||
size = (token != NULL) ? strlen(token) : 0;
|
||||
char svalue[size +1];
|
||||
strlcpy(svalue, (token == NULL) ? "" : token, sizeof(svalue)); // Fixed 5.8.0b
|
||||
MqttDataHandler(stopic, (uint8_t*)svalue, strlen(svalue));
|
||||
}
|
||||
|
@ -1672,13 +1610,13 @@ void PublishStatus(uint8_t payload)
|
|||
snprintf_P(stemp2, sizeof(stemp2), PSTR("%s%s%d" ), stemp2, (i > 0 ? "," : ""), Settings.switchmode[i]);
|
||||
}
|
||||
snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_CMND_STATUS "\":{\"" D_CMND_MODULE "\":%d,\"" D_CMND_FRIENDLYNAME "\":[%s],\"" D_CMND_TOPIC "\":\"%s\",\"" D_CMND_BUTTONTOPIC "\":\"%s\",\"" D_CMND_POWER "\":%d,\"" D_CMND_POWERONSTATE "\":%d,\"" D_CMND_LEDSTATE "\":%d,\"" D_CMND_SAVEDATA "\":%d,\"" D_JSON_SAVESTATE "\":%d,\"" D_CMND_SWITCHTOPIC "\":\"%s\",\"" D_CMND_SWITCHMODE "\":[%s],\"" D_CMND_BUTTONRETAIN "\":%d,\"" D_CMND_SWITCHRETAIN "\":%d,\"" D_CMND_SENSORRETAIN "\":%d,\"" D_CMND_POWERRETAIN "\":%d}}"),
|
||||
(USER_MODULE == Settings.module)?0:Settings.module +1, stemp, mqtt_topic, Settings.button_topic, power, Settings.poweronstate, Settings.ledstate, Settings.save_data, Settings.flag.save_state, Settings.switch_topic, stemp2, Settings.flag.mqtt_button_retain, Settings.flag.mqtt_switch_retain, Settings.flag.mqtt_sensor_retain, Settings.flag.mqtt_power_retain);
|
||||
ModuleNr(), stemp, mqtt_topic, Settings.button_topic, power, Settings.poweronstate, Settings.ledstate, Settings.save_data, Settings.flag.save_state, Settings.switch_topic, stemp2, Settings.flag.mqtt_button_retain, Settings.flag.mqtt_switch_retain, Settings.flag.mqtt_sensor_retain, Settings.flag.mqtt_power_retain);
|
||||
MqttPublishPrefixTopic_P(option, PSTR(D_CMND_STATUS));
|
||||
}
|
||||
|
||||
if ((0 == payload) || (1 == payload)) {
|
||||
snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_CMND_STATUS D_STATUS1_PARAMETER "\":{\"" D_JSON_BAUDRATE "\":%d,\"" D_CMND_GROUPTOPIC "\":\"%s\",\"" D_CMND_OTAURL "\":\"%s\",\"" D_JSON_RESTARTREASON "\":\"%s\",\"" D_JSON_UPTIME "\":\"%s\",\"" D_JSON_STARTUPUTC "\":\"%s\",\"" D_CMND_SLEEP "\":%d,\"" D_JSON_BOOTCOUNT "\":%d,\"" D_JSON_SAVECOUNT "\":%d,\"" D_JSON_SAVEADDRESS "\":\"%X\"}}"),
|
||||
baudrate, Settings.mqtt_grptopic, Settings.ota_url, GetResetReason().c_str(), GetUptime().c_str(), GetDateAndTime(DT_RESTART).c_str(), Settings.sleep, Settings.bootcount, Settings.save_flag, GetSettingsAddress());
|
||||
snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_CMND_STATUS D_STATUS1_PARAMETER "\":{\"" D_JSON_BAUDRATE "\":%d,\"" D_CMND_GROUPTOPIC "\":\"%s\",\"" D_CMND_OTAURL "\":\"%s\",\"" D_JSON_RESTARTREASON "\":\"%s\",\"" D_JSON_UPTIME "\":\"%s\",\"" D_JSON_STARTUPUTC "\":\"%s\",\"" D_CMND_SLEEP "\":%d,\"" D_JSON_CONFIG_HOLDER "\":%d,\"" D_JSON_BOOTCOUNT "\":%d,\"" D_JSON_SAVECOUNT "\":%d,\"" D_JSON_SAVEADDRESS "\":\"%X\"}}"),
|
||||
baudrate, Settings.mqtt_grptopic, Settings.ota_url, GetResetReason().c_str(), GetUptime().c_str(), GetDateAndTime(DT_RESTART).c_str(), Settings.sleep, Settings.cfg_holder, Settings.bootcount, Settings.save_flag, GetSettingsAddress());
|
||||
MqttPublishPrefixTopic_P(option, PSTR(D_CMND_STATUS "1"));
|
||||
}
|
||||
|
||||
|
@ -1712,8 +1650,8 @@ void PublishStatus(uint8_t payload)
|
|||
}
|
||||
|
||||
if (((0 == payload) || (6 == payload)) && Settings.flag.mqtt_enabled) {
|
||||
snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_CMND_STATUS D_STATUS6_MQTT "\":{\"" D_CMND_MQTTHOST "\":\"%s\",\"" D_CMND_MQTTPORT "\":%d,\"" D_CMND_MQTTCLIENT D_JSON_MASK "\":\"%s\",\"" D_CMND_MQTTCLIENT "\":\"%s\",\"" D_CMND_MQTTUSER "\":\"%s\",\"MqttType\":%d,\"MAX_PACKET_SIZE\":%d,\"KEEPALIVE\":%d}}"),
|
||||
Settings.mqtt_host, Settings.mqtt_port, Settings.mqtt_client, mqtt_client, Settings.mqtt_user, MqttLibraryType(), MQTT_MAX_PACKET_SIZE, MQTT_KEEPALIVE);
|
||||
snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_CMND_STATUS D_STATUS6_MQTT "\":{\"" D_CMND_MQTTHOST "\":\"%s\",\"" D_CMND_MQTTPORT "\":%d,\"" D_CMND_MQTTCLIENT D_JSON_MASK "\":\"%s\",\"" D_CMND_MQTTCLIENT "\":\"%s\",\"" D_CMND_MQTTUSER "\":\"%s\",\"MqttType\":%d,\"" D_JSON_MQTT_COUNT "\":%d,\"MAX_PACKET_SIZE\":%d,\"KEEPALIVE\":%d}}"),
|
||||
Settings.mqtt_host, Settings.mqtt_port, Settings.mqtt_client, mqtt_client, Settings.mqtt_user, MqttLibraryType(), MqttConnectCount(), MQTT_MAX_PACKET_SIZE, MQTT_KEEPALIVE);
|
||||
MqttPublishPrefixTopic_P(option, PSTR(D_CMND_STATUS "6"));
|
||||
}
|
||||
|
||||
|
@ -1805,8 +1743,8 @@ void MqttShowState(void)
|
|||
MqttShowPWMState();
|
||||
}
|
||||
|
||||
snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"" D_JSON_WIFI "\":{\"" D_JSON_AP "\":%d,\"" D_JSON_SSID "\":\"%s\",\"" D_JSON_BSSID "\":\"%s\",\"" D_JSON_CHANNEL "\":%d,\"" D_JSON_RSSI "\":%d}}"),
|
||||
mqtt_data, Settings.sta_active +1, Settings.sta_ssid[Settings.sta_active], WiFi.BSSIDstr().c_str(), WiFi.channel(), WifiGetRssiAsQuality(WiFi.RSSI()));
|
||||
snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"" D_JSON_WIFI "\":{\"" D_JSON_AP "\":%d,\"" D_JSON_SSID "\":\"%s\",\"" D_JSON_BSSID "\":\"%s\",\"" D_JSON_CHANNEL "\":%d,\"" D_JSON_RSSI "\":%d,\"" D_JSON_LINK_COUNT "\":%d,\"" D_JSON_DOWNTIME "\":\"%s\"}}"),
|
||||
mqtt_data, Settings.sta_active +1, Settings.sta_ssid[Settings.sta_active], WiFi.BSSIDstr().c_str(), WiFi.channel(), WifiGetRssiAsQuality(WiFi.RSSI()), WifiLinkCount(), WifiDowntime().c_str());
|
||||
}
|
||||
|
||||
bool MqttShowSensor(void)
|
||||
|
@ -2114,14 +2052,33 @@ void Every250mSeconds(void)
|
|||
}
|
||||
}
|
||||
if (restart_flag && (backlog_pointer == backlog_index)) {
|
||||
if ((214 == restart_flag) || (215 == restart_flag)) {
|
||||
if ((214 == restart_flag) || (215 == restart_flag) || (216 == restart_flag)) {
|
||||
char storage[sizeof(Settings.sta_ssid) + sizeof(Settings.sta_pwd)];
|
||||
char storage_mqtt_host[sizeof(Settings.mqtt_host)];
|
||||
uint16_t storage_mqtt_port;
|
||||
char storage_mqtt_user[sizeof(Settings.mqtt_user)];
|
||||
char storage_mqtt_pwd[sizeof(Settings.mqtt_pwd)];
|
||||
char storage_mqtt_topic[sizeof(Settings.mqtt_topic)];
|
||||
memcpy(storage, Settings.sta_ssid, sizeof(storage)); // Backup current SSIDs and Passwords
|
||||
if (215 == restart_flag) {
|
||||
if (216 == restart_flag) {
|
||||
memcpy(storage_mqtt_host, Settings.mqtt_host, sizeof(Settings.mqtt_host));
|
||||
storage_mqtt_port = Settings.mqtt_port;
|
||||
memcpy(storage_mqtt_user, Settings.mqtt_user, sizeof(Settings.mqtt_user));
|
||||
memcpy(storage_mqtt_pwd, Settings.mqtt_pwd, sizeof(Settings.mqtt_pwd));
|
||||
memcpy(storage_mqtt_topic, Settings.mqtt_topic, sizeof(Settings.mqtt_topic));
|
||||
}
|
||||
if ((215 == restart_flag) || (216 == restart_flag)) {
|
||||
SettingsErase(0); // Erase all flash from program end to end of physical flash
|
||||
}
|
||||
SettingsDefault();
|
||||
memcpy(Settings.sta_ssid, storage, sizeof(storage)); // Restore current SSIDs and Passwords
|
||||
if (216 == restart_flag) { // Restore the mqtt host, port, username and password
|
||||
memcpy(Settings.mqtt_host, storage_mqtt_host, sizeof(Settings.mqtt_host));
|
||||
Settings.mqtt_port = storage_mqtt_port;
|
||||
memcpy(Settings.mqtt_user, storage_mqtt_user, sizeof(Settings.mqtt_user));
|
||||
memcpy(Settings.mqtt_pwd, storage_mqtt_pwd, sizeof(Settings.mqtt_pwd));
|
||||
memcpy(Settings.mqtt_topic, storage_mqtt_topic, sizeof(Settings.mqtt_topic));
|
||||
}
|
||||
restart_flag = 2;
|
||||
}
|
||||
else if (213 == restart_flag) {
|
||||
|
@ -2237,7 +2194,8 @@ void ArduinoOTAInit(void)
|
|||
void SerialInput(void)
|
||||
{
|
||||
while (Serial.available()) {
|
||||
yield();
|
||||
// yield();
|
||||
delay(0);
|
||||
serial_in_byte = Serial.read();
|
||||
|
||||
/*-------------------------------------------------------------------------------------------*\
|
||||
|
@ -2346,17 +2304,23 @@ void GpioInit(void)
|
|||
baudrate = APP_BAUDRATE;
|
||||
}
|
||||
|
||||
for (uint8_t i = 0; i < sizeof(Settings.user_template.gp); i++) {
|
||||
if ((Settings.user_template.gp.io[i] >= GPIO_SENSOR_END) && (Settings.user_template.gp.io[i] < GPIO_USER)) {
|
||||
Settings.user_template.gp.io[i] = GPIO_USER; // Fix not supported sensor ids in template
|
||||
}
|
||||
}
|
||||
|
||||
myio def_gp;
|
||||
ModuleGpios(&def_gp);
|
||||
for (uint8_t i = 0; i < sizeof(Settings.my_gp); i++) {
|
||||
if (Settings.my_gp.io[i] > GPIO_NONE) {
|
||||
if ((Settings.my_gp.io[i] >= GPIO_SENSOR_END) && (Settings.my_gp.io[i] < GPIO_USER)) {
|
||||
Settings.my_gp.io[i] = GPIO_NONE; // Fix not supported sensor ids in module
|
||||
}
|
||||
else if (Settings.my_gp.io[i] > GPIO_NONE) {
|
||||
my_module.io[i] = Settings.my_gp.io[i];
|
||||
}
|
||||
if ((def_gp.io[i] > GPIO_NONE) && (def_gp.io[i] < GPIO_USER)) {
|
||||
my_module.io[i] = def_gp.io[i];
|
||||
if (USER_MODULE == Settings.module) {
|
||||
Settings.my_gp.io[i] = def_gp.io[i]; // Copy user template settings
|
||||
}
|
||||
}
|
||||
}
|
||||
my_module_flag = ModuleFlag();
|
||||
|
|
|
@ -335,8 +335,10 @@ typedef struct MYCFGIO {
|
|||
uint8_t io[MAX_GPIO_PIN - MIN_FLASH_PINS];
|
||||
} mycfgio;
|
||||
|
||||
#define GPIO_FLAG_USED 1 // Currently only one flag used
|
||||
|
||||
#define GPIO_FLAG_ADC0 1 // Allow ADC0 when define USE_ADC_VCC is disabled
|
||||
#define GPIO_FLAG_PULLUP 2 // Allow input pull-up control using SetOption62
|
||||
#define GPIO_FLAG_SPARE01 2 // Allow input pull-up control using SetOption62 - Superseded by user template editing
|
||||
#define GPIO_FLAG_SPARE02 4
|
||||
#define GPIO_FLAG_SPARE03 8
|
||||
#define GPIO_FLAG_SPARE04 16
|
||||
|
@ -348,7 +350,7 @@ typedef union {
|
|||
uint8_t data;
|
||||
struct {
|
||||
uint8_t adc0 : 1; // Allow ADC0 when define USE_ADC_VCC is disabled
|
||||
uint8_t pullup : 1; // Allow input pull-up control using SetOption62
|
||||
uint8_t spare01 : 1;
|
||||
uint8_t spare02 : 1;
|
||||
uint8_t spare03 : 1;
|
||||
uint8_t spare04 : 1;
|
||||
|
@ -974,7 +976,6 @@ const mytmplt kModules[MAXMODULE] PROGMEM = {
|
|||
GPIO_USER, // GPIO15 D8
|
||||
GPIO_USER, // GPIO16 D0 Wemos Wake
|
||||
GPIO_FLAG_ADC0 // ADC0 A0 Analog input
|
||||
// + GPIO_FLAG_PULLUP // Allow input pull-up control
|
||||
},
|
||||
{ "Sonoff Dev", // Sonoff Dev (ESP8266)
|
||||
GPIO_KEY1, // GPIO00 E-FW Button
|
||||
|
@ -1503,7 +1504,7 @@ const mytmplt kModules[MAXMODULE] PROGMEM = {
|
|||
GPIO_SWT2, // GPIO14
|
||||
GPIO_MCP39F5_RST, // GPIO15 MCP39F501 Reset
|
||||
0,
|
||||
GPIO_FLAG_PULLUP // Allow input pull-up control
|
||||
0
|
||||
},
|
||||
{ "Xiaomi Philips", // Xiaomi Philips bulb (ESP8266)
|
||||
0, 0, 0, 0, 0, 0,
|
||||
|
|
|
@ -20,7 +20,7 @@
|
|||
#ifndef _SONOFF_VERSION_H_
|
||||
#define _SONOFF_VERSION_H_
|
||||
|
||||
#define VERSION 0x06040110
|
||||
#define VERSION 0x06040112
|
||||
|
||||
#define D_PROGRAMNAME "Sonoff-Tasmota"
|
||||
#define D_AUTHOR "Theo Arends"
|
||||
|
|
|
@ -154,7 +154,7 @@ char* subStr(char* dest, char* str, const char *delim, int index)
|
|||
return sub;
|
||||
}
|
||||
|
||||
double CharToDouble(char *str)
|
||||
double CharToDouble(const char *str)
|
||||
{
|
||||
// simple ascii to double, because atof or strtod are too large
|
||||
char strbuf[24];
|
||||
|
@ -305,27 +305,6 @@ char* UpperCase_P(char* dest, const char* source)
|
|||
return dest;
|
||||
}
|
||||
|
||||
/*
|
||||
char* LTrim(char* p)
|
||||
{
|
||||
while ((*p != '\0') && (isblank(*p))) {
|
||||
p++; // Trim leading spaces
|
||||
}
|
||||
return p;
|
||||
}
|
||||
|
||||
char* RTrim(char* p)
|
||||
{
|
||||
char* q = p + strlen(p) -1;
|
||||
while ((q >= p) && (isblank(*q))) {
|
||||
q--; // Trim trailing spaces
|
||||
}
|
||||
q++;
|
||||
*q = '\0';
|
||||
return p;
|
||||
}
|
||||
*/
|
||||
|
||||
char* Trim(char* p)
|
||||
{
|
||||
while ((*p != '\0') && isblank(*p)) { p++; } // Trim leading spaces
|
||||
|
@ -505,162 +484,6 @@ String PressureUnit(void)
|
|||
return (Settings.flag.pressure_conversion) ? String(D_UNIT_MILLIMETER_MERCURY) : String(D_UNIT_PRESSURE);
|
||||
}
|
||||
|
||||
String AnyModuleName(uint8_t index)
|
||||
{
|
||||
if (USER_MODULE == index) {
|
||||
return String(Settings.user_template.name);
|
||||
} else {
|
||||
return FPSTR(kModules[index].name);
|
||||
}
|
||||
}
|
||||
|
||||
String ModuleName()
|
||||
{
|
||||
return AnyModuleName(Settings.module);
|
||||
}
|
||||
|
||||
void ModuleGpios(myio *gp)
|
||||
{
|
||||
uint8_t *dest = (uint8_t *)gp;
|
||||
memset(dest, GPIO_NONE, sizeof(myio));
|
||||
|
||||
uint8_t src[sizeof(mycfgio)];
|
||||
if (USER_MODULE == Settings.module) {
|
||||
// src = Settings.user_template.gp;
|
||||
memcpy(&src, &Settings.user_template.gp, sizeof(mycfgio));
|
||||
} else {
|
||||
memcpy_P(&src, &kModules[Settings.module].gp, sizeof(mycfgio));
|
||||
}
|
||||
// 11 85 00 85 85 00 00 00 15 38 85 00 00 81
|
||||
|
||||
// AddLogBuffer(LOG_LEVEL_DEBUG, (uint8_t *)&src, sizeof(mycfgio));
|
||||
|
||||
uint8_t j = 0;
|
||||
for (uint8_t i = 0; i < sizeof(mycfgio); i++) {
|
||||
if (6 == i) { j = 9; }
|
||||
if (8 == i) { j = 12; }
|
||||
dest[j] = src[i];
|
||||
j++;
|
||||
}
|
||||
// 11 85 00 85 85 00 00 00 00 00 00 00 15 38 85 00 00 81
|
||||
|
||||
// AddLogBuffer(LOG_LEVEL_DEBUG, (uint8_t *)gp, sizeof(myio));
|
||||
}
|
||||
|
||||
gpio_flag ModuleFlag()
|
||||
{
|
||||
gpio_flag flag;
|
||||
|
||||
if (USER_MODULE == Settings.module) {
|
||||
flag = Settings.user_template.flag;
|
||||
} else {
|
||||
memcpy_P(&flag, &kModules[Settings.module].flag, sizeof(gpio_flag));
|
||||
}
|
||||
|
||||
return flag;
|
||||
}
|
||||
|
||||
void ModuleDefault(uint8_t module)
|
||||
{
|
||||
if (USER_MODULE == module) { module = WEMOS; } // Generic
|
||||
Settings.user_template_base = module;
|
||||
memcpy_P(&Settings.user_template, &kModules[module], sizeof(mytmplt));
|
||||
}
|
||||
|
||||
void SetModuleType()
|
||||
{
|
||||
my_module_type = (USER_MODULE == Settings.module) ? Settings.user_template_base : Settings.module;
|
||||
}
|
||||
|
||||
uint8_t ValidPin(uint8_t pin, uint8_t gpio)
|
||||
{
|
||||
uint8_t result = gpio;
|
||||
if ((pin > 5) && (pin < 12)) {
|
||||
result = GPIO_NONE; // Disable all flash pins
|
||||
}
|
||||
if (Settings.flag3.user_esp8285_enable) {
|
||||
if ((pin == 9) || (pin == 10)) {
|
||||
result = gpio; // Allow optional flash pins
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
bool ValidGPIO(uint8_t pin, uint8_t gpio)
|
||||
{
|
||||
bool result = false;
|
||||
|
||||
if (USER_MODULE == Settings.module) {
|
||||
result = (ValidPin(pin, gpio) > GPIO_NONE); // Allow any pin
|
||||
} else {
|
||||
result = (GPIO_USER == ValidPin(pin, gpio)); // Only allow GPIO_USER pins
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
bool GetUsedInModule(uint8_t val, uint8_t *arr)
|
||||
{
|
||||
int offset = 0;
|
||||
|
||||
if (USER_MODULE == Settings.module) { return false; }
|
||||
|
||||
if (!val) { return false; } // None
|
||||
|
||||
if ((val >= GPIO_KEY1) && (val < GPIO_KEY1 + MAX_KEYS)) {
|
||||
offset = (GPIO_KEY1_NP - GPIO_KEY1);
|
||||
}
|
||||
if ((val >= GPIO_KEY1_NP) && (val < GPIO_KEY1_NP + MAX_KEYS)) {
|
||||
offset = -(GPIO_KEY1_NP - GPIO_KEY1);
|
||||
}
|
||||
if ((val >= GPIO_KEY1_INV) && (val < GPIO_KEY1_INV + MAX_KEYS)) {
|
||||
offset = -(GPIO_KEY1_INV - GPIO_KEY1);
|
||||
}
|
||||
if ((val >= GPIO_KEY1_INV_NP) && (val < GPIO_KEY1_INV_NP + MAX_KEYS)) {
|
||||
offset = -(GPIO_KEY1_INV_NP - GPIO_KEY1);
|
||||
}
|
||||
|
||||
if ((val >= GPIO_SWT1) && (val < GPIO_SWT1 + MAX_SWITCHES)) {
|
||||
offset = (GPIO_SWT1_NP - GPIO_SWT1);
|
||||
}
|
||||
if ((val >= GPIO_SWT1_NP) && (val < GPIO_SWT1_NP + MAX_SWITCHES)) {
|
||||
offset = -(GPIO_SWT1_NP - GPIO_SWT1);
|
||||
}
|
||||
|
||||
if ((val >= GPIO_REL1) && (val < GPIO_REL1 + MAX_RELAYS)) {
|
||||
offset = (GPIO_REL1_INV - GPIO_REL1);
|
||||
}
|
||||
if ((val >= GPIO_REL1_INV) && (val < GPIO_REL1_INV + MAX_RELAYS)) {
|
||||
offset = -(GPIO_REL1_INV - GPIO_REL1);
|
||||
}
|
||||
|
||||
if ((val >= GPIO_LED1) && (val < GPIO_LED1 + MAX_LEDS)) {
|
||||
offset = (GPIO_LED1_INV - GPIO_LED1);
|
||||
}
|
||||
if ((val >= GPIO_LED1_INV) && (val < GPIO_LED1_INV + MAX_LEDS)) {
|
||||
offset = -(GPIO_LED1_INV - GPIO_LED1);
|
||||
}
|
||||
|
||||
if ((val >= GPIO_PWM1) && (val < GPIO_PWM1 + MAX_PWMS)) {
|
||||
offset = (GPIO_PWM1_INV - GPIO_PWM1);
|
||||
}
|
||||
if ((val >= GPIO_PWM1_INV) && (val < GPIO_PWM1_INV + MAX_PWMS)) {
|
||||
offset = -(GPIO_PWM1_INV - GPIO_PWM1);
|
||||
}
|
||||
|
||||
if ((val >= GPIO_CNTR1) && (val < GPIO_CNTR1 + MAX_COUNTERS)) {
|
||||
offset = (GPIO_CNTR1_NP - GPIO_CNTR1);
|
||||
}
|
||||
if ((val >= GPIO_CNTR1_NP) && (val < GPIO_CNTR1_NP + MAX_COUNTERS)) {
|
||||
offset = -(GPIO_CNTR1_NP - GPIO_CNTR1);
|
||||
}
|
||||
|
||||
for (uint8_t i = 0; i < MAX_GPIO_PIN; i++) {
|
||||
if (arr[i] == val) { return true; }
|
||||
if (arr[i] == val + offset) { return true; }
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void SetGlobalValues(float temperature, float humidity)
|
||||
{
|
||||
global_update = uptime;
|
||||
|
@ -872,6 +695,200 @@ void ShowSource(int source)
|
|||
}
|
||||
}
|
||||
|
||||
/*********************************************************************************************\
|
||||
* GPIO Module and Template management
|
||||
\*********************************************************************************************/
|
||||
|
||||
uint8_t ModuleNr()
|
||||
{
|
||||
// 0 = User module (255)
|
||||
// 1 up = Template module 0 up
|
||||
return (USER_MODULE == Settings.module) ? 0 : Settings.module +1;
|
||||
}
|
||||
|
||||
String AnyModuleName(uint8_t index)
|
||||
{
|
||||
if (USER_MODULE == index) {
|
||||
return String(Settings.user_template.name);
|
||||
} else {
|
||||
return FPSTR(kModules[index].name);
|
||||
}
|
||||
}
|
||||
|
||||
String ModuleName()
|
||||
{
|
||||
return AnyModuleName(Settings.module);
|
||||
}
|
||||
|
||||
void ModuleGpios(myio *gp)
|
||||
{
|
||||
uint8_t *dest = (uint8_t *)gp;
|
||||
memset(dest, GPIO_NONE, sizeof(myio));
|
||||
|
||||
uint8_t src[sizeof(mycfgio)];
|
||||
if (USER_MODULE == Settings.module) {
|
||||
memcpy(&src, &Settings.user_template.gp, sizeof(mycfgio));
|
||||
} else {
|
||||
memcpy_P(&src, &kModules[Settings.module].gp, sizeof(mycfgio));
|
||||
}
|
||||
// 11 85 00 85 85 00 00 00 15 38 85 00 00 81
|
||||
|
||||
// AddLogBuffer(LOG_LEVEL_DEBUG, (uint8_t *)&src, sizeof(mycfgio));
|
||||
|
||||
uint8_t j = 0;
|
||||
for (uint8_t i = 0; i < sizeof(mycfgio); i++) {
|
||||
if (6 == i) { j = 9; }
|
||||
if (8 == i) { j = 12; }
|
||||
dest[j] = src[i];
|
||||
j++;
|
||||
}
|
||||
// 11 85 00 85 85 00 00 00 00 00 00 00 15 38 85 00 00 81
|
||||
|
||||
// AddLogBuffer(LOG_LEVEL_DEBUG, (uint8_t *)gp, sizeof(myio));
|
||||
}
|
||||
|
||||
gpio_flag ModuleFlag()
|
||||
{
|
||||
gpio_flag flag;
|
||||
|
||||
if (USER_MODULE == Settings.module) {
|
||||
flag = Settings.user_template.flag;
|
||||
} else {
|
||||
memcpy_P(&flag, &kModules[Settings.module].flag, sizeof(gpio_flag));
|
||||
}
|
||||
|
||||
return flag;
|
||||
}
|
||||
|
||||
void ModuleDefault(uint8_t module)
|
||||
{
|
||||
if (USER_MODULE == module) { module = WEMOS; } // Generic
|
||||
Settings.user_template_base = module;
|
||||
memcpy_P(&Settings.user_template, &kModules[module], sizeof(mytmplt));
|
||||
}
|
||||
|
||||
void SetModuleType()
|
||||
{
|
||||
my_module_type = (USER_MODULE == Settings.module) ? Settings.user_template_base : Settings.module;
|
||||
}
|
||||
|
||||
uint8_t ValidPin(uint8_t pin, uint8_t gpio)
|
||||
{
|
||||
uint8_t result = gpio;
|
||||
|
||||
if (((pin > 5) && (pin < 9)) || (11 == pin)) {
|
||||
result = GPIO_NONE; // Disable flash pins GPIO6, GPIO7, GPIO8 and GPIO11
|
||||
}
|
||||
if ((WEMOS == Settings.module) && (!Settings.flag3.user_esp8285_enable)) {
|
||||
if ((pin == 9) || (pin == 10)) { result = GPIO_NONE; } // Disable possible flash GPIO9 and GPIO10
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
bool ValidGPIO(uint8_t pin, uint8_t gpio)
|
||||
{
|
||||
return (GPIO_USER == ValidPin(pin, gpio)); // Only allow GPIO_USER pins
|
||||
}
|
||||
|
||||
bool GetUsedInModule(uint8_t val, uint8_t *arr)
|
||||
{
|
||||
int offset = 0;
|
||||
|
||||
if (!val) { return false; } // None
|
||||
|
||||
if ((val >= GPIO_KEY1) && (val < GPIO_KEY1 + MAX_KEYS)) {
|
||||
offset = (GPIO_KEY1_NP - GPIO_KEY1);
|
||||
}
|
||||
if ((val >= GPIO_KEY1_NP) && (val < GPIO_KEY1_NP + MAX_KEYS)) {
|
||||
offset = -(GPIO_KEY1_NP - GPIO_KEY1);
|
||||
}
|
||||
if ((val >= GPIO_KEY1_INV) && (val < GPIO_KEY1_INV + MAX_KEYS)) {
|
||||
offset = -(GPIO_KEY1_INV - GPIO_KEY1);
|
||||
}
|
||||
if ((val >= GPIO_KEY1_INV_NP) && (val < GPIO_KEY1_INV_NP + MAX_KEYS)) {
|
||||
offset = -(GPIO_KEY1_INV_NP - GPIO_KEY1);
|
||||
}
|
||||
|
||||
if ((val >= GPIO_SWT1) && (val < GPIO_SWT1 + MAX_SWITCHES)) {
|
||||
offset = (GPIO_SWT1_NP - GPIO_SWT1);
|
||||
}
|
||||
if ((val >= GPIO_SWT1_NP) && (val < GPIO_SWT1_NP + MAX_SWITCHES)) {
|
||||
offset = -(GPIO_SWT1_NP - GPIO_SWT1);
|
||||
}
|
||||
|
||||
if ((val >= GPIO_REL1) && (val < GPIO_REL1 + MAX_RELAYS)) {
|
||||
offset = (GPIO_REL1_INV - GPIO_REL1);
|
||||
}
|
||||
if ((val >= GPIO_REL1_INV) && (val < GPIO_REL1_INV + MAX_RELAYS)) {
|
||||
offset = -(GPIO_REL1_INV - GPIO_REL1);
|
||||
}
|
||||
|
||||
if ((val >= GPIO_LED1) && (val < GPIO_LED1 + MAX_LEDS)) {
|
||||
offset = (GPIO_LED1_INV - GPIO_LED1);
|
||||
}
|
||||
if ((val >= GPIO_LED1_INV) && (val < GPIO_LED1_INV + MAX_LEDS)) {
|
||||
offset = -(GPIO_LED1_INV - GPIO_LED1);
|
||||
}
|
||||
|
||||
if ((val >= GPIO_PWM1) && (val < GPIO_PWM1 + MAX_PWMS)) {
|
||||
offset = (GPIO_PWM1_INV - GPIO_PWM1);
|
||||
}
|
||||
if ((val >= GPIO_PWM1_INV) && (val < GPIO_PWM1_INV + MAX_PWMS)) {
|
||||
offset = -(GPIO_PWM1_INV - GPIO_PWM1);
|
||||
}
|
||||
|
||||
if ((val >= GPIO_CNTR1) && (val < GPIO_CNTR1 + MAX_COUNTERS)) {
|
||||
offset = (GPIO_CNTR1_NP - GPIO_CNTR1);
|
||||
}
|
||||
if ((val >= GPIO_CNTR1_NP) && (val < GPIO_CNTR1_NP + MAX_COUNTERS)) {
|
||||
offset = -(GPIO_CNTR1_NP - GPIO_CNTR1);
|
||||
}
|
||||
|
||||
for (uint8_t i = 0; i < MAX_GPIO_PIN; i++) {
|
||||
if (arr[i] == val) { return true; }
|
||||
if (arr[i] == val + offset) { return true; }
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool JsonTemplate(const char* dataBuf)
|
||||
{
|
||||
StaticJsonBuffer<350> jb; // 331 from https://arduinojson.org/v5/assistant/
|
||||
JsonObject& obj = jb.parseObject(dataBuf);
|
||||
if (!obj.success()) { return false; }
|
||||
|
||||
// All parameters are optional allowing for partial changes
|
||||
const char* name = obj[D_JSON_NAME];
|
||||
if (name != nullptr) {
|
||||
strlcpy(Settings.user_template.name, name, sizeof(Settings.user_template.name));
|
||||
}
|
||||
if (obj[D_JSON_GPIO].success()) {
|
||||
for (uint8_t i = 0; i < sizeof(mycfgio); i++) {
|
||||
Settings.user_template.gp.io[i] = obj[D_JSON_GPIO][i] | 0;
|
||||
}
|
||||
}
|
||||
if (obj[D_JSON_FLAG].success()) {
|
||||
uint8_t flag = obj[D_JSON_FLAG] | 0;
|
||||
memcpy(&Settings.user_template.flag, &flag, sizeof(gpio_flag));
|
||||
}
|
||||
if (obj[D_JSON_BASE].success()) {
|
||||
uint8_t base = obj[D_JSON_BASE];
|
||||
if ((0 == base) || (base >= MAXMODULE)) { base = 17; } else { base--; }
|
||||
Settings.user_template_base = base; // Default WEMOS
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void TemplateJson()
|
||||
{
|
||||
snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_JSON_NAME "\":\"%s\",\"" D_JSON_GPIO "\":["), Settings.user_template.name);
|
||||
for (uint8_t i = 0; i < sizeof(Settings.user_template.gp); i++) {
|
||||
snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s%s%d"), mqtt_data, (i>0)?",":"", Settings.user_template.gp.io[i]);
|
||||
}
|
||||
snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s],\"" D_JSON_FLAG "\":%d,\"" D_JSON_BASE "\":%d}"),
|
||||
mqtt_data, Settings.user_template.flag, Settings.user_template_base +1);
|
||||
}
|
||||
|
||||
/*********************************************************************************************\
|
||||
* Sleep aware time scheduler functions borrowed from ESPEasy
|
||||
\*********************************************************************************************/
|
||||
|
|
|
@ -50,12 +50,6 @@ void ButtonInvertFlag(uint8 button_bit)
|
|||
|
||||
void ButtonInit(void)
|
||||
{
|
||||
if (my_module_flag.pullup) {
|
||||
if (Settings.flag3.no_pullup) {
|
||||
key_no_pullup = 0xff;
|
||||
}
|
||||
}
|
||||
|
||||
buttons_found = 0;
|
||||
for (uint8_t i = 0; i < MAX_KEYS; i++) {
|
||||
if (pin[GPIO_KEY1 +i] < 99) {
|
||||
|
|
|
@ -87,6 +87,23 @@ String GetTimeZone(void)
|
|||
return String(tz); // -03:45
|
||||
}
|
||||
|
||||
String GetDuration(uint32_t time)
|
||||
{
|
||||
char dt[16];
|
||||
|
||||
TIME_T ut;
|
||||
BreakTime(time, ut);
|
||||
|
||||
// "P128DT14H35M44S" - ISO8601:2004 - https://en.wikipedia.org/wiki/ISO_8601 Durations
|
||||
// snprintf_P(dt, sizeof(dt), PSTR("P%dDT%02dH%02dM%02dS"), ut.days, ut.hour, ut.minute, ut.second);
|
||||
|
||||
// "128 14:35:44" - OpenVMS
|
||||
// "128T14:35:44" - Tasmota
|
||||
snprintf_P(dt, sizeof(dt), PSTR("%dT%02d:%02d:%02d"), ut.days, ut.hour, ut.minute, ut.second);
|
||||
|
||||
return String(dt); // 128T14:35:44
|
||||
}
|
||||
|
||||
String GetDT(uint32_t time)
|
||||
{
|
||||
// "2017-03-07T11:08:02" - ISO8601:2004
|
||||
|
@ -155,42 +172,26 @@ String GetTime(int type)
|
|||
return String(stime); // Thu Nov 01 11:41:02 2018
|
||||
}
|
||||
|
||||
uint32_t UpTime(void)
|
||||
{
|
||||
if (restart_time) {
|
||||
return utc_time - restart_time;
|
||||
} else {
|
||||
return uptime;
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t MinutesUptime(void)
|
||||
{
|
||||
return (UpTime() / 60);
|
||||
}
|
||||
|
||||
String GetUptime(void)
|
||||
{
|
||||
char dt[16];
|
||||
|
||||
TIME_T ut;
|
||||
|
||||
if (restart_time) {
|
||||
BreakTime(utc_time - restart_time, ut);
|
||||
} else {
|
||||
BreakTime(uptime, ut);
|
||||
}
|
||||
|
||||
// "P128DT14H35M44S" - ISO8601:2004 - https://en.wikipedia.org/wiki/ISO_8601 Durations
|
||||
// snprintf_P(dt, sizeof(dt), PSTR("P%dDT%02dH%02dM%02dS"), ut.days, ut.hour, ut.minute, ut.second);
|
||||
|
||||
// "128 14:35:44" - OpenVMS
|
||||
// "128T14:35:44" - Tasmota
|
||||
snprintf_P(dt, sizeof(dt), PSTR("%dT%02d:%02d:%02d"), ut.days, ut.hour, ut.minute, ut.second);
|
||||
|
||||
return String(dt); // 128T14:35:44
|
||||
return GetDuration(UpTime());
|
||||
}
|
||||
|
||||
uint32_t GetMinutesUptime(void)
|
||||
{
|
||||
TIME_T ut;
|
||||
|
||||
if (restart_time) {
|
||||
BreakTime(utc_time - restart_time, ut);
|
||||
} else {
|
||||
BreakTime(uptime, ut);
|
||||
}
|
||||
|
||||
return (ut.days *1440) + (ut.hour *60) + ut.minute;
|
||||
}
|
||||
|
||||
uint32_t GetMinutesPastMidnight(void)
|
||||
uint32_t MinutesPastMidnight(void)
|
||||
{
|
||||
uint32_t minutes = 0;
|
||||
|
||||
|
@ -322,6 +323,11 @@ uint32_t RuleToTime(TimeRule r, int yr)
|
|||
return t;
|
||||
}
|
||||
|
||||
uint32_t UtcTime(void)
|
||||
{
|
||||
return utc_time;
|
||||
}
|
||||
|
||||
uint32_t LocalTime(void)
|
||||
{
|
||||
return local_time;
|
||||
|
|
|
@ -110,12 +110,6 @@ void SwitchProbe(void)
|
|||
|
||||
void SwitchInit(void)
|
||||
{
|
||||
if (my_module_flag.pullup) {
|
||||
if (Settings.flag3.no_pullup) {
|
||||
switch_no_pullup = 0xffff;
|
||||
}
|
||||
}
|
||||
|
||||
switches_found = 0;
|
||||
for (uint8_t i = 0; i < MAX_SWITCHES; i++) {
|
||||
lastwallswitch[i] = 1; // Init global to virtual switch state;
|
||||
|
|
|
@ -49,6 +49,9 @@ using namespace axTLS;
|
|||
*/
|
||||
#include <ESP8266WiFi.h> // Wifi, MQTT, Ota, WifiManager
|
||||
|
||||
uint32_t wifi_last_event = 0; // Last wifi connection event
|
||||
uint32_t wifi_downtime = 0; // Wifi down duration
|
||||
uint16_t wifi_link_count = 0; // Number of wifi re-connect
|
||||
uint8_t wifi_counter;
|
||||
uint8_t wifi_retry_init;
|
||||
uint8_t wifi_retry;
|
||||
|
@ -171,9 +174,9 @@ void WifiConfig(uint8_t type)
|
|||
}
|
||||
#endif // USE_WPS
|
||||
#ifdef USE_WEBSERVER
|
||||
else if (WIFI_MANAGER == wifi_config_type) {
|
||||
else if (WIFI_MANAGER == wifi_config_type || WIFI_MANAGER_RESET_ONLY == wifi_config_type) {
|
||||
AddLog_P(LOG_LEVEL_INFO, S_LOG_WIFI, PSTR(D_WCFG_2_WIFIMANAGER " " D_ACTIVE_FOR_3_MINUTES));
|
||||
WifiManagerBegin();
|
||||
WifiManagerBegin(WIFI_MANAGER_RESET_ONLY == wifi_config_type);
|
||||
}
|
||||
#endif // USE_WEBSERVER
|
||||
}
|
||||
|
@ -222,7 +225,8 @@ void WifiBegin(uint8_t flag, uint8_t channel)
|
|||
delay(200);
|
||||
WiFi.mode(WIFI_STA); // Disable AP mode
|
||||
WiFiSetSleepMode();
|
||||
// if (WiFi.getPhyMode() != WIFI_PHY_MODE_11N) { WiFi.setPhyMode(WIFI_PHY_MODE_11N); }
|
||||
// if (WiFi.getPhyMode() != WIFI_PHY_MODE_11N) { WiFi.setPhyMode(WIFI_PHY_MODE_11N); } // B/G/N
|
||||
// if (WiFi.getPhyMode() != WIFI_PHY_MODE_11G) { WiFi.setPhyMode(WIFI_PHY_MODE_11G); } // B/G
|
||||
if (!WiFi.getAutoConnect()) { WiFi.setAutoConnect(true); }
|
||||
// WiFi.setAutoReconnect(true);
|
||||
switch (flag) {
|
||||
|
@ -339,13 +343,26 @@ void WifiBeginAfterScan()
|
|||
}
|
||||
}
|
||||
|
||||
uint16_t WifiLinkCount()
|
||||
{
|
||||
return wifi_link_count;
|
||||
}
|
||||
|
||||
String WifiDowntime()
|
||||
{
|
||||
return GetDuration(wifi_downtime);
|
||||
}
|
||||
|
||||
void WifiSetState(uint8_t state)
|
||||
{
|
||||
if (state == global_state.wifi_down) {
|
||||
if (state) {
|
||||
rules_flag.wifi_connected = 1;
|
||||
wifi_link_count++;
|
||||
wifi_downtime += UpTime() - wifi_last_event;
|
||||
} else {
|
||||
rules_flag.wifi_disconnected = 1;
|
||||
wifi_last_event = UpTime();
|
||||
}
|
||||
}
|
||||
global_state.wifi_down = state ^1;
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -73,6 +73,7 @@ const char kMqttCommands[] PROGMEM =
|
|||
D_CMND_MQTTUSER "|" D_CMND_MQTTPASSWORD "|" D_CMND_FULLTOPIC "|" D_CMND_PREFIX "|" D_CMND_GROUPTOPIC "|" D_CMND_TOPIC "|" D_CMND_PUBLISH "|"
|
||||
D_CMND_BUTTONTOPIC "|" D_CMND_SWITCHTOPIC "|" D_CMND_BUTTONRETAIN "|" D_CMND_SWITCHRETAIN "|" D_CMND_POWERRETAIN "|" D_CMND_SENSORRETAIN ;
|
||||
|
||||
uint16_t mqtt_connect_count = 0; // MQTT re-connect count
|
||||
uint16_t mqtt_retry_counter = 1; // MQTT connection retry counter
|
||||
uint8_t mqtt_initial_connection_state = 2; // MQTT connection messages state
|
||||
bool mqtt_connected = false; // MQTT virtual connection status
|
||||
|
@ -379,6 +380,11 @@ void MqttPublishPowerBlinkState(uint8_t device)
|
|||
|
||||
/*********************************************************************************************/
|
||||
|
||||
uint16_t MqttConnectCount()
|
||||
{
|
||||
return mqtt_connect_count;
|
||||
}
|
||||
|
||||
void MqttDisconnected(int state)
|
||||
{
|
||||
mqtt_connected = false;
|
||||
|
@ -398,6 +404,7 @@ void MqttConnected(void)
|
|||
AddLog_P(LOG_LEVEL_INFO, S_LOG_MQTT, PSTR(D_CONNECTED));
|
||||
mqtt_connected = true;
|
||||
mqtt_retry_counter = 0;
|
||||
mqtt_connect_count++;
|
||||
|
||||
GetTopic_P(stopic, TELE, mqtt_topic, S_LWT);
|
||||
snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR(D_ONLINE));
|
||||
|
@ -868,17 +875,18 @@ bool MqttCommand(void)
|
|||
const char S_CONFIGURE_MQTT[] PROGMEM = D_CONFIGURE_MQTT;
|
||||
|
||||
const char HTTP_BTN_MENU_MQTT[] PROGMEM =
|
||||
"<br/><form action='" WEB_HANDLE_MQTT "' method='get'><button>" D_CONFIGURE_MQTT "</button></form>";
|
||||
"<p><form action='" WEB_HANDLE_MQTT "' method='get'><button>" D_CONFIGURE_MQTT "</button></form></p>";
|
||||
|
||||
const char HTTP_FORM_MQTT[] PROGMEM =
|
||||
"<fieldset><legend><b> " D_MQTT_PARAMETERS " </b></legend><form method='get' action='" WEB_HANDLE_MQTT "'>"
|
||||
"<br/><b>" D_HOST "</b> (" MQTT_HOST ")<br/><input id='mh' name='mh' placeholder='" MQTT_HOST" ' value='{m1'><br/>"
|
||||
"<br/><b>" D_PORT "</b> (" STR(MQTT_PORT) ")<br/><input id='ml' name='ml' placeholder='" STR(MQTT_PORT) "' value='{m2'><br/>"
|
||||
"<br/><b>" D_CLIENT "</b> ({m0)<br/><input id='mc' name='mc' placeholder='" MQTT_CLIENT_ID "' value='{m3'><br/>"
|
||||
"<br/><b>" D_USER "</b> (" MQTT_USER ")<br/><input id='mu' name='mu' placeholder='" MQTT_USER "' value='{m4'><br/>"
|
||||
"<br/><b>" D_PASSWORD "</b><br/><input id='mp' name='mp' type='password' placeholder='" D_PASSWORD "' value='" D_ASTERIX "'><br/>"
|
||||
"<br/><b>" D_TOPIC "</b> = %topic% (" MQTT_TOPIC ")<br/><input id='mt' name='mt' placeholder='" MQTT_TOPIC" ' value='{m6'><br/>"
|
||||
"<br/><b>" D_FULL_TOPIC "</b> (" MQTT_FULLTOPIC ")<br/><input id='mf' name='mf' placeholder='" MQTT_FULLTOPIC" ' value='{m7'><br/>";
|
||||
"<fieldset><legend><b> " D_MQTT_PARAMETERS " </b></legend>"
|
||||
"<form method='get' action='" WEB_HANDLE_MQTT "'>"
|
||||
"<p><b>" D_HOST "</b> (" MQTT_HOST ")<br/><input id='mh' name='mh' placeholder='" MQTT_HOST" ' value='{m1'></p>"
|
||||
"<p><b>" D_PORT "</b> (" STR(MQTT_PORT) ")<br/><input id='ml' name='ml' placeholder='" STR(MQTT_PORT) "' value='{m2'></p>"
|
||||
"<p><b>" D_CLIENT "</b> ({m0)<br/><input id='mc' name='mc' placeholder='" MQTT_CLIENT_ID "' value='{m3'></p>"
|
||||
"<p><b>" D_USER "</b> (" MQTT_USER ")<br/><input id='mu' name='mu' placeholder='" MQTT_USER "' value='{m4'></p>"
|
||||
"<p><b>" D_PASSWORD "</b><br/><input id='mp' name='mp' type='password' placeholder='" D_PASSWORD "' value='" D_ASTERISK_PWD "'></p>"
|
||||
"<p><b>" D_TOPIC "</b> = %topic% (" MQTT_TOPIC ")<br/><input id='mt' name='mt' placeholder='" MQTT_TOPIC" ' value='{m6'></p>"
|
||||
"<p><b>" D_FULL_TOPIC "</b> (" MQTT_FULLTOPIC ")<br/><input id='mf' name='mf' placeholder='" MQTT_FULLTOPIC" ' value='{m7'></p>";
|
||||
|
||||
void HandleMqttConfiguration(void)
|
||||
{
|
||||
|
@ -938,7 +946,7 @@ void MqttSaveSettings(void)
|
|||
WebGetArg("mu", tmp, sizeof(tmp));
|
||||
strlcpy(Settings.mqtt_user, (!strlen(tmp)) ? MQTT_USER : (!strcmp(tmp,"0")) ? "" : tmp, sizeof(Settings.mqtt_user));
|
||||
WebGetArg("mp", tmp, sizeof(tmp));
|
||||
strlcpy(Settings.mqtt_pwd, (!strlen(tmp)) ? "" : (strchr(tmp,'*')) ? Settings.mqtt_pwd : tmp, sizeof(Settings.mqtt_pwd));
|
||||
strlcpy(Settings.mqtt_pwd, (!strlen(tmp)) ? "" : (!strcmp(tmp, D_ASTERISK_PWD)) ? Settings.mqtt_pwd : tmp, sizeof(Settings.mqtt_pwd));
|
||||
snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_MQTT D_CMND_MQTTHOST " %s, " D_CMND_MQTTPORT " %d, " D_CMND_MQTTCLIENT " %s, " D_CMND_MQTTUSER " %s, " D_CMND_TOPIC " %s, " D_CMND_FULLTOPIC " %s"),
|
||||
Settings.mqtt_host, Settings.mqtt_port, Settings.mqtt_client, Settings.mqtt_user, Settings.mqtt_topic, Settings.mqtt_fulltopic);
|
||||
AddLog(LOG_LEVEL_INFO);
|
||||
|
|
|
@ -896,7 +896,11 @@ void LightAnimate(void)
|
|||
}
|
||||
}
|
||||
else {
|
||||
#ifdef PWM_LIGHTSCHEME0_IGNORE_SLEEP
|
||||
sleep = (LS_POWER == Settings.light_scheme) ? Settings.sleep : 0; // If no animation then use sleep as is
|
||||
#else
|
||||
sleep = 0;
|
||||
#endif // PWM_LIGHTSCHEME0_IGNORE_SLEEP
|
||||
switch (Settings.light_scheme) {
|
||||
case LS_POWER:
|
||||
LightSetDimmer(Settings.light_dimmer);
|
||||
|
|
|
@ -431,11 +431,13 @@ void DomoticzSensorPowerEnergy(int power, char *energy)
|
|||
const char S_CONFIGURE_DOMOTICZ[] PROGMEM = D_CONFIGURE_DOMOTICZ;
|
||||
|
||||
const char HTTP_BTN_MENU_DOMOTICZ[] PROGMEM =
|
||||
"<br/><form action='" WEB_HANDLE_DOMOTICZ "' method='get'><button>" D_CONFIGURE_DOMOTICZ "</button></form>";
|
||||
"<p><form action='" WEB_HANDLE_DOMOTICZ "' method='get'><button>" D_CONFIGURE_DOMOTICZ "</button></form></p>";
|
||||
|
||||
const char HTTP_FORM_DOMOTICZ[] PROGMEM =
|
||||
"<fieldset><legend><b> " D_DOMOTICZ_PARAMETERS " </b></legend><form method='post' action='" WEB_HANDLE_DOMOTICZ "'>"
|
||||
"<br/><table>";
|
||||
"<fieldset><legend><b> " D_DOMOTICZ_PARAMETERS " </b></legend>"
|
||||
"<form method='post' action='" WEB_HANDLE_DOMOTICZ "'>"
|
||||
"<br/>"
|
||||
"<table>";
|
||||
const char HTTP_FORM_DOMOTICZ_RELAY[] PROGMEM =
|
||||
"<tr><td style='width:260px'><b>" D_DOMOTICZ_IDX " {1</b></td><td style='width:70px'><input id='r{1' name='r{1' placeholder='0' value='{2'></td></tr>"
|
||||
"<tr><td style='width:260px'><b>" D_DOMOTICZ_KEY_IDX " {1</b></td><td style='width:70px'><input id='k{1' name='k{1' placeholder='0' value='{3'></td></tr>";
|
||||
|
|
|
@ -232,7 +232,7 @@ String GetSun(uint8_t dawn)
|
|||
return String(stime);
|
||||
}
|
||||
|
||||
uint16_t GetSunMinutes(uint8_t dawn)
|
||||
uint16_t SunMinutes(uint8_t dawn)
|
||||
{
|
||||
uint8_t hour[2];
|
||||
uint8_t minute[2];
|
||||
|
@ -517,7 +517,7 @@ bool TimerCommand(void)
|
|||
const char S_CONFIGURE_TIMER[] PROGMEM = D_CONFIGURE_TIMER;
|
||||
|
||||
const char HTTP_BTN_MENU_TIMER[] PROGMEM =
|
||||
"<br/><form action='" WEB_HANDLE_TIMER "' method='get'><button>" D_CONFIGURE_TIMER "</button></form>";
|
||||
"<p><form action='" WEB_HANDLE_TIMER "' method='get'><button>" D_CONFIGURE_TIMER "</button></form></p>";
|
||||
|
||||
const char HTTP_TIMER_SCRIPT[] PROGMEM =
|
||||
"var pt=[],ct=99;"
|
||||
|
@ -593,8 +593,8 @@ const char HTTP_TIMER_SCRIPT[] PROGMEM =
|
|||
"if(ct<99){st();}" // Save changes
|
||||
"ct=t;"
|
||||
"o=document.getElementsByClassName('tl');" // Restore style to all tabs/buttons
|
||||
"for(i=0;i<o.length;i++){o[i].style.cssText=\"background-color:#ccc;color:#fff;font-weight:normal;\"}"
|
||||
"e.style.cssText=\"background-color:#fff;color:#000;font-weight:bold;\";" // Change style to tab/button used to open content
|
||||
"for(i=0;i<o.length;i++){o[i].style.cssText=\"background-color:#999;color:#fff;font-weight:normal;\"}"
|
||||
"e.style.cssText=\"background-color:transparent;color:#000;font-weight:bold;\";" // Change style to tab/button used to open content
|
||||
"s=pt[ct];" // Get parameters from array
|
||||
#ifdef USE_SUNRISE
|
||||
"p=(s>>29)&3;eb('b'+p).checked=1;" // Set mode
|
||||
|
@ -637,36 +637,34 @@ const char HTTP_TIMER_SCRIPT[] PROGMEM =
|
|||
"o=qs('#mw');for(i=0;i<=15;i++){ce((i<10)?('0'+i):i,o);}" // Create window minutes select options
|
||||
"o=qs('#d1');for(i=0;i<}1;i++){ce(i+1,o);}" // Create outputs
|
||||
"var a='" D_DAY3LIST "';"
|
||||
"s='';for(i=0;i<7;i++){s+=\"<input style='width:5%;' id='w\"+i+\"' name='w\"+i+\"' type='checkbox'><b>\"+a.substring(i*3,(i*3)+3)+\"</b>\"}"
|
||||
"s='';for(i=0;i<7;i++){s+=\"<input id='w\"+i+\"' name='w\"+i+\"' type='checkbox'><b>\"+a.substring(i*3,(i*3)+3)+\"</b> \"}"
|
||||
"eb('ds').innerHTML=s;" // Create weekdays
|
||||
"eb('dP').click();" // Get the element with id='dP' and click on it
|
||||
"}";
|
||||
const char HTTP_TIMER_STYLE[] PROGMEM =
|
||||
".tl{float:left;border-radius:0;border:1px solid #fff;padding:1px;width:6.25%;}"
|
||||
#ifdef USE_SUNRISE
|
||||
"input[type='radio']{width:13px;height:24px;margin-top:-1px;margin-right:8px;vertical-align:middle;}"
|
||||
#endif
|
||||
".tl{float:left;border-radius:0;border:1px solid #f2f2f2;padding:1px;width:6.25%;}" // Border color needs to be the same as Fieldset background color from HTTP_HEAD_STYLE (transparent won't work)
|
||||
"</style>";
|
||||
const char HTTP_FORM_TIMER[] PROGMEM =
|
||||
"<fieldset style='min-width:470px;text-align:center;'>"
|
||||
"<legend style='text-align:left;'><b> " D_TIMER_PARAMETERS " </b></legend>"
|
||||
"<form method='post' action='" WEB_HANDLE_TIMER "' onsubmit='return st();'>"
|
||||
"<br/><input style='width:5%;' id='e0' name='e0' type='checkbox'{e0><b>" D_TIMER_ENABLE "</b><br/><br/><hr/>"
|
||||
"<br/><input id='e0' name='e0' type='checkbox'{e0><b>" D_TIMER_ENABLE "</b><br/><br/><hr/>"
|
||||
"<input id='t0' name='t0' value='";
|
||||
const char HTTP_FORM_TIMER1[] PROGMEM =
|
||||
"' hidden><div id='bt' name='bt'></div><br/><br/><br/>"
|
||||
"<div id='oa' name='oa'></div><br/>"
|
||||
"<div>"
|
||||
"<input style='width:5%;' id='a0' name='a0' type='checkbox'><b>" D_TIMER_ARM "</b> "
|
||||
"<input style='width:5%;' id='r0' name='r0' type='checkbox'><b>" D_TIMER_REPEAT "</b>"
|
||||
"<input id='a0' name='a0' type='checkbox'><b>" D_TIMER_ARM "</b> "
|
||||
"<input id='r0' name='r0' type='checkbox'><b>" D_TIMER_REPEAT "</b>"
|
||||
"</div><br/>"
|
||||
"<div>"
|
||||
#ifdef USE_SUNRISE
|
||||
"<fieldset style='width:299px;margin:auto;text-align:left;border:0;'>"
|
||||
"<fieldset style='width:299px;margin:auto;text-align:left;border:0;'>" // 299 used in page.replace(F("299")
|
||||
"<input id='b0' name='rd' type='radio' value='0' onclick='gt();'><b>" D_TIMER_TIME "</b><br/>"
|
||||
"<input id='b1' name='rd' type='radio' value='1' onclick='gt();'><b>" D_SUNRISE "</b> (}8)<br/>"
|
||||
"<input id='b2' name='rd' type='radio' value='2' onclick='gt();'><b>" D_SUNSET "</b> (}9)<br/>"
|
||||
"</fieldset>"
|
||||
"<p></p>"
|
||||
"<span><select style='width:46px;' id='dr' name='dr'></select></span>"
|
||||
" "
|
||||
#else
|
||||
|
|
|
@ -90,6 +90,21 @@
|
|||
#define MAXIMUM_COMPARE_OPERATOR COMPARE_OPERATOR_SMALLER_EQUAL
|
||||
const char kCompareOperators[] PROGMEM = "=\0>\0<\0|\0==!=>=<=";
|
||||
|
||||
#ifdef USE_EXPRESSION
|
||||
#include <LinkedList.h> // Import LinkedList library
|
||||
|
||||
const char kExpressionOperators[] PROGMEM = "+-*/%^";
|
||||
#define EXPRESSION_OPERATOR_ADD 0
|
||||
#define EXPRESSION_OPERATOR_SUBTRACT 1
|
||||
#define EXPRESSION_OPERATOR_MULTIPLY 2
|
||||
#define EXPRESSION_OPERATOR_DIVIDEDBY 3
|
||||
#define EXPRESSION_OPERATOR_MODULO 4
|
||||
#define EXPRESSION_OPERATOR_POWER 5
|
||||
|
||||
const uint8_t kExpressionOperatorsPriorities[] PROGMEM = {1, 1, 2, 2, 3, 4};
|
||||
#define MAX_EXPRESSION_OPERATOR_PRIORITY 4
|
||||
#endif // USE_EXPRESSION
|
||||
|
||||
enum RulesCommands { CMND_RULE, CMND_RULETIMER, CMND_EVENT, CMND_VAR, CMND_MEM, CMND_ADD, CMND_SUB, CMND_MULT, CMND_SCALE, CMND_CALC_RESOLUTION };
|
||||
const char kRulesCommands[] PROGMEM = D_CMND_RULE "|" D_CMND_RULETIMER "|" D_CMND_EVENT "|" D_CMND_VAR "|" D_CMND_MEM "|" D_CMND_ADD "|" D_CMND_SUB "|" D_CMND_MULT "|" D_CMND_SCALE "|" D_CMND_CALC_RESOLUTION ;
|
||||
|
||||
|
@ -170,11 +185,11 @@ bool RulesRuleMatch(uint8_t rule_set, String &event, String &rule)
|
|||
}
|
||||
snprintf_P(stemp, sizeof(stemp), PSTR("%%TIME%%"));
|
||||
if (rule_param.startsWith(stemp)) {
|
||||
rule_param = String(GetMinutesPastMidnight());
|
||||
rule_param = String(MinutesPastMidnight());
|
||||
}
|
||||
snprintf_P(stemp, sizeof(stemp), PSTR("%%UPTIME%%"));
|
||||
if (rule_param.startsWith(stemp)) {
|
||||
rule_param = String(GetMinutesUptime());
|
||||
rule_param = String(MinutesUptime());
|
||||
}
|
||||
snprintf_P(stemp, sizeof(stemp), PSTR("%%TIMESTAMP%%"));
|
||||
if (rule_param.startsWith(stemp)) {
|
||||
|
@ -183,11 +198,11 @@ bool RulesRuleMatch(uint8_t rule_set, String &event, String &rule)
|
|||
#if defined(USE_TIMERS) && defined(USE_SUNRISE)
|
||||
snprintf_P(stemp, sizeof(stemp), PSTR("%%SUNRISE%%"));
|
||||
if (rule_param.startsWith(stemp)) {
|
||||
rule_param = String(GetSunMinutes(0));
|
||||
rule_param = String(SunMinutes(0));
|
||||
}
|
||||
snprintf_P(stemp, sizeof(stemp), PSTR("%%SUNSET%%"));
|
||||
if (rule_param.startsWith(stemp)) {
|
||||
rule_param = String(GetSunMinutes(1));
|
||||
rule_param = String(SunMinutes(1));
|
||||
}
|
||||
#endif // USE_TIMERS and USE_SUNRISE
|
||||
rule_param.toUpperCase();
|
||||
|
@ -332,12 +347,12 @@ bool RuleSetProcess(uint8_t rule_set, String &event_saved)
|
|||
snprintf_P(stemp, sizeof(stemp), PSTR("%%mem%d%%"), i +1);
|
||||
commands.replace(stemp, Settings.mems[i]);
|
||||
}
|
||||
commands.replace(F("%time%"), String(GetMinutesPastMidnight()));
|
||||
commands.replace(F("%uptime%"), String(GetMinutesUptime()));
|
||||
commands.replace(F("%time%"), String(MinutesPastMidnight()));
|
||||
commands.replace(F("%uptime%"), String(MinutesUptime()));
|
||||
commands.replace(F("%timestamp%"), GetDateAndTime(DT_LOCAL).c_str());
|
||||
#if defined(USE_TIMERS) && defined(USE_SUNRISE)
|
||||
commands.replace(F("%sunrise%"), String(GetSunMinutes(0)));
|
||||
commands.replace(F("%sunset%"), String(GetSunMinutes(1)));
|
||||
commands.replace(F("%sunrise%"), String(SunMinutes(0)));
|
||||
commands.replace(F("%sunset%"), String(SunMinutes(1)));
|
||||
#endif // USE_TIMERS and USE_SUNRISE
|
||||
|
||||
char command[commands.length() +1];
|
||||
|
@ -490,8 +505,8 @@ void RulesEvery50ms(void)
|
|||
json_event[0] = '\0';
|
||||
switch (i) {
|
||||
case 0: strncpy_P(json_event, PSTR("{\"System\":{\"Boot\":1}}"), sizeof(json_event)); break;
|
||||
case 1: snprintf_P(json_event, sizeof(json_event), PSTR("{\"Time\":{\"Initialized\":%d}}"), GetMinutesPastMidnight()); break;
|
||||
case 2: snprintf_P(json_event, sizeof(json_event), PSTR("{\"Time\":{\"Set\":%d}}"), GetMinutesPastMidnight()); break;
|
||||
case 1: snprintf_P(json_event, sizeof(json_event), PSTR("{\"Time\":{\"Initialized\":%d}}"), MinutesPastMidnight()); break;
|
||||
case 2: snprintf_P(json_event, sizeof(json_event), PSTR("{\"Time\":{\"Set\":%d}}"), MinutesPastMidnight()); break;
|
||||
case 3: strncpy_P(json_event, PSTR("{\"MQTT\":{\"Connected\":1}}"), sizeof(json_event)); break;
|
||||
case 4: strncpy_P(json_event, PSTR("{\"MQTT\":{\"Disconnected\":1}}"), sizeof(json_event)); break;
|
||||
case 5: strncpy_P(json_event, PSTR("{\"WIFI\":{\"Connected\":1}}"), sizeof(json_event)); break;
|
||||
|
@ -534,7 +549,7 @@ void RulesEverySecond(void)
|
|||
if (RtcTime.valid) {
|
||||
if ((uptime > 60) && (RtcTime.minute != rules_last_minute)) { // Execute from one minute after restart every minute only once
|
||||
rules_last_minute = RtcTime.minute;
|
||||
snprintf_P(json_event, sizeof(json_event), PSTR("{\"Time\":{\"Minute\":%d}}"), GetMinutesPastMidnight());
|
||||
snprintf_P(json_event, sizeof(json_event), PSTR("{\"Time\":{\"Minute\":%d}}"), MinutesPastMidnight());
|
||||
RulesProcessEvent(json_event);
|
||||
}
|
||||
}
|
||||
|
@ -562,6 +577,310 @@ void RulesTeleperiod(void)
|
|||
rules_teleperiod = 0;
|
||||
}
|
||||
|
||||
#ifdef USE_EXPRESSION
|
||||
/********************************************************************************************/
|
||||
/*
|
||||
* Parse a number value
|
||||
* Input:
|
||||
* pNumber - A char pointer point to a digit started string (guaranteed)
|
||||
* value - Reference a double variable used to accept the result
|
||||
* Output:
|
||||
* pNumber - Pointer forward to next character after the number
|
||||
* value - double type, the result value
|
||||
* Return:
|
||||
* true - succeed
|
||||
* false - failed
|
||||
*/
|
||||
bool findNextNumber(char * &pNumber, double &value)
|
||||
{
|
||||
bool bSucceed = false;
|
||||
String sNumber = "";
|
||||
while (*pNumber) {
|
||||
if (isdigit(*pNumber) || (*pNumber == '.')) {
|
||||
sNumber += *pNumber;
|
||||
pNumber++;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (sNumber.length() > 0) {
|
||||
value = CharToDouble(sNumber.c_str());
|
||||
bSucceed = true;
|
||||
}
|
||||
return bSucceed;
|
||||
}
|
||||
|
||||
/********************************************************************************************/
|
||||
/*
|
||||
* Parse a variable (like VAR1, MEM3) and get its value (double type)
|
||||
* Input:
|
||||
* pVarname - A char pointer point to a variable name string
|
||||
* value - Reference a double variable used to accept the result
|
||||
* Output:
|
||||
* pVarname - Pointer forward to next character after the variable
|
||||
* value - double type, the result value
|
||||
* Return:
|
||||
* true - succeed
|
||||
* false - failed
|
||||
*/
|
||||
bool findNextVariableValue(char * &pVarname, double &value)
|
||||
{
|
||||
bool succeed = true;
|
||||
value = 0;
|
||||
String sVarName = "";
|
||||
while (*pVarname) {
|
||||
if (isalpha(*pVarname) || isdigit(*pVarname)) {
|
||||
sVarName.concat(*pVarname);
|
||||
pVarname++;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
sVarName.toUpperCase();
|
||||
if (sVarName.startsWith(F("VAR"))) {
|
||||
int index = sVarName.substring(3).toInt();
|
||||
if (index > 0 && index <= MAX_RULE_VARS) {
|
||||
value = CharToDouble(vars[index -1]);
|
||||
}
|
||||
} else if (sVarName.startsWith(F("MEM"))) {
|
||||
int index = sVarName.substring(3).toInt();
|
||||
if (index > 0 && index <= MAX_RULE_MEMS) {
|
||||
value = CharToDouble(Settings.mems[index -1]);
|
||||
}
|
||||
} else if (sVarName.equals(F("TIME"))) {
|
||||
value = MinutesPastMidnight();
|
||||
} else if (sVarName.equals(F("UPTIME"))) {
|
||||
value = MinutesUptime();
|
||||
} else if (sVarName.equals(F("UTCTIME"))) {
|
||||
value = UtcTime();
|
||||
} else if (sVarName.equals(F("LOCALTIME"))) {
|
||||
value = LocalTime();
|
||||
#if defined(USE_TIMERS) && defined(USE_SUNRISE)
|
||||
} else if (sVarName.equals(F("SUNRISE"))) {
|
||||
value = SunMinutes(0);
|
||||
} else if (sVarName.equals(F("SUNSET"))) {
|
||||
value = SunMinutes(1);
|
||||
#endif
|
||||
} else {
|
||||
succeed = false;
|
||||
}
|
||||
|
||||
return succeed;
|
||||
}
|
||||
|
||||
/********************************************************************************************/
|
||||
/*
|
||||
* Find next object in expression and evaluate it
|
||||
* An object could be:
|
||||
* - A float number start with a digit, like 0.787
|
||||
* - A variable name, like VAR1, MEM3
|
||||
* - An expression enclosed with a pair of round brackets, (.....)
|
||||
* Input:
|
||||
* pointer - A char pointer point to a place of the expression string
|
||||
* value - Reference a double variable used to accept the result
|
||||
* Output:
|
||||
* pointer - Pointer forward to next character after next object
|
||||
* value - double type, the result value
|
||||
* Return:
|
||||
* true - succeed
|
||||
* false - failed
|
||||
*/
|
||||
bool findNextObjectValue(char * &pointer, double &value)
|
||||
{
|
||||
bool bSucceed = false;
|
||||
while (*pointer)
|
||||
{
|
||||
if (isspace(*pointer)) { //Skip leading spaces
|
||||
pointer++;
|
||||
continue;
|
||||
}
|
||||
if (isdigit(*pointer)) { //This object is a number
|
||||
bSucceed = findNextNumber(pointer, value);
|
||||
break;
|
||||
} else if (isalpha(*pointer)) { //Should be a variable like VAR12, MEM1
|
||||
bSucceed = findNextVariableValue(pointer, value);
|
||||
break;
|
||||
} else if (*pointer == '(') { //It is a sub expression bracketed with ()
|
||||
pointer++;
|
||||
char * sub_exp_start = pointer; //Find out the sub expression between a pair of parenthesis. "()"
|
||||
unsigned int sub_exp_len = 0;
|
||||
//Look for the matched closure parenthesis.")"
|
||||
bool bFindClosures = false;
|
||||
uint8_t matchClosures = 1;
|
||||
while (*pointer)
|
||||
{
|
||||
if (*pointer == ')') {
|
||||
matchClosures--;
|
||||
if (matchClosures == 0) {
|
||||
sub_exp_len = pointer - sub_exp_start;
|
||||
bFindClosures = true;
|
||||
break;
|
||||
}
|
||||
} else if (*pointer == '(') {
|
||||
matchClosures++;
|
||||
}
|
||||
pointer++;
|
||||
}
|
||||
if (bFindClosures) {
|
||||
value = evaluateExpression(sub_exp_start, sub_exp_len);
|
||||
bSucceed = true;
|
||||
}
|
||||
break;
|
||||
} else { //No number, no variable, no expression, then invalid object.
|
||||
break;
|
||||
}
|
||||
}
|
||||
return bSucceed;
|
||||
}
|
||||
|
||||
/********************************************************************************************/
|
||||
/*
|
||||
* Find next operator in expression
|
||||
* An operator could be: +, - , * , / , %, ^
|
||||
* Input:
|
||||
* pointer - A char pointer point to a place of the expression string
|
||||
* op - Reference to a variable used to accept the result
|
||||
* Output:
|
||||
* pointer - Pointer forward to next character after next operator
|
||||
* op - The operator. 0, 1, 2, 3, 4, 5
|
||||
* Return:
|
||||
* true - succeed
|
||||
* false - failed
|
||||
*/
|
||||
bool findNextOperator(char * &pointer, int8_t &op)
|
||||
{
|
||||
bool bSucceed = false;
|
||||
while (*pointer)
|
||||
{
|
||||
if (isspace(*pointer)) { //Skip leading spaces
|
||||
pointer++;
|
||||
continue;
|
||||
}
|
||||
if (char *pch = strchr(kExpressionOperators, *pointer)) { //If it is an operator
|
||||
op = (int8_t)(pch - kExpressionOperators);
|
||||
pointer++;
|
||||
bSucceed = true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
return bSucceed;
|
||||
}
|
||||
/********************************************************************************************/
|
||||
/*
|
||||
* Calculate a simple expression composed by 2 value and 1 operator, like 2 * 3
|
||||
* Input:
|
||||
* pointer - A char pointer point to a place of the expression string
|
||||
* value - Reference a double variable used to accept the result
|
||||
* Output:
|
||||
* pointer - Pointer forward to next character after next object
|
||||
* value - double type, the result value
|
||||
* Return:
|
||||
* true - succeed
|
||||
* false - failed
|
||||
*/
|
||||
double calculateTwoValues(double v1, double v2, uint8_t op)
|
||||
{
|
||||
switch (op)
|
||||
{
|
||||
case EXPRESSION_OPERATOR_ADD:
|
||||
return v1 + v2;
|
||||
case EXPRESSION_OPERATOR_SUBTRACT:
|
||||
return v1 - v2;
|
||||
case EXPRESSION_OPERATOR_MULTIPLY:
|
||||
return v1 * v2;
|
||||
case EXPRESSION_OPERATOR_DIVIDEDBY:
|
||||
return (0 == v2) ? 0 : (v1 / v2);
|
||||
case EXPRESSION_OPERATOR_MODULO:
|
||||
return (0 == v2) ? 0 : (int(v1) % int(v2));
|
||||
case EXPRESSION_OPERATOR_POWER:
|
||||
return FastPrecisePow(v1, v2);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/********************************************************************************************/
|
||||
/*
|
||||
* Parse and evaluate an expression.
|
||||
* For example: "10 * ( MEM2 + 1) / 2"
|
||||
* Right now, only support operators listed here: (order by priority)
|
||||
* Priority 4: ^ (power)
|
||||
* Priority 3: % (modulo, always get integer result)
|
||||
* Priority 2: *, /
|
||||
* Priority 1: +, -
|
||||
* Input:
|
||||
* expression - The expression to be evaluated
|
||||
* len - Length of the expression
|
||||
* Return:
|
||||
* double - result.
|
||||
* 0 - if the expression is invalid
|
||||
* An example:
|
||||
* MEM1 = 3, MEM2 = 6, VAR2 = 15, VAR10 = 80
|
||||
* At beginning, the expression might be complicated like: 3.14 * (MEM1 * (10 + VAR2 ^2) - 100) % 10 + VAR10 / (2 + MEM2)
|
||||
* We are going to scan the whole expression, evaluate each object.
|
||||
* Finally we will have a value list:.
|
||||
* Order Object Value
|
||||
* 0 3.14 3.14
|
||||
* 1 (MEM1 * (10 + VAR2 ^2) - 100) 605
|
||||
* 2 10 10
|
||||
* 3 VAR10 80
|
||||
* 4 (2 + MEM2) 8
|
||||
* And an operator list:
|
||||
* Order Operator Priority
|
||||
* 0 * 2
|
||||
* 1 % 3
|
||||
* 2 + 1
|
||||
* 3 / 2
|
||||
*/
|
||||
double evaluateExpression(const char * expression, unsigned int len)
|
||||
{
|
||||
char expbuf[len + 1];
|
||||
memcpy(expbuf, expression, len);
|
||||
expbuf[len] = '\0';
|
||||
char * scan_pointer = expbuf;
|
||||
|
||||
LinkedList<double> object_values;
|
||||
LinkedList<int8_t> operators;
|
||||
int8_t op;
|
||||
double va;
|
||||
//Find and add the value of first object
|
||||
if (findNextObjectValue(scan_pointer, va)) {
|
||||
object_values.add(va);
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
while (*scan_pointer)
|
||||
{
|
||||
if (findNextOperator(scan_pointer, op)
|
||||
&& *scan_pointer
|
||||
&& findNextObjectValue(scan_pointer, va))
|
||||
{
|
||||
operators.add(op);
|
||||
object_values.add(va);
|
||||
} else {
|
||||
//No operator followed or no more object after this operator, we done.
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//Going to evaluate the whole expression
|
||||
//Calculate by order of operator priorities. Looking for all operators with specified priority (from High to Low)
|
||||
for (int8_t priority = MAX_EXPRESSION_OPERATOR_PRIORITY; priority>0; priority--) {
|
||||
int index = 0;
|
||||
while (index < operators.size()) {
|
||||
if (priority == kExpressionOperatorsPriorities[(operators.get(index))]) { //need to calculate the operator first
|
||||
//get current object value and remove the next object with current operator
|
||||
va = calculateTwoValues(object_values.get(index), object_values.remove(index + 1), operators.remove(index));
|
||||
//Replace the current value with the result
|
||||
object_values.set(index, va);
|
||||
} else {
|
||||
index++;
|
||||
}
|
||||
}
|
||||
}
|
||||
return object_values.get(0);
|
||||
}
|
||||
#endif //USE_EXPRESSION
|
||||
|
||||
bool RulesCommand(void)
|
||||
{
|
||||
char command[CMDSZ];
|
||||
|
@ -620,7 +939,12 @@ bool RulesCommand(void)
|
|||
}
|
||||
else if ((CMND_RULETIMER == command_code) && (index > 0) && (index <= MAX_RULE_TIMERS)) {
|
||||
if (XdrvMailbox.data_len > 0) {
|
||||
#ifdef USE_EXPRESSION
|
||||
double timer_set = evaluateExpression(XdrvMailbox.data, XdrvMailbox.data_len);
|
||||
rules_timer[index -1] = (timer_set > 0) ? millis() + (1000 * timer_set) : 0;
|
||||
#else
|
||||
rules_timer[index -1] = (XdrvMailbox.payload > 0) ? millis() + (1000 * XdrvMailbox.payload) : 0;
|
||||
#endif //USE_EXPRESSION
|
||||
}
|
||||
mqtt_data[0] = '\0';
|
||||
for (uint8_t i = 0; i < MAX_RULE_TIMERS; i++) {
|
||||
|
@ -636,14 +960,22 @@ bool RulesCommand(void)
|
|||
}
|
||||
else if ((CMND_VAR == command_code) && (index > 0) && (index <= MAX_RULE_VARS)) {
|
||||
if (XdrvMailbox.data_len > 0) {
|
||||
#ifdef USE_EXPRESSION
|
||||
dtostrfd(evaluateExpression(XdrvMailbox.data, XdrvMailbox.data_len), Settings.flag2.calc_resolution, vars[index -1]);
|
||||
#else
|
||||
strlcpy(vars[index -1], ('"' == XdrvMailbox.data[0]) ? "" : XdrvMailbox.data, sizeof(vars[index -1]));
|
||||
#endif //USE_EXPRESSION
|
||||
bitSet(vars_event, index -1);
|
||||
}
|
||||
snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_INDEX_SVALUE, command, index, vars[index -1]);
|
||||
}
|
||||
else if ((CMND_MEM == command_code) && (index > 0) && (index <= MAX_RULE_MEMS)) {
|
||||
if (XdrvMailbox.data_len > 0) {
|
||||
#ifdef USE_EXPRESSION
|
||||
dtostrfd(evaluateExpression(XdrvMailbox.data, XdrvMailbox.data_len), Settings.flag2.calc_resolution, Settings.mems[index -1]);
|
||||
#else
|
||||
strlcpy(Settings.mems[index -1], ('"' == XdrvMailbox.data[0]) ? "" : XdrvMailbox.data, sizeof(Settings.mems[index -1]));
|
||||
#endif //USE_EXPRESSION
|
||||
bitSet(mems_event, index -1);
|
||||
}
|
||||
snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_INDEX_SVALUE, command, index, Settings.mems[index -1]);
|
||||
|
|
|
@ -752,20 +752,21 @@ void KnxSensor(uint8_t sensor_type, float value)
|
|||
const char S_CONFIGURE_KNX[] PROGMEM = D_CONFIGURE_KNX;
|
||||
|
||||
const char HTTP_BTN_MENU_KNX[] PROGMEM =
|
||||
"<br/><form action='kn' method='get'><button>" D_CONFIGURE_KNX "</button></form>";
|
||||
"<p><form action='kn' method='get'><button>" D_CONFIGURE_KNX "</button></form></p>";
|
||||
|
||||
const char HTTP_FORM_KNX[] PROGMEM =
|
||||
"<fieldset><legend style='text-align:left;'><b> " D_KNX_PARAMETERS " </b></legend><form method='post' action='kn'>"
|
||||
"<fieldset><legend style='text-align:left;'><b> " D_KNX_PARAMETERS " </b>"
|
||||
"</legend><form method='post' action='kn'>"
|
||||
"<br/><center>"
|
||||
"<b>" D_KNX_PHYSICAL_ADDRESS " </b>"
|
||||
"<input style='width:12%;' type='number' name='area' min='0' max='15' value='{kna'> . "
|
||||
"<input style='width:12%;' type='number' name='line' min='0' max='15' value='{knl'> . "
|
||||
"<input style='width:12%;' type='number' name='member' min='0' max='255' value='{knm'>"
|
||||
"<br/><br/>" D_KNX_PHYSICAL_ADDRESS_NOTE "<br/><br/>"
|
||||
"<input style='width:10%;' id='b1' name='b1' type='checkbox'";
|
||||
"<input id='b1' name='b1' type='checkbox'";
|
||||
|
||||
const char HTTP_FORM_KNX1[] PROGMEM =
|
||||
"><b>" D_KNX_ENABLE " </b><input style='width:10%;' id='b2' name='b2' type='checkbox'";
|
||||
"><b>" D_KNX_ENABLE "</b> <input id='b2' name='b2' type='checkbox'";
|
||||
|
||||
const char HTTP_FORM_KNX2[] PROGMEM =
|
||||
"><b>" D_KNX_ENHANCEMENT "</b><br/></center><br/>"
|
||||
|
|
|
@ -205,17 +205,17 @@ bool CseCommand(void)
|
|||
|
||||
if (CMND_POWERSET == energy_command_code) {
|
||||
if (XdrvMailbox.data_len && power_cycle) {
|
||||
Settings.energy_power_calibration = ((unsigned long)CharToDouble(XdrvMailbox.data) * power_cycle) / CSE_PREF;
|
||||
Settings.energy_power_calibration = (unsigned long)(CharToDouble(XdrvMailbox.data) * power_cycle) / CSE_PREF;
|
||||
}
|
||||
}
|
||||
else if (CMND_VOLTAGESET == energy_command_code) {
|
||||
if (XdrvMailbox.data_len && voltage_cycle) {
|
||||
Settings.energy_voltage_calibration = ((unsigned long)CharToDouble(XdrvMailbox.data) * voltage_cycle) / CSE_UREF;
|
||||
Settings.energy_voltage_calibration = (unsigned long)(CharToDouble(XdrvMailbox.data) * voltage_cycle) / CSE_UREF;
|
||||
}
|
||||
}
|
||||
else if (CMND_CURRENTSET == energy_command_code) {
|
||||
if (XdrvMailbox.data_len && current_cycle) {
|
||||
Settings.energy_current_calibration = ((unsigned long)CharToDouble(XdrvMailbox.data) * current_cycle) / 1000;
|
||||
Settings.energy_current_calibration = (unsigned long)(CharToDouble(XdrvMailbox.data) * current_cycle) / 1000;
|
||||
}
|
||||
}
|
||||
else serviced = false; // Unknown command
|
||||
|
|
|
@ -103,7 +103,7 @@ void CounterShow(bool json)
|
|||
dtostrfd((double)RtcSettings.pulse_counter[i] / 1000000, 6, counter);
|
||||
} else {
|
||||
dsxflg++;
|
||||
dtostrfd(RtcSettings.pulse_counter[i], 0, counter);
|
||||
snprintf_P(counter, sizeof(counter), PSTR("%lu"), RtcSettings.pulse_counter[i]);
|
||||
}
|
||||
|
||||
if (json) {
|
||||
|
|
|
@ -377,19 +377,19 @@ const char HTTP_BTN_MENU_MAIN_HX711[] PROGMEM =
|
|||
"<br/><form action='" WEB_HANDLE_HX711 "' method='get'><button name='reset'>" D_RESET_HX711 "</button></form>";
|
||||
|
||||
const char HTTP_BTN_MENU_HX711[] PROGMEM =
|
||||
"<br/><form action='" WEB_HANDLE_HX711 "' method='get'><button>" D_CONFIGURE_HX711 "</button></form>";
|
||||
"<p><form action='" WEB_HANDLE_HX711 "' method='get'><button>" D_CONFIGURE_HX711 "</button></form></p>";
|
||||
|
||||
const char HTTP_FORM_HX711[] PROGMEM =
|
||||
"<fieldset><legend><b> " D_CALIBRATION " </b></legend>"
|
||||
"<form method='post' action='" WEB_HANDLE_HX711 "'>"
|
||||
"<br/><b>" D_REFERENCE_WEIGHT "</b> (" D_UNIT_KILOGRAM ")<br/><input type='number' step='0.001' id='p1' name='p1' placeholder='0' value='{1'><br/>"
|
||||
"<br/><button name='calibrate' type='submit'>" D_CALIBRATE "</button><br/>"
|
||||
"<p><b>" D_REFERENCE_WEIGHT "</b> (" D_UNIT_KILOGRAM ")<br/><input type='number' step='0.001' id='p1' name='p1' placeholder='0' value='{1'></p>"
|
||||
"<br/><button name='calibrate' type='submit'>" D_CALIBRATE "</button>"
|
||||
"</form>"
|
||||
"</fieldset><br/><br/>"
|
||||
|
||||
"<fieldset><legend><b> " D_HX711_PARAMETERS " </b></legend>"
|
||||
"<form method='post' action='" WEB_HANDLE_HX711 "'>"
|
||||
"<br/><b>" D_ITEM_WEIGHT "</b> (" D_UNIT_KILOGRAM ")<br/><input type='number' max='6.5535' step='0.0001' id='p2' name='p2' placeholder='0.0' value='{2'><br/>";
|
||||
"<p><b>" D_ITEM_WEIGHT "</b> (" D_UNIT_KILOGRAM ")<br/><input type='number' max='6.5535' step='0.0001' id='p2' name='p2' placeholder='0.0' value='{2'></p>";
|
||||
|
||||
void HandleHxAction(void)
|
||||
{
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
VER = '2.1.0020'
|
||||
VER = '2.1.0021'
|
||||
|
||||
"""
|
||||
decode-config.py - Backup/Restore Sonoff-Tasmota configuration data
|
||||
|
@ -841,9 +841,41 @@ Setting_6_4_1_13.update ({
|
|||
'mhz19b_abc_disable': ('B', (0x717,1, 7), (None, None, ('Sensor', '"Sensor15 {}".format($)')) ),
|
||||
}, 0x717, (None, None, ('*', None)), (None, False) ),
|
||||
})
|
||||
|
||||
# ======================================================================
|
||||
Setting_6_4_1_16 = copy.deepcopy(Setting_6_4_1_13)
|
||||
Setting_6_4_1_16.update({
|
||||
'user_template_base': ('B', 0x71F, (None, None, ('Management', '"Template {}".format($)')), ('$ + 1','$ - 1') ),
|
||||
'user_template': ({
|
||||
'name': ('15s', 0x720, (None, None, ('Management', '"Template {{\\\"NAME\\\":\\\"{}\\\"}}".format($)' )) ),
|
||||
'gpio00': ('B', 0x72F, (None, None, ('Management', '"Template {{\\\"GPIO\\\":[{},{},{},{},{},{},{},{},{},{},{},{},{}]}}".format(@["user_template"]["gpio00"],@["user_template"]["gpio01"],@["user_template"]["gpio02"],@["user_template"]["gpio03"],@["user_template"]["gpio04"],@["user_template"]["gpio05"],@["user_template"]["gpio09"],@["user_template"]["gpio10"],@["user_template"]["gpio12"],@["user_template"]["gpio13"],@["user_template"]["gpio14"],@["user_template"]["gpio15"],@["user_template"]["gpio16"])')) ),
|
||||
'gpio01': ('B', 0x730, (None, None, ('Management', None)) ),
|
||||
'gpio02': ('B', 0x731, (None, None, ('Management', None)) ),
|
||||
'gpio03': ('B', 0x732, (None, None, ('Management', None)) ),
|
||||
'gpio04': ('B', 0x733, (None, None, ('Management', None)) ),
|
||||
'gpio05': ('B', 0x734, (None, None, ('Management', None)) ),
|
||||
'gpio09': ('B', 0x735, (None, None, ('Management', None)) ),
|
||||
'gpio10': ('B', 0x736, (None, None, ('Management', None)) ),
|
||||
'gpio12': ('B', 0x737, (None, None, ('Management', None)) ),
|
||||
'gpio13': ('B', 0x738, (None, None, ('Management', None)) ),
|
||||
'gpio14': ('B', 0x739, (None, None, ('Management', None)) ),
|
||||
'gpio15': ('B', 0x73A, (None, None, ('Management', None)) ),
|
||||
'gpio16': ('B', 0x73B, (None, None, ('Management', None)) ),
|
||||
'flag': ({
|
||||
'value': ('B', 0x73C , (None, None, ('Management', '"Template {{\\\"FLAG\\\":{}}}".format($)')) ),
|
||||
'adc0': ('B', (0x73C,1,0), (None, None, ('Management', None)) ),
|
||||
'pullup': ('B', (0x73C,1,1), (None, None, ('Management', None)) ),
|
||||
}, 0x73C, (None, None, ('Management', None))
|
||||
),
|
||||
}, 0x720, (None, None, ('Management', None))
|
||||
),
|
||||
})
|
||||
# ======================================================================
|
||||
Setting_6_4_1_17 = copy.deepcopy(Setting_6_4_1_16)
|
||||
Setting_6_4_1_17['flag3'][0].pop('no_pullup',None)
|
||||
# ======================================================================
|
||||
Settings = [
|
||||
(0x6040111, 0xe00, Setting_6_4_1_17),
|
||||
(0x6040110, 0xe00, Setting_6_4_1_16),
|
||||
(0x604010D, 0xe00, Setting_6_4_1_13),
|
||||
(0x604010B, 0xe00, Setting_6_4_1_11),
|
||||
(0x6040108, 0xe00, Setting_6_4_1_8),
|
||||
|
@ -2850,4 +2882,4 @@ if __name__ == "__main__":
|
|||
tasmotacmnds = Mapping2Cmnd(decode_cfg, configmapping)
|
||||
OutputTasmotaCmnds(tasmotacmnds)
|
||||
|
||||
sys.exit(exitcode)
|
||||
sys.exit(exitcode)
|
||||
|
|
Loading…
Reference in New Issue