diff --git a/CHANGELOG.md b/CHANGELOG.md
index 02e2ce7b7..4465d003b 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -5,22 +5,36 @@ All notable changes to this project will be documented in this file.
## [9.3.1.1]
### Added
+- Support for CSE7761 energy monitor as used in ESP32 based Sonoff Dual R3 Pow (#10793)
+- Command ``Sensor80 1 <0..7>`` to control MFRC522 RFID antenna gain from 18dB (0) to 48dB (7) (#11073)
- Allow MCP230xx pinmode from output to input (#11104)
- SML VBUS support (#11125)
-- Command ``Sensor80 1 <0..7>`` to control MFRC522 RFID antenna gain from 18dB (0) to 48dB (7) (#11073)
- Support for NEC and OPTOMA LCD/DLP Projector serial power control by Jan Bubík (#11145)
+- Support for XPT2046 touch screen digitizer on ILI9341 display by nonix (#11159)
+- Berry improvements (#11163)
+- Support for zigbee lumi.sensor_wleak (#11200)
+- Crash protection in ext_vnsprintf_P (#11202)
+- Extent compile time SetOptions support (#11204)
+- ESP32 Extent BLE (#11212)
### Changed
-- TuyaMcu dimmer timeout (#11121)
+- ESP32 core library from v1.0.5-rc6 to v1.0.5
- TasmotaSerial library from v3.2.0 to v3.3.0
+- TuyaMcu dimmer timeout (#11121)
+- Rename epaper 42 commands (#11222)
+- DeepSleep announcement topic (#11223)
### Fixed
+- PN532 on ESP32 Serial flush both Tx and Rx buffers (#10910)
+- Light scheme related color changes (#11041)
- Refactor acceleration function for shutter stepper and servo (#11088)
- LM75AD detection on different addresses (#11096)
- Timer loop when console is scrolled up regression from v9.3.0 (#11108)
- Display exception when no file system is present (#11125)
-- PN532 on ESP32 Serial flush both Tx and Rx buffers (#10910)
-- Light scheme related color changes (#11041)
+- Scripter and SML fixes (#11150)
+- Zigbee exception when bad frame is received (#11192)
+- ESP32 flash script for Odroid and Core2 (#11227)
+- ESP32 WS2812 bitbang support (#11248)
## [Released]
diff --git a/RELEASENOTES.md b/RELEASENOTES.md
index ba3720df4..960d14b18 100644
--- a/RELEASENOTES.md
+++ b/RELEASENOTES.md
@@ -58,7 +58,7 @@ Above binaries are also available as gzipped version allowing faster uploads.
The attached binaries can also be downloaded from http://ota.tasmota.com/tasmota/release. The links can be used for OTA upgrades too like ``OtaUrl http://ota.tasmota.com/tasmota/release/tasmota.bin.gz``
### ESP32 based
-The following binary downloads have been compiled with ESP32/Arduino library core version **1.0.5-rc6**.
+The following binary downloads have been compiled with ESP32/Arduino library core version **1.0.5**.
- **tasmota32.bin** = The Tasmota version with most drivers. **RECOMMENDED RELEASE BINARY**
- **tasmota32-BG.bin** to **tasmota32-TW.bin** = The Tasmota version in different languages.
@@ -83,16 +83,29 @@ The attached binaries can also be downloaded from http://ota.tasmota.com/tasmota
- Command ``Sensor80 1 <0..7>`` to control MFRC522 RFID antenna gain from 18dB (0) to 48dB (7) [#11073](https://github.com/arendst/Tasmota/issues/11073)
- Support for SML VBUS [#11125](https://github.com/arendst/Tasmota/issues/11125)
- Support for NEC and OPTOMA LCD/DLP Projector serial power control by Jan Bubík [#11145](https://github.com/arendst/Tasmota/issues/11145)
+- Support for XPT2046 touch screen digitizer on ILI9341 display by nonix [#11159](https://github.com/arendst/Tasmota/issues/11159)
+- Support for zigbee lumi.sensor_wleak [#11200](https://github.com/arendst/Tasmota/issues/11200)
+- Support for CSE7761 energy monitor as used in ESP32 based Sonoff Dual R3 Pow [#10793](https://github.com/arendst/Tasmota/issues/10793)
- Allow MCP230xx pinmode from output to input [#11104](https://github.com/arendst/Tasmota/issues/11104)
+- Berry improvements [#11163](https://github.com/arendst/Tasmota/issues/11163)
+- Extent compile time SetOptions support [#11204](https://github.com/arendst/Tasmota/issues/11204)
+- ESP32 Extent BLE [#11212](https://github.com/arendst/Tasmota/issues/11212)
### Changed
-- TuyaMcu dimmer timeout [#11121](https://github.com/arendst/Tasmota/issues/11121)
- TasmotaSerial library from v3.2.0 to v3.3.0
+- ESP32 core library from v1.0.5-rc6 to v1.0.5
+- TuyaMcu dimmer timeout [#11121](https://github.com/arendst/Tasmota/issues/11121)
+- Rename epaper 42 commands [#11222](https://github.com/arendst/Tasmota/issues/11222)
+- DeepSleep announcement topic [#11223](https://github.com/arendst/Tasmota/issues/11223)
### Fixed
+- PN532 on ESP32 Serial flush both Tx and Rx buffers [#10910](https://github.com/arendst/Tasmota/issues/10910)
+- Light scheme related color changes [#11041](https://github.com/arendst/Tasmota/issues/11041)
- Refactor acceleration function for shutter stepper and servo [#11088](https://github.com/arendst/Tasmota/issues/11088)
- LM75AD detection on different addresses [#11096](https://github.com/arendst/Tasmota/issues/11096)
- Timer loop when console is scrolled up regression from v9.3.0 [#11108](https://github.com/arendst/Tasmota/issues/11108)
- Display exception when no file system is present [#11125](https://github.com/arendst/Tasmota/issues/11125)
-- PN532 on ESP32 Serial flush both Tx and Rx buffers [#10910](https://github.com/arendst/Tasmota/issues/10910)
-- Light scheme related color changes [#11041](https://github.com/arendst/Tasmota/issues/11041)
+- Scripter and SML fixes [#11150](https://github.com/arendst/Tasmota/issues/11150)
+- Zigbee exception when bad frame is received [#11192](https://github.com/arendst/Tasmota/issues/11192)
+- ESP32 flash script for Odroid and Core2 [#11227](https://github.com/arendst/Tasmota/issues/11227)
+- ESP32 WS2812 bitbang support [#11248](https://github.com/arendst/Tasmota/issues/11248)
diff --git a/lib/lib_basic/NeoPixelBus-2.6.1.4/src/internal/NeoEspBitBangMethod.cpp b/lib/lib_basic/NeoPixelBus-2.6.1.4/src/internal/NeoEspBitBangMethod.cpp
new file mode 100644
index 000000000..637fef0c5
--- /dev/null
+++ b/lib/lib_basic/NeoPixelBus-2.6.1.4/src/internal/NeoEspBitBangMethod.cpp
@@ -0,0 +1,115 @@
+/*-------------------------------------------------------------------------
+NeoPixel library helper functions for Esp8266 and Esp32
+
+Written by Michael C. Miller.
+
+I invest time and resources providing this open source code,
+please support me by dontating (see https://github.com/Makuna/NeoPixelBus)
+
+-------------------------------------------------------------------------
+This file is part of the Makuna/NeoPixelBus library.
+
+NeoPixelBus is free software: you can redistribute it and/or modify
+it under the terms of the GNU Lesser General Public License as
+published by the Free Software Foundation, either version 3 of
+the License, or (at your option) any later version.
+
+NeoPixelBus is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with NeoPixel. If not, see
+.
+-------------------------------------------------------------------------*/
+
+#if defined(ARDUINO_ARCH_ESP8266) || defined(ARDUINO_ARCH_ESP32)
+
+#include
+#include "NeoEspBitBangMethod.h"
+
+static inline uint32_t getCycleCount(void)
+{
+ uint32_t ccount;
+ __asm__ __volatile__("rsr %0,ccount":"=a" (ccount));
+ return ccount;
+}
+
+void ICACHE_RAM_ATTR NeoEspBitBangBase_send_pixels(uint8_t* pixels, uint8_t* end, uint8_t pin, uint32_t t0h, uint32_t t1h, uint32_t period, uint8_t IdleLevel)
+{
+ const uint32_t pinRegister = _BV(pin);
+ uint8_t mask = 0x80;
+ uint8_t subpix = *pixels++;
+ uint32_t cyclesStart = 0; // trigger emediately
+ uint32_t cyclesNext = 0;
+
+ for (;;)
+ {
+ // do the checks here while we are waiting on time to pass
+ uint32_t cyclesBit = t0h;
+ if (subpix & mask)
+ {
+ cyclesBit = t1h;
+ }
+
+ // after we have done as much work as needed for this next bit
+ // now wait for the HIGH
+ while (((cyclesStart = getCycleCount()) - cyclesNext) < period);
+
+ // set pin state
+ if (IdleLevel == LOW) {
+#if defined(ARDUINO_ARCH_ESP32)
+ GPIO.out_w1ts = pinRegister;
+#else
+ GPIO_REG_WRITE(GPIO_OUT_W1TS_ADDRESS, pinRegister);
+#endif
+ } else {
+#if defined(ARDUINO_ARCH_ESP32)
+ GPIO.out_w1tc = pinRegister;
+#else
+ GPIO_REG_WRITE(GPIO_OUT_W1TC_ADDRESS, pinRegister);
+#endif
+ }
+ // T_PINSET::setPin(pinRegister);
+
+ // wait for the LOW
+ while ((getCycleCount() - cyclesStart) < cyclesBit);
+
+ // reset pin start
+ if (IdleLevel == LOW) {
+#if defined(ARDUINO_ARCH_ESP32)
+ GPIO.out_w1tc = pinRegister;
+#else
+ GPIO_REG_WRITE(GPIO_OUT_W1TC_ADDRESS, pinRegister);
+#endif
+ } else {
+#if defined(ARDUINO_ARCH_ESP32)
+ GPIO.out_w1ts = pinRegister;
+#else
+ GPIO_REG_WRITE(GPIO_OUT_W1TS_ADDRESS, pinRegister);
+#endif
+ }
+ // T_PINSET::resetPin(pinRegister);
+
+ cyclesNext = cyclesStart;
+
+ // next bit
+ mask >>= 1;
+ if (mask == 0)
+ {
+ // no more bits to send in this byte
+ // check for another byte
+ if (pixels >= end)
+ {
+ // no more bytes to send so stop
+ break;
+ }
+ // reset mask to first bit and get the next byte
+ mask = 0x80;
+ subpix = *pixels++;
+ }
+ }
+}
+
+#endif
\ No newline at end of file
diff --git a/lib/lib_basic/NeoPixelBus-2.6.1.4/src/internal/NeoEspBitBangMethod.h b/lib/lib_basic/NeoPixelBus-2.6.1.4/src/internal/NeoEspBitBangMethod.h
index b0b9753b2..abbb4a685 100644
--- a/lib/lib_basic/NeoPixelBus-2.6.1.4/src/internal/NeoEspBitBangMethod.h
+++ b/lib/lib_basic/NeoPixelBus-2.6.1.4/src/internal/NeoEspBitBangMethod.h
@@ -55,6 +55,14 @@ public:
const static uint32_t Period = (F_CPU / 800000 - CYCLES_LOOPTEST); // 1.25us per bit
};
+class NeoEspSpeedTm1829
+{
+public:
+ const static uint32_t T0H = (F_CPU / 3333333 - CYCLES_LOOPTEST); // 0.3us
+ const static uint32_t T1H = (F_CPU / 1250000 - CYCLES_LOOPTEST); // 0.8us
+ const static uint32_t Period = (F_CPU / 800000 - CYCLES_LOOPTEST); // 1.25us per bit
+};
+
class NeoEspSpeed800Mhz
{
public:
@@ -83,109 +91,22 @@ class NeoEspPinset
{
public:
const static uint8_t IdleLevel = LOW;
-
- inline static void setPin(const uint32_t pinRegister)
- {
-#if defined(ARDUINO_ARCH_ESP32)
- GPIO.out_w1ts = pinRegister;
-#else
- GPIO_REG_WRITE(GPIO_OUT_W1TS_ADDRESS, pinRegister);
-#endif
- }
-
- inline static void resetPin(const uint32_t pinRegister)
- {
-#if defined(ARDUINO_ARCH_ESP32)
- GPIO.out_w1tc = pinRegister;
-#else
- GPIO_REG_WRITE(GPIO_OUT_W1TC_ADDRESS, pinRegister);
-#endif
- }
};
class NeoEspPinsetInverted
{
public:
const static uint8_t IdleLevel = HIGH;
-
- inline static void setPin(const uint32_t pinRegister)
- {
-#if defined(ARDUINO_ARCH_ESP32)
- GPIO.out_w1tc = pinRegister;
-#else
- GPIO_REG_WRITE(GPIO_OUT_W1TC_ADDRESS, pinRegister);
-#endif
- }
-
- inline static void resetPin(const uint32_t pinRegister)
- {
-#if defined(ARDUINO_ARCH_ESP32)
- GPIO.out_w1ts = pinRegister;
-#else
- GPIO_REG_WRITE(GPIO_OUT_W1TS_ADDRESS, pinRegister);
-#endif
- }
};
+extern void NeoEspBitBangBase_send_pixels(uint8_t* pixels, uint8_t* end, uint8_t pin, uint32_t t0h, uint32_t t1h, uint32_t period, uint8_t IdleLevel);
+
template class NeoEspBitBangBase
{
public:
- __attribute__((noinline)) static void ICACHE_RAM_ATTR send_pixels(uint8_t* pixels, uint8_t* end, uint8_t pin)
+ static void send_pixels(uint8_t* pixels, uint8_t* end, uint8_t pin)
{
- const uint32_t pinRegister = _BV(pin);
- uint8_t mask = 0x80;
- uint8_t subpix = *pixels++;
- uint32_t cyclesStart = 0; // trigger emediately
- uint32_t cyclesNext = 0;
-
- for (;;)
- {
- // do the checks here while we are waiting on time to pass
- uint32_t cyclesBit = T_SPEED::T0H;
- if (subpix & mask)
- {
- cyclesBit = T_SPEED::T1H;
- }
-
- // after we have done as much work as needed for this next bit
- // now wait for the HIGH
- while (((cyclesStart = getCycleCount()) - cyclesNext) < T_SPEED::Period);
-
- // set pin state
- T_PINSET::setPin(pinRegister);
-
- // wait for the LOW
- while ((getCycleCount() - cyclesStart) < cyclesBit);
-
- // reset pin start
- T_PINSET::resetPin(pinRegister);
-
- cyclesNext = cyclesStart;
-
- // next bit
- mask >>= 1;
- if (mask == 0)
- {
- // no more bits to send in this byte
- // check for another byte
- if (pixels >= end)
- {
- // no more bytes to send so stop
- break;
- }
- // reset mask to first bit and get the next byte
- mask = 0x80;
- subpix = *pixels++;
- }
- }
- }
-
-protected:
- static inline uint32_t getCycleCount(void)
- {
- uint32_t ccount;
- __asm__ __volatile__("rsr %0,ccount":"=a" (ccount));
- return ccount;
+ NeoEspBitBangBase_send_pixels(pixels, end, pin, T_SPEED::T0H, T_SPEED::T1H, T_SPEED::Period, T_PINSET::IdleLevel);
}
};
@@ -214,6 +135,13 @@ public:
static const uint32_t ResetTimeUs = 200;
};
+// normal is inverted signal
+class NeoEspBitBangSpeedTm1829 : public NeoEspBitBangBase
+{
+public:
+ static const uint32_t ResetTimeUs = 200;
+};
+
class NeoEspBitBangSpeed800Kbps : public NeoEspBitBangBase
{
public:
@@ -257,6 +185,13 @@ public:
static const uint32_t ResetTimeUs = 200;
};
+// normal is inverted signal, so inverted is normal
+class NeoEspBitBangInvertedSpeedTm1829 : public NeoEspBitBangBase
+{
+public:
+ static const uint32_t ResetTimeUs = 200;
+};
+
class NeoEspBitBangInvertedSpeed800Kbps : public NeoEspBitBangBase
{
public:
@@ -369,6 +304,7 @@ typedef NeoEspBitBangMethodBase NeoEsp32
typedef NeoEspBitBangMethodBase NeoEsp32BitBangWs2812xMethod;
typedef NeoEspBitBangMethodBase NeoEsp32BitBangSk6812Method;
typedef NeoEspBitBangMethodBase NeoEsp32BitBangTm1814Method;
+typedef NeoEspBitBangMethodBase NeoEsp32BitBangTm1829Method;
typedef NeoEspBitBangMethodBase NeoEsp32BitBang800KbpsMethod;
typedef NeoEspBitBangMethodBase NeoEsp32BitBang400KbpsMethod;
typedef NeoEspBitBangMethodBase NeoEsp32BitBangApa106Method;
@@ -381,6 +317,7 @@ typedef NeoEspBitBangMethodBase NeoEsp32BitBangWs2812xInvertedMethod;
typedef NeoEspBitBangMethodBase NeoEsp32BitBangSk6812InvertedMethod;
typedef NeoEspBitBangMethodBase NeoEsp32BitBangTm1814InvertedMethod;
+typedef NeoEspBitBangMethodBase NeoEsp32BitBangTm1829InvertedMethod;
typedef NeoEspBitBangMethodBase NeoEsp32BitBang800KbpsInvertedMethod;
typedef NeoEspBitBangMethodBase NeoEsp32BitBang400KbpsInvertedMethod;
typedef NeoEspBitBangMethodBase NeoEsp32BitBangApa106InvertedMethod;
@@ -395,6 +332,7 @@ typedef NeoEspBitBangMethodBase NeoEsp82
typedef NeoEspBitBangMethodBase NeoEsp8266BitBangWs2812xMethod;
typedef NeoEspBitBangMethodBase NeoEsp8266BitBangSk6812Method;
typedef NeoEspBitBangMethodBase NeoEsp8266BitBangTm1814Method;
+typedef NeoEspBitBangMethodBase NeoEsp8266BitBangTm1829Method;
typedef NeoEspBitBangMethodBase NeoEsp8266BitBang800KbpsMethod;
typedef NeoEspBitBangMethodBase NeoEsp8266BitBang400KbpsMethod;
typedef NeoEspBitBangMethodBase NeoEsp8266BitBangApa106Method;
@@ -407,6 +345,7 @@ typedef NeoEspBitBangMethodBase NeoEsp8266BitBangWs2812xInvertedMethod;
typedef NeoEspBitBangMethodBase NeoEsp8266BitBangSk6812InvertedMethod;
typedef NeoEspBitBangMethodBase NeoEsp8266BitBangTm1814InvertedMethod;
+typedef NeoEspBitBangMethodBase NeoEsp8266BitBangTm1829InvertedMethod;
typedef NeoEspBitBangMethodBase NeoEsp8266BitBang800KbpsInvertedMethod;
typedef NeoEspBitBangMethodBase NeoEsp8266BitBang400KbpsInvertedMethod;
typedef NeoEspBitBangMethodBase NeoEsp8266BitBangApa106InvertedMethod;
@@ -418,4 +357,4 @@ typedef NeoEsp8266BitBangSk6812InvertedMethod NeoEsp8266BitBangLc8812InvertedMet
#endif
// ESP bitbang doesn't have defaults and should avoided except for testing
-#endif
\ No newline at end of file
+#endif
diff --git a/lib/libesp32/Berry-0.1.10/src/be_api.c b/lib/libesp32/Berry-0.1.10/src/be_api.c
index ad1a0dfb0..dc34b950c 100644
--- a/lib/libesp32/Berry-0.1.10/src/be_api.c
+++ b/lib/libesp32/Berry-0.1.10/src/be_api.c
@@ -976,6 +976,7 @@ BERRY_API int be_pcall(bvm *vm, int argc)
return be_protectedcall(vm, f, argc);
}
+__attribute__((noreturn))
BERRY_API void be_raise(bvm *vm, const char *except, const char *msg)
{
be_pushstring(vm, except);
@@ -987,6 +988,9 @@ BERRY_API void be_raise(bvm *vm, const char *except, const char *msg)
be_pop(vm, 2);
be_save_stacktrace(vm);
be_throw(vm, BE_EXCEPTION);
+#ifdef __GNUC__
+ __builtin_unreachable();
+#endif
}
BERRY_API void be_stop_iteration(bvm *vm)
diff --git a/lib/libesp32/Berry-0.1.10/src/berry.h b/lib/libesp32/Berry-0.1.10/src/berry.h
index 40ceecab4..91bc652a4 100644
--- a/lib/libesp32/Berry-0.1.10/src/berry.h
+++ b/lib/libesp32/Berry-0.1.10/src/berry.h
@@ -401,6 +401,7 @@ BERRY_API int be_pcall(bvm *vm, int argc);
BERRY_API void be_exit(bvm *vm, int status);
/* exception APIs */
+__attribute__((noreturn))
BERRY_API void be_raise(bvm *vm, const char *except, const char *msg);
BERRY_API int be_getexcept(bvm *vm, int code);
BERRY_API void be_dumpvalue(bvm *vm, int index);
diff --git a/lib/libesp32/Berry-0.1.10/src/port/be_tasmotalib.c b/lib/libesp32/Berry-0.1.10/src/port/be_tasmotalib.c
index bb02f19ca..bd484a9da 100644
--- a/lib/libesp32/Berry-0.1.10/src/port/be_tasmotalib.c
+++ b/lib/libesp32/Berry-0.1.10/src/port/be_tasmotalib.c
@@ -12,6 +12,7 @@ extern int l_getoption(bvm *vm);
extern int l_millis(bvm *vm);
extern int l_timereached(bvm *vm);
extern int l_yield(bvm *vm);
+extern int l_delay(bvm *vm);
extern int l_respCmnd(bvm *vm);
extern int l_respCmndStr(bvm *vm);
@@ -20,6 +21,8 @@ extern int l_respCmndError(bvm *vm);
extern int l_respCmndFailed(bvm *vm);
extern int l_resolveCmnd(bvm *vm);
+extern int l_getlight(bvm *vm);
+
// #if !BE_USE_PRECOMPILED_OBJECT
#if 1 // TODO we will do pre-compiled later
@@ -31,6 +34,7 @@ be_native_module_attr_table(tasmota_ntv) {
be_native_module_function("millis", l_millis),
be_native_module_function("timereached", l_timereached),
be_native_module_function("yield", l_yield),
+ be_native_module_function("delay", l_delay),
be_native_module_function("respcmnd", l_respCmnd),
be_native_module_function("respcmndstr", l_respCmndStr),
@@ -39,6 +43,8 @@ be_native_module_attr_table(tasmota_ntv) {
be_native_module_function("respcmnd_failed", l_respCmndFailed),
be_native_module_function("resolvecmnd", l_resolveCmnd),
+ be_native_module_function("getlight", l_getlight),
+
be_native_module_str("_operators", "=<>!|"),
};
diff --git a/lib/libesp32/Berry-0.1.10/src/port/be_wirelib.c b/lib/libesp32/Berry-0.1.10/src/port/be_wirelib.c
index 0d3cd51f4..948ccddef 100644
--- a/lib/libesp32/Berry-0.1.10/src/port/be_wirelib.c
+++ b/lib/libesp32/Berry-0.1.10/src/port/be_wirelib.c
@@ -14,18 +14,23 @@ extern int b_wire_available(bvm *vm);
extern int b_wire_write(bvm *vm);
extern int b_wire_read(bvm *vm);
+extern int b_wire_scan(bvm *vm);
+
+extern int b_wire_validwrite(bvm *vm);
extern int b_wire_validread(bvm *vm);
// #if !BE_USE_PRECOMPILED_OBJECT
#if 1 // TODO we will do pre-compiled later
be_native_module_attr_table(wire) {
- be_native_module_function("begintransmission", b_wire_begintransmission),
- be_native_module_function("endtransmission", b_wire_endtransmission),
- be_native_module_function("requestfrom", b_wire_requestfrom),
- be_native_module_function("available", b_wire_available),
- be_native_module_function("write", b_wire_write),
- be_native_module_function("read", b_wire_read),
- be_native_module_function("validread", b_wire_validread),
+ be_native_module_function("_begintransmission", b_wire_begintransmission),
+ be_native_module_function("_endtransmission", b_wire_endtransmission),
+ be_native_module_function("_requestfrom", b_wire_requestfrom),
+ be_native_module_function("_available", b_wire_available),
+ be_native_module_function("_write", b_wire_write),
+ be_native_module_function("_read", b_wire_read),
+ be_native_module_function("scan", b_wire_scan),
+ be_native_module_function("write", b_wire_validwrite),
+ be_native_module_function("read", b_wire_validread),
};
be_define_native_module(wire, NULL);
diff --git a/tasmota/support_tasmota.ino b/tasmota/support_tasmota.ino
index 9556f5aee..642b6afeb 100644
--- a/tasmota/support_tasmota.ino
+++ b/tasmota/support_tasmota.ino
@@ -1099,9 +1099,11 @@ void Every250mSeconds(void)
}
}
#endif // ESP8266
- AddLog(LOG_LEVEL_DEBUG, PSTR(D_LOG_UPLOAD "%s"), TasmotaGlobal.mqtt_data);
+ char version[50];
+ snprintf_P(version, sizeof(version), PSTR("%s-%s"), TasmotaGlobal.image_name, TasmotaGlobal.version);
+ AddLog(LOG_LEVEL_DEBUG, PSTR(D_LOG_UPLOAD "%s %s"), TasmotaGlobal.mqtt_data, version);
WiFiClient OTAclient;
- ota_result = (HTTP_UPDATE_FAILED != ESPhttpUpdate.update(OTAclient, TasmotaGlobal.mqtt_data));
+ ota_result = (HTTP_UPDATE_FAILED != ESPhttpUpdate.update(OTAclient, TasmotaGlobal.mqtt_data, version));
if (!ota_result) {
#ifndef FIRMWARE_MINIMAL
int ota_error = ESPhttpUpdate.getLastError();
diff --git a/tasmota/xdrv_52_3_berry_native.ino b/tasmota/xdrv_52_3_berry_native.ino
index 8897603a4..46b869544 100644
--- a/tasmota/xdrv_52_3_berry_native.ino
+++ b/tasmota/xdrv_52_3_berry_native.ino
@@ -23,6 +23,7 @@
#include
#include
+const char kTypeError[] PROGMEM = "type_error";
/*********************************************************************************************\
* Native functions mapped to Berry functions
*
@@ -58,7 +59,7 @@ extern "C" {
be_return(vm); // Return
}
}
- be_return_nil(vm); // Return nil when something goes wrong
+ be_raise(vm, kTypeError, nullptr);
}
// Berry: `tasmota.cmd(command:string) -> string`
@@ -72,7 +73,7 @@ extern "C" {
be_pushstring(vm, TasmotaGlobal.mqtt_data);
be_return(vm); // Return
}
- be_return_nil(vm); // Return nil when something goes wrong
+ be_raise(vm, kTypeError, nullptr);
}
// Berry: tasmota.millis([delay:int]) -> int
@@ -89,7 +90,7 @@ extern "C" {
be_pushint(vm, ret_millis);
be_return(vm); // Return
}
- be_return_nil(vm); // Return nil when something goes wrong
+ be_raise(vm, kTypeError, nullptr);
}
// Berry: tasmota.getoption(index:int) -> int
@@ -102,7 +103,7 @@ extern "C" {
be_pushint(vm, opt);
be_return(vm); // Return
}
- be_return_nil(vm); // Return nil when something goes wrong
+ be_raise(vm, kTypeError, nullptr);
}
// Berry: tasmota.timereached(timer:int) -> bool
@@ -116,7 +117,20 @@ extern "C" {
be_pushbool(vm, reached);
be_return(vm); // Return
}
- be_return_nil(vm); // Return nil when something goes wrong
+ be_raise(vm, kTypeError, nullptr);
+ }
+
+ // Berry: tasmota.delay(timer:int) -> nil
+ //
+ int32_t l_delay(struct bvm *vm);
+ int32_t l_delay(struct bvm *vm) {
+ int32_t top = be_top(vm); // Get the number of arguments
+ if (top == 1 && be_isint(vm, 1)) { // only 1 argument of type string accepted
+ uint32_t timer = be_toint(vm, 1);
+ delay(timer);
+ be_return_nil(vm); // Return
+ }
+ be_raise(vm, kTypeError, nullptr);
}
// Berry: `yield() -> nil`
@@ -137,7 +151,7 @@ extern "C" {
be_pushint(vm, ret);
be_return(vm); // Return
}
- be_return_nil(vm); // Return nil when something goes wrong
+ be_raise(vm, kTypeError, nullptr);
}
int32_t l_respCmnd(bvm *vm);
@@ -146,8 +160,9 @@ extern "C" {
if (top == 1) {
const char *msg = be_tostring(vm, 1);
Response_P("%s", msg);
+ be_return_nil(vm); // Return nil when something goes wrong
}
- be_return_nil(vm); // Return nil when something goes wrong
+ be_raise(vm, kTypeError, nullptr);
}
int32_t l_respCmndStr(bvm *vm);
@@ -156,8 +171,9 @@ extern "C" {
if (top == 1) {
const char *msg = be_tostring(vm, 1);
ResponseCmndChar(msg);
+ be_return_nil(vm); // Return nil when something goes wrong
}
- be_return_nil(vm); // Return nil when something goes wrong
+ be_raise(vm, kTypeError, nullptr);
}
int32_t l_respCmndDone(bvm *vm);
@@ -185,9 +201,139 @@ extern "C" {
if (top == 1 && be_isstring(vm, 1)) {
const char *msg = be_tostring(vm, 1);
strlcpy(XdrvMailbox.command, msg, CMDSZ);
+ be_return_nil(vm); // Return nil when something goes wrong
}
- be_return_nil(vm); // Return nil when something goes wrong
+ be_raise(vm, kTypeError, nullptr);
}
+
+
+ static void map_insert_int(bvm *vm, const char *key, int value)
+ {
+ be_pushstring(vm, key);
+ be_pushint(vm, value);
+ be_data_insert(vm, -3);
+ be_pop(vm, 2);
+ }
+ static void map_insert_bool(bvm *vm, const char *key, bool value)
+ {
+ be_pushstring(vm, key);
+ be_pushbool(vm, value);
+ be_data_insert(vm, -3);
+ be_pop(vm, 2);
+ }
+ static void map_insert_str(bvm *vm, const char *key, const char *value)
+ {
+ be_pushstring(vm, key);
+ be_pushstring(vm, value);
+ be_data_insert(vm, -3);
+ be_pop(vm, 2);
+ }
+
+ // get light
+ int32_t l_getlight(bvm *vm);
+ int32_t l_getlight(bvm *vm) {
+ int32_t top = be_top(vm); // Get the number of arguments
+ if (top == 0 || (top == 1 && be_isint(vm, 1))) {
+ int32_t light_num = 0;
+ if (top > 0) {
+ light_num = be_toint(vm, 1);
+ }
+ bool data_present = false; // do we have relevant data
+ be_newobject(vm, "map");
+ // check if the light exist
+ // TasmotaGlobal.devices_present
+ // Light.device
+ // Light.subtype
+ // Light.pwm_multi_channels
+ // light_controller.isCTRGBLinked()
+
+ if (Light.device > 0) {
+ // we have a light
+
+ uint8_t channels[LST_MAX];
+ uint8_t channelsb[LST_MAX];
+ char rgbcw[12] = {0};
+ char rgbcwb[12] = {0};
+ light_state.getChannelsRaw(channels);
+ light_state.getChannels(channelsb);
+
+ // map_insert_int(vm, "_devices_present", TasmotaGlobal.devices_present);
+ // map_insert_int(vm, "_light_device", Light.device);
+ // map_insert_int(vm, "_light_subtype", Light.subtype);
+ // map_insert_int(vm, "_light_multi", Light.pwm_multi_channels);
+ // map_insert_int(vm, "_light_linked", light_controller.isCTRGBLinked());
+
+ if (!Light.pwm_multi_channels) {
+ uint32_t subtype = Light.subtype; // virtual sub-type, for SO37 128
+ uint32_t chanidx = 0; // channel offset, for SO37 128
+
+
+ if (light_controller.isCTRGBLinked() && (light_num == 0)) {
+ data_present = true; // valid combination
+ }
+ if (!light_controller.isCTRGBLinked()) {
+ if (light_num == 0) {
+ data_present = true; // valid combination
+ if (subtype > LST_RGB) { subtype = LST_RGB; } // limit to RGB
+ }
+ if ((light_num == 1) && subtype > LST_RGB) {
+ data_present = true; // valid combination
+ subtype = subtype - LST_RGB;
+ chanidx = 3; // skip first 3 channels
+ }
+ }
+
+ if (data_present) {
+ // see ResponseLightState()
+ map_insert_bool(vm, "power", (bool)(Light.power & 1));
+ map_insert_int(vm, "bri", light_state.getBri());
+
+
+ if (subtype >= LST_RGB) {
+ uint16_t hue;
+ uint8_t sat, bri;
+ light_state.getHSB(&hue, &sat, &bri);
+ map_insert_int(vm, "hue", hue);
+ map_insert_int(vm, "sat", sat);
+ }
+ if ((LST_COLDWARM == subtype) || (LST_RGBW <= subtype)) {
+ map_insert_int(vm, "ct", light_state.getCT());
+ }
+ if (subtype > LST_NONE) {
+ for (uint32_t i=0; i < subtype; i++) {
+ snprintf_P(rgbcw, sizeof(rgbcw), PSTR("%s%02X"), rgbcw, channels[i+chanidx]);
+ snprintf_P(rgbcwb, sizeof(rgbcwb), PSTR("%s%02X"), rgbcwb, channelsb[i+chanidx]);
+ }
+ map_insert_str(vm, "channels", rgbcw);
+ map_insert_str(vm, "channelsb", rgbcwb);
+ // map_insert_bool(vm, "gamma", Settings.light_correction);
+ }
+ }
+ } else { // Light.pwm_multi_channels
+ if ((light_num >= 0) && (light_num < LST_MAX)) {
+ data_present = true;
+ map_insert_bool(vm, "power", Light.power & (1 << light_num));
+ map_insert_int(vm, "bri", Light.current_color[light_num]);
+ snprintf_P(rgbcw, sizeof(rgbcw), PSTR("%02X"), channels[light_num]);
+ snprintf_P(rgbcwb, sizeof(rgbcwb), PSTR("%02X"), channelsb[light_num]);
+ map_insert_str(vm, "channels", rgbcw);
+ map_insert_str(vm, "channelsb", rgbcwb);
+ }
+ }
+
+ be_pop(vm, 1);
+ if (data_present) {
+ be_return(vm); // Return
+ } else {
+ be_return_nil(vm); // no data, return nil instead of empty map
+ }
+ } else {
+ be_return_nil(vm);
+ }
+ }
+ be_raise(vm, kTypeError, nullptr);
+ }
+
}
/*********************************************************************************************\
@@ -208,7 +354,7 @@ extern "C" {
Wire.beginTransmission(address);
be_return(vm); // Return
}
- be_return_nil(vm); // Return nil when something goes wrong
+ be_raise(vm, kTypeError, nullptr);
}
// Berry: `endtransmission([stop:bool]) -> nil`
@@ -224,7 +370,7 @@ extern "C" {
be_pushint(vm, ret);
be_return(vm); // Return
}
- be_return_nil(vm); // Return nil when something goes wrong
+ be_raise(vm, kTypeError, nullptr);
}
// Berry: `requestfrom(address:int, quantity:int [stop:bool = true]) -> nil`
@@ -242,7 +388,7 @@ extern "C" {
Wire.requestFrom((uint16_t)address, (uint8_t)quantity, stop);
be_return(vm); // Return
}
- be_return_nil(vm); // Return nil when something goes wrong
+ be_raise(vm, kTypeError, nullptr);
}
// Berry: `available() -> bool`
@@ -254,14 +400,14 @@ extern "C" {
be_pushint(vm, available);
be_return(vm); // Return
}
- be_return_nil(vm); // Return nil when something goes wrong
+ be_raise(vm, kTypeError, nullptr);
}
// Berry: `write(value:int | s:string) -> nil`
int32_t b_wire_write(struct bvm *vm);
int32_t b_wire_write(struct bvm *vm) {
int32_t top = be_top(vm); // Get the number of arguments
- if (top == 1 && (be_isint(vm, 1) || be_isint(vm, 1))) {
+ if (top == 1 && (be_isint(vm, 1) || be_isstring(vm, 1))) {
if (be_isint(vm, 1)) {
int32_t value = be_toint(vm, 1);
Wire.write(value);
@@ -273,7 +419,7 @@ extern "C" {
}
be_return(vm); // Return
}
- be_return_nil(vm); // Return nil when something goes wrong
+ be_raise(vm, kTypeError, nullptr);
}
// Berry: `read() -> int`
@@ -285,7 +431,43 @@ extern "C" {
be_pushint(vm, value);
be_return(vm); // Return
}
- be_return_nil(vm); // Return nil when something goes wrong
+ be_raise(vm, kTypeError, nullptr);
+ }
+
+ int32_t b_wire_scan(struct bvm *vm);
+ int32_t b_wire_scan(struct bvm *vm) {
+ int32_t top = be_top(vm); // Get the number of arguments
+ if (top == 0) {
+ be_newobject(vm, "list");
+ for (uint8_t address = 1; address <= 127; address++) {
+ Wire.beginTransmission(address);
+ int32_t error = Wire.endTransmission();
+ if (0 == error) {
+ be_pushint(vm, address);
+ be_data_push(vm, -2);
+ be_pop(vm, 1);
+ }
+ }
+ be_pop(vm, 1);
+ be_return(vm); // Return
+ }
+ be_raise(vm, kTypeError, nullptr);
+ }
+
+ // Berry: `validwrite(address:int, reg:int, val:int, size:int) -> bool or nil`
+ int32_t b_wire_validwrite(struct bvm *vm);
+ int32_t b_wire_validwrite(struct bvm *vm) {
+ int32_t top = be_top(vm); // Get the number of arguments
+ if (top == 4 && be_isint(vm, 1) && be_isint(vm, 2) && be_isint(vm, 3) && be_isint(vm, 4)) {
+ uint8_t addr = be_toint(vm, 1);
+ uint8_t reg = be_toint(vm, 2);
+ uint8_t val = be_toint(vm, 3);
+ uint8_t size = be_toint(vm, 4);
+ bool ok = I2cWrite(addr, reg, val, size);
+ be_pushbool(vm, ok);
+ be_return(vm); // Return
+ }
+ be_raise(vm, kTypeError, nullptr);
}
// Berry: `validread(address:int, reg:int, size:int) -> int or nil`
@@ -304,7 +486,7 @@ extern "C" {
}
be_return(vm); // Return
}
- be_return_nil(vm); // Return nil when something goes wrong
+ be_raise(vm, kTypeError, nullptr);
}
}
diff --git a/tasmota/xdrv_52_7_berry_embedded.ino b/tasmota/xdrv_52_7_berry_embedded.ino
index 43b33652c..b9575da81 100644
--- a/tasmota/xdrv_52_7_berry_embedded.ino
+++ b/tasmota/xdrv_52_7_berry_embedded.ino
@@ -45,6 +45,7 @@ const char berry_prog[] =
// Again, this will be eventually pre-compiled
"var getfreeheap, publish, cmd, getoption, millis, timereached, yield "
"var respcmnd, respcmndstr, respcmnd_done, respcmnd_error, respcmnd_failed, resolvecmnd "
+ "var getlight "
"def init_ntv() "
"import tasmota_ntv "
"self.getfreeheap = tasmota_ntv.getfreeheap "
@@ -62,6 +63,8 @@ const char berry_prog[] =
"self.respcmnd_error = tasmota_ntv.respcmnd_error "
"self.respcmnd_failed = tasmota_ntv.respcmnd_failed "
"self.resolvecmnd = tasmota_ntv.resolvecmnd "
+
+ "self.getlight = tasmota_ntv.getlight "
"end "
"def init() "
diff --git a/tasmota/xdrv_52_9_berry.ino b/tasmota/xdrv_52_9_berry.ino
index 666b36818..fbbda679e 100644
--- a/tasmota/xdrv_52_9_berry.ino
+++ b/tasmota/xdrv_52_9_berry.ino
@@ -304,11 +304,15 @@ void CmndBrRun(void) {
// AddLog(LOG_LEVEL_INFO, "run: type(2)=%s", be_typename(berry.vm, 2));
// code taken from REPL, look first at top, and if nil, look at return value
- ret_val = be_tostring(berry.vm, 1);
- Response_P("{\"" D_PRFX_BR "\":\"%s\"}", ret_val); // can't use XdrvMailbox.command as it may have been overwritten by subcommand
+ if (!be_isnil(berry.vm, 1)) {
+ ret_val = be_tostring(berry.vm, 1);
+ } else {
+ ret_val = be_tostring(berry.vm, 2);
+ }
+ Response_P("{\"" D_PRFX_BR "\":\"%s\"}", EscapeJSONString(ret_val).c_str()); // can't use XdrvMailbox.command as it may have been overwritten by subcommand
be_pop(berry.vm, 1);
} else {
- Response_P(PSTR("{\"" D_PRFX_BR "\":\"[%s] %s\"}"), be_tostring(berry.vm, -2), be_tostring(berry.vm, -1));
+ Response_P(PSTR("{\"" D_PRFX_BR "\":\"[%s] %s\"}"), EscapeJSONString(be_tostring(berry.vm, -2)).c_str(), EscapeJSONString(be_tostring(berry.vm, -1)).c_str());
be_pop(berry.vm, 2);
}