Resolved conflicts

This commit is contained in:
Ajith Vasudevan 2021-02-15 15:11:39 +05:30
commit dad81769e3
102 changed files with 199 additions and 347 deletions

View File

@ -251,7 +251,7 @@ void Renderer::setTextFont(uint8_t f) {
#else
#ifdef USE_EPD_FONTS
switch (font) {
case 1:
case 1:
selected_font = &Font12;
break;
case 2:
@ -540,8 +540,14 @@ void Renderer::drawPixel(int16_t x, int16_t y, uint16_t color) {
}
extern uint16_t index_colors[MAX_INDEXCOLORS];
// this is called for every driver
void Renderer::setDrawMode(uint8_t mode) {
drawmode=mode;
for (uint32_t count = 0; count < MAX_INDEXCOLORS; count++) {
index_colors[count] = GetColorFromIndex(count);
}
}
void Renderer::invertDisplay(boolean i) {

View File

@ -9,6 +9,8 @@
#define WHITE 1
#define INVERSE 2
#define MAX_INDEXCOLORS 32
// depends on GFX driver
// GFX patched
// a. in class GFX setCursor,setTextSize => virtual

View File

@ -11,6 +11,7 @@ extern int l_cmd(bvm *vm);
extern int l_getoption(bvm *vm);
extern int l_millis(bvm *vm);
extern int l_timereached(bvm *vm);
extern int l_yield(bvm *vm);
// #if !BE_USE_PRECOMPILED_OBJECT
#if 1 // TODO we will do pre-compiled later
@ -21,6 +22,7 @@ be_native_module_attr_table(tasmota) {
be_native_module_function("getoption", l_getoption),
be_native_module_function("millis", l_millis),
be_native_module_function("timereached", l_timereached),
be_native_module_function("yield", l_yield),
};
be_define_native_module(tasmota, NULL);

View File

@ -1,46 +0,0 @@
![Tasmota logo](/tools/logo/TASMOTA_FullLogo_Vector.svg)
## ESP32 port with minimal changes
## Description:
This is my esp32 port, i try to make only minimal changes to the original source code
from Theo Arends, now again for development branch.
## Checklist:
- [x] The pull request is done against the latest dev branch
- [x] Only relevant files were touched
- [x] Only one feature/fix was added per PR.
- [x] The code change is tested and works on core Tasmota_core_stage
- [ ] The code change pass travis tests. **Your PR cannot be merged unless tests pass**
- [x] I accept the [CLA](https://github.com/arendst/Tasmota/blob/development/CONTRIBUTING.md#contributor-license-agreement-cla).
- [x] i checked binary "tasmota.bin" to be the same in development and development_esp32 branch
Here are the main things i have done
- in "lib_extra_dirs" i have libesp32 directory for things missing in ESP32 framework
my "ESP32-to-ESP8266-compat" has all files that are not available in ESP32
so you dont have to change the source code and i write code to get the informations from ESP32
- all librarys that are not compatibel i add to lib_ignore
- all code that is not for ESP32 i put in "#ifdef ESP8266" the define is from espessif platform
- all code for ESP32 is in "#ifdef ESP32"
- SerConfu8 type uint8_t for SerialConfig list
- changed "HTTP_HEADER" to "HTTP_HEADER1", in ESP32 its an enum
- for ip adress 0 i used IPAddress(0,0,0,0)
- Special ESP.xxx call i change to ESP_xxx (ESP_rtcUserMemoryWrite, ...) and write macros for ESP8266
- because ESP32 has only WEMOS 32 modul, i exclude all code like this:
"if (SONOFF_xxx == Settings.module)" in "#ifdef ESP8266"
- variable "sleep" i changed to "ssleep" because of standard library sleep(..) function
- all esp32 stuff is in support_esp32.ino
- in tasmota.ino i include "tasmota_compat.h"
- in tasmota_template.h i use ifdef and tasmota_templESP32.h
- defines for sensors that currently don't work, i undef in tasmota_templESP32.h
- comment fo "no warnig" in "xdrv_20_hue.ino" thats the only warning i had
Build info
Copy platformio_override_esp32.ini to platformio_override.ini an select your imagetype.
You can build tasmota and tasmota32 Version with one build.
If you need other versions change platformio_override.ini
stay at home, have fun and keep good
Jörg

View File

@ -87,7 +87,8 @@ upload_speed = 115200
upload_resetmethod = nodemcu
upload_port = COM5
extra_scripts = ${scripts_defaults.extra_scripts}
lib_ldf_mode = chain+
lib_ldf_mode = chain
lib_compat_mode = strict
shared_libdeps_dir = lib
lib_extra_dirs =
lib/lib_basic

View File

@ -136,7 +136,6 @@ build_flags = ${esp32_defaults.build_flags}
;-DESP32_STAGE=true
[library]
lib_ldf_mode = chain+
shared_libdeps_dir = lib
; *** Library disable / enable for variant Tasmota(32). Disable reduces compile time
; *** !!! Disabling needed libs will generate compile errors !!!
@ -178,7 +177,6 @@ platform_packages = framework-arduinoespressif32 @ https://github.com/
build_unflags = ${esp32_defaults.build_unflags}
build_flags = ${common32.build_flags}
lib_ignore =
cc1101
NimBLE-Arduino
Micro-RTSP
ESP32 Ethernet

View File

@ -61,7 +61,8 @@ upload_port = ${common.upload_port}
upload_resetmethod = ${common.upload_resetmethod}
upload_speed = 921600
extra_scripts = ${common.extra_scripts}
lib_ldf_mode = chain+
lib_ldf_mode = ${common.lib_ldf_mode}
lib_compat_mode = ${common.lib_compat_mode}
shared_libdeps_dir = lib
lib_extra_dirs =
lib/libesp32

View File

@ -16,6 +16,8 @@ upload_resetmethod = ${common.upload_resetmethod}
upload_speed = ${common.upload_speed}
extra_scripts = ${common.extra_scripts}
lib_extra_dirs = ${common.lib_extra_dirs}
lib_ldf_mode = ${common.lib_ldf_mode}
lib_compat_mode = ${common.lib_compat_mode}
lib_ignore =
Servo(esp8266)
ESP8266AVRISP

View File

@ -16,8 +16,9 @@ extra_scripts = ${common32.extra_scripts}
build_unflags = ${common32.build_unflags}
build_flags = ${common32.build_flags}
lib_extra_dirs = ${common32.lib_extra_dirs}
lib_ldf_mode = ${common32.lib_ldf_mode}
lib_compat_mode = ${common32.lib_compat_mode}
lib_ignore =
cc1101
ESP32 Azure IoT Arduino
ESP32 Async UDP
ESP32 BLE Arduino

View File

@ -100,6 +100,13 @@ tasmota.exec_rules = def (ev_json)
return ret
end
tasmota.delay = def(ms)
tend = tasmota.millis(ms)
while !tasmota.timereached(tend)
tasmota.yield()
end
end
#- Test
#################################################################
@ -154,4 +161,11 @@ br def backlog(cmd_list) delay_backlog = tasmota.getoption(34) delay = 0 for cmd
br backlog( [ "Power 0", "Status 4", "Power 1" ] )
-#
#-
tasmota.delay = def(ms) tend = tasmota.millis(ms) log(str(tasmota.millis())) while !tasmota.timereached(tend) end log(str(tasmota.millis())) end
tasmota.delay = def(ms) a=0 tend = tasmota.millis(ms) log(str(tasmota.millis())) while !tasmota.timereached(tend) a=a+1 end log(str(tasmota.millis())) log(str(a)) end
-#

View File

@ -1338,7 +1338,7 @@ int ICACHE_RAM_ATTR Pin(uint32_t gpio, uint32_t index) {
bool PinUsed(uint32_t gpio, uint32_t index = 0);
bool PinUsed(uint32_t gpio, uint32_t index) {
return (Pin(gpio, index) > -1);
return (Pin(gpio, index) >= 0);
}
uint32_t GetPin(uint32_t lpin) {

View File

@ -168,7 +168,7 @@ void RotaryInit(void) {
attachInterruptArg(Encoder[index].pina, RotaryIsrArg, &Encoder[index], FALLING);
}
}
Rotary.present |= (Encoder[index].pinb > -1);
Rotary.present |= (Encoder[index].pinb >= 0);
}
}
@ -213,7 +213,7 @@ void RotaryHandler(void) {
#ifdef USE_LIGHT
if (!Settings.flag4.rotary_uses_rules) { // SetOption98 - Use rules instead of light control
bool second_rotary = (Encoder[1].pinb > -1);
bool second_rotary = (Encoder[1].pinb >= 0);
if (0 == index) { // Rotary1
if (button_pressed) {
if (second_rotary) { // Color RGB

View File

@ -412,7 +412,7 @@ void SetLedLink(uint32_t state)
if (-1 == led_pin) { // Legacy - LED1 is status
SetLedPowerIdx(0, state);
}
else if (led_pin > -1) {
else if (led_pin >= 0) {
if (state) { state = 1; }
digitalWrite(led_pin, (led_inv) ? !state : state);
}

View File

@ -64,6 +64,7 @@ const uint8_t DISPLAY_LOG_ROWS = 32; // Number of lines in display log
#define D_CMND_DISP_WIDTH "Width"
#define D_CMND_DISP_HEIGHT "Height"
#define D_CMND_DISP_BLINKRATE "Blinkrate"
#define D_CMND_DISP_BATCH "Batch"
#define D_CMND_DISP_CLEAR "Clear"
#define D_CMND_DISP_NUMBER "Number"
#define D_CMND_DISP_FLOAT "Float"
@ -78,6 +79,7 @@ const uint8_t DISPLAY_LOG_ROWS = 32; // Number of lines in display log
#define D_CMND_DISP_CLOCK "Clock"
#define D_CMND_DISP_TEXTNC "TextNC" // NC - "No Clear"
enum XdspFunctions { FUNC_DISPLAY_INIT_DRIVER, FUNC_DISPLAY_INIT, FUNC_DISPLAY_EVERY_50_MSECOND, FUNC_DISPLAY_EVERY_SECOND,
FUNC_DISPLAY_MODEL, FUNC_DISPLAY_MODE, FUNC_DISPLAY_POWER,
FUNC_DISPLAY_CLEAR, FUNC_DISPLAY_DRAW_FRAME,
@ -85,27 +87,42 @@ enum XdspFunctions { FUNC_DISPLAY_INIT_DRIVER, FUNC_DISPLAY_INIT, FUNC_DISPLAY_E
FUNC_DISPLAY_DRAW_CIRCLE, FUNC_DISPLAY_FILL_CIRCLE,
FUNC_DISPLAY_DRAW_RECTANGLE, FUNC_DISPLAY_FILL_RECTANGLE,
FUNC_DISPLAY_TEXT_SIZE, FUNC_DISPLAY_FONT_SIZE, FUNC_DISPLAY_ROTATION, FUNC_DISPLAY_DRAW_STRING,
FUNC_DISPLAY_DIM, FUNC_DISPLAY_BLINKRATE, FUNC_DISPLAY_NUMBER, FUNC_DISPLAY_FLOAT,
FUNC_DISPLAY_DIM, FUNC_DISPLAY_BLINKRATE
#ifdef USE_UFILESYS
,FUNC_DISPLAY_BATCH
#endif
, FUNC_DISPLAY_NUMBER, FUNC_DISPLAY_FLOAT,
FUNC_DISPLAY_NUMBERNC, FUNC_DISPLAY_FLOATNC, FUNC_DISPLAY_BRIGHTNESS, FUNC_DISPLAY_RAW,
FUNC_DISPLAY_LEVEL, FUNC_DISPLAY_SEVENSEG_TEXT, FUNC_DISPLAY_SEVENSEG_TEXTNC,
FUNC_DISPLAY_SCROLLDELAY, FUNC_DISPLAY_CLOCK };
};
enum DisplayInitModes { DISPLAY_INIT_MODE, DISPLAY_INIT_PARTIAL, DISPLAY_INIT_FULL };
const char kDisplayCommands[] PROGMEM = D_PRFX_DISPLAY "|" // Prefix
"|" D_CMND_DISP_MODEL "|" D_CMND_DISP_WIDTH "|" D_CMND_DISP_HEIGHT "|" D_CMND_DISP_MODE "|" D_CMND_DISP_REFRESH "|"
D_CMND_DISP_DIMMER "|" D_CMND_DISP_COLS "|" D_CMND_DISP_ROWS "|" D_CMND_DISP_SIZE "|" D_CMND_DISP_FONT "|"
D_CMND_DISP_ROTATE "|" D_CMND_DISP_TEXT "|" D_CMND_DISP_ADDRESS "|" D_CMND_DISP_BLINKRATE "|" D_CMND_DISP_CLEAR "|"
D_CMND_DISP_NUMBER "|" D_CMND_DISP_FLOAT "|" D_CMND_DISP_NUMBERNC "|" D_CMND_DISP_FLOATNC "|" D_CMND_DISP_BRIGHTNESS "|"
D_CMND_DISP_RAW "|" D_CMND_DISP_LEVEL "|" D_CMND_DISP_SEVENSEG_TEXT "|" D_CMND_DISP_SEVENSEG_TEXTNC "|"
D_CMND_DISP_ROTATE "|" D_CMND_DISP_TEXT "|" D_CMND_DISP_ADDRESS "|" D_CMND_DISP_BLINKRATE
#ifdef USE_UFILESYS
"|" D_CMND_DISP_BATCH
#endif
"|" D_CMND_DISP_CLEAR "|" D_CMND_DISP_NUMBER "|" D_CMND_DISP_FLOAT "|" D_CMND_DISP_NUMBERNC "|" D_CMND_DISP_FLOATNC "|"
D_CMND_DISP_BRIGHTNESS "|" D_CMND_DISP_RAW "|" D_CMND_DISP_LEVEL "|" D_CMND_DISP_SEVENSEG_TEXT "|" D_CMND_DISP_SEVENSEG_TEXTNC "|"
D_CMND_DISP_SCROLLDELAY "|" D_CMND_DISP_CLOCK "|" D_CMND_DISP_TEXTNC;
;
void (* const DisplayCommand[])(void) PROGMEM = {
&CmndDisplay, &CmndDisplayModel, &CmndDisplayWidth, &CmndDisplayHeight, &CmndDisplayMode, &CmndDisplayRefresh,
&CmndDisplayDimmer, &CmndDisplayColumns, &CmndDisplayRows, &CmndDisplaySize, &CmndDisplayFont,
&CmndDisplayRotate, &CmndDisplayText, &CmndDisplayAddress, &CmndDisplayBlinkrate, &CmndDisplayClear, &CmndDisplayNumber,
&CmndDisplayFloat, &CmndDisplayNumberNC, &CmndDisplayFloatNC, &CmndDisplayBrightness, &CmndDisplayRaw,
&CmndDisplayLevel, &CmndDisplaySevensegText, &CmndDisplaySevensegTextNC, &CmndDisplayScrollDelay, &CmndDisplayClock, &CmndDisplayTextNC };
&CmndDisplayRotate, &CmndDisplayText, &CmndDisplayAddress, &CmndDisplayBlinkrate
#ifdef USE_UFILESYS
,&CmndDisplayBatch
#endif
, &CmndDisplayClear, &CmndDisplayNumber, &CmndDisplayFloat, &CmndDisplayNumberNC, &CmndDisplayFloatNC, &CmndDisplayBrightness, &CmndDisplayRaw,
&CmndDisplayLevel, &CmndDisplaySevensegText, &CmndDisplaySevensegTextNC, &CmndDisplayScrollDelay, &CmndDisplayClock, &CmndDisplayTextNC
};
char *dsp_str;
@ -128,6 +145,8 @@ uint8_t dsp_font;
uint8_t dsp_flag;
uint8_t dsp_on;
uint16_t index_colors[MAX_INDEXCOLORS];
#ifdef USE_DISPLAY_MODES1TO5
char **disp_log_buffer;
@ -384,6 +403,11 @@ uint32_t decode_te(char *line) {
#define DISPLAY_BUFFER_COLS 128 // Max number of characters in linebuf
uint16_t GetColorFromIndex(uint32_t index) {
if (index >= MAX_INDEXCOLORS) index = 0;
return index_colors[index];
}
void DisplayText(void)
{
uint8_t lpos;
@ -489,7 +513,7 @@ void DisplayText(void)
// color index 0-18
cp++;
var = atoiv(cp, &temp);
if (renderer) ftemp=renderer->GetColorFromIndex(temp);
if (renderer) ftemp = GetColorFromIndex(temp);
} else {
// float because it must handle unsigned 16 bit
var = fatoiv(cp,&ftemp);
@ -504,7 +528,7 @@ void DisplayText(void)
// color index 0-18
cp++;
var = atoiv(cp, &temp);
if (renderer) ftemp=renderer->GetColorFromIndex(temp);
if (renderer) ftemp = GetColorFromIndex(temp);
} else {
var = fatoiv(cp,&ftemp);
}
@ -661,6 +685,18 @@ void DisplayText(void)
}
break; }
case 'd':
if (*cp == 'c') {
cp++;
// define index colo
var = atoiv(cp, &temp);
cp += var;
cp++;
var = fatoiv(cp, &ftemp);
cp += var;
if (temp >= MAX_INDEXCOLORS) temp = 0;
index_colors[temp] = ftemp;
break;
}
// force draw grafics buffer
if (renderer) renderer->Updateframe();
else DisplayDrawFrame();
@ -876,8 +912,8 @@ void DisplayText(void)
if (buttons[num]) {
if (!sbt) {
buttons[num]->vpower.slider = 0;
buttons[num]->initButtonUL(renderer, gxp, gyp, gxs, gys, renderer->GetColorFromIndex(outline),\
renderer->GetColorFromIndex(fill), renderer->GetColorFromIndex(textcolor), bbuff, textsize);
buttons[num]->initButtonUL(renderer, gxp, gyp, gxs, gys, GetColorFromIndex(outline),\
GetColorFromIndex(fill), GetColorFromIndex(textcolor), bbuff, textsize);
if (!bflags) {
// power button
if (dflg) buttons[num]->xdrawButton(bitRead(TasmotaGlobal.power, num));
@ -898,8 +934,8 @@ void DisplayText(void)
} else {
// slider
buttons[num]->vpower.slider = 1;
buttons[num]->SliderInit(renderer, gxp, gyp, gxs, gys, outline, renderer->GetColorFromIndex(fill),\
renderer->GetColorFromIndex(textcolor), renderer->GetColorFromIndex(textsize));
buttons[num]->SliderInit(renderer, gxp, gyp, gxs, gys, outline, GetColorFromIndex(fill),\
GetColorFromIndex(textcolor), GetColorFromIndex(textsize));
}
}
}
@ -945,6 +981,45 @@ void DisplayText(void)
}
}
#ifdef USE_UFILESYS
extern FS *ufsp;
void Display_Text_From_File(const char *file) {
File fp;
fp = ufsp->open(file, FS_FILE_READ);
if (fp >= 0) {
char *savptr = XdrvMailbox.data;
char linebuff[128];
while (fp.available()) {
uint16_t index = 0;
while (fp.available()) {
uint8_t buf[1];
fp.read(buf,1);
if (buf[0]=='\n' || buf[0]=='\r') {
break;
} else {
linebuff[index] = buf[0];
index++;
if (index >= sizeof(linebuff) - 1) {
break;
}
}
}
linebuff[index] = 0;
char *cp = linebuff;
while (*cp==' ') cp++;
if (*cp == ';') continue;
//AddLog(LOG_LEVEL_INFO, PSTR("displaytext %s"), cp);
// execute display text here
XdrvMailbox.data = cp;
XdrvMailbox.data_len = 0;
DisplayText();
}
XdrvMailbox.data = savptr;
fp.close();
}
}
#endif
/*********************************************************************************************/
#ifdef USE_DISPLAY_MODES1TO5
@ -1329,6 +1404,7 @@ void DisplayLocalSensor(void)
#endif // USE_DISPLAY_MODES1TO5
/*********************************************************************************************\
* Public
\*********************************************************************************************/
@ -1344,6 +1420,9 @@ void DisplayInitDriver(void)
renderer->setDrawMode(0);
}
#ifdef USE_UFILESYS
Display_Text_From_File("/display.ini");
#endif
// AddLog(LOG_LEVEL_DEBUG, PSTR(D_LOG_DEBUG "Display model %d"), Settings.display_model);
@ -1594,6 +1673,16 @@ void CmndDisplayClock(void)
}
ResponseCmndNumber(XdrvMailbox.payload);
}
#ifdef USE_UFILESYS
void CmndDisplayBatch(void) {
if (XdrvMailbox.data_len > 0) {
if (!Settings.display_mode) {
Display_Text_From_File(XdrvMailbox.data);
}
ResponseCmndChar(XdrvMailbox.data);
}
}
#endif
void CmndDisplaySize(void)
{
@ -2168,7 +2257,7 @@ void RedrawGraph(uint8_t num, uint8_t flags) {
uint16_t linecol=fg_color;
if (color_type==COLOR_COLOR) {
linecol=renderer->GetColorFromIndex(gp->color_index);
linecol = GetColorFromIndex(gp->color_index);
}
if (!gp->flags.overlay) {
@ -2190,7 +2279,7 @@ void AddGraph(uint8_t num,uint8_t val) {
uint16_t linecol=fg_color;
if (color_type==COLOR_COLOR) {
linecol=renderer->GetColorFromIndex(gp->color_index);
linecol = GetColorFromIndex(gp->color_index);
}
gp->xcnt++;
if (gp->xcnt>gp->xs) {

View File

@ -230,29 +230,29 @@ void HueRespondToMSearch(void)
* Hue web server additions
\*********************************************************************************************/
//<?xml version="1.0"?><root xmlns="urn:schemas-upnp-org:device-1-0"><specVersion><major>1</major><minor>0</minor></specVersion>"<URLBase>http://{x1:80/</URLBase><device><deviceType>urn:schemas-upnp-org:device:Basic:1</deviceType><friendlyName>Amazon-Echo-HA-Bridge ({x1)</friendlyName><manufacturer>Royal Philips Electronics</manufacturer><manufacturerURL>http://www.philips.com</manufacturerURL><modelDescription>Philips hue Personal Wireless Lighting</modelDescription><modelName>Philips hue bridge 2012</modelName><modelNumber>929000226503</modelNumber><serialNumber>{x3</serialNumber><UDN>uuid:{x2</UDN></device></root>\r\n\r\n
//Successfully compressed from 626 to 394 bytes (-37.1%)
const size_t HUE_DESCRIPTION_XML_SIZE = 626;
//<?xml version="1.0"?><root xmlns="urn:schemas-upnp-org:device-1-0"><specVersion><major>1</major><minor>0</minor></specVersion><URLBase>http://{x1:80/</URLBase><device><deviceType>urn:schemas-upnp-org:device:Basic:1</deviceType><friendlyName>Amazon-Echo-HA-Bridge ({x1)</friendlyName><manufacturer>Royal Philips Electronics</manufacturer><manufacturerURL>http://www.philips.com</manufacturerURL><modelDescription>Philips hue Personal Wireless Lighting</modelDescription><modelName>Philips hue bridge 2012</modelName><modelNumber>929000226503</modelNumber><serialNumber>{x3</serialNumber><UDN>uuid:{x2</UDN></device></root>\r\n\r\n
//Successfully compressed from 625 to 391 bytes (-37.4%)
const size_t HUE_DESCRIPTION_XML_SIZE = 625;
const char HUE_DESCRIPTION_XML_COMPRESSED[] PROGMEM = "\x3D\x0E\xD1\xB0\x68\x48\xCD\xFF\xDB\x9C\x7C\x3D\x87\x21\xD1\x9E\xC3\xB4\x7E\x1E"
"\x85\xFC\xCA\x46\xC1\xA1\x77\x8F\x87\xB0\x5F\xF8\xF3\xF0\x62\x98\xDB\xF1\xD6\x2C"
"\x67\x0C\x3A\xF3\xE3\xC7\x98\x8C\xCF\x43\x67\x59\xC8\x75\xB3\xD8\x7E\x1E\x85\xE1"
"\x8C\x32\x33\x04\x1C\x78\xFC\x3D\x06\xD9\xAF\x3E\x7E\x1C\x87\xA1\xD8\x40\x83\x14"
"\xF4\x1B\xBD\x9F\x3F\x0E\x33\xD0\xEC\x20\x41\x8A\x7A\x1D\x80\x8F\x85\x1E\xC3\xD0"
"\x85\x97\xC8\x22\x1D\x7E\x67\xE0\xAA\xA1\x87\x99\xD8\x76\x1E\xD3\x61\xC8\x79\xFD"
"\x9D\x87\xA1\xD8\x40\x87\x50\xF4\x04\x1D\x18\x10\xE2\x15\x19\x0C\x67\xE0\x2B\x6D"
"\xC7\x99\x0E\xBF\x68\x67\x99\xC8\x7A\x1D\x84\x08\xD8\x61\xE8\x63\xFA\xF8\x40\x8C"
"\x8B\xAC\x6B\x3F\x0A\xC6\xD9\xB7\x38\xEB\x26\x18\xAC\x3A\xC8\x51\x59\xD6\x43\xBF"
"\xA2\x0F\x34\x77\x4F\x69\xB0\xE4\x3B\xC7\xA1\xD8\x40\x91\x83\x1E\x83\x6F\x85\x98"
"\xB0\xE8\x5F\xDF\xCF\xC2\xFE\x19\x58\x48\x86\x0A\xD0\xB4\x67\x91\x30\x98\x75\xFC"
"\xED\x0F\xC7\xA1\xD8\x09\x18\x20\x24\x62\x44\x2C\xBE\x41\x02\x1F\x06\xE3\xE3\xE3"
"\xE7\x41\x80\x83\x8D\x1D\x03\xC1\xA0\x93\x89\x10\xB2\xF9\x04\x7E\x1E\x83\x70\x46"
"\x11\x08\xFC\x1F\xF4\x65\x6E\x71\xF8\x08\x7A\x48\xA1\x6D\x10\xC7\xFF\x67\x58\x48"
"\x87\xF7\xEC\x27\xEF\x22\x0B\x47\x85\x56\xF0\xF1\xE8\x76\x02\x66\x2A\x2B\x08\x39"
"\x39\x75\x8D\x60\x91\x90\x0E\x04\x1E\x12\x0E\x53\x94\x40\x85\x88\x82\x17\x08\x98"
"\x23\x08\xB8\x58\xD1\xCF\xE7\xE1\xC5\x49\xB7\x55\xDA\xEC\x81\x0F\x01\x04\x1A\xC7"
"\xA7\x9F\xF6\xC1\x0E\x51\xED\x36\x1C\xB3\xD0\xEC\x20\x48\x9C\x7A\x10\xB2\x10\xB8"
"\xFC\x16\x2F\x44\x3C\xCF\x69\xB0\xE5\x1E\x87\x61\x10\xB2\x10\xB8\xFC\x04\x3E\x38"
"\xCF\xC3\xD0\xEC\xFE\x65\x1F\x93\x85\x23\x74\xE1\x48\xDC";
"\xF4\x1B\xBD\x9F\x3F\x0E\x33\xD0\xEC\x20\x41\x8A\x7A\x1D\x80\x91\x85\x10\xB2\xF9"
"\x04\x43\xAF\xCC\xFC\x15\x54\x30\xF3\x3B\x0E\xC3\xDA\x6C\x39\x0F\x3F\xB3\xB0\xF4"
"\x3B\x08\x10\xEA\x1E\x80\x83\xA2\x82\x1C\x42\xA3\x21\x8C\xFC\x05\x6D\xB4\xF3\x21"
"\xD7\xED\x0C\xF3\x39\x0F\x43\xB0\x81\x1B\x0C\x3D\x0C\x7F\x5F\x08\x11\x91\x75\x8D"
"\x67\xE1\x58\xDB\x36\xE7\x1D\x64\xC3\x15\x87\x59\x0A\x2B\x3A\xC8\x77\xF4\x41\xE6"
"\x8E\xE9\xED\x36\x1C\x87\x78\xF4\x3B\x08\x12\x30\x63\xD0\x6D\xF0\xB3\x16\x1D\x0B"
"\xFB\xF9\xF8\x5F\xC3\x2B\x09\x10\xC1\x5A\x16\x8C\xF2\x26\x13\x0E\xBF\x9D\xA1\xF8"
"\xF4\x3B\x01\x23\x04\x04\x8C\x48\x85\x97\xC8\x20\x43\xE0\xDC\x7C\x7C\x7C\xE8\x30"
"\x10\x71\xA3\xA0\x78\x34\x12\x71\x22\x16\x5F\x20\x8F\xC3\xD0\x6E\x08\xC2\x21\x1F"
"\x83\xFE\x8C\xAD\xCE\x3F\x01\x0F\x49\x14\x2D\xA2\x18\xFF\xEC\xEB\x09\x10\xFE\xFD"
"\x84\xFD\xE4\x41\x68\xF0\xAA\xDE\x1E\x3D\x0E\xC0\x4C\xC5\x41\x07\x27\x2E\xB1\xAC"
"\x12\x32\x01\xC0\x83\xC2\x41\xCA\x72\x88\x10\xB1\x10\x42\xE1\x13\x04\x61\x17\x0B"
"\x1A\x39\xFC\xFC\x38\xA9\x36\xEA\xBB\x5D\x90\x21\xE0\x20\x83\x58\xF4\xF3\xFE\xD8"
"\x21\xCA\x3D\xA6\xC3\x96\x7A\x1D\x84\x09\x13\x8F\x42\x16\x42\x17\x1F\x82\xC5\xE8"
"\x87\x99\xED\x36\x1C\xA3\xD0\xEC\x22\x16\x42\x17\x1F\x80\x87\xC7\x19\xF8\x7A\x1D"
"\x9F\xCC\xA3\xF2\x70\xA4\x6E\x9C\x29\x1B\x8D";
// const char HUE_DESCRIPTION_XML[] PROGMEM =
// "<?xml version=\"1.0\"?>"
// "<root xmlns=\"urn:schemas-upnp-org:device-1-0\">"

View File

@ -142,6 +142,15 @@ bool Z_Mapper::addEdge(const Z_Mapper_Edge & edge2) {
return true;
}
String EscapeHTMLString(const char *s_P) {
String s((const __FlashStringHelper*) s_P);
s.replace(F("&"), F("&amp;"));
s.replace(F("\""), F("&quot;"));
s.replace(F("<"), F("&lt;"));
s.replace(F(">"), F("&gt;"));
return s;
}
void Z_Mapper::dumpInternals(void) const {
WSContentSend_P(PSTR("nodes:[" "{id:\"0x0000\",label:\"Coordinator\",group:\"o\",title:\"0x0000\"}"));
for (const auto & device : zigbee_devices.getDevices()) {
@ -150,7 +159,7 @@ void Z_Mapper::dumpInternals(void) const {
const char *fname = device.friendlyName;
if (fname != nullptr) {
WSContentSend_P(PSTR("%s"), fname);
WSContentSend_P(PSTR("%s"), EscapeJSONString(fname).c_str());
} else {
WSContentSend_P(PSTR("0x%04X"), device.shortaddr);
}

View File

@ -138,10 +138,10 @@ void ZigbeeInputLoop(void) {
// buffer received, now check integrity
if (zigbee_buffer->len() != zigbee_frame_len) {
// Len is not correct, log and reject frame
AddLog_P(LOG_LEVEL_INFO, PSTR(D_JSON_ZIGBEEZNPRECEIVED ": received frame of wrong size %_B, len %d, expected %d"), &zigbee_buffer, zigbee_buffer->len(), zigbee_frame_len);
AddLog_P(LOG_LEVEL_INFO, PSTR(D_JSON_ZIGBEEZNPRECEIVED ": received frame of wrong size %_B, len %d, expected %d"), zigbee_buffer, zigbee_buffer->len(), zigbee_frame_len);
} else if (0x00 != fcs) {
// FCS is wrong, packet is corrupt, log and reject frame
AddLog_P(LOG_LEVEL_INFO, PSTR(D_JSON_ZIGBEEZNPRECEIVED ": received bad FCS frame %_B, %d"), &zigbee_buffer, fcs);
AddLog_P(LOG_LEVEL_INFO, PSTR(D_JSON_ZIGBEEZNPRECEIVED ": received bad FCS frame %_B, %d"), zigbee_buffer, fcs);
} else {
// frame is correct
//AddLog_P(LOG_LEVEL_DEBUG_MORE, PSTR(D_JSON_ZIGBEEZNPRECEIVED ": received correct frame %s"), hex_char);
@ -243,7 +243,7 @@ void ZigbeeInputLoop(void) {
// remove 2 last bytes
if (crc_received != crc) {
AddLog_P(LOG_LEVEL_INFO, PSTR(D_JSON_ZIGBEE_EZSP_RECEIVED ": bad crc (received 0x%04X, computed 0x%04X) %_B"), crc_received, crc, &zigbee_buffer);
AddLog_P(LOG_LEVEL_INFO, PSTR(D_JSON_ZIGBEE_EZSP_RECEIVED ": bad crc (received 0x%04X, computed 0x%04X) %_B"), crc_received, crc, zigbee_buffer);
} else {
// copy buffer
SBuffer ezsp_buffer = zigbee_buffer->subBuffer(0, frame_len - 2); // CRC
@ -265,7 +265,7 @@ void ZigbeeInputLoop(void) {
}
} else {
// the buffer timed-out, print error and discard
AddLog_P(LOG_LEVEL_INFO, PSTR(D_JSON_ZIGBEE_EZSP_RECEIVED ": time-out, discarding %s, %_B"), &zigbee_buffer);
AddLog_P(LOG_LEVEL_INFO, PSTR(D_JSON_ZIGBEE_EZSP_RECEIVED ": time-out, discarding %s, %_B"), zigbee_buffer);
}
zigbee_buffer->setLen(0); // empty buffer
escape = false;

View File

@ -1517,7 +1517,7 @@ void ZigbeeGlowPermitJoinLight(void) {
// change the led state
int led_pin = Pin(GPIO_LEDLNK);
if (led_pin > -1) {
if (led_pin >= 0) {
analogWrite(led_pin, TasmotaGlobal.ledlnk_inverted ? 1023 - led_power : led_power);
}
}
@ -1960,9 +1960,9 @@ void ZigbeeShow(bool json)
WSContentSend_PD(msg[ZB_WEB_STATUS_LINE],
shortaddr,
device.modelId ? device.modelId : "",
device.manufacturerId ? device.manufacturerId : "",
name, sbatt, slqi);
device.modelId ? EscapeHTMLString(device.modelId).c_str() : "",
device.manufacturerId ? EscapeHTMLString(device.manufacturerId).c_str() : "",
EscapeHTMLString(name).c_str(), sbatt, slqi);
if(device.validLqi()) {
for(uint32_t j = 0; j < 4; ++j) {

View File

@ -25,8 +25,6 @@
#include <berry.h>
#include <csetjmp>
const size_t BERRY_STACK = 4096; // size for the alternate stack for continuation
const char kBrCommands[] PROGMEM = D_PRFX_BR "|" // prefix
D_CMND_BR_RUN "|" D_CMND_BR_RESET
;
@ -35,49 +33,10 @@ void (* const BerryCommand[])(void) PROGMEM = {
CmndBrRun, CmndBrReset,
};
/*********************************************************************************************\
* Async mode for Berry VM
*
* We enhance the berry language with `yield()` and `wait(ms)` functions.
* When called, the VM is frozen and control is given back to Tasmota. Then Tasmota
* at next tick or when the time is reached, resumes the VM.
*
* This is based on coroutines scheme, similar to the contiuation stack of ESP8266.
* The basic concept is that Tasmota records a longjump target including current stack position
* and return address.
* The Berry VM is then called with an alternate stack so that we can switch from both stacks
* and keep the callchain intact.
*
* High level view:
* - Tasmota records a return vector with `setjmp`
* - Tasmota changes replaces the native stack with an alternate stack pre-allocated on the heap
* - Tasmota calls the Berry VM with `be_pcall`
* - During the flow of Berry VM, the user code calls `yield()` or `wait(ms)`
* - Corresponding native function is called (still on alternate stack)
* - Native function records VM resume target with `setjmp`
* - and gives back function to Tasmota via `longjmp`.
* Note: `longjmp` restores at the same time the native stack.
*
* Note: trampoline functions relies on global variables, since stack variable don't work anymore
* when replacing stack.
*
\*********************************************************************************************/
class BerrySupport {
public:
bvm *vm = nullptr; // berry vm
bool rules_busy = false; // are we already processing rules, avoid infinite loop
#ifdef USE_BERRY_ASYNC
// Alternate stack for the Berry VM
uint8_t *stack_alloc = nullptr; // stack malloc address
uint8_t *stack = nullptr; // alternate stack for continuation (top of stack)
// longjmp vectors to yield from Tasmota to VM and reverse
bool ta_cont_ok = false; // is the Tasmota continuation address valid?
bool vm_cont_ok = false; // is the VM continuation address valid?
jmp_buf ta_cont; // continuation structure for the longjump back to Tasmota
jmp_buf vm_cont;
// used by trampoline to call be_pcall()
#endif // USE_BERRY_ASYNC
const char *fname = nullptr; // name of berry function to call
int32_t fret = 0;
};
@ -109,6 +68,7 @@ void checkBeTop(void) {
* tasmota.getoption(index:int) -> int
* tasmota.millis([delay:int]) -> int
* tasmota.timereached(timer:int) -> bool
* tasmota.yield() -> nil
*
\*********************************************************************************************/
extern "C" {
@ -216,37 +176,16 @@ extern "C" {
}
be_return_nil(vm); // Return nil when something goes wrong
}
}
// Berry: `printStack() -> nul`
// print stack pointer
// int32_t l_printStack(bvm *vm) {
// int r = 0;
// AddLog(LOG_LEVEL_INFO, PSTR("Trampo: stack = 0x%08X"), &r);
// be_return(vm);
// }
// Yield
int32_t l_yield(struct bvm *vm) {
#ifdef USE_BERRY_ASYNC
if (berry.ta_cont_ok) { // if no ta_cont address, then ignore
if (setjmp(berry.vm_cont) == 0) { // record the current state
berry.vm_cont_ok = true;
longjmp(berry.ta_cont, -1); // give back control to Tasmota
}
// Berry: `yield() -> nil`
// ESP object
int32_t l_yield(bvm *vm);
int32_t l_yield(bvm *vm) {
optimistic_yield(10);
be_return(vm);
}
berry.vm_cont_ok = false; // from now, berry.vm_cont is no more valid
#endif // USE_BERRY_ASYNC
be_return(vm);
}
// be_native_module_attr_table(esp) {
// be_native_module_function("getFreeHeap", l_getFreeHeap),
// };
// be_define_native_module(math, nullptr);
/*********************************************************************************************\
* Handlers for Berry calls and async
@ -329,82 +268,6 @@ void callBerryFunctionVoid(const char * fname) {
checkBeTop();
}
void test_input(void) {
int i = 0;
AddLog(LOG_LEVEL_INFO, PSTR("test_input stack = 0x%08X"), &i);
callBerryFunctionVoid("noop");
}
int be_pcall_with_alt_stack() {
berry.fret = be_pcall(berry.vm, 0);
return berry.fret;
}
void printStack(void) {
int r = 0;
AddLog(LOG_LEVEL_INFO, PSTR("Trampo: stack = 0x%08X"), &r);
}
#ifdef USE_BERRY_ASYNC
int32_t callTrampoline(void *func) {
// Tasmota stack active
// ----------------------------------
static int r;
berry.vm_cont_ok = false;
if ((r = setjmp(berry.ta_cont)) == 0) { // capture registers
// Tasmota stack active
// ----------------------------------
// on the first run, we call back ourselves with the alternate stack
// we clone the return vector and change the stack pointer
static jmp_buf trampo;
memmove(trampo, berry.ta_cont, sizeof(berry.ta_cont));
#if defined(ESP8266) || defined(ESP32)
trampo[1] = (int32_t) berry.stack; // change stack
#else
#error "Need CPU specific code for setting alternate stack"
#endif
longjmp(trampo, (int)func);
// this part is unreachable (longjmp does not return)
} else if (r == -1) {
// Tasmota stack active
// ----------------------------------
// the call has completed normally, and `yield` was not called
berry.ta_cont_ok = false;
AddLog(LOG_LEVEL_INFO, PSTR("Trampo: old stack restored"));
// printStack();
} else {
// WARNING
// ALTERNATE stack active
// - DON'T USE ANY LOCAL VARIABLE HERE
// -----------------------------------
// r contains the address of the function to call
// AddLog(LOG_LEVEL_INFO, "Trampo: new stack reg");
// printStack();
berry.ta_cont_ok = true; // Berry can call back Tasmota thread
callBerryFunctionVoid("noop");
AddLog(LOG_LEVEL_INFO, PSTR("Trampo: after callBerryFunctionVoid"));
// printStack();
longjmp(berry.ta_cont, -1);
// this part is unreachable (longjmp does not return)
// which protects us from accidentally using the alternate stack
// in regular code
}
// Tasmota stack active
// ----------------------------------
}
#endif // USE_BERRY_ASYNC
// void fake_callBerryFunctionVoid(const char * fname, jmp_buf * env) {
// (void) setjmp(env);
// }
// void call_callBerryFunctionVoid(const char * fname, jmp_buf * ret_env, ) {
// callBerryFunctionVoid(fname);
// longjump(env, 1);
// }
/*********************************************************************************************\
* Handlers for Berry calls and async
*
@ -553,10 +416,16 @@ const char berry_prog[] PROGMEM =
"end "
"end "
// Delay function, internally calls yield() every 10ms to avoid WDT
"tasmota.delay = def(ms) "
"tend = tasmota.millis(ms) "
"while !tasmota.timereached(tend) "
"tasmota.yield() "
"end "
"end "
// trigger Garbage Collector
"gc.collect() "
// "n = 1;"
// "def every_second() n = n + 1; if (n % 100 == 10) log('foobar '+str(n)+' free_heap = '+str(tasmota.getfreeheap())) end end; "
;
/*********************************************************************************************\
@ -567,28 +436,17 @@ void BrReset(void) {
if (berry.vm != nullptr) {
be_vm_delete(berry.vm);
berry.vm = nullptr;
#ifdef USE_BERRY_ASYNC
berry.ta_cont_ok = false; // is the Tasmota continuation address valid?
berry.vm_cont_ok = false; // is the VM continuation address valid?
#endif // USE_BERRY_ASYNC
}
int32_t ret_code1, ret_code2;
bool berry_init_ok = false;
do {
#ifdef USE_BERRY_ASYNC
berry.stack_alloc = (uint8_t*) malloc(BERRY_STACK); // alternate stack
berry.stack = berry.stack_alloc + BERRY_STACK; // top of stack
#endif // USE_BERRY_ASYNC
do {
uint32_t heap_before = ESP.getFreeHeap();
berry.vm = be_vm_new(); /* create a virtual machine instance */
AddLog(LOG_LEVEL_DEBUG, PSTR(D_LOG_BERRY "Berry VM created, RAM consumed=%u (Heap=%u)"), heap_before - ESP.getFreeHeap(), ESP.getFreeHeap());
// Register functions
be_regfunc(berry.vm, PSTR("log"), l_logInfo);
// be_regfunc(berry.vm, "printStack", l_printStack);
be_regfunc(berry.vm, PSTR("yield"), l_yield);
AddLog(LOG_LEVEL_DEBUG, PSTR(D_LOG_BERRY "Berry function registered, RAM consumed=%u (Heap=%u)"), heap_before - ESP.getFreeHeap(), ESP.getFreeHeap());
@ -608,83 +466,6 @@ void BrReset(void) {
AddLog(LOG_LEVEL_DEBUG, PSTR(D_LOG_BERRY "Berry code ran, RAM consumed=%u (Heap=%u)"), heap_before - ESP.getFreeHeap(), ESP.getFreeHeap());
be_pop(berry.vm, 1);
// AddLog(LOG_LEVEL_INFO, PSTR("Get function"));
// AddLog(LOG_LEVEL_INFO, PSTR("BE_TOP = %d"), be_top(berry.vm));
// AddLog(LOG_LEVEL_INFO, PSTR("Get function"));
// be_getglobal(vm, PSTR("func"));
// be_pushint(vm, 3);
// be_pcall(vm, 1);
// be_pop(vm, 2);
// // AddLog(LOG_LEVEL_INFO, PSTR("BE_TOP = %d"), be_top(vm));
// be_getglobal(vm, "testreal");
// AddLog(LOG_LEVEL_INFO, PSTR("is_nil -1 = %d"), be_isnil(vm, -1));
// be_pcall(vm, 0);
// // AddLog(LOG_LEVEL_INFO, PSTR("is_nil -1 = %d"), be_isnil(vm, -1));
// AddLog(LOG_LEVEL_INFO, PSTR("to_string -1 = %s"), be_tostring(vm, -1));
// be_pop(vm, 1);
// AddLog(LOG_LEVEL_INFO, PSTR("BE_TOP = %d"), be_top(vm));
// try a non-existant function
// be_getglobal(vm, "doesnotexist");
// AddLog(LOG_LEVEL_INFO, PSTR("is_nil -1 = %d"), be_isnil(vm, -1));
// AddLog(LOG_LEVEL_INFO, PSTR("BE_TOP = %d"), be_top(vm));
// be_pop(vm, 1);
// Try
// callBerryFunctionVoid("noop");
// callBerryFunctionVoid("noop2");
// test_input();
/////////////////////////////////
// callTrampoline(nullptr);
// // Try coroutines
// int jmp_val;
// if ((jmp_val=setjmp(berry.ta_cont)) == 0) {
// AddLog(LOG_LEVEL_INFO, "vm return address = 0x%08X", berry.ta_cont[0]);
// AddLog(LOG_LEVEL_INFO, "vm stack address = 0x%08X", berry.ta_cont[1]);
// callTrampoline(nullptr);
// // // call routine
// // jmp_buf trampoline_env;
// // fake_callBerryFunctionVoid("noop", &tasmota_env);
// // trampoline_env[0] = call_callBerryFunctionVoid
// } else {
// AddLog(LOG_LEVEL_INFO, "vm return address = 0x%08X", berry.ta_cont[0]);
// // we get back control
// }
#ifdef USE_BERRY_ASYNC
if (berry.vm_cont_ok) {
printStack();
AddLog(LOG_LEVEL_INFO, PSTR("Trampo: we need to complete vm exec 1"));
if (setjmp(berry.ta_cont) == 0) {
berry.ta_cont_ok = true;
berry.vm_cont_ok = false;
AddLog(LOG_LEVEL_INFO, PSTR("Trampo: call exec 1"));
longjmp(berry.vm_cont, 1);
}
berry.ta_cont_ok = false;
AddLog(LOG_LEVEL_INFO, PSTR("Trampo: returned from exec 1"));
}
printStack();
if (berry.vm_cont_ok) {
printStack();
AddLog(LOG_LEVEL_INFO, PSTR("Trampo: we need to complete vm exec 2"));
if (setjmp(berry.ta_cont) == 0) {
berry.ta_cont_ok = true;
berry.vm_cont_ok = false;
AddLog(LOG_LEVEL_INFO, PSTR("Trampo: call exec 2"));
longjmp(berry.vm_cont, 1);
}
berry.ta_cont_ok = false;
AddLog(LOG_LEVEL_INFO, PSTR("Trampo: returned from exec 2"));
}
printStack();
#endif // USE_BERRY_ASYNC
AddLog(LOG_LEVEL_INFO, PSTR(D_LOG_BERRY "Berry initialized, RAM consumed=%u (Heap=%u)"), heap_before - ESP.getFreeHeap(), ESP.getFreeHeap());
// AddLog(LOG_LEVEL_INFO, PSTR("Delete Berry VM"));
// be_vm_delete(vm);
@ -699,12 +480,6 @@ void BrReset(void) {
be_vm_delete(berry.vm);
berry.vm = nullptr;
}
#ifdef USE_BERRY_ASYNC
if (berry.stack_alloc != nullptr) {
free(berry.stack_alloc);
berry.stack_alloc = nullptr;
}
#endif // USE_BERRY_ASYNC
}
}

Some files were not shown because too many files have changed in this diff Show More