Merge branch 'development' of github.com:arendst/Tasmota into pr2_tm1637

This commit is contained in:
Ajith Vasudevan 2021-02-15 22:33:43 +05:30
commit dce391f3ee
19 changed files with 500 additions and 145 deletions

View File

@ -10,6 +10,8 @@ All notable changes to this project will be documented in this file.
- Support for Frysk language translations by Christiaan Heerze
- ESP8266 Fallback to ``*.bin.gz`` binary when OTA upload of ``*.bin`` binary fails
- Berry language improved Tasmota integration
- Filesystem commands ``Ufs``, ``UfsType``, ``UfsSize``, ``UfsFree``, ``UfsDelete`` and ``UfsRename``
- Basic support for filesystem ``autoexec.bat``
### Changed
- IRremoteESP8266 library from v2.7.14 to v2.7.15

View File

@ -95,6 +95,8 @@ The attached binaries can also be downloaded from http://ota.tasmota.com/tasmota
- Commands ``ZbNameKey``, ``ZbDeviceTopic``, ``ZbNoPrefix``, ``ZbEndpointSuffix``, ``ZbNoAutoBind`` and ``ZbNameTopic`` as synonyms for ``SetOption83, 89, 100, 101, 110`` and ``112``
- Commands ``ZbNoAutoBind``, ``ZbReceivedTopic`` and ``ZbOmitDevice`` as synonyms for ``SetOption116, 118`` and ``119``
- Commands ``BuzzerActive`` and ``BuzzerPwm`` as synonyms for ``SetOption67`` and ``111``
- Filesystem commands ``Ufs``, ``UfsType``, ``UfsSize``, ``UfsFree``, ``UfsDelete`` and ``UfsRename``
- Basic support for filesystem ``autoexec.bat``
- Milliseconds to console output [#10152](https://github.com/arendst/Tasmota/issues/10152)
- Gpio ``Option_a1`` enabling PWM2 high impedance if powered off as used by Wyze bulbs [#10196](https://github.com/arendst/Tasmota/issues/10196)
- Rotary No Pullup GPIO selection ``Rotary A/B_n`` [#10407](https://github.com/arendst/Tasmota/issues/10407)

View File

@ -1,9 +1,9 @@
name=Waveshare esp 2.9 inch e-paper display driver
name=Display renderer
version=1.0
author=Gerhard Mutz
maintainer=Gerhard Mutz
sentence=ESP8266 library for Waveshare e-paper display.
sentence=ESP8266 ESP32 library for Tasmota displays
paragraph=
category=Display
url=https://github.com/gemu2015/Sonoff-Tasmota/tree/displays/lib/esp-epaper-29-ws-20171230-gemu-1.0#
url=https://github.com/arendst/Tasmota
architectures=*

View File

@ -0,0 +1,9 @@
name=Waveshare esp 2.9 inch e-paper display driver
version=1.0
author=Gerhard Mutz
maintainer=Gerhard Mutz
sentence=ESP8266 ESP32 library for Waveshare 2.9 inch e-paper display
paragraph=
category=Display
url=https://github.com/arendst/Tasmota
architectures=*

View File

@ -0,0 +1,9 @@
name=Waveshare esp 4.2 inch e-paper display driver
version=1.0
author=Gerhard Mutz
maintainer=Gerhard Mutz
sentence=ESP8266 ESP32 library for Waveshare e-paper display.
paragraph=
category=Display
url=https://github.com/arendst/Tasmota
architectures=*

View File

@ -0,0 +1,9 @@
name=ILI9341
version=1.0.0
author=Gerhard Mutz
maintainer=Gerhard Mutz
sentence=ILI9341 ESP8266 ESP32 display driver for Tasmota
paragraph=ILI9341 ESP8266 ESP32 display driver for Tasmota
category=Display
url=https://github.com/arendst/Tasmota
architectures=*

View File

@ -1,9 +1,9 @@
name=RA8876
version=1.0.2
author=Jaret Burkett
maintainer=Jaret Burkett <jaretburkett@gmail.com>
sentence=Library for RA8876 displays
paragraph=Library for RA8876 displays
version=1.0.0
author=Jaret Burkett / Gerhard Mutz
maintainer=Gerhard Mutz
sentence=Tasmota Library for RA8876 displays
paragraph=Tasmota Library for RA8876 displays
category=Display
url=https://github.com/jaretburkett/ILI9488
url=https://github.com/arendst/Tasmota
architectures=*

View File

@ -0,0 +1,9 @@
name=Process_control
version=1.0.0
author=Colin Law
maintainer=Colin Law
sentence=C++ library of process control algorithms
paragraph=C++ library of process control algorithms
category=Heating
url=https://github.com/colinl/process-control.git
architectures=*

View File

@ -0,0 +1,9 @@
name=stm32_flash
version=1.0.0
author=Tormod Volden
maintainer=Tormod Volden
sentence=STM32 Flasher
paragraph=STM32 Flaher
category=Tools
url=
architectures=esp8266

View File

@ -2,7 +2,7 @@
"name": "NimBLE-Arduino",
"keywords": "esp32, bluetooth",
"description": "Bluetooth low energy (BLE) library for arduino-esp32 based on NimBLE",
"version": "1.0.2",
"version": "1.1.0",
"frameworks": "arduino",
"platforms": "espressif32"
}

View File

@ -1667,6 +1667,92 @@ void TemplateJson(void)
ResponseAppend_P(PSTR("],\"" D_JSON_FLAG "\":%d,\"" D_JSON_BASE "\":%d}"), Settings.user_template.flag, Settings.user_template_base +1);
}
#if ( defined(USE_SCRIPT) && defined(SUPPORT_MQTT_EVENT) ) || defined (USE_DT_VARS)
/*********************************************************************************************\
* Parse json paylod with path
\*********************************************************************************************/
// parser object, source keys, delimiter, float result or NULL, string result or NULL, string size
// return 1 if numeric 2 if string, else 0 = not found
uint32_t JsonParsePath(JsonParserObject *jobj, const char *spath, char delim, float *nres, char *sres, uint32_t slen) {
uint32_t res = 0;
const char *cp = spath;
#ifdef DEBUG_JSON_PARSE_PATH
AddLog(LOG_LEVEL_INFO, PSTR("JSON: parsing json key: %s from json: %s"), cp, jpath);
#endif
JsonParserObject obj = *jobj;
JsonParserObject lastobj = obj;
char selem[32];
uint8_t aindex = 0;
String value = "";
while (1) {
// read next element
for (uint32_t sp=0; sp<sizeof(selem)-1; sp++) {
if (!*cp || *cp==delim) {
selem[sp] = 0;
cp++;
break;
}
selem[sp] = *cp++;
}
#ifdef DEBUG_JSON_PARSE_PATH
AddLog(LOG_LEVEL_INFO, PSTR("JSON: cmp current key: %s"), selem);
#endif
// check for array
char *sp = strchr(selem,'[');
if (sp) {
*sp = 0;
aindex = atoi(sp+1);
}
// now check element
obj = obj[selem];
if (!obj.isValid()) {
#ifdef DEBUG_JSON_PARSE_PATH
AddLog(LOG_LEVEL_INFO, PSTR("JSON: obj invalid: %s"), selem);
#endif
JsonParserToken tok = lastobj[selem];
if (tok.isValid()) {
if (tok.isArray()) {
JsonParserArray array = JsonParserArray(tok);
value = array[aindex].getStr();
if (array.isNum()) {
if (nres) *nres=tok.getFloat();
res = 1;
} else {
res = 2;
}
} else {
value = tok.getStr();
if (tok.isNum()) {
if (nres) *nres=tok.getFloat();
res = 1;
} else {
res = 2;
}
}
}
#ifdef DEBUG_JSON_PARSE_PATH
AddLog(LOG_LEVEL_INFO, PSTR("JSON: token invalid: %s"), selem);
#endif
break;
}
if (obj.isObject()) {
lastobj = obj;
continue;
}
if (!*cp) break;
}
if (sres) {
strlcpy(sres,value.c_str(), slen);
}
return res;
}
#endif // USE_SCRIPT
/*********************************************************************************************\
* Sleep aware time scheduler functions borrowed from ESPEasy
\*********************************************************************************************/
@ -2237,6 +2323,9 @@ void AddLogSpi(bool hardware, uint32_t clk, uint32_t mosi, uint32_t miso) {
}
}
/*********************************************************************************************\
* Uncompress static PROGMEM strings
\*********************************************************************************************/

View File

@ -716,6 +716,11 @@ void MqttPublishTeleState(void)
ResponseClear();
MqttShowState();
MqttPublishPrefixTopic_P(TELE, PSTR(D_RSLT_STATE), MQTT_TELE_RETAIN);
#ifdef USE_DT_VARS
DTVarsTeleperiod();
#endif // USE_DT_VARS
#if defined(USE_RULES) || defined(USE_SCRIPT)
RulesTeleperiod(); // Allow rule based HA messages
#endif // USE_SCRIPT

View File

@ -370,10 +370,10 @@ enum DevGroupShareItem { DGR_SHARE_POWER = 1, DGR_SHARE_LIGHT_BRI = 2, DGR_SHARE
enum CommandSource { SRC_IGNORE, SRC_MQTT, SRC_RESTART, SRC_BUTTON, SRC_SWITCH, SRC_BACKLOG, SRC_SERIAL, SRC_WEBGUI, SRC_WEBCOMMAND, SRC_WEBCONSOLE, SRC_PULSETIMER,
SRC_TIMER, SRC_RULE, SRC_MAXPOWER, SRC_MAXENERGY, SRC_OVERTEMP, SRC_LIGHT, SRC_KNX, SRC_DISPLAY, SRC_WEMO, SRC_HUE, SRC_RETRY, SRC_REMOTE, SRC_SHUTTER,
SRC_THERMOSTAT, SRC_CHAT, SRC_TCL, SRC_BERRY, SRC_MAX };
SRC_THERMOSTAT, SRC_CHAT, SRC_TCL, SRC_BERRY, SRC_AUTOEXEC, SRC_MAX };
const char kCommandSource[] PROGMEM = "I|MQTT|Restart|Button|Switch|Backlog|Serial|WebGui|WebCommand|WebConsole|PulseTimer|"
"Timer|Rule|MaxPower|MaxEnergy|Overtemp|Light|Knx|Display|Wemo|Hue|Retry|Remote|Shutter|"
"Thermostat|Chat|TCL|Berry";
"Thermostat|Chat|TCL|Berry|Autoexec";
const uint8_t kDefaultRfCode[9] PROGMEM = { 0x21, 0x16, 0x01, 0x0E, 0x03, 0x48, 0x2E, 0x1A, 0x00 };

View File

@ -146,6 +146,7 @@ struct {
bool restart_halt; // Do not restart but stay in wait loop
bool module_changed; // Indicate module changed since last restart
bool wifi_stay_asleep; // Allow sleep only incase of ESP32 BLE
bool no_autoexec; // Disable autoexec
StateBitfield global_state; // Global states (currently Wifi and Mqtt) (8 bits)
uint8_t spi_enabled; // SPI configured
@ -303,6 +304,7 @@ void setup(void) {
}
if (RtcReboot.fast_reboot_count > Settings.param[P_BOOT_LOOP_OFFSET] +2) { // Restarted 4 times
Settings.rule_enabled = 0; // Disable all rules
TasmotaGlobal.no_autoexec = true;
}
if (RtcReboot.fast_reboot_count > Settings.param[P_BOOT_LOOP_OFFSET] +3) { // Restarted 5 times
for (uint32_t i = 0; i < ARRAY_SIZE(Settings.my_gp.io); i++) {

View File

@ -261,6 +261,8 @@ const uint16_t LOG_BUFFER_SIZE = 4000; // Max number of characters in lo
#define TASM_FILE_DRIVER "/.drvset%03d"
#define TASM_FILE_SENSOR "/.snsset%03d"
#define TASM_FILE_ZIGBEE "/zb" // Zigbee settings blob as used by CC2530 on ESP32
#define TASM_FILE_AUTOEXEC "/autoexec.bat" // Commands executed after restart
#define TASM_FILE_CONFIG "/config.sys" // Settings executed after restart
#ifndef MQTT_MAX_PACKET_SIZE
#define MQTT_MAX_PACKET_SIZE 1200 // Bytes

View File

@ -501,7 +501,7 @@ void EnergyEverySecond(void)
{
// Overtemp check
if (TasmotaGlobal.global_update) {
if (TasmotaGlobal.power && !isnan(TasmotaGlobal.temperature_celsius) && (TasmotaGlobal.temperature_celsius > (float)Settings.param[P_OVER_TEMP])) { // Device overtemp, turn off relays
if (TasmotaGlobal.power && !isnan(TasmotaGlobal.temperature_celsius) && (TasmotaGlobal.temperature_celsius > (float)Settings.param[P_OVER_TEMP])) { // SetOption42 Device overtemp, turn off relays
AddLog(LOG_LEVEL_DEBUG, PSTR("NRG: GlobTemp %1_f"), &TasmotaGlobal.temperature_celsius);

View File

@ -4326,14 +4326,13 @@ int16_t Run_script_sub(const char *type, int8_t tlen, struct GVARS *gv) {
goto next_line;
}
#ifdef USE_SENDMAIL
/*
else if (!strncmp(lp, "sm", 2)) {
lp+=3;
else if (!strncmp(lp, "mail", 4)) {
lp+=5;
char tmp[256];
Replace_Cmd_Vars(lp ,1 , tmp, sizeof(tmp));
SendMail(tmp);
goto next_line;
}*/
}
#endif
else if (!strncmp(lp,"=>",2) || !strncmp(lp,"->",2) || !strncmp(lp,"+>",2) || !strncmp(lp,"print",5)) {
// execute cmd
@ -5819,14 +5818,14 @@ void dateTime(uint16_t* date, uint16_t* time) {
#ifdef SUPPORT_MQTT_EVENT
/*
//#define DEBUG_MQTT_EVENT
// parser object, source keys, delimiter, float result or NULL, string result or NULL, string size
uint32_t JsonParsePath(JsonParserObject *jobj, const char *spath, char delim, float *nres, char *sres, uint32_t slen) {
uint32_t res = 0;
const char *cp = spath;
#ifdef DEBUG_MQTT_EVENT
// AddLog(LOG_LEVEL_INFO, PSTR("Script: parsing json key: %s from json: %s"), cp, jpath);
#ifdef DEBUG_JSON_PARSE_PATH
AddLog(LOG_LEVEL_INFO, PSTR("JSON: parsing json key: %s from json: %s"), cp, jpath);
#endif
JsonParserObject obj = *jobj;
JsonParserObject lastobj = obj;
@ -5843,8 +5842,8 @@ uint32_t JsonParsePath(JsonParserObject *jobj, const char *spath, char delim, fl
}
selem[sp] = *cp++;
}
#ifdef DEBUG_MQTT_EVENT
AddLog(LOG_LEVEL_INFO, PSTR("Script: cmp current key: %s"), selem);
#ifdef DEBUG_JSON_PARSE_PATH
AddLog(LOG_LEVEL_INFO, PSTR("JSON: cmp current key: %s"), selem);
#endif
// check for array
char *sp = strchr(selem,'[');
@ -5856,8 +5855,8 @@ uint32_t JsonParsePath(JsonParserObject *jobj, const char *spath, char delim, fl
// now check element
obj = obj[selem];
if (!obj.isValid()) {
#ifdef DEBUG_MQTT_EVENT
AddLog(LOG_LEVEL_INFO, PSTR("Script: obj invalid: %s"), selem);
#ifdef DEBUG_JSON_PARSE_PATH
AddLog(LOG_LEVEL_INFO, PSTR("JSON: obj invalid: %s"), selem);
#endif
JsonParserToken tok = lastobj[selem];
if (tok.isValid()) {
@ -5881,8 +5880,8 @@ uint32_t JsonParsePath(JsonParserObject *jobj, const char *spath, char delim, fl
}
}
#ifdef DEBUG_MQTT_EVENT
AddLog(LOG_LEVEL_INFO, PSTR("Script: token invalid: %s"), selem);
#ifdef DEBUG_JSON_PARSE_PATH
AddLog(LOG_LEVEL_INFO, PSTR("JSON: token invalid: %s"), selem);
#endif
break;
}
@ -5892,11 +5891,13 @@ uint32_t JsonParsePath(JsonParserObject *jobj, const char *spath, char delim, fl
}
if (!*cp) break;
}
strlcpy(sres,value.c_str(),slen);
if (sres) {
strlcpy(sres,value.c_str(), slen);
}
return res;
}
*/
#ifndef MQTT_EVENT_MSIZE
#define MQTT_EVENT_MSIZE 256
#endif // MQTT_EVENT_MSIZE

View File

@ -180,95 +180,6 @@ void DisplayClear(void)
XdspCall(FUNC_DISPLAY_CLEAR);
}
void DisplayDrawHLine(uint16_t x, uint16_t y, int16_t len, uint16_t color)
{
dsp_x = x;
dsp_y = y;
dsp_len = len;
dsp_color = color;
XdspCall(FUNC_DISPLAY_DRAW_HLINE);
}
void DisplayDrawVLine(uint16_t x, uint16_t y, int16_t len, uint16_t color)
{
dsp_x = x;
dsp_y = y;
dsp_len = len;
dsp_color = color;
XdspCall(FUNC_DISPLAY_DRAW_VLINE);
}
void DisplayDrawLine(uint16_t x, uint16_t y, uint16_t x2, uint16_t y2, uint16_t color)
{
dsp_x = x;
dsp_y = y;
dsp_x2 = x2;
dsp_y2 = y2;
dsp_color = color;
XdspCall(FUNC_DISPLAY_DRAW_LINE);
}
void DisplayDrawCircle(uint16_t x, uint16_t y, uint16_t rad, uint16_t color)
{
dsp_x = x;
dsp_y = y;
dsp_rad = rad;
dsp_color = color;
XdspCall(FUNC_DISPLAY_DRAW_CIRCLE);
}
void DisplayDrawFilledCircle(uint16_t x, uint16_t y, uint16_t rad, uint16_t color)
{
dsp_x = x;
dsp_y = y;
dsp_rad = rad;
dsp_color = color;
XdspCall(FUNC_DISPLAY_FILL_CIRCLE);
}
void DisplayDrawRectangle(uint16_t x, uint16_t y, uint16_t x2, uint16_t y2, uint16_t color)
{
dsp_x = x;
dsp_y = y;
dsp_x2 = x2;
dsp_y2 = y2;
dsp_color = color;
XdspCall(FUNC_DISPLAY_DRAW_RECTANGLE);
}
void DisplayDrawFilledRectangle(uint16_t x, uint16_t y, uint16_t x2, uint16_t y2, uint16_t color)
{
dsp_x = x;
dsp_y = y;
dsp_x2 = x2;
dsp_y2 = y2;
dsp_color = color;
XdspCall(FUNC_DISPLAY_FILL_RECTANGLE);
}
void DisplayDrawFrame(void)
{
XdspCall(FUNC_DISPLAY_DRAW_FRAME);
}
void DisplaySetSize(uint8_t size)
{
Settings.display_size = size &3;
XdspCall(FUNC_DISPLAY_TEXT_SIZE);
}
void DisplaySetFont(uint8_t font)
{
Settings.display_font = font &3;
XdspCall(FUNC_DISPLAY_FONT_SIZE);
}
void DisplaySetRotation(uint8_t rotation)
{
Settings.display_rotate = rotation &3;
XdspCall(FUNC_DISPLAY_ROTATION);
}
void DisplayDrawStringAt(uint16_t x, uint16_t y, char *str, uint16_t color, uint8_t flag)
{
dsp_x = x;
@ -559,10 +470,10 @@ void DisplayText(void)
cp += var;
if (temp < 0) {
if (renderer) renderer->writeFastHLine(disp_xpos + temp, disp_ypos, -temp, fg_color);
else DisplayDrawHLine(disp_xpos + temp, disp_ypos, -temp, fg_color);
//else DisplayDrawHLine(disp_xpos + temp, disp_ypos, -temp, fg_color);
} else {
if (renderer) renderer->writeFastHLine(disp_xpos, disp_ypos, temp, fg_color);
else DisplayDrawHLine(disp_xpos, disp_ypos, temp, fg_color);
//else DisplayDrawHLine(disp_xpos, disp_ypos, temp, fg_color);
}
disp_xpos += temp;
break;
@ -572,10 +483,10 @@ void DisplayText(void)
cp += var;
if (temp < 0) {
if (renderer) renderer->writeFastVLine(disp_xpos, disp_ypos + temp, -temp, fg_color);
else DisplayDrawVLine(disp_xpos, disp_ypos + temp, -temp, fg_color);
//else DisplayDrawVLine(disp_xpos, disp_ypos + temp, -temp, fg_color);
} else {
if (renderer) renderer->writeFastVLine(disp_xpos, disp_ypos, temp, fg_color);
else DisplayDrawVLine(disp_xpos, disp_ypos, temp, fg_color);
//else DisplayDrawVLine(disp_xpos, disp_ypos, temp, fg_color);
}
disp_ypos += temp;
break;
@ -587,7 +498,7 @@ void DisplayText(void)
var = atoiv(cp, &temp1);
cp += var;
if (renderer) renderer->writeLine(disp_xpos, disp_ypos, temp, temp1, fg_color);
else DisplayDrawLine(disp_xpos, disp_ypos, temp, temp1, fg_color);
//else DisplayDrawLine(disp_xpos, disp_ypos, temp, temp1, fg_color);
disp_xpos += temp;
disp_ypos += temp1;
break;
@ -596,14 +507,14 @@ void DisplayText(void)
var = atoiv(cp, &temp);
cp += var;
if (renderer) renderer->drawCircle(disp_xpos, disp_ypos, temp, fg_color);
else DisplayDrawCircle(disp_xpos, disp_ypos, temp, fg_color);
//else DisplayDrawCircle(disp_xpos, disp_ypos, temp, fg_color);
break;
case 'K':
// filled circle
var = atoiv(cp, &temp);
cp += var;
if (renderer) renderer->fillCircle(disp_xpos, disp_ypos, temp, fg_color);
else DisplayDrawFilledCircle(disp_xpos, disp_ypos, temp, fg_color);
//else DisplayDrawFilledCircle(disp_xpos, disp_ypos, temp, fg_color);
break;
case 'r':
// rectangle
@ -613,7 +524,7 @@ void DisplayText(void)
var = atoiv(cp, &temp1);
cp += var;
if (renderer) renderer->drawRect(disp_xpos, disp_ypos, temp, temp1, fg_color);
else DisplayDrawRectangle(disp_xpos, disp_ypos, temp, temp1, fg_color);
//else DisplayDrawRectangle(disp_xpos, disp_ypos, temp, temp1, fg_color);
break;
case 'R':
// filled rectangle
@ -623,7 +534,7 @@ void DisplayText(void)
var = atoiv(cp, &temp1);
cp += var;
if (renderer) renderer->fillRect(disp_xpos, disp_ypos, temp, temp1, fg_color);
else DisplayDrawFilledRectangle(disp_xpos, disp_ypos, temp, temp1, fg_color);
//else DisplayDrawFilledRectangle(disp_xpos, disp_ypos, temp, temp1, fg_color);
break;
case 'u':
// rounded rectangle
@ -696,9 +607,49 @@ void DisplayText(void)
index_colors[temp] = ftemp;
break;
}
#ifdef USE_DT_VARS
if (*cp == 'v') {
cp++;
{ int16_t num, gxp, gyp, textbcol, textfcol, font, textsize, txlen, dp;
var=atoiv(cp,&num);
cp+=var;
cp++;
var=atoiv(cp,&gxp);
cp+=var;
cp++;
var=atoiv(cp,&gyp);
cp+=var;
cp++;
var=atoiv(cp,&textbcol);
cp+=var;
cp++;
var=atoiv(cp,&textfcol);
cp+=var;
cp++;
var=atoiv(cp,&font);
cp+=var;
cp++;
var=atoiv(cp,&textsize);
cp+=var;
cp++;
var=atoiv(cp,&txlen);
cp+=var;
cp++;
var=atoiv(cp,&dp);
cp+=var;
cp++;
// text itself
char bbuff[32];
cp = get_string(bbuff, sizeof(bbuff), cp);
char unit[4];
cp = get_string(unit, sizeof(unit), cp);
define_dt_var(num, gxp, gyp, textbcol, textfcol, font, textsize, txlen, dp, bbuff, unit);
}
}
#endif // USE_DT_VARS
// force draw grafics buffer
if (renderer) renderer->Updateframe();
else DisplayDrawFrame();
//else DisplayDrawFrame();
break;
case 'D':
// set auto draw mode
@ -709,18 +660,18 @@ void DisplayText(void)
case 's':
// size sx
if (renderer) renderer->setTextSize(*cp&7);
else DisplaySetSize(*cp&3);
//else DisplaySetSize(*cp&3);
cp += 1;
break;
case 'f':
// font sx
{ uint8_t font = *cp&7;
if (renderer) renderer->setTextFont(font);
else DisplaySetFont(font);
//else DisplaySetFont(font);
if (font) {
// for backward compatibility set size to 1 on non GFX fonts
if (renderer) renderer->setTextSize(1);
else DisplaySetSize(1);
//else DisplaySetSize(1);
}
cp += 1;
}
@ -728,7 +679,7 @@ void DisplayText(void)
case 'a':
// rotation angle
if (renderer) renderer->setRotation(*cp&3);
else DisplaySetRotation(*cp&3);
//else DisplaySetRotation(*cp&3);
cp+=1;
break;
@ -976,7 +927,7 @@ void DisplayText(void)
// draw buffer
if (auto_draw&1) {
if (renderer) renderer->Updateframe();
else DisplayDrawFrame();
//else DisplayDrawFrame();
}
}
@ -1019,6 +970,167 @@ void Display_Text_From_File(const char *file) {
}
#endif
#ifdef USE_DT_VARS
#ifndef MAX_DT_VARS
#define MAX_DT_VARS 8
#endif // MAX_DT_VARS
#define MAX_DVTSIZE 24
typedef struct {
uint16_t xp;
uint16_t yp;
uint8_t txtbcol;
uint8_t txtfcol;
int8_t txtsiz;
int8_t txtlen;
int8_t dp;
int8_t font;
char unit[6];
char *jstrbuf;
char rstr[32];
} DT_VARS;
DT_VARS *dt_vars[MAX_DT_VARS];
void define_dt_var(uint32_t num, uint32_t xp, uint32_t yp, uint32_t txtbcol, uint32_t txtfcol, int32_t font, int32_t txtsiz, int32_t txtlen, int32_t dp, char *jstr, char *unit) {
if (num >= MAX_DT_VARS) return;
if (dt_vars[num]) {
if (dt_vars[num]->jstrbuf) free(dt_vars[num]->jstrbuf);
free(dt_vars[num]);
}
//dt [dv0:100:100:0:3:2:1:10:2:WLAN#ID:uV:]
DT_VARS *dtp = (DT_VARS*)malloc(sizeof(DT_VARS));
if (!dtp) return;
dt_vars[num] = dtp;
dtp->xp = xp;
dtp->yp = yp;
dtp->txtbcol = txtbcol;
dtp->txtfcol = txtfcol;
dtp->font = font;
dtp->txtsiz = txtsiz;
if (txtlen > MAX_DVTSIZE) {txtlen = MAX_DVTSIZE;}
dtp->txtlen = txtlen;
dtp->dp = dp;
dtp->jstrbuf = (char*)malloc(strlen(jstr + 1));
if (!dtp->jstrbuf) {
free (dtp);
return;
}
strcpy(dtp->jstrbuf, jstr);
strcpy(dtp->unit,unit);
}
void draw_dt_vars(void) {
if (!renderer) return;
for (uint32_t cnt = 0; cnt < MAX_DT_VARS; cnt++) {
if (dt_vars[cnt]) {
if (dt_vars[cnt]->jstrbuf) {
// draw
char vstr[MAX_DVTSIZE + 7];
memset(vstr, ' ', sizeof(vstr));
strcpy(vstr, dt_vars[cnt]->rstr);
strcat(vstr, " ");
strcat(vstr, dt_vars[cnt]->unit);
uint16_t slen = strlen(vstr);
vstr[slen] = ' ';
if (!dt_vars[cnt]->txtlen) {
vstr[slen] = 0;
} else {
vstr[abs(int(dt_vars[cnt]->txtlen))] = 0;
}
if (dt_vars[cnt]->txtlen < 0) {
// right align
alignright(vstr);
}
if (dt_vars[cnt]->txtsiz > 0) {
renderer->setDrawMode(0);
} else {
renderer->setDrawMode(2);
}
renderer->setTextColor(GetColorFromIndex(dt_vars[cnt]->txtfcol),GetColorFromIndex(dt_vars[cnt]->txtbcol));
renderer->setTextFont(dt_vars[cnt]->font);
renderer->setTextSize(abs(dt_vars[cnt]->txtsiz));
renderer->DrawStringAt(dt_vars[cnt]->xp, dt_vars[cnt]->yp, vstr, GetColorFromIndex(dt_vars[cnt]->txtfcol), 0);
// reset display vars
renderer->setTextColor(fg_color, bg_color);
renderer->setDrawMode(auto_draw);
}
}
}
}
#define DTV_JSON_SIZE 1024
void DTVarsTeleperiod(void) {
char *json = (char*)malloc(DTV_JSON_SIZE);
if (json) {
strlcpy(json, TasmotaGlobal.mqtt_data, DTV_JSON_SIZE);
get_dt_vars(json);
free(json);
}
}
void get_dt_mqtt(void) {
ResponseClear();
uint16_t script_tele_period_save = TasmotaGlobal.tele_period;
TasmotaGlobal.tele_period = 2;
XsnsNextCall(FUNC_JSON_APPEND, script_xsns_index);
TasmotaGlobal.tele_period = script_tele_period_save;
if (strlen(TasmotaGlobal.mqtt_data)) {
TasmotaGlobal.mqtt_data[0] = '{';
snprintf_P(TasmotaGlobal.mqtt_data, sizeof(TasmotaGlobal.mqtt_data), PSTR("%s}"), TasmotaGlobal.mqtt_data);
}
get_dt_vars(TasmotaGlobal.mqtt_data);
}
void get_dt_vars(char *json) {
if (strlen(json)) {
JsonParser parser(json);
JsonParserObject obj = parser.getRootObject();
for (uint32_t cnt = 0; cnt < MAX_DT_VARS; cnt++) {
if (dt_vars[cnt]) {
if (dt_vars[cnt]->jstrbuf) {
char sbuf[32];
uint32_t res = JsonParsePath(&obj, dt_vars[cnt]->jstrbuf, '#', NULL, sbuf, sizeof(sbuf));
if (res) {
if (dt_vars[cnt]->dp < 0) {
// use string
strcpy(dt_vars[cnt]->rstr, sbuf);
} else {
// convert back and forth
dtostrfd(CharToFloat(sbuf), dt_vars[cnt]->dp, dt_vars[cnt]->rstr);
}
}
}
}
}
}
}
void free_dt_vars(void) {
for (uint32_t cnt = 0; cnt < MAX_DT_VARS; cnt++) {
if (dt_vars[cnt]) {
if (dt_vars[cnt]->jstrbuf) free(dt_vars[cnt]->jstrbuf);
free(dt_vars[cnt]);
dt_vars[cnt] = 0;
}
}
}
#endif // USE_DT_VARS
/*********************************************************************************************/
#ifdef USE_DISPLAY_MODES1TO5
@ -1423,6 +1535,10 @@ void DisplayInitDriver(void)
Display_Text_From_File("/display.ini");
#endif
#ifdef USE_DT_VARS
free_dt_vars();
#endif
// AddLog(LOG_LEVEL_DEBUG, PSTR(D_LOG_DEBUG "Display model %d"), Settings.display_model);
if (Settings.display_model) {
@ -1688,7 +1804,7 @@ void CmndDisplaySize(void)
if ((XdrvMailbox.payload > 0) && (XdrvMailbox.payload <= 4)) {
Settings.display_size = XdrvMailbox.payload;
if (renderer) renderer->setTextSize(Settings.display_size);
else DisplaySetSize(Settings.display_size);
//else DisplaySetSize(Settings.display_size);
}
ResponseCmndNumber(Settings.display_size);
}
@ -1698,7 +1814,7 @@ void CmndDisplayFont(void)
if ((XdrvMailbox.payload >=0) && (XdrvMailbox.payload <= 4)) {
Settings.display_font = XdrvMailbox.payload;
if (renderer) renderer->setTextFont(Settings.display_font);
else DisplaySetFont(Settings.display_font);
//else DisplaySetFont(Settings.display_font);
}
ResponseCmndNumber(Settings.display_font);
}
@ -2547,9 +2663,7 @@ bool Xdrv13(uint8_t function)
case FUNC_PRE_INIT:
DisplayInitDriver();
#ifdef USE_GRAPH
for (uint8_t count=0;count<NUM_GRAPHS;count++) {
graph[count]=0;
}
for (uint8_t count = 0; count < NUM_GRAPHS; count++) { graph[count] = 0; }
#endif
break;
case FUNC_EVERY_50_MSECOND:
@ -2562,11 +2676,16 @@ bool Xdrv13(uint8_t function)
#ifdef USE_GRAPH
DisplayCheckGraph();
#endif
#ifdef USE_DT_VARS
get_dt_mqtt();
draw_dt_vars();
#endif // USE_DT_VARS
#ifdef USE_DISPLAY_MODES1TO5
if (Settings.display_model && Settings.display_mode) { XdspCall(FUNC_DISPLAY_EVERY_SECOND); }
#endif
break;
#ifdef USE_DISPLAY_MODES1TO5
case FUNC_MQTT_SUBSCRIBE:
DisplayMqttSubscribe();

View File

@ -83,7 +83,11 @@ uint8_t ufs_dir;
// 0 = None, 1 = SD, 2 = ffat, 3 = littlefs
uint8_t ufs_type;
uint8_t ffs_type;
bool download_busy;
struct {
bool download_busy;
bool autoexec = false;
} UfsData;
/*********************************************************************************************/
@ -332,15 +336,67 @@ bool TfsDeleteFile(const char *fname) {
return true;
}
bool TfsRenameFile(const char *fname1, const char *fname2) {
if (!ffs_type) { return false; }
if (!ffsp->rename(fname1, fname2)) {
AddLog(LOG_LEVEL_INFO, PSTR("TFS: Rename failed"));
return false;
}
return true;
}
/*********************************************************************************************\
* Autoexec support
\*********************************************************************************************/
void UfsAutoexec(void) {
if (!ffs_type) { return; }
File file = ffsp->open(TASM_FILE_AUTOEXEC, "r");
if (!file) { return; }
char cmd_line[512];
while (file.available()) {
uint16_t index = 0;
while (file.available()) {
uint8_t buf[1];
file.read(buf, 1);
if ((buf[0] == '\n') || (buf[0] == '\r')) {
// Line terminated with linefeed or carriage return
if (index < sizeof(cmd_line) - 1) {
// Process line
break;
} else {
// Discard too long line and start with next line
index = 0;
}
}
else if ((0 == index) && isspace(buf[0])) {
// Skip leading spaces (' ','\t','\n','\v','\f','\r')
}
else if (index < sizeof(cmd_line) - 2) {
cmd_line[index++] = buf[0];
}
}
if ((index > 0) && (cmd_line[0] != ';')) { // Information but no comment
cmd_line[index] = 0;
ExecuteCommand(cmd_line, SRC_AUTOEXEC);
}
delay(0);
}
file.close();
}
/*********************************************************************************************\
* Commands
\*********************************************************************************************/
const char kUFSCommands[] PROGMEM = "Ufs|" // Prefix
"|Type|Size|Free|Delete";
"|Type|Size|Free|Delete|Rename";
void (* const kUFSCommand[])(void) PROGMEM = {
&UFSInfo, &UFSType, &UFSSize, &UFSFree, &UFSDelete};
&UFSInfo, &UFSType, &UFSSize, &UFSFree, &UFSDelete, &UFSRename};
void UFSInfo(void) {
Response_P(PSTR("{\"Ufs\":{\"Type\":%d,\"Size\":%d,\"Free\":%d}"), ufs_type, UfsInfo(0, 0), UfsInfo(1, 0));
@ -392,11 +448,32 @@ void UFSDelete(void) {
}
}
void UFSRename(void) {
// UfsRename sdcard or flashfs file if only one of them available
// UfsRename2 flashfs file if available
if (XdrvMailbox.data_len > 0) {
bool result = false;
const char *fname1 = strtok(XdrvMailbox.data, ",");
const char *fname2 = strtok(nullptr, ",");
if (fname1 && fname2) {
if (ffs_type && (ffs_type != ufs_type) && (2 == XdrvMailbox.index)) {
result = TfsRenameFile(fname1, fname2);
} else {
result = (ufs_type && ufsp->rename(fname1, fname2));
}
}
if (!result) {
ResponseCmndChar(PSTR(D_JSON_FAILED));
} else {
ResponseCmndDone();
}
}
}
/*********************************************************************************************\
* Web support
\*********************************************************************************************/
#ifdef USE_WEBSERVER
const char UFS_WEB_DIR[] PROGMEM =
@ -654,12 +731,12 @@ uint8_t UfsDownloadFile(char *file) {
#ifdef ESP32_DOWNLOAD_TASK
download_file.close();
if (download_busy == true) {
if (UfsData.download_busy == true) {
AddLog(LOG_LEVEL_INFO, PSTR("UFS: Download is busy"));
return 0;
}
download_busy = true;
UfsData.download_busy = true;
char *path = (char*)malloc(128);
strcpy(path,file);
xTaskCreatePinnedToCore(donload_task, "DT", 6000, (void*)path, 3, NULL, 1);
@ -710,7 +787,7 @@ void donload_task(void *path) {
}
download_file.close();
download_Client.stop();
download_busy = false;
UfsData.download_busy = false;
vTaskDelete( NULL );
}
#endif // ESP32_DOWNLOAD_TASK
@ -752,6 +829,17 @@ bool Xdrv50(uint8_t function) {
UfsCheckSDCardInit();
break;
#endif // USE_SDCARD
case FUNC_EVERY_SECOND:
if (UfsData.autoexec) {
// Safe to execute autoexec commands here
UfsData.autoexec = false;
if (!TasmotaGlobal.no_autoexec) { UfsAutoexec(); }
}
break;
case FUNC_MQTT_INIT:
// Do not execute autoexec commands here
UfsData.autoexec = true;
break;
case FUNC_COMMAND:
result = DecodeCommand(kUFSCommands, kUFSCommand);
break;