From f2db069e39193e8ce006e4f7baffd1f17f81c4fc Mon Sep 17 00:00:00 2001 From: Hans-Rune Bue Date: Tue, 27 Aug 2024 21:24:11 +0200 Subject: [PATCH 01/23] Initial ESPeasy tools add --- tools/ESPEasy-tools.md | 158 +++++++++++++++++++++++++++++++++++ tools/espeasybackup | 183 +++++++++++++++++++++++++++++++++++++++++ tools/espeasyconfig | 71 ++++++++++++++++ tools/espeasyupdate | 53 ++++++++++++ 4 files changed, 465 insertions(+) create mode 100644 tools/ESPEasy-tools.md create mode 100755 tools/espeasybackup create mode 100755 tools/espeasyconfig create mode 100755 tools/espeasyupdate diff --git a/tools/ESPEasy-tools.md b/tools/ESPEasy-tools.md new file mode 100644 index 0000000000..54602e24c5 --- /dev/null +++ b/tools/ESPEasy-tools.md @@ -0,0 +1,158 @@ +|Latest Nightly | Build Status | Downloads | Docs | Patreon | Ko-Fi | PayPal | +|-------|-------|-------|-------|-------|-------|-------| +| [![GitHub version](https://img.shields.io/github/release/letscontrolit/ESPEasy/all.svg)](https://github.com/letscontrolit/ESPEasy/releases/latest) | ![Build status](https://github.com/letscontrolit/ESPEasy/actions/workflows/build.yml/badge.svg) | [![Downloads](https://img.shields.io/github/downloads/letscontrolit/ESPEasy/total.svg)](https://github.com/letscontrolit/ESPEasy/releases) | [![Documentation Status](https://readthedocs.org/projects/espeasy/badge/?version=latest)](https://espeasy.readthedocs.io/en/latest/?badge=latest) | [![donate](https://img.shields.io/badge/donate-Patreon-blue.svg)](https://www.patreon.com/GrovkillenTDer) | [![donate](https://img.shields.io/badge/donate-KoFi-blue.svg)](https://ko-fi.com/grovkillentder) | [![donate](https://img.shields.io/badge/donate-PayPal-blue.svg)](https://www.paypal.me/espeasy) | + +For ways to *support* us, see [this announcement on the forum](https://www.letscontrolit.com/forum/viewtopic.php?f=14&t=5787), or have a look at the [Patreon](https://www.patreon.com/GrovkillenTDer), [Ko-Fi](https://ko-fi.com/grovkillentder) or [PayPal](https://www.paypal.me/espeasy) links above. + +# ESPEasy (development branch) + + +Introduction https://espeasy.readthedocs.io/en/latest/ (and, mostly outdated, wiki: https://www.letscontrolit.com/wiki/index.php/ESPEasy#Introduction) + +**MEGA** +This is the development branch of ESPEasy. All new features go into this branch, and it has become the current stable branch. If you want to do a bugfix, do it on this branch. + + +Check here to learn how to use this branch and help us improving ESPEasy: [Starter guide for (local) development on ESPEasy](https://espeasy.readthedocs.io/en/latest/Participate/PlatformIO.html#starter-guide-for-local-development-on-espeasy) + +## Web based flasher (experimental) + +To make it easier to get started, one may flash a build directly to the ESP from your browser. +Currently only Chrome and Edge are supported. + +See [this flash page](https://td-er.nl/ESPEasy/) to try the new web flash feature. + +The web flasher is using [ESP Web Tools](https://esphome.github.io/esp-web-tools/) made by the people behind ESPHome and Home Assistant. + + +## Binary releases + +On demand, controlled by the repo owner, our build-bot will build a new binary release: https://github.com/letscontrolit/ESPEasy/releases + +The releases are named something like 'mega-20220626' (last number is the build date) + +Depending on your needs, we release different types of files: + +The name is built up from a few key parts: + +ESPEasy_mega\_*[releasedate]*\_*[build-type]*\_*[opt-arduino-library]*\_*[hardware-type]*\_*[flash-size][filesystem-size]*\_*[opt-build-features]*.bin + +*[build-type]* can be any of: +Build type | Description | included plugins | +-------------|-------------------------------------------|----------------------------------| +climate | All plugins related to climate measurement| Stable + Climate | +custom | Custom predefined set/Defined in Custom.h | Specific | +normal | Standard plugins | Stable | +collection_A | Normal + plugin collection A | Stable + Collection base + set A | +collection_B | Normal + plugin collection B | Stable + Collection base + set B | +collection_C | Normal + plugin collection C | Stable + Collection base + set C | +collection_D | Normal + plugin collection D | Stable + Collection base + set D | +collection_E | Normal + plugin collection E | Stable + Collection base + set E | +collection_F | Normal + plugin collection F | Stable + Collection base + set F | +collection_G | Normal + plugin collection G | Stable + Collection base + set G | +max | All available plugins | All available | +energy | All plugins related to energy measurement | Stable + Energy measurement | +display | All plugins related to displays | Stable + Displays | +neopixel | All plugins related to neopixel | Stable + Neopixel | +hard | hardware specific builds | Minimal | +minimal | minimal plugins for specific use-cases | Switch and Controller | +spec_* | specialized technical builds | Not intended for regular use | +IRext | Infra-red hardware specific | Sending and receiving IR cmd | +safeboot | (Experimental) `safeboot` build to enable
most/all plugins on 4MB Flash boards | None | + + +*[opt-arduino-library]* (optional) can be any of: +Arduino library | Description | +----------------|------------------------------------| +alt_wifi | Alternative WiFi configuration | +beta | Arduino Beta release | +sdk3 | Arduino SDK v.3 | +core_274 | Arduino Core 2.7.4 release | +core_302 | Arduino Core 3.0.2 release | +core_274_sdk3 | Arduino Core 2.7.4 SDK v.3 release | + + +*[hardware-type]* can be any of: +Hardware type | Description | +-----------------|---------------------------------------------| +ESP8266 | Espressif ESP8266/ESP8285 generic boards | +WROOM02 | Espressif ESP8266 WRoom02 boards | +ESP32 | Espressif ESP32 generic boards | +ESP32solo1 | Espressif ESP32-Solo1 generic boards | +ESP32s2 | Espressif ESP32-S2 generic boards | +ESP32c3 | Espressif ESP32-C3 generic boards | +ESP32s3 | Espressif ESP32-S3 generic boards | +ESP32c2 | Espressif ESP32-C2 generic boards | +ESP32c6 | Espressif ESP32-C6 generic boards | +ESP32-wrover-kit | Espressif ESP32 wrover-kit boards | +SONOFF | Sonoff hardware specific | +other_POW | Switch with power measurement | +Shelly_1 | Shelly 1 switch | +Shelly_PLUG_S | Shelly plug S switch with power measurement | +Ventus | Ventus W266 weather station | +LCtech_relay | LC-tech serial switch | + +N.B. Starting 2022/07/23, 1M ESP8266 builds can also be used on ESP8285 units and thus there is no longer a specific ESP8285 build anymore. + + +*[flash-size]* can be any of: +Flash size | Description | +-----------|-----------------------------| +1M | 1 MB with 128 kB filesystem | +2M | 2 MB with 128 kB filesystem | +2M256 | 2 MB with 256 kB filesystem | +2M320k | 2 MB with 320 kB filesystem | +4M1M | 4 MB with 1 MB filesystem | +4M2M | 4 MB with 2 MB filesystem | +16M | 16 MB with 14 MB filesystem | +4M316k | 4 MB with 316 kB filesystem | +8M1M | 8 MB with 1 MB filesystem | +16M1M | 16 MB with 1 MB filesystem | +16M8M | 16 MB with 8 MB filesystem | + +N.B. Starting with release 2023/12/25, All ESP32 LittleFS builds use IDF 5.1, to support newer ESP32 chips like ESP32-C2 and ESP32-C6. Other SPIFFS based ESP32 builds will be migrated to LittleFS as SPIFFS is no longer available in IDF 5 and later. A migration plan will be made available in 2024. + +*[opt-build-features]* can be any of: +Build features | Description | +----------------|-----------------------------------------------------------------------------------------------------------| +LittleFS | Use LittleFS instead of SPIFFS filesystem (SPIFFS is unstable \> 2 MB, and no longer supported in IDF \> 5) | +VCC | Analog input configured to measure VCC voltage (ESP8266 only) | +OTA | Arduino OTA (Over The Air) update feature enabled | +Domoticz | Only Domoticz controllers (HTTP) and plugins included | +Domoticz_MQTT | Only Domoticz controllers (MQTT) and plugins included | +FHEM_HA | Only FHEM/OpenHAB/Home Assistant (MQTT) controllers and plugins included | +ETH | Ethernet interface enabled (ESP32-classic only) | +OPI_PSRAM | Specific configuration to enable PSRAM detection, ESP32-S3 only | +CDC | Support USBCDC/HWCDC-serial console on ESP32-C3, ESP32-S2, ESP32-S3 and ESP32-C6 | +noOTA/NO_OTA | Does not support OTA (Over The Air-updating of the firmware) Use [the flash page](https://td-er.nl/ESPEasy/) or ESPTool via USB Serial | + +Some example firmware names: +Firmware name | Hardware | Included plugins | +------------------------------------------------------------------|---------------------------------------|----------------------------------| +ESPEasy_mega-20230822_normal_ESP8266_1M.bin | ESP8266/ESP8285 with 1MB flash | Stable | +ESPEasy_mega-20230822_normal_ESP8266_4M1M.bin | ESP8266 with 4MB flash | Stable | +ESPEasy_mega-20230822_collection_A_ESP8266_4M1M.bin | ESP8266 with 4MB flash | Stable + Collection base + set A | +ESPEasy_mega-20230822_normal_ESP32_4M316k.bin | ESP32 with 4MB flash | Stable | +ESPEasy_mega-20230822_collection_A_ESP32_4M316k.bin | ESP32 with 4MB flash | Stable + Collection base + set A | +ESPEasy_mega-20230822_collection_B_ESP32_4M316k.bin | ESP32 with 4MB flash | Stable + Collection base + set B | +ESPEasy_mega-20230822_max_ESP32s3_8M1M_LittleFS_CDC.bin | ESP32-S3 with 8MB flash, CDC-serial | All available plugins | +ESPEasy_mega-20230822_max_ESP32s3_8M1M_LittleFS_OPI_PSRAM_CDC.bin | ESP32-S3 8MB flash, PSRAM, CDC-serial | All available plugins | +ESPEasy_mega-20230822_max_ESP32_16M1M.bin | ESP32 with 16MB flash | All available plugins | +ESPEasy_mega-20230822_max_ESP32_16M8M_LittleFS.bin | ESP32 with 16MB flash | All available plugins | + +The binary files for the different ESP32 variants (S2, C3, S3, C2, C6, 'Classic') are available in separate archives. + +To see what plugins are included in which collection set, you can find that on the [ESPEasy Plugin overview page](https://espeasy.readthedocs.io/en/latest/Plugin/_Plugin.html) + +## Documentation & more info + +Our new, in-depth documentation can be found at [ESPEasy.readthedocs.io](https://espeasy.readthedocs.io/en/latest/). Automatically built, so always up-to-date according to the contributed contents. The old Wiki documentation can be found at [letscontrolit.com/wiki](https://www.letscontrolit.com/wiki/index.php?title=ESPEasy). + +Additional details and discussion are on the "Experimental" section of the forum: https://www.letscontrolit.com/forum/viewforum.php?f=18 + +[![Gitpod Ready-to-Code](https://img.shields.io/badge/Gitpod-Ready--to--Code-blue?logo=gitpod)](https://gitpod.io/#https://github.com/letscontrolit/ESPEasy) + + +## Icons used + +Icons on courtesy of [ICONS8](https://icons8.com/). diff --git a/tools/espeasybackup b/tools/espeasybackup new file mode 100755 index 0000000000..d781935f00 --- /dev/null +++ b/tools/espeasybackup @@ -0,0 +1,183 @@ +#!/bin/bash +PROG=$( basename $0 ) +DATETIME=$( date "+%Y%m%d-%H%M%S-" ) +PREREQS="curl jq" +MAXTIME=30 +JSONTIME=6 +HWPROVIDERRE="5c:cf:7f:|18:fe:34:|60:01:94:|a0:20:a6:|b4:e6:2d:|68:c6:3a:" + +IPLIST=() + +function dbgprint { + [[ -n "${DBGPRINT}" ]] && echo "$PROG debug: $*" >&2 +} + +function peerlist { + local H="$1" + local O="${DATETIME}${H}.json" + + if [[ -s "${O}" ]] + then + dbgprint "PROG: Reading json file from $O ..." + else + dbgprint "PROG: Downloading json file from $H ..." + curl -s -m ${JSONTIME} "http://${H}/json" > "${O}" + fi + if [[ -s "${O}" ]] + then + jq '.nodes[]|{ IPaddr: .ip}' "${O}" | tr -d '"' | awk '{ if ( $1 == "IPaddr:" ) print $2 }' + else + rm "${O}" + echo "$PROG: Warning: Empty response from http://${H}/json" >&2 + fi +} + +function collectip { + local H="$1" + local IP I NIDX + for IP in $( peerlist ${H} ) + do + NIDX=${#IPLIST[*]} + for ((I=0; I < ${NIDX}; I++)) + do + [[ ${IPLIST[$I]} == ${IP} ]] && break + done + # if we made it to end of list without matches + if [[ ${I} == ${NIDX} ]] + then + IPLIST[$NIDX]="${IP}" + dbgprint "Found new $IP (index $NIDX ) ..." + fi + done +} + + +if [[ "$1" == "-h" ]] || [[ -z "$1" ]] +then + echo "Usage: $PROG [-a][-z zipfilefullpath|-Z] IPorHostname ..." >&2 + exit 1 +fi + +# +# put CURLARGS='-u username:password' in ~/.espeasy , then chmod 600 ~/.espeasy +# +if [[ -r "${HOME}/.espeasy" ]] +then + dbgprint "PROG: sourcing ${HOME}/.espeasy" + source "${HOME}/.espeasy" +else + echo "$PROG: Cannot read ${HOME}/.espeasy" >&2 + exit 1 +fi + + +if [[ "$1" == "-a" ]] +then + shift + ARPADDR=$( /usr/sbin/arp -an | awk "/${HWPROVIDERRE}/ { print \$2 }" | tr -d '()' | tr '\n' ' ' ) + dbgprint "PROG: arp address list: $ARPADDR" +fi + +if [[ "$1" == "-z" ]] +then + ZIP="$2" ; shift ; shift + DATETIME="" + PREPREQS="${PREREQS} zip" + mkdir "/tmp/${PROG}-$$" && cd "/tmp/${PROG}-$$" +elif [[ "$1" == "-Z" ]] +then + shift + ZIP="/tmp/config-$(hostname -s)-$( date +%F )" + DATETIME="" + PREPREQS="${PREREQS} zip" + mkdir "/tmp/${PROG}-$$" && cd "/tmp/${PROG}-$$" +fi + +[[ -n "${MAILTO}" ]] && PREPREQS="${PREREQS} mail" + +for CMD in ${PREREQS} +do + type $CMD > /dev/null 2>&1 && continue + echo "$PROG: Please install all prereqs: ${PREREQS}" + exit 2 +done + + +if [[ $# -gt 1 ]] || [[ -n "${ARPADDR}" ]] +then + echo "$PROG: Initial list $* $ARPADDR ..." + for H in $* ${ARPADDR} + do + collectip "${H}" + done + + echo "$PROG: Secondary list: ${IPLIST[*]} ..." + for H in ${IPLIST} + do + collectip "${H}" + done + +else + collectip "$1" + IPLIST=( $1 ) +fi + +echo "PROG: Backup list has ${#IPLIST[*]} nodes: ${IPLIST[*]} " + +for H in ${IPLIST[*]} +do + O="${DATETIME}${H}.json" + + if [[ ! -s "${O}" ]] + then + dbgprint "PROG: Downloading missing json file from $H ..." + curl -s -m ${JSONTIME} "http://${H}/json" > "${O}" + fi + + NAME=$( jq '.WiFi.Hostname' "${O}" | tr -d '"') + NAME="${NAME:-$H}" + for F in config.dat security.dat notification.dat rules1.txt rules2.txt rules3.txt rules4.txt esp.css + do + O="${DATETIME}${NAME}-${F}" + echo -n "$PROG: Backup $H $F --> ${O} ..." + curl -s -m ${MAXTIME} ${CURLARGS} "http://${H}/${F}" > "${O}" + if [[ -s "${O}" ]] + then + if grep -q "URI: /${F}" "${O}" + then + echo "Header only - removed" + rm "${O}" + else + echo " OK" + fi + else + echo "empty - removed" + rm "${O}" + fi + done + # + # We're done with this IP address. Rename to hostname if relevant ... + # + [[ ${NAME} != ${H} ]] && mv "${DATETIME}${H}.json" "${DATETIME}${NAME}.json" +done + +if [[ -n "${ZIP}" ]] +then + echo "$PROG: Sending ZIP file $ZIP to $MAILTO ..." + dbgprint "PROG: Creating zip-file ${ZIP}.zip from ${PWD}" + zip -rq9 "${ZIP}" . + NFILES=$( ls -1 | wc -l ) + cd "${HOME}" + rm -rf "/tmp/${PROG}-$$" + if [[ -n "${MAILTO}" ]] + then + dbgprint "Email to ${MAILTO}" + SUB="$PROG backup from $( hostname -s ) on $( date +%F ) (${#IPLIST[*]} nodes, ${NFILES} files)" + #mpack -s "${SUB}" "${ZIP}.zip" ${MAILTO} + echo -e "Backup file attached from ${#IPLIST[*]} nodes, total of ${NFILES} files\n\n" | \ + mail -s "${SUB}" --content-type=application/zip -A "${ZIP}.zip" ${MAILTO} + fi +fi + +# :tabSize=4:indentSize=4:noTabs=true +# vim:ts=4:sw=4 diff --git a/tools/espeasyconfig b/tools/espeasyconfig new file mode 100755 index 0000000000..d58f4b8e49 --- /dev/null +++ b/tools/espeasyconfig @@ -0,0 +1,71 @@ +#!/bin/bash +PROG=$( basename $0 .sh ) +TMP="/tmp/${PROG}-$$/" + +[[ "$1" == "-r" ]] && REBOOTESP="Y" && shift +H="$1"; shift +FILE="$1" + +if [[ $# -lt 1 ]] || [[ ! -r "${FILE}" ]] +then + echo "Usage: $PROG [-r] NameOrIP file [ file ... ]" >&2 + exit 2 +fi + +# +# put CURLARGS='-u username:password' in ~/.espeasy +# +if [[ -r "${HOME}/.espeasy" ]] +then + source "${HOME}/.espeasy" +else + echo "$PROG: Cannot read ${HOME}/.espeasy" >&2 + exit 1 +fi + +mkdir "${TMP}" || exit 2 + +for FILE in $* +do + for NAME in notification.dat security.dat config.dat rules1.txt rules2.txt rules3.txt rules4.txt esp.css + do + if [[ ${FILE} =~ "${NAME}" ]] + then + MATCH="${NAME}" + echo -n "$PROG: File name ${NAME}: " + cp -v "${FILE}" "${TMP}/${MATCH}" + break; + fi + done + [[ -z "${MATCH}" ]] && echo "$PROG: Cannot determine name of $FILE ... Skipping" +done + +cd "${TMP}" || exit 2 + +for FILE in * +do + echo -n "Upload $FILE: " + if curl ${CURLARGS} --progress-bar -X POST -F "name=@${FILE}" -F "type=file" "http://${H}/upload" | grep -q "Upload OK" + then + echo "$PROG: $FILE upload OK " + else + echo "$PROG: $FILE upload FAILED" >&2 + fi +done +if [[ -n "${REBOOTESP}" ]] +then + echo -n "Reboot: " + if curl ${CURLARGS} --progress-bar "http://${H}/?cmd=reboot" | grep -q '>OK' + then + echo "$PROG: Reboot OK " + else + echo "$PROG: Reboot FAILED" >&2 + fi +fi +cd +#echo "$PROG: Please do a manual rm -rf $TMP" + +rm -rf "${TMP}" + +# vim:ts=4:sw=4 + diff --git a/tools/espeasyupdate b/tools/espeasyupdate new file mode 100755 index 0000000000..55824a5d0e --- /dev/null +++ b/tools/espeasyupdate @@ -0,0 +1,53 @@ +#!/bin/bash +PROG=$( basename $0 .sh ) + +[[ "$1" == "-f" ]] && FORCEUPDATE=1 && shift +[[ "$1" == "-n" ]] && NOUPDATE=1 && shift +[[ "$1" == "-f" ]] && FORCEUPDATE=1 && shift + +FILE="$1" +FILEFW=$( echo ${FILE%.bi*} | sed 's/_20[[:digit:]]*//' ) +FILEFW=$( basename ${FILEFW} ) + +if [[ $# -lt 1 ]] || [[ ! -r "${FILE}" ]] +then + echo "Usage: $PROG [-n|-f] filename NameOrIP [ NameOrIP ... ]" >&2 + exit 2 +fi +shift + +# +# put CURLARGS='-u username:password' in ~/.espeasy - file readable only by user +# +if [[ -r "${HOME}/.espeasy" ]] +then + source "${HOME}/.espeasy" +fi + +for H in $* +do + echo "$PROG: Updating $H ..." + VER=$( curl -s "http://${H}/json"| jq -r '.System."Git Build"' ) + if [[ "${VER#Custom}" != "${VER}" ]] + then + if strings "${FILE}" | grep -q "^${VER}" + then + echo "$PROG: ${H} already has '${VER}'" + [ -z "${FORCEUPDATE}" ] && continue + fi + fi + DEVFW=$( curl -s "http://${H}/json"| jq -r '.System."Binary Filename"' ) + [[ -n "${DEVFW}" ]] && DEVFW=$( sed 's/_20[[:digit:]]*//' <<< ${DEVFW} ) + if [[ "${DEVFW}" != "${FILEFW}" ]] + then + echo "$PROG: Firmware on file (${FILEFW}) different from device (${DEVFW}). Use -f to force update." + [ -z "${FORCEUPDATE}" ] && continue + fi + if [ -n "${NOUPDATE}" ] + then + echo "curl ${CURLARGS} -X POST -F \"name=@${FILE}\" -F \"value=Update\" \"http://${H}/update\"" + continue + fi + curl ${CURLARGS} -X POST -F "name=@${FILE}" -F "value=Update" "http://${H}/update" +done +# vim:ts=4:sw=4 From 17a6add596e7bcf7ac9eb8bba0640cb915c36ed7 Mon Sep 17 00:00:00 2001 From: Hans-Rune Bue Date: Tue, 27 Aug 2024 21:28:41 +0200 Subject: [PATCH 02/23] ESPeasy tools readme --- tools/ESPEasy-tools.md | 300 ++++++++++++++++++++--------------------- 1 file changed, 146 insertions(+), 154 deletions(-) diff --git a/tools/ESPEasy-tools.md b/tools/ESPEasy-tools.md index 54602e24c5..49d72420fa 100644 --- a/tools/ESPEasy-tools.md +++ b/tools/ESPEasy-tools.md @@ -1,158 +1,150 @@ -|Latest Nightly | Build Status | Downloads | Docs | Patreon | Ko-Fi | PayPal | -|-------|-------|-------|-------|-------|-------|-------| -| [![GitHub version](https://img.shields.io/github/release/letscontrolit/ESPEasy/all.svg)](https://github.com/letscontrolit/ESPEasy/releases/latest) | ![Build status](https://github.com/letscontrolit/ESPEasy/actions/workflows/build.yml/badge.svg) | [![Downloads](https://img.shields.io/github/downloads/letscontrolit/ESPEasy/total.svg)](https://github.com/letscontrolit/ESPEasy/releases) | [![Documentation Status](https://readthedocs.org/projects/espeasy/badge/?version=latest)](https://espeasy.readthedocs.io/en/latest/?badge=latest) | [![donate](https://img.shields.io/badge/donate-Patreon-blue.svg)](https://www.patreon.com/GrovkillenTDer) | [![donate](https://img.shields.io/badge/donate-KoFi-blue.svg)](https://ko-fi.com/grovkillentder) | [![donate](https://img.shields.io/badge/donate-PayPal-blue.svg)](https://www.paypal.me/espeasy) | -For ways to *support* us, see [this announcement on the forum](https://www.letscontrolit.com/forum/viewtopic.php?f=14&t=5787), or have a look at the [Patreon](https://www.patreon.com/GrovkillenTDer), [Ko-Fi](https://ko-fi.com/grovkillentder) or [PayPal](https://www.paypal.me/espeasy) links above. +# ESPEasy tools -# ESPEasy (development branch) - - -Introduction https://espeasy.readthedocs.io/en/latest/ (and, mostly outdated, wiki: https://www.letscontrolit.com/wiki/index.php/ESPEasy#Introduction) - -**MEGA** -This is the development branch of ESPEasy. All new features go into this branch, and it has become the current stable branch. If you want to do a bugfix, do it on this branch. +This is a set of simple but powerful command line tools for scripting updates, and for backup and restore of configuration settings and ESPeasy rule files +Be careful not to use these tools in a multiuser environment as the login password may display with something like `ps f -ef` -Check here to learn how to use this branch and help us improving ESPEasy: [Starter guide for (local) development on ESPEasy](https://espeasy.readthedocs.io/en/latest/Participate/PlatformIO.html#starter-guide-for-local-development-on-espeasy) - -## Web based flasher (experimental) - -To make it easier to get started, one may flash a build directly to the ESP from your browser. -Currently only Chrome and Edge are supported. - -See [this flash page](https://td-er.nl/ESPEasy/) to try the new web flash feature. - -The web flasher is using [ESP Web Tools](https://esphome.github.io/esp-web-tools/) made by the people behind ESPHome and Home Assistant. - - -## Binary releases - -On demand, controlled by the repo owner, our build-bot will build a new binary release: https://github.com/letscontrolit/ESPEasy/releases - -The releases are named something like 'mega-20220626' (last number is the build date) - -Depending on your needs, we release different types of files: - -The name is built up from a few key parts: - -ESPEasy_mega\_*[releasedate]*\_*[build-type]*\_*[opt-arduino-library]*\_*[hardware-type]*\_*[flash-size][filesystem-size]*\_*[opt-build-features]*.bin - -*[build-type]* can be any of: -Build type | Description | included plugins | --------------|-------------------------------------------|----------------------------------| -climate | All plugins related to climate measurement| Stable + Climate | -custom | Custom predefined set/Defined in Custom.h | Specific | -normal | Standard plugins | Stable | -collection_A | Normal + plugin collection A | Stable + Collection base + set A | -collection_B | Normal + plugin collection B | Stable + Collection base + set B | -collection_C | Normal + plugin collection C | Stable + Collection base + set C | -collection_D | Normal + plugin collection D | Stable + Collection base + set D | -collection_E | Normal + plugin collection E | Stable + Collection base + set E | -collection_F | Normal + plugin collection F | Stable + Collection base + set F | -collection_G | Normal + plugin collection G | Stable + Collection base + set G | -max | All available plugins | All available | -energy | All plugins related to energy measurement | Stable + Energy measurement | -display | All plugins related to displays | Stable + Displays | -neopixel | All plugins related to neopixel | Stable + Neopixel | -hard | hardware specific builds | Minimal | -minimal | minimal plugins for specific use-cases | Switch and Controller | -spec_* | specialized technical builds | Not intended for regular use | -IRext | Infra-red hardware specific | Sending and receiving IR cmd | -safeboot | (Experimental) `safeboot` build to enable
most/all plugins on 4MB Flash boards | None | - - -*[opt-arduino-library]* (optional) can be any of: -Arduino library | Description | -----------------|------------------------------------| -alt_wifi | Alternative WiFi configuration | -beta | Arduino Beta release | -sdk3 | Arduino SDK v.3 | -core_274 | Arduino Core 2.7.4 release | -core_302 | Arduino Core 3.0.2 release | -core_274_sdk3 | Arduino Core 2.7.4 SDK v.3 release | - - -*[hardware-type]* can be any of: -Hardware type | Description | ------------------|---------------------------------------------| -ESP8266 | Espressif ESP8266/ESP8285 generic boards | -WROOM02 | Espressif ESP8266 WRoom02 boards | -ESP32 | Espressif ESP32 generic boards | -ESP32solo1 | Espressif ESP32-Solo1 generic boards | -ESP32s2 | Espressif ESP32-S2 generic boards | -ESP32c3 | Espressif ESP32-C3 generic boards | -ESP32s3 | Espressif ESP32-S3 generic boards | -ESP32c2 | Espressif ESP32-C2 generic boards | -ESP32c6 | Espressif ESP32-C6 generic boards | -ESP32-wrover-kit | Espressif ESP32 wrover-kit boards | -SONOFF | Sonoff hardware specific | -other_POW | Switch with power measurement | -Shelly_1 | Shelly 1 switch | -Shelly_PLUG_S | Shelly plug S switch with power measurement | -Ventus | Ventus W266 weather station | -LCtech_relay | LC-tech serial switch | - -N.B. Starting 2022/07/23, 1M ESP8266 builds can also be used on ESP8285 units and thus there is no longer a specific ESP8285 build anymore. - - -*[flash-size]* can be any of: -Flash size | Description | ------------|-----------------------------| -1M | 1 MB with 128 kB filesystem | -2M | 2 MB with 128 kB filesystem | -2M256 | 2 MB with 256 kB filesystem | -2M320k | 2 MB with 320 kB filesystem | -4M1M | 4 MB with 1 MB filesystem | -4M2M | 4 MB with 2 MB filesystem | -16M | 16 MB with 14 MB filesystem | -4M316k | 4 MB with 316 kB filesystem | -8M1M | 8 MB with 1 MB filesystem | -16M1M | 16 MB with 1 MB filesystem | -16M8M | 16 MB with 8 MB filesystem | - -N.B. Starting with release 2023/12/25, All ESP32 LittleFS builds use IDF 5.1, to support newer ESP32 chips like ESP32-C2 and ESP32-C6. Other SPIFFS based ESP32 builds will be migrated to LittleFS as SPIFFS is no longer available in IDF 5 and later. A migration plan will be made available in 2024. - -*[opt-build-features]* can be any of: -Build features | Description | -----------------|-----------------------------------------------------------------------------------------------------------| -LittleFS | Use LittleFS instead of SPIFFS filesystem (SPIFFS is unstable \> 2 MB, and no longer supported in IDF \> 5) | -VCC | Analog input configured to measure VCC voltage (ESP8266 only) | -OTA | Arduino OTA (Over The Air) update feature enabled | -Domoticz | Only Domoticz controllers (HTTP) and plugins included | -Domoticz_MQTT | Only Domoticz controllers (MQTT) and plugins included | -FHEM_HA | Only FHEM/OpenHAB/Home Assistant (MQTT) controllers and plugins included | -ETH | Ethernet interface enabled (ESP32-classic only) | -OPI_PSRAM | Specific configuration to enable PSRAM detection, ESP32-S3 only | -CDC | Support USBCDC/HWCDC-serial console on ESP32-C3, ESP32-S2, ESP32-S3 and ESP32-C6 | -noOTA/NO_OTA | Does not support OTA (Over The Air-updating of the firmware) Use [the flash page](https://td-er.nl/ESPEasy/) or ESPTool via USB Serial | - -Some example firmware names: -Firmware name | Hardware | Included plugins | -------------------------------------------------------------------|---------------------------------------|----------------------------------| -ESPEasy_mega-20230822_normal_ESP8266_1M.bin | ESP8266/ESP8285 with 1MB flash | Stable | -ESPEasy_mega-20230822_normal_ESP8266_4M1M.bin | ESP8266 with 4MB flash | Stable | -ESPEasy_mega-20230822_collection_A_ESP8266_4M1M.bin | ESP8266 with 4MB flash | Stable + Collection base + set A | -ESPEasy_mega-20230822_normal_ESP32_4M316k.bin | ESP32 with 4MB flash | Stable | -ESPEasy_mega-20230822_collection_A_ESP32_4M316k.bin | ESP32 with 4MB flash | Stable + Collection base + set A | -ESPEasy_mega-20230822_collection_B_ESP32_4M316k.bin | ESP32 with 4MB flash | Stable + Collection base + set B | -ESPEasy_mega-20230822_max_ESP32s3_8M1M_LittleFS_CDC.bin | ESP32-S3 with 8MB flash, CDC-serial | All available plugins | -ESPEasy_mega-20230822_max_ESP32s3_8M1M_LittleFS_OPI_PSRAM_CDC.bin | ESP32-S3 8MB flash, PSRAM, CDC-serial | All available plugins | -ESPEasy_mega-20230822_max_ESP32_16M1M.bin | ESP32 with 16MB flash | All available plugins | -ESPEasy_mega-20230822_max_ESP32_16M8M_LittleFS.bin | ESP32 with 16MB flash | All available plugins | - -The binary files for the different ESP32 variants (S2, C3, S3, C2, C6, 'Classic') are available in separate archives. - -To see what plugins are included in which collection set, you can find that on the [ESPEasy Plugin overview page](https://espeasy.readthedocs.io/en/latest/Plugin/_Plugin.html) - -## Documentation & more info - -Our new, in-depth documentation can be found at [ESPEasy.readthedocs.io](https://espeasy.readthedocs.io/en/latest/). Automatically built, so always up-to-date according to the contributed contents. The old Wiki documentation can be found at [letscontrolit.com/wiki](https://www.letscontrolit.com/wiki/index.php?title=ESPEasy). - -Additional details and discussion are on the "Experimental" section of the forum: https://www.letscontrolit.com/forum/viewforum.php?f=18 - -[![Gitpod Ready-to-Code](https://img.shields.io/badge/Gitpod-Ready--to--Code-blue?logo=gitpod)](https://gitpod.io/#https://github.com/letscontrolit/ESPEasy) - - -## Icons used - -Icons on courtesy of [ICONS8](https://icons8.com/). + +## Installation and setup + +### Prereqs + +You will need: + +- `curl`, `jq` and `gzip` must be available +- A working `mail` command is needed if you want backups sent somewhere else by email + +### Copy scripts + +The `espeasy*` scripts will normally be copied somewhere in your `$PATH`, for example: + +```bash +chmod a+rx espeasy* +cp -v espeasy* /usr/local/bin/ +``` + +### Credentials + +You will need to set up a `$HOME/.espeasy` file as follows: + +```bash +# +# espeasy logins +# +CURLFLAGS="" +CURLARGS=${CURLARGS:-"$CURLFLAGS -u admin:password"} # change password to yours +``` + +Then make sure this file is readable by your user only (`chmod 600 $HOME/.espeasy`) + + +## Backup / restore + +### Single device + +ESP device backup for a single device can be done to your current directory as follows: + +```bash +$ espeasybackup 192.168.202.62 +PROG: Backup list has 1 nodes: 192.168.202.62 +espeasybackup: Backup 192.168.202.62 config.dat --> 20240827-205701-MitsubishiIR-12-config.dat ... OK +espeasybackup: Backup 192.168.202.62 security.dat --> 20240827-205701-MitsubishiIR-12-security.dat ... OK +espeasybackup: Backup 192.168.202.62 notification.dat --> 20240827-205701-MitsubishiIR-12-notification.dat ... OK +espeasybackup: Backup 192.168.202.62 rules1.txt --> 20240827-205701-MitsubishiIR-12-rules1.txt ... OK +espeasybackup: Backup 192.168.202.62 rules2.txt --> 20240827-205701-MitsubishiIR-12-rules2.txt ... OK +espeasybackup: Backup 192.168.202.62 rules3.txt --> 20240827-205701-MitsubishiIR-12-rules3.txt ... OK +espeasybackup: Backup 192.168.202.62 rules4.txt --> 20240827-205701-MitsubishiIR-12-rules4.txt ... OK +espeasybackup: Backup 192.168.202.62 esp.css --> 20240827-205701-MitsubishiIR-12-esp.css ... OK +``` + +... and restored as follows: + +```bash +$ rm *.css # sometimes causes problems +$ espeasyconfig 192.168.202.62 20240827-205701-MitsubishiIR-12* +espeasyconfig: File name config.dat: '20240827-205701-MitsubishiIR-12-config.dat' -> '/tmp/espeasyconfig-1185//config.dat' +espeasyconfig: File name notification.dat: '20240827-205701-MitsubishiIR-12-notification.dat' -> '/tmp/espeasyconfig-1185//notification.dat' +espeasyconfig: File name rules1.txt: '20240827-205701-MitsubishiIR-12-rules1.txt' -> '/tmp/espeasyconfig-1185//rules1.txt' +espeasyconfig: File name rules2.txt: '20240827-205701-MitsubishiIR-12-rules2.txt' -> '/tmp/espeasyconfig-1185//rules2.txt' +espeasyconfig: File name rules3.txt: '20240827-205701-MitsubishiIR-12-rules3.txt' -> '/tmp/espeasyconfig-1185//rules3.txt' +espeasyconfig: File name rules4.txt: '20240827-205701-MitsubishiIR-12-rules4.txt' -> '/tmp/espeasyconfig-1185//rules4.txt' +espeasyconfig: File name security.dat: '20240827-205701-MitsubishiIR-12-security.dat' -> '/tmp/espeasyconfig-1185//security.dat' +Upload config.dat: ########### 100.0% +espeasyconfig: config.dat upload OK +########### 100.0% +espeasyconfig: notification.dat upload OK +########### 100.0% +espeasyconfig: rules1.txt upload OK +########### 100.0% +espeasyconfig: rules2.txt upload OK +########### 100.0% +espeasyconfig: rules3.txt upload OK +########### 100.0% +espeasyconfig: rules4.txt upload OK +########### 100.0% +espeasyconfig: security.dat upload OK +``` + +The restore destination must be same ESP device type + +### Multiple devices + +If you add the `-a` option, the peer device list will be used to find your ESP devices, and also add any well known ESP MAC addresses found in the local arp table (`arp -a`) + + +```bash +$ espeasybackup -a 192.168.202.62 +espeasybackup: Initial list 192.168.202.62 192.168.202.63 ... +espeasybackup: Secondary list: 192.168.202.242 192.168.202.52 192.168.202.61 192.168.202.62 192.168.202.63 192.168.202.65 192.168.202.66 192.168.202.67 ... +PROG: Backup list has 8 nodes: 192.168.202.242 192.168.202.52 192.168.202.61 192.168.202.62 192.168.202.63 192.168.202.65 192.168.202.66 192.168.202.67 +espeasybackup: Backup 192.168.202.242 config.dat --> 20240827-210214-TestBallValve-2-config.dat ... OK +espeasybackup: Backup 192.168.202.242 security.dat --> 20240827-210214-TestBallValve-2-security.dat ... OK +espeasybackup: Backup 192.168.202.242 notification.dat --> 20240827-210214-TestBallValve-2-notification.dat ... OK +espeasybackup: Backup 192.168.202.242 rules1.txt --> 20240827-210214-TestBallValve-2-rules1.txt ... OK +espeasybackup: Backup 192.168.202.242 rules2.txt --> 20240827-210214-TestBallValve-2-rules2.txt ... OK +espeasybackup: Backup 192.168.202.242 rules3.txt --> 20240827-210214-TestBallValve-2-rules3.txt ... OK +espeasybackup: Backup 192.168.202.242 rules4.txt --> 20240827-210214-TestBallValve-2-rules4.txt ... OK +espeasybackup: Backup 192.168.202.62 config.dat --> 20240827-210214-MitsubishiIR-12-config.dat ... OK +espeasybackup: Backup 192.168.202.62 security.dat --> 20240827-210214-MitsubishiIR-12-security.dat ... OK +espeasybackup: Backup 192.168.202.62 notification.dat --> 20240827-210214-MitsubishiIR-12-notification.dat ... OK +espeasybackup: Backup 192.168.202.62 rules1.txt --> 20240827-210214-MitsubishiIR-12-rules1.txt ... OK +espeasybackup: Backup 192.168.202.62 rules2.txt --> 20240827-210214-MitsubishiIR-12-rules2.txt ... OK +espeasybackup: Backup 192.168.202.62 rules3.txt --> 20240827-210214-MitsubishiIR-12-rules3.txt ... OK +espeasybackup: Backup 192.168.202.62 rules4.txt --> 20240827-210214-MitsubishiIR-12-rules4.txt ... OK +espeasybackup: Backup 192.168.202.62 esp.css --> 20240827-210214-MitsubishiIR-12-esp.css ... OK +. +. +. +``` + +### cron jobs for backup + +You may want to back up your ESP devices regularly to a remote place. This is a way to find all ESP devices from the peer list of some og them (`-a` option), compress into a `.tar.gz` file (`-Z` option), and email that to a mail account (when `MAILTO` defined in the environment): + +```bash +20 06 * * 6 env MAILTO=admin@mydomain.net /usr/local/bin/espeasybackup -a -Z 192.168.202.52 192.168.202.62 192.168.202.64 > /tmp/espeasybackup.log 2>&1 +``` + + +## New firmware deployment + +To upload new firmware, you specify a firmware file and as many IP addresses / hostnames that you want to update with that same hardware + +```bash +$ espeasyupdate -f ESP_Easy_mega_20240826_IR_ESP32c3_4M316k_LittleFS_CDC.bin 192.168.202.242 +espeasyupdate: Updating 192.168.202.242 ... +espeasyupdate: 192.168.202.242 already has 'Custom IR for AC - 20240822-1' +espeasyupdate: Firmware on file (ESP_Easy_mega_IR_ESP32c3_4M316k_LittleFS_CDC) different from device (ESP_Easy_mega_public_IR_ESP32c3_4M316k_LittleFS_CDC). Use -f to force update. +Update Success! Rebooting... +``` + +The `-f` option is needed if you want to switch from one firmware file to another, or repeat a git build already deployed. + +This is tested as follows: + +```bash +# IP is hoatname or IP address +curl -s "http://${IP}/json"| jq -r '.System."Git Build"' # normally skipped if already deployed +curl -s "http://${IP}/json"| jq -r '.System."Binary Filename"' # normally skipped if binary file is different +``` From c657c1816e32a5a5fa6ed90655b7927ea37797ae Mon Sep 17 00:00:00 2001 From: Hans-Rune Bue Date: Tue, 27 Aug 2024 21:33:55 +0200 Subject: [PATCH 03/23] Missing $ in --- tools/ESPEasy-tools.md | 2 +- tools/espeasybackup | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/ESPEasy-tools.md b/tools/ESPEasy-tools.md index 49d72420fa..91a3bb728c 100644 --- a/tools/ESPEasy-tools.md +++ b/tools/ESPEasy-tools.md @@ -97,7 +97,7 @@ If you add the `-a` option, the peer device list will be used to find your ESP d $ espeasybackup -a 192.168.202.62 espeasybackup: Initial list 192.168.202.62 192.168.202.63 ... espeasybackup: Secondary list: 192.168.202.242 192.168.202.52 192.168.202.61 192.168.202.62 192.168.202.63 192.168.202.65 192.168.202.66 192.168.202.67 ... -PROG: Backup list has 8 nodes: 192.168.202.242 192.168.202.52 192.168.202.61 192.168.202.62 192.168.202.63 192.168.202.65 192.168.202.66 192.168.202.67 +espeasybackup: Backup list has 8 nodes: 192.168.202.242 192.168.202.52 192.168.202.61 192.168.202.62 192.168.202.63 192.168.202.65 192.168.202.66 192.168.202.67 espeasybackup: Backup 192.168.202.242 config.dat --> 20240827-210214-TestBallValve-2-config.dat ... OK espeasybackup: Backup 192.168.202.242 security.dat --> 20240827-210214-TestBallValve-2-security.dat ... OK espeasybackup: Backup 192.168.202.242 notification.dat --> 20240827-210214-TestBallValve-2-notification.dat ... OK diff --git a/tools/espeasybackup b/tools/espeasybackup index d781935f00..2cb8bb3891 100755 --- a/tools/espeasybackup +++ b/tools/espeasybackup @@ -122,7 +122,7 @@ else IPLIST=( $1 ) fi -echo "PROG: Backup list has ${#IPLIST[*]} nodes: ${IPLIST[*]} " +echo "$PROG: Backup list has ${#IPLIST[*]} nodes: ${IPLIST[*]} " for H in ${IPLIST[*]} do From e23df8129aa1702aa617e7087db95b69e284280b Mon Sep 17 00:00:00 2001 From: Hans-Rune Bue Date: Wed, 28 Aug 2024 07:41:09 +0200 Subject: [PATCH 04/23] Document enhancements on requirements, security + linting --- tools/ESPEasy-tools.md | 24 +++++++++++++++--------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/tools/ESPEasy-tools.md b/tools/ESPEasy-tools.md index 91a3bb728c..fbb1e44bb0 100644 --- a/tools/ESPEasy-tools.md +++ b/tools/ESPEasy-tools.md @@ -3,8 +3,13 @@ This is a set of simple but powerful command line tools for scripting updates, and for backup and restore of configuration settings and ESPeasy rule files -Be careful not to use these tools in a multiuser environment as the login password may display with something like `ps f -ef` +## Security +Some warnings apply: + +- Be careful not to use these tools in a multiuser environment. The ESPEasy device password may display with something like `ps f -ef` while commands are in progress. +- Protect your `$HOME/.espeasy` credential files as well as your home directory from access for other users. +- Make sure you have physical access / can powercycle your ESPEasy devices. In rare cases a power cycle is needed for updates to work, or if a formware upload does not complete ## Installation and setup @@ -12,6 +17,7 @@ Be careful not to use these tools in a multiuser environment as the login passwo You will need: +- A `bash` shell environment (Linux, MacOS, WSL does not really matter) - `curl`, `jq` and `gzip` must be available - A working `mail` command is needed if you want backups sent somewhere else by email @@ -20,13 +26,14 @@ You will need: The `espeasy*` scripts will normally be copied somewhere in your `$PATH`, for example: ```bash +cd tools chmod a+rx espeasy* -cp -v espeasy* /usr/local/bin/ +cp -v espeasy* /usr/local/bin/ # you may need sudo command in front ``` ### Credentials -You will need to set up a `$HOME/.espeasy` file as follows: +You will normally set up a `$HOME/.espeasy` file as follows for the ESPEasy password. This is not needed if the `CURLARGS` variable is set up in your shell environment from somewhere else. In that case, create an empty file. ```bash # @@ -38,8 +45,9 @@ CURLARGS=${CURLARGS:-"$CURLFLAGS -u admin:password"} # change password to yours Then make sure this file is readable by your user only (`chmod 600 $HOME/.espeasy`) +This assumes that the same ESPEasy passwords apply on all devices, but you can also do something like `env CURLARGS="-u admin:otherpasswd" espeasy....` if some devices need another password. -## Backup / restore +## Backup / restore ### Single device @@ -92,7 +100,6 @@ The restore destination must be same ESP device type If you add the `-a` option, the peer device list will be used to find your ESP devices, and also add any well known ESP MAC addresses found in the local arp table (`arp -a`) - ```bash $ espeasybackup -a 192.168.202.62 espeasybackup: Initial list 192.168.202.62 192.168.202.63 ... @@ -126,7 +133,6 @@ You may want to back up your ESP devices regularly to a remote place. This is a 20 06 * * 6 env MAILTO=admin@mydomain.net /usr/local/bin/espeasybackup -a -Z 192.168.202.52 192.168.202.62 192.168.202.64 > /tmp/espeasybackup.log 2>&1 ``` - ## New firmware deployment To upload new firmware, you specify a firmware file and as many IP addresses / hostnames that you want to update with that same hardware @@ -139,12 +145,12 @@ espeasyupdate: Firmware on file (ESP_Easy_mega_IR_ESP32c3_4M316k_LittleFS_CDC) d Update Success! Rebooting... ``` -The `-f` option is needed if you want to switch from one firmware file to another, or repeat a git build already deployed. +The `-f` option is needed if you want to switch from one firmware file to another, or repeat installing a git build already deployed. -This is tested as follows: +These facts are tested from the ESPEasy device as follows: ```bash -# IP is hoatname or IP address +# IP is hostname or IP address curl -s "http://${IP}/json"| jq -r '.System."Git Build"' # normally skipped if already deployed curl -s "http://${IP}/json"| jq -r '.System."Binary Filename"' # normally skipped if binary file is different ``` From ae52bea87277f208bd74a3c5682b321ae186c40c Mon Sep 17 00:00:00 2001 From: chromoxdor <33860956+chromoxdor@users.noreply.github.com> Date: Thu, 17 Oct 2024 09:56:27 +0200 Subject: [PATCH 05/23] Update Misc.cpp --- src/src/Helpers/Misc.cpp | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/src/Helpers/Misc.cpp b/src/src/Helpers/Misc.cpp index 966de49e38..1b581289da 100644 --- a/src/src/Helpers/Misc.cpp +++ b/src/src/Helpers/Misc.cpp @@ -410,8 +410,8 @@ void HSV2RGBW(float H, float S, float I, int rgbw[4]) { I = I > 0 ? (I < 1 ? I : 1) : 0; #define RGB_ORDER 0 - #define GBR_ORDER 1 - #define BRG_ORDER 2 + #define BRG_ORDER 1 + #define GBR_ORDER 2 int order = RGB_ORDER; @@ -423,10 +423,10 @@ void HSV2RGBW(float H, float S, float I, int rgbw[4]) { order = RGB_ORDER; } else if (H < ANGLE_240_DEG) { H = H - ANGLE_120_DEG; - order = GBR_ORDER; + order = BRG_ORDER; } else { H = H - ANGLE_240_DEG; - order = BRG_ORDER; + order = GBR_ORDER; } const float cos_h = cosf(H); const float cos_1047_h = cosf(ANGLE_60_DEG - H); @@ -440,14 +440,14 @@ void HSV2RGBW(float H, float S, float I, int rgbw[4]) { rgbw[0] = r; rgbw[1] = g; rgbw[2] = b; - } else if (GBR_ORDER == order) { - rgbw[0] = g; - rgbw[1] = b; - rgbw[2] = r; } else if (BRG_ORDER == order) { rgbw[0] = b; rgbw[1] = r; rgbw[2] = g; + } else if (GBR_ORDER == order) { + rgbw[0] = g; + rgbw[1] = b; + rgbw[2] = r; } } From 148c7030f596ce55250d8737ad44a1d396b292a6 Mon Sep 17 00:00:00 2001 From: chromoxdor <33860956+chromoxdor@users.noreply.github.com> Date: Thu, 17 Oct 2024 11:51:20 +0200 Subject: [PATCH 06/23] Update Misc.cpp --- src/src/Helpers/Misc.cpp | 46 ++++++++++++++++++++-------------------- 1 file changed, 23 insertions(+), 23 deletions(-) diff --git a/src/src/Helpers/Misc.cpp b/src/src/Helpers/Misc.cpp index 1b581289da..8dc19bb765 100644 --- a/src/src/Helpers/Misc.cpp +++ b/src/src/Helpers/Misc.cpp @@ -409,25 +409,21 @@ void HSV2RGBW(float H, float S, float I, int rgbw[4]) { I = I / 100; I = I > 0 ? (I < 1 ? I : 1) : 0; - #define RGB_ORDER 0 - #define BRG_ORDER 1 - #define GBR_ORDER 2 - - int order = RGB_ORDER; - constexpr float ANGLE_120_DEG = 120.0f * deg2rad; constexpr float ANGLE_240_DEG = 240.0f * deg2rad; constexpr float ANGLE_60_DEG = 60.0f * deg2rad; + int order; if (H < ANGLE_120_DEG) { - order = RGB_ORDER; + order = 0; // RGB_ORDER } else if (H < ANGLE_240_DEG) { - H = H - ANGLE_120_DEG; - order = BRG_ORDER; + H -= ANGLE_120_DEG; + order = 1; // BRG_ORDER } else { - H = H - ANGLE_240_DEG; - order = GBR_ORDER; + H -= ANGLE_240_DEG; + order = 2; // GBR_ORDER } + const float cos_h = cosf(H); const float cos_1047_h = cosf(ANGLE_60_DEG - H); @@ -436,18 +432,22 @@ void HSV2RGBW(float H, float S, float I, int rgbw[4]) { const int b = 0; rgbw[3] = 255 * (1 - S) * I; - if (RGB_ORDER == order) { - rgbw[0] = r; - rgbw[1] = g; - rgbw[2] = b; - } else if (BRG_ORDER == order) { - rgbw[0] = b; - rgbw[1] = r; - rgbw[2] = g; - } else if (GBR_ORDER == order) { - rgbw[0] = g; - rgbw[1] = b; - rgbw[2] = r; + switch (order) { + case 0: // RGB_ORDER + rgbw[0] = r; + rgbw[1] = g; + rgbw[2] = b; + break; + case 1: // BRG_ORDER + rgbw[0] = b; + rgbw[1] = r; + rgbw[2] = g; + break; + case 2: // GBR_ORDER + rgbw[0] = g; + rgbw[1] = b; + rgbw[2] = r; + break; } } From 9de293ba624fc7b1aefa67a239afe12388c1c982 Mon Sep 17 00:00:00 2001 From: chromoxdor <33860956+chromoxdor@users.noreply.github.com> Date: Fri, 18 Oct 2024 11:03:19 +0200 Subject: [PATCH 07/23] Update Misc.cpp reverting back to the state of the first commit --- src/src/Helpers/Misc.cpp | 46 ++++++++++++++++++++-------------------- 1 file changed, 23 insertions(+), 23 deletions(-) diff --git a/src/src/Helpers/Misc.cpp b/src/src/Helpers/Misc.cpp index 8dc19bb765..1b581289da 100644 --- a/src/src/Helpers/Misc.cpp +++ b/src/src/Helpers/Misc.cpp @@ -409,21 +409,25 @@ void HSV2RGBW(float H, float S, float I, int rgbw[4]) { I = I / 100; I = I > 0 ? (I < 1 ? I : 1) : 0; + #define RGB_ORDER 0 + #define BRG_ORDER 1 + #define GBR_ORDER 2 + + int order = RGB_ORDER; + constexpr float ANGLE_120_DEG = 120.0f * deg2rad; constexpr float ANGLE_240_DEG = 240.0f * deg2rad; constexpr float ANGLE_60_DEG = 60.0f * deg2rad; - int order; if (H < ANGLE_120_DEG) { - order = 0; // RGB_ORDER + order = RGB_ORDER; } else if (H < ANGLE_240_DEG) { - H -= ANGLE_120_DEG; - order = 1; // BRG_ORDER + H = H - ANGLE_120_DEG; + order = BRG_ORDER; } else { - H -= ANGLE_240_DEG; - order = 2; // GBR_ORDER + H = H - ANGLE_240_DEG; + order = GBR_ORDER; } - const float cos_h = cosf(H); const float cos_1047_h = cosf(ANGLE_60_DEG - H); @@ -432,22 +436,18 @@ void HSV2RGBW(float H, float S, float I, int rgbw[4]) { const int b = 0; rgbw[3] = 255 * (1 - S) * I; - switch (order) { - case 0: // RGB_ORDER - rgbw[0] = r; - rgbw[1] = g; - rgbw[2] = b; - break; - case 1: // BRG_ORDER - rgbw[0] = b; - rgbw[1] = r; - rgbw[2] = g; - break; - case 2: // GBR_ORDER - rgbw[0] = g; - rgbw[1] = b; - rgbw[2] = r; - break; + if (RGB_ORDER == order) { + rgbw[0] = r; + rgbw[1] = g; + rgbw[2] = b; + } else if (BRG_ORDER == order) { + rgbw[0] = b; + rgbw[1] = r; + rgbw[2] = g; + } else if (GBR_ORDER == order) { + rgbw[0] = g; + rgbw[1] = b; + rgbw[2] = r; } } From df42dfeeb3bfe9b7e3e00aac87b625bed2faaf96 Mon Sep 17 00:00:00 2001 From: TD-er Date: Mon, 4 Nov 2024 00:37:38 +0100 Subject: [PATCH 08/23] [GPS] Add course (bearing) as output option --- src/_P082_GPS.ino | 8 ++++++++ src/src/PluginStructs/P082_data_struct.cpp | 1 + src/src/PluginStructs/P082_data_struct.h | 1 + 3 files changed, 10 insertions(+) diff --git a/src/_P082_GPS.ino b/src/_P082_GPS.ino index 569d607b6c..e993d3de84 100644 --- a/src/_P082_GPS.ino +++ b/src/_P082_GPS.ino @@ -435,6 +435,14 @@ boolean Plugin_082(uint8_t function, struct EventStruct *event, String& string) # endif // ifndef BUILD_NO_DEBUG success = true; } + + if (P082_data->gps->course.isUpdated()) { + P082_setOutputValue(event, static_cast(P082_query::P082_QUERY_COURSE), P082_data->gps->course.deg()); + # ifndef BUILD_NO_DEBUG + addLog(LOG_LEVEL_DEBUG, F("GPS: Course update.")); + # endif // ifndef BUILD_NO_DEBUG + success = true; + } } P082_setOutputValue(event, static_cast(P082_query::P082_QUERY_SATVIS), P082_data->gps->satellitesStats.nrSatsVisible()); P082_setOutputValue(event, static_cast(P082_query::P082_QUERY_SATUSE), P082_data->gps->satellitesStats.nrSatsTracked()); diff --git a/src/src/PluginStructs/P082_data_struct.cpp b/src/src/PluginStructs/P082_data_struct.cpp index 6f8f8deb32..354455ca8d 100644 --- a/src/src/PluginStructs/P082_data_struct.cpp +++ b/src/src/PluginStructs/P082_data_struct.cpp @@ -23,6 +23,7 @@ const __FlashStringHelper* Plugin_082_valuename(P082_query value_nr, bool displa case P082_query::P082_QUERY_CHKSUM_FAIL: return displayString ? F("Checksum Fail") : F("chksum_fail"); case P082_query::P082_QUERY_DISTANCE: return displayString ? F("Distance (ODO)") : F("dist"); case P082_query::P082_QUERY_DIST_REF: return displayString ? F("Distance from Reference Point") : F("dist_ref"); + case P082_query::P082_QUERY_COURSE: return displayString ? F("Course (BeaRinG)") : F("course"); case P082_query::P082_NR_OUTPUT_OPTIONS: break; } return F(""); diff --git a/src/src/PluginStructs/P082_data_struct.h b/src/src/PluginStructs/P082_data_struct.h index d0858fe840..8222aaa51b 100644 --- a/src/src/PluginStructs/P082_data_struct.h +++ b/src/src/PluginStructs/P082_data_struct.h @@ -61,6 +61,7 @@ enum class P082_query : uint8_t { P082_QUERY_CHKSUM_FAIL = 9, P082_QUERY_DISTANCE = 10, P082_QUERY_DIST_REF = 11, + P082_QUERY_COURSE = 12, P082_NR_OUTPUT_OPTIONS }; From 67af91b0ff1ab6f2a8536cdf9b95fcf141b8de29 Mon Sep 17 00:00:00 2001 From: Ton Huisman Date: Thu, 7 Nov 2024 22:14:14 +0100 Subject: [PATCH 09/23] [Build] Enable Servo support for most builds --- src/src/CustomBuild/define_plugin_sets.h | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/src/CustomBuild/define_plugin_sets.h b/src/src/CustomBuild/define_plugin_sets.h index bda798b336..22eb50595f 100644 --- a/src/src/CustomBuild/define_plugin_sets.h +++ b/src/src/CustomBuild/define_plugin_sets.h @@ -2748,10 +2748,10 @@ To create/register a plugin, you have to : #define FEATURE_SETTINGS_ARCHIVE 0 #ifndef PLUGIN_BUILD_CUSTOM - #ifdef FEATURE_SERVO - #undef FEATURE_SERVO - #endif - #define FEATURE_SERVO 0 + // #ifdef FEATURE_SERVO + // #undef FEATURE_SERVO + // #endif + // #define FEATURE_SERVO 0 #endif #ifdef FEATURE_RTTTL #undef FEATURE_RTTTL @@ -3210,7 +3210,7 @@ To create/register a plugin, you have to : #endif #ifndef FEATURE_SERVO -#define FEATURE_SERVO 0 +#define FEATURE_SERVO 1 #endif #ifndef FEATURE_SETTINGS_ARCHIVE From 30cbc48c180246fa5c526cc2c598f588b1cf8dc4 Mon Sep 17 00:00:00 2001 From: Ton Huisman Date: Sat, 9 Nov 2024 20:47:06 +0100 Subject: [PATCH 10/23] [Docs] Updates and fixes, November 2024 --- docs/source/Participate/PlatformIO.rst | 68 ++++++++++++++++++++++++-- docs/source/Plugin/P022_commands.repl | 6 +-- 2 files changed, 67 insertions(+), 7 deletions(-) diff --git a/docs/source/Participate/PlatformIO.rst b/docs/source/Participate/PlatformIO.rst index 3952252185..4b2add038c 100644 --- a/docs/source/Participate/PlatformIO.rst +++ b/docs/source/Participate/PlatformIO.rst @@ -6,7 +6,7 @@ PlatformIO ESP easy can be built using the Arduino IDE or PlatformIO (PIO). Arduino IDE is not being used during development, so it may take some more effort to get it setup for building ESPeasy. -We advice to use PlatformIO as build environment. +We *strongly* advise to use PlatformIO as build environment. PlatformIO is just the build, test and upload environment for many micro controllers like the ESP8266 and ESP32 we use. @@ -68,6 +68,7 @@ For development of ESPEasy, a number of extensions has to be installed in VS-Cod * PlatformIO IDE (by PlatformIO) * C/C++ IntelliSense (by Microsoft) +* C/C++ Extension Pack (by Microsoft) * Uncrustify (by Zachary Flower, originally by Laurent Tréguier) Optional, but highly recommended: @@ -81,6 +82,7 @@ Optional, but highly recommended: * reStructuredText Syntax highlighting (by Trond Snekvik) * Extension pack for reStructuredText (by LeXtudio Inc.) * Markdown All in One (by Yu Zhang) +* WSL (by Microsoft) (when using WSL2 as documented below) Uncrustify @@ -92,6 +94,8 @@ For new code contributions, it is highly appreciated if the code is formatted us NB: Uncrustify has to be installed separately, as it is not included in the plugin! Download `Uncrustify from Sourceforge.net `_ +When using a Linux OS, f.e. WSL with Ubuntu, uncrustify can be installed via the regular package manager (shown below). It is strongly advised to use version 0.78 or newer, as older versions seem to have some bugs, causing document formatting to fail. + To do so: * Right click mouse in editor @@ -176,10 +180,66 @@ All these mainly apply to the latest ESP32-xx builds using ESP-IDF5.x. On a beefy desktop PC, like an AMD Ryzen9 with 12 CPU cores, building a ``MAX`` build for ESP32-S3 takes about 10 - 15 minutes on Windows. The same build when using WSL2 via VS-Code takes only 2 minutes to build. +When using VS-Code with WSL2, the VS-Code editor application runs on Windows, and, via the WSL plugin, communicates with a VS-Code server component on a Linux instance, running on WSL, that has the source code repository available, and where the build process is executed. + Installing WSL2 --------------- +For installing WSL2 a couple of steps are needed. Assumption here is that the default Linux distribution for WSL is used, currently Ubuntu (24.04 LTS), using apt-get as the package manager. Other Linux distributions may use a different package manager, like dnf, zypper or yum, using somewhat different commands. Those commands are not documented here. + +Install WSL2 - The Windows part +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +* Open a Windows Command prompt, preferrably Powershell, with Administrator privileges (Press the Windows key and start typing ``powershell``, then select Run as administrator) + +* Type the command ``wsl --install`` and press , this will start the installation procedure, ask for permissions via User Account Control where needed (that must be confirmed), and download and install what's required. + +* Once this part of the installation is complete, the computer must be restarted. This will install any additional Windows components that weren't installed yet. + +* After logging in to Windows, the installation procedure will be further completed, and you will be asked to enter a username and password for your day-to-day Linux user. This password will be needed later, f.e. when starting the WSL Linux instance, so best practice is to store it in a password safe of some sort (or write it on a Post-It note and stick that under your keyboard ;-)) + +Install WSL2 - The Linux part +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Now that Linux is installed, it's strongly advised to get it up to date with the latest patches, similar to Windows Update. This should be repeated on a regular basis to keep your installation up to date: + +.. highlight::sh + +.. code-block:: + + sudo apt-get update + sudo apt-get upgrade + +NB: The ``sudo`` command will ask for your current account password once, (and maybe later again after some time has passed). When asked for confirmation, confirm the installation of any needed updates, or add the ``-y`` parameter to the ``upgrade`` command to continue without questions. + +Additionally some tools need to be installed so PlatformIO can be properly installed later, and we can use the Uncrustify plugin in VS-Code to format the code nicely: + +.. highlight::sh + +.. code-block:: + + sudo apt-get install python3-venv + sudo apt-get install python3-pip + sudo apt-get install uncrustify + +Once this is completed, you can get the ESPEasy code in your WSL Linux file system. By default your Linux instance has access to the same internet connection as the host-computer that's running WSL, so the commands are the same as below for cloning a repository (**Clone your forked repositoryto your computer**) + +Start VS-Code from Linux +^^^^^^^^^^^^^^^^^^^^^^^^ + +Now that the repository is available locally, you can start VS-Code from the root folder of this repository: + +.. highlight::sh + +.. code-block:: + + cd ESPEasy + code . + +This will install, or update, the VS-Code server component in Linux and then open the VS-Code IDE in your Windows environment, assuming you have installed the suggested WSL plugin in VS-Code. + + Linking USB serial adapter to WSL2 ---------------------------------- @@ -190,7 +250,7 @@ After the USB device is 'bound' (shared), it must be attached to a specific wsl N.B. this must be repeated after a device was unplugged and replugged. The required steps are described `here `_ -However since this is rather tedious and error prone, it is strongly adviced to use a GUI tool like `WSL USB Manager `_ to perform these steps. +However since this is rather tedious and error prone, it is strongly advised to use a GUI tool like `WSL USB Manager `_ to perform these steps. After attaching an USB device to a WSL instance, it is best to check whether it was found using `dmesg` via the command line on WSL2. @@ -201,7 +261,7 @@ If only an USB device was detected but no `/dev/ttyUSBxx` was assigned, then a m * ``sudo modprobe cp210x`` - For FTDI CP210x USB to serial chips (small square form factor) * ``sudo modprobe ftdi_sio`` - For FTDI USB to serial chips with multiple serial ports like the FTDI4232H which has 4 serial ports. -After calling these 'modprobe' commands, the result can be verified using ``lsmod`` and rechecking ``dmesg`` to see which ``/dev/ttyUSBxx`` ports were assigned. +After calling these 'modprobe' commands, the result can be verified using ``lsmod`` and re-checking ``dmesg`` to see which ``/dev/ttyUSBxx`` ports were assigned. The ownerchip and permissions of these ``/dev/ttyUSBxx`` are probably set like this: @@ -455,7 +515,7 @@ Writing documentation Updating, or adding if it does not yet exist, the documentation is a useful activity that should be part of changing or adding to the ESPEasy code. Some of the optional VSCode extensions are specifically aimed at that task. -The documentation is created in the reStructuredText format, using mostly a ``.rst`` extension, and can be built locally by installing the sphinx tool. This can be installed manually by opening a Terminal window in VSCode (an already open Terminal can also be used) and issuing these commands: +The documentation is created in the reStructuredText format, using mostly a ``.rst`` extension, and can be built locally by installing the sphinx tool. This can be installed manually by opening a PlatformIO Terminal window in VSCode (an already open PIO Terminal can also be used, when using WSL2 a PlatformIO Terminal is *required* to execute in the correct Python Virtual Environment (venv)) and issuing these commands: .. code-block:: diff --git a/docs/source/Plugin/P022_commands.repl b/docs/source/Plugin/P022_commands.repl index 78d1a64edb..ebdf27d45e 100644 --- a/docs/source/Plugin/P022_commands.repl +++ b/docs/source/Plugin/P022_commands.repl @@ -7,7 +7,7 @@ ``[].pwm,,[,]`` - pcagpio: 0 ... 255 + pcagpio: 0 ... 15 value: 0 ... 4096 @@ -25,7 +25,7 @@ " ``[].gpio,,`` - pcagpio: 0 ... 255/all + pcagpio: 0 ... 15/all value: 0/1 "," @@ -36,7 +36,7 @@ " ``[].pulse,,,[,|auto]`` - pcagpio: 0 ... 255 + pcagpio: 0 ... 15 value: 0/1 From f0b3f7d926b485929d2a11cc6f5e0a1940169dda Mon Sep 17 00:00:00 2001 From: Ton Huisman Date: Sat, 9 Nov 2024 22:32:48 +0100 Subject: [PATCH 11/23] [Docs] Rewording a few phrases --- docs/source/Participate/PlatformIO.rst | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/source/Participate/PlatformIO.rst b/docs/source/Participate/PlatformIO.rst index 4b2add038c..eb32add3ce 100644 --- a/docs/source/Participate/PlatformIO.rst +++ b/docs/source/Participate/PlatformIO.rst @@ -186,7 +186,7 @@ When using VS-Code with WSL2, the VS-Code editor application runs on Windows, an Installing WSL2 --------------- -For installing WSL2 a couple of steps are needed. Assumption here is that the default Linux distribution for WSL is used, currently Ubuntu (24.04 LTS), using apt-get as the package manager. Other Linux distributions may use a different package manager, like dnf, zypper or yum, using somewhat different commands. Those commands are not documented here. +For installing WSL2 the following steps are needed. Assumption here is that the default Linux distribution for WSL is used, currently Ubuntu (24.04 LTS), using apt-get as the package manager. Other Linux distributions may use a different package manager, like dnf, zypper or yum, using somewhat different commands. Those commands are not documented here. Install WSL2 - The Windows part ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -219,9 +219,9 @@ Additionally some tools need to be installed so PlatformIO can be properly insta .. code-block:: - sudo apt-get install python3-venv - sudo apt-get install python3-pip - sudo apt-get install uncrustify + sudo apt-get install python3-venv python3-pip uncrustify + +NB: When running an older release of Ubuntu, like 2022.04 LTS, then uncrustify needs to be install/updated manually with a newer version, as the distributed version isn't working correctly. Or your Ubuntu install could be upgraded to 2024.04 (or newer) to correct this issue. Once this is completed, you can get the ESPEasy code in your WSL Linux file system. By default your Linux instance has access to the same internet connection as the host-computer that's running WSL, so the commands are the same as below for cloning a repository (**Clone your forked repositoryto your computer**) From 73fe561559dfa1ed0277045984d93594c6eaad63 Mon Sep 17 00:00:00 2001 From: TD-er Date: Tue, 12 Nov 2024 23:23:46 +0100 Subject: [PATCH 12/23] [GPIO] Allow to select GPIO-10 on ESP32-U4WDH As reported on the [forum](https://www.letscontrolit.com/forum/viewtopic.php?t=10503) --- src/src/Helpers/Hardware_device_info.cpp | 37 ++++++++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/src/src/Helpers/Hardware_device_info.cpp b/src/src/Helpers/Hardware_device_info.cpp index 2c21db8967..08c0ff5aee 100644 --- a/src/src/Helpers/Hardware_device_info.cpp +++ b/src/src/Helpers/Hardware_device_info.cpp @@ -126,6 +126,43 @@ int32_t getPartitionInfo(ESP8266_partition_type ptype, uint32_t& address, int32_ bool isFlashInterfacePin_ESPEasy(int gpio) { #if CONFIG_IDF_TARGET_ESP32 + if (getChipFeatures().embeddedFlash || + getChipFeatures().embeddedPSRAM) { + + // See page 20: https://www.espressif.com/sites/default/files/documentation/esp32_datasheet_en.pdf + if (getChipFeatures().embeddedFlash) { + // ESP32-U4WDH In-Package Flash (4 MB) + // SD_DATA_1 IO0/DI (GPIO-8) + // GPIO17 IO1/DO (GPIO-17) + // SD_DATA_0 IO2/WP# (GPIO-7) + // SD_CMD IO3/HOLD# (GPIO-11) + // SD_CLK CLK (GPIO-6) + // GPIO16 CS# (GPIO-16) + // GND VSS + // VDD_SDIO1 VDD + + if (gpio >= 6 && gpio <= 8) return true; + if (gpio == 17 || gpio == 11 || gpio == 16) return true; + } + + if (getChipFeatures().embeddedPSRAM) { + // ESP32-D0WDR2-V3 In-Package PSRAM (2 MB) + // SD_DATA_1 SIO0/SI (GPIO-8) + // SD_DATA_0 SIO1/SO (GPIO-7) + // SD_DATA_3 SIO2 (GPIO-10) + // SD_DATA_2 SIO3 (GPIO-9) + // SD_CLK SCLK (GPIO-6) + // GPIO16 CE# (GPIO-16) + // GND VSS + // VDD_SDIO1 VDD + if (gpio >= 6 && gpio <= 10) return true; + if (gpio == 16) return true; + + } + return false; + } + + // GPIO-6 ... 11: SPI flash and PSRAM // GPIO-16 & 17: CS for PSRAM, thus only unuable when PSRAM is present return (gpio) >= 6 && (gpio) <= 11; From 5181dd6b8b2b58dc085ade6354bef43a9c74d5a6 Mon Sep 17 00:00:00 2001 From: chromoxdor <33860956+chromoxdor@users.noreply.github.com> Date: Wed, 13 Nov 2024 10:36:37 +0100 Subject: [PATCH 13/23] [P049] added commands added missing commands to colorcode and updated also the documentation --- docs/source/Plugin/P049.rst | 12 ++++++++---- docs/source/Plugin/P049_commands.repl | 24 ++++++++++++++++++++++++ static/espeasy.js | 2 ++ static/espeasy.min.js | 2 +- 4 files changed, 35 insertions(+), 5 deletions(-) create mode 100644 docs/source/Plugin/P049_commands.repl diff --git a/docs/source/Plugin/P049.rst b/docs/source/Plugin/P049.rst index 5b1d8b2795..a1e118f0cc 100644 --- a/docs/source/Plugin/P049.rst +++ b/docs/source/Plugin/P049.rst @@ -34,12 +34,16 @@ Sensor See: :ref:`SerialHelper_page` -**TODO**: Complete this documentation... +Commands available +^^^^^^^^^^^^^^^^^^ + +.. include:: P049_commands.repl + +Additional infos can be found here: https://emariete.com/en/sensor-co2-mh-z19b/ -.. Commands available -.. ^^^^^^^^^^^^^^^^^^ -.. .. include:: P049_commands.repl + +**TODO**: Complete this documentation... .. Events .. ~~~~~~ diff --git a/docs/source/Plugin/P049_commands.repl b/docs/source/Plugin/P049_commands.repl new file mode 100644 index 0000000000..50b744c37c --- /dev/null +++ b/docs/source/Plugin/P049_commands.repl @@ -0,0 +1,24 @@ +.. csv-table:: + :header: "Command", "Examples" + :widths: 20, 30 + + " + ``MHZCalibrateZero`` + + ``MHZReset`` + + ``MHZABCEnable`` + + ``MHZABCDisable`` + + "," + Sets the zero point of the sensor (in this case 400ppm) + + Reset to factory defaults + + Enables automatic baseline calibration + + Disables automatic baseline calibration + " + + \ No newline at end of file diff --git a/static/espeasy.js b/static/espeasy.js index 536dab7127..fcba3339ff 100644 --- a/static/espeasy.js +++ b/static/espeasy.js @@ -43,6 +43,8 @@ var commonPlugins = [ "NeoPixel", "NeoPixelAll", "NeoPixelLine", "NeoPixelHSV", "NeoPixelAllHSV", "NeoPixelLineHSV", "NeoPixelBright", //P048 "MotorShieldCmd,DCMotor", "MotorShieldCmd,Stepper", + //P049 + "MHZCalibrateZero", "MHZReset", "MHZABCEnable", "MHZABCDisable", //P052 "Sensair_SetRelay", //P053 diff --git a/static/espeasy.min.js b/static/espeasy.min.js index 32c26855aa..3c405ae7ef 100644 --- a/static/espeasy.min.js +++ b/static/espeasy.min.js @@ -1 +1 @@ -var rEdit,commonAtoms=["And","Or"],commonKeywords=["If","Else","Elseif","Endif"],commonCommands=["AccessInfo","Background","Build","ClearAccessBlock","ClearRTCam","Config","ControllerDisable","ControllerEnable","DateTime","Debug","Dec","DeepSleep","DisablePriorityTask","DNS","DST","EraseSDKWiFi","ExecuteRules","FactoryReset","Gateway","I2Cscanner","Inc","IP","Let","Load","LogEntry","LogPortStatus","LoopTimerSet","LoopTimerSet_ms","MemInfo","MemInfoDetail","Name","Password","PostToHTTP","Publish","PublishR","Reboot","Save","SendTo","SendToHTTP","SendToUDP","Settings","Subnet","Subscribe","TaskClear","TaskClearAll","TaskDisable","TaskEnable","TaskRun","TaskValueSet","TaskValueSetAndRun","TimerPause","TimerResume","TimerSet","TimerSet_ms","TimeZone","UdpPort","UdpTest","Unit","UseNTP","WdConfig","WdRead","WiFi","WiFiAllowAP","WiFiAPMode","WiFiConnect","WiFiDisconnect","WiFiKey","WiFiKey2","WiFiMode","WiFiScan","WiFiSSID","WiFiSSID2","WiFiSTAMode","Event","AsyncEvent","GPIO","GPIOToggle","LongPulse","LongPulse_mS","Monitor","Pulse","PWM","Servo","Status","Tone","RTTTL","UnMonitor",],commonEvents=["Clock#Time","Login#Failed","MQTT#Connected","MQTT#Disconnected","MQTTimport#Connected","MQTTimport#Disconnected","Rules#Timer","System#Boot","System#BootMode","System#Sleep","System#Wake","TaskExit#","TaskInit#","ThingspeakReply","Time#Initialized","Time#Set","WiFi#APmodeDisabled","WiFi#APmodeEnabled","WiFi#ChangedAccesspoint","WiFi#ChangedWiFichannel","WiFi#Connected","WiFi#Disconnected"],commonPlugins=["ResetPulseCounter","SetPulseCounterTotal","LogPulseStatistic","analogout","MCPGPIO","MCPGPIOToggle","MCPLongPulse","MCPLongPulse_ms","MCPPulse","Status,MCP","Monitor,MCP","MonitorRange,MCP","UnMonitorRange,MCP","UnMonitor,MCP","MCPGPIORange","MCPGPIOPattern","MCPMode","MCPModeRange","ExtGpio","ExtPwm","ExtPulse","ExtLongPulse","Status,EXT,","LCDCmd","LCD","PCFGPIO","PCFGPIOToggle","PCFLongPulse","PCFLongPulse_ms","PCFPulse","Status,PCF","Monitor,PCF","MonitorRange,PCF","UnMonitorRange,PCF","UnMonitor,PCF","PCFGPIORange","PCFGPIOpattern","PCFMode","PCFmodeRange","pcapwm","pcafrq","mode2","OLED","OLEDCMD","OLEDCMD,on","OLEDCMD,off","OLEDCMD,clear","IRSEND","IRSENDAC","OledFramedCmd","OledFramedCmd,Display","OledFramedCmd,low","OledFramedCmd,med","OledFramedCmd,high","OledFramedCmd,Frame","OledFramedCmd,linecount","OledFramedCmd,leftalign","OledFramedCmd,align","OledFramedCmd,userDef1","OledFramedCmd,userDef2","NeoPixel","NeoPixelAll","NeoPixelLine","NeoPixelHSV","NeoPixelAllHSV","NeoPixelLineHSV","NeoPixelBright","MotorShieldCmd,DCMotor","MotorShieldCmd,Stepper","Sensair_SetRelay","PMSX003","PMSX003,Wake","PMSX003,Sleep","PMSX003,Reset","encwrite","Play","Vol","Eq","Mode","Repeat","tareChanA","tareChanB","7dn","7dst","7dsd","7dtext","7ddt","7dt","7dtfont","7dtbin","7don","7doff","7output","HLWCalibrate","HLWReset","csecalibrate","cseclearpulses","csereset","WemosMotorShieldCMD","LolinMotorShieldCMD","GPS","GPS,Sleep","GPS,Wake","GPS#GotFix","GPS#LostFix","GPS#Travelled","homieValueSet","HeatPumpir","MitsubishiHP","MitsubishiHP,temperature","MitsubishiHP,power","MitsubishiHP,mode","MitsubishiHP,fan","MitsubishiHP,vane","MitsubishiHP,widevane","Culreader_Write","Touch","Touch,Rot","Touch,Flip","Touch,Enable","Touch,Disable","Touch,On","Touch,Off","Touch,Toggle","Touch,Setgrp","Touch,Incgrp","Touch,Decgrp","Touch,Incpage","Touch,Decpage","Touch,Updatebutton","WakeOnLan","DotMatrix","DotMatrix,clear","DotMatrix,update","DotMatrix,size","DotMatrix,txt","DotMatrix,settxt","DotMatrix,content","DotMatrix,alignment","DotMatrix,anim.in","DotMatrix,anim.out","DotMatrix,speed","DotMatrix,pause","DotMatrix,font","DotMatrix,layout","DotMatrix,inverted","DotMatrix,specialeffect","DotMatrix,offset","DotMatrix,brightness","DotMatrix,repeat","DotMatrix,setbar","DotMatrix,bar","Thermo","Thermo,Up","Thermo,Down","Thermo,Mode","Thermo,ModeBtn","Thermo,Setpoint","Max1704xclearalert","scdgetabc","scdgetalt","scdgettmp","scdsetcalibration","scdsetfrc","scdgetinterval","multirelay","multirelay,on","multirelay,off","multirelay,set","multirelay,get","multirelay,loop","ShiftOut","ShiftOut,Set","ShiftOut,SetNoUpdate","ShiftOut,Update","ShiftOut,SetAll","ShiftOut,SetAllNoUpdate","ShiftOut,SetAllLow","ShiftOut,SetAllHigh","ShiftOut,SetChipCount","ShiftOut,SetHexBin","cdmrst","nfx","nfx,off","nfx,on","nfx,dim","nfx,line,","nfx,hsvline,","nfx,one,","nfx,hsvone,","nfx,all,","nfx,rgb,","nfx,fade,","nfx,hsv,","nfx,colorfade,","nfx,rainbow","nfx,kitt,","nfx,comet,","nfx,theatre,","nfx,scan,","nfx,dualscan,","nfx,twinkle,","nfx,twinklefade,","nfx,sparkle,","nfx,wipe,","nfx,dualwipe","nfx,fire","nfx,fireflicker","nfx,faketv","nfx,simpleclock","nfx,stop","nfx,statusrequest","nfx,fadetime,","nfx,fadedelay,","nfx,speed,","nfx,count,","nfx,bgcolor","ShiftIn","ShiftIn,PinEvent","ShiftIn,ChipEvent","ShiftIn,SetChipCount","ShiftIn,SampleFrequency","ShiftIn,EventPerPin","scd4x","scd4x,storesettings","scd4x,facoryreset","scd4x,selftest","scd4x,setfrc,","axp","axp,ldo2","axp,ldo3","axp,ldoio","axp,gpio0","axp,gpio1","axp,gpio2","axp,gpio3","axp,gpio4","axp,dcdc2","axp,dcdc3","axp,ldo2map","axp,ldo3map","axp,ldoiomap","axp,dcdc2map","axp,dcdc3map","axp,ldo2perc","axp,ldo3perc","axp,ldoioperc","axp,dcdc2perc","axp,dcdc3perc","I2CEncoder","I2CEncoder,bright","I2CEncoder,led1","I2CEncoder,led2","I2CEncoder,gain","I2CEncoder,set","cachereader","cachereader,readpos","cachereader,sendtaskinfo","cachereader,flush","tm1621","tm1621,write,","tm1621,writerow,","tm1621,voltamp,","tm1621,energy,","tm1621,celcius,","tm1621,fahrenheit,","tm1621,humidity,","tm1621,raw,","dac","dac,1","dac,2","sht4x","sht4x,startup","ld2410","ld2410,factoryreset","ld2410,logall","digipot","digipot,reset","digipot,shutdown","digipot,","7dextra","7dbefore","7dgroup","7digit","7color","7digitcolor","7groupcolor","gp8403","gp8403,volt,","gp8403,mvolt,","gp8403,range,","gp8403,preset,","gp8403,init,","sen5x","sen5x,startclean","sen5x,techlog,",],pluginDispKind=["tft","ili9341","ili9342","ili9481","ili9486","ili9488","epd","eink","epaper","il3897","uc8151d","ssd1680","ws2in7","ws1in54","st77xx","st7735","st7789","st7796","neomatrix","neo","pcd8544",],pluginDispCmd=["cmd,on","cmd,off","cmd,clear","cmd,backlight","cmd,bright","cmd,deepsleep","cmd,seq_start","cmd,seq_end","cmd,inv","cmd,rot",",clear",",rot",",tpm",",txt",",txp",",txz",",txc",",txs",",txtfull",",asciitable",",font",",l",",lh",",lv",",lm",",lmr",",r",",rf",",c",",cf",",rf",",t",",tf",",rr",",rrf",",px",",pxh",",pxv",",bmp",",btn",",win",",defwin",",delwin",],commonTag=["On","Do","Endon"],commonNumber=["toBin","toHex","Constrain","XOR","AND:","OR:","Ord","bitRead","bitSet","bitClear","bitWrite","urlencode"],commonMath=["Log","Ln","Abs","Exp","Sqrt","Sq","Round","Sin","Cos","Tan","aSin","aCos","aTan","Sin_d","Cos_d","Tan_d","aSin_d","aCos_d","aTan_d"],commonWarning=["delay","Delay","ResetFlashWriteCounter"],taskSpecifics=["settings.Enabled","settings.Interval","settings.ValueCount","settings.Controller1.Enabled","settings.Controller2.Enabled","settings.Controller3.Enabled","settings.Controller1.Idx","settings.Controller2.Idx","settings.Controller3.Idx"],AnythingElse=["%eventvalue%","%eventpar%","%eventname%","%sysname%","%bootcause%","%systime%","%systm_hm%","%systm_hm_0%","%systm_hm_sp%","%systime_am%","%systime_am_0%","%systime_am_sp%","%systm_hm_am%","%systm_hm_am_0%","%systm_hm_am_sp%","%lcltime%","%sunrise%","%s_sunrise%","%m_sunrise%","%sunset%","%s_sunset%","%m_sunset%","%lcltime_am%","%syshour%","%syshour_0%","%sysmin%","%sysmin_0%","%syssec%","%syssec_0%","%sysday%","%sysday_0%","%sysmonth%","%sysmonth_0%","%sysyear%","%sysyear_0%","%sysyears%","%sysweekday%","%sysweekday_s%","%unixtime%","%uptime%","%uptime_ms%","%rssi%","%ip%","%unit%","%unit_0%","%ssid%","%bssid%","%wi_ch%","%iswifi%","%vcc%","%mac%","%mac_int%","%isntp%","%ismqtt%","%dns%","%dns1%","%dns2%","%flash_freq%","%flash_size%","%flash_chip_vendor%","%flash_chip_model%","%fs_free%","%fs_size%","%cpu_id%","%cpu_freq%","%cpu_model%","%cpu_rev%","%cpu_cores%","%board_name%","%inttemp%","substring","indexOf","indexOf_ci","equals","equals_ci","strtol","timeToMin","timeToSec","%ethwifimode%","%ethconnected%","%ethduplex%","%ethspeed%","%ethstate%","%ethspeedstate%","%c_w_dir%","%c_c2f%","%c_ms2Bft%","%c_dew_th%","%c_alt_pres_sea%","%c_sea_pres_alt%","%c_cm2imp%","%c_mm2imp%","%c_m2day%","%c_m2dh%","%c_m2dhm%","%c_s2dhms%","%c_2hex%","%c_u2ip%","%c_uname%","%c_uage%","%c_ubuild%","%c_ubuildstr%","%c_uload%","%c_utype%","%c_utypestr%","var","int"];for(const element2 of pluginDispKind)commonPlugins=commonPlugins.concat(element2);for(const element2 of pluginDispKind)for(const element3 of pluginDispCmd){let e=element2+element3;commonPlugins=commonPlugins.concat(e)}var EXTRAWORDS=commonAtoms.concat(commonPlugins,commonKeywords,commonCommands,commonEvents,commonTag,commonNumber,commonMath,commonWarning,taskSpecifics,AnythingElse);function initCM(){CodeMirror.commands.autocomplete=function(e){e.showHint({hint:CodeMirror.hint.anyword})},(rEdit=CodeMirror.fromTextArea(document.getElementById("rules"),{tabSize:2,indentWithTabs:!1,lineNumbers:!0,autoCloseBrackets:!0,extraKeys:{"Ctrl-Space":"autocomplete",Tab(e){"null"===e.getMode().name?e.execCommand("insertTab"):e.somethingSelected()?e.execCommand("indentMore"):e.execCommand("insertSoftTab")},"Shift-Tab":e=>e.execCommand("indentLess")}})).on("change",function(){rEdit.save()}),rEdit.on("inputRead",function(e,t){var n=e.getCursor(),o=e.getTokenAt(n);/[\w%,.]/.test(t.text)&&"comment"!=o.type&&e.showHint({completeSingle:!1})})}!function(e){"object"==typeof exports&&"object"==typeof module?e(require("codemirror")):"function"==typeof define&&define.amd?define(["codemirror"],e):e(CodeMirror)}(function(e){"use strict";e.defineMode("espeasy",function(){var e={};function t(t,n){for(var o=0;oe.toLowerCase());commonCommands=commonCommands.concat(n);var o=commonEvents.map(e=>e.toLowerCase());commonEvents=commonEvents.concat(o);var i=commonPlugins.map(e=>e.toLowerCase());commonPlugins=commonPlugins.concat(i);var a=commonAtoms.map(e=>e.toLowerCase());commonAtoms=commonAtoms.concat(a);var s=commonKeywords.map(e=>e.toLowerCase());commonKeywords=commonKeywords.concat(s);var r=commonTag.map(e=>e.toLowerCase());commonTag=commonTag.concat(r);var c=commonNumber.map(e=>e.toLowerCase());commonNumber=commonNumber.concat(c);var l=commonMath.map(e=>e.toLowerCase());commonMath=commonMath.concat(l);var m=AnythingElse.map(e=>e.toLowerCase());AnythingElse=AnythingElse.concat(m);var d=taskSpecifics.map(e=>e.toLowerCase());function u(t,n){if(t.eatSpace())return null;t.sol();var o=t.next();if(/\d/.test(o)){if("0"==o)return"x"===t.next()?(t.eatWhile(/\w/),"number"):(t.eatWhile(/\d|\./),"number");if(t.eatWhile(/\d|\./),!t.match("d")&&!t.match("output")&&(t.eol()||/\D/.test(t.peek())))return"number"}if(/\w/.test(o))for(let i of EXTRAWORDS){let a=i.substring(1);(i.includes(":")||i.includes(",")||i.includes("."))&&t.match(a)}if(/\w/.test(o)&&(t.eatWhile(/[\w]/),t.match(".gpio")||t.match(".pulse")||t.match(".frq")||t.match(".pwm")))return"def";if("\\"===o)return t.next(),null;if("("===o||")"===o)return"bracket";if("{"===o||"}"===o||":"===o)return"number";if("/"==o)return/\//.test(t.peek())?(t.skipToEnd(),"comment"):"operator";if("'"==o&&(t.eatWhile(/[^']/),t.match("'")))return"attribute";if("+"===o||"="===o||"<"===o||">"===o||"-"===o||","===o||"*"===o||"!"===o)return"operator";if("%"==o){if(/\d/.test(t.next()))return"number";if(t.eatWhile(/[^\s\%]/),t.match("%"))return"hr"}if("["==o&&(t.eatWhile(/[^\s\]]/),t.eat("]")))return"hr";t.eatWhile(/\w/);var s=t.current();return/\w/.test(o)&&t.match("#")?(t.eatWhile(/[\w.#]/),"events"):"#"===o?(t.eatWhile(/\w/),"number"):e.hasOwnProperty(s)?e[s]:null}return taskSpecifics=taskSpecifics.concat(d),t("atom",commonAtoms),t("keyword",commonKeywords),t("builtin",commonCommands),t("events",commonEvents),t("def",commonPlugins),t("tag",commonTag),t("number",commonNumber),t("bracket",commonMath),t("warning",commonWarning),t("hr",AnythingElse),t("comment",taskSpecifics),{startState:function(){return{tokens:[]}},token:function(e,t){var n,o;return n=e,((o=t).tokens[0]||u)(n,o)},closeBrackets:"[]{}''\"\"``()",lineComment:"//",fold:"brace"}})}),function(e){"object"==typeof exports&&"object"==typeof module?e(require("../../lib/codemirror")):"function"==typeof define&&define.amd?define(["../../lib/codemirror"],mod):e(CodeMirror)}(function(e){var t={pairs:"()[]{}''\"\"",closeBefore:")]}'\":;>",triples:"",explode:"[]{}"},n=e.Pos;function o(e,n){return"pairs"==n&&"string"==typeof e?e:"object"==typeof e&&null!=e[n]?e[n]:t[n]}e.defineOption("autoCloseBrackets",!1,function(t,n,s){s&&s!=e.Init&&(t.removeKeyMap(i),t.state.closeBrackets=null),n&&(a(o(n,"pairs")),t.state.closeBrackets=n,t.addKeyMap(i))});var i={Backspace:function t(i){var a=r(i);if(!a||i.getOption("disableInput"))return e.Pass;for(var s=o(a,"pairs"),c=i.listSelections(),l=0;l=0;l--){var u=c[l].head;i.replaceRange("",n(u.line,u.ch-1),n(u.line,u.ch+1),"+delete")}},Enter:function t(n){var i=r(n),a=i&&o(i,"explode");if(!a||n.getOption("disableInput"))return e.Pass;for(var s=n.listSelections(),l=0;l=0&&i.getRange(b,n(b.line,b.ch+3))==a+a+a?"skipThree":"skip";else if(h&&b.ch>1&&p.indexOf(a)>=0&&i.getRange(n(b.line,b.ch-2),b)==a+a){if(b.ch>2&&/\bstring/.test(i.getTokenTypeAt(n(b.line,b.ch-2))))return e.Pass;P="addFour"}else if(h){var M=0==b.ch?" ":i.getRange(n(b.line,b.ch-1),b);if(e.isWordChar(y)||M==a||e.isWordChar(M))return e.Pass;P="both"}else{if(!(x&&(0===y.length||/\s/.test(y)||f.indexOf(y)>-1)))return e.Pass;P="both"}if(S){if(S!=P)return e.Pass}else S=P}var v=u%2?m.charAt(u-1):a,D=u%2?a:m.charAt(u+1);i.operation(function(){if("skip"==S)c(i,1);else if("skipThree"==S)c(i,3);else if("surround"==S){for(var e=i.getSelections(),t=0;t0?{line:s.head.line,ch:s.head.ch+t}:{line:s.head.line-1};n.push({anchor:r,head:r})}e.setSelections(n,i)}function l(t){var o=e.cmpPos(t.anchor,t.head)>0;return{anchor:new n(t.anchor.line,t.anchor.ch+(o?-1:1)),head:new n(t.head.line,t.head.ch+(o?1:-1))}}function m(e,t){var o=e.getRange(n(t.line,t.ch-1),n(t.line,t.ch+1));return 2==o.length?o:null}function d(e,t){var o=e.getTokenAt(n(t.line,t.ch+1));return/\bstring/.test(o.type)&&o.start==t.ch&&(0==t.ch||!/\bstring/.test(e.getTokenTypeAt(t)))}a(t.pairs+"`")}); \ No newline at end of file +var commonAtoms=["And","Or"],commonKeywords=["If","Else","Elseif","Endif"],commonCommands=["AccessInfo","Background","Build","ClearAccessBlock","ClearRTCam","Config","ControllerDisable","ControllerEnable","DateTime","Debug","Dec","DeepSleep","DisablePriorityTask","DNS","DST","EraseSDKWiFi","ExecuteRules","FactoryReset","Gateway","I2Cscanner","Inc","IP","Let","Load","LogEntry","LogPortStatus","LoopTimerSet","LoopTimerSet_ms","MemInfo","MemInfoDetail","Name","Password","PostToHTTP","Publish","PublishR","Reboot","Save","SendTo","SendToHTTP","SendToUDP","Settings","Subnet","Subscribe","TaskClear","TaskClearAll","TaskDisable","TaskEnable","TaskRun","TaskValueSet","TaskValueSetAndRun","TimerPause","TimerResume","TimerSet","TimerSet_ms","TimeZone","UdpPort","UdpTest","Unit","UseNTP","WdConfig","WdRead","WiFi","WiFiAllowAP","WiFiAPMode","WiFiConnect","WiFiDisconnect","WiFiKey","WiFiKey2","WiFiMode","WiFiScan","WiFiSSID","WiFiSSID2","WiFiSTAMode","Event","AsyncEvent","GPIO","GPIOToggle","LongPulse","LongPulse_mS","Monitor","Pulse","PWM","Servo","Status","Tone","RTTTL","UnMonitor"],commonEvents=["Clock#Time","Login#Failed","MQTT#Connected","MQTT#Disconnected","MQTTimport#Connected","MQTTimport#Disconnected","Rules#Timer","System#Boot","System#BootMode","System#Sleep","System#Wake","TaskExit#","TaskInit#","ThingspeakReply","Time#Initialized","Time#Set","WiFi#APmodeDisabled","WiFi#APmodeEnabled","WiFi#ChangedAccesspoint","WiFi#ChangedWiFichannel","WiFi#Connected","WiFi#Disconnected"],commonPlugins=["ResetPulseCounter","SetPulseCounterTotal","LogPulseStatistic","analogout","MCPGPIO","MCPGPIOToggle","MCPLongPulse","MCPLongPulse_ms","MCPPulse","Status,MCP","Monitor,MCP","MonitorRange,MCP","UnMonitorRange,MCP","UnMonitor,MCP","MCPGPIORange","MCPGPIOPattern","MCPMode","MCPModeRange","ExtGpio","ExtPwm","ExtPulse","ExtLongPulse","Status,EXT,","LCDCmd","LCD","PCFGPIO","PCFGPIOToggle","PCFLongPulse","PCFLongPulse_ms","PCFPulse","Status,PCF","Monitor,PCF","MonitorRange,PCF","UnMonitorRange,PCF","UnMonitor,PCF","PCFGPIORange","PCFGPIOpattern","PCFMode","PCFmodeRange","pcapwm","pcafrq","mode2","OLED","OLEDCMD","OLEDCMD,on","OLEDCMD,off","OLEDCMD,clear","IRSEND","IRSENDAC","OledFramedCmd","OledFramedCmd,Display","OledFramedCmd,low","OledFramedCmd,med","OledFramedCmd,high","OledFramedCmd,Frame","OledFramedCmd,linecount","OledFramedCmd,leftalign","OledFramedCmd,align","OledFramedCmd,userDef1","OledFramedCmd,userDef2","NeoPixel","NeoPixelAll","NeoPixelLine","NeoPixelHSV","NeoPixelAllHSV","NeoPixelLineHSV","NeoPixelBright","MotorShieldCmd,DCMotor","MotorShieldCmd,Stepper","MHZCalibrateZero","MHZReset","MHZABCEnable","MHZABCDisable","Sensair_SetRelay","PMSX003","PMSX003,Wake","PMSX003,Sleep","PMSX003,Reset","encwrite","Play","Vol","Eq","Mode","Repeat","tareChanA","tareChanB","7dn","7dst","7dsd","7dtext","7ddt","7dt","7dtfont","7dtbin","7don","7doff","7output","HLWCalibrate","HLWReset","csecalibrate","cseclearpulses","csereset","WemosMotorShieldCMD","LolinMotorShieldCMD","GPS","GPS,Sleep","GPS,Wake","GPS#GotFix","GPS#LostFix","GPS#Travelled","homieValueSet","HeatPumpir","MitsubishiHP","MitsubishiHP,temperature","MitsubishiHP,power","MitsubishiHP,mode","MitsubishiHP,fan","MitsubishiHP,vane","MitsubishiHP,widevane","Culreader_Write","Touch","Touch,Rot","Touch,Flip","Touch,Enable","Touch,Disable","Touch,On","Touch,Off","Touch,Toggle","Touch,Setgrp","Touch,Incgrp","Touch,Decgrp","Touch,Incpage","Touch,Decpage","Touch,Updatebutton","WakeOnLan","DotMatrix","DotMatrix,clear","DotMatrix,update","DotMatrix,size","DotMatrix,txt","DotMatrix,settxt","DotMatrix,content","DotMatrix,alignment","DotMatrix,anim.in","DotMatrix,anim.out","DotMatrix,speed","DotMatrix,pause","DotMatrix,font","DotMatrix,layout","DotMatrix,inverted","DotMatrix,specialeffect","DotMatrix,offset","DotMatrix,brightness","DotMatrix,repeat","DotMatrix,setbar","DotMatrix,bar","Thermo","Thermo,Up","Thermo,Down","Thermo,Mode","Thermo,ModeBtn","Thermo,Setpoint","Max1704xclearalert","scdgetabc","scdgetalt","scdgettmp","scdsetcalibration","scdsetfrc","scdgetinterval","multirelay","multirelay,on","multirelay,off","multirelay,set","multirelay,get","multirelay,loop","ShiftOut","ShiftOut,Set","ShiftOut,SetNoUpdate","ShiftOut,Update","ShiftOut,SetAll","ShiftOut,SetAllNoUpdate","ShiftOut,SetAllLow","ShiftOut,SetAllHigh","ShiftOut,SetChipCount","ShiftOut,SetHexBin","cdmrst","nfx","nfx,off","nfx,on","nfx,dim","nfx,line,","nfx,hsvline,","nfx,one,","nfx,hsvone,","nfx,all,","nfx,rgb,","nfx,fade,","nfx,hsv,","nfx,colorfade,","nfx,rainbow","nfx,kitt,","nfx,comet,","nfx,theatre,","nfx,scan,","nfx,dualscan,","nfx,twinkle,","nfx,twinklefade,","nfx,sparkle,","nfx,wipe,","nfx,dualwipe","nfx,fire","nfx,fireflicker","nfx,faketv","nfx,simpleclock","nfx,stop","nfx,statusrequest","nfx,fadetime,","nfx,fadedelay,","nfx,speed,","nfx,count,","nfx,bgcolor","ShiftIn","ShiftIn,PinEvent","ShiftIn,ChipEvent","ShiftIn,SetChipCount","ShiftIn,SampleFrequency","ShiftIn,EventPerPin","scd4x","scd4x,storesettings","scd4x,facoryreset","scd4x,selftest","scd4x,setfrc,","axp","axp,ldo2","axp,ldo3","axp,ldoio","axp,gpio0","axp,gpio1","axp,gpio2","axp,gpio3","axp,gpio4","axp,dcdc2","axp,dcdc3","axp,ldo2map","axp,ldo3map","axp,ldoiomap","axp,dcdc2map","axp,dcdc3map","axp,ldo2perc","axp,ldo3perc","axp,ldoioperc","axp,dcdc2perc","axp,dcdc3perc","I2CEncoder","I2CEncoder,bright","I2CEncoder,led1","I2CEncoder,led2","I2CEncoder,gain","I2CEncoder,set","cachereader","cachereader,readpos","cachereader,sendtaskinfo","cachereader,flush","tm1621","tm1621,write,","tm1621,writerow,","tm1621,voltamp,","tm1621,energy,","tm1621,celcius,","tm1621,fahrenheit,","tm1621,humidity,","tm1621,raw,","dac","dac,1","dac,2","sht4x","sht4x,startup","ld2410","ld2410,factoryreset","ld2410,logall","digipot","digipot,reset","digipot,shutdown","digipot,","7dextra","7dbefore","7dgroup","7digit","7color","7digitcolor","7groupcolor","gp8403","gp8403,volt,","gp8403,mvolt,","gp8403,range,","gp8403,preset,","gp8403,init,","sen5x","sen5x,startclean","sen5x,techlog,"],pluginDispKind=["tft","ili9341","ili9342","ili9481","ili9486","ili9488","epd","eink","epaper","il3897","uc8151d","ssd1680","ws2in7","ws1in54","st77xx","st7735","st7789","st7796","neomatrix","neo","pcd8544"],pluginDispCmd=["cmd,on","cmd,off","cmd,clear","cmd,backlight","cmd,bright","cmd,deepsleep","cmd,seq_start","cmd,seq_end","cmd,inv","cmd,rot",",clear",",rot",",tpm",",txt",",txp",",txz",",txc",",txs",",txtfull",",asciitable",",font",",l",",lh",",lv",",lm",",lmr",",r",",rf",",c",",cf",",rf",",t",",tf",",rr",",rrf",",px",",pxh",",pxv",",bmp",",btn",",win",",defwin",",delwin"],commonTag=["On","Do","Endon"],commonNumber=["toBin","toHex","Constrain","XOR","AND:","OR:","Ord","bitRead","bitSet","bitClear","bitWrite","urlencode"],commonMath=["Log","Ln","Abs","Exp","Sqrt","Sq","Round","Sin","Cos","Tan","aSin","aCos","aTan","Sin_d","Cos_d","Tan_d","aSin_d","aCos_d","aTan_d"],commonWarning=["delay","Delay","ResetFlashWriteCounter"],taskSpecifics=["settings.Enabled","settings.Interval","settings.ValueCount","settings.Controller1.Enabled","settings.Controller2.Enabled","settings.Controller3.Enabled","settings.Controller1.Idx","settings.Controller2.Idx","settings.Controller3.Idx"],AnythingElse=["%eventvalue%","%eventpar%","%eventname%","%sysname%","%bootcause%","%systime%","%systm_hm%","%systm_hm_0%","%systm_hm_sp%","%systime_am%","%systime_am_0%","%systime_am_sp%","%systm_hm_am%","%systm_hm_am_0%","%systm_hm_am_sp%","%lcltime%","%sunrise%","%s_sunrise%","%m_sunrise%","%sunset%","%s_sunset%","%m_sunset%","%lcltime_am%","%syshour%","%syshour_0%","%sysmin%","%sysmin_0%","%syssec%","%syssec_0%","%sysday%","%sysday_0%","%sysmonth%","%sysmonth_0%","%sysyear%","%sysyear_0%","%sysyears%","%sysweekday%","%sysweekday_s%","%unixtime%","%uptime%","%uptime_ms%","%rssi%","%ip%","%unit%","%unit_0%","%ssid%","%bssid%","%wi_ch%","%iswifi%","%vcc%","%mac%","%mac_int%","%isntp%","%ismqtt%","%dns%","%dns1%","%dns2%","%flash_freq%","%flash_size%","%flash_chip_vendor%","%flash_chip_model%","%fs_free%","%fs_size%","%cpu_id%","%cpu_freq%","%cpu_model%","%cpu_rev%","%cpu_cores%","%board_name%","%inttemp%","substring","indexOf","indexOf_ci","equals","equals_ci","strtol","timeToMin","timeToSec","%ethwifimode%","%ethconnected%","%ethduplex%","%ethspeed%","%ethstate%","%ethspeedstate%","%c_w_dir%","%c_c2f%","%c_ms2Bft%","%c_dew_th%","%c_alt_pres_sea%","%c_sea_pres_alt%","%c_cm2imp%","%c_mm2imp%","%c_m2day%","%c_m2dh%","%c_m2dhm%","%c_s2dhms%","%c_2hex%","%c_u2ip%","%c_uname%","%c_uage%","%c_ubuild%","%c_ubuildstr%","%c_uload%","%c_utype%","%c_utypestr%","var","int"];for(const e of pluginDispKind)commonPlugins=commonPlugins.concat(e);for(const e of pluginDispKind)for(const t of pluginDispCmd){let n=e+t;commonPlugins=commonPlugins.concat(n)}var rEdit,EXTRAWORDS=commonAtoms.concat(commonPlugins,commonKeywords,commonCommands,commonEvents,commonTag,commonNumber,commonMath,commonWarning,taskSpecifics,AnythingElse);function initCM(){CodeMirror.commands.autocomplete=function(e){e.showHint({hint:CodeMirror.hint.anyword})},(rEdit=CodeMirror.fromTextArea(document.getElementById("rules"),{tabSize:2,indentWithTabs:!1,lineNumbers:!0,autoCloseBrackets:!0,extraKeys:{"Ctrl-Space":"autocomplete",Tab:e=>{"null"===e.getMode().name?e.execCommand("insertTab"):e.somethingSelected()?e.execCommand("indentMore"):e.execCommand("insertSoftTab")},"Shift-Tab":e=>e.execCommand("indentLess")}})).on("change",(function(){rEdit.save()})),rEdit.on("inputRead",(function(e,t){var n=e.getCursor(),o=e.getTokenAt(n);/[\w%,.]/.test(t.text)&&"comment"!=o.type&&e.showHint({completeSingle:!1})}))}!function(e){"object"==typeof exports&&"object"==typeof module?e(require("codemirror")):"function"==typeof define&&define.amd?define(["codemirror"],e):e(CodeMirror)}((function(e){"use strict";e.defineMode("espeasy",(function(){var e={};function t(t,n){for(var o=0;oe.toLowerCase()));commonCommands=commonCommands.concat(n);var o=commonEvents.map((e=>e.toLowerCase()));commonEvents=commonEvents.concat(o);var i=commonPlugins.map((e=>e.toLowerCase()));commonPlugins=commonPlugins.concat(i);var r=commonAtoms.map((e=>e.toLowerCase()));commonAtoms=commonAtoms.concat(r);var a=commonKeywords.map((e=>e.toLowerCase()));commonKeywords=commonKeywords.concat(a);var s=commonTag.map((e=>e.toLowerCase()));commonTag=commonTag.concat(s);var c=commonNumber.map((e=>e.toLowerCase()));commonNumber=commonNumber.concat(c);var l=commonMath.map((e=>e.toLowerCase()));commonMath=commonMath.concat(l);var m=AnythingElse.map((e=>e.toLowerCase()));AnythingElse=AnythingElse.concat(m);var d=taskSpecifics.map((e=>e.toLowerCase()));function u(t,n){if(t.eatSpace())return null;t.sol();var o=t.next();if(/\d/.test(o)){if("0"==o)return"x"===t.next()?(t.eatWhile(/\w/),"number"):(t.eatWhile(/\d|\./),"number");if(t.eatWhile(/\d|\./),!t.match("d")&&!t.match("output")&&(t.eol()||/\D/.test(t.peek())))return"number"}if(/\w/.test(o))for(const e of EXTRAWORDS){let n=e.substring(1);(e.includes(":")||e.includes(",")||e.includes("."))&&t.match(n)}if(/\w/.test(o)&&(t.eatWhile(/[\w]/),t.match(".gpio")||t.match(".pulse")||t.match(".frq")||t.match(".pwm")))return"def";if("\\"===o)return t.next(),null;if("("===o||")"===o)return"bracket";if("{"===o||"}"===o||":"===o)return"number";if("/"==o)return/\//.test(t.peek())?(t.skipToEnd(),"comment"):"operator";if("'"==o&&(t.eatWhile(/[^']/),t.match("'")))return"attribute";if("+"===o||"="===o||"<"===o||">"===o||"-"===o||","===o||"*"===o||"!"===o)return"operator";if("%"==o){if(/\d/.test(t.next()))return"number";if(t.eatWhile(/[^\s\%]/),t.match("%"))return"hr"}if("["==o&&(t.eatWhile(/[^\s\]]/),t.eat("]")))return"hr";t.eatWhile(/\w/);var i=t.current();return/\w/.test(o)&&t.match("#")?(t.eatWhile(/[\w.#]/),"events"):"#"===o?(t.eatWhile(/\w/),"number"):e.hasOwnProperty(i)?e[i]:null}function f(e,t){return(t.tokens[0]||u)(e,t)}return taskSpecifics=taskSpecifics.concat(d),t("atom",commonAtoms),t("keyword",commonKeywords),t("builtin",commonCommands),t("events",commonEvents),t("def",commonPlugins),t("tag",commonTag),t("number",commonNumber),t("bracket",commonMath),t("warning",commonWarning),t("hr",AnythingElse),t("comment",taskSpecifics),{startState:function(){return{tokens:[]}},token:function(e,t){return f(e,t)},closeBrackets:"[]{}''\"\"``()",lineComment:"//",fold:"brace"}}))})),function(e){"object"==typeof exports&&"object"==typeof module?e(require("../../lib/codemirror")):"function"==typeof define&&define.amd?define(["../../lib/codemirror"],mod):e(CodeMirror)}((function(e){var t={pairs:"()[]{}''\"\"",closeBefore:")]}'\":;>",triples:"",explode:"[]{}"},n=e.Pos;function o(e,n){return"pairs"==n&&"string"==typeof e?e:"object"==typeof e&&null!=e[n]?e[n]:t[n]}e.defineOption("autoCloseBrackets",!1,(function(t,n,a){a&&a!=e.Init&&(t.removeKeyMap(i),t.state.closeBrackets=null),n&&(r(o(n,"pairs")),t.state.closeBrackets=n,t.addKeyMap(i))}));var i={Backspace:function(t){var i=s(t);if(!i||t.getOption("disableInput"))return e.Pass;for(var r=o(i,"pairs"),a=t.listSelections(),c=0;c=0;c--){var d=a[c].head;t.replaceRange("",n(d.line,d.ch-1),n(d.line,d.ch+1),"+delete")}},Enter:function(t){var n=s(t),i=n&&o(n,"explode");if(!i||t.getOption("disableInput"))return e.Pass;for(var r=t.listSelections(),a=0;a1&&p.indexOf(i)>=0&&t.getRange(n(M.line,M.ch-2),M)==i+i){if(M.ch>2&&/\bstring/.test(t.getTokenTypeAt(n(M.line,M.ch-2))))return e.Pass;S="addFour"}else if(h){var T=0==M.ch?" ":t.getRange(n(M.line,M.ch-1),M);if(e.isWordChar(b)||T==i||e.isWordChar(T))return e.Pass;S="both"}else{if(!x||!(0===b.length||/\s/.test(b)||f.indexOf(b)>-1))return e.Pass;S="both"}else S=h&&d(t,M)?"both":p.indexOf(i)>=0&&t.getRange(M,n(M.line,M.ch+3))==i+i+i?"skipThree":"skip";if(u){if(u!=S)return e.Pass}else u=S}var y=m%2?a.charAt(m-1):i,_=m%2?i:a.charAt(m+1);t.operation((function(){if("skip"==u)c(t,1);else if("skipThree"==u)c(t,3);else if("surround"==u){for(var e=t.getSelections(),n=0;n0?{line:a.head.line,ch:a.head.ch+t}:{line:a.head.line-1};n.push({anchor:s,head:s})}e.setSelections(n,i)}function l(t){var o=e.cmpPos(t.anchor,t.head)>0;return{anchor:new n(t.anchor.line,t.anchor.ch+(o?-1:1)),head:new n(t.head.line,t.head.ch+(o?1:-1))}}function m(e,t){var o=e.getRange(n(t.line,t.ch-1),n(t.line,t.ch+1));return 2==o.length?o:null}function d(e,t){var o=e.getTokenAt(n(t.line,t.ch+1));return/\bstring/.test(o.type)&&o.start==t.ch&&(0==t.ch||!/\bstring/.test(e.getTokenTypeAt(t)))}r(t.pairs+"`")})); \ No newline at end of file From cada1bb2e9bbbb5dd82340eaf8fd5fbc32d7bd37 Mon Sep 17 00:00:00 2001 From: chromoxdor <33860956+chromoxdor@users.noreply.github.com> Date: Wed, 13 Nov 2024 10:41:42 +0100 Subject: [PATCH 14/23] Update P049_commands.repl --- docs/source/Plugin/P049_commands.repl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/source/Plugin/P049_commands.repl b/docs/source/Plugin/P049_commands.repl index 50b744c37c..42d89f4b3f 100644 --- a/docs/source/Plugin/P049_commands.repl +++ b/docs/source/Plugin/P049_commands.repl @@ -1,5 +1,5 @@ .. csv-table:: - :header: "Command", "Examples" + :header: "Command", "Explanation" :widths: 20, 30 " From edf44f07d0fd2db55ac730ea5d126a84e3602d22 Mon Sep 17 00:00:00 2001 From: chromoxdor <33860956+chromoxdor@users.noreply.github.com> Date: Wed, 13 Nov 2024 11:11:57 +0100 Subject: [PATCH 15/23] Update P049.rst --- docs/source/Plugin/P049.rst | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/docs/source/Plugin/P049.rst b/docs/source/Plugin/P049.rst index a1e118f0cc..0d660f835b 100644 --- a/docs/source/Plugin/P049.rst +++ b/docs/source/Plugin/P049.rst @@ -26,7 +26,12 @@ Used libraries: |P049_usedlibraries| Supported hardware ------------------ -|P049_usedby| +.. ..|P049_usedby| + +MHZ-19B, +MHZ-19C, +MHZ-19D, +MHZ-19E Sensor ^^^^^^ From 5d9ef61c7a82ac3271aecfdd2b4963d6178dd92b Mon Sep 17 00:00:00 2001 From: chromoxdor <33860956+chromoxdor@users.noreply.github.com> Date: Wed, 13 Nov 2024 11:13:29 +0100 Subject: [PATCH 16/23] Update P049.rst --- docs/source/Plugin/P049.rst | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/source/Plugin/P049.rst b/docs/source/Plugin/P049.rst index 0d660f835b..d214deacf3 100644 --- a/docs/source/Plugin/P049.rst +++ b/docs/source/Plugin/P049.rst @@ -28,10 +28,10 @@ Supported hardware .. ..|P049_usedby| -MHZ-19B, -MHZ-19C, -MHZ-19D, -MHZ-19E +MH-Z19B, +MH-Z19C, +MH-Z19D, +MH-Z19E Sensor ^^^^^^ From 91fd93212fde533ab27dba301bd126fe8284cd61 Mon Sep 17 00:00:00 2001 From: chromoxdor <33860956+chromoxdor@users.noreply.github.com> Date: Wed, 13 Nov 2024 13:02:06 +0100 Subject: [PATCH 17/23] Update Command.rst --- docs/source/Reference/Command.rst | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/source/Reference/Command.rst b/docs/source/Reference/Command.rst index c552549bc5..afb01a2bcd 100644 --- a/docs/source/Reference/Command.rst +++ b/docs/source/Reference/Command.rst @@ -423,10 +423,10 @@ P048 :ref:`P048_page` .. include:: ../Plugin/P048_commands.repl -.. P049 :ref:`P049_page` -.. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +P049 :ref:`P049_page` +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -.. .. include:: ../Plugin/P049_commands.repl +.. include:: ../Plugin/P049_commands.repl .. P050 :ref:`P050_page` From 889aa835f8a8767785eee82ae6f7cbb40983ff46 Mon Sep 17 00:00:00 2001 From: TD-er Date: Wed, 13 Nov 2024 16:01:28 +0100 Subject: [PATCH 18/23] [GPIO] Fix missing check on ESP32-classic for GPIO-10 with emb. flash --- src/src/Helpers/Hardware_GPIO.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/src/Helpers/Hardware_GPIO.cpp b/src/src/Helpers/Hardware_GPIO.cpp index f86d14c973..e170d212dc 100644 --- a/src/src/Helpers/Hardware_GPIO.cpp +++ b/src/src/Helpers/Hardware_GPIO.cpp @@ -259,7 +259,7 @@ bool getGpioInfo(int gpio, int& pinnr, bool& input, bool& output, bool& warning) output = false; } - if ((gpio >= 6) && (gpio <= 11)) { + if (isFlashInterfacePin_ESPEasy(gpio)) { // Connected to the integrated SPI flash. input = false; output = false; From 20aea9656b2a41dedf9998ba60d9fc734a290010 Mon Sep 17 00:00:00 2001 From: Ton Huisman Date: Thu, 21 Nov 2024 22:05:24 +0100 Subject: [PATCH 19/23] [EasyColorCode] P020/P044/P087 serial commands --- static/espeasy.js | 4 ++++ static/espeasy.min.js | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/static/espeasy.js b/static/espeasy.js index fcba3339ff..217f39093a 100644 --- a/static/espeasy.js +++ b/static/espeasy.js @@ -31,6 +31,8 @@ var commonPlugins = [ //P019 "PCFGPIO", "PCFGPIOToggle", "PCFLongPulse", "PCFLongPulse_ms", "PCFPulse", "Status,PCF", "Monitor,PCF", "MonitorRange,PCF", "UnMonitorRange,PCF", "UnMonitor,PCF", "PCFGPIORange", "PCFGPIOpattern", "PCFMode", "PCFmodeRange", + //P020/P044 + "SerialSend", "SerialSendMix", "Ser2NetClientSend", //P022 "pcapwm", "pcafrq", "mode2", //P023 @@ -67,6 +69,8 @@ var commonPlugins = [ "GPS", "GPS,Sleep", "GPS,Wake", "GPS#GotFix", "GPS#LostFix", "GPS#Travelled", //P086 "homieValueSet", + //P087 + "SerialProxy_Write", "SerialProxy_WriteMix", "SerialProxy_Test", //P088 "HeatPumpir", //P093 diff --git a/static/espeasy.min.js b/static/espeasy.min.js index 3c405ae7ef..1325164757 100644 --- a/static/espeasy.min.js +++ b/static/espeasy.min.js @@ -1 +1 @@ -var commonAtoms=["And","Or"],commonKeywords=["If","Else","Elseif","Endif"],commonCommands=["AccessInfo","Background","Build","ClearAccessBlock","ClearRTCam","Config","ControllerDisable","ControllerEnable","DateTime","Debug","Dec","DeepSleep","DisablePriorityTask","DNS","DST","EraseSDKWiFi","ExecuteRules","FactoryReset","Gateway","I2Cscanner","Inc","IP","Let","Load","LogEntry","LogPortStatus","LoopTimerSet","LoopTimerSet_ms","MemInfo","MemInfoDetail","Name","Password","PostToHTTP","Publish","PublishR","Reboot","Save","SendTo","SendToHTTP","SendToUDP","Settings","Subnet","Subscribe","TaskClear","TaskClearAll","TaskDisable","TaskEnable","TaskRun","TaskValueSet","TaskValueSetAndRun","TimerPause","TimerResume","TimerSet","TimerSet_ms","TimeZone","UdpPort","UdpTest","Unit","UseNTP","WdConfig","WdRead","WiFi","WiFiAllowAP","WiFiAPMode","WiFiConnect","WiFiDisconnect","WiFiKey","WiFiKey2","WiFiMode","WiFiScan","WiFiSSID","WiFiSSID2","WiFiSTAMode","Event","AsyncEvent","GPIO","GPIOToggle","LongPulse","LongPulse_mS","Monitor","Pulse","PWM","Servo","Status","Tone","RTTTL","UnMonitor"],commonEvents=["Clock#Time","Login#Failed","MQTT#Connected","MQTT#Disconnected","MQTTimport#Connected","MQTTimport#Disconnected","Rules#Timer","System#Boot","System#BootMode","System#Sleep","System#Wake","TaskExit#","TaskInit#","ThingspeakReply","Time#Initialized","Time#Set","WiFi#APmodeDisabled","WiFi#APmodeEnabled","WiFi#ChangedAccesspoint","WiFi#ChangedWiFichannel","WiFi#Connected","WiFi#Disconnected"],commonPlugins=["ResetPulseCounter","SetPulseCounterTotal","LogPulseStatistic","analogout","MCPGPIO","MCPGPIOToggle","MCPLongPulse","MCPLongPulse_ms","MCPPulse","Status,MCP","Monitor,MCP","MonitorRange,MCP","UnMonitorRange,MCP","UnMonitor,MCP","MCPGPIORange","MCPGPIOPattern","MCPMode","MCPModeRange","ExtGpio","ExtPwm","ExtPulse","ExtLongPulse","Status,EXT,","LCDCmd","LCD","PCFGPIO","PCFGPIOToggle","PCFLongPulse","PCFLongPulse_ms","PCFPulse","Status,PCF","Monitor,PCF","MonitorRange,PCF","UnMonitorRange,PCF","UnMonitor,PCF","PCFGPIORange","PCFGPIOpattern","PCFMode","PCFmodeRange","pcapwm","pcafrq","mode2","OLED","OLEDCMD","OLEDCMD,on","OLEDCMD,off","OLEDCMD,clear","IRSEND","IRSENDAC","OledFramedCmd","OledFramedCmd,Display","OledFramedCmd,low","OledFramedCmd,med","OledFramedCmd,high","OledFramedCmd,Frame","OledFramedCmd,linecount","OledFramedCmd,leftalign","OledFramedCmd,align","OledFramedCmd,userDef1","OledFramedCmd,userDef2","NeoPixel","NeoPixelAll","NeoPixelLine","NeoPixelHSV","NeoPixelAllHSV","NeoPixelLineHSV","NeoPixelBright","MotorShieldCmd,DCMotor","MotorShieldCmd,Stepper","MHZCalibrateZero","MHZReset","MHZABCEnable","MHZABCDisable","Sensair_SetRelay","PMSX003","PMSX003,Wake","PMSX003,Sleep","PMSX003,Reset","encwrite","Play","Vol","Eq","Mode","Repeat","tareChanA","tareChanB","7dn","7dst","7dsd","7dtext","7ddt","7dt","7dtfont","7dtbin","7don","7doff","7output","HLWCalibrate","HLWReset","csecalibrate","cseclearpulses","csereset","WemosMotorShieldCMD","LolinMotorShieldCMD","GPS","GPS,Sleep","GPS,Wake","GPS#GotFix","GPS#LostFix","GPS#Travelled","homieValueSet","HeatPumpir","MitsubishiHP","MitsubishiHP,temperature","MitsubishiHP,power","MitsubishiHP,mode","MitsubishiHP,fan","MitsubishiHP,vane","MitsubishiHP,widevane","Culreader_Write","Touch","Touch,Rot","Touch,Flip","Touch,Enable","Touch,Disable","Touch,On","Touch,Off","Touch,Toggle","Touch,Setgrp","Touch,Incgrp","Touch,Decgrp","Touch,Incpage","Touch,Decpage","Touch,Updatebutton","WakeOnLan","DotMatrix","DotMatrix,clear","DotMatrix,update","DotMatrix,size","DotMatrix,txt","DotMatrix,settxt","DotMatrix,content","DotMatrix,alignment","DotMatrix,anim.in","DotMatrix,anim.out","DotMatrix,speed","DotMatrix,pause","DotMatrix,font","DotMatrix,layout","DotMatrix,inverted","DotMatrix,specialeffect","DotMatrix,offset","DotMatrix,brightness","DotMatrix,repeat","DotMatrix,setbar","DotMatrix,bar","Thermo","Thermo,Up","Thermo,Down","Thermo,Mode","Thermo,ModeBtn","Thermo,Setpoint","Max1704xclearalert","scdgetabc","scdgetalt","scdgettmp","scdsetcalibration","scdsetfrc","scdgetinterval","multirelay","multirelay,on","multirelay,off","multirelay,set","multirelay,get","multirelay,loop","ShiftOut","ShiftOut,Set","ShiftOut,SetNoUpdate","ShiftOut,Update","ShiftOut,SetAll","ShiftOut,SetAllNoUpdate","ShiftOut,SetAllLow","ShiftOut,SetAllHigh","ShiftOut,SetChipCount","ShiftOut,SetHexBin","cdmrst","nfx","nfx,off","nfx,on","nfx,dim","nfx,line,","nfx,hsvline,","nfx,one,","nfx,hsvone,","nfx,all,","nfx,rgb,","nfx,fade,","nfx,hsv,","nfx,colorfade,","nfx,rainbow","nfx,kitt,","nfx,comet,","nfx,theatre,","nfx,scan,","nfx,dualscan,","nfx,twinkle,","nfx,twinklefade,","nfx,sparkle,","nfx,wipe,","nfx,dualwipe","nfx,fire","nfx,fireflicker","nfx,faketv","nfx,simpleclock","nfx,stop","nfx,statusrequest","nfx,fadetime,","nfx,fadedelay,","nfx,speed,","nfx,count,","nfx,bgcolor","ShiftIn","ShiftIn,PinEvent","ShiftIn,ChipEvent","ShiftIn,SetChipCount","ShiftIn,SampleFrequency","ShiftIn,EventPerPin","scd4x","scd4x,storesettings","scd4x,facoryreset","scd4x,selftest","scd4x,setfrc,","axp","axp,ldo2","axp,ldo3","axp,ldoio","axp,gpio0","axp,gpio1","axp,gpio2","axp,gpio3","axp,gpio4","axp,dcdc2","axp,dcdc3","axp,ldo2map","axp,ldo3map","axp,ldoiomap","axp,dcdc2map","axp,dcdc3map","axp,ldo2perc","axp,ldo3perc","axp,ldoioperc","axp,dcdc2perc","axp,dcdc3perc","I2CEncoder","I2CEncoder,bright","I2CEncoder,led1","I2CEncoder,led2","I2CEncoder,gain","I2CEncoder,set","cachereader","cachereader,readpos","cachereader,sendtaskinfo","cachereader,flush","tm1621","tm1621,write,","tm1621,writerow,","tm1621,voltamp,","tm1621,energy,","tm1621,celcius,","tm1621,fahrenheit,","tm1621,humidity,","tm1621,raw,","dac","dac,1","dac,2","sht4x","sht4x,startup","ld2410","ld2410,factoryreset","ld2410,logall","digipot","digipot,reset","digipot,shutdown","digipot,","7dextra","7dbefore","7dgroup","7digit","7color","7digitcolor","7groupcolor","gp8403","gp8403,volt,","gp8403,mvolt,","gp8403,range,","gp8403,preset,","gp8403,init,","sen5x","sen5x,startclean","sen5x,techlog,"],pluginDispKind=["tft","ili9341","ili9342","ili9481","ili9486","ili9488","epd","eink","epaper","il3897","uc8151d","ssd1680","ws2in7","ws1in54","st77xx","st7735","st7789","st7796","neomatrix","neo","pcd8544"],pluginDispCmd=["cmd,on","cmd,off","cmd,clear","cmd,backlight","cmd,bright","cmd,deepsleep","cmd,seq_start","cmd,seq_end","cmd,inv","cmd,rot",",clear",",rot",",tpm",",txt",",txp",",txz",",txc",",txs",",txtfull",",asciitable",",font",",l",",lh",",lv",",lm",",lmr",",r",",rf",",c",",cf",",rf",",t",",tf",",rr",",rrf",",px",",pxh",",pxv",",bmp",",btn",",win",",defwin",",delwin"],commonTag=["On","Do","Endon"],commonNumber=["toBin","toHex","Constrain","XOR","AND:","OR:","Ord","bitRead","bitSet","bitClear","bitWrite","urlencode"],commonMath=["Log","Ln","Abs","Exp","Sqrt","Sq","Round","Sin","Cos","Tan","aSin","aCos","aTan","Sin_d","Cos_d","Tan_d","aSin_d","aCos_d","aTan_d"],commonWarning=["delay","Delay","ResetFlashWriteCounter"],taskSpecifics=["settings.Enabled","settings.Interval","settings.ValueCount","settings.Controller1.Enabled","settings.Controller2.Enabled","settings.Controller3.Enabled","settings.Controller1.Idx","settings.Controller2.Idx","settings.Controller3.Idx"],AnythingElse=["%eventvalue%","%eventpar%","%eventname%","%sysname%","%bootcause%","%systime%","%systm_hm%","%systm_hm_0%","%systm_hm_sp%","%systime_am%","%systime_am_0%","%systime_am_sp%","%systm_hm_am%","%systm_hm_am_0%","%systm_hm_am_sp%","%lcltime%","%sunrise%","%s_sunrise%","%m_sunrise%","%sunset%","%s_sunset%","%m_sunset%","%lcltime_am%","%syshour%","%syshour_0%","%sysmin%","%sysmin_0%","%syssec%","%syssec_0%","%sysday%","%sysday_0%","%sysmonth%","%sysmonth_0%","%sysyear%","%sysyear_0%","%sysyears%","%sysweekday%","%sysweekday_s%","%unixtime%","%uptime%","%uptime_ms%","%rssi%","%ip%","%unit%","%unit_0%","%ssid%","%bssid%","%wi_ch%","%iswifi%","%vcc%","%mac%","%mac_int%","%isntp%","%ismqtt%","%dns%","%dns1%","%dns2%","%flash_freq%","%flash_size%","%flash_chip_vendor%","%flash_chip_model%","%fs_free%","%fs_size%","%cpu_id%","%cpu_freq%","%cpu_model%","%cpu_rev%","%cpu_cores%","%board_name%","%inttemp%","substring","indexOf","indexOf_ci","equals","equals_ci","strtol","timeToMin","timeToSec","%ethwifimode%","%ethconnected%","%ethduplex%","%ethspeed%","%ethstate%","%ethspeedstate%","%c_w_dir%","%c_c2f%","%c_ms2Bft%","%c_dew_th%","%c_alt_pres_sea%","%c_sea_pres_alt%","%c_cm2imp%","%c_mm2imp%","%c_m2day%","%c_m2dh%","%c_m2dhm%","%c_s2dhms%","%c_2hex%","%c_u2ip%","%c_uname%","%c_uage%","%c_ubuild%","%c_ubuildstr%","%c_uload%","%c_utype%","%c_utypestr%","var","int"];for(const e of pluginDispKind)commonPlugins=commonPlugins.concat(e);for(const e of pluginDispKind)for(const t of pluginDispCmd){let n=e+t;commonPlugins=commonPlugins.concat(n)}var rEdit,EXTRAWORDS=commonAtoms.concat(commonPlugins,commonKeywords,commonCommands,commonEvents,commonTag,commonNumber,commonMath,commonWarning,taskSpecifics,AnythingElse);function initCM(){CodeMirror.commands.autocomplete=function(e){e.showHint({hint:CodeMirror.hint.anyword})},(rEdit=CodeMirror.fromTextArea(document.getElementById("rules"),{tabSize:2,indentWithTabs:!1,lineNumbers:!0,autoCloseBrackets:!0,extraKeys:{"Ctrl-Space":"autocomplete",Tab:e=>{"null"===e.getMode().name?e.execCommand("insertTab"):e.somethingSelected()?e.execCommand("indentMore"):e.execCommand("insertSoftTab")},"Shift-Tab":e=>e.execCommand("indentLess")}})).on("change",(function(){rEdit.save()})),rEdit.on("inputRead",(function(e,t){var n=e.getCursor(),o=e.getTokenAt(n);/[\w%,.]/.test(t.text)&&"comment"!=o.type&&e.showHint({completeSingle:!1})}))}!function(e){"object"==typeof exports&&"object"==typeof module?e(require("codemirror")):"function"==typeof define&&define.amd?define(["codemirror"],e):e(CodeMirror)}((function(e){"use strict";e.defineMode("espeasy",(function(){var e={};function t(t,n){for(var o=0;oe.toLowerCase()));commonCommands=commonCommands.concat(n);var o=commonEvents.map((e=>e.toLowerCase()));commonEvents=commonEvents.concat(o);var i=commonPlugins.map((e=>e.toLowerCase()));commonPlugins=commonPlugins.concat(i);var r=commonAtoms.map((e=>e.toLowerCase()));commonAtoms=commonAtoms.concat(r);var a=commonKeywords.map((e=>e.toLowerCase()));commonKeywords=commonKeywords.concat(a);var s=commonTag.map((e=>e.toLowerCase()));commonTag=commonTag.concat(s);var c=commonNumber.map((e=>e.toLowerCase()));commonNumber=commonNumber.concat(c);var l=commonMath.map((e=>e.toLowerCase()));commonMath=commonMath.concat(l);var m=AnythingElse.map((e=>e.toLowerCase()));AnythingElse=AnythingElse.concat(m);var d=taskSpecifics.map((e=>e.toLowerCase()));function u(t,n){if(t.eatSpace())return null;t.sol();var o=t.next();if(/\d/.test(o)){if("0"==o)return"x"===t.next()?(t.eatWhile(/\w/),"number"):(t.eatWhile(/\d|\./),"number");if(t.eatWhile(/\d|\./),!t.match("d")&&!t.match("output")&&(t.eol()||/\D/.test(t.peek())))return"number"}if(/\w/.test(o))for(const e of EXTRAWORDS){let n=e.substring(1);(e.includes(":")||e.includes(",")||e.includes("."))&&t.match(n)}if(/\w/.test(o)&&(t.eatWhile(/[\w]/),t.match(".gpio")||t.match(".pulse")||t.match(".frq")||t.match(".pwm")))return"def";if("\\"===o)return t.next(),null;if("("===o||")"===o)return"bracket";if("{"===o||"}"===o||":"===o)return"number";if("/"==o)return/\//.test(t.peek())?(t.skipToEnd(),"comment"):"operator";if("'"==o&&(t.eatWhile(/[^']/),t.match("'")))return"attribute";if("+"===o||"="===o||"<"===o||">"===o||"-"===o||","===o||"*"===o||"!"===o)return"operator";if("%"==o){if(/\d/.test(t.next()))return"number";if(t.eatWhile(/[^\s\%]/),t.match("%"))return"hr"}if("["==o&&(t.eatWhile(/[^\s\]]/),t.eat("]")))return"hr";t.eatWhile(/\w/);var i=t.current();return/\w/.test(o)&&t.match("#")?(t.eatWhile(/[\w.#]/),"events"):"#"===o?(t.eatWhile(/\w/),"number"):e.hasOwnProperty(i)?e[i]:null}function f(e,t){return(t.tokens[0]||u)(e,t)}return taskSpecifics=taskSpecifics.concat(d),t("atom",commonAtoms),t("keyword",commonKeywords),t("builtin",commonCommands),t("events",commonEvents),t("def",commonPlugins),t("tag",commonTag),t("number",commonNumber),t("bracket",commonMath),t("warning",commonWarning),t("hr",AnythingElse),t("comment",taskSpecifics),{startState:function(){return{tokens:[]}},token:function(e,t){return f(e,t)},closeBrackets:"[]{}''\"\"``()",lineComment:"//",fold:"brace"}}))})),function(e){"object"==typeof exports&&"object"==typeof module?e(require("../../lib/codemirror")):"function"==typeof define&&define.amd?define(["../../lib/codemirror"],mod):e(CodeMirror)}((function(e){var t={pairs:"()[]{}''\"\"",closeBefore:")]}'\":;>",triples:"",explode:"[]{}"},n=e.Pos;function o(e,n){return"pairs"==n&&"string"==typeof e?e:"object"==typeof e&&null!=e[n]?e[n]:t[n]}e.defineOption("autoCloseBrackets",!1,(function(t,n,a){a&&a!=e.Init&&(t.removeKeyMap(i),t.state.closeBrackets=null),n&&(r(o(n,"pairs")),t.state.closeBrackets=n,t.addKeyMap(i))}));var i={Backspace:function(t){var i=s(t);if(!i||t.getOption("disableInput"))return e.Pass;for(var r=o(i,"pairs"),a=t.listSelections(),c=0;c=0;c--){var d=a[c].head;t.replaceRange("",n(d.line,d.ch-1),n(d.line,d.ch+1),"+delete")}},Enter:function(t){var n=s(t),i=n&&o(n,"explode");if(!i||t.getOption("disableInput"))return e.Pass;for(var r=t.listSelections(),a=0;a1&&p.indexOf(i)>=0&&t.getRange(n(M.line,M.ch-2),M)==i+i){if(M.ch>2&&/\bstring/.test(t.getTokenTypeAt(n(M.line,M.ch-2))))return e.Pass;S="addFour"}else if(h){var T=0==M.ch?" ":t.getRange(n(M.line,M.ch-1),M);if(e.isWordChar(b)||T==i||e.isWordChar(T))return e.Pass;S="both"}else{if(!x||!(0===b.length||/\s/.test(b)||f.indexOf(b)>-1))return e.Pass;S="both"}else S=h&&d(t,M)?"both":p.indexOf(i)>=0&&t.getRange(M,n(M.line,M.ch+3))==i+i+i?"skipThree":"skip";if(u){if(u!=S)return e.Pass}else u=S}var y=m%2?a.charAt(m-1):i,_=m%2?i:a.charAt(m+1);t.operation((function(){if("skip"==u)c(t,1);else if("skipThree"==u)c(t,3);else if("surround"==u){for(var e=t.getSelections(),n=0;n0?{line:a.head.line,ch:a.head.ch+t}:{line:a.head.line-1};n.push({anchor:s,head:s})}e.setSelections(n,i)}function l(t){var o=e.cmpPos(t.anchor,t.head)>0;return{anchor:new n(t.anchor.line,t.anchor.ch+(o?-1:1)),head:new n(t.head.line,t.head.ch+(o?1:-1))}}function m(e,t){var o=e.getRange(n(t.line,t.ch-1),n(t.line,t.ch+1));return 2==o.length?o:null}function d(e,t){var o=e.getTokenAt(n(t.line,t.ch+1));return/\bstring/.test(o.type)&&o.start==t.ch&&(0==t.ch||!/\bstring/.test(e.getTokenTypeAt(t)))}r(t.pairs+"`")})); \ No newline at end of file +var rEdit,commonAtoms=["And","Or"],commonKeywords=["If","Else","Elseif","Endif"],commonCommands=["AccessInfo","Background","Build","ClearAccessBlock","ClearRTCam","Config","ControllerDisable","ControllerEnable","DateTime","Debug","Dec","DeepSleep","DisablePriorityTask","DNS","DST","EraseSDKWiFi","ExecuteRules","FactoryReset","Gateway","I2Cscanner","Inc","IP","Let","Load","LogEntry","LogPortStatus","LoopTimerSet","LoopTimerSet_ms","MemInfo","MemInfoDetail","Name","Password","PostToHTTP","Publish","PublishR","Reboot","Save","SendTo","SendToHTTP","SendToUDP","Settings","Subnet","Subscribe","TaskClear","TaskClearAll","TaskDisable","TaskEnable","TaskRun","TaskValueSet","TaskValueSetAndRun","TimerPause","TimerResume","TimerSet","TimerSet_ms","TimeZone","UdpPort","UdpTest","Unit","UseNTP","WdConfig","WdRead","WiFi","WiFiAllowAP","WiFiAPMode","WiFiConnect","WiFiDisconnect","WiFiKey","WiFiKey2","WiFiMode","WiFiScan","WiFiSSID","WiFiSSID2","WiFiSTAMode","Event","AsyncEvent","GPIO","GPIOToggle","LongPulse","LongPulse_mS","Monitor","Pulse","PWM","Servo","Status","Tone","RTTTL","UnMonitor",],commonEvents=["Clock#Time","Login#Failed","MQTT#Connected","MQTT#Disconnected","MQTTimport#Connected","MQTTimport#Disconnected","Rules#Timer","System#Boot","System#BootMode","System#Sleep","System#Wake","TaskExit#","TaskInit#","ThingspeakReply","Time#Initialized","Time#Set","WiFi#APmodeDisabled","WiFi#APmodeEnabled","WiFi#ChangedAccesspoint","WiFi#ChangedWiFichannel","WiFi#Connected","WiFi#Disconnected"],commonPlugins=["ResetPulseCounter","SetPulseCounterTotal","LogPulseStatistic","analogout","MCPGPIO","MCPGPIOToggle","MCPLongPulse","MCPLongPulse_ms","MCPPulse","Status,MCP","Monitor,MCP","MonitorRange,MCP","UnMonitorRange,MCP","UnMonitor,MCP","MCPGPIORange","MCPGPIOPattern","MCPMode","MCPModeRange","ExtGpio","ExtPwm","ExtPulse","ExtLongPulse","Status,EXT,","LCDCmd","LCD","PCFGPIO","PCFGPIOToggle","PCFLongPulse","PCFLongPulse_ms","PCFPulse","Status,PCF","Monitor,PCF","MonitorRange,PCF","UnMonitorRange,PCF","UnMonitor,PCF","PCFGPIORange","PCFGPIOpattern","PCFMode","PCFmodeRange","SerialSend","SerialSendMix","Ser2NetClientSend","pcapwm","pcafrq","mode2","OLED","OLEDCMD","OLEDCMD,on","OLEDCMD,off","OLEDCMD,clear","IRSEND","IRSENDAC","OledFramedCmd","OledFramedCmd,Display","OledFramedCmd,low","OledFramedCmd,med","OledFramedCmd,high","OledFramedCmd,Frame","OledFramedCmd,linecount","OledFramedCmd,leftalign","OledFramedCmd,align","OledFramedCmd,userDef1","OledFramedCmd,userDef2","NeoPixel","NeoPixelAll","NeoPixelLine","NeoPixelHSV","NeoPixelAllHSV","NeoPixelLineHSV","NeoPixelBright","MotorShieldCmd,DCMotor","MotorShieldCmd,Stepper","MHZCalibrateZero","MHZReset","MHZABCEnable","MHZABCDisable","Sensair_SetRelay","PMSX003","PMSX003,Wake","PMSX003,Sleep","PMSX003,Reset","encwrite","Play","Vol","Eq","Mode","Repeat","tareChanA","tareChanB","7dn","7dst","7dsd","7dtext","7ddt","7dt","7dtfont","7dtbin","7don","7doff","7output","HLWCalibrate","HLWReset","csecalibrate","cseclearpulses","csereset","WemosMotorShieldCMD","LolinMotorShieldCMD","GPS","GPS,Sleep","GPS,Wake","GPS#GotFix","GPS#LostFix","GPS#Travelled","homieValueSet","SerialProxy_Write","SerialProxy_WriteMix","SerialProxy_Test","HeatPumpir","MitsubishiHP","MitsubishiHP,temperature","MitsubishiHP,power","MitsubishiHP,mode","MitsubishiHP,fan","MitsubishiHP,vane","MitsubishiHP,widevane","Culreader_Write","Touch","Touch,Rot","Touch,Flip","Touch,Enable","Touch,Disable","Touch,On","Touch,Off","Touch,Toggle","Touch,Setgrp","Touch,Incgrp","Touch,Decgrp","Touch,Incpage","Touch,Decpage","Touch,Updatebutton","WakeOnLan","DotMatrix","DotMatrix,clear","DotMatrix,update","DotMatrix,size","DotMatrix,txt","DotMatrix,settxt","DotMatrix,content","DotMatrix,alignment","DotMatrix,anim.in","DotMatrix,anim.out","DotMatrix,speed","DotMatrix,pause","DotMatrix,font","DotMatrix,layout","DotMatrix,inverted","DotMatrix,specialeffect","DotMatrix,offset","DotMatrix,brightness","DotMatrix,repeat","DotMatrix,setbar","DotMatrix,bar","Thermo","Thermo,Up","Thermo,Down","Thermo,Mode","Thermo,ModeBtn","Thermo,Setpoint","Max1704xclearalert","scdgetabc","scdgetalt","scdgettmp","scdsetcalibration","scdsetfrc","scdgetinterval","multirelay","multirelay,on","multirelay,off","multirelay,set","multirelay,get","multirelay,loop","ShiftOut","ShiftOut,Set","ShiftOut,SetNoUpdate","ShiftOut,Update","ShiftOut,SetAll","ShiftOut,SetAllNoUpdate","ShiftOut,SetAllLow","ShiftOut,SetAllHigh","ShiftOut,SetChipCount","ShiftOut,SetHexBin","cdmrst","nfx","nfx,off","nfx,on","nfx,dim","nfx,line,","nfx,hsvline,","nfx,one,","nfx,hsvone,","nfx,all,","nfx,rgb,","nfx,fade,","nfx,hsv,","nfx,colorfade,","nfx,rainbow","nfx,kitt,","nfx,comet,","nfx,theatre,","nfx,scan,","nfx,dualscan,","nfx,twinkle,","nfx,twinklefade,","nfx,sparkle,","nfx,wipe,","nfx,dualwipe","nfx,fire","nfx,fireflicker","nfx,faketv","nfx,simpleclock","nfx,stop","nfx,statusrequest","nfx,fadetime,","nfx,fadedelay,","nfx,speed,","nfx,count,","nfx,bgcolor","ShiftIn","ShiftIn,PinEvent","ShiftIn,ChipEvent","ShiftIn,SetChipCount","ShiftIn,SampleFrequency","ShiftIn,EventPerPin","scd4x","scd4x,storesettings","scd4x,facoryreset","scd4x,selftest","scd4x,setfrc,","axp","axp,ldo2","axp,ldo3","axp,ldoio","axp,gpio0","axp,gpio1","axp,gpio2","axp,gpio3","axp,gpio4","axp,dcdc2","axp,dcdc3","axp,ldo2map","axp,ldo3map","axp,ldoiomap","axp,dcdc2map","axp,dcdc3map","axp,ldo2perc","axp,ldo3perc","axp,ldoioperc","axp,dcdc2perc","axp,dcdc3perc","I2CEncoder","I2CEncoder,bright","I2CEncoder,led1","I2CEncoder,led2","I2CEncoder,gain","I2CEncoder,set","cachereader","cachereader,readpos","cachereader,sendtaskinfo","cachereader,flush","tm1621","tm1621,write,","tm1621,writerow,","tm1621,voltamp,","tm1621,energy,","tm1621,celcius,","tm1621,fahrenheit,","tm1621,humidity,","tm1621,raw,","dac","dac,1","dac,2","sht4x","sht4x,startup","ld2410","ld2410,factoryreset","ld2410,logall","digipot","digipot,reset","digipot,shutdown","digipot,","7dextra","7dbefore","7dgroup","7digit","7color","7digitcolor","7groupcolor","gp8403","gp8403,volt,","gp8403,mvolt,","gp8403,range,","gp8403,preset,","gp8403,init,","sen5x","sen5x,startclean","sen5x,techlog,",],pluginDispKind=["tft","ili9341","ili9342","ili9481","ili9486","ili9488","epd","eink","epaper","il3897","uc8151d","ssd1680","ws2in7","ws1in54","st77xx","st7735","st7789","st7796","neomatrix","neo","pcd8544",],pluginDispCmd=["cmd,on","cmd,off","cmd,clear","cmd,backlight","cmd,bright","cmd,deepsleep","cmd,seq_start","cmd,seq_end","cmd,inv","cmd,rot",",clear",",rot",",tpm",",txt",",txp",",txz",",txc",",txs",",txtfull",",asciitable",",font",",l",",lh",",lv",",lm",",lmr",",r",",rf",",c",",cf",",rf",",t",",tf",",rr",",rrf",",px",",pxh",",pxv",",bmp",",btn",",win",",defwin",",delwin",],commonTag=["On","Do","Endon"],commonNumber=["toBin","toHex","Constrain","XOR","AND:","OR:","Ord","bitRead","bitSet","bitClear","bitWrite","urlencode"],commonMath=["Log","Ln","Abs","Exp","Sqrt","Sq","Round","Sin","Cos","Tan","aSin","aCos","aTan","Sin_d","Cos_d","Tan_d","aSin_d","aCos_d","aTan_d"],commonWarning=["delay","Delay","ResetFlashWriteCounter"],taskSpecifics=["settings.Enabled","settings.Interval","settings.ValueCount","settings.Controller1.Enabled","settings.Controller2.Enabled","settings.Controller3.Enabled","settings.Controller1.Idx","settings.Controller2.Idx","settings.Controller3.Idx"],AnythingElse=["%eventvalue%","%eventpar%","%eventname%","%sysname%","%bootcause%","%systime%","%systm_hm%","%systm_hm_0%","%systm_hm_sp%","%systime_am%","%systime_am_0%","%systime_am_sp%","%systm_hm_am%","%systm_hm_am_0%","%systm_hm_am_sp%","%lcltime%","%sunrise%","%s_sunrise%","%m_sunrise%","%sunset%","%s_sunset%","%m_sunset%","%lcltime_am%","%syshour%","%syshour_0%","%sysmin%","%sysmin_0%","%syssec%","%syssec_0%","%sysday%","%sysday_0%","%sysmonth%","%sysmonth_0%","%sysyear%","%sysyear_0%","%sysyears%","%sysweekday%","%sysweekday_s%","%unixtime%","%uptime%","%uptime_ms%","%rssi%","%ip%","%unit%","%unit_0%","%ssid%","%bssid%","%wi_ch%","%iswifi%","%vcc%","%mac%","%mac_int%","%isntp%","%ismqtt%","%dns%","%dns1%","%dns2%","%flash_freq%","%flash_size%","%flash_chip_vendor%","%flash_chip_model%","%fs_free%","%fs_size%","%cpu_id%","%cpu_freq%","%cpu_model%","%cpu_rev%","%cpu_cores%","%board_name%","%inttemp%","substring","indexOf","indexOf_ci","equals","equals_ci","strtol","timeToMin","timeToSec","%ethwifimode%","%ethconnected%","%ethduplex%","%ethspeed%","%ethstate%","%ethspeedstate%","%c_w_dir%","%c_c2f%","%c_ms2Bft%","%c_dew_th%","%c_alt_pres_sea%","%c_sea_pres_alt%","%c_cm2imp%","%c_mm2imp%","%c_m2day%","%c_m2dh%","%c_m2dhm%","%c_s2dhms%","%c_2hex%","%c_u2ip%","%c_uname%","%c_uage%","%c_ubuild%","%c_ubuildstr%","%c_uload%","%c_utype%","%c_utypestr%","var","int"];for(const element2 of pluginDispKind)commonPlugins=commonPlugins.concat(element2);for(const element2 of pluginDispKind)for(const element3 of pluginDispCmd){let e=element2+element3;commonPlugins=commonPlugins.concat(e)}var EXTRAWORDS=commonAtoms.concat(commonPlugins,commonKeywords,commonCommands,commonEvents,commonTag,commonNumber,commonMath,commonWarning,taskSpecifics,AnythingElse);function initCM(){CodeMirror.commands.autocomplete=function(e){e.showHint({hint:CodeMirror.hint.anyword})},(rEdit=CodeMirror.fromTextArea(document.getElementById("rules"),{tabSize:2,indentWithTabs:!1,lineNumbers:!0,autoCloseBrackets:!0,extraKeys:{"Ctrl-Space":"autocomplete",Tab(e){"null"===e.getMode().name?e.execCommand("insertTab"):e.somethingSelected()?e.execCommand("indentMore"):e.execCommand("insertSoftTab")},"Shift-Tab":e=>e.execCommand("indentLess")}})).on("change",function(){rEdit.save()}),rEdit.on("inputRead",function(e,t){var n=e.getCursor(),o=e.getTokenAt(n);/[\w%,.]/.test(t.text)&&"comment"!=o.type&&e.showHint({completeSingle:!1})})}!function(e){"object"==typeof exports&&"object"==typeof module?e(require("codemirror")):"function"==typeof define&&define.amd?define(["codemirror"],e):e(CodeMirror)}(function(e){"use strict";e.defineMode("espeasy",function(){var e={};function t(t,n){for(var o=0;oe.toLowerCase());commonCommands=commonCommands.concat(n);var o=commonEvents.map(e=>e.toLowerCase());commonEvents=commonEvents.concat(o);var i=commonPlugins.map(e=>e.toLowerCase());commonPlugins=commonPlugins.concat(i);var a=commonAtoms.map(e=>e.toLowerCase());commonAtoms=commonAtoms.concat(a);var r=commonKeywords.map(e=>e.toLowerCase());commonKeywords=commonKeywords.concat(r);var s=commonTag.map(e=>e.toLowerCase());commonTag=commonTag.concat(s);var c=commonNumber.map(e=>e.toLowerCase());commonNumber=commonNumber.concat(c);var l=commonMath.map(e=>e.toLowerCase());commonMath=commonMath.concat(l);var m=AnythingElse.map(e=>e.toLowerCase());AnythingElse=AnythingElse.concat(m);var d=taskSpecifics.map(e=>e.toLowerCase());function u(t,n){if(t.eatSpace())return null;t.sol();var o=t.next();if(/\d/.test(o)){if("0"==o)return"x"===t.next()?(t.eatWhile(/\w/),"number"):(t.eatWhile(/\d|\./),"number");if(t.eatWhile(/\d|\./),!t.match("d")&&!t.match("output")&&(t.eol()||/\D/.test(t.peek())))return"number"}if(/\w/.test(o))for(let i of EXTRAWORDS){let a=i.substring(1);(i.includes(":")||i.includes(",")||i.includes("."))&&t.match(a)}if(/\w/.test(o)&&(t.eatWhile(/[\w]/),t.match(".gpio")||t.match(".pulse")||t.match(".frq")||t.match(".pwm")))return"def";if("\\"===o)return t.next(),null;if("("===o||")"===o)return"bracket";if("{"===o||"}"===o||":"===o)return"number";if("/"==o)return/\//.test(t.peek())?(t.skipToEnd(),"comment"):"operator";if("'"==o&&(t.eatWhile(/[^']/),t.match("'")))return"attribute";if("+"===o||"="===o||"<"===o||">"===o||"-"===o||","===o||"*"===o||"!"===o)return"operator";if("%"==o){if(/\d/.test(t.next()))return"number";if(t.eatWhile(/[^\s\%]/),t.match("%"))return"hr"}if("["==o&&(t.eatWhile(/[^\s\]]/),t.eat("]")))return"hr";t.eatWhile(/\w/);var r=t.current();return/\w/.test(o)&&t.match("#")?(t.eatWhile(/[\w.#]/),"events"):"#"===o?(t.eatWhile(/\w/),"number"):e.hasOwnProperty(r)?e[r]:null}return taskSpecifics=taskSpecifics.concat(d),t("atom",commonAtoms),t("keyword",commonKeywords),t("builtin",commonCommands),t("events",commonEvents),t("def",commonPlugins),t("tag",commonTag),t("number",commonNumber),t("bracket",commonMath),t("warning",commonWarning),t("hr",AnythingElse),t("comment",taskSpecifics),{startState:function(){return{tokens:[]}},token:function(e,t){var n,o;return n=e,((o=t).tokens[0]||u)(n,o)},closeBrackets:"[]{}''\"\"``()",lineComment:"//",fold:"brace"}})}),function(e){"object"==typeof exports&&"object"==typeof module?e(require("../../lib/codemirror")):"function"==typeof define&&define.amd?define(["../../lib/codemirror"],mod):e(CodeMirror)}(function(e){var t={pairs:"()[]{}''\"\"",closeBefore:")]}'\":;>",triples:"",explode:"[]{}"},n=e.Pos;function o(e,n){return"pairs"==n&&"string"==typeof e?e:"object"==typeof e&&null!=e[n]?e[n]:t[n]}e.defineOption("autoCloseBrackets",!1,function(t,n,r){r&&r!=e.Init&&(t.removeKeyMap(i),t.state.closeBrackets=null),n&&(a(o(n,"pairs")),t.state.closeBrackets=n,t.addKeyMap(i))});var i={Backspace:function t(i){var a=s(i);if(!a||i.getOption("disableInput"))return e.Pass;for(var r=o(a,"pairs"),c=i.listSelections(),l=0;l=0;l--){var u=c[l].head;i.replaceRange("",n(u.line,u.ch-1),n(u.line,u.ch+1),"+delete")}},Enter:function t(n){var i=s(n),a=i&&o(i,"explode");if(!a||n.getOption("disableInput"))return e.Pass;for(var r=n.listSelections(),l=0;l=0&&i.getRange(T,n(T.line,T.ch+3))==a+a+a?"skipThree":"skip";else if(h&&T.ch>1&&p.indexOf(a)>=0&&i.getRange(n(T.line,T.ch-2),T)==a+a){if(T.ch>2&&/\bstring/.test(i.getTokenTypeAt(n(T.line,T.ch-2))))return e.Pass;P="addFour"}else if(h){var y=0==T.ch?" ":i.getRange(n(T.line,T.ch-1),T);if(e.isWordChar(b)||y==a||e.isWordChar(y))return e.Pass;P="both"}else{if(!(x&&(0===b.length||/\s/.test(b)||f.indexOf(b)>-1)))return e.Pass;P="both"}if(C){if(C!=P)return e.Pass}else C=P}var v=u%2?m.charAt(u-1):a,D=u%2?a:m.charAt(u+1);i.operation(function(){if("skip"==C)c(i,1);else if("skipThree"==C)c(i,3);else if("surround"==C){for(var e=i.getSelections(),t=0;t0?{line:r.head.line,ch:r.head.ch+t}:{line:r.head.line-1};n.push({anchor:s,head:s})}e.setSelections(n,i)}function l(t){var o=e.cmpPos(t.anchor,t.head)>0;return{anchor:new n(t.anchor.line,t.anchor.ch+(o?-1:1)),head:new n(t.head.line,t.head.ch+(o?1:-1))}}function m(e,t){var o=e.getRange(n(t.line,t.ch-1),n(t.line,t.ch+1));return 2==o.length?o:null}function d(e,t){var o=e.getTokenAt(n(t.line,t.ch+1));return/\bstring/.test(o.type)&&o.start==t.ch&&(0==t.ch||!/\bstring/.test(e.getTokenTypeAt(t)))}a(t.pairs+"`")}); \ No newline at end of file From d44a308aa0bbeecdd66a5c4466f67bcd7054c2cb Mon Sep 17 00:00:00 2001 From: Ton Huisman Date: Sat, 23 Nov 2024 22:04:56 +0100 Subject: [PATCH 20/23] [P020] Fix docs typo --- docs/source/Plugin/P020.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/source/Plugin/P020.rst b/docs/source/Plugin/P020.rst index 0373e404db..65f75a347a 100644 --- a/docs/source/Plugin/P020.rst +++ b/docs/source/Plugin/P020.rst @@ -81,7 +81,7 @@ When selecting the **Event processing** options *Generic* or *RFLink*, after sub * *(Unchecked)* -> ``Serial`` * *HW Serial0* -> ``serial0`` -* *HW Serial0 swap* -> ``serial0`` +* *HW Serial0 swap* -> ``serial0swap`` * *HW Serial1* -> ``serial1`` * *HW Serial2* -> ``serial2`` * *SW Serial* -> ``serialsw`` From 51c8dbed3bb9bdf432292d1613a8914d80856f1a Mon Sep 17 00:00:00 2001 From: Ton Huisman Date: Wed, 27 Nov 2024 22:29:11 +0100 Subject: [PATCH 21/23] [P009]/[P061] Add note about possible non-working input for MCP23017 PA7/PB7 pins --- docs/source/Plugin/MCP23017_rev_d.repl | 7 +++++++ docs/source/Plugin/P009.rst | 2 ++ docs/source/Plugin/P061.rst | 2 ++ 3 files changed, 11 insertions(+) create mode 100644 docs/source/Plugin/MCP23017_rev_d.repl diff --git a/docs/source/Plugin/MCP23017_rev_d.repl b/docs/source/Plugin/MCP23017_rev_d.repl new file mode 100644 index 0000000000..c52fb782d2 --- /dev/null +++ b/docs/source/Plugin/MCP23017_rev_d.repl @@ -0,0 +1,7 @@ +.. note:: Due to technical reasons, the **MCP23017 rev. D** chip no longer has (official) Input capability on the ``GPA7`` and ``GPB7`` pins! + +Following `this news article `_, the MCP23017 I2C chip, since **revision D** released around 2022, might possibly no longer accept signals reliably for Input on the ``GPA7`` and ``GPB7`` pins. Other sources (links no longer available) suggest these pins have had issues taking input signals since at least 2014, so your milage may vary! (Output is still working as usual on these pins.) + +This may have impact on the use of this board/chip with this plugin when using a MCP23017 rev. D. + +Possible alternatives are using an older revision of this chip, or switching to a different chip, like PCF8574 (8 I/O pins), PCF8575 (16 I/O pins, external pull-up), 74HC165 (Input only), 74HC595 (Output only). diff --git a/docs/source/Plugin/P009.rst b/docs/source/Plugin/P009.rst index 16387dea3d..cba06c135e 100644 --- a/docs/source/Plugin/P009.rst +++ b/docs/source/Plugin/P009.rst @@ -37,6 +37,8 @@ Supported hardware The chip can be used on specifically designed hardware, or a generic module can be used. These are available from several sources. +.. include:: MCP23017_rev_d.repl + |P009_usedby| Configuration diff --git a/docs/source/Plugin/P061.rst b/docs/source/Plugin/P061.rst index e3a6a0c7d2..daf2c20366 100644 --- a/docs/source/Plugin/P061.rst +++ b/docs/source/Plugin/P061.rst @@ -91,6 +91,8 @@ Often used matrix keypads, in 16 and 12 key configuration: (Image sourced from Aliexpress) +.. include:: MCP23017_rev_d.repl + Configuration ------------- From 43fc9e3b47bb51436de1bc8978d2f7c6e5d08b3a Mon Sep 17 00:00:00 2001 From: Ton Huisman Date: Sun, 1 Dec 2024 21:32:49 +0100 Subject: [PATCH 22/23] [C002] Bugfix: Use correct GPIO pin for controlling P001 --- src/_C002.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/_C002.cpp b/src/_C002.cpp index 1645866698..dc9f9f13bd 100644 --- a/src/_C002.cpp +++ b/src/_C002.cpp @@ -110,7 +110,7 @@ bool CPlugin_002(CPlugin::Function function, struct EventStruct *event, String& switch (Settings.getPluginID_for_task(x).value) { case 1: // temp solution, if input switch, update state { - action = strformat(F("gpio,%d,%d"), x, static_cast(nvalue)); + action = strformat(F("gpio,%d,%d"), Settings.TaskDevicePin1[x], static_cast(nvalue)); break; } case 29: // temp solution, if plugin 029, set gpio From d47783cac25e1236dd6b5c9edeb577ae93d5086f Mon Sep 17 00:00:00 2001 From: Ton Huisman Date: Sun, 8 Dec 2024 22:14:25 +0100 Subject: [PATCH 23/23] [P041][P042] Update documentation (no longer in Normal builds) --- docs/source/Plugin/_plugin_substitutions_p04x.repl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/source/Plugin/_plugin_substitutions_p04x.repl b/docs/source/Plugin/_plugin_substitutions_p04x.repl index 77494d918d..fb11018a5f 100644 --- a/docs/source/Plugin/_plugin_substitutions_p04x.repl +++ b/docs/source/Plugin/_plugin_substitutions_p04x.repl @@ -15,7 +15,7 @@ .. |P041_type| replace:: :cyan:`Output` .. |P041_typename| replace:: :cyan:`Output - NeoPixel (Word Clock)` .. |P041_porttype| replace:: `.` -.. |P041_status| replace:: :green:`NORMAL` :yellow:`NEOPIXEL` +.. |P041_status| replace:: :yellow:`NEOPIXEL` .. |P041_github| replace:: P041_NeoClock.ino .. _P041_github: https://github.com/letscontrolit/ESPEasy/blob/mega/src/_P041_NeoClock.ino .. |P041_usedby| replace:: `.` @@ -28,7 +28,7 @@ .. |P042_type| replace:: :cyan:`Output` .. |P042_typename| replace:: :cyan:`Output - NeoPixel (Candle)` .. |P042_porttype| replace:: `.` -.. |P042_status| replace:: :green:`NORMAL` :yellow:`NEOPIXEL` +.. |P042_status| replace:: :yellow:`NEOPIXEL` .. |P042_github| replace:: P042_Candle.ino .. _P042_github: https://github.com/letscontrolit/ESPEasy/blob/mega/src/_P042_Candle.ino .. |P042_usedby| replace:: `.`