2019-05-18 08:45:04 +01:00
/*
2019-10-27 10:13:24 +00:00
xdrv_10_scripter . ino - script support for Tasmota
2019-05-18 08:45:04 +01:00
2021-01-03 07:13:16 +00:00
Copyright ( C ) 2021 Gerhard Mutz and Theo Arends
2019-05-18 08:45:04 +01:00
This program is free software : you can redistribute it and / or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation , either version 3 of the License , or
( at your option ) any later version .
This program 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 General Public License for more details .
You should have received a copy of the GNU General Public License
along with this program . If not , see < http : //www.gnu.org/licenses/>.
*/
2020-04-12 12:22:23 +01:00
2019-05-18 12:34:52 +01:00
# ifdef USE_SCRIPT
# ifndef USE_RULES
/*********************************************************************************************\
for documentation see up to date docs in file SCRIPTER . md
2019-05-30 12:23:54 +01:00
uses about 17 k of flash
2019-05-18 08:45:04 +01:00
2019-05-18 12:34:52 +01:00
to do
2019-05-18 08:45:04 +01:00
optimize code for space
2019-05-18 12:34:52 +01:00
remarks
2019-05-22 11:33:51 +01:00
2019-05-18 08:45:04 +01:00
goal is fast execution time , minimal use of ram and intuitive syntax
therefore = >
case sensitive cmds and vars ( lowercase uses time and code )
no math hierarchy ( costs ram and execution time , better group with brackets , anyhow better readable for beginners )
( will probably make math hierarchy an ifdefed option )
keywords if then else endif , or , and are better readable for beginners ( others may use { } )
2019-05-18 12:34:52 +01:00
2021-01-05 15:37:22 +00:00
// to doo
remove all filesystem inititialization and gui
adapt 3 options
1. ufilesystem
2. eeprom hardware and emulation
3. compression
2019-05-18 12:34:52 +01:00
\ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2019-05-18 08:45:04 +01:00
# define XDRV_10 10
2019-11-07 15:56:05 +00:00
# define XI2C_37 37 // See I2CDEVICES.md
2019-05-18 08:45:04 +01:00
# define SCRIPT_DEBUG 0
2020-08-09 09:58:22 +01:00
# define FORMAT_SPIFFS_IF_FAILED true
2019-09-30 09:25:02 +01:00
# ifndef MAXVARS
2019-05-18 08:45:04 +01:00
# define MAXVARS 50
2019-09-30 09:25:02 +01:00
# endif
# ifndef MAXSVARS
2019-05-18 08:45:04 +01:00
# define MAXSVARS 5
2019-09-30 09:25:02 +01:00
# endif
2019-09-24 14:30:26 +01:00
# define MAXNVARS MAXVARS-MAXSVARS
2020-05-21 05:06:42 +01:00
# ifndef MAXFILT
2019-05-18 08:45:04 +01:00
# define MAXFILT 5
2020-05-21 05:06:42 +01:00
# endif
2019-05-18 08:45:04 +01:00
# define SCRIPT_SVARSIZE 20
# define SCRIPT_MAXSSIZE 48
# define SCRIPT_EOL '\n'
# define SCRIPT_FLOAT_PRECISION 2
2019-12-25 08:04:54 +00:00
# define PMEM_SIZE sizeof(Settings.script_pram)
# define SCRIPT_MAXPERM (PMEM_SIZE)-4 / sizeof(float)
2019-05-30 12:23:54 +01:00
# define MAX_SCRIPT_SIZE MAX_RULE_SIZE*MAX_RULE_SETS
2019-05-18 08:45:04 +01:00
2020-09-23 11:51:35 +01:00
# define MAX_SARRAY_NUM 32
2020-04-12 12:22:23 +01:00
2020-12-18 15:06:51 +00:00
//uint32_t EncodeLightId(uint8_t relay_id);
//uint32_t DecodeLightId(uint32_t hue_id);
2020-04-12 12:22:23 +01:00
2021-01-05 15:37:22 +00:00
# define SPECIAL_EEPMODE_SIZE 6200
2020-06-15 16:20:50 +01:00
2021-01-05 15:37:22 +00:00
# ifdef USE_UFILESYS
2020-08-09 09:58:22 +01:00
2021-01-05 15:37:22 +00:00
# undef USE_SCRIPT_FATFS
# define USE_SCRIPT_FATFS -1
# pragma message "universal file system used"
2020-06-05 19:15:16 +01:00
2021-01-05 15:37:22 +00:00
# else // USE_UFILESYS
2020-06-05 19:15:16 +01:00
// eeprom script
# ifdef EEP_SCRIPT_SIZE
2021-01-05 15:37:22 +00:00
# ifdef ESP32
# error "unsupported option for ESP32"
# endif
2020-06-05 19:15:16 +01:00
# ifdef USE_24C256
# pragma message "script 24c256 file option used"
# else
2021-01-05 15:37:22 +00:00
# if EEP_SCRIPT_SIZE==SPECIAL_EEPMODE_SIZE
2020-12-13 06:32:09 +00:00
# pragma message "internal compressed eeprom script buffer used"
2021-01-05 15:37:22 +00:00
# else
# error "unsupported eeprom option used"
2020-12-13 06:32:09 +00:00
# endif
2021-01-05 15:37:22 +00:00
# endif // USE_24C256
# else // EEP_SCRIPT_SIZE
2020-06-05 19:15:16 +01:00
2021-01-05 15:37:22 +00:00
// default
2020-06-05 19:15:16 +01:00
# pragma message "script compression option used"
2021-01-05 15:37:22 +00:00
# endif // EEP_SCRIPT_SIZE
2020-06-05 19:15:16 +01:00
2021-01-05 15:37:22 +00:00
# endif // USE_UFILESYS
2020-04-15 07:11:54 +01:00
2021-01-05 15:37:22 +00:00
# include <unishox.h>
2020-05-21 05:06:42 +01:00
# define SCRIPT_COMPRESS compressor.unishox_compress
# define SCRIPT_DECOMPRESS compressor.unishox_decompress
# ifndef UNISHOXRSIZE
# define UNISHOXRSIZE 2560
# endif
2020-12-13 06:32:09 +00:00
2020-05-21 05:06:42 +01:00
2020-10-19 06:24:18 +01:00
# ifndef STASK_PRIO
# define STASK_PRIO 1
# endif
2020-06-15 16:20:50 +01:00
# ifdef USE_SCRIPT_TIMER
# include <Ticker.h>
Ticker Script_ticker1 ;
Ticker Script_ticker2 ;
Ticker Script_ticker3 ;
Ticker Script_ticker4 ;
void Script_ticker1_end ( void ) {
Script_ticker1 . detach ( ) ;
2020-09-11 14:44:16 +01:00
Run_Scripter ( " >ti1 " , 4 , 0 ) ;
2020-06-15 16:20:50 +01:00
}
void Script_ticker2_end ( void ) {
Script_ticker2 . detach ( ) ;
2020-09-11 14:44:16 +01:00
Run_Scripter ( " >ti2 " , 4 , 0 ) ;
2020-06-15 16:20:50 +01:00
}
void Script_ticker3_end ( void ) {
Script_ticker3 . detach ( ) ;
2020-09-11 14:44:16 +01:00
Run_Scripter ( " >ti3 " , 4 , 0 ) ;
2020-06-15 16:20:50 +01:00
}
void Script_ticker4_end ( void ) {
Script_ticker4 . detach ( ) ;
2020-09-11 14:44:16 +01:00
Run_Scripter ( " >ti4 " , 4 , 0 ) ;
2020-06-15 16:20:50 +01:00
}
# endif
2020-12-13 06:32:09 +00:00
// EEPROM MACROS
// i2c eeprom
2021-01-05 15:37:22 +00:00
# define EEP_WRITE(A,B,C) eeprom_writeBytes(A, B, (uint8_t*)C);
# define EEP_READ(A,B,C) eeprom_readBytes(A, B, (uint8_t*)C);
2021-01-10 18:43:03 +00:00
# ifdef ESP8266
# ifdef USE_24C256
# undef EEP_INIT
2021-01-05 15:37:22 +00:00
# define EEP_INIT(A) eeprom_init(A)
2021-01-10 18:43:03 +00:00
# else
# undef EEP_INIT
# define EEP_INIT(A) alt_eeprom_init(A)
# endif
# endif
2020-12-13 06:32:09 +00:00
2021-01-05 15:37:22 +00:00
# if defined(EEP_SCRIPT_SIZE) && !defined(ESP32)
2020-12-13 06:32:09 +00:00
2021-01-10 18:43:03 +00:00
// seems to be the last untouched sector, beside OTA and serial Flash
# define SPEC_SCRIPT_FLASH 0x000F2000
2021-01-05 15:37:22 +00:00
uint32_t eeprom_block ;
2021-01-10 18:43:03 +00:00
2020-12-13 06:32:09 +00:00
// these support only one 4 k block below EEPROM this steals 4k of application area
uint32_t alt_eeprom_init ( uint32_t size ) {
//EEPROM.begin(size);
2021-01-11 16:56:18 +00:00
//eeprom_block = (uint32_t)&_EEPROM_start - 0x40200000 - SPI_FLASH_SEC_SIZE;
2021-01-10 18:43:03 +00:00
eeprom_block = SPEC_SCRIPT_FLASH ;
2020-12-13 06:32:09 +00:00
return 1 ;
}
void alt_eeprom_writeBytes ( uint32_t adr , uint32_t len , uint8_t * buf ) {
uint32_t * lwp = ( uint32_t * ) buf ;
ESP . flashEraseSector ( eeprom_block / SPI_FLASH_SEC_SIZE ) ;
ESP . flashWrite ( eeprom_block , lwp , SPI_FLASH_SEC_SIZE ) ;
}
void alt_eeprom_readBytes ( uint32_t adr , uint32_t len , uint8_t * buf ) {
uint32_t * lwp = ( uint32_t * ) buf ;
ESP . flashRead ( eeprom_block , lwp , SPI_FLASH_SEC_SIZE ) ;
}
2021-01-05 15:37:22 +00:00
# endif // EEP_SCRIPT_SIZE
# include "FS.h"
2021-01-03 07:08:28 +00:00
# if USE_SCRIPT_FATFS==-1
2020-05-30 14:29:47 +01:00
# ifdef ESP32
2021-01-05 15:37:22 +00:00
//#include "FS.h"
//#include "FFat.h"
2020-08-09 09:58:22 +01:00
# else
2021-01-05 15:37:22 +00:00
//#include <LittleFS.h>
# endif
# ifndef UFILESYSTEM
//FS *ufsp;
2020-05-30 14:29:47 +01:00
# endif
2021-01-05 15:37:22 +00:00
2020-06-05 19:15:16 +01:00
# endif // LITTLEFS_SCRIPT_SIZE
2020-04-15 07:11:54 +01:00
2019-08-31 09:10:16 +01:00
// offsets epoch readings by 1.1.2019 00:00:00 to fit into float with second resolution
# define EPOCH_OFFSET 1546300800
2019-05-18 08:45:04 +01:00
enum { OPER_EQU = 1 , OPER_PLS , OPER_MIN , OPER_MUL , OPER_DIV , OPER_PLSEQU , OPER_MINEQU , OPER_MULEQU , OPER_DIVEQU , OPER_EQUEQU , OPER_NOTEQU , OPER_GRTEQU , OPER_LOWEQU , OPER_GRT , OPER_LOW , OPER_PERC , OPER_XOR , OPER_AND , OPER_OR , OPER_ANDEQU , OPER_OREQU , OPER_XOREQU , OPER_PERCEQU } ;
2020-07-16 16:15:12 +01:00
enum { SCRIPT_LOGLEVEL = 1 , SCRIPT_TELEPERIOD , SCRIPT_EVENT_HANDLED } ;
2019-05-18 08:45:04 +01:00
2019-05-30 12:23:54 +01:00
# ifdef USE_SCRIPT_FATFS
2020-05-02 07:10:23 +01:00
2020-05-30 14:29:47 +01:00
# if USE_SCRIPT_FATFS>=0
2021-01-05 15:37:22 +00:00
//#include <SPI.h>
//#include <SD.h>
//#include <FS.h>
2021-01-03 07:08:28 +00:00
2020-05-30 14:29:47 +01:00
# ifdef ESP32
2021-01-05 15:37:22 +00:00
//#include "FFat.h"
# ifndef UFILESYSTEM
//FS *ufsp;
# endif
2020-05-30 14:29:47 +01:00
# else
2021-01-05 15:37:22 +00:00
# ifndef UFILESYSTEM
//SDClass *ufsp;
# endif
2020-05-30 14:29:47 +01:00
# endif
2020-09-11 14:44:16 +01:00
# endif //USE_SCRIPT_FATFS
2020-05-02 07:10:23 +01:00
2021-01-05 15:37:22 +00:00
# ifndef FAT_SCRIPT_SIZE
# define FAT_SCRIPT_SIZE 4096
# endif
2020-05-02 07:10:23 +01:00
# ifndef ESP32
2020-05-30 14:29:47 +01:00
// esp8266
# if USE_SCRIPT_FATFS>=0
// old fs
2021-01-05 15:37:22 +00:00
//#undef FILE_WRITE
//#define FILE_WRITE (sdfat::O_READ | sdfat::O_WRITE | sdfat::O_CREAT)
//#undef FILE_APPEND
//#define FILE_APPEND (sdfat::O_READ | sdfat::O_WRITE | sdfat::O_CREAT | sdfat::O_APPEND)
2020-05-30 14:29:47 +01:00
# else
// new fs
2021-01-05 15:37:22 +00:00
//undef FILE_WRITE
//#define FILE_WRITE "w"
//#undef FILE_READ
//#define FILE_READ "r"
//#undef FILE_APPEND
//#define FILE_APPEND "a"
2020-05-02 07:10:23 +01:00
# endif
2020-05-30 14:29:47 +01:00
# endif // USE_SCRIPT_FATFS>=0
2021-01-05 15:37:22 +00:00
extern uint8_t ufs_type ;
extern FS * ufsp ;
# ifndef UFSYS_SIZE
# define UFSYS_SIZE 8192
2019-09-30 09:25:02 +01:00
# endif
2020-05-30 14:29:47 +01:00
2021-01-05 15:37:22 +00:00
2020-05-02 07:10:23 +01:00
# ifdef ESP32
# undef FAT_SCRIPT_NAME
# define FAT_SCRIPT_NAME " / script.txt"
# else
# undef FAT_SCRIPT_NAME
2021-01-05 15:37:22 +00:00
# define FAT_SCRIPT_NAME " / script.txt"
2019-07-09 09:20:11 +01:00
# endif
2020-05-02 07:10:23 +01:00
2020-09-17 08:11:24 +01:00
//#if USE_STANDARD_SPI_LIBRARY==0
//#warning ("FATFS standard spi should be used");
//#endif
2020-05-30 14:29:47 +01:00
# endif // USE_SCRIPT_FATFS
2019-07-09 09:20:11 +01:00
2019-07-23 06:01:17 +01:00
# ifdef SUPPORT_MQTT_EVENT
# include <LinkedList.h> // Import LinkedList library
typedef struct {
String Event ;
String Topic ;
String Key ;
} MQTT_Subscription ;
LinkedList < MQTT_Subscription > subscriptions ;
# endif //SUPPORT_MQTT_EVENT
2019-08-31 09:10:16 +01:00
# ifdef USE_DISPLAY
2019-07-09 09:20:11 +01:00
# ifdef USE_TOUCH_BUTTONS
# include <renderer.h>
2021-01-20 14:12:41 +00:00
extern VButton * buttons [ MAX_TOUCH_BUTTONS ] ;
2019-05-30 12:23:54 +01:00
# endif
2019-08-31 09:10:16 +01:00
# endif
2019-05-30 12:23:54 +01:00
2019-05-18 08:45:04 +01:00
typedef union {
2020-06-13 12:05:25 +01:00
# ifdef USE_SCRIPT_GLOBVARS
uint16_t data ;
# else
2019-05-18 08:45:04 +01:00
uint8_t data ;
2020-06-13 12:05:25 +01:00
# endif
2019-05-18 08:45:04 +01:00
struct {
uint8_t is_string : 1 ; // string or number
uint8_t is_permanent : 1 ;
uint8_t is_timer : 1 ;
uint8_t is_autoinc : 1 ;
uint8_t changed : 1 ;
uint8_t settable : 1 ;
uint8_t is_filter : 1 ;
uint8_t constant : 1 ;
2020-06-13 12:05:25 +01:00
# ifdef USE_SCRIPT_GLOBVARS
uint8_t global : 1 ;
# endif
2019-05-18 08:45:04 +01:00
} ;
} SCRIPT_TYPE ;
struct T_INDEX {
uint8_t index ;
SCRIPT_TYPE bits ;
} ;
struct M_FILT {
2020-09-03 11:26:03 +01:00
# ifdef LARGE_ARRAYS
uint16_t numvals ;
uint16_t index ;
# else
2019-05-18 08:45:04 +01:00
uint8_t numvals ;
uint8_t index ;
2020-09-03 11:26:03 +01:00
# endif // LARGE_ARRAYS
2019-05-18 08:45:04 +01:00
float maccu ;
float rbuff [ 1 ] ;
} ;
2020-09-03 11:26:03 +01:00
# ifdef LARGE_ARRAYS
# undef AND_FILT_MASK
# undef OR_FILT_MASK
# define AND_FILT_MASK 0x7fff
# define OR_FILT_MASK 0x8000
# undef MAX_ARRAY_SIZE
# define MAX_ARRAY_SIZE 1000
# else
# undef AND_FILT_MASK
# undef OR_FILT_MASK
# define AND_FILT_MASK 0x7f
# define OR_FILT_MASK 0x80
# undef MAX_ARRAY_SIZE
# define MAX_ARRAY_SIZE 127
# endif
2019-06-15 06:02:34 +01:00
typedef union {
uint8_t data ;
struct {
uint8_t nutu8 : 1 ;
uint8_t nutu7 : 1 ;
uint8_t nutu6 : 1 ;
uint8_t nutu5 : 1 ;
uint8_t nutu4 : 1 ;
uint8_t nutu3 : 1 ;
uint8_t is_dir : 1 ;
uint8_t is_open : 1 ;
} ;
} FILE_FLAGS ;
2020-06-13 12:05:25 +01:00
typedef union {
uint8_t data ;
struct {
uint8_t nutu8 : 1 ;
uint8_t nutu7 : 1 ;
uint8_t nutu6 : 1 ;
uint8_t nutu5 : 1 ;
uint8_t nutu4 : 1 ;
uint8_t nutu3 : 1 ;
uint8_t udp_connected : 1 ;
uint8_t udp_used : 1 ;
} ;
} UDP_FLAGS ;
2021-01-05 15:37:22 +00:00
typedef union {
uint8_t data ;
struct {
uint8_t nutu8 : 1 ;
uint8_t nutu7 : 1 ;
uint8_t nutu6 : 1 ;
uint8_t nutu5 : 1 ;
uint8_t nutu4 : 1 ;
uint8_t nutu3 : 1 ;
bool fsys : 1 ;
bool eeprom : 1 ;
} ;
} FS_FLAGS ;
2020-06-13 12:05:25 +01:00
# define NUM_RES 0xfe
# define STR_RES 0xfd
# define VAR_NV 0xff
# define NTYPE 0
# define STYPE 0x80
# ifndef FLT_MAX
# define FLT_MAX 99999999
# endif
2019-05-30 12:23:54 +01:00
# define SFS_MAX 4
2019-05-18 08:45:04 +01:00
// global memory
struct SCRIPT_MEM {
float * fvars ; // number var pointer
float * s_fvars ; // shadow var pointer
struct T_INDEX * type ; // type and index pointer
struct M_FILT * mfilt ;
char * glob_vnp ; // var name pointer
2020-09-17 08:11:24 +01:00
# ifdef SCRIPT_LARGE_VNBUFF
uint16_t * vnp_offset ;
# else
2019-05-18 08:45:04 +01:00
uint8_t * vnp_offset ;
2020-09-17 08:11:24 +01:00
# endif
2019-05-18 08:45:04 +01:00
char * glob_snp ; // string vars pointer
char * scriptptr ;
2019-08-31 09:10:16 +01:00
char * section_ptr ;
2019-08-19 07:20:51 +01:00
char * scriptptr_bu ;
2019-05-30 12:23:54 +01:00
char * script_ram ;
uint16_t script_size ;
uint8_t * script_pram ;
uint16_t script_pram_size ;
2019-05-18 08:45:04 +01:00
uint8_t numvars ;
void * script_mem ;
uint16_t script_mem_size ;
uint8_t script_dprec ;
2020-09-23 11:51:35 +01:00
uint8_t script_lzero ;
2019-05-18 08:45:04 +01:00
uint8_t var_not_found ;
uint8_t glob_error ;
uint8_t max_ssize ;
uint8_t script_loglevel ;
2021-01-05 15:37:22 +00:00
FS_FLAGS FLAGS ;
2020-09-23 11:51:35 +01:00
uint8_t si_num [ 3 ] ;
uint8_t siro_num [ 3 ] ;
uint8_t sind_num ;
char * last_index_string [ 3 ] ;
2020-06-29 06:06:08 +01:00
2019-05-30 12:23:54 +01:00
# ifdef USE_SCRIPT_FATFS
File files [ SFS_MAX ] ;
2019-06-15 06:02:34 +01:00
FILE_FLAGS file_flags [ SFS_MAX ] ;
2019-05-30 12:23:54 +01:00
uint8_t script_sd_found ;
char flink [ 2 ] [ 14 ] ;
2020-09-11 14:44:16 +01:00
# endif //USE_SCRIPT_FATFS
2020-06-13 12:05:25 +01:00
# ifdef USE_SCRIPT_GLOBVARS
UDP_FLAGS udp_flags ;
# endif
2020-10-23 06:45:35 +01:00
char web_mode ;
2019-05-18 08:45:04 +01:00
} glob_script_mem ;
2020-10-23 06:45:35 +01:00
2020-07-16 16:15:12 +01:00
bool event_handeled = false ;
2020-06-29 06:06:08 +01:00
2020-06-13 12:05:25 +01:00
# ifdef USE_SCRIPT_GLOBVARS
IPAddress last_udp_ip ;
2020-06-21 08:13:51 +01:00
WiFiUDP Script_PortUdp ;
2020-06-29 09:48:24 +01:00
2020-09-11 14:44:16 +01:00
# endif //USE_SCRIPT_GLOBVARS
2019-05-22 11:33:51 +01:00
int16_t last_findex ;
2020-06-29 06:06:08 +01:00
int16_t last_sindex ;
2019-05-18 08:45:04 +01:00
uint8_t tasm_cmd_activ = 0 ;
2019-07-16 15:50:52 +01:00
uint8_t fast_script = 0 ;
2020-06-13 12:05:25 +01:00
uint8_t glob_script = 0 ;
2019-05-18 08:45:04 +01:00
uint32_t script_lastmillis ;
2021-01-01 05:43:50 +00:00
void Script_AddLog_P ( uint32_t loglevel , PGM_P formatP , . . . ) {
char log_data [ 128 ] ;
va_list arg ;
va_start ( arg , formatP ) ;
vsnprintf_P ( log_data , sizeof ( log_data ) , formatP , arg ) ;
va_end ( arg ) ;
AddLogData ( loglevel , log_data ) ;
}
2020-09-23 11:51:35 +01:00
void flt2char ( float num , char * nbuff ) {
dtostrfd ( num , glob_script_mem . script_dprec , nbuff ) ;
}
// convert float to char with leading zeros
void f2char ( float num , uint32_t dprec , uint32_t lzeros , char * nbuff ) {
dtostrfd ( num , dprec , nbuff ) ;
if ( lzeros > 1 ) {
// check leading zeros
uint32_t nd = num ;
nd / = 10 ;
nd + = 1 ;
if ( lzeros > nd ) {
// insert zeros
char cpbuf [ 24 ] ;
char * cp = cpbuf ;
for ( uint32_t cnt = 0 ; cnt < lzeros - nd ; cnt + + ) {
* cp + + = ' 0 ' ;
}
* cp = 0 ;
strcat ( cpbuf , nbuff ) ;
strcpy ( nbuff , cpbuf ) ;
}
}
}
2019-08-19 07:20:51 +01:00
2019-10-15 19:07:12 +01:00
# ifdef USE_BUTTON_EVENT
int8_t script_button [ MAX_KEYS ] ;
2020-09-11 14:44:16 +01:00
# endif //USE_BUTTON_EVENT
2019-10-15 19:07:12 +01:00
2020-09-25 07:52:28 +01:00
char * GetNumericArgument ( char * lp , uint8_t lastop , float * fp , JsonParserObject * jo ) ;
char * GetStringArgument ( char * lp , uint8_t lastop , char * cp , JsonParserObject * jo ) ;
2019-05-30 12:23:54 +01:00
char * ForceStringVar ( char * lp , char * dstr ) ;
void send_download ( void ) ;
2021-01-08 14:00:40 +00:00
uint8_t UfsReject ( char * name ) ;
2019-05-18 08:45:04 +01:00
void ScriptEverySecond ( void ) {
if ( bitRead ( Settings . rule_enabled , 0 ) ) {
2020-09-11 14:44:16 +01:00
struct T_INDEX * vtp = glob_script_mem . type ;
float delta = ( millis ( ) - script_lastmillis ) / 1000.0 ;
script_lastmillis = millis ( ) ;
2019-05-18 08:45:04 +01:00
for ( uint8_t count = 0 ; count < glob_script_mem . numvars ; count + + ) {
if ( vtp [ count ] . bits . is_timer ) {
// decrements timers
2020-09-11 14:44:16 +01:00
float * fp = & glob_script_mem . fvars [ vtp [ count ] . index ] ;
2019-05-18 08:45:04 +01:00
if ( * fp > 0 ) {
// decrement
2020-09-11 14:44:16 +01:00
* fp - = delta ;
if ( * fp < 0 ) * fp = 0 ;
2019-05-18 08:45:04 +01:00
}
}
if ( vtp [ count ] . bits . is_autoinc ) {
// increments timers
2020-09-11 14:44:16 +01:00
float * fp = & glob_script_mem . fvars [ vtp [ count ] . index ] ;
2019-05-18 08:45:04 +01:00
if ( * fp > = 0 ) {
2020-09-11 14:44:16 +01:00
* fp + = delta ;
2019-05-18 08:45:04 +01:00
}
}
}
2020-09-11 14:44:16 +01:00
Run_Scripter ( " >S " , 2 , 0 ) ;
2019-05-18 08:45:04 +01:00
}
}
void RulesTeleperiod ( void ) {
2020-10-30 11:29:48 +00:00
if ( bitRead ( Settings . rule_enabled , 0 ) & & TasmotaGlobal . mqtt_data [ 0 ] ) Run_Scripter ( " >T " , 2 , TasmotaGlobal . mqtt_data ) ;
2019-05-18 08:45:04 +01:00
}
2020-12-13 06:32:09 +00:00
2019-09-30 09:25:02 +01:00
2019-05-30 12:23:54 +01:00
2019-05-18 08:45:04 +01:00
# define SCRIPT_SKIP_SPACES while (*lp==' ' || *lp=='\t') lp++;
# define SCRIPT_SKIP_EOL while (*lp==SCRIPT_EOL) lp++;
2020-09-11 14:44:16 +01:00
float * Get_MFAddr ( uint8_t index , uint16_t * len , uint16_t * ipos ) ;
2020-09-03 11:26:03 +01:00
2019-05-30 12:23:54 +01:00
// allocates all variables and presets them
int16_t Init_Scripter ( void ) {
char * script ;
2021-01-01 05:43:50 +00:00
int16_t err = 0 ;
2020-09-11 14:44:16 +01:00
script = glob_script_mem . script_ram ;
2021-01-01 05:43:50 +00:00
if ( ! * script ) return - 999 ;
2019-05-30 12:23:54 +01:00
2019-05-18 08:45:04 +01:00
// scan lines for >DEF
2020-09-11 14:44:16 +01:00
uint16_t lines = 0 ;
uint16_t nvars = 0 ;
uint16_t svars = 0 ;
uint16_t vars = 0 ;
char * lp = script ;
2021-01-01 05:43:50 +00:00
uint16_t imemsize = ( MAXVARS * 10 ) + 4 ;
uint8_t * imemptr = ( uint8_t * ) calloc ( imemsize , 1 ) ;
if ( ! imemptr ) {
return - 7 ;
}
//ClaimSerial();
//SetSerialBaudrate(115200);
//Serial.printf("size %d\n",imemsize);
//Serial.printf("stack %d\n",GetStack()); // 2848
// 2896
//char vnames[MAXVARS*10];
char * vnames = ( char * ) imemptr ;
char * vnp [ MAXVARS ] ;
float fvalues [ MAXVARS ] ;
struct T_INDEX vtypes [ MAXVARS ] ;
/*
uint32_t imemp = ( uint32_t ) imemptr ;
imemp + = ( MAXVARS * 10 ) ;
imemp = ( imemp & 0xfffc ) + 4 ;
Serial . printf ( " >1 %x \n " , imemp ) ;
2019-05-18 08:45:04 +01:00
char * vnp [ MAXVARS ] ;
2021-01-01 05:43:50 +00:00
//char **vnp = (char**)imemp;
imemp + = ( sizeof ( char * ) * MAXVARS ) ;
imemp = ( imemp & 0xfffc ) + 4 ;
Serial . printf ( " >2 %x \n " , imemp ) ;
float fvalues [ MAXVARS ] ;
//float *fvalues = (float*)imemp;
imemp + = ( sizeof ( float * ) * MAXVARS ) ;
imemp = ( imemp & 0xfffc ) + 4 ;
Serial . printf ( " >3 %x \n " , imemp ) ;
struct T_INDEX vtypes [ MAXVARS ] ;
//struct T_INDEX *vtypes = (struct T_INDEX*)imemp;
*/
char * vnames_p = vnames ;
2020-09-11 14:44:16 +01:00
char * * vnp_p = vnp ;
2021-01-01 05:43:50 +00:00
2019-05-18 08:45:04 +01:00
char strings [ MAXSVARS * SCRIPT_MAXSSIZE ] ;
2021-01-01 05:43:50 +00:00
char * snp [ MAXSVARS ] ;
2019-05-18 08:45:04 +01:00
struct M_FILT mfilt [ MAXFILT ] ;
2020-09-11 14:44:16 +01:00
char * strings_p = strings ;
2021-01-01 05:43:50 +00:00
2020-09-11 14:44:16 +01:00
char * * snp_p = snp ;
uint8_t numperm = 0 ;
uint8_t numflt = 0 ;
2020-09-17 08:11:24 +01:00
uint16_t count ;
2019-05-18 08:45:04 +01:00
2020-09-11 14:44:16 +01:00
glob_script_mem . max_ssize = SCRIPT_SVARSIZE ;
glob_script_mem . scriptptr = 0 ;
2019-08-19 07:20:51 +01:00
2020-09-11 14:44:16 +01:00
char init = 0 ;
2019-05-18 08:45:04 +01:00
while ( 1 ) {
// check line
// skip leading spaces
SCRIPT_SKIP_SPACES
// skip empty line
if ( * lp = = ' \n ' | | * lp = = ' \r ' ) goto next_line ;
// skip comment
if ( * lp = = ' ; ' ) goto next_line ;
if ( init ) {
// init section
2020-07-02 05:46:04 +01:00
if ( * lp = = ' > ' | | ! * lp ) {
2020-09-11 14:44:16 +01:00
init = 0 ;
2019-05-18 08:45:04 +01:00
break ;
}
2020-09-11 14:44:16 +01:00
char * op = strchr ( lp , ' = ' ) ;
2019-05-18 08:45:04 +01:00
if ( op ) {
2020-09-11 14:44:16 +01:00
vtypes [ vars ] . bits . data = 0 ;
2019-05-18 08:45:04 +01:00
// found variable definition
if ( * lp = = ' p ' & & * ( lp + 1 ) = = ' : ' ) {
2020-09-11 14:44:16 +01:00
lp + = 2 ;
2019-05-18 08:45:04 +01:00
if ( numperm < SCRIPT_MAXPERM ) {
2020-09-11 14:44:16 +01:00
vtypes [ vars ] . bits . is_permanent = 1 ;
2019-05-18 08:45:04 +01:00
numperm + + ;
}
} else {
2020-09-11 14:44:16 +01:00
vtypes [ vars ] . bits . is_permanent = 0 ;
2019-05-18 08:45:04 +01:00
}
if ( * lp = = ' t ' & & * ( lp + 1 ) = = ' : ' ) {
2020-09-11 14:44:16 +01:00
lp + = 2 ;
vtypes [ vars ] . bits . is_timer = 1 ;
2019-05-18 08:45:04 +01:00
} else {
2020-09-11 14:44:16 +01:00
vtypes [ vars ] . bits . is_timer = 0 ;
2019-05-18 08:45:04 +01:00
}
if ( * lp = = ' i ' & & * ( lp + 1 ) = = ' : ' ) {
2020-09-11 14:44:16 +01:00
lp + = 2 ;
vtypes [ vars ] . bits . is_autoinc = 1 ;
2019-05-18 08:45:04 +01:00
} else {
2020-09-11 14:44:16 +01:00
vtypes [ vars ] . bits . is_autoinc = 0 ;
2019-05-18 08:45:04 +01:00
}
2020-06-13 12:05:25 +01:00
# ifdef USE_SCRIPT_GLOBVARS
if ( * lp = = ' g ' & & * ( lp + 1 ) = = ' : ' ) {
2020-09-11 14:44:16 +01:00
lp + = 2 ;
vtypes [ vars ] . bits . global = 1 ;
2020-06-13 12:05:25 +01:00
glob_script_mem . udp_flags . udp_used = 1 ;
} else {
2020-09-11 14:44:16 +01:00
vtypes [ vars ] . bits . global = 0 ;
2020-06-13 12:05:25 +01:00
}
2020-09-11 14:44:16 +01:00
# endif //USE_SCRIPT_GLOBVARS
2019-05-18 08:45:04 +01:00
if ( ( * lp = = ' m ' | | * lp = = ' M ' ) & & * ( lp + 1 ) = = ' : ' ) {
2020-09-11 14:44:16 +01:00
uint8_t flg = * lp ;
lp + = 2 ;
2020-09-03 11:26:03 +01:00
if ( * lp = = ' p ' & & * ( lp + 1 ) = = ' : ' ) {
2020-09-11 14:44:16 +01:00
vtypes [ vars ] . bits . is_permanent = 1 ;
lp + = 2 ;
2020-09-03 11:26:03 +01:00
}
2020-09-11 14:44:16 +01:00
if ( flg = = ' M ' ) mfilt [ numflt ] . numvals = 8 ;
else mfilt [ numflt ] . numvals = 5 ;
vtypes [ vars ] . bits . is_filter = 1 ;
mfilt [ numflt ] . index = 0 ;
2019-05-18 08:45:04 +01:00
if ( flg = = ' M ' ) {
2020-09-11 14:44:16 +01:00
mfilt [ numflt ] . numvals | = OR_FILT_MASK ;
2019-05-18 08:45:04 +01:00
}
2020-09-11 14:44:16 +01:00
vtypes [ vars ] . index = numflt ;
2019-05-18 08:45:04 +01:00
numflt + + ;
if ( numflt > MAXFILT ) {
2021-01-01 05:43:50 +00:00
if ( imemptr ) free ( imemptr ) ;
2019-05-18 08:45:04 +01:00
return - 6 ;
}
} else {
2020-09-11 14:44:16 +01:00
vtypes [ vars ] . bits . is_filter = 0 ;
2019-05-18 08:45:04 +01:00
}
2020-09-17 08:11:24 +01:00
* vnp_p + + = vnames_p ;
2019-05-18 08:45:04 +01:00
while ( lp < op ) {
2020-09-11 14:44:16 +01:00
* vnames_p + + = * lp + + ;
2019-05-18 08:45:04 +01:00
}
2020-09-11 14:44:16 +01:00
* vnames_p + + = 0 ;
2019-05-18 08:45:04 +01:00
// init variable
op + + ;
if ( * op ! = ' " ' ) {
float fv ;
2019-07-28 16:10:55 +01:00
if ( * op = = ' 0 ' & & * ( op + 1 ) = = ' x ' ) {
2020-09-11 14:44:16 +01:00
op + = 2 ;
fv = strtol ( op , & op , 16 ) ;
2019-07-28 16:10:55 +01:00
} else {
fv = CharToFloat ( op ) ;
}
2020-09-11 14:44:16 +01:00
fvalues [ nvars ] = fv ;
vtypes [ vars ] . bits . is_string = 0 ;
if ( ! vtypes [ vars ] . bits . is_filter ) vtypes [ vars ] . index = nvars ;
2019-05-18 08:45:04 +01:00
nvars + + ;
if ( nvars > MAXNVARS ) {
2021-01-01 05:43:50 +00:00
if ( imemptr ) free ( imemptr ) ;
2019-05-18 08:45:04 +01:00
return - 1 ;
}
2019-05-22 11:33:51 +01:00
if ( vtypes [ vars ] . bits . is_filter ) {
while ( isdigit ( * op ) | | * op = = ' . ' | | * op = = ' - ' ) {
op + + ;
}
while ( * op = = ' ' ) op + + ;
if ( isdigit ( * op ) ) {
// lenght define follows
2020-09-11 14:44:16 +01:00
uint16_t flen = atoi ( op ) ;
2020-09-03 11:26:03 +01:00
if ( flen > MAX_ARRAY_SIZE ) {
// limit array size
2020-09-11 14:44:16 +01:00
flen = MAX_ARRAY_SIZE ;
2020-09-03 11:26:03 +01:00
}
2020-09-11 14:44:16 +01:00
mfilt [ numflt - 1 ] . numvals & = OR_FILT_MASK ;
mfilt [ numflt - 1 ] . numvals | = flen & AND_FILT_MASK ;
2019-05-22 11:33:51 +01:00
}
}
2019-05-18 08:45:04 +01:00
} else {
// string vars
op + + ;
2020-09-11 14:44:16 +01:00
* snp_p + + = strings_p ;
2019-05-18 08:45:04 +01:00
while ( * op ! = ' \" ' ) {
if ( * op = = SCRIPT_EOL ) break ;
2020-09-11 14:44:16 +01:00
* strings_p + + = * op + + ;
2019-05-18 08:45:04 +01:00
}
2020-09-11 14:44:16 +01:00
* strings_p + + = 0 ;
vtypes [ vars ] . bits . is_string = 1 ;
vtypes [ vars ] . index = svars ;
2019-05-18 08:45:04 +01:00
svars + + ;
if ( svars > MAXSVARS ) {
2021-01-01 05:43:50 +00:00
if ( imemptr ) free ( imemptr ) ;
2019-05-18 08:45:04 +01:00
return - 2 ;
}
}
vars + + ;
if ( vars > MAXVARS ) {
2021-01-01 05:43:50 +00:00
if ( imemptr ) free ( imemptr ) ;
2019-05-18 08:45:04 +01:00
return - 3 ;
}
}
} else {
2020-09-11 14:44:16 +01:00
if ( ! strncmp ( lp , " >D " , 2 ) ) {
lp + = 2 ;
2019-05-18 08:45:04 +01:00
SCRIPT_SKIP_SPACES
if ( isdigit ( * lp ) ) {
2020-09-11 14:44:16 +01:00
uint8_t ssize = atoi ( lp ) + 1 ;
2019-05-18 08:45:04 +01:00
if ( ssize < 10 | | ssize > SCRIPT_MAXSSIZE ) ssize = SCRIPT_MAXSSIZE ;
2020-09-11 14:44:16 +01:00
glob_script_mem . max_ssize = ssize ;
2019-05-18 08:45:04 +01:00
}
2020-09-11 14:44:16 +01:00
init = 1 ;
2019-05-18 08:45:04 +01:00
}
}
// next line
next_line :
lp = strchr ( lp , SCRIPT_EOL ) ;
if ( ! lp ) break ;
lp + + ;
}
2020-09-11 14:44:16 +01:00
uint16_t fsize = 0 ;
2019-05-18 08:45:04 +01:00
for ( count = 0 ; count < numflt ; count + + ) {
2020-09-11 14:44:16 +01:00
fsize + = sizeof ( struct M_FILT ) + ( ( mfilt [ count ] . numvals & AND_FILT_MASK ) - 1 ) * sizeof ( float ) ;
2019-05-18 08:45:04 +01:00
}
// now copy vars to memory
2020-09-11 14:44:16 +01:00
uint32_t script_mem_size =
2019-05-18 08:45:04 +01:00
// number and number shadow vars
2020-09-11 14:44:16 +01:00
( sizeof ( float ) * nvars ) +
( sizeof ( float ) * nvars ) +
2019-05-18 08:45:04 +01:00
// var names
2020-09-11 14:44:16 +01:00
( vnames_p - vnames ) +
2019-05-18 08:45:04 +01:00
// vars offsets
2020-09-17 08:11:24 +01:00
# ifdef SCRIPT_LARGE_VNBUFF
( sizeof ( uint16_t ) * vars ) +
# else
2020-09-11 14:44:16 +01:00
( sizeof ( uint8_t ) * vars ) +
2020-09-17 08:11:24 +01:00
# endif
2019-05-18 08:45:04 +01:00
// strings
2020-09-11 14:44:16 +01:00
( glob_script_mem . max_ssize * svars ) +
2019-05-18 08:45:04 +01:00
// type array
2020-09-11 14:44:16 +01:00
( sizeof ( struct T_INDEX ) * vars ) +
2019-05-18 08:45:04 +01:00
fsize ;
2020-09-11 14:44:16 +01:00
script_mem_size + = 16 ;
2019-05-18 08:45:04 +01:00
uint8_t * script_mem ;
2020-09-11 14:44:16 +01:00
script_mem = ( uint8_t * ) calloc ( script_mem_size , 1 ) ;
2019-05-18 08:45:04 +01:00
if ( ! script_mem ) {
2021-01-01 05:43:50 +00:00
if ( imemptr ) free ( imemptr ) ;
2019-05-18 08:45:04 +01:00
return - 4 ;
}
2020-09-11 14:44:16 +01:00
glob_script_mem . script_mem = script_mem ;
glob_script_mem . script_mem_size = script_mem_size ;
2019-05-18 08:45:04 +01:00
// now copy all vars
// numbers
2020-09-11 14:44:16 +01:00
glob_script_mem . fvars = ( float * ) script_mem ;
2020-12-04 07:57:52 +00:00
uint16_t size = sizeof ( float ) * nvars ;
2020-09-11 14:44:16 +01:00
memcpy ( script_mem , fvalues , size ) ;
script_mem + = size ;
glob_script_mem . s_fvars = ( float * ) script_mem ;
size = sizeof ( float ) * nvars ;
memcpy ( script_mem , fvalues , size ) ;
script_mem + = size ;
glob_script_mem . mfilt = ( struct M_FILT * ) script_mem ;
script_mem + = fsize ;
2019-05-18 08:45:04 +01:00
// memory types
2020-09-11 14:44:16 +01:00
glob_script_mem . type = ( struct T_INDEX * ) script_mem ;
size = sizeof ( struct T_INDEX ) * vars ;
memcpy ( script_mem , vtypes , size ) ;
script_mem + = size ;
2019-05-18 08:45:04 +01:00
// var name strings
2020-09-11 14:44:16 +01:00
char * namep = ( char * ) script_mem ;
glob_script_mem . glob_vnp = ( char * ) script_mem ;
size = vnames_p - vnames ;
memcpy ( script_mem , vnames , size ) ;
script_mem + = size ;
2019-05-18 08:45:04 +01:00
2020-09-17 08:11:24 +01:00
# ifdef SCRIPT_LARGE_VNBUFF
2020-10-23 06:45:35 +01:00
uint32_t alignedmem = ( uint32_t ) script_mem ;
if ( alignedmem & 1 ) {
alignedmem + + ;
size = vars * sizeof ( uint16_t ) + 1 ;
} else {
size = vars * sizeof ( uint16_t ) ;
}
glob_script_mem . vnp_offset = ( uint16_t * ) alignedmem ;
2020-09-17 08:11:24 +01:00
# else
2020-09-11 14:44:16 +01:00
glob_script_mem . vnp_offset = ( uint8_t * ) script_mem ;
size = vars * sizeof ( uint8_t ) ;
2020-09-17 08:11:24 +01:00
# endif
2020-09-11 14:44:16 +01:00
script_mem + = size ;
2019-05-18 08:45:04 +01:00
// strings
2020-09-11 14:44:16 +01:00
char * snamep = ( char * ) script_mem ;
glob_script_mem . glob_snp = ( char * ) script_mem ;
size = glob_script_mem . max_ssize * svars ;
2019-05-18 08:45:04 +01:00
//memcpy(script_mem,strings,size);
2020-09-11 14:44:16 +01:00
script_mem + = size ;
2019-05-18 08:45:04 +01:00
// now must recalc memory offsets
2020-09-11 14:44:16 +01:00
uint16_t index = 0 ;
2020-09-17 08:11:24 +01:00
# ifdef SCRIPT_LARGE_VNBUFF
# ifndef MAXVNSIZ
# define MAXVNSIZ 4096
# endif
uint16_t * cp = glob_script_mem . vnp_offset ;
# else
# undef MAXVNSIZ
# define MAXVNSIZ 255
2020-09-11 14:44:16 +01:00
uint8_t * cp = glob_script_mem . vnp_offset ;
2020-09-17 08:11:24 +01:00
# endif
for ( count = 0 ; count < vars ; count + + ) {
2020-09-11 14:44:16 +01:00
* cp + + = index ;
2019-05-18 08:45:04 +01:00
while ( * namep ) {
index + + ;
namep + + ;
}
namep + + ;
index + + ;
2020-09-17 08:11:24 +01:00
if ( index > MAXVNSIZ ) {
2019-09-24 14:30:26 +01:00
free ( glob_script_mem . script_mem ) ;
2021-01-01 05:43:50 +00:00
if ( imemptr ) free ( imemptr ) ;
2019-09-24 14:30:26 +01:00
return - 5 ;
}
2019-05-18 08:45:04 +01:00
}
2021-01-01 05:43:50 +00:00
2019-09-30 09:25:02 +01:00
// variables usage info
2021-01-01 05:43:50 +00:00
Script_AddLog_P ( LOG_LEVEL_INFO , PSTR ( " Script: nv=%d, tv=%d, vns=%d, ram=%d " ) , nvars , svars , index , glob_script_mem . script_mem_size ) ;
2019-05-18 08:45:04 +01:00
// copy string variables
2020-09-11 14:44:16 +01:00
char * cp1 = glob_script_mem . glob_snp ;
char * sp = strings ;
2020-09-17 08:11:24 +01:00
for ( count = 0 ; count < svars ; count + + ) {
2019-05-18 08:45:04 +01:00
strcpy ( cp1 , sp ) ;
2020-09-11 14:44:16 +01:00
sp + = strlen ( sp ) + 1 ;
cp1 + = glob_script_mem . max_ssize ;
2019-05-18 08:45:04 +01:00
}
// setup filter vars
2020-09-11 14:44:16 +01:00
uint8_t * mp = ( uint8_t * ) glob_script_mem . mfilt ;
for ( count = 0 ; count < numflt ; count + + ) {
struct M_FILT * mflp = ( struct M_FILT * ) mp ;
mflp - > numvals = mfilt [ count ] . numvals ;
mp + = sizeof ( struct M_FILT ) + ( ( mfilt [ count ] . numvals & AND_FILT_MASK ) - 1 ) * sizeof ( float ) ;
2019-05-18 08:45:04 +01:00
}
2020-09-11 14:44:16 +01:00
glob_script_mem . numvars = vars ;
glob_script_mem . script_dprec = SCRIPT_FLOAT_PRECISION ;
2020-09-23 11:51:35 +01:00
glob_script_mem . script_lzero = 0 ;
2020-09-11 14:44:16 +01:00
glob_script_mem . script_loglevel = LOG_LEVEL_INFO ;
2019-05-18 08:45:04 +01:00
# if SCRIPT_DEBUG>2
2020-09-11 14:44:16 +01:00
struct T_INDEX * dvtp = glob_script_mem . type ;
for ( uint8_t count = 0 ; count < glob_script_mem . numvars ; count + + ) {
2019-05-18 08:45:04 +01:00
if ( dvtp [ count ] . bits . is_string ) {
} else {
char string [ 32 ] ;
2020-09-23 11:51:35 +01:00
f2char ( glob_script_mem . fvars [ dvtp [ count ] . index ] , glob_script_mem . script_dprec , glob_script_mem . script_lzero , string ) ;
2019-05-18 08:45:04 +01:00
toLog ( string ) ;
}
}
2020-09-11 14:44:16 +01:00
# endif //SCRIPT_DEBUG
2019-05-18 08:45:04 +01:00
// now preset permanent vars
2020-09-11 14:44:16 +01:00
float * fp = ( float * ) glob_script_mem . script_pram ;
struct T_INDEX * vtp = glob_script_mem . type ;
for ( uint8_t count = 0 ; count < glob_script_mem . numvars ; count + + ) {
2019-05-18 08:45:04 +01:00
if ( vtp [ count ] . bits . is_permanent & & ! vtp [ count ] . bits . is_string ) {
2020-09-11 14:44:16 +01:00
uint8_t index = vtp [ count ] . index ;
2020-09-03 11:26:03 +01:00
if ( vtp [ count ] . bits . is_filter ) {
// preset array
2020-09-11 14:44:16 +01:00
uint16_t len = 0 ;
float * fa = Get_MFAddr ( index , & len , 0 ) ;
2020-09-03 11:26:03 +01:00
while ( len - - ) {
2020-09-11 14:44:16 +01:00
* fa + + = * fp + + ;
2020-09-03 11:26:03 +01:00
}
2019-05-18 08:45:04 +01:00
} else {
2020-09-03 11:26:03 +01:00
if ( ! isnan ( * fp ) ) {
2020-09-11 14:44:16 +01:00
glob_script_mem . fvars [ index ] = * fp ;
2020-09-03 11:26:03 +01:00
} else {
2020-09-11 14:44:16 +01:00
* fp = glob_script_mem . fvars [ index ] ;
2020-09-03 11:26:03 +01:00
}
fp + + ;
2019-05-18 08:45:04 +01:00
}
}
}
2020-09-11 14:44:16 +01:00
sp = ( char * ) fp ;
for ( uint8_t count = 0 ; count < glob_script_mem . numvars ; count + + ) {
2019-05-18 08:45:04 +01:00
if ( vtp [ count ] . bits . is_permanent & & vtp [ count ] . bits . is_string ) {
2020-09-11 14:44:16 +01:00
uint8_t index = vtp [ count ] . index ;
char * dp = glob_script_mem . glob_snp + ( index * glob_script_mem . max_ssize ) ;
uint8_t slen = strlen ( sp ) ;
strlcpy ( dp , sp , glob_script_mem . max_ssize ) ;
sp + = slen + 1 ;
2019-05-18 08:45:04 +01:00
}
}
# if SCRIPT_DEBUG>0
ClaimSerial ( ) ;
SetSerialBaudrate ( 9600 ) ;
2020-09-11 14:44:16 +01:00
# endif //SCRIPT_DEBUG
2019-05-18 08:45:04 +01:00
// store start of actual program here
2020-09-11 14:44:16 +01:00
glob_script_mem . scriptptr = lp - 1 ;
glob_script_mem . scriptptr_bu = glob_script_mem . scriptptr ;
2020-06-13 12:05:25 +01:00
# ifdef USE_SCRIPT_GLOBVARS
if ( glob_script_mem . udp_flags . udp_used ) {
Script_Init_UDP ( ) ;
2020-09-11 14:44:16 +01:00
glob_script = Run_Scripter ( " >G " , - 2 , 0 ) ;
2020-06-13 12:05:25 +01:00
}
2020-09-11 14:44:16 +01:00
# endif //USE_SCRIPT_GLOBVARS
2020-06-13 12:05:25 +01:00
2021-01-01 05:43:50 +00:00
if ( imemptr ) {
free ( imemptr ) ;
}
return err ;
2019-05-18 08:45:04 +01:00
}
2020-09-17 08:11:24 +01:00
2020-06-13 12:05:25 +01:00
# ifdef USE_SCRIPT_GLOBVARS
# define SCRIPT_UDP_BUFFER_SIZE 128
# define SCRIPT_UDP_PORT 1999
IPAddress script_udp_remote_ip ;
2020-10-19 06:24:18 +01:00
void Restart_globvars ( void ) {
Script_Stop_UDP ( ) ;
Script_Init_UDP ( ) ;
}
2020-06-21 08:13:51 +01:00
void Script_Stop_UDP ( void ) {
2020-09-17 08:11:24 +01:00
if ( ! glob_script_mem . udp_flags . udp_used ) return ;
if ( glob_script_mem . udp_flags . udp_connected ) {
Script_PortUdp . flush ( ) ;
Script_PortUdp . stop ( ) ;
glob_script_mem . udp_flags . udp_connected = 0 ;
}
2020-06-21 08:13:51 +01:00
}
2020-06-13 12:05:25 +01:00
void Script_Init_UDP ( ) {
2020-10-30 11:29:48 +00:00
if ( TasmotaGlobal . global_state . network_down ) return ;
2020-09-17 08:11:24 +01:00
if ( ! glob_script_mem . udp_flags . udp_used ) return ;
2020-06-13 12:05:25 +01:00
if ( glob_script_mem . udp_flags . udp_connected ) return ;
2020-06-21 08:13:51 +01:00
if ( Script_PortUdp . beginMulticast ( WiFi . localIP ( ) , IPAddress ( 239 , 255 , 255 , 250 ) , SCRIPT_UDP_PORT ) ) {
2021-01-01 05:43:50 +00:00
Script_AddLog_P ( LOG_LEVEL_DEBUG , PSTR ( D_LOG_UPNP " SCRIPT UDP started " ) ) ;
2020-06-13 12:05:25 +01:00
glob_script_mem . udp_flags . udp_connected = 1 ;
} else {
2021-01-01 05:43:50 +00:00
Script_AddLog_P ( LOG_LEVEL_DEBUG , PSTR ( D_LOG_UPNP " SCRIPT UDP failed " ) ) ;
2020-06-13 12:05:25 +01:00
glob_script_mem . udp_flags . udp_connected = 0 ;
}
}
2020-09-17 08:11:24 +01:00
2020-06-13 12:05:25 +01:00
void Script_PollUdp ( void ) {
2020-10-30 11:29:48 +00:00
if ( TasmotaGlobal . global_state . network_down ) return ;
2020-06-13 12:05:25 +01:00
if ( ! glob_script_mem . udp_flags . udp_used ) return ;
if ( glob_script_mem . udp_flags . udp_connected ) {
2020-06-21 08:13:51 +01:00
while ( Script_PortUdp . parsePacket ( ) ) {
2020-06-13 12:05:25 +01:00
char packet_buffer [ SCRIPT_UDP_BUFFER_SIZE ] ;
2020-09-11 14:44:16 +01:00
int32_t len = Script_PortUdp . read ( packet_buffer , SCRIPT_UDP_BUFFER_SIZE - 1 ) ;
2020-06-13 12:05:25 +01:00
packet_buffer [ len ] = 0 ;
2020-06-21 08:13:51 +01:00
script_udp_remote_ip = Script_PortUdp . remoteIP ( ) ;
2021-01-01 05:43:50 +00:00
Script_AddLog_P ( LOG_LEVEL_DEBUG , PSTR ( " UDP: Packet %s - %d - %s " ) , packet_buffer , len , script_udp_remote_ip . toString ( ) . c_str ( ) ) ;
2020-06-13 12:05:25 +01:00
char * lp = packet_buffer ;
2020-09-11 14:44:16 +01:00
if ( ! strncmp ( lp , " => " , 2 ) ) {
lp + = 2 ;
char * cp = strchr ( lp , ' = ' ) ;
2020-06-13 12:05:25 +01:00
if ( cp ) {
char vnam [ 32 ] ;
2020-09-11 14:44:16 +01:00
for ( uint32_t count = 0 ; count < len ; count + + ) {
2020-06-13 12:05:25 +01:00
if ( lp [ count ] = = ' = ' ) {
2020-09-11 14:44:16 +01:00
vnam [ count ] = 0 ;
2020-06-13 12:05:25 +01:00
break ;
}
2020-09-11 14:44:16 +01:00
vnam [ count ] = lp [ count ] ;
2020-06-13 12:05:25 +01:00
}
float * fp ;
char * sp ;
uint32_t index ;
2020-09-11 14:44:16 +01:00
uint32_t res = match_vars ( vnam , & fp , & sp , & index ) ;
if ( res = = NUM_RES ) {
2021-01-01 05:43:50 +00:00
Script_AddLog_P ( LOG_LEVEL_DEBUG , PSTR ( " num var found - %s - %d - %d " ) , vnam , res , index ) ;
2020-09-11 14:44:16 +01:00
* fp = CharToFloat ( cp + 1 ) ;
} else if ( res = = STR_RES ) {
2021-01-01 05:43:50 +00:00
Script_AddLog_P ( LOG_LEVEL_DEBUG , PSTR ( " string var found - %s - %d - %d " ) , vnam , res , index ) ;
2020-09-11 14:44:16 +01:00
strlcpy ( sp , cp + 1 , SCRIPT_MAXSSIZE ) ;
2020-06-13 12:05:25 +01:00
} else {
// error var not found
}
if ( res ) {
// mark changed
2020-09-11 14:44:16 +01:00
last_udp_ip = Script_PortUdp . remoteIP ( ) ;
glob_script_mem . type [ index ] . bits . changed = 1 ;
2020-06-13 12:05:25 +01:00
if ( glob_script = = 99 ) {
2020-09-11 14:44:16 +01:00
Run_Scripter ( " >G " , 2 , 0 ) ;
2020-06-13 12:05:25 +01:00
}
}
}
}
optimistic_yield ( 100 ) ;
}
} else {
Script_Init_UDP ( ) ;
}
}
void script_udp_sendvar ( char * vname , float * fp , char * sp ) {
if ( ! glob_script_mem . udp_flags . udp_used ) return ;
if ( ! glob_script_mem . udp_flags . udp_connected ) return ;
2020-09-11 14:44:16 +01:00
char sbuf [ SCRIPT_MAXSSIZE + 4 ] ;
strcpy ( sbuf , " => " ) ;
strcat ( sbuf , vname ) ;
strcat ( sbuf , " = " ) ;
2020-06-13 12:05:25 +01:00
if ( fp ) {
char flstr [ 16 ] ;
2020-09-11 14:44:16 +01:00
dtostrfd ( * fp , 8 , flstr ) ;
strcat ( sbuf , flstr ) ;
2021-01-01 05:43:50 +00:00
Script_AddLog_P ( LOG_LEVEL_DEBUG , PSTR ( " num var updated - %s " ) , sbuf ) ;
2020-06-13 12:05:25 +01:00
} else {
2020-09-11 14:44:16 +01:00
strcat ( sbuf , sp ) ;
2021-01-01 05:43:50 +00:00
Script_AddLog_P ( LOG_LEVEL_DEBUG , PSTR ( " string var updated - %s " ) , sbuf ) ;
2020-06-13 12:05:25 +01:00
}
2020-09-11 14:44:16 +01:00
Script_PortUdp . beginPacket ( IPAddress ( 239 , 255 , 255 , 250 ) , SCRIPT_UDP_PORT ) ;
2020-06-13 12:05:25 +01:00
// Udp.print(String("RET UC: ") + String(recv_Packet));
2020-09-11 14:44:16 +01:00
Script_PortUdp . write ( ( const uint8_t * ) sbuf , strlen ( sbuf ) ) ;
2020-06-21 08:13:51 +01:00
Script_PortUdp . endPacket ( ) ;
2020-06-13 12:05:25 +01:00
}
2020-09-11 14:44:16 +01:00
# endif //USE_SCRIPT_GLOBVARS
2020-06-13 12:05:25 +01:00
2019-07-28 16:10:55 +01:00
# ifdef USE_LIGHT
# ifdef USE_WS2812
2020-05-15 14:30:32 +01:00
void ws2812_set_array ( float * array , uint32_t len , uint32_t offset ) {
2019-07-28 16:10:55 +01:00
Ws2812ForceSuspend ( ) ;
2020-09-11 14:44:16 +01:00
for ( uint32_t cnt = 0 ; cnt < len ; cnt + + ) {
uint32_t index = cnt + offset ;
2020-05-15 14:30:32 +01:00
if ( index > Settings . light_pixels ) break ;
2020-09-11 14:44:16 +01:00
uint32_t col = array [ cnt ] ;
Ws2812SetColor ( index + 1 , col > > 16 , col > > 8 , col , 0 ) ;
2019-07-28 16:10:55 +01:00
}
Ws2812ForceUpdate ( ) ;
}
2020-09-11 14:44:16 +01:00
# endif //USE_WS2812
# endif //USE_LIGHT
2019-07-28 16:10:55 +01:00
2019-05-18 08:45:04 +01:00
2019-05-22 11:33:51 +01:00
2020-09-11 14:44:16 +01:00
float median_array ( float * array , uint16_t len ) {
2019-05-22 11:33:51 +01:00
uint8_t ind [ len ] ;
2020-09-11 14:44:16 +01:00
uint8_t mind = 0 ;
uint8_t index = 0 ;
uint8_t flg ;
float min = FLT_MAX ;
for ( uint8_t hcnt = 0 ; hcnt < len / 2 + 1 ; hcnt + + ) {
for ( uint8_t mcnt = 0 ; mcnt < len ; mcnt + + ) {
flg = 0 ;
for ( uint8_t icnt = 0 ; icnt < index ; icnt + + ) {
if ( ind [ icnt ] = = mcnt ) {
flg = 1 ;
2019-05-22 11:33:51 +01:00
}
}
if ( ! flg ) {
if ( array [ mcnt ] < min ) {
2020-09-11 14:44:16 +01:00
min = array [ mcnt ] ;
mind = mcnt ;
2019-05-22 11:33:51 +01:00
}
}
}
2020-09-11 14:44:16 +01:00
ind [ index ] = mind ;
2019-05-22 11:33:51 +01:00
index + + ;
2020-09-11 14:44:16 +01:00
min = FLT_MAX ;
2019-05-22 11:33:51 +01:00
}
2020-09-11 14:44:16 +01:00
return array [ ind [ len / 2 ] ] ;
2019-05-22 11:33:51 +01:00
}
2019-07-28 16:10:55 +01:00
2020-09-11 14:44:16 +01:00
float * Get_MFAddr ( uint8_t index , uint16_t * len , uint16_t * ipos ) {
* len = 0 ;
uint8_t * mp = ( uint8_t * ) glob_script_mem . mfilt ;
for ( uint8_t count = 0 ; count < MAXFILT ; count + + ) {
struct M_FILT * mflp = ( struct M_FILT * ) mp ;
2019-07-28 16:10:55 +01:00
if ( count = = index ) {
2020-09-11 14:44:16 +01:00
* len = mflp - > numvals & AND_FILT_MASK ;
if ( ipos ) * ipos = mflp - > index ;
2019-07-28 16:10:55 +01:00
return mflp - > rbuff ;
}
2020-09-11 14:44:16 +01:00
mp + = sizeof ( struct M_FILT ) + ( ( mflp - > numvals & AND_FILT_MASK ) - 1 ) * sizeof ( float ) ;
2019-07-28 16:10:55 +01:00
}
return 0 ;
}
2020-09-25 07:52:28 +01:00
char * isvar ( char * lp , uint8_t * vtype , struct T_INDEX * tind , float * fp , char * sp , JsonParserObject * jo ) ;
2020-09-23 11:51:35 +01:00
float * get_array_by_name ( char * name , uint16_t * alen ) {
struct T_INDEX ind ;
uint8_t vtype ;
isvar ( name , & vtype , & ind , 0 , 0 , 0 ) ;
if ( vtype = = VAR_NV ) return 0 ;
if ( vtype & STYPE ) return 0 ;
uint16_t index = glob_script_mem . type [ ind . index ] . index ;
if ( glob_script_mem . type [ ind . index ] . bits . is_filter ) {
float * fa = Get_MFAddr ( index , alen , 0 ) ;
return fa ;
}
return 0 ;
}
2019-07-28 16:10:55 +01:00
2020-09-11 14:44:16 +01:00
float Get_MFVal ( uint8_t index , int16_t bind ) {
uint8_t * mp = ( uint8_t * ) glob_script_mem . mfilt ;
for ( uint8_t count = 0 ; count < MAXFILT ; count + + ) {
struct M_FILT * mflp = ( struct M_FILT * ) mp ;
2019-05-22 11:33:51 +01:00
if ( count = = index ) {
2020-09-11 14:44:16 +01:00
uint16_t maxind = mflp - > numvals & AND_FILT_MASK ;
2019-05-22 11:33:51 +01:00
if ( ! bind ) {
return mflp - > index ;
}
2020-09-03 11:26:03 +01:00
if ( bind < 0 ) {
return maxind ;
}
2020-12-26 08:45:59 +00:00
if ( bind < 1 | | bind > maxind ) bind = 1 ;
2020-09-11 14:44:16 +01:00
return mflp - > rbuff [ bind - 1 ] ;
2019-05-22 11:33:51 +01:00
}
2020-09-11 14:44:16 +01:00
mp + = sizeof ( struct M_FILT ) + ( ( mflp - > numvals & AND_FILT_MASK ) - 1 ) * sizeof ( float ) ;
2019-05-22 11:33:51 +01:00
}
return 0 ;
}
2020-09-11 14:44:16 +01:00
void Set_MFVal ( uint8_t index , uint16_t bind , float val ) {
uint8_t * mp = ( uint8_t * ) glob_script_mem . mfilt ;
for ( uint8_t count = 0 ; count < MAXFILT ; count + + ) {
struct M_FILT * mflp = ( struct M_FILT * ) mp ;
2019-05-22 11:33:51 +01:00
if ( count = = index ) {
2020-09-11 14:44:16 +01:00
uint16_t maxind = mflp - > numvals & AND_FILT_MASK ;
2019-05-30 12:23:54 +01:00
if ( ! bind ) {
2020-12-26 08:45:59 +00:00
if ( val < 0 | | val > = maxind ) val = 0 ;
2020-09-11 14:44:16 +01:00
mflp - > index = val ;
2019-05-30 12:23:54 +01:00
} else {
2021-01-01 05:43:50 +00:00
if ( bind > = 1 & & bind < = maxind ) {
2020-12-26 08:45:59 +00:00
mflp - > rbuff [ bind - 1 ] = val ;
}
2019-05-30 12:23:54 +01:00
}
return ;
2019-05-22 11:33:51 +01:00
}
2020-09-11 14:44:16 +01:00
mp + = sizeof ( struct M_FILT ) + ( ( mflp - > numvals & AND_FILT_MASK ) - 1 ) * sizeof ( float ) ;
2019-05-22 11:33:51 +01:00
}
}
2019-05-18 08:45:04 +01:00
float Get_MFilter ( uint8_t index ) {
2020-09-11 14:44:16 +01:00
uint8_t * mp = ( uint8_t * ) glob_script_mem . mfilt ;
for ( uint8_t count = 0 ; count < MAXFILT ; count + + ) {
struct M_FILT * mflp = ( struct M_FILT * ) mp ;
2019-05-18 08:45:04 +01:00
if ( count = = index ) {
2020-09-11 14:44:16 +01:00
if ( mflp - > numvals & OR_FILT_MASK ) {
2019-05-18 08:45:04 +01:00
// moving average
2020-09-11 14:44:16 +01:00
return mflp - > maccu / ( mflp - > numvals & AND_FILT_MASK ) ;
2019-05-18 08:45:04 +01:00
} else {
2019-05-22 11:33:51 +01:00
// median, sort array indices
2020-09-11 14:44:16 +01:00
return median_array ( mflp - > rbuff , mflp - > numvals ) ;
2019-05-18 08:45:04 +01:00
}
}
2020-09-11 14:44:16 +01:00
mp + = sizeof ( struct M_FILT ) + ( ( mflp - > numvals & AND_FILT_MASK ) - 1 ) * sizeof ( float ) ;
2019-05-18 08:45:04 +01:00
}
return 0 ;
}
void Set_MFilter ( uint8_t index , float invar ) {
2020-09-11 14:44:16 +01:00
uint8_t * mp = ( uint8_t * ) glob_script_mem . mfilt ;
for ( uint8_t count = 0 ; count < MAXFILT ; count + + ) {
struct M_FILT * mflp = ( struct M_FILT * ) mp ;
2019-05-18 08:45:04 +01:00
if ( count = = index ) {
2020-09-11 14:44:16 +01:00
if ( mflp - > numvals & OR_FILT_MASK ) {
2019-05-18 08:45:04 +01:00
// moving average
2020-09-11 14:44:16 +01:00
mflp - > maccu - = mflp - > rbuff [ mflp - > index ] ;
mflp - > maccu + = invar ;
mflp - > rbuff [ mflp - > index ] = invar ;
2019-05-18 08:45:04 +01:00
mflp - > index + + ;
2020-09-11 14:44:16 +01:00
if ( mflp - > index > = ( mflp - > numvals & AND_FILT_MASK ) ) mflp - > index = 0 ;
2019-05-18 08:45:04 +01:00
} else {
// median
2020-09-11 14:44:16 +01:00
mflp - > rbuff [ mflp - > index ] = invar ;
2019-05-18 08:45:04 +01:00
mflp - > index + + ;
2020-09-11 14:44:16 +01:00
if ( mflp - > index > = mflp - > numvals ) mflp - > index = 0 ;
2019-05-18 08:45:04 +01:00
}
break ;
}
2020-09-11 14:44:16 +01:00
mp + = sizeof ( struct M_FILT ) + ( ( mflp - > numvals & AND_FILT_MASK ) - 1 ) * sizeof ( float ) ;
2019-05-18 08:45:04 +01:00
}
}
# define MEDIAN_SIZE 5
# define MEDIAN_FILTER_NUM 2
struct MEDIAN_FILTER {
float buffer [ MEDIAN_SIZE ] ;
int8_t index ;
} script_mf [ MEDIAN_FILTER_NUM ] ;
float DoMedian5 ( uint8_t index , float in ) {
2020-09-11 14:44:16 +01:00
if ( index > = MEDIAN_FILTER_NUM ) index = 0 ;
2019-05-18 08:45:04 +01:00
2020-09-11 14:44:16 +01:00
struct MEDIAN_FILTER * mf = & script_mf [ index ] ;
mf - > buffer [ mf - > index ] = in ;
2019-05-18 08:45:04 +01:00
mf - > index + + ;
2020-09-11 14:44:16 +01:00
if ( mf - > index > = MEDIAN_SIZE ) mf - > index = 0 ;
return median_array ( mf - > buffer , MEDIAN_SIZE ) ;
2019-05-18 08:45:04 +01:00
}
2019-08-16 06:37:16 +01:00
# ifdef USE_LIGHT
uint32_t HSVToRGB ( uint16_t hue , uint8_t saturation , uint8_t value ) {
float r = 0 , g = 0 , b = 0 ;
struct HSV {
float H ;
float S ;
float V ;
} hsv ;
2020-09-11 14:44:16 +01:00
hsv . H = hue ;
hsv . S = ( float ) saturation / 100.0 ;
hsv . V = ( float ) value / 100.0 ;
2019-08-16 06:37:16 +01:00
if ( hsv . S = = 0 ) {
r = hsv . V ;
g = hsv . V ;
b = hsv . V ;
} else {
int i ;
float f , p , q , t ;
if ( hsv . H = = 360 )
hsv . H = 0 ;
else
hsv . H = hsv . H / 60 ;
i = ( int ) trunc ( hsv . H ) ;
f = hsv . H - i ;
p = hsv . V * ( 1.0 - hsv . S ) ;
q = hsv . V * ( 1.0 - ( hsv . S * f ) ) ;
t = hsv . V * ( 1.0 - ( hsv . S * ( 1.0 - f ) ) ) ;
switch ( i )
{
case 0 :
r = hsv . V ;
g = t ;
b = p ;
break ;
case 1 :
r = q ;
g = hsv . V ;
b = p ;
break ;
case 2 :
r = p ;
g = hsv . V ;
b = t ;
break ;
case 3 :
r = p ;
g = q ;
b = hsv . V ;
break ;
case 4 :
r = t ;
g = p ;
b = hsv . V ;
break ;
default :
r = hsv . V ;
g = p ;
b = q ;
break ;
}
}
2020-09-11 14:44:16 +01:00
uint8_t ir , ig , ib ;
ir = r * 255 ;
ig = g * 255 ;
ib = b * 255 ;
2019-08-16 06:37:16 +01:00
2020-09-11 14:44:16 +01:00
uint32_t rgb = ( ir < < 16 ) | ( ig < < 8 ) | ib ;
2019-08-16 06:37:16 +01:00
return rgb ;
}
2020-09-11 14:44:16 +01:00
# endif //USE_LIGHT
2019-05-18 08:45:04 +01:00
2020-06-05 19:15:16 +01:00
# ifdef USE_ANGLE_FUNC
uint32_t pulse_time_hl ;
uint32_t pulse_time_lh ;
uint32_t pulse_ltime_hl ;
uint32_t pulse_ltime_lh ;
uint8_t pt_pin ;
# define MPT_DEBOUNCE 10
2020-07-17 10:49:56 +01:00
void ICACHE_RAM_ATTR MP_Timer ( void ) {
2020-06-05 19:15:16 +01:00
uint32_t level = digitalRead ( pt_pin & 0x3f ) ;
uint32_t ms = millis ( ) ;
uint32_t time ;
if ( level ) {
// rising edge
pulse_ltime_lh = ms ;
time = ms - pulse_ltime_hl ;
if ( time > MPT_DEBOUNCE ) pulse_time_hl = time ;
} else {
// falling edge
pulse_ltime_hl = ms ;
time = ms - pulse_ltime_lh ;
if ( time > MPT_DEBOUNCE ) pulse_time_lh = time ;
}
}
uint32_t MeasurePulseTime ( int32_t in ) {
if ( in > = 0 ) {
// define pin;
pt_pin = in ;
2020-09-11 14:44:16 +01:00
pinMode ( pt_pin & 0x3f , INPUT_PULLUP ) ;
attachInterrupt ( pt_pin & 0x3f , MP_Timer , CHANGE ) ;
2020-06-05 19:15:16 +01:00
pulse_ltime_lh = millis ( ) ;
pulse_ltime_hl = millis ( ) ;
return 0 ;
}
uint32_t ptime ;
if ( in = = - 1 ) {
ptime = pulse_time_lh ;
pulse_time_lh = 0 ;
} else {
ptime = pulse_time_hl ;
pulse_time_hl = 0 ;
}
return ptime ;
}
# endif // USE_ANGLE_FUNC
2020-06-13 12:05:25 +01:00
# ifdef USE_SCRIPT_GLOBVARS
uint32_t match_vars ( char * dvnam , float * * fp , char * * sp , uint32_t * ind ) {
2020-09-11 14:44:16 +01:00
uint16_t olen = strlen ( dvnam ) ;
struct T_INDEX * vtp = glob_script_mem . type ;
for ( uint32_t count = 0 ; count < glob_script_mem . numvars ; count + + ) {
char * cp = glob_script_mem . glob_vnp + glob_script_mem . vnp_offset [ count ] ;
uint8_t slen = strlen ( cp ) ;
2020-06-13 12:05:25 +01:00
if ( slen = = olen & & * cp = = dvnam [ 0 ] ) {
2020-09-11 14:44:16 +01:00
if ( ! strncmp ( cp , dvnam , olen ) ) {
uint8_t index = vtp [ count ] . index ;
2020-06-13 12:05:25 +01:00
if ( vtp [ count ] . bits . is_string = = 0 ) {
if ( vtp [ count ] . bits . is_filter ) {
// error
return 0 ;
} else {
2020-09-11 14:44:16 +01:00
* fp = & glob_script_mem . fvars [ index ] ;
* ind = count ;
2020-06-13 12:05:25 +01:00
return NUM_RES ;
}
} else {
2020-09-11 14:44:16 +01:00
* sp = glob_script_mem . glob_snp + ( index * glob_script_mem . max_ssize ) ;
* ind = count ;
2020-06-13 12:05:25 +01:00
return STR_RES ;
}
}
}
}
return 0 ;
}
2020-09-11 14:44:16 +01:00
# endif //USE_SCRIPT_GLOBVARS
2020-06-13 12:05:25 +01:00
2020-09-23 11:51:35 +01:00
char * isargs ( char * lp , uint32_t isind ) {
float fvar ;
lp = GetNumericArgument ( lp , OPER_EQU , & fvar , 0 ) ;
SCRIPT_SKIP_SPACES
if ( * lp ! = ' " ' ) {
return lp ;
}
lp + + ;
if ( glob_script_mem . si_num [ isind ] > 0 & & glob_script_mem . last_index_string [ isind ] ) {
free ( glob_script_mem . last_index_string [ isind ] ) ;
}
char * sstart = lp ;
uint8_t slen = 0 ;
for ( uint32_t cnt = 0 ; cnt < 256 ; cnt + + ) {
if ( * lp = = ' \n ' | | * lp = = ' " ' | | * lp = = 0 ) {
lp + + ;
if ( cnt > 0 & & ! slen ) {
slen + + ;
}
glob_script_mem . siro_num [ isind ] = slen ;
break ;
}
if ( * lp = = ' | ' ) {
slen + + ;
}
lp + + ;
}
glob_script_mem . si_num [ isind ] = fvar ;
if ( glob_script_mem . si_num [ isind ] > 0 ) {
if ( glob_script_mem . si_num [ isind ] > MAX_SARRAY_NUM ) {
glob_script_mem . si_num [ isind ] = MAX_SARRAY_NUM ;
}
glob_script_mem . last_index_string [ isind ] = ( char * ) calloc ( glob_script_mem . max_ssize * glob_script_mem . si_num [ isind ] , 1 ) ;
for ( uint32_t cnt = 0 ; cnt < glob_script_mem . siro_num [ isind ] ; cnt + + ) {
char str [ SCRIPT_MAXSSIZE ] ;
GetTextIndexed ( str , sizeof ( str ) , cnt , sstart ) ;
strlcpy ( glob_script_mem . last_index_string [ isind ] + ( cnt * glob_script_mem . max_ssize ) , str , glob_script_mem . max_ssize ) ;
}
} else {
glob_script_mem . last_index_string [ isind ] = sstart ;
}
lp + + ;
return lp ;
}
char * isget ( char * lp , char * sp , uint32_t isind ) {
float fvar ;
lp = GetNumericArgument ( lp , OPER_EQU , & fvar , 0 ) ;
SCRIPT_SKIP_SPACES
char str [ SCRIPT_MAXSSIZE ] ;
str [ 0 ] = 0 ;
uint8_t index = fvar ;
if ( index < 1 ) index = 1 ;
index - - ;
last_sindex = index ;
glob_script_mem . sind_num = isind ;
if ( glob_script_mem . last_index_string [ isind ] ) {
if ( ! glob_script_mem . si_num [ isind ] ) {
if ( index < = glob_script_mem . siro_num [ isind ] ) {
GetTextIndexed ( str , sizeof ( str ) , index , glob_script_mem . last_index_string [ isind ] ) ;
}
} else {
if ( index > glob_script_mem . si_num [ isind ] ) {
index = glob_script_mem . si_num [ isind ] ;
}
strlcpy ( str , glob_script_mem . last_index_string [ isind ] + ( index * glob_script_mem . max_ssize ) , glob_script_mem . max_ssize ) ;
}
}
lp + + ;
if ( sp ) strlcpy ( sp , str , glob_script_mem . max_ssize ) ;
return lp ;
}
2020-07-15 08:44:52 +01:00
2019-05-18 08:45:04 +01:00
// vtype => ff=nothing found, fe=constant number,fd = constant string else bit 7 => 80 = string, 0 = number
// no flash strings here for performance reasons!!!
2020-09-25 07:52:28 +01:00
char * isvar ( char * lp , uint8_t * vtype , struct T_INDEX * tind , float * fp , char * sp , JsonParserObject * jo ) {
2020-09-11 14:44:16 +01:00
uint16_t count , len = 0 ;
uint8_t nres = 0 ;
2020-12-20 11:07:21 +00:00
char vname [ 64 ] ;
2020-09-11 14:44:16 +01:00
float fvar = 0 ;
tind - > index = 0 ;
tind - > bits . data = 0 ;
2019-05-18 08:45:04 +01:00
if ( isdigit ( * lp ) | | ( * lp = = ' - ' & & isdigit ( * ( lp + 1 ) ) ) | | * lp = = ' . ' ) {
// isnumber
2019-07-28 16:10:55 +01:00
if ( fp ) {
if ( * lp = = ' 0 ' & & * ( lp + 1 ) = = ' x ' ) {
2020-09-11 14:44:16 +01:00
lp + = 2 ;
* fp = strtol ( lp , 0 , 16 ) ;
2019-07-28 16:10:55 +01:00
} else {
2020-09-11 14:44:16 +01:00
* fp = CharToFloat ( lp ) ;
2019-07-28 16:10:55 +01:00
}
}
2019-05-18 08:45:04 +01:00
if ( * lp = = ' - ' ) lp + + ;
while ( isdigit ( * lp ) | | * lp = = ' . ' ) {
if ( * lp = = 0 | | * lp = = SCRIPT_EOL ) break ;
lp + + ;
}
2020-09-11 14:44:16 +01:00
tind - > bits . constant = 1 ;
tind - > bits . is_string = 0 ;
* vtype = NUM_RES ;
2019-05-18 08:45:04 +01:00
return lp ;
}
if ( * lp = = ' " ' ) {
lp + + ;
while ( * lp ! = ' " ' ) {
if ( * lp = = 0 | | * lp = = SCRIPT_EOL ) break ;
2020-09-11 14:44:16 +01:00
uint8_t iob = * lp ;
2019-05-30 12:23:54 +01:00
if ( iob = = ' \\ ' ) {
lp + + ;
if ( * lp = = ' t ' ) {
2020-09-11 14:44:16 +01:00
iob = ' \t ' ;
2019-05-30 12:23:54 +01:00
} else if ( * lp = = ' n ' ) {
2020-09-11 14:44:16 +01:00
iob = ' \n ' ;
2019-05-30 12:23:54 +01:00
} else if ( * lp = = ' r ' ) {
2020-09-11 14:44:16 +01:00
iob = ' \r ' ;
2019-05-30 12:23:54 +01:00
} else if ( * lp = = ' \\ ' ) {
2020-09-11 14:44:16 +01:00
iob = ' \\ ' ;
2019-05-30 12:23:54 +01:00
} else {
lp - - ;
}
2020-09-11 14:44:16 +01:00
if ( sp ) * sp + + = iob ;
2019-05-30 12:23:54 +01:00
} else {
2020-09-11 14:44:16 +01:00
if ( sp ) * sp + + = iob ;
2019-05-30 12:23:54 +01:00
}
2019-05-18 08:45:04 +01:00
lp + + ;
}
2020-09-11 14:44:16 +01:00
if ( sp ) * sp = 0 ;
* vtype = STR_RES ;
tind - > bits . constant = 1 ;
tind - > bits . is_string = 1 ;
return lp + 1 ;
2019-05-18 08:45:04 +01:00
}
if ( * lp = = ' - ' ) {
// inverted var
2020-09-11 14:44:16 +01:00
nres = 1 ;
2019-05-18 08:45:04 +01:00
lp + + ;
}
2020-09-11 14:44:16 +01:00
const char * term = " \n \r ])=+-/*%><!^&|}{ " ;
for ( count = 0 ; count < sizeof ( vname ) ; count + + ) {
char iob = lp [ count ] ;
2019-05-18 08:45:04 +01:00
if ( ! iob | | strchr ( term , iob ) ) {
2020-09-11 14:44:16 +01:00
vname [ count ] = 0 ;
2019-05-18 08:45:04 +01:00
break ;
}
2020-09-11 14:44:16 +01:00
vname [ count ] = iob ;
len + = 1 ;
2019-05-18 08:45:04 +01:00
}
if ( ! vname [ 0 ] ) {
// empty string
2020-09-11 14:44:16 +01:00
* vtype = VAR_NV ;
tind - > index = VAR_NV ;
glob_script_mem . var_not_found = 1 ;
2019-05-18 08:45:04 +01:00
return lp ;
}
2020-09-11 14:44:16 +01:00
struct T_INDEX * vtp = glob_script_mem . type ;
2019-05-22 11:33:51 +01:00
char dvnam [ 32 ] ;
2020-09-11 14:44:16 +01:00
strcpy ( dvnam , vname ) ;
uint8_t olen = len ;
last_findex = - 1 ;
last_sindex = - 1 ;
char * ja = strchr ( dvnam , ' [ ' ) ;
2019-05-22 11:33:51 +01:00
if ( ja ) {
2020-09-11 14:44:16 +01:00
* ja = 0 ;
2019-05-22 11:33:51 +01:00
ja + + ;
2020-09-11 14:44:16 +01:00
olen = strlen ( dvnam ) ;
2019-05-22 11:33:51 +01:00
}
2020-09-11 14:44:16 +01:00
for ( count = 0 ; count < glob_script_mem . numvars ; count + + ) {
char * cp = glob_script_mem . glob_vnp + glob_script_mem . vnp_offset [ count ] ;
uint8_t slen = strlen ( cp ) ;
2019-05-22 11:33:51 +01:00
if ( slen = = olen & & * cp = = dvnam [ 0 ] ) {
2020-09-11 14:44:16 +01:00
if ( ! strncmp ( cp , dvnam , olen ) ) {
uint8_t index = vtp [ count ] . index ;
* tind = vtp [ count ] ;
tind - > index = count ; // overwrite with global var index
2019-05-18 08:45:04 +01:00
if ( vtp [ count ] . bits . is_string = = 0 ) {
2020-09-11 14:44:16 +01:00
* vtype = NTYPE | index ;
2019-05-18 08:45:04 +01:00
if ( vtp [ count ] . bits . is_filter ) {
2019-05-22 11:33:51 +01:00
if ( ja ) {
2020-09-11 14:44:16 +01:00
lp + = olen + 1 ;
lp = GetNumericArgument ( lp , OPER_EQU , & fvar , 0 ) ;
last_findex = fvar ;
fvar = Get_MFVal ( index , fvar ) ;
len = 1 ;
2019-05-22 11:33:51 +01:00
} else {
2020-09-11 14:44:16 +01:00
fvar = Get_MFilter ( index ) ;
2019-05-22 11:33:51 +01:00
}
2019-05-18 08:45:04 +01:00
} else {
2021-01-03 07:08:28 +00:00
if ( ja ) continue ;
2020-09-11 14:44:16 +01:00
fvar = glob_script_mem . fvars [ index ] ;
2019-05-18 08:45:04 +01:00
}
2020-09-11 14:44:16 +01:00
if ( nres ) fvar = - fvar ;
if ( fp ) * fp = fvar ;
2019-05-18 08:45:04 +01:00
} else {
2020-09-11 14:44:16 +01:00
* vtype = STYPE | index ;
if ( sp ) strlcpy ( sp , glob_script_mem . glob_snp + ( index * glob_script_mem . max_ssize ) , SCRIPT_MAXSSIZE ) ;
2019-05-18 08:45:04 +01:00
}
2020-09-11 14:44:16 +01:00
return lp + len ;
2019-05-18 08:45:04 +01:00
}
}
}
if ( jo ) {
// look for json input
2020-12-20 11:07:21 +00:00
char jvname [ 64 ] ;
2020-09-11 14:44:16 +01:00
strcpy ( jvname , vname ) ;
2019-05-18 08:45:04 +01:00
const char * str_value ;
uint8_t aindex ;
String vn ;
2020-09-11 14:44:16 +01:00
char * ja = strchr ( jvname , ' [ ' ) ;
2019-05-18 08:45:04 +01:00
if ( ja ) {
// json array
2020-09-11 14:44:16 +01:00
* ja = 0 ;
2019-05-18 08:45:04 +01:00
ja + + ;
// fetch array index
float fvar ;
2020-09-11 14:44:16 +01:00
GetNumericArgument ( ja , OPER_EQU , & fvar , 0 ) ;
aindex = fvar ;
if ( aindex < 1 | | aindex > 6 ) aindex = 1 ;
2019-05-18 08:45:04 +01:00
aindex - - ;
}
2020-09-25 07:52:28 +01:00
if ( jo - > isValid ( ) ) {
2020-09-11 14:44:16 +01:00
char * subtype = strchr ( jvname , ' # ' ) ;
2019-08-19 07:20:51 +01:00
char * subtype2 ;
2019-05-18 08:45:04 +01:00
if ( subtype ) {
2020-09-11 14:44:16 +01:00
* subtype = 0 ;
2019-05-18 08:45:04 +01:00
subtype + + ;
2020-09-11 14:44:16 +01:00
subtype2 = strchr ( subtype , ' # ' ) ;
2019-08-19 07:20:51 +01:00
if ( subtype2 ) {
2020-09-11 14:44:16 +01:00
* subtype2 = 0 ;
2019-08-19 07:20:51 +01:00
* subtype2 + + ;
}
2019-05-18 08:45:04 +01:00
}
2020-09-11 14:44:16 +01:00
vn = jvname ;
2020-09-25 07:52:28 +01:00
str_value = ( * jo ) [ vn ] . getStr ( ) ;
if ( ( * jo ) [ vn ] . isValid ( ) ) {
2019-05-18 08:45:04 +01:00
if ( subtype ) {
2020-09-25 07:52:28 +01:00
JsonParserObject jobj1 = ( * jo ) [ vn ] ;
if ( jobj1 . isValid ( ) ) {
2020-09-11 14:44:16 +01:00
vn = subtype ;
jo = & jobj1 ;
2020-09-25 07:52:28 +01:00
str_value = ( * jo ) [ vn ] . getStr ( ) ;
if ( ( * jo ) [ vn ] . isValid ( ) ) {
2019-08-19 07:20:51 +01:00
// 2. stage
if ( subtype2 ) {
2020-09-25 07:52:28 +01:00
JsonParserObject jobj2 = ( * jo ) [ vn ] ;
if ( ( * jo ) [ vn ] . isValid ( ) ) {
2020-09-11 14:44:16 +01:00
vn = subtype2 ;
jo = & jobj2 ;
2020-09-25 07:52:28 +01:00
str_value = ( * jo ) [ vn ] . getStr ( ) ;
if ( ( * jo ) [ vn ] . isValid ( ) ) {
2019-08-19 07:20:51 +01:00
goto skip ;
} else {
goto chknext ;
}
} else {
goto chknext ;
}
}
// end
2019-05-18 08:45:04 +01:00
goto skip ;
}
} else {
goto chknext ;
}
}
skip :
if ( ja ) {
// json array
2020-09-25 07:52:28 +01:00
str_value = ( * jo ) [ vn ] . getArray ( ) [ aindex ] . getStr ( ) ;
2019-05-18 08:45:04 +01:00
}
if ( str_value & & * str_value ) {
2020-09-25 07:52:28 +01:00
if ( ( * jo ) [ vn ] . isStr ( ) ) {
2020-09-11 14:44:16 +01:00
if ( ! strncmp ( str_value , " ON " , 2 ) ) {
if ( fp ) * fp = 1 ;
2019-12-16 05:52:25 +00:00
goto nexit ;
2020-09-11 14:44:16 +01:00
} else if ( ! strncmp ( str_value , " OFF " , 3 ) ) {
if ( fp ) * fp = 0 ;
2019-12-16 05:52:25 +00:00
goto nexit ;
2019-05-18 08:45:04 +01:00
} else {
2020-09-11 14:44:16 +01:00
* vtype = STR_RES ;
tind - > bits . constant = 1 ;
tind - > bits . is_string = 1 ;
if ( sp ) strlcpy ( sp , str_value , SCRIPT_MAXSSIZE ) ;
return lp + len ;
2019-05-18 08:45:04 +01:00
}
2019-12-22 14:23:52 +00:00
2019-05-18 08:45:04 +01:00
} else {
2019-08-31 09:10:16 +01:00
if ( fp ) {
2020-09-11 14:44:16 +01:00
if ( ! strncmp ( vn . c_str ( ) , " Epoch " , 5 ) ) {
* fp = atoi ( str_value ) - ( uint32_t ) EPOCH_OFFSET ;
2019-08-31 09:10:16 +01:00
} else {
2020-09-11 14:44:16 +01:00
* fp = CharToFloat ( ( char * ) str_value ) ;
2019-08-31 09:10:16 +01:00
}
}
2019-12-16 05:52:25 +00:00
nexit :
2020-09-11 14:44:16 +01:00
* vtype = NUM_RES ;
tind - > bits . constant = 1 ;
tind - > bits . is_string = 0 ;
return lp + len ;
2019-05-18 08:45:04 +01:00
}
}
}
}
}
chknext :
switch ( vname [ 0 ] ) {
2019-11-27 16:15:41 +00:00
case ' a ' :
# ifdef USE_ANGLE_FUNC
2020-09-11 14:44:16 +01:00
if ( ! strncmp ( vname , " acos( " , 5 ) ) {
2020-09-17 08:11:24 +01:00
lp = GetNumericArgument ( lp + 5 , OPER_EQU , & fvar , 0 ) ;
fvar = acosf ( fvar ) ;
lp + + ;
len = 0 ;
goto exit ;
}
if ( ! strncmp ( vname , " abs( " , 4 ) ) {
lp = GetNumericArgument ( lp + 4 , OPER_EQU , & fvar , 0 ) ;
fvar = fabs ( fvar ) ;
lp + + ;
len = 0 ;
goto exit ;
2019-11-27 16:15:41 +00:00
}
# endif
2020-09-11 14:44:16 +01:00
if ( ! strncmp ( vname , " asc( " , 4 ) ) {
2020-07-15 08:44:52 +01:00
char str [ SCRIPT_MAXSSIZE ] ;
2020-09-11 14:44:16 +01:00
lp = GetStringArgument ( lp + 4 , OPER_EQU , str , 0 ) ;
fvar = str [ 0 ] ;
2020-07-15 08:44:52 +01:00
lp + + ;
2020-09-11 14:44:16 +01:00
len = 0 ;
2020-07-15 08:44:52 +01:00
goto exit ;
}
2020-09-11 14:44:16 +01:00
if ( ! strncmp ( vname , " adc( " , 4 ) ) {
lp = GetNumericArgument ( lp + 4 , OPER_EQU , & fvar , 0 ) ;
2020-08-13 15:04:30 +01:00
while ( * lp = = ' ' ) lp + + ;
2020-09-11 14:44:16 +01:00
float fvar1 = 1 ;
2020-08-13 15:04:30 +01:00
if ( * lp ! = ' ) ' ) {
2020-09-11 14:44:16 +01:00
lp = GetNumericArgument ( lp , OPER_EQU , & fvar1 , 0 ) ;
2020-08-29 10:34:00 +01:00
if ( fvar1 < 32 | | fvar1 > 39 ) fvar1 = 32 ;
2020-08-13 15:04:30 +01:00
}
lp + + ;
2020-08-29 10:34:00 +01:00
if ( fvar > 7 ) fvar = 7 ;
2020-08-13 15:04:30 +01:00
# ifdef ESP32
2020-08-29 10:34:00 +01:00
// ESP32
# ifdef USE_ADC
2020-09-11 14:44:16 +01:00
fvar = AdcRead ( fvar1 , fvar ) ;
2020-08-13 15:04:30 +01:00
# else
2020-09-11 14:44:16 +01:00
fvar = 999.999 ;
2020-08-29 10:34:00 +01:00
# endif // USE_ADC
# else
// ESP8266
# ifndef USE_ADC_VCC
2020-10-02 13:24:23 +01:00
fvar = AdcRead ( 17 , fvar ) ;
2020-08-29 10:34:00 +01:00
# else
2020-09-11 14:44:16 +01:00
fvar = ( float ) ESP . getVcc ( ) / 1000.0 ;
2020-08-29 10:34:00 +01:00
# endif // USE_ADC_VCC
# endif // ESP32
2020-09-11 14:44:16 +01:00
len = 0 ;
2020-08-29 10:34:00 +01:00
goto exit ;
2020-08-13 15:04:30 +01:00
}
2019-11-27 16:15:41 +00:00
break ;
2019-05-18 08:45:04 +01:00
case ' b ' :
2020-09-11 14:44:16 +01:00
if ( ! strncmp ( vname , " boot " , 4 ) ) {
2020-10-29 12:58:50 +00:00
if ( TasmotaGlobal . rules_flag . system_boot ) {
TasmotaGlobal . rules_flag . system_boot = 0 ;
2020-09-11 14:44:16 +01:00
fvar = 1 ;
2019-05-18 08:45:04 +01:00
}
goto exit ;
}
2019-10-15 19:07:12 +01:00
# ifdef USE_BUTTON_EVENT
2020-09-11 14:44:16 +01:00
if ( ! strncmp ( vname , " bt[ " , 3 ) ) {
2019-10-15 19:07:12 +01:00
// tasmota button state
2020-09-11 14:44:16 +01:00
GetNumericArgument ( vname + 3 , OPER_EQU , & fvar , 0 ) ;
uint32_t index = fvar ;
if ( index < 1 | | index > MAX_KEYS ) index = 1 ;
fvar = script_button [ index - 1 ] ;
script_button [ index - 1 ] | = 0x80 ;
2019-10-15 19:07:12 +01:00
len + + ;
goto exit ;
}
2020-09-11 14:44:16 +01:00
# endif //USE_BUTTON_EVENT
2019-05-18 08:45:04 +01:00
break ;
case ' c ' :
2020-09-11 14:44:16 +01:00
if ( ! strncmp ( vname , " chg[ " , 4 ) ) {
2019-05-18 08:45:04 +01:00
// var changed
struct T_INDEX ind ;
uint8_t vtype ;
2020-09-11 14:44:16 +01:00
isvar ( vname + 4 , & vtype , & ind , 0 , 0 , 0 ) ;
2019-05-18 08:45:04 +01:00
if ( ! ind . bits . constant ) {
2020-09-11 14:44:16 +01:00
uint8_t index = glob_script_mem . type [ ind . index ] . index ;
if ( glob_script_mem . fvars [ index ] ! = glob_script_mem . s_fvars [ index ] ) {
2019-05-18 08:45:04 +01:00
// var has changed
2020-09-11 14:44:16 +01:00
glob_script_mem . s_fvars [ index ] = glob_script_mem . fvars [ index ] ;
fvar = 1 ;
2019-05-18 08:45:04 +01:00
len + + ;
goto exit ;
} else {
2020-09-11 14:44:16 +01:00
fvar = 0 ;
2019-05-18 08:45:04 +01:00
len + + ;
goto exit ;
}
}
}
2020-05-06 19:37:05 +01:00
# ifdef ESP32
2020-09-11 14:44:16 +01:00
if ( ! strncmp ( vname , " core " , 4 ) ) {
fvar = xPortGetCoreID ( ) ;
2020-05-06 19:37:05 +01:00
goto exit ;
}
2020-12-18 09:35:14 +00:00
# ifdef USE_M5STACK_CORE2
if ( ! strncmp ( vname , " c2ps( " , 5 ) ) {
lp = GetNumericArgument ( lp + 5 , OPER_EQU , & fvar , 0 ) ;
while ( * lp = = ' ' ) lp + + ;
float fvar1 ;
lp = GetNumericArgument ( lp , OPER_EQU , & fvar1 , 0 ) ;
fvar = core2_setaxppin ( fvar , fvar1 ) ;
lp + + ;
len = 0 ;
goto exit ;
}
# endif // USE_M5STACK_CORE2
2020-05-07 15:16:46 +01:00
# ifdef USE_SCRIPT_TASK
2020-09-11 14:44:16 +01:00
if ( ! strncmp ( vname , " ct( " , 3 ) ) {
lp = GetNumericArgument ( lp + 3 , OPER_EQU , & fvar , 0 ) ;
2020-05-07 15:16:46 +01:00
while ( * lp = = ' ' ) lp + + ;
float fvar1 ;
2020-09-11 14:44:16 +01:00
lp = GetNumericArgument ( lp , OPER_EQU , & fvar1 , 0 ) ;
2020-05-07 15:16:46 +01:00
while ( * lp = = ' ' ) lp + + ;
float fvar2 ;
2020-09-11 14:44:16 +01:00
lp = GetNumericArgument ( lp , OPER_EQU , & fvar2 , 0 ) ;
2020-10-19 06:24:18 +01:00
float prio = STASK_PRIO ;
if ( * lp ! = ' ) ' ) {
lp = GetNumericArgument ( lp , OPER_EQU , & prio , 0 ) ;
}
2020-05-07 15:16:46 +01:00
lp + + ;
2020-10-19 06:24:18 +01:00
fvar = scripter_create_task ( fvar , fvar1 , fvar2 , prio ) ;
2020-09-11 14:44:16 +01:00
len = 0 ;
2020-05-07 15:16:46 +01:00
goto exit ;
}
2020-09-11 14:44:16 +01:00
# endif //USE_SCRIPT_TASK
# endif //ESP32
2019-05-18 08:45:04 +01:00
break ;
case ' d ' :
2020-09-11 14:44:16 +01:00
if ( ! strncmp ( vname , " day " , 3 ) ) {
fvar = RtcTime . day_of_month ;
2019-05-18 08:45:04 +01:00
goto exit ;
}
2021-01-08 10:51:14 +00:00
if ( ! strncmp ( vname , " dvnm " , 4 ) ) {
if ( sp ) strlcpy ( sp , SettingsText ( SET_DEVICENAME ) , glob_script_mem . max_ssize ) ;
goto strexit ;
}
2019-05-18 08:45:04 +01:00
break ;
2019-08-31 09:10:16 +01:00
case ' e ' :
2020-09-11 14:44:16 +01:00
if ( ! strncmp ( vname , " epoch " , 5 ) ) {
fvar = UtcTime ( ) - ( uint32_t ) EPOCH_OFFSET ;
2019-08-31 09:10:16 +01:00
goto exit ;
}
2020-09-11 14:44:16 +01:00
if ( ! strncmp ( vname , " eres " , 4 ) ) {
fvar = event_handeled ;
tind - > index = SCRIPT_EVENT_HANDLED ;
2020-07-16 16:15:12 +01:00
goto exit_settable ;
}
2020-05-23 09:24:08 +01:00
# ifdef USE_ENERGY_SENSOR
2020-09-11 14:44:16 +01:00
if ( ! strncmp ( vname , " enrg[ " , 5 ) ) {
lp = GetNumericArgument ( lp + 5 , OPER_EQU , & fvar , 0 ) ;
2020-05-23 09:24:08 +01:00
while ( * lp = = ' ' ) lp + + ;
switch ( ( uint32_t ) fvar ) {
case 0 :
2020-09-11 14:44:16 +01:00
fvar = Energy . total ;
2020-05-23 09:24:08 +01:00
break ;
case 1 :
2020-09-11 14:44:16 +01:00
fvar = Energy . voltage [ 0 ] ;
2020-05-23 09:24:08 +01:00
break ;
case 2 :
2020-09-11 14:44:16 +01:00
fvar = Energy . voltage [ 1 ] ;
2020-05-23 09:24:08 +01:00
break ;
case 3 :
2020-09-11 14:44:16 +01:00
fvar = Energy . voltage [ 2 ] ;
2020-05-23 09:24:08 +01:00
break ;
case 4 :
2020-09-11 14:44:16 +01:00
fvar = Energy . current [ 0 ] ;
2020-05-23 09:24:08 +01:00
break ;
case 5 :
2020-09-11 14:44:16 +01:00
fvar = Energy . current [ 1 ] ;
2020-05-23 09:24:08 +01:00
break ;
case 6 :
2020-09-11 14:44:16 +01:00
fvar = Energy . current [ 2 ] ;
2020-05-23 09:24:08 +01:00
break ;
case 7 :
2020-09-11 14:44:16 +01:00
fvar = Energy . active_power [ 0 ] ;
2020-05-23 09:24:08 +01:00
break ;
case 8 :
2020-09-11 14:44:16 +01:00
fvar = Energy . active_power [ 1 ] ;
2020-05-23 09:24:08 +01:00
break ;
case 9 :
2020-09-11 14:44:16 +01:00
fvar = Energy . active_power [ 2 ] ;
2020-05-23 09:24:08 +01:00
break ;
2020-12-04 07:57:52 +00:00
case 10 :
fvar = Energy . start_energy ;
break ;
case 11 :
fvar = Energy . daily ;
break ;
2021-01-20 07:49:10 +00:00
case 12 :
fvar = ( float ) Settings . energy_kWhyesterday / 100000.0 ;
break ;
2020-05-23 09:24:08 +01:00
default :
2020-09-11 14:44:16 +01:00
fvar = 99999 ;
2020-05-23 09:24:08 +01:00
break ;
}
2020-09-11 14:44:16 +01:00
len = 0 ;
2020-05-23 09:24:08 +01:00
lp + + ;
goto exit ;
}
# endif //USE_ENERGY_SENSOR
2019-08-31 09:10:16 +01:00
break ;
2019-05-30 12:23:54 +01:00
case ' f ' :
2020-05-30 09:48:12 +01:00
//#define DEBUG_FS
2020-05-02 07:10:23 +01:00
# ifdef USE_SCRIPT_FATFS
2020-09-11 14:44:16 +01:00
if ( ! strncmp ( vname , " fo( " , 3 ) ) {
2019-05-30 12:23:54 +01:00
char str [ SCRIPT_MAXSSIZE ] ;
2020-09-11 14:44:16 +01:00
lp = GetStringArgument ( lp + 3 , OPER_EQU , str , 0 ) ;
2019-05-30 12:23:54 +01:00
while ( * lp = = ' ' ) lp + + ;
2020-09-11 14:44:16 +01:00
uint8_t mode = 0 ;
2020-05-02 07:10:23 +01:00
if ( ( * lp = = ' r ' ) | | ( * lp = = ' w ' ) | | ( * lp = = ' a ' ) ) {
switch ( * lp ) {
case ' r ' :
2020-09-11 14:44:16 +01:00
mode = 0 ;
2020-05-02 07:10:23 +01:00
break ;
case ' w ' :
2020-09-11 14:44:16 +01:00
mode = 1 ;
2020-05-02 07:10:23 +01:00
break ;
case ' a ' :
2020-09-11 14:44:16 +01:00
mode = 2 ;
2020-05-02 07:10:23 +01:00
break ;
}
lp + + ;
} else {
2020-09-11 14:44:16 +01:00
lp = GetNumericArgument ( lp , OPER_EQU , & fvar , 0 ) ;
mode = fvar ;
2020-05-02 07:10:23 +01:00
}
2020-09-11 14:44:16 +01:00
fvar = - 1 ;
for ( uint8_t cnt = 0 ; cnt < SFS_MAX ; cnt + + ) {
2019-06-15 06:02:34 +01:00
if ( ! glob_script_mem . file_flags [ cnt ] . is_open ) {
if ( mode = = 0 ) {
2020-05-30 09:48:12 +01:00
# ifdef DEBUG_FS
2021-01-01 05:43:50 +00:00
Script_AddLog_P ( LOG_LEVEL_INFO , PSTR ( " open file for read %d " ) , cnt ) ;
2020-05-30 09:48:12 +01:00
# endif
2021-01-05 15:37:22 +00:00
glob_script_mem . files [ cnt ] = ufsp - > open ( str , FS_FILE_READ ) ;
2019-06-15 06:02:34 +01:00
if ( glob_script_mem . files [ cnt ] . isDirectory ( ) ) {
glob_script_mem . files [ cnt ] . rewindDirectory ( ) ;
2020-09-11 14:44:16 +01:00
glob_script_mem . file_flags [ cnt ] . is_dir = 1 ;
2019-06-15 06:02:34 +01:00
} else {
2020-09-11 14:44:16 +01:00
glob_script_mem . file_flags [ cnt ] . is_dir = 0 ;
2019-06-15 06:02:34 +01:00
}
}
2020-05-02 07:10:23 +01:00
else {
if ( mode = = 1 ) {
2021-01-05 15:37:22 +00:00
glob_script_mem . files [ cnt ] = ufsp - > open ( str , FS_FILE_WRITE ) ;
2020-05-30 09:48:12 +01:00
# ifdef DEBUG_FS
2021-01-01 05:43:50 +00:00
Script_AddLog_P ( LOG_LEVEL_INFO , PSTR ( " open file for write %d " ) , cnt ) ;
2020-05-30 09:48:12 +01:00
# endif
2020-05-02 07:10:23 +01:00
} else {
2021-01-05 15:37:22 +00:00
glob_script_mem . files [ cnt ] = ufsp - > open ( str , FS_FILE_APPEND ) ;
2020-05-30 09:48:12 +01:00
# ifdef DEBUG_FS
2021-01-01 05:43:50 +00:00
Script_AddLog_P ( LOG_LEVEL_INFO , PSTR ( " open file for append %d " ) , cnt ) ;
2020-05-30 09:48:12 +01:00
# endif
2020-05-02 07:10:23 +01:00
}
}
2019-06-15 06:02:34 +01:00
if ( glob_script_mem . files [ cnt ] ) {
2020-09-11 14:44:16 +01:00
fvar = cnt ;
glob_script_mem . file_flags [ cnt ] . is_open = 1 ;
2019-05-30 12:23:54 +01:00
} else {
2021-01-01 05:43:50 +00:00
Script_AddLog_P ( LOG_LEVEL_INFO , PSTR ( " file open failed " ) ) ;
2019-05-30 12:23:54 +01:00
}
break ;
}
}
lp + + ;
2020-09-11 14:44:16 +01:00
len = 0 ;
2019-05-30 12:23:54 +01:00
goto exit ;
}
2020-09-11 14:44:16 +01:00
if ( ! strncmp ( vname , " fc( " , 3 ) ) {
lp = GetNumericArgument ( lp + 3 , OPER_EQU , & fvar , 0 ) ;
2020-05-30 09:48:12 +01:00
if ( fvar > = 0 ) {
2020-09-11 14:44:16 +01:00
uint8_t ind = fvar ;
if ( ind > = SFS_MAX ) ind = SFS_MAX - 1 ;
2020-05-30 09:48:12 +01:00
# ifdef DEBUG_FS
2021-01-01 05:43:50 +00:00
Script_AddLog_P ( LOG_LEVEL_INFO , PSTR ( " closing file %d " ) , ind ) ;
2020-05-30 09:48:12 +01:00
# endif
glob_script_mem . files [ ind ] . close ( ) ;
2020-09-11 14:44:16 +01:00
glob_script_mem . file_flags [ ind ] . is_open = 0 ;
2020-05-30 09:48:12 +01:00
}
2020-09-11 14:44:16 +01:00
fvar = 0 ;
2019-06-15 06:02:34 +01:00
lp + + ;
2020-09-11 14:44:16 +01:00
len = 0 ;
2019-06-15 06:02:34 +01:00
goto exit ;
}
2020-09-11 14:44:16 +01:00
if ( ! strncmp ( vname , " ff( " , 3 ) ) {
lp = GetNumericArgument ( lp + 3 , OPER_EQU , & fvar , 0 ) ;
uint8_t ind = fvar ;
if ( ind > = SFS_MAX ) ind = SFS_MAX - 1 ;
2019-06-15 06:02:34 +01:00
glob_script_mem . files [ ind ] . flush ( ) ;
2020-09-11 14:44:16 +01:00
fvar = 0 ;
2019-05-30 12:23:54 +01:00
lp + + ;
2020-09-11 14:44:16 +01:00
len = 0 ;
2019-05-30 12:23:54 +01:00
goto exit ;
}
2020-09-11 14:44:16 +01:00
if ( ! strncmp ( vname , " fw( " , 3 ) ) {
2019-05-30 12:23:54 +01:00
char str [ SCRIPT_MAXSSIZE ] ;
2020-09-11 14:44:16 +01:00
lp = ForceStringVar ( lp + 3 , str ) ;
2019-05-30 12:23:54 +01:00
while ( * lp = = ' ' ) lp + + ;
2020-09-11 14:44:16 +01:00
lp = GetNumericArgument ( lp , OPER_EQU , & fvar , 0 ) ;
uint8_t ind = fvar ;
if ( ind > = SFS_MAX ) ind = SFS_MAX - 1 ;
2019-06-15 06:02:34 +01:00
if ( glob_script_mem . file_flags [ ind ] . is_open ) {
2020-09-11 14:44:16 +01:00
fvar = glob_script_mem . files [ ind ] . print ( str ) ;
2019-05-30 12:23:54 +01:00
} else {
2020-09-11 14:44:16 +01:00
fvar = 0 ;
2019-05-30 12:23:54 +01:00
}
lp + + ;
2020-09-11 14:44:16 +01:00
len = 0 ;
2019-05-30 12:23:54 +01:00
goto exit ;
}
2020-09-11 14:44:16 +01:00
if ( ! strncmp ( vname , " fr( " , 3 ) ) {
2019-05-30 12:23:54 +01:00
struct T_INDEX ind ;
uint8_t vtype ;
2020-09-11 14:44:16 +01:00
uint8_t sindex = 0 ;
lp = isvar ( lp + 3 , & vtype , & ind , 0 , 0 , 0 ) ;
2019-05-30 12:23:54 +01:00
if ( vtype ! = VAR_NV ) {
// found variable as result
if ( ( vtype & STYPE ) = = 0 ) {
// error
2020-09-11 14:44:16 +01:00
fvar = 0 ;
2019-05-30 12:23:54 +01:00
goto exit ;
} else {
// string result
2020-09-11 14:44:16 +01:00
sindex = glob_script_mem . type [ ind . index ] . index ;
2019-05-30 12:23:54 +01:00
}
} else {
// error
2020-09-11 14:44:16 +01:00
fvar = 0 ;
2019-05-30 12:23:54 +01:00
goto exit ;
}
while ( * lp = = ' ' ) lp + + ;
2020-09-11 14:44:16 +01:00
lp = GetNumericArgument ( lp , OPER_EQU , & fvar , 0 ) ;
uint8_t find = fvar ;
if ( find > = SFS_MAX ) find = SFS_MAX - 1 ;
uint8_t index = 0 ;
char str [ glob_script_mem . max_ssize + 1 ] ;
char * cp = str ;
2019-06-15 06:02:34 +01:00
if ( glob_script_mem . file_flags [ find ] . is_open ) {
if ( glob_script_mem . file_flags [ find ] . is_dir ) {
while ( true ) {
2020-09-11 14:44:16 +01:00
File entry = glob_script_mem . files [ find ] . openNextFile ( ) ;
2019-06-15 06:02:34 +01:00
if ( entry ) {
2021-01-08 14:00:40 +00:00
if ( ! UfsReject ( ( char * ) entry . name ( ) ) ) {
2020-09-11 14:44:16 +01:00
char * ep = ( char * ) entry . name ( ) ;
2020-05-02 07:10:23 +01:00
if ( * ep = = ' / ' ) ep + + ;
char * lcp = strrchr ( ep , ' / ' ) ;
if ( lcp ) {
2020-09-11 14:44:16 +01:00
ep = lcp + 1 ;
2020-05-02 07:10:23 +01:00
}
2020-09-11 14:44:16 +01:00
strcpy ( str , ep ) ;
2019-06-15 06:02:34 +01:00
entry . close ( ) ;
break ;
}
} else {
2020-09-11 14:44:16 +01:00
* cp = 0 ;
2019-06-15 06:02:34 +01:00
break ;
}
entry . close ( ) ;
}
2020-09-11 14:44:16 +01:00
index = strlen ( str ) ;
2019-06-15 06:02:34 +01:00
} else {
while ( glob_script_mem . files [ find ] . available ( ) ) {
uint8_t buf [ 1 ] ;
glob_script_mem . files [ find ] . read ( buf , 1 ) ;
if ( buf [ 0 ] = = ' \t ' | | buf [ 0 ] = = ' , ' | | buf [ 0 ] = = ' \n ' | | buf [ 0 ] = = ' \r ' ) {
break ;
} else {
2020-09-11 14:44:16 +01:00
* cp + + = buf [ 0 ] ;
2019-06-15 06:02:34 +01:00
index + + ;
2020-09-11 14:44:16 +01:00
if ( index > = glob_script_mem . max_ssize - 1 ) break ;
2019-06-15 06:02:34 +01:00
}
2019-05-30 12:23:54 +01:00
}
2020-09-11 14:44:16 +01:00
* cp = 0 ;
2019-05-30 12:23:54 +01:00
}
} else {
2020-09-11 14:44:16 +01:00
strcpy ( str , " file error " ) ;
2019-05-30 12:23:54 +01:00
}
lp + + ;
2020-09-11 14:44:16 +01:00
strlcpy ( glob_script_mem . glob_snp + ( sindex * glob_script_mem . max_ssize ) , str , glob_script_mem . max_ssize ) ;
fvar = index ;
len = 0 ;
2019-05-30 12:23:54 +01:00
goto exit ;
}
2020-09-11 14:44:16 +01:00
if ( ! strncmp ( vname , " fd( " , 3 ) ) {
char str [ glob_script_mem . max_ssize + 1 ] ;
lp = GetStringArgument ( lp + 3 , OPER_EQU , str , 0 ) ;
2021-01-05 15:37:22 +00:00
ufsp - > remove ( str ) ;
2020-05-02 07:10:23 +01:00
lp + + ;
2020-09-11 14:44:16 +01:00
len = 0 ;
2020-05-02 07:10:23 +01:00
goto exit ;
}
# if defined(ESP32) && defined(USE_WEBCAM)
2020-09-11 14:44:16 +01:00
if ( ! strncmp ( vname , " fwp( " , 4 ) ) {
lp = GetNumericArgument ( lp + 4 , OPER_EQU , & fvar , 0 ) ;
2020-05-02 07:10:23 +01:00
while ( * lp = = ' ' ) lp + + ;
float fvar1 ;
2020-09-11 14:44:16 +01:00
lp = GetNumericArgument ( lp , OPER_EQU , & fvar1 , 0 ) ;
uint8_t ind = fvar1 ;
if ( ind > = SFS_MAX ) ind = SFS_MAX - 1 ;
2020-05-02 07:10:23 +01:00
if ( glob_script_mem . file_flags [ ind ] . is_open ) {
uint8_t * buff ;
2020-09-11 14:44:16 +01:00
float maxps = WcGetPicstore ( - 1 , 0 ) ;
if ( fvar < 1 | | fvar > maxps ) fvar = 1 ;
uint32_t len = WcGetPicstore ( fvar - 1 , & buff ) ;
2020-05-02 07:10:23 +01:00
if ( len ) {
//glob_script_mem.files[ind].seek(0,SeekEnd);
2020-09-11 14:44:16 +01:00
fvar = glob_script_mem . files [ ind ] . write ( buff , len ) ;
2020-05-02 07:10:23 +01:00
} else {
2020-09-11 14:44:16 +01:00
fvar = 0 ;
2020-05-02 07:10:23 +01:00
}
2021-01-01 05:43:50 +00:00
//Script_AddLog_P(LOG_LEVEL_INFO, PSTR("picture save: %d"), len);
2020-05-02 07:10:23 +01:00
} else {
2020-09-11 14:44:16 +01:00
fvar = 0 ;
2020-05-02 07:10:23 +01:00
}
2019-05-30 12:23:54 +01:00
lp + + ;
2020-09-11 14:44:16 +01:00
len = 0 ;
2019-05-30 12:23:54 +01:00
goto exit ;
}
2020-09-11 14:44:16 +01:00
# endif //ESP32 && USE_WEBCAM
2019-06-15 06:02:34 +01:00
# ifdef USE_SCRIPT_FATFS_EXT
2020-09-11 14:44:16 +01:00
if ( ! strncmp ( vname , " fe( " , 3 ) ) {
char str [ glob_script_mem . max_ssize + 1 ] ;
lp = GetStringArgument ( lp + 3 , OPER_EQU , str , 0 ) ;
2019-06-15 06:02:34 +01:00
// execute script
2021-01-05 15:37:22 +00:00
File ef = ufsp - > open ( str , FS_FILE_READ ) ;
2019-06-15 06:02:34 +01:00
if ( ef ) {
2020-09-11 14:44:16 +01:00
uint16_t fsiz = ef . size ( ) ;
2019-06-15 06:02:34 +01:00
if ( fsiz < 2048 ) {
2020-09-11 14:44:16 +01:00
char * script = ( char * ) calloc ( fsiz + 16 , 1 ) ;
2019-06-15 06:02:34 +01:00
if ( script ) {
ef . read ( ( uint8_t * ) script , fsiz ) ;
execute_script ( script ) ;
free ( script ) ;
2020-09-11 14:44:16 +01:00
fvar = 1 ;
2019-06-15 06:02:34 +01:00
}
}
ef . close ( ) ;
}
lp + + ;
2020-09-11 14:44:16 +01:00
len = 0 ;
2019-06-15 06:02:34 +01:00
goto exit ;
}
2020-09-11 14:44:16 +01:00
if ( ! strncmp ( vname , " fmd( " , 4 ) ) {
char str [ glob_script_mem . max_ssize + 1 ] ;
lp = GetStringArgument ( lp + 4 , OPER_EQU , str , 0 ) ;
2021-01-05 15:37:22 +00:00
fvar = ufsp - > mkdir ( str ) ;
2019-06-15 06:02:34 +01:00
lp + + ;
2020-09-11 14:44:16 +01:00
len = 0 ;
2019-06-15 06:02:34 +01:00
goto exit ;
}
2020-09-11 14:44:16 +01:00
if ( ! strncmp ( vname , " frd( " , 4 ) ) {
char str [ glob_script_mem . max_ssize + 1 ] ;
lp = GetStringArgument ( lp + 4 , OPER_EQU , str , 0 ) ;
2021-01-05 15:37:22 +00:00
fvar = ufsp - > rmdir ( str ) ;
2019-06-15 06:02:34 +01:00
lp + + ;
2020-09-11 14:44:16 +01:00
len = 0 ;
2019-06-15 06:02:34 +01:00
goto exit ;
}
2020-09-11 14:44:16 +01:00
if ( ! strncmp ( vname , " fx( " , 3 ) ) {
char str [ glob_script_mem . max_ssize + 1 ] ;
lp = GetStringArgument ( lp + 3 , OPER_EQU , str , 0 ) ;
2021-01-05 15:37:22 +00:00
if ( ufsp - > exists ( str ) ) fvar = 1 ;
2020-09-11 14:44:16 +01:00
else fvar = 0 ;
2019-06-15 06:02:34 +01:00
lp + + ;
2020-09-11 14:44:16 +01:00
len = 0 ;
2019-06-15 06:02:34 +01:00
goto exit ;
}
2020-09-17 08:11:24 +01:00
if ( ! strncmp ( vname , " fsi( " , 4 ) ) {
lp = GetNumericArgument ( lp + 4 , OPER_EQU , & fvar , 0 ) ;
2021-01-08 14:00:40 +00:00
fvar = UfsInfo ( fvar , 0 ) ;
2020-09-17 08:11:24 +01:00
lp + + ;
len = 0 ;
goto exit ;
}
2020-09-23 11:51:35 +01:00
if ( ! strncmp ( vname , " fwa( " , 4 ) ) {
struct T_INDEX ind ;
uint8_t vtype ;
lp = isvar ( lp + 4 , & vtype , & ind , 0 , 0 , 0 ) ;
if ( vtype ! = VAR_NV & & ( vtype & STYPE ) = = 0 & & glob_script_mem . type [ ind . index ] . bits . is_filter ) {
// found array as result
} else {
// error
fvar = 0 ;
goto exit ;
}
while ( * lp = = ' ' ) lp + + ;
lp = GetNumericArgument ( lp , OPER_EQU , & fvar , 0 ) ;
uint8_t index = fvar ;
if ( index > = SFS_MAX ) index = SFS_MAX - 1 ;
if ( glob_script_mem . file_flags [ index ] . is_open ) {
uint16_t len = 0 ;
float * fa = Get_MFAddr ( glob_script_mem . type [ ind . index ] . index , & len , 0 ) ;
char dstr [ 24 ] ;
for ( uint32_t cnt = 0 ; cnt < len ; cnt + + ) {
dtostrfd ( * fa , glob_script_mem . script_dprec , dstr ) ;
fa + + ;
if ( cnt < ( len - 1 ) ) {
strcat ( dstr , " \t " ) ;
} else {
strcat ( dstr , " \n " ) ;
}
glob_script_mem . files [ index ] . print ( dstr ) ;
}
} else {
fvar = 0 ;
}
lp + + ;
len = 0 ;
goto exit ;
}
if ( ! strncmp ( vname , " fra( " , 4 ) ) {
struct T_INDEX ind ;
uint8_t vtype ;
lp = isvar ( lp + 4 , & vtype , & ind , 0 , 0 , 0 ) ;
if ( vtype ! = VAR_NV & & ( vtype & STYPE ) = = 0 & & glob_script_mem . type [ ind . index ] . bits . is_filter ) {
// found array as result
} else {
// error
fvar = 0 ;
goto exit ;
}
while ( * lp = = ' ' ) lp + + ;
lp = GetNumericArgument ( lp , OPER_EQU , & fvar , 0 ) ;
uint8_t find = fvar ;
if ( find > = SFS_MAX ) find = SFS_MAX - 1 ;
char str [ glob_script_mem . max_ssize + 1 ] ;
if ( glob_script_mem . file_flags [ find ] . is_open ) {
uint16_t len = 0 ;
float * fa = Get_MFAddr ( glob_script_mem . type [ ind . index ] . index , & len , 0 ) ;
char dstr [ 24 ] ;
for ( uint32_t cnt = 0 ; cnt < len ; cnt + + ) {
uint8_t index = 0 ;
char * cp = str ;
while ( glob_script_mem . files [ find ] . available ( ) ) {
uint8_t buf [ 1 ] ;
glob_script_mem . files [ find ] . read ( buf , 1 ) ;
if ( buf [ 0 ] = = ' \t ' | | buf [ 0 ] = = ' , ' | | buf [ 0 ] = = ' \n ' | | buf [ 0 ] = = ' \r ' ) {
break ;
} else {
* cp + + = buf [ 0 ] ;
index + + ;
if ( index > = glob_script_mem . max_ssize - 1 ) break ;
}
}
* cp = 0 ;
* fa + + = CharToFloat ( str ) ;
}
} else {
fvar = 0 ;
}
lp + + ;
len = 0 ;
goto exit ;
}
2020-05-02 07:10:23 +01:00
# endif // USE_SCRIPT_FATFS_EXT
2020-09-11 14:44:16 +01:00
if ( ! strncmp ( vname , " fl1( " , 4 ) | | ! strncmp ( vname , " fl2( " , 4 ) ) {
uint8_t lknum = * ( lp + 2 ) & 3 ;
char str [ glob_script_mem . max_ssize + 1 ] ;
lp = GetStringArgument ( lp + 4 , OPER_EQU , str , 0 ) ;
if ( lknum < 1 | | lknum > 2 ) lknum = 1 ;
strlcpy ( glob_script_mem . flink [ lknum - 1 ] , str , 14 ) ;
2019-05-30 12:23:54 +01:00
lp + + ;
2020-09-11 14:44:16 +01:00
fvar = 0 ;
len = 0 ;
2019-05-30 12:23:54 +01:00
goto exit ;
}
2020-09-11 14:44:16 +01:00
if ( ! strncmp ( vname , " fsm " , 3 ) ) {
2019-05-30 12:23:54 +01:00
fvar = glob_script_mem . script_sd_found ;
//card_init();
goto exit ;
}
# endif //USE_SCRIPT_FATFS
2020-09-11 14:44:16 +01:00
if ( ! strncmp ( vname , " freq " , 4 ) ) {
2020-05-02 07:10:23 +01:00
# ifdef ESP32
2020-09-11 14:44:16 +01:00
fvar = getCpuFrequencyMhz ( ) ;
2020-05-02 07:10:23 +01:00
# else
2020-09-11 14:44:16 +01:00
fvar = ESP . getCpuFreqMHz ( ) ;
2020-05-02 07:10:23 +01:00
# endif
goto exit ;
}
2020-12-26 08:45:59 +00:00
if ( ! strncmp ( vname , " frnm " , 4 ) ) {
if ( sp ) strlcpy ( sp , SettingsText ( SET_FRIENDLYNAME1 ) , glob_script_mem . max_ssize ) ;
goto strexit ;
}
2020-05-02 07:10:23 +01:00
break ;
2021-01-08 10:51:14 +00:00
2019-05-18 08:45:04 +01:00
case ' g ' :
2020-09-11 14:44:16 +01:00
if ( ! strncmp ( vname , " gtmp " , 4 ) ) {
2020-10-28 18:03:39 +00:00
fvar = TasmotaGlobal . temperature_celsius ;
2019-05-18 08:45:04 +01:00
goto exit ;
}
2020-09-11 14:44:16 +01:00
if ( ! strncmp ( vname , " ghum " , 4 ) ) {
2020-10-28 18:03:39 +00:00
fvar = TasmotaGlobal . humidity ;
2019-05-18 08:45:04 +01:00
goto exit ;
}
2020-09-11 14:44:16 +01:00
if ( ! strncmp ( vname , " gprs " , 4 ) ) {
2020-10-28 18:03:39 +00:00
fvar = TasmotaGlobal . pressure_hpa ;
2019-05-18 08:45:04 +01:00
goto exit ;
}
2020-09-11 14:44:16 +01:00
if ( ! strncmp ( vname , " gtopic " , 6 ) ) {
if ( sp ) strlcpy ( sp , SettingsText ( SET_MQTT_GRP_TOPIC ) , glob_script_mem . max_ssize ) ;
2019-05-18 08:45:04 +01:00
goto strexit ;
}
2020-06-15 16:20:50 +01:00
# ifdef SCRIPT_GET_HTTPS_JP
2020-09-11 14:44:16 +01:00
if ( ! strncmp ( vname , " gjp( " , 4 ) ) {
2020-06-15 16:20:50 +01:00
char host [ SCRIPT_MAXSSIZE ] ;
2020-09-11 14:44:16 +01:00
lp = GetStringArgument ( lp + 4 , OPER_EQU , host , 0 ) ;
2020-06-15 16:20:50 +01:00
SCRIPT_SKIP_SPACES
char path [ SCRIPT_MAXSSIZE ] ;
2020-09-11 14:44:16 +01:00
lp = GetStringArgument ( lp , OPER_EQU , path , 0 ) ;
fvar = call2https ( host , path ) ;
2020-06-15 16:20:50 +01:00
lp + + ;
2020-09-11 14:44:16 +01:00
len = 0 ;
2020-06-15 16:20:50 +01:00
goto exit ;
}
2020-09-11 14:44:16 +01:00
# endif //SCRIPT_GET_HTTPS_JP
2019-05-18 08:45:04 +01:00
break ;
case ' h ' :
2020-09-11 14:44:16 +01:00
if ( ! strncmp ( vname , " hours " , 5 ) ) {
fvar = RtcTime . hour ;
2019-05-18 08:45:04 +01:00
goto exit ;
}
2020-09-11 14:44:16 +01:00
if ( ! strncmp ( vname , " heap " , 4 ) ) {
fvar = ESP_getFreeHeap ( ) ;
2019-05-18 08:45:04 +01:00
goto exit ;
}
2020-09-11 14:44:16 +01:00
if ( ! strncmp ( vname , " hn( " , 3 ) ) {
lp = GetNumericArgument ( lp + 3 , OPER_EQU , & fvar , 0 ) ;
if ( fvar < 0 | | fvar > 255 ) fvar = 0 ;
2019-05-18 08:45:04 +01:00
lp + + ;
2020-09-11 14:44:16 +01:00
len = 0 ;
2019-05-18 08:45:04 +01:00
if ( sp ) {
2020-09-11 14:44:16 +01:00
sprintf ( sp , " %02x " , ( uint8_t ) fvar ) ;
2019-05-18 08:45:04 +01:00
}
goto strexit ;
}
2020-09-11 14:44:16 +01:00
if ( ! strncmp ( vname , " hx( " , 3 ) ) {
lp = GetNumericArgument ( lp + 3 , OPER_EQU , & fvar , 0 ) ;
2019-09-18 17:50:25 +01:00
lp + + ;
2020-09-11 14:44:16 +01:00
len = 0 ;
2019-09-18 17:50:25 +01:00
if ( sp ) {
2020-09-11 14:44:16 +01:00
sprintf ( sp , " %08x " , ( uint32_t ) fvar ) ;
2019-09-18 17:50:25 +01:00
}
goto strexit ;
}
2020-09-11 14:44:16 +01:00
if ( ! strncmp ( vname , " hd( " , 3 ) ) {
2020-07-15 08:44:52 +01:00
char str [ SCRIPT_MAXSSIZE ] ;
2020-09-11 14:44:16 +01:00
lp = GetStringArgument ( lp + 3 , OPER_EQU , str , 0 ) ;
fvar = strtol ( str , NULL , 16 ) ;
2020-07-15 08:44:52 +01:00
lp + + ;
2020-09-11 14:44:16 +01:00
len = 0 ;
2020-07-15 08:44:52 +01:00
goto exit ;
}
2019-08-16 06:37:16 +01:00
# ifdef USE_LIGHT
2020-09-11 14:44:16 +01:00
if ( ! strncmp ( vname , " hsvrgb( " , 7 ) ) {
lp = GetNumericArgument ( lp + 7 , OPER_EQU , & fvar , 0 ) ;
if ( fvar < 0 | | fvar > 360 ) fvar = 0 ;
2019-08-16 06:37:16 +01:00
SCRIPT_SKIP_SPACES
// arg2
float fvar2 ;
2020-09-11 14:44:16 +01:00
lp = GetNumericArgument ( lp , OPER_EQU , & fvar2 , 0 ) ;
if ( fvar2 < 0 | | fvar2 > 100 ) fvar2 = 0 ;
2019-08-16 06:37:16 +01:00
SCRIPT_SKIP_SPACES
// arg3
float fvar3 ;
2020-09-11 14:44:16 +01:00
lp = GetNumericArgument ( lp , OPER_EQU , & fvar3 , 0 ) ;
if ( fvar3 < 0 | | fvar3 > 100 ) fvar3 = 0 ;
2019-08-16 06:37:16 +01:00
2020-09-11 14:44:16 +01:00
fvar = HSVToRGB ( fvar , fvar2 , fvar3 ) ;
2019-08-16 06:37:16 +01:00
lp + + ;
2020-09-11 14:44:16 +01:00
len = 0 ;
2019-08-16 06:37:16 +01:00
goto exit ;
}
2020-09-11 14:44:16 +01:00
# endif //USE_LIGHT
2019-05-18 08:45:04 +01:00
break ;
case ' i ' :
2020-09-11 14:44:16 +01:00
if ( ! strncmp ( vname , " int( " , 4 ) ) {
lp = GetNumericArgument ( lp + 4 , OPER_EQU , & fvar , 0 ) ;
fvar = floor ( fvar ) ;
2019-05-18 08:45:04 +01:00
lp + + ;
2020-09-11 14:44:16 +01:00
len = 0 ;
2019-05-18 08:45:04 +01:00
goto exit ;
}
2020-09-11 14:44:16 +01:00
if ( ! strncmp ( vname , " is( " , 3 ) ) {
2020-09-23 11:51:35 +01:00
lp = isargs ( lp + 3 , 0 ) ;
fvar = 0 ;
len = 0 ;
goto exit ;
}
if ( ! strncmp ( vname , " is1( " , 4 ) ) {
lp = isargs ( lp + 4 , 1 ) ;
fvar = 0 ;
len = 0 ;
goto exit ;
}
if ( ! strncmp ( vname , " is2( " , 4 ) ) {
lp = isargs ( lp + 4 , 2 ) ;
2020-09-11 14:44:16 +01:00
fvar = 0 ;
len = 0 ;
2020-06-13 12:05:25 +01:00
goto exit ;
}
2020-09-11 14:44:16 +01:00
if ( ! strncmp ( vname , " is[ " , 3 ) ) {
2020-09-23 11:51:35 +01:00
lp = isget ( lp + 3 , sp , 0 ) ;
len = 0 ;
goto strexit ;
}
if ( ! strncmp ( vname , " is1[ " , 4 ) ) {
lp = isget ( lp + 4 , sp , 1 ) ;
len = 0 ;
goto strexit ;
}
if ( ! strncmp ( vname , " is2[ " , 4 ) ) {
lp = isget ( lp + 4 , sp , 2 ) ;
2020-09-11 14:44:16 +01:00
len = 0 ;
2020-06-29 06:06:08 +01:00
goto strexit ;
}
2019-05-18 08:45:04 +01:00
break ;
case ' l ' :
2020-09-11 14:44:16 +01:00
if ( ! strncmp ( vname , " lip " , 3 ) ) {
if ( sp ) strlcpy ( sp , ( const char * ) WiFi . localIP ( ) . toString ( ) . c_str ( ) , glob_script_mem . max_ssize ) ;
2020-05-02 15:44:44 +01:00
goto strexit ;
}
2020-06-13 12:05:25 +01:00
# ifdef USE_SCRIPT_GLOBVARS
2020-09-11 14:44:16 +01:00
if ( ! strncmp ( vname , " luip " , 4 ) ) {
2021-01-18 15:32:58 +00:00
if ( sp ) strlcpy ( sp , last_udp_ip . toString ( ) . c_str ( ) , glob_script_mem . max_ssize ) ;
2020-06-13 12:05:25 +01:00
goto strexit ;
}
2020-09-11 14:44:16 +01:00
# endif //USE_SCRIPT_GLOBVARS
if ( ! strncmp ( vname , " loglvl " , 6 ) ) {
fvar = glob_script_mem . script_loglevel ;
tind - > index = SCRIPT_LOGLEVEL ;
2019-05-18 08:45:04 +01:00
exit_settable :
2020-09-11 14:44:16 +01:00
if ( fp ) * fp = fvar ;
* vtype = NTYPE ;
tind - > bits . settable = 1 ;
tind - > bits . is_string = 0 ;
return lp + len ;
2019-05-18 08:45:04 +01:00
}
break ;
case ' m ' :
2020-09-11 14:44:16 +01:00
if ( ! strncmp ( vname , " med( " , 4 ) ) {
2019-05-18 08:45:04 +01:00
float fvar1 ;
2020-09-11 14:44:16 +01:00
lp = GetNumericArgument ( lp + 4 , OPER_EQU , & fvar1 , 0 ) ;
2019-05-18 08:45:04 +01:00
SCRIPT_SKIP_SPACES
// arg2
float fvar2 ;
2020-09-11 14:44:16 +01:00
lp = GetNumericArgument ( lp , OPER_EQU , & fvar2 , 0 ) ;
fvar = DoMedian5 ( fvar1 , fvar2 ) ;
2019-05-18 08:45:04 +01:00
lp + + ;
2020-09-11 14:44:16 +01:00
len = 0 ;
2019-05-18 08:45:04 +01:00
goto exit ;
}
2020-06-05 19:15:16 +01:00
# ifdef USE_ANGLE_FUNC
2020-09-11 14:44:16 +01:00
if ( ! strncmp ( vname , " mpt( " , 4 ) ) {
lp = GetNumericArgument ( lp + 4 , OPER_EQU , & fvar , 0 ) ;
fvar = MeasurePulseTime ( fvar ) ;
2020-06-05 19:15:16 +01:00
lp + + ;
2020-09-11 14:44:16 +01:00
len = 0 ;
2020-06-05 19:15:16 +01:00
goto exit ;
}
2020-09-11 14:44:16 +01:00
# endif //USE_ANGLE_FUNC
if ( ! strncmp ( vname , " micros " , 6 ) ) {
fvar = micros ( ) ;
2019-05-18 08:45:04 +01:00
goto exit ;
}
2020-09-11 14:44:16 +01:00
if ( ! strncmp ( vname , " millis " , 6 ) ) {
fvar = millis ( ) ;
2019-05-18 08:45:04 +01:00
goto exit ;
}
2020-09-11 14:44:16 +01:00
if ( ! strncmp ( vname , " mins " , 4 ) ) {
fvar = RtcTime . minute ;
2019-05-18 08:45:04 +01:00
goto exit ;
}
2020-09-11 14:44:16 +01:00
if ( ! strncmp ( vname , " month " , 5 ) ) {
fvar = RtcTime . month ;
2019-05-18 08:45:04 +01:00
goto exit ;
}
2020-09-11 14:44:16 +01:00
if ( ! strncmp ( vname , " mqttc " , 5 ) ) {
2020-10-29 12:58:50 +00:00
if ( TasmotaGlobal . rules_flag . mqtt_connected ) {
TasmotaGlobal . rules_flag . mqtt_connected = 0 ;
2020-09-11 14:44:16 +01:00
fvar = 1 ;
2019-05-18 08:45:04 +01:00
}
goto exit ;
}
2020-09-11 14:44:16 +01:00
if ( ! strncmp ( vname , " mqttd " , 5 ) ) {
2020-10-29 12:58:50 +00:00
if ( TasmotaGlobal . rules_flag . mqtt_disconnected ) {
TasmotaGlobal . rules_flag . mqtt_disconnected = 0 ;
2020-09-11 14:44:16 +01:00
fvar = 1 ;
2019-05-18 08:45:04 +01:00
}
goto exit ;
}
2020-09-11 14:44:16 +01:00
if ( ! strncmp ( vname , " mqtts " , 5 ) ) {
2020-10-30 11:29:48 +00:00
fvar = ! TasmotaGlobal . global_state . mqtt_down ;
2019-05-18 08:45:04 +01:00
goto exit ;
}
2020-09-11 14:44:16 +01:00
if ( ! strncmp ( vname , " mp( " , 3 ) ) {
2020-03-06 20:13:12 +00:00
float fvar1 ;
2020-09-11 14:44:16 +01:00
lp = GetNumericArgument ( lp + 3 , OPER_EQU , & fvar1 , 0 ) ;
2020-03-06 20:13:12 +00:00
SCRIPT_SKIP_SPACES
while ( * lp ! = ' ) ' ) {
2020-09-11 14:44:16 +01:00
char * opp = lp ;
2020-03-07 15:53:49 +00:00
lp + + ;
2020-03-06 20:13:12 +00:00
float fvar2 ;
2020-09-11 14:44:16 +01:00
lp = GetNumericArgument ( lp , OPER_EQU , & fvar2 , 0 ) ;
2020-03-07 15:53:49 +00:00
SCRIPT_SKIP_SPACES
2020-09-11 14:44:16 +01:00
fvar = fvar1 ;
2020-03-29 15:29:22 +01:00
if ( ( * opp = = ' < ' & & fvar1 < fvar2 ) | |
( * opp = = ' > ' & & fvar1 > fvar2 ) | |
2020-09-11 14:44:16 +01:00
( * opp = = ' = ' & & fvar1 = = fvar2 ) ) {
if ( * lp ! = ' < ' & & * lp ! = ' > ' & & * lp ! = ' = ' & & * lp ! = ' ) ' & & * lp ! = SCRIPT_EOL ) {
float fvar3 ;
lp = GetNumericArgument ( lp , OPER_EQU , & fvar3 , 0 ) ;
SCRIPT_SKIP_SPACES
fvar = fvar3 ;
} else {
fvar = fvar2 ;
}
break ;
2020-03-06 20:13:12 +00:00
}
2020-03-07 15:53:49 +00:00
while ( * lp ! = ' < ' & & * lp ! = ' > ' & & * lp ! = ' = ' & & * lp ! = ' ) ' & & * lp ! = SCRIPT_EOL ) lp + + ;
2020-03-06 20:13:12 +00:00
}
2020-09-11 14:44:16 +01:00
len = 0 ;
2020-03-06 20:13:12 +00:00
goto exit ;
}
2020-07-02 05:46:04 +01:00
# ifdef USE_MORITZ
2020-09-11 14:44:16 +01:00
if ( ! strncmp ( vname , " mo( " , 3 ) ) {
2020-07-02 05:46:04 +01:00
float fvar1 ;
2020-09-11 14:44:16 +01:00
lp = GetNumericArgument ( lp + 3 , OPER_EQU , & fvar1 , 0 ) ;
2020-07-02 05:46:04 +01:00
SCRIPT_SKIP_SPACES
float fvar2 ;
2020-09-11 14:44:16 +01:00
lp = GetNumericArgument ( lp , OPER_EQU , & fvar2 , 0 ) ;
2020-07-02 05:46:04 +01:00
SCRIPT_SKIP_SPACES
char rbuff [ 64 ] ;
2020-09-11 14:44:16 +01:00
fvar = mo_getvars ( fvar1 , fvar2 , rbuff ) ;
2020-07-02 05:46:04 +01:00
lp + + ;
2020-09-11 14:44:16 +01:00
if ( sp ) strlcpy ( sp , rbuff , glob_script_mem . max_ssize ) ;
len = 0 ;
2020-07-02 05:46:04 +01:00
goto strexit ;
}
2020-09-11 14:44:16 +01:00
# endif //USE_MORITZ
2019-05-18 08:45:04 +01:00
break ;
case ' p ' :
2020-09-11 14:44:16 +01:00
if ( ! strncmp ( vname , " pin[ " , 4 ) ) {
2019-05-18 08:45:04 +01:00
// raw pin level
2020-09-11 14:44:16 +01:00
GetNumericArgument ( vname + 4 , OPER_EQU , & fvar , 0 ) ;
fvar = digitalRead ( ( uint8_t ) fvar ) ;
2019-05-18 08:45:04 +01:00
// skip ] bracket
len + + ;
goto exit ;
}
2020-09-11 14:44:16 +01:00
if ( ! strncmp ( vname , " pn[ " , 3 ) ) {
GetNumericArgument ( vname + 3 , OPER_EQU , & fvar , 0 ) ;
fvar = Pin ( fvar ) ;
2020-05-02 07:10:23 +01:00
// skip ] bracket
len + + ;
goto exit ;
}
2020-12-18 09:35:14 +00:00
# if defined(ESP32) && (defined(USE_I2S_AUDIO) || defined(USE_TTGO_WATCH) || defined(USE_M5STACK_CORE2))
2020-09-11 14:44:16 +01:00
if ( ! strncmp ( vname , " pl( " , 3 ) ) {
2020-08-13 15:04:30 +01:00
char path [ SCRIPT_MAXSSIZE ] ;
2020-09-11 14:44:16 +01:00
lp = GetStringArgument ( lp + 3 , OPER_EQU , path , 0 ) ;
2020-08-13 15:04:30 +01:00
Play_mp3 ( path ) ;
2019-05-18 08:45:04 +01:00
len + + ;
2020-09-11 14:44:16 +01:00
len = 0 ;
2019-05-18 08:45:04 +01:00
goto exit ;
}
2020-08-13 15:04:30 +01:00
# endif // USE_I2S_AUDIO
2020-09-11 14:44:16 +01:00
if ( ! strncmp ( vname , " pd[ " , 3 ) ) {
GetNumericArgument ( vname + 3 , OPER_EQU , & fvar , 0 ) ;
uint8_t gpiopin = fvar ;
2020-05-01 16:37:56 +01:00
/*
2020-04-29 13:01:02 +01:00
for ( uint8_t i = 0 ; i < GPIO_SENSOR_END ; i + + ) {
// if (pin_gpio[i]==gpiopin) {
2020-04-27 10:54:23 +01:00
if ( Pin ( i ) = = gpiopin ) {
2019-05-18 08:45:04 +01:00
fvar = i ;
// skip ] bracket
len + + ;
goto exit ;
}
}
2020-05-01 16:37:56 +01:00
*/
2020-10-29 12:58:50 +00:00
if ( ( gpiopin < ARRAY_SIZE ( TasmotaGlobal . gpio_pin ) ) & & ( TasmotaGlobal . gpio_pin [ gpiopin ] > 0 ) ) {
fvar = TasmotaGlobal . gpio_pin [ gpiopin ] ;
2020-04-28 13:42:47 +01:00
// skip ] bracket
len + + ;
goto exit ;
}
2020-09-11 14:44:16 +01:00
fvar = 999 ;
2019-05-18 08:45:04 +01:00
goto exit ;
}
2020-05-06 19:37:05 +01:00
# ifdef ESP32
2020-09-11 14:44:16 +01:00
if ( ! strncmp ( vname , " pheap " , 5 ) ) {
fvar = ESP . getFreePsram ( ) ;
2020-05-06 19:37:05 +01:00
goto exit ;
}
2020-09-11 14:44:16 +01:00
# endif //ESP32
if ( ! strncmp ( vname , " prefix1 " , 7 ) ) {
if ( sp ) strlcpy ( sp , SettingsText ( SET_MQTTPREFIX1 ) , glob_script_mem . max_ssize ) ;
2019-05-18 08:45:04 +01:00
goto strexit ;
}
2020-09-11 14:44:16 +01:00
if ( ! strncmp ( vname , " prefix2 " , 7 ) ) {
if ( sp ) strlcpy ( sp , SettingsText ( SET_MQTTPREFIX2 ) , glob_script_mem . max_ssize ) ;
2019-05-18 08:45:04 +01:00
goto strexit ;
}
2020-09-11 14:44:16 +01:00
if ( ! strncmp ( vname , " prefix3 " , 7 ) ) {
if ( sp ) strlcpy ( sp , SettingsText ( SET_MQTTPREFIX3 ) , glob_script_mem . max_ssize ) ;
2019-05-18 08:45:04 +01:00
goto strexit ;
}
2020-09-11 14:44:16 +01:00
if ( ! strncmp ( vname , " pow( " , 4 ) ) {
2019-05-18 08:45:04 +01:00
// arg1
float fvar1 ;
2020-09-11 14:44:16 +01:00
lp = GetNumericArgument ( lp + 4 , OPER_EQU , & fvar1 , 0 ) ;
2019-05-18 08:45:04 +01:00
SCRIPT_SKIP_SPACES
// arg2
float fvar2 ;
2020-09-11 14:44:16 +01:00
lp = GetNumericArgument ( lp , OPER_EQU , & fvar2 , 0 ) ;
2019-05-18 08:45:04 +01:00
lp + + ;
2020-09-11 14:44:16 +01:00
fvar = FastPrecisePowf ( fvar1 , fvar2 ) ;
len = 0 ;
2019-05-18 08:45:04 +01:00
goto exit ;
}
2020-09-11 14:44:16 +01:00
if ( ! strncmp ( vname , " pwr[ " , 4 ) ) {
GetNumericArgument ( vname + 4 , OPER_EQU , & fvar , 0 ) ;
uint8_t index = fvar ;
2020-10-30 11:29:48 +00:00
if ( index < = TasmotaGlobal . devices_present ) {
2020-10-28 18:03:39 +00:00
fvar = bitRead ( TasmotaGlobal . power , index - 1 ) ;
2019-05-18 08:45:04 +01:00
} else {
2020-09-11 14:44:16 +01:00
fvar = - 1 ;
2019-05-18 08:45:04 +01:00
}
2020-09-11 14:44:16 +01:00
len + = 1 ;
2019-05-18 08:45:04 +01:00
goto exit ;
}
2020-09-11 14:44:16 +01:00
if ( ! strncmp ( vname , " pc[ " , 3 ) ) {
GetNumericArgument ( vname + 3 , OPER_EQU , & fvar , 0 ) ;
uint8_t index = fvar ;
if ( index < 1 | | index > MAX_COUNTERS ) index = 1 ;
fvar = RtcSettings . pulse_counter [ index - 1 ] ;
len + = 1 ;
2019-07-16 15:50:52 +01:00
goto exit ;
}
2019-05-18 08:45:04 +01:00
break ;
2019-07-16 15:50:52 +01:00
2019-05-18 08:45:04 +01:00
case ' r ' :
2020-09-11 14:44:16 +01:00
if ( ! strncmp ( vname , " ram " , 3 ) ) {
fvar = glob_script_mem . script_mem_size + ( glob_script_mem . script_size ) + ( PMEM_SIZE ) ;
2019-05-18 08:45:04 +01:00
goto exit ;
}
2020-09-11 14:44:16 +01:00
if ( ! strncmp ( vname , " rnd( " , 4 ) ) {
2020-06-08 08:24:49 +01:00
// tasmota switch state
2020-09-11 14:44:16 +01:00
GetNumericArgument ( vname + 4 , OPER_EQU , & fvar , 0 ) ;
2020-06-08 08:24:49 +01:00
if ( fvar < 0 ) {
randomSeed ( - fvar ) ;
2020-09-11 14:44:16 +01:00
fvar = 0 ;
2020-06-08 08:24:49 +01:00
} else {
2020-09-11 14:44:16 +01:00
fvar = random ( fvar ) ;
2020-06-08 08:24:49 +01:00
}
// skip ] bracket
len + + ;
goto exit ;
}
2020-12-26 08:45:59 +00:00
# if defined(ESP32) && (defined(USE_M5STACK_CORE2))
if ( ! strncmp ( vname , " rec( " , 4 ) ) {
char str [ SCRIPT_MAXSSIZE ] ;
lp = GetStringArgument ( lp + 4 , OPER_EQU , str , 0 ) ;
SCRIPT_SKIP_SPACES
lp = GetNumericArgument ( lp , OPER_EQU , & fvar , 0 ) ;
fvar = i2s_record ( str , fvar ) ;
len + + ;
goto exit ;
}
# endif
2019-05-18 08:45:04 +01:00
break ;
case ' s ' :
2020-09-11 14:44:16 +01:00
if ( ! strncmp ( vname , " secs " , 4 ) ) {
fvar = RtcTime . second ;
2019-05-18 08:45:04 +01:00
goto exit ;
}
2020-09-11 14:44:16 +01:00
if ( ! strncmp ( vname , " sw[ " , 3 ) ) {
2019-05-18 08:45:04 +01:00
// tasmota switch state
2020-09-11 14:44:16 +01:00
GetNumericArgument ( vname + 3 , OPER_EQU , & fvar , 0 ) ;
fvar = SwitchLastState ( ( uint32_t ) fvar ) ;
2019-05-18 08:45:04 +01:00
// skip ] bracket
len + + ;
goto exit ;
}
2020-09-11 14:44:16 +01:00
if ( ! strncmp ( vname , " stack " , 5 ) ) {
fvar = GetStack ( ) ;
2019-05-18 08:45:04 +01:00
goto exit ;
}
2021-01-20 07:49:10 +00:00
# ifdef ESP32
if ( ! strncmp ( vname , " stkwm " , 5 ) ) {
fvar = uxTaskGetStackHighWaterMark ( NULL ) ;
goto exit ;
}
# endif // ESP32
2020-09-11 14:44:16 +01:00
if ( ! strncmp ( vname , " slen " , 4 ) ) {
fvar = strlen ( glob_script_mem . script_ram ) ;
2019-05-18 08:45:04 +01:00
goto exit ;
}
2020-09-11 14:44:16 +01:00
if ( ! strncmp ( vname , " sl( " , 3 ) ) {
2019-08-19 07:20:51 +01:00
char str [ SCRIPT_MAXSSIZE ] ;
2020-09-11 14:44:16 +01:00
lp = GetStringArgument ( lp + 3 , OPER_EQU , str , 0 ) ;
2019-08-19 07:20:51 +01:00
lp + + ;
2020-09-11 14:44:16 +01:00
len = 0 ;
fvar = strlen ( str ) ;
2019-08-19 07:20:51 +01:00
goto exit ;
}
2020-09-11 14:44:16 +01:00
if ( ! strncmp ( vname , " sb( " , 3 ) ) {
2019-08-19 07:20:51 +01:00
char str [ SCRIPT_MAXSSIZE ] ;
2020-09-11 14:44:16 +01:00
lp = GetStringArgument ( lp + 3 , OPER_EQU , str , 0 ) ;
2019-08-19 07:20:51 +01:00
SCRIPT_SKIP_SPACES
float fvar1 ;
2020-09-11 14:44:16 +01:00
lp = GetNumericArgument ( lp , OPER_EQU , & fvar1 , 0 ) ;
2019-08-19 07:20:51 +01:00
SCRIPT_SKIP_SPACES
float fvar2 ;
2020-09-11 14:44:16 +01:00
lp = GetNumericArgument ( lp , OPER_EQU , & fvar2 , 0 ) ;
2019-08-19 07:20:51 +01:00
lp + + ;
2020-09-11 14:44:16 +01:00
len = 0 ;
2019-08-19 07:20:51 +01:00
if ( fvar1 < 0 ) {
2020-09-11 14:44:16 +01:00
fvar1 = strlen ( str ) + fvar1 ;
2019-08-19 07:20:51 +01:00
}
2020-09-11 14:44:16 +01:00
memcpy ( sp , & str [ ( uint8_t ) fvar1 ] , ( uint8_t ) fvar2 ) ;
2019-08-19 07:20:51 +01:00
sp [ ( uint8_t ) fvar2 ] = ' \0 ' ;
goto strexit ;
}
2020-09-11 14:44:16 +01:00
if ( ! strncmp ( vname , " st( " , 3 ) ) {
2019-05-22 11:33:51 +01:00
char str [ SCRIPT_MAXSSIZE ] ;
2020-09-11 14:44:16 +01:00
lp = GetStringArgument ( lp + 3 , OPER_EQU , str , 0 ) ;
2019-05-22 11:33:51 +01:00
while ( * lp = = ' ' ) lp + + ;
char token [ 2 ] ;
2020-09-11 14:44:16 +01:00
token [ 0 ] = * lp + + ;
token [ 1 ] = 0 ;
2019-05-22 11:33:51 +01:00
while ( * lp = = ' ' ) lp + + ;
2020-09-11 14:44:16 +01:00
lp = GetNumericArgument ( lp , OPER_EQU , & fvar , 0 ) ;
2019-05-22 11:33:51 +01:00
// skip ) bracket
lp + + ;
2020-09-11 14:44:16 +01:00
len = 0 ;
2019-05-22 11:33:51 +01:00
if ( sp ) {
// get stringtoken
2020-09-11 14:44:16 +01:00
char * st = strtok ( str , token ) ;
2019-05-22 11:33:51 +01:00
if ( ! st ) {
2020-09-11 14:44:16 +01:00
* sp = 0 ;
2019-05-22 11:33:51 +01:00
} else {
2020-09-11 14:44:16 +01:00
for ( uint8_t cnt = 1 ; cnt < = fvar ; cnt + + ) {
2019-05-22 11:33:51 +01:00
if ( cnt = = fvar ) {
2020-09-11 14:44:16 +01:00
strcpy ( sp , st ) ;
2019-05-22 11:33:51 +01:00
break ;
}
2020-09-11 14:44:16 +01:00
st = strtok ( NULL , token ) ;
2019-05-22 11:33:51 +01:00
if ( ! st ) {
2020-09-11 14:44:16 +01:00
* sp = 0 ;
2019-05-22 11:33:51 +01:00
break ;
}
}
}
}
goto strexit ;
}
2020-09-11 14:44:16 +01:00
if ( ! strncmp ( vname , " s( " , 2 ) ) {
lp = GetNumericArgument ( lp + 2 , OPER_EQU , & fvar , 0 ) ;
char str [ glob_script_mem . max_ssize + 1 ] ;
2020-09-23 11:51:35 +01:00
f2char ( fvar , glob_script_mem . script_dprec , glob_script_mem . script_lzero , str ) ;
2020-09-11 14:44:16 +01:00
if ( sp ) strlcpy ( sp , str , glob_script_mem . max_ssize ) ;
2019-05-30 12:23:54 +01:00
lp + + ;
2020-09-11 14:44:16 +01:00
len = 0 ;
2019-05-30 12:23:54 +01:00
goto strexit ;
}
2020-12-18 09:35:14 +00:00
# if defined(ESP32) && (defined(USE_I2S_AUDIO) || defined(USE_TTGO_WATCH) || defined(USE_M5STACK_CORE2))
2020-09-11 14:44:16 +01:00
if ( ! strncmp ( vname , " say( " , 4 ) ) {
2020-08-13 15:04:30 +01:00
char text [ SCRIPT_MAXSSIZE ] ;
2020-09-11 14:44:16 +01:00
lp = GetStringArgument ( lp + 4 , OPER_EQU , text , 0 ) ;
2020-08-13 15:04:30 +01:00
Say ( text ) ;
len + + ;
2020-09-11 14:44:16 +01:00
len = 0 ;
2020-08-13 15:04:30 +01:00
goto exit ;
}
# endif // USE_I2S_AUDIO
2020-05-10 16:51:22 +01:00
# ifdef ESP32
2020-09-11 14:44:16 +01:00
if ( ! strncmp ( vname , " sf( " , 3 ) ) {
lp = GetNumericArgument ( lp + 3 , OPER_EQU , & fvar , 0 ) ;
if ( fvar < 80 ) fvar = 80 ;
if ( fvar > 240 ) fvar = 240 ;
2020-05-10 16:51:22 +01:00
setCpuFrequencyMhz ( fvar ) ;
2020-09-11 14:44:16 +01:00
fvar = getCpuFrequencyMhz ( ) ;
2020-05-10 16:51:22 +01:00
lp + + ;
2020-09-11 14:44:16 +01:00
len = 0 ;
2020-05-10 16:51:22 +01:00
goto exit ;
}
2020-09-11 14:44:16 +01:00
# endif //ESP32
2020-08-29 10:34:00 +01:00
# ifdef USE_TTGO_WATCH
2020-09-11 14:44:16 +01:00
if ( ! strncmp ( vname , " slp( " , 4 ) ) {
lp = GetNumericArgument ( lp + 4 , OPER_EQU , & fvar , 0 ) ;
2020-08-29 10:34:00 +01:00
SCRIPT_SKIP_SPACES
TTGO_Sleep ( fvar ) ;
lp + + ;
2020-09-11 14:44:16 +01:00
len = 0 ;
2020-08-29 10:34:00 +01:00
goto exit ;
}
2020-09-11 14:44:16 +01:00
# endif //USE_TTGO_WATCH
2019-05-18 08:45:04 +01:00
# if defined(USE_TIMERS) && defined(USE_SUNRISE)
2020-09-11 14:44:16 +01:00
if ( ! strncmp ( vname , " sunrise " , 7 ) ) {
fvar = SunMinutes ( 0 ) ;
2019-05-18 08:45:04 +01:00
goto exit ;
}
2020-09-11 14:44:16 +01:00
if ( ! strncmp ( vname , " sunset " , 6 ) ) {
fvar = SunMinutes ( 1 ) ;
2019-05-18 08:45:04 +01:00
goto exit ;
}
2020-09-11 14:44:16 +01:00
# endif //USE_TIMERS
2019-09-30 09:41:04 +01:00
# ifdef USE_SHUTTER
2020-09-11 14:44:16 +01:00
if ( ! strncmp ( vname , " sht[ " , 4 ) ) {
GetNumericArgument ( vname + 4 , OPER_EQU , & fvar , 0 ) ;
uint8_t index = fvar ;
2020-10-30 11:29:48 +00:00
if ( index < = TasmotaGlobal . shutters_present ) {
2020-09-11 14:44:16 +01:00
fvar = Settings . shutter_position [ index - 1 ] ;
2019-09-30 09:41:04 +01:00
} else {
2020-09-11 14:44:16 +01:00
fvar = - 1 ;
2019-09-30 09:41:04 +01:00
}
2020-09-11 14:44:16 +01:00
len + = 1 ;
2019-09-30 09:41:04 +01:00
goto exit ;
}
2020-09-11 14:44:16 +01:00
# endif //USE_SHUTTER
2019-11-27 16:15:41 +00:00
# ifdef USE_ANGLE_FUNC
2020-09-11 14:44:16 +01:00
if ( ! strncmp ( vname , " sin( " , 4 ) ) {
lp = GetNumericArgument ( lp + 4 , OPER_EQU , & fvar , 0 ) ;
fvar = sinf ( fvar ) ;
2019-11-27 16:15:41 +00:00
lp + + ;
2020-09-11 14:44:16 +01:00
len = 0 ;
2019-11-27 16:15:41 +00:00
goto exit ;
}
2020-09-11 14:44:16 +01:00
if ( ! strncmp ( vname , " sqrt( " , 5 ) ) {
lp = GetNumericArgument ( lp + 5 , OPER_EQU , & fvar , 0 ) ;
fvar = sqrtf ( fvar ) ;
2019-11-27 16:15:41 +00:00
lp + + ;
2020-09-11 14:44:16 +01:00
len = 0 ;
2019-11-27 16:15:41 +00:00
goto exit ;
}
2020-09-11 14:44:16 +01:00
# endif //USE_ANGLE_FUNC
2020-05-25 14:49:03 +01:00
2020-05-02 07:10:23 +01:00
# if defined(USE_SML_M) && defined (USE_SML_SCRIPT_CMD)
2020-09-11 14:44:16 +01:00
if ( ! strncmp ( vname , " sml[ " , 4 ) ) {
lp = GetNumericArgument ( lp + 4 , OPER_EQU , & fvar , 0 ) ;
2020-05-23 09:24:08 +01:00
SCRIPT_SKIP_SPACES
2020-09-11 14:44:16 +01:00
fvar = SML_GetVal ( fvar ) ;
2020-05-23 09:24:08 +01:00
lp + + ;
2020-09-11 14:44:16 +01:00
len = 0 ;
2020-05-23 09:24:08 +01:00
goto exit ;
}
2020-09-11 14:44:16 +01:00
if ( ! strncmp ( vname , " sml( " , 4 ) ) {
2020-02-04 06:07:56 +00:00
float fvar1 ;
2020-09-11 14:44:16 +01:00
lp = GetNumericArgument ( lp + 4 , OPER_EQU , & fvar1 , 0 ) ;
2020-02-04 06:07:56 +00:00
SCRIPT_SKIP_SPACES
float fvar2 ;
2020-09-11 14:44:16 +01:00
lp = GetNumericArgument ( lp , OPER_EQU , & fvar2 , 0 ) ;
2020-02-04 06:07:56 +00:00
SCRIPT_SKIP_SPACES
if ( fvar2 = = 0 ) {
float fvar3 ;
2020-09-11 14:44:16 +01:00
lp = GetNumericArgument ( lp , OPER_EQU , & fvar3 , 0 ) ;
fvar = SML_SetBaud ( fvar1 , fvar3 ) ;
2020-03-29 15:29:22 +01:00
} else if ( fvar2 = = 1 ) {
2020-02-04 06:07:56 +00:00
char str [ SCRIPT_MAXSSIZE ] ;
2020-09-11 14:44:16 +01:00
lp = GetStringArgument ( lp , OPER_EQU , str , 0 ) ;
fvar = SML_Write ( fvar1 , str ) ;
2020-07-15 08:44:52 +01:00
} else if ( fvar2 = = 2 ) {
char str [ SCRIPT_MAXSSIZE ] ;
2020-09-11 14:44:16 +01:00
str [ 0 ] = 0 ;
fvar = SML_Read ( fvar1 , str , SCRIPT_MAXSSIZE ) ;
if ( sp ) strlcpy ( sp , str , glob_script_mem . max_ssize ) ;
2020-07-15 08:44:52 +01:00
lp + + ;
2020-09-11 14:44:16 +01:00
len = 0 ;
2020-07-15 08:44:52 +01:00
goto strexit ;
2020-03-29 15:29:22 +01:00
} else {
# ifdef ED300L
2020-09-11 14:44:16 +01:00
fvar = SML_Status ( fvar1 ) ;
2020-03-29 15:29:22 +01:00
# else
2020-09-11 14:44:16 +01:00
fvar = 0 ;
# endif //ED300L
2020-02-04 06:07:56 +00:00
}
lp + + ;
2020-09-11 14:44:16 +01:00
len = 0 ;
2020-02-04 06:07:56 +00:00
goto exit ;
}
2020-09-11 14:44:16 +01:00
# endif //USE_SML_M
2019-05-18 08:45:04 +01:00
break ;
case ' t ' :
2020-09-11 14:44:16 +01:00
if ( ! strncmp ( vname , " time " , 4 ) ) {
fvar = MinutesPastMidnight ( ) ;
2019-05-18 08:45:04 +01:00
goto exit ;
}
2020-09-11 14:44:16 +01:00
if ( ! strncmp ( vname , " tper " , 4 ) ) {
fvar = Settings . tele_period ;
tind - > index = SCRIPT_TELEPERIOD ;
2019-05-18 08:45:04 +01:00
goto exit_settable ;
}
2020-09-11 14:44:16 +01:00
if ( ! strncmp ( vname , " tinit " , 5 ) ) {
2020-10-29 12:58:50 +00:00
fvar = TasmotaGlobal . rules_flag . time_init ;
2019-05-18 08:45:04 +01:00
goto exit ;
}
2020-09-11 14:44:16 +01:00
if ( ! strncmp ( vname , " tset " , 4 ) ) {
2020-10-29 12:58:50 +00:00
fvar = TasmotaGlobal . rules_flag . time_set ;
2019-05-18 08:45:04 +01:00
goto exit ;
}
2020-09-11 14:44:16 +01:00
if ( ! strncmp ( vname , " tstamp " , 6 ) ) {
if ( sp ) strlcpy ( sp , GetDateAndTime ( DT_LOCAL ) . c_str ( ) , glob_script_mem . max_ssize ) ;
2019-05-18 08:45:04 +01:00
goto strexit ;
}
2020-09-11 14:44:16 +01:00
if ( ! strncmp ( vname , " topic " , 5 ) ) {
if ( sp ) strlcpy ( sp , SettingsText ( SET_MQTT_TOPIC ) , glob_script_mem . max_ssize ) ;
2019-05-18 08:45:04 +01:00
goto strexit ;
}
2020-06-15 16:20:50 +01:00
# ifdef USE_SCRIPT_TIMER
2020-09-11 14:44:16 +01:00
if ( ! strncmp ( vname , " ts1( " , 4 ) ) {
lp = GetNumericArgument ( lp + 4 , OPER_EQU , & fvar , 0 ) ;
if ( fvar < 10 ) fvar = 10 ;
2020-06-15 16:20:50 +01:00
Script_ticker1 . attach_ms ( fvar , Script_ticker1_end ) ;
lp + + ;
2020-09-11 14:44:16 +01:00
len = 0 ;
2020-06-15 16:20:50 +01:00
goto exit ;
}
2020-09-11 14:44:16 +01:00
if ( ! strncmp ( vname , " ts2( " , 4 ) ) {
lp = GetNumericArgument ( lp + 4 , OPER_EQU , & fvar , 0 ) ;
if ( fvar < 10 ) fvar = 10 ;
2020-06-15 16:20:50 +01:00
Script_ticker2 . attach_ms ( fvar , Script_ticker2_end ) ;
lp + + ;
2020-09-11 14:44:16 +01:00
len = 0 ;
2020-06-15 16:20:50 +01:00
goto exit ;
}
2020-09-11 14:44:16 +01:00
if ( ! strncmp ( vname , " ts3( " , 4 ) ) {
lp = GetNumericArgument ( lp + 4 , OPER_EQU , & fvar , 0 ) ;
if ( fvar < 10 ) fvar = 10 ;
2020-06-15 16:20:50 +01:00
Script_ticker3 . attach_ms ( fvar , Script_ticker3_end ) ;
lp + + ;
2020-09-11 14:44:16 +01:00
len = 0 ;
2020-06-15 16:20:50 +01:00
goto exit ;
}
2020-09-11 14:44:16 +01:00
if ( ! strncmp ( vname , " ts4( " , 4 ) ) {
lp = GetNumericArgument ( lp + 4 , OPER_EQU , & fvar , 0 ) ;
if ( fvar < 10 ) fvar = 10 ;
2020-06-15 16:20:50 +01:00
Script_ticker4 . attach_ms ( fvar , Script_ticker4_end ) ;
lp + + ;
2020-09-11 14:44:16 +01:00
len = 0 ;
2020-06-15 16:20:50 +01:00
goto exit ;
}
# endif // USE_SCRIPT_TIMER
2019-08-31 09:10:16 +01:00
# ifdef USE_DISPLAY
2019-07-09 09:20:11 +01:00
# ifdef USE_TOUCH_BUTTONS
2020-09-11 14:44:16 +01:00
if ( ! strncmp ( vname , " tbut[ " , 5 ) ) {
GetNumericArgument ( vname + 5 , OPER_EQU , & fvar , 0 ) ;
uint8_t index = fvar ;
2021-01-20 14:12:41 +00:00
if ( index < 1 | | index > MAX_TOUCH_BUTTONS ) index = 1 ;
2019-07-09 09:20:11 +01:00
index - - ;
if ( buttons [ index ] ) {
2020-09-11 14:44:16 +01:00
fvar = buttons [ index ] - > vpower . on_off ;
2019-07-09 09:20:11 +01:00
} else {
2020-09-11 14:44:16 +01:00
fvar = - 1 ;
2019-07-09 09:20:11 +01:00
}
2020-09-11 14:44:16 +01:00
len + = 1 ;
2019-07-09 09:20:11 +01:00
goto exit ;
}
2020-09-11 14:44:16 +01:00
# endif //USE_TOUCH_BUTTONS
# endif //USE_DISPLAY
2021-01-20 07:49:10 +00:00
# if 1
if ( ! strncmp ( vname , " test( " , 5 ) ) {
lp = GetNumericArgument ( lp + 5 , OPER_EQU , & fvar , 0 ) ;
uint32_t cycles ;
uint64_t accu = 0 ;
char sbuffer [ 32 ] ;
// PSTR performance test
// this is best case since everything will be in cache
// PSTR at least 3 times slower here, will be much slower if cache missed
for ( uint16 cnt = 0 ; cnt < 1000 ; cnt + + ) {
cycles = ESP . getCycleCount ( ) ;
if ( fvar > 0 ) {
snprintf_P ( sbuffer , sizeof ( sbuffer ) , PSTR ( " 1234 " ) ) ;
} else {
snprintf ( sbuffer , sizeof ( sbuffer ) , " 1234 " ) ;
}
accu + = ESP . getCycleCount ( ) - cycles ;
}
lp + + ;
len = 0 ;
fvar = accu / 1000 ;
goto exit ;
}
# endif
2019-05-18 08:45:04 +01:00
break ;
case ' u ' :
2020-09-11 14:44:16 +01:00
if ( ! strncmp ( vname , " uptime " , 6 ) ) {
fvar = MinutesUptime ( ) ;
2019-05-18 08:45:04 +01:00
goto exit ;
}
2020-09-11 14:44:16 +01:00
if ( ! strncmp ( vname , " upsecs " , 6 ) ) {
2020-10-28 16:32:07 +00:00
fvar = TasmotaGlobal . uptime ;
2019-05-18 08:45:04 +01:00
goto exit ;
}
2020-09-11 14:44:16 +01:00
if ( ! strncmp ( vname , " upd[ " , 4 ) ) {
2019-05-18 08:45:04 +01:00
// var was updated
struct T_INDEX ind ;
uint8_t vtype ;
2020-09-11 14:44:16 +01:00
isvar ( vname + 4 , & vtype , & ind , 0 , 0 , 0 ) ;
2019-05-18 08:45:04 +01:00
if ( ! ind . bits . constant ) {
if ( ! ind . bits . changed ) {
2020-09-11 14:44:16 +01:00
fvar = 0 ;
2019-05-18 08:45:04 +01:00
len + + ;
goto exit ;
} else {
2020-09-11 14:44:16 +01:00
glob_script_mem . type [ ind . index ] . bits . changed = 0 ;
fvar = 1 ;
2019-05-18 08:45:04 +01:00
len + + ;
goto exit ;
}
}
goto notfound ;
}
break ;
2019-07-09 09:20:11 +01:00
2019-05-18 08:45:04 +01:00
case ' w ' :
2020-05-02 07:10:23 +01:00
# if defined(ESP32) && defined(USE_WEBCAM)
2020-09-11 14:44:16 +01:00
if ( ! strncmp ( vname , " wc( " , 3 ) ) {
2020-05-02 07:10:23 +01:00
float fvar1 ;
2020-09-11 14:44:16 +01:00
lp = GetNumericArgument ( lp + 3 , OPER_EQU , & fvar1 , 0 ) ;
2020-05-02 07:10:23 +01:00
SCRIPT_SKIP_SPACES
switch ( ( uint32 ) fvar1 ) {
case 0 :
{ float fvar2 ;
2020-09-11 14:44:16 +01:00
lp = GetNumericArgument ( lp , OPER_EQU , & fvar2 , 0 ) ;
fvar = WcSetup ( fvar2 ) ;
2020-05-02 07:10:23 +01:00
}
break ;
case 1 :
{ float fvar2 ;
2020-09-11 14:44:16 +01:00
lp = GetNumericArgument ( lp , OPER_EQU , & fvar2 , 0 ) ;
fvar = WcGetFrame ( fvar2 ) ;
2020-05-02 07:10:23 +01:00
}
break ;
case 2 :
{ float fvar2 , fvar3 ;
2020-09-11 14:44:16 +01:00
lp = GetNumericArgument ( lp , OPER_EQU , & fvar2 , 0 ) ;
2020-05-02 07:10:23 +01:00
SCRIPT_SKIP_SPACES
2020-09-11 14:44:16 +01:00
lp = GetNumericArgument ( lp , OPER_EQU , & fvar3 , 0 ) ;
fvar = WcSetOptions ( fvar2 , fvar3 ) ;
2020-05-02 07:10:23 +01:00
}
break ;
case 3 :
2020-09-11 14:44:16 +01:00
fvar = WcGetWidth ( ) ;
2020-05-02 07:10:23 +01:00
break ;
case 4 :
2020-09-11 14:44:16 +01:00
fvar = WcGetHeight ( ) ;
2020-05-02 07:10:23 +01:00
break ;
case 5 :
{ float fvar2 ;
2020-09-11 14:44:16 +01:00
lp = GetNumericArgument ( lp , OPER_EQU , & fvar2 , 0 ) ;
fvar = WcSetStreamserver ( fvar2 ) ;
2020-05-02 07:10:23 +01:00
}
break ;
case 6 :
{ float fvar2 ;
2020-09-11 14:44:16 +01:00
lp = GetNumericArgument ( lp , OPER_EQU , & fvar2 , 0 ) ;
fvar = WcSetMotionDetect ( fvar2 ) ;
2020-05-02 07:10:23 +01:00
}
break ;
2020-05-05 08:36:43 +01:00
# ifdef USE_FACE_DETECT
case 7 :
{ float fvar2 ;
2020-09-11 14:44:16 +01:00
lp = GetNumericArgument ( lp , OPER_EQU , & fvar2 , 0 ) ;
fvar = WcSetFaceDetect ( fvar2 ) ;
2020-05-05 08:36:43 +01:00
}
break ;
2020-09-11 14:44:16 +01:00
# endif //USE_FACE_DETECT
2020-05-02 07:10:23 +01:00
default :
2020-09-11 14:44:16 +01:00
fvar = 0 ;
2020-05-02 07:10:23 +01:00
}
lp + + ;
2020-09-11 14:44:16 +01:00
len = 0 ;
2020-05-02 07:10:23 +01:00
goto exit ;
}
2020-05-10 16:51:22 +01:00
# endif //ESP32, USE_WEBCAM
2020-08-29 10:34:00 +01:00
# if defined(USE_TTGO_WATCH) && defined(USE_BMA423)
2020-09-11 14:44:16 +01:00
if ( ! strncmp ( vname , " wdclk " , 5 ) ) {
fvar = TTGO_doubleclick ( ) ;
2020-08-29 10:34:00 +01:00
goto exit ;
}
2020-09-11 14:44:16 +01:00
if ( ! strncmp ( vname , " wbut " , 4 ) ) {
fvar = TTGO_button ( ) ;
2020-08-29 10:34:00 +01:00
goto exit ;
}
# endif // USE_TTGO_WATCH
2020-12-18 09:35:14 +00:00
# if defined(USE_FT5206)
2020-09-11 14:44:16 +01:00
if ( ! strncmp ( vname , " wtch( " , 5 ) ) {
lp = GetNumericArgument ( lp + 5 , OPER_EQU , & fvar , 0 ) ;
fvar = Touch_Status ( fvar ) ;
2020-08-29 10:34:00 +01:00
lp + + ;
2020-09-11 14:44:16 +01:00
len = 0 ;
2020-08-29 10:34:00 +01:00
goto exit ;
}
# endif // USE_FT5206
2020-10-23 06:45:35 +01:00
if ( ! strncmp ( vname , " wm " , 2 ) ) {
fvar = glob_script_mem . web_mode ;
goto exit ;
}
2020-09-11 14:44:16 +01:00
if ( ! strncmp ( vname , " wday " , 4 ) ) {
fvar = RtcTime . day_of_week ;
2019-05-18 08:45:04 +01:00
goto exit ;
}
2020-09-11 14:44:16 +01:00
if ( ! strncmp ( vname , " wific " , 5 ) ) {
2020-10-29 12:58:50 +00:00
if ( TasmotaGlobal . rules_flag . wifi_connected ) {
TasmotaGlobal . rules_flag . wifi_connected = 0 ;
2020-09-11 14:44:16 +01:00
fvar = 1 ;
2019-05-18 08:45:04 +01:00
}
goto exit ;
}
2020-09-11 14:44:16 +01:00
if ( ! strncmp ( vname , " wifid " , 5 ) ) {
2020-10-29 12:58:50 +00:00
if ( TasmotaGlobal . rules_flag . wifi_disconnected ) {
TasmotaGlobal . rules_flag . wifi_disconnected = 0 ;
2020-09-11 14:44:16 +01:00
fvar = 1 ;
2019-05-18 08:45:04 +01:00
}
goto exit ;
}
2020-09-11 14:44:16 +01:00
if ( ! strncmp ( vname , " wifis " , 5 ) ) {
2020-10-30 11:29:48 +00:00
fvar = ! TasmotaGlobal . global_state . wifi_down ;
2019-05-18 08:45:04 +01:00
goto exit ;
}
break ;
case ' y ' :
2020-09-11 14:44:16 +01:00
if ( ! strncmp ( vname , " year " , 4 ) ) {
fvar = RtcTime . year ;
2019-05-18 08:45:04 +01:00
goto exit ;
}
break ;
default :
break ;
}
// nothing valid found
notfound :
if ( fp ) * fp = 0 ;
2020-09-11 14:44:16 +01:00
* vtype = VAR_NV ;
tind - > index = VAR_NV ;
glob_script_mem . var_not_found = 1 ;
2019-05-18 08:45:04 +01:00
return lp ;
// return constant numbers
exit :
2020-09-11 14:44:16 +01:00
if ( fp ) * fp = fvar ;
* vtype = NUM_RES ;
tind - > bits . constant = 1 ;
tind - > bits . is_string = 0 ;
return lp + len ;
2019-05-18 08:45:04 +01:00
// return constant strings
strexit :
2020-09-11 14:44:16 +01:00
* vtype = STYPE ;
tind - > bits . constant = 1 ;
tind - > bits . is_string = 1 ;
return lp + len ;
2019-05-18 08:45:04 +01:00
}
char * getop ( char * lp , uint8_t * operand ) {
switch ( * lp ) {
case ' = ' :
2020-09-11 14:44:16 +01:00
if ( * ( lp + 1 ) = = ' = ' ) {
* operand = OPER_EQUEQU ;
return lp + 2 ;
2019-05-18 08:45:04 +01:00
} else {
2020-09-11 14:44:16 +01:00
* operand = OPER_EQU ;
return lp + 1 ;
2019-05-18 08:45:04 +01:00
}
break ;
case ' + ' :
2020-09-11 14:44:16 +01:00
if ( * ( lp + 1 ) = = ' = ' ) {
* operand = OPER_PLSEQU ;
return lp + 2 ;
2019-05-18 08:45:04 +01:00
} else {
2020-09-11 14:44:16 +01:00
* operand = OPER_PLS ;
return lp + 1 ;
2019-05-18 08:45:04 +01:00
}
break ;
case ' - ' :
2020-09-11 14:44:16 +01:00
if ( * ( lp + 1 ) = = ' = ' ) {
* operand = OPER_MINEQU ;
return lp + 2 ;
2019-05-18 08:45:04 +01:00
} else {
2020-09-11 14:44:16 +01:00
* operand = OPER_MIN ;
return lp + 1 ;
2019-05-18 08:45:04 +01:00
}
break ;
case ' * ' :
2020-09-11 14:44:16 +01:00
if ( * ( lp + 1 ) = = ' = ' ) {
* operand = OPER_MULEQU ;
return lp + 2 ;
2019-05-18 08:45:04 +01:00
} else {
2020-09-11 14:44:16 +01:00
* operand = OPER_MUL ;
return lp + 1 ;
2019-05-18 08:45:04 +01:00
}
break ;
case ' / ' :
2020-09-11 14:44:16 +01:00
if ( * ( lp + 1 ) = = ' = ' ) {
* operand = OPER_DIVEQU ;
return lp + 2 ;
2019-05-18 08:45:04 +01:00
} else {
2020-09-11 14:44:16 +01:00
* operand = OPER_DIV ;
return lp + 1 ;
2019-05-18 08:45:04 +01:00
}
break ;
case ' ! ' :
2020-09-11 14:44:16 +01:00
if ( * ( lp + 1 ) = = ' = ' ) {
* operand = OPER_NOTEQU ;
return lp + 2 ;
2019-05-18 08:45:04 +01:00
}
break ;
case ' > ' :
2020-09-11 14:44:16 +01:00
if ( * ( lp + 1 ) = = ' = ' ) {
* operand = OPER_GRTEQU ;
return lp + 2 ;
2019-05-18 08:45:04 +01:00
} else {
2020-09-11 14:44:16 +01:00
* operand = OPER_GRT ;
return lp + 1 ;
2019-05-18 08:45:04 +01:00
}
break ;
case ' < ' :
2020-09-11 14:44:16 +01:00
if ( * ( lp + 1 ) = = ' = ' ) {
* operand = OPER_LOWEQU ;
return lp + 2 ;
2019-05-18 08:45:04 +01:00
} else {
2020-09-11 14:44:16 +01:00
* operand = OPER_LOW ;
return lp + 1 ;
2019-05-18 08:45:04 +01:00
}
break ;
case ' % ' :
2020-09-11 14:44:16 +01:00
if ( * ( lp + 1 ) = = ' = ' ) {
* operand = OPER_PERCEQU ;
return lp + 2 ;
2019-05-18 08:45:04 +01:00
} else {
2020-09-11 14:44:16 +01:00
* operand = OPER_PERC ;
return lp + 1 ;
2019-05-18 08:45:04 +01:00
}
break ;
case ' ^ ' :
2020-09-11 14:44:16 +01:00
if ( * ( lp + 1 ) = = ' = ' ) {
* operand = OPER_XOREQU ;
return lp + 2 ;
2019-05-18 08:45:04 +01:00
} else {
2020-09-11 14:44:16 +01:00
* operand = OPER_XOR ;
return lp + 1 ;
2019-05-18 08:45:04 +01:00
}
break ;
case ' & ' :
2020-09-11 14:44:16 +01:00
if ( * ( lp + 1 ) = = ' = ' ) {
* operand = OPER_ANDEQU ;
return lp + 2 ;
2019-05-18 08:45:04 +01:00
} else {
2020-09-11 14:44:16 +01:00
* operand = OPER_AND ;
return lp + 1 ;
2019-05-18 08:45:04 +01:00
}
break ;
case ' | ' :
2020-09-11 14:44:16 +01:00
if ( * ( lp + 1 ) = = ' = ' ) {
* operand = OPER_OREQU ;
return lp + 2 ;
2019-05-18 08:45:04 +01:00
} else {
2020-09-11 14:44:16 +01:00
* operand = OPER_OR ;
return lp + 1 ;
2019-05-18 08:45:04 +01:00
}
break ;
}
2020-09-11 14:44:16 +01:00
* operand = 0 ;
2019-05-18 08:45:04 +01:00
return lp ;
}
2020-04-12 12:22:23 +01:00
# ifdef ESP8266
2019-05-18 08:45:04 +01:00
extern " C " {
# include <cont.h>
extern cont_t * g_pcont ;
}
uint16_t GetStack ( void ) {
register uint32_t * sp asm ( " a1 " ) ;
return ( 4 * ( sp - g_pcont - > stack ) ) ;
}
2020-04-12 12:22:23 +01:00
# else
uint16_t GetStack ( void ) {
register uint8_t * sp asm ( " a1 " ) ;
return ( sp - pxTaskGetStackStart ( NULL ) ) ;
}
2020-09-11 14:44:16 +01:00
# endif //ESP8266
2019-05-18 08:45:04 +01:00
2020-09-25 07:52:28 +01:00
char * GetStringArgument ( char * lp , uint8_t lastop , char * cp , JsonParserObject * jo ) {
2020-09-11 14:44:16 +01:00
uint8_t operand = 0 ;
2019-05-18 08:45:04 +01:00
uint8_t vtype ;
char * slp ;
struct T_INDEX ind ;
char str [ SCRIPT_MAXSSIZE ] , str1 [ SCRIPT_MAXSSIZE ] ;
while ( 1 ) {
2020-09-11 14:44:16 +01:00
lp = isvar ( lp , & vtype , & ind , 0 , str1 , jo ) ;
if ( vtype ! = STR_RES & & ! ( vtype & STYPE ) ) {
2019-09-18 17:50:25 +01:00
// numeric type
2020-09-11 14:44:16 +01:00
glob_script_mem . glob_error = 1 ;
2019-09-18 17:50:25 +01:00
return lp ;
}
2019-05-18 08:45:04 +01:00
switch ( lastop ) {
case OPER_EQU :
2020-09-11 14:44:16 +01:00
strlcpy ( str , str1 , sizeof ( str ) ) ;
2019-05-18 08:45:04 +01:00
break ;
case OPER_PLS :
2020-09-11 14:44:16 +01:00
strncat ( str , str1 , sizeof ( str ) - strlen ( str1 ) ) ;
2019-05-18 08:45:04 +01:00
break ;
}
2020-09-11 14:44:16 +01:00
slp = lp ;
lp = getop ( lp , & operand ) ;
2019-05-18 08:45:04 +01:00
switch ( operand ) {
case OPER_EQUEQU :
case OPER_NOTEQU :
case OPER_LOW :
case OPER_LOWEQU :
case OPER_GRT :
case OPER_GRTEQU :
2020-09-11 14:44:16 +01:00
lp = slp ;
strcpy ( cp , str ) ;
2019-05-18 08:45:04 +01:00
return lp ;
break ;
default :
break ;
}
2020-09-11 14:44:16 +01:00
lastop = operand ;
2019-05-18 08:45:04 +01:00
if ( ! operand ) {
2020-09-11 14:44:16 +01:00
strcpy ( cp , str ) ;
2019-05-18 08:45:04 +01:00
return lp ;
}
}
2020-07-15 08:44:52 +01:00
return lp ;
2019-05-18 08:45:04 +01:00
}
2020-09-25 07:52:28 +01:00
char * GetNumericArgument ( char * lp , uint8_t lastop , float * fp , JsonParserObject * jo ) {
2020-09-11 14:44:16 +01:00
uint8_t operand = 0 ;
2019-05-18 08:45:04 +01:00
float fvar1 , fvar ;
char * slp ;
uint8_t vtype ;
struct T_INDEX ind ;
while ( 1 ) {
// get 1. value
if ( * lp = = ' ( ' ) {
lp + + ;
2020-09-11 14:44:16 +01:00
lp = GetNumericArgument ( lp , OPER_EQU , & fvar1 , jo ) ;
2019-05-18 08:45:04 +01:00
lp + + ;
//if (*lp==')') lp++;
} else {
2020-09-11 14:44:16 +01:00
lp = isvar ( lp , & vtype , & ind , & fvar1 , 0 , jo ) ;
if ( ( vtype ! = NUM_RES ) & & ( vtype & STYPE ) ) {
2019-05-18 08:45:04 +01:00
// string type
2020-09-11 14:44:16 +01:00
glob_script_mem . glob_error = 1 ;
2019-05-18 08:45:04 +01:00
}
}
switch ( lastop ) {
case OPER_EQU :
2020-09-11 14:44:16 +01:00
fvar = fvar1 ;
2019-05-18 08:45:04 +01:00
break ;
case OPER_PLS :
2020-09-11 14:44:16 +01:00
fvar + = fvar1 ;
2019-05-18 08:45:04 +01:00
break ;
case OPER_MIN :
2020-09-11 14:44:16 +01:00
fvar - = fvar1 ;
2019-05-18 08:45:04 +01:00
break ;
case OPER_MUL :
2020-09-11 14:44:16 +01:00
fvar * = fvar1 ;
2019-05-18 08:45:04 +01:00
break ;
case OPER_DIV :
2020-09-11 14:44:16 +01:00
fvar / = fvar1 ;
2019-05-18 08:45:04 +01:00
break ;
case OPER_PERC :
2020-09-11 14:44:16 +01:00
fvar = fmodf ( fvar , fvar1 ) ;
2019-05-18 08:45:04 +01:00
break ;
case OPER_XOR :
2020-09-11 14:44:16 +01:00
fvar = ( uint32_t ) fvar ^ ( uint32_t ) fvar1 ;
2019-05-18 08:45:04 +01:00
break ;
case OPER_AND :
2020-09-11 14:44:16 +01:00
fvar = ( uint32_t ) fvar & ( uint32_t ) fvar1 ;
2019-05-18 08:45:04 +01:00
break ;
case OPER_OR :
2020-09-11 14:44:16 +01:00
fvar = ( uint32_t ) fvar | ( uint32_t ) fvar1 ;
2019-05-18 08:45:04 +01:00
break ;
default :
break ;
2019-07-09 09:20:11 +01:00
2019-05-18 08:45:04 +01:00
}
2020-09-11 14:44:16 +01:00
slp = lp ;
lp = getop ( lp , & operand ) ;
2019-05-18 08:45:04 +01:00
switch ( operand ) {
case OPER_EQUEQU :
case OPER_NOTEQU :
case OPER_LOW :
case OPER_LOWEQU :
case OPER_GRT :
case OPER_GRTEQU :
2020-09-11 14:44:16 +01:00
lp = slp ;
* fp = fvar ;
2019-05-18 08:45:04 +01:00
return lp ;
break ;
default :
break ;
}
2020-09-11 14:44:16 +01:00
lastop = operand ;
2019-05-18 08:45:04 +01:00
if ( ! operand ) {
2020-09-11 14:44:16 +01:00
* fp = fvar ;
2019-05-18 08:45:04 +01:00
return lp ;
}
}
}
2020-09-11 14:44:16 +01:00
char * ForceStringVar ( char * lp , char * dstr ) {
2019-05-30 12:23:54 +01:00
float fvar ;
2020-09-11 14:44:16 +01:00
char * slp = lp ;
glob_script_mem . glob_error = 0 ;
lp = GetStringArgument ( lp , OPER_EQU , dstr , 0 ) ;
2019-09-18 17:50:25 +01:00
if ( glob_script_mem . glob_error ) {
2019-05-30 12:23:54 +01:00
// mismatch
2020-09-11 14:44:16 +01:00
lp = GetNumericArgument ( slp , OPER_EQU , & fvar , 0 ) ;
dtostrfd ( fvar , 6 , dstr ) ;
glob_script_mem . glob_error = 0 ;
2019-05-30 12:23:54 +01:00
}
return lp ;
}
2019-05-18 08:45:04 +01:00
// replace vars in cmd %var%
2020-09-11 14:44:16 +01:00
void Replace_Cmd_Vars ( char * srcbuf , uint32_t srcsize , char * dstbuf , uint32_t dstsize ) {
2019-05-18 08:45:04 +01:00
char * cp ;
uint16_t count ;
uint8_t vtype ;
2020-09-11 14:44:16 +01:00
uint8_t dprec = glob_script_mem . script_dprec ;
2020-09-23 11:51:35 +01:00
uint8_t lzero = glob_script_mem . script_lzero ;
2019-05-18 08:45:04 +01:00
float fvar ;
2020-09-11 14:44:16 +01:00
cp = srcbuf ;
2019-05-18 08:45:04 +01:00
struct T_INDEX ind ;
char string [ SCRIPT_MAXSSIZE ] ;
2020-09-11 14:44:16 +01:00
dstsize - = 2 ;
for ( count = 0 ; count < dstsize ; count + + ) {
2020-05-15 14:30:32 +01:00
if ( srcsize & & ( * cp = = SCRIPT_EOL ) ) break ;
2019-05-18 08:45:04 +01:00
if ( * cp = = ' % ' ) {
cp + + ;
if ( * cp = = ' % ' ) {
2020-09-11 14:44:16 +01:00
dstbuf [ count ] = * cp + + ;
2019-05-18 08:45:04 +01:00
} else {
2019-09-08 11:14:28 +01:00
if ( isdigit ( * cp ) ) {
2020-09-23 11:51:35 +01:00
if ( * ( cp + 1 ) = = ' . ' ) {
lzero = * cp & 0xf ;
cp + = 2 ;
}
2020-09-11 14:44:16 +01:00
dprec = * cp & 0xf ;
2019-09-08 11:14:28 +01:00
cp + + ;
2019-09-14 06:48:55 +01:00
} else {
2020-09-11 14:44:16 +01:00
dprec = glob_script_mem . script_dprec ;
2020-09-23 11:51:35 +01:00
lzero = glob_script_mem . script_lzero ;
2019-09-08 11:14:28 +01:00
}
2020-09-11 14:44:16 +01:00
if ( * cp = = ' ( ' ) {
// math expression
2019-05-18 08:45:04 +01:00
cp + + ;
2020-09-11 14:44:16 +01:00
cp = GetNumericArgument ( cp , OPER_EQU , & fvar , 0 ) ;
2020-09-23 11:51:35 +01:00
f2char ( fvar , dprec , lzero , string ) ;
2020-09-11 14:44:16 +01:00
uint8_t slen = strlen ( string ) ;
if ( count + slen < dstsize - 1 ) {
strcpy ( & dstbuf [ count ] , string ) ;
count + = slen - 1 ;
}
cp + = 2 ;
2019-05-18 08:45:04 +01:00
} else {
2020-09-11 14:44:16 +01:00
cp = isvar ( cp , & vtype , & ind , & fvar , string , 0 ) ;
if ( vtype ! = VAR_NV ) {
// found variable as result
if ( vtype = = NUM_RES | | ( vtype & STYPE ) = = 0 ) {
// numeric result
2020-09-23 11:51:35 +01:00
f2char ( fvar , dprec , lzero , string ) ;
2020-09-11 14:44:16 +01:00
} else {
// string result
}
uint8_t slen = strlen ( string ) ;
if ( count + slen < dstsize - 1 ) {
strcpy ( & dstbuf [ count ] , string ) ;
count + = slen - 1 ;
}
cp + + ;
} else {
strcpy ( & dstbuf [ count ] , " ??? " ) ;
count + = 2 ;
while ( * cp ! = ' % ' ) {
if ( * cp = = 0 | | * cp = = SCRIPT_EOL ) {
dstbuf [ count + 1 ] = 0 ;
return ;
}
cp + + ;
2019-05-18 08:45:04 +01:00
}
cp + + ;
}
}
}
} else {
2019-10-15 19:07:12 +01:00
if ( * cp = = ' \\ ' ) {
cp + + ;
if ( * cp = = ' n ' ) {
2020-09-11 14:44:16 +01:00
dstbuf [ count ] = ' \n ' ;
2019-10-15 19:07:12 +01:00
} else if ( * cp = = ' r ' ) {
2020-09-11 14:44:16 +01:00
dstbuf [ count ] = ' \r ' ;
2019-10-15 19:07:12 +01:00
} else if ( * cp = = ' \\ ' ) {
2020-09-11 14:44:16 +01:00
dstbuf [ count ] = ' \\ ' ;
2019-10-15 19:07:12 +01:00
} else {
2020-09-11 14:44:16 +01:00
dstbuf [ count ] = * cp ;
2019-10-15 19:07:12 +01:00
}
} else {
2020-09-11 14:44:16 +01:00
dstbuf [ count ] = * cp ;
2019-10-15 19:07:12 +01:00
}
2019-05-18 08:45:04 +01:00
if ( * cp = = 0 ) {
break ;
}
cp + + ;
}
}
2020-09-11 14:44:16 +01:00
dstbuf [ count ] = 0 ;
2019-05-18 08:45:04 +01:00
}
void toLog ( const char * str ) {
if ( ! str ) return ;
2021-01-01 05:43:50 +00:00
Script_AddLog_P ( LOG_LEVEL_INFO , str ) ;
2019-05-18 08:45:04 +01:00
}
2019-09-24 07:25:32 +01:00
2020-09-11 14:44:16 +01:00
void toLogN ( const char * cp , uint8_t len ) {
2019-05-18 08:45:04 +01:00
if ( ! cp ) return ;
char str [ 32 ] ;
2020-09-11 14:44:16 +01:00
if ( len > = sizeof ( str ) ) len = sizeof ( str ) ;
strlcpy ( str , cp , len ) ;
2019-05-18 08:45:04 +01:00
toSLog ( str ) ;
}
void toLogEOL ( const char * s1 , const char * str ) {
if ( ! str ) return ;
2020-09-11 14:44:16 +01:00
uint8_t index = 0 ;
2021-01-02 15:20:15 +00:00
char log_data [ MAX_LOGSZ ] ;
2020-12-23 17:00:59 +00:00
char * cp = log_data ;
2020-09-11 14:44:16 +01:00
strcpy ( cp , s1 ) ;
cp + = strlen ( s1 ) ;
2019-05-18 08:45:04 +01:00
while ( * str ) {
if ( * str = = SCRIPT_EOL ) break ;
2020-09-11 14:44:16 +01:00
* cp + + = * str + + ;
2019-05-18 08:45:04 +01:00
}
2020-09-11 14:44:16 +01:00
* cp = 0 ;
2020-12-23 17:00:59 +00:00
AddLogData ( LOG_LEVEL_INFO , log_data ) ;
2019-05-18 08:45:04 +01:00
}
void toSLog ( const char * str ) {
if ( ! str ) return ;
# if SCRIPT_DEBUG>0
while ( * str ) {
Serial . write ( * str ) ;
str + + ;
}
# endif
}
2020-09-25 07:52:28 +01:00
char * Evaluate_expression ( char * lp , uint8_t and_or , uint8_t * result , JsonParserObject * jo ) {
2019-08-05 12:01:23 +01:00
float fvar , * dfvar , fvar1 ;
uint8_t numeric ;
struct T_INDEX ind ;
2020-09-11 14:44:16 +01:00
uint8_t vtype = 0 , lastop ;
uint8_t res = 0 ;
char * llp = lp ;
2019-10-24 07:17:19 +01:00
char * slp ;
2019-08-05 12:01:23 +01:00
SCRIPT_SKIP_SPACES
if ( * lp = = ' ( ' ) {
2020-09-11 14:44:16 +01:00
uint8_t res = 0 ;
uint8_t xand_or = 0 ;
2019-08-05 12:01:23 +01:00
lp + + ;
2019-10-24 07:17:19 +01:00
loop :
SCRIPT_SKIP_SPACES
2020-09-11 14:44:16 +01:00
lp = Evaluate_expression ( lp , xand_or , & res , jo ) ;
2019-10-24 07:17:19 +01:00
if ( * lp = = ' ) ' ) {
lp + + ;
goto exit0 ;
}
2019-08-05 12:01:23 +01:00
// check for next and or
SCRIPT_SKIP_SPACES
2020-09-11 14:44:16 +01:00
if ( ! strncmp ( lp , " or " , 2 ) ) {
lp + = 2 ;
xand_or = 1 ;
2019-10-24 07:17:19 +01:00
goto loop ;
2020-09-11 14:44:16 +01:00
} else if ( ! strncmp ( lp , " and " , 3 ) ) {
lp + = 3 ;
xand_or = 2 ;
2019-10-24 07:17:19 +01:00
goto loop ;
2019-08-05 12:01:23 +01:00
}
2019-10-24 07:17:19 +01:00
exit0 :
if ( ! and_or ) {
2020-09-11 14:44:16 +01:00
* result = res ;
2019-10-24 07:17:19 +01:00
} else if ( and_or = = 1 ) {
* result | = res ;
} else {
2020-09-11 14:44:16 +01:00
* result & = res ;
2019-10-24 07:17:19 +01:00
}
goto exit10 ;
2019-08-05 12:01:23 +01:00
}
2020-09-11 14:44:16 +01:00
llp = lp ;
2019-08-05 12:01:23 +01:00
// compare
2020-09-11 14:44:16 +01:00
dfvar = & fvar ;
glob_script_mem . glob_error = 0 ;
slp = lp ;
numeric = 1 ;
lp = GetNumericArgument ( lp , OPER_EQU , dfvar , 0 ) ;
2019-08-05 12:01:23 +01:00
if ( glob_script_mem . glob_error = = 1 ) {
// was string, not number
char cmpstr [ SCRIPT_MAXSSIZE ] ;
2020-09-11 14:44:16 +01:00
lp = slp ;
numeric = 0 ;
2019-08-05 12:01:23 +01:00
// get the string
2020-09-11 14:44:16 +01:00
lp = isvar ( lp , & vtype , & ind , 0 , cmpstr , 0 ) ;
lp = getop ( lp , & lastop ) ;
2019-08-05 12:01:23 +01:00
// compare string
char str [ SCRIPT_MAXSSIZE ] ;
2020-09-11 14:44:16 +01:00
lp = GetStringArgument ( lp , OPER_EQU , str , jo ) ;
2019-08-05 12:01:23 +01:00
if ( lastop = = OPER_EQUEQU | | lastop = = OPER_NOTEQU ) {
2020-09-11 14:44:16 +01:00
res = strcmp ( cmpstr , str ) ;
2019-08-05 12:01:23 +01:00
if ( lastop = = OPER_EQUEQU ) res = ! res ;
2019-10-24 07:17:19 +01:00
goto exit ;
2019-08-05 12:01:23 +01:00
}
2019-05-22 11:33:51 +01:00
2019-08-05 12:01:23 +01:00
} else {
// numeric
// evaluate operand
2020-09-11 14:44:16 +01:00
lp = getop ( lp , & lastop ) ;
lp = GetNumericArgument ( lp , OPER_EQU , & fvar1 , jo ) ;
2019-08-05 12:01:23 +01:00
switch ( lastop ) {
case OPER_EQUEQU :
2020-09-11 14:44:16 +01:00
res = ( * dfvar = = fvar1 ) ;
2019-08-05 12:01:23 +01:00
break ;
case OPER_NOTEQU :
2020-09-11 14:44:16 +01:00
res = ( * dfvar ! = fvar1 ) ;
2019-08-05 12:01:23 +01:00
break ;
case OPER_LOW :
2020-09-11 14:44:16 +01:00
res = ( * dfvar < fvar1 ) ;
2019-08-05 12:01:23 +01:00
break ;
case OPER_LOWEQU :
2020-09-11 14:44:16 +01:00
res = ( * dfvar < = fvar1 ) ;
2019-08-05 12:01:23 +01:00
break ;
case OPER_GRT :
2020-09-11 14:44:16 +01:00
res = ( * dfvar > fvar1 ) ;
2019-08-05 12:01:23 +01:00
break ;
case OPER_GRTEQU :
2020-09-11 14:44:16 +01:00
res = ( * dfvar > = fvar1 ) ;
2019-08-05 12:01:23 +01:00
break ;
default :
// error
break ;
}
2019-10-24 07:17:19 +01:00
exit :
2019-08-05 12:01:23 +01:00
if ( ! and_or ) {
2020-09-11 14:44:16 +01:00
* result = res ;
2019-08-05 12:01:23 +01:00
} else if ( and_or = = 1 ) {
2020-09-11 14:44:16 +01:00
* result | = res ;
2019-08-05 12:01:23 +01:00
} else {
2020-09-11 14:44:16 +01:00
* result & = res ;
2019-08-05 12:01:23 +01:00
}
}
2019-10-24 07:17:19 +01:00
exit10 :
2020-08-29 10:34:00 +01:00
# if IFTHEN_DEBUG>0
2019-08-05 12:01:23 +01:00
char tbuff [ 128 ] ;
2020-09-11 14:44:16 +01:00
sprintf ( tbuff , " p1=%d,p2=%d,cmpres=%d,and_or=%d line: " , ( int32_t ) * dfvar , ( int32_t ) fvar1 , * result , and_or ) ;
toLogEOL ( tbuff , llp ) ;
2019-08-05 12:01:23 +01:00
# endif
return lp ;
}
2019-05-22 11:33:51 +01:00
2020-05-11 18:19:59 +01:00
# ifdef ESP32
TimerHandle_t beep_th ;
void StopBeep ( TimerHandle_t xTimer ) ;
void StopBeep ( TimerHandle_t xTimer ) {
2020-09-11 14:44:16 +01:00
ledcWriteTone ( 7 , 0 ) ;
2020-05-11 18:19:59 +01:00
xTimerStop ( xTimer , 0 ) ;
}
void esp32_beep ( int32_t freq , uint32_t len ) {
if ( freq < 0 ) {
2020-12-04 07:57:52 +00:00
if ( freq < = - 64 ) freq = 0 ;
2020-09-11 14:44:16 +01:00
ledcSetup ( 7 , 500 , 10 ) ;
ledcAttachPin ( - freq , 7 ) ;
ledcWriteTone ( 7 , 0 ) ;
2020-05-11 18:19:59 +01:00
if ( ! beep_th ) {
2020-09-11 14:44:16 +01:00
beep_th = xTimerCreate ( " beep " , 100 , pdFALSE , ( void * ) 0 , StopBeep ) ;
2020-05-11 18:19:59 +01:00
}
} else {
if ( ! beep_th ) return ;
if ( ! freq ) {
2020-09-11 14:44:16 +01:00
ledcWriteTone ( 7 , 0 ) ;
2020-05-11 18:19:59 +01:00
xTimerStop ( beep_th , 10 ) ;
return ;
}
if ( len < 10 ) return ;
if ( xTimerIsTimerActive ( beep_th ) ) return ;
2020-09-11 14:44:16 +01:00
ledcWriteTone ( 7 , freq ) ;
2020-05-11 18:19:59 +01:00
uint32_t ticks = pdMS_TO_TICKS ( len ) ;
xTimerChangePeriod ( beep_th , ticks , 10 ) ;
}
}
2020-12-13 06:32:09 +00:00
# endif // ESP32
uint8_t pwmpin [ 5 ] ;
2020-12-04 07:57:52 +00:00
2020-12-13 06:32:09 +00:00
void esp_pwm ( int32_t value , uint32 freq , uint32_t channel ) {
2020-12-26 08:45:59 +00:00
2020-12-13 06:32:09 +00:00
# ifdef ESP32
2020-12-26 08:45:59 +00:00
if ( channel < 1 | | channel > 8 ) channel = 1 ;
2020-12-13 06:32:09 +00:00
channel + = 7 ;
2020-12-04 07:57:52 +00:00
if ( value < 0 ) {
if ( value < = - 64 ) value = 0 ;
2020-12-13 06:32:09 +00:00
// set range to 10 bit
ledcSetup ( channel , freq , 10 ) ;
ledcAttachPin ( - value , channel ) ;
ledcWrite ( channel , 0 ) ;
2020-12-04 07:57:52 +00:00
} else {
if ( value > 1023 ) {
value = 1023 ;
}
2020-12-13 06:32:09 +00:00
ledcWrite ( channel , value ) ;
2020-12-04 07:57:52 +00:00
}
2020-12-13 06:32:09 +00:00
# else
// esp8266 default to range 0-1023
2020-12-26 08:45:59 +00:00
if ( channel < 1 | | channel > 5 ) channel = 1 ;
2020-12-13 06:32:09 +00:00
channel - = 1 ;
if ( value < 0 ) {
if ( value < = - 64 ) value = 0 ;
pwmpin [ channel ] = - value ;
pinMode ( pwmpin [ channel ] , OUTPUT ) ;
analogWriteFreq ( freq ) ;
analogWrite ( pwmpin [ channel ] , 0 ) ;
} else {
if ( value > 1023 ) {
value = 1023 ;
}
analogWrite ( pwmpin [ channel ] , value ) ;
}
# endif // ESP32
2020-12-04 07:57:52 +00:00
}
2020-12-13 06:32:09 +00:00
2020-05-11 18:19:59 +01:00
2019-06-15 06:02:34 +01:00
//#define IFTHEN_DEBUG
2019-05-22 11:33:51 +01:00
2020-10-23 06:45:35 +01:00
char * scripter_sub ( char * lp , uint8_t fromscriptcmd ) {
lp + = 1 ;
char * slp = lp ;
uint8_t plen = 0 ;
while ( * lp ) {
if ( * lp = = ' \n ' | | * lp = = ' \r ' | | * lp = = ' ( ' ) {
break ;
}
lp + + ;
plen + + ;
}
if ( fromscriptcmd ) {
char * sp = glob_script_mem . scriptptr ;
glob_script_mem . scriptptr = glob_script_mem . scriptptr_bu ;
Run_Scripter ( slp , plen , 0 ) ;
glob_script_mem . scriptptr = sp ;
} else {
Run_Scripter ( slp , plen , 0 ) ;
}
lp = slp ;
return lp ;
}
2019-05-18 08:45:04 +01:00
# define IF_NEST 8
// execute section of scripter
2019-07-16 15:50:52 +01:00
int16_t Run_Scripter ( const char * type , int8_t tlen , char * js ) {
2020-10-03 17:30:18 +01:00
int16_t retval ;
2019-08-16 06:37:16 +01:00
2020-07-02 05:46:04 +01:00
if ( ! glob_script_mem . scriptptr ) {
return - 99 ;
}
2019-08-16 06:37:16 +01:00
if ( tasm_cmd_activ & & tlen > 0 ) return 0 ;
2020-09-25 07:52:28 +01:00
JsonParserObject jo ;
2020-07-02 05:46:04 +01:00
if ( js ) {
2020-10-03 17:30:18 +01:00
//String jss = js; // copy the string to a new buffer, not sure we can change the original buffer
//JsonParser parser((char*)jss.c_str());
JsonParser parser ( js ) ;
2020-09-25 07:52:28 +01:00
jo = parser . getRootObject ( ) ;
2020-10-03 17:30:18 +01:00
retval = Run_script_sub ( type , tlen , & jo ) ;
} else {
retval = Run_script_sub ( type , tlen , 0 ) ;
2020-07-02 05:46:04 +01:00
}
2020-10-03 17:30:18 +01:00
return retval ;
2020-07-02 05:46:04 +01:00
}
2020-09-25 07:52:28 +01:00
int16_t Run_script_sub ( const char * type , int8_t tlen , JsonParserObject * jo ) {
2019-08-19 07:20:51 +01:00
uint8_t vtype = 0 , sindex , xflg , floop = 0 , globvindex , fromscriptcmd = 0 ;
2020-05-25 14:49:03 +01:00
char * lp_next ;
2020-09-03 11:26:03 +01:00
int16_t globaindex , saindex ;
2019-05-18 08:45:04 +01:00
struct T_INDEX ind ;
2020-09-11 14:44:16 +01:00
uint8_t operand , lastop , numeric = 1 , if_state [ IF_NEST ] , if_exe [ IF_NEST ] , if_result [ IF_NEST ] , and_or , ifstck = 0 ;
if_state [ ifstck ] = 0 ;
if_result [ ifstck ] = 0 ;
if_exe [ ifstck ] = 1 ;
2019-05-18 08:45:04 +01:00
char cmpstr [ SCRIPT_MAXSSIZE ] ;
2020-09-11 14:44:16 +01:00
uint8_t check = 0 ;
2019-07-16 15:50:52 +01:00
if ( tlen < 0 ) {
2020-09-11 14:44:16 +01:00
tlen = abs ( tlen ) ;
check = 1 ;
2019-07-16 15:50:52 +01:00
}
2019-05-18 08:45:04 +01:00
float * dfvar , * cv_count , cv_max , cv_inc ;
char * cv_ptr ;
2020-09-11 14:44:16 +01:00
float fvar = 0 , fvar1 , sysvar , swvar ;
uint8_t section = 0 , sysv_type = 0 , swflg = 0 ;
2019-05-18 08:45:04 +01:00
2020-09-11 14:44:16 +01:00
char * lp = glob_script_mem . scriptptr ;
2019-05-18 08:45:04 +01:00
while ( 1 ) {
// check line
// skip leading spaces
startline :
SCRIPT_SKIP_SPACES
// skip empty line
SCRIPT_SKIP_EOL
// skip comment
if ( * lp = = ' ; ' ) goto next_line ;
if ( ! * lp ) break ;
if ( section ) {
// we are in section
if ( * lp = = ' > ' ) {
2019-09-24 07:25:32 +01:00
return 0 ;
2019-05-18 08:45:04 +01:00
}
if ( * lp = = ' # ' ) {
2019-09-24 07:25:32 +01:00
return 0 ;
2019-05-18 08:45:04 +01:00
}
2020-09-11 14:44:16 +01:00
glob_script_mem . var_not_found = 0 ;
2019-05-18 08:45:04 +01:00
2019-06-15 06:02:34 +01:00
//#if SCRIPT_DEBUG>0
# ifdef IFTHEN_DEBUG
2019-05-18 08:45:04 +01:00
char tbuff [ 128 ] ;
2020-09-11 14:44:16 +01:00
sprintf ( tbuff , " stack=%d,exe=%d,state=%d,cmpres=%d line: " , ifstck , if_exe [ ifstck ] , if_state [ ifstck ] , if_result [ ifstck ] ) ;
toLogEOL ( tbuff , lp ) ;
# endif //IFTHEN_DEBUG
2019-05-18 08:45:04 +01:00
2019-07-16 15:50:52 +01:00
//if (if_state[s_ifstck]==3 && if_result[s_ifstck]) goto next_line;
//if (if_state[s_ifstck]==2 && !if_result[s_ifstck]) goto next_line;
2020-09-11 14:44:16 +01:00
if ( ! strncmp ( lp , " if " , 2 ) ) {
lp + = 2 ;
2019-07-16 15:50:52 +01:00
if ( ifstck < IF_NEST - 1 ) ifstck + + ;
2020-09-11 14:44:16 +01:00
if_state [ ifstck ] = 1 ;
if_result [ ifstck ] = 0 ;
if ( ifstck = = 1 ) if_exe [ ifstck ] = 1 ;
else if_exe [ ifstck ] = if_exe [ ifstck - 1 ] ;
and_or = 0 ;
} else if ( ! strncmp ( lp , " then " , 4 ) & & if_state [ ifstck ] = = 1 ) {
lp + = 4 ;
if_state [ ifstck ] = 2 ;
if ( if_exe [ ifstck - 1 ] ) if_exe [ ifstck ] = if_result [ ifstck ] ;
} else if ( ! strncmp ( lp , " else " , 4 ) & & if_state [ ifstck ] = = 2 ) {
lp + = 4 ;
if_state [ ifstck ] = 3 ;
if ( if_exe [ ifstck - 1 ] ) if_exe [ ifstck ] = ! if_result [ ifstck ] ;
} else if ( ! strncmp ( lp , " endif " , 5 ) & & if_state [ ifstck ] > = 2 ) {
lp + = 5 ;
2019-05-18 08:45:04 +01:00
if ( ifstck > 0 ) {
2020-09-11 14:44:16 +01:00
if_state [ ifstck ] = 0 ;
2019-05-18 08:45:04 +01:00
ifstck - - ;
}
goto next_line ;
2020-09-11 14:44:16 +01:00
} else if ( ! strncmp ( lp , " or " , 2 ) & & if_state [ ifstck ] = = 1 ) {
lp + = 2 ;
and_or = 1 ;
} else if ( ! strncmp ( lp , " and " , 3 ) & & if_state [ ifstck ] = = 1 ) {
lp + = 3 ;
and_or = 2 ;
2019-05-18 08:45:04 +01:00
}
if ( * lp = = ' { ' & & if_state [ ifstck ] = = 1 ) {
2020-09-11 14:44:16 +01:00
lp + = 1 ; // then
if_state [ ifstck ] = 2 ;
if ( if_exe [ ifstck - 1 ] ) if_exe [ ifstck ] = if_result [ ifstck ] ;
2019-05-18 08:45:04 +01:00
} else if ( * lp = = ' { ' & & if_state [ ifstck ] = = 3 ) {
2020-09-11 14:44:16 +01:00
lp + = 1 ; // after else
2019-05-18 08:45:04 +01:00
//if_state[ifstck]=3;
} else if ( * lp = = ' } ' & & if_state [ ifstck ] > = 2 ) {
lp + + ; // must check for else
2020-09-11 14:44:16 +01:00
char * slp = lp ;
uint8_t iselse = 0 ;
for ( uint8_t count = 0 ; count < 8 ; count + + ) {
2019-05-18 08:45:04 +01:00
if ( * lp = = ' } ' ) {
// must be endif
break ;
}
2020-09-11 14:44:16 +01:00
if ( ! strncmp ( lp , " else " , 4 ) ) {
2019-05-18 08:45:04 +01:00
// is before else, no endif
2020-09-11 14:44:16 +01:00
if_state [ ifstck ] = 3 ;
2019-07-16 15:50:52 +01:00
if ( if_exe [ ifstck - 1 ] ) if_exe [ ifstck ] = ! if_result [ ifstck ] ;
2020-09-11 14:44:16 +01:00
lp + = 4 ;
iselse = 1 ;
2019-07-16 15:50:52 +01:00
SCRIPT_SKIP_SPACES
if ( * lp = = ' { ' ) lp + + ;
2019-05-18 08:45:04 +01:00
break ;
}
lp + + ;
}
if ( ! iselse ) {
2020-09-11 14:44:16 +01:00
lp = slp ;
2019-05-18 08:45:04 +01:00
// endif
if ( ifstck > 0 ) {
2020-09-11 14:44:16 +01:00
if_state [ ifstck ] = 0 ;
2019-05-18 08:45:04 +01:00
ifstck - - ;
}
2019-07-16 15:50:52 +01:00
goto next_line ;
2019-05-18 08:45:04 +01:00
}
}
2020-09-11 14:44:16 +01:00
if ( ! strncmp ( lp , " for " , 3 ) ) {
2019-05-18 08:45:04 +01:00
// start for next loop, fetch 3 params
// simple implementation, zero loop count not supported
2020-09-11 14:44:16 +01:00
lp + = 3 ;
2019-05-18 08:45:04 +01:00
SCRIPT_SKIP_SPACES
2020-09-11 14:44:16 +01:00
lp_next = 0 ;
lp = isvar ( lp , & vtype , & ind , 0 , 0 , 0 ) ;
2019-05-18 08:45:04 +01:00
if ( ( vtype ! = VAR_NV ) & & ( vtype & STYPE ) = = 0 ) {
// numeric var
2020-09-11 14:44:16 +01:00
uint8_t index = glob_script_mem . type [ ind . index ] . index ;
cv_count = & glob_script_mem . fvars [ index ] ;
2019-05-18 08:45:04 +01:00
SCRIPT_SKIP_SPACES
2020-09-11 14:44:16 +01:00
lp = GetNumericArgument ( lp , OPER_EQU , cv_count , 0 ) ;
2019-05-18 08:45:04 +01:00
SCRIPT_SKIP_SPACES
2020-09-11 14:44:16 +01:00
lp = GetNumericArgument ( lp , OPER_EQU , & cv_max , 0 ) ;
2019-05-18 08:45:04 +01:00
SCRIPT_SKIP_SPACES
2020-09-11 14:44:16 +01:00
lp = GetNumericArgument ( lp , OPER_EQU , & cv_inc , 0 ) ;
2019-07-28 16:10:55 +01:00
//SCRIPT_SKIP_EOL
2020-09-11 14:44:16 +01:00
cv_ptr = lp ;
2020-07-02 05:46:04 +01:00
if ( * cv_count < = cv_max & & cv_inc > 0 ) {
// inc loop
2020-09-11 14:44:16 +01:00
floop = 1 ;
2020-05-15 14:30:32 +01:00
} else {
2020-07-02 05:46:04 +01:00
// dec loop
2020-09-11 14:44:16 +01:00
floop = 2 ;
2020-07-02 05:46:04 +01:00
if ( cv_inc > 0 ) {
2020-09-11 14:44:16 +01:00
floop = 1 ;
2020-07-02 05:46:04 +01:00
}
2020-05-15 14:30:32 +01:00
}
2019-05-18 08:45:04 +01:00
} else {
// error
2020-09-11 14:44:16 +01:00
toLogEOL ( " for error " , lp ) ;
2019-05-18 08:45:04 +01:00
}
2020-09-11 14:44:16 +01:00
} else if ( ! strncmp ( lp , " next " , 4 ) ) {
lp_next = lp ;
2020-05-25 14:49:03 +01:00
if ( floop > 0 ) {
// for next loop
2020-09-11 14:44:16 +01:00
* cv_count + = cv_inc ;
2020-05-25 14:49:03 +01:00
if ( floop = = 1 ) {
if ( * cv_count < = cv_max ) {
2020-09-11 14:44:16 +01:00
lp = cv_ptr ;
2020-05-25 14:49:03 +01:00
} else {
2020-09-11 14:44:16 +01:00
lp + = 4 ;
floop = 0 ;
2020-05-25 14:49:03 +01:00
}
2020-05-15 14:30:32 +01:00
} else {
2020-05-25 14:49:03 +01:00
if ( * cv_count > = cv_max ) {
2020-09-11 14:44:16 +01:00
lp = cv_ptr ;
2020-05-25 14:49:03 +01:00
} else {
2020-09-11 14:44:16 +01:00
lp + = 4 ;
floop = 0 ;
2020-05-25 14:49:03 +01:00
}
2020-05-15 14:30:32 +01:00
}
2019-05-18 08:45:04 +01:00
}
}
2020-09-11 14:44:16 +01:00
if ( ! strncmp ( lp , " switch " , 6 ) ) {
lp + = 6 ;
2019-05-18 08:45:04 +01:00
SCRIPT_SKIP_SPACES
2020-09-11 14:44:16 +01:00
char * slp = lp ;
lp = GetNumericArgument ( lp , OPER_EQU , & swvar , 0 ) ;
2019-07-16 15:50:52 +01:00
if ( glob_script_mem . glob_error = = 1 ) {
// was string, not number
2020-09-11 14:44:16 +01:00
lp = slp ;
2019-07-16 15:50:52 +01:00
// get the string
2020-09-11 14:44:16 +01:00
lp = isvar ( lp , & vtype , & ind , 0 , cmpstr , 0 ) ;
swflg = 0x81 ;
2019-07-16 15:50:52 +01:00
} else {
2020-09-11 14:44:16 +01:00
swflg = 1 ;
2019-07-16 15:50:52 +01:00
}
2020-09-11 14:44:16 +01:00
} else if ( ! strncmp ( lp , " case " , 4 ) & & swflg > 0 ) {
lp + = 4 ;
2019-05-18 08:45:04 +01:00
SCRIPT_SKIP_SPACES
float cvar ;
2020-09-11 14:44:16 +01:00
if ( ! ( swflg & 0x80 ) ) {
lp = GetNumericArgument ( lp , OPER_EQU , & cvar , 0 ) ;
2019-07-16 15:50:52 +01:00
if ( swvar ! = cvar ) {
2020-09-11 14:44:16 +01:00
swflg = 2 ;
2019-07-16 15:50:52 +01:00
} else {
2020-09-11 14:44:16 +01:00
swflg = 1 ;
2019-07-16 15:50:52 +01:00
}
2019-05-18 08:45:04 +01:00
} else {
2019-07-16 15:50:52 +01:00
char str [ SCRIPT_MAXSSIZE ] ;
2020-09-11 14:44:16 +01:00
lp = GetStringArgument ( lp , OPER_EQU , str , 0 ) ;
if ( ! strcmp ( cmpstr , str ) ) {
swflg = 0x81 ;
2019-07-16 15:50:52 +01:00
} else {
2020-09-11 14:44:16 +01:00
swflg = 0x82 ;
2019-07-16 15:50:52 +01:00
}
2019-05-18 08:45:04 +01:00
}
2020-09-11 14:44:16 +01:00
} else if ( ! strncmp ( lp , " ends " , 4 ) & & swflg > 0 ) {
lp + = 4 ;
swflg = 0 ;
2019-05-18 08:45:04 +01:00
}
2020-09-11 14:44:16 +01:00
if ( ( swflg & 3 ) = = 2 ) goto next_line ;
2019-05-18 08:45:04 +01:00
SCRIPT_SKIP_SPACES
//SCRIPT_SKIP_EOL
if ( * lp = = SCRIPT_EOL ) {
goto next_line ;
}
2019-06-15 06:02:34 +01:00
2019-05-18 08:45:04 +01:00
//toLogN(lp,16);
2019-07-16 15:50:52 +01:00
if ( ! if_exe [ ifstck ] & & if_state [ ifstck ] ! = 1 ) goto next_line ;
2019-05-18 08:45:04 +01:00
2019-06-15 06:02:34 +01:00
# ifdef IFTHEN_DEBUG
2020-09-11 14:44:16 +01:00
sprintf ( tbuff , " stack=%d,exe=%d,state=%d,cmpres=%d execute line: " , ifstck , if_exe [ ifstck ] , if_state [ ifstck ] , if_result [ ifstck ] ) ;
toLogEOL ( tbuff , lp ) ;
# endif //IFTHEN_DEBUG
2019-05-18 08:45:04 +01:00
2020-09-11 14:44:16 +01:00
if ( ! strncmp ( lp , " break " , 5 ) ) {
lp + = 5 ;
2020-06-26 08:22:57 +01:00
if ( floop ) {
2019-05-18 08:45:04 +01:00
// should break loop
2020-06-26 08:22:57 +01:00
if ( lp_next ) {
2020-09-11 14:44:16 +01:00
lp = lp_next ;
2020-06-26 08:22:57 +01:00
}
2020-09-11 14:44:16 +01:00
floop = 0 ;
2019-05-18 08:45:04 +01:00
} else {
2020-09-11 14:44:16 +01:00
section = 0 ;
2019-05-18 08:45:04 +01:00
}
2020-05-25 14:49:03 +01:00
goto next_line ;
2020-09-11 14:44:16 +01:00
} else if ( ! strncmp ( lp , " dp " , 2 ) & & isdigit ( * ( lp + 2 ) ) ) {
lp + = 2 ;
2019-05-18 08:45:04 +01:00
// number precision
2020-09-23 11:51:35 +01:00
if ( * ( lp + 1 ) = = ' . ' ) {
glob_script_mem . script_lzero = atoi ( lp ) ;
lp + = 2 ;
}
2020-09-11 14:44:16 +01:00
glob_script_mem . script_dprec = atoi ( lp ) ;
2019-05-18 08:45:04 +01:00
goto next_line ;
2020-08-09 09:58:22 +01:00
}
# ifdef USE_DISPLAY
2020-09-11 14:44:16 +01:00
else if ( ! strncmp ( lp , " dt " , 2 ) ) {
2020-08-09 09:58:22 +01:00
char dstbuf [ 256 ] ;
2020-09-11 14:44:16 +01:00
lp + = 2 ;
2020-08-09 09:58:22 +01:00
SCRIPT_SKIP_SPACES
2020-09-11 14:44:16 +01:00
Replace_Cmd_Vars ( lp , 1 , dstbuf , sizeof ( dstbuf ) ) ;
2020-08-09 09:58:22 +01:00
char * savptr = XdrvMailbox . data ;
XdrvMailbox . data = dstbuf ;
XdrvMailbox . data_len = 0 ;
DisplayText ( ) ;
XdrvMailbox . data = savptr ;
goto next_line ;
}
2020-09-11 14:44:16 +01:00
# endif //USE_DISPLAY
else if ( ! strncmp ( lp , " delay( " , 6 ) ) {
2019-05-18 08:45:04 +01:00
// delay
2020-09-11 14:44:16 +01:00
lp = GetNumericArgument ( lp + 5 , OPER_EQU , & fvar , 0 ) ;
2019-05-18 08:45:04 +01:00
delay ( fvar ) ;
goto next_line ;
2020-09-11 14:44:16 +01:00
} else if ( ! strncmp ( lp , " spinm( " , 6 ) ) {
2019-05-18 08:45:04 +01:00
// set pin mode
2020-09-11 14:44:16 +01:00
lp = GetNumericArgument ( lp + 6 , OPER_EQU , & fvar , 0 ) ;
int8_t pinnr = fvar ;
2019-05-18 08:45:04 +01:00
SCRIPT_SKIP_SPACES
2020-09-11 14:44:16 +01:00
uint8_t mode = 0 ;
2020-05-02 07:10:23 +01:00
if ( ( * lp = = ' I ' ) | | ( * lp = = ' O ' ) | | ( * lp = = ' P ' ) ) {
switch ( * lp ) {
case ' I ' :
2020-09-11 14:44:16 +01:00
mode = 0 ;
2020-05-02 07:10:23 +01:00
break ;
case ' O ' :
2020-09-11 14:44:16 +01:00
mode = 1 ;
2020-05-02 07:10:23 +01:00
break ;
case ' P ' :
2020-09-11 14:44:16 +01:00
mode = 2 ;
2020-05-02 07:10:23 +01:00
break ;
}
lp + + ;
} else {
2020-09-11 14:44:16 +01:00
lp = GetNumericArgument ( lp , OPER_EQU , & fvar , 0 ) ;
mode = fvar ;
2020-05-02 07:10:23 +01:00
}
uint8_t pm = 0 ;
2020-09-11 14:44:16 +01:00
if ( mode = = 0 ) pm = INPUT ;
if ( mode = = 1 ) pm = OUTPUT ;
if ( mode = = 2 ) pm = INPUT_PULLUP ;
pinMode ( pinnr , pm ) ;
2019-05-18 08:45:04 +01:00
goto next_line ;
2020-09-11 14:44:16 +01:00
} else if ( ! strncmp ( lp , " spin( " , 5 ) ) {
2019-07-23 06:01:17 +01:00
// set pin
2020-09-11 14:44:16 +01:00
lp = GetNumericArgument ( lp + 5 , OPER_EQU , & fvar , 0 ) ;
int8_t pinnr = fvar ;
2019-05-18 08:45:04 +01:00
SCRIPT_SKIP_SPACES
2020-09-11 14:44:16 +01:00
lp = GetNumericArgument ( lp , OPER_EQU , & fvar , 0 ) ;
int8_t mode = fvar ;
digitalWrite ( pinnr , mode & 1 ) ;
2019-05-18 08:45:04 +01:00
goto next_line ;
2020-10-19 06:24:18 +01:00
} else if ( ! strncmp ( lp , " svars " , 5 ) ) {
2020-09-11 14:44:16 +01:00
lp + = 5 ;
2019-05-18 08:45:04 +01:00
// save vars
Scripter_save_pvars ( ) ;
goto next_line ;
}
2020-10-19 06:24:18 +01:00
# ifdef USE_SCRIPT_GLOBVARS
else if ( ! strncmp ( lp , " gvr " , 3 ) ) {
lp + = 3 ;
// reset global vars udp server
Restart_globvars ( ) ;
goto next_line ;
}
# endif
2019-07-28 16:10:55 +01:00
# ifdef USE_LIGHT
# ifdef USE_WS2812
2020-09-11 14:44:16 +01:00
else if ( ! strncmp ( lp , " ws2812( " , 7 ) ) {
lp = isvar ( lp + 7 , & vtype , & ind , 0 , 0 , 0 ) ;
2019-07-28 16:10:55 +01:00
if ( vtype ! = VAR_NV ) {
2020-05-15 14:30:32 +01:00
SCRIPT_SKIP_SPACES
if ( * lp ! = ' ) ' ) {
2020-09-11 14:44:16 +01:00
lp = GetNumericArgument ( lp , OPER_EQU , & fvar , 0 ) ;
2020-05-15 14:30:32 +01:00
} else {
2020-09-11 14:44:16 +01:00
fvar = 0 ;
2020-05-15 14:30:32 +01:00
}
2019-07-28 16:10:55 +01:00
// found variable as result
2020-09-11 14:44:16 +01:00
uint8_t index = glob_script_mem . type [ ind . index ] . index ;
2019-07-28 16:10:55 +01:00
if ( ( vtype & STYPE ) = = 0 ) {
// numeric result
2020-05-19 15:44:01 +01:00
if ( glob_script_mem . type [ ind . index ] . bits . is_filter ) {
2020-09-11 14:44:16 +01:00
uint16_t len = 0 ;
float * fa = Get_MFAddr ( index , & len , 0 ) ;
2019-07-28 16:10:55 +01:00
//Serial.printf(">> 2 %d\n",(uint32_t)*fa);
2020-09-11 14:44:16 +01:00
if ( fa & & len ) ws2812_set_array ( fa , len , fvar ) ;
2019-07-28 16:10:55 +01:00
}
}
}
goto next_line ;
}
2020-09-11 14:44:16 +01:00
# endif //USE_WS2812
# endif //USE_LIGHT
2020-05-02 07:10:23 +01:00
# ifdef ESP32
2020-09-11 14:44:16 +01:00
else if ( ! strncmp ( lp , " beep( " , 5 ) ) {
lp = GetNumericArgument ( lp + 5 , OPER_EQU , & fvar , 0 ) ;
2020-05-11 18:19:59 +01:00
SCRIPT_SKIP_SPACES
float fvar1 ;
2020-09-11 14:44:16 +01:00
lp = GetNumericArgument ( lp , OPER_EQU , & fvar1 , 0 ) ;
esp32_beep ( fvar , fvar1 ) ;
2020-05-02 07:10:23 +01:00
lp + + ;
goto next_line ;
}
2020-12-13 06:32:09 +00:00
# endif //ESP32
else if ( ! strncmp ( lp , " pwm " , 3 ) ) {
lp + = 3 ;
uint8_t channel = 1 ;
if ( * ( lp + 1 ) = = ' ( ' ) {
2021-01-11 16:45:06 +00:00
channel = * lp & 0x0f ;
# ifdef ESP8266
if ( channel > 5 ) { channel = 5 ; }
# endif // ESP8266
# ifdef ESP32
if ( channel > 8 ) { channel = 8 ; }
# endif // ESP32
if ( channel < 1 ) { channel = 1 ; }
2020-12-13 06:32:09 +00:00
lp + = 2 ;
} else {
if ( * lp = = ' ( ' ) {
lp + + ;
} else {
goto next_line ;
}
}
lp = GetNumericArgument ( lp , OPER_EQU , & fvar , 0 ) ;
2020-12-04 07:57:52 +00:00
SCRIPT_SKIP_SPACES
2020-12-13 06:32:09 +00:00
float fvar1 = 4000 ;
if ( * lp ! = ' ) ' ) {
lp = GetNumericArgument ( lp , OPER_EQU , & fvar1 , 0 ) ;
}
esp_pwm ( fvar , fvar1 , channel ) ;
2020-12-04 07:57:52 +00:00
lp + + ;
goto next_line ;
}
2020-10-23 06:45:35 +01:00
else if ( ! strncmp ( lp , " wcs " , 3 ) ) {
lp + = 4 ;
// skip one space after cmd
char tmp [ 256 ] ;
Replace_Cmd_Vars ( lp , 1 , tmp , sizeof ( tmp ) ) ;
WSContentFlush ( ) ;
WSContentSend_P ( PSTR ( " %s " ) , tmp ) ;
WSContentFlush ( ) ;
goto next_line ;
}
2019-10-10 12:39:52 +01:00
else if ( ! strncmp ( lp , " => " , 2 ) | | ! strncmp ( lp , " -> " , 2 ) | | ! strncmp ( lp , " +> " , 2 ) | | ! strncmp ( lp , " print " , 5 ) ) {
2019-05-18 08:45:04 +01:00
// execute cmd
2020-09-11 14:44:16 +01:00
uint8_t sflag = 0 , pflg = 0 , svmqtt , swll ;
2019-08-19 07:20:51 +01:00
if ( * lp = = ' p ' ) {
2020-09-11 14:44:16 +01:00
pflg = 1 ;
lp + = 5 ;
2019-08-19 07:20:51 +01:00
}
else {
2020-09-11 14:44:16 +01:00
if ( * lp = = ' - ' ) sflag = 1 ;
if ( * lp = = ' + ' ) sflag = 2 ;
lp + = 2 ;
2019-08-19 07:20:51 +01:00
}
2020-09-11 14:44:16 +01:00
char * slp = lp ;
2019-05-18 08:45:04 +01:00
SCRIPT_SKIP_SPACES
# define SCRIPT_CMDMEM 512
2020-09-11 14:44:16 +01:00
char * cmdmem = ( char * ) malloc ( SCRIPT_CMDMEM ) ;
2019-05-18 08:45:04 +01:00
if ( cmdmem ) {
2020-09-11 14:44:16 +01:00
char * cmd = cmdmem ;
2019-07-09 09:20:11 +01:00
uint16_t count ;
2020-09-11 14:44:16 +01:00
for ( count = 0 ; count < SCRIPT_CMDMEM / 2 - 2 ; count + + ) {
2019-05-18 08:45:04 +01:00
//if (*lp=='\r' || *lp=='\n' || *lp=='}') {
if ( ! * lp | | * lp = = ' \r ' | | * lp = = ' \n ' ) {
2020-09-11 14:44:16 +01:00
cmd [ count ] = 0 ;
2019-05-18 08:45:04 +01:00
break ;
}
2020-09-11 14:44:16 +01:00
cmd [ count ] = * lp + + ;
2019-05-18 08:45:04 +01:00
}
2021-01-01 05:43:50 +00:00
//Script_AddLog_P(LOG_LEVEL_INFO, tmp);
2019-05-18 08:45:04 +01:00
// replace vars in cmd
2020-09-11 14:44:16 +01:00
char * tmp = cmdmem + SCRIPT_CMDMEM / 2 ;
Replace_Cmd_Vars ( cmd , 0 , tmp , SCRIPT_CMDMEM / 2 ) ;
2019-05-18 08:45:04 +01:00
//toSLog(tmp);
2020-09-11 14:44:16 +01:00
if ( ! strncmp ( tmp , " print " , 5 ) | | pflg ) {
2019-08-19 07:20:51 +01:00
if ( pflg ) toLog ( tmp ) ;
else toLog ( & tmp [ 5 ] ) ;
2019-05-18 08:45:04 +01:00
} else {
2019-07-16 15:50:52 +01:00
if ( ! sflag ) {
2020-09-11 14:44:16 +01:00
tasm_cmd_activ = 1 ;
2021-01-01 05:43:50 +00:00
Script_AddLog_P ( glob_script_mem . script_loglevel & 0x7f , PSTR ( " Script: performs \" %s \" " ) , tmp ) ;
2019-10-10 12:39:52 +01:00
} else if ( sflag = = 2 ) {
// allow recursive call
2019-07-16 15:50:52 +01:00
} else {
2020-09-11 14:44:16 +01:00
tasm_cmd_activ = 1 ;
svmqtt = Settings . flag . mqtt_enabled ; // SetOption3 - Enable MQTT
swll = Settings . weblog_level ;
Settings . flag . mqtt_enabled = 0 ; // SetOption3 - Enable MQTT
Settings . weblog_level = 0 ;
2019-07-16 15:50:52 +01:00
}
2019-05-18 08:45:04 +01:00
ExecuteCommand ( ( char * ) tmp , SRC_RULE ) ;
2020-09-11 14:44:16 +01:00
tasm_cmd_activ = 0 ;
2019-10-10 12:39:52 +01:00
if ( sflag = = 1 ) {
2020-09-11 14:44:16 +01:00
Settings . flag . mqtt_enabled = svmqtt ; // SetOption3 - Enable MQTT
Settings . weblog_level = swll ;
2019-07-16 15:50:52 +01:00
}
2019-05-18 08:45:04 +01:00
}
if ( cmdmem ) free ( cmdmem ) ;
}
2020-09-11 14:44:16 +01:00
lp = slp ;
2019-05-18 08:45:04 +01:00
goto next_line ;
2020-09-11 14:44:16 +01:00
} else if ( ! strncmp ( lp , " =# " , 2 ) ) {
2019-05-18 08:45:04 +01:00
// subroutine
2020-10-23 06:45:35 +01:00
lp = scripter_sub ( lp , fromscriptcmd ) ;
2019-05-18 08:45:04 +01:00
goto next_line ;
2020-09-11 14:44:16 +01:00
} else if ( ! strncmp ( lp , " =( " , 2 ) ) {
lp + = 2 ;
2019-08-19 07:20:51 +01:00
char str [ 128 ] ;
2020-09-11 14:44:16 +01:00
str [ 0 ] = ' > ' ;
lp = GetStringArgument ( lp , OPER_EQU , & str [ 1 ] , 0 ) ;
2019-08-19 07:20:51 +01:00
lp + + ;
2020-07-02 05:46:04 +01:00
//execute_script(str);
2020-09-11 14:44:16 +01:00
char * svd_sp = glob_script_mem . scriptptr ;
strcat ( str , " \n # " ) ;
glob_script_mem . scriptptr = str ;
Run_script_sub ( " > " , 1 , jo ) ;
glob_script_mem . scriptptr = svd_sp ;
2019-05-18 08:45:04 +01:00
}
// check for variable result
2019-07-16 15:50:52 +01:00
if ( if_state [ ifstck ] = = 1 ) {
2019-08-05 12:01:23 +01:00
// evaluate exxpression
2020-09-11 14:44:16 +01:00
lp = Evaluate_expression ( lp , and_or , & if_result [ ifstck ] , jo ) ;
2019-08-05 12:01:23 +01:00
SCRIPT_SKIP_SPACES
if ( * lp = = ' { ' & & if_state [ ifstck ] = = 1 ) {
2020-09-11 14:44:16 +01:00
lp + = 1 ; // then
if_state [ ifstck ] = 2 ;
if ( if_exe [ ifstck - 1 ] ) if_exe [ ifstck ] = if_result [ ifstck ] ;
2019-05-18 08:45:04 +01:00
}
2019-08-05 12:01:23 +01:00
goto next_line ;
2019-05-18 08:45:04 +01:00
} else {
2020-09-11 14:44:16 +01:00
char * vnp = lp ;
lp = isvar ( lp , & vtype , & ind , & sysvar , 0 , 0 ) ;
2019-05-18 08:45:04 +01:00
if ( vtype ! = VAR_NV ) {
2020-06-13 12:05:25 +01:00
# ifdef USE_SCRIPT_GLOBVARS
char varname [ 16 ] ;
2020-09-11 14:44:16 +01:00
uint32_t vnl = ( uint32_t ) lp - ( uint32 ) vnp ;
strncpy ( varname , vnp , vnl ) ;
varname [ vnl ] = 0 ;
# endif //USE_SCRIPT_GLOBVARS
2020-06-13 12:05:25 +01:00
2019-05-18 08:45:04 +01:00
// found variable as result
2020-09-11 14:44:16 +01:00
globvindex = ind . index ; // save destination var index here
globaindex = last_findex ;
uint8_t index = glob_script_mem . type [ ind . index ] . index ;
2019-05-18 08:45:04 +01:00
if ( ( vtype & STYPE ) = = 0 ) {
// numeric result
2019-10-26 09:31:27 +01:00
if ( ind . bits . settable | | ind . bits . is_filter ) {
2020-09-11 14:44:16 +01:00
dfvar = & sysvar ;
2019-10-26 09:36:41 +01:00
if ( ind . bits . settable ) {
2020-09-11 14:44:16 +01:00
sysv_type = ind . index ;
2019-10-26 09:36:41 +01:00
} else {
2020-09-11 14:44:16 +01:00
sysv_type = 0 ;
2019-10-26 09:36:41 +01:00
}
2019-05-18 08:45:04 +01:00
} else {
2020-09-11 14:44:16 +01:00
dfvar = & glob_script_mem . fvars [ index ] ;
sysv_type = 0 ;
2019-05-18 08:45:04 +01:00
}
2020-09-11 14:44:16 +01:00
numeric = 1 ;
lp = getop ( lp , & lastop ) ;
char * slp = lp ;
glob_script_mem . glob_error = 0 ;
lp = GetNumericArgument ( lp , OPER_EQU , & fvar , jo ) ;
2019-08-05 12:01:23 +01:00
if ( glob_script_mem . glob_error = = 1 ) {
// mismatch was string, not number
// get the string and convert to number
2020-09-11 14:44:16 +01:00
lp = isvar ( slp , & vtype , & ind , 0 , cmpstr , jo ) ;
fvar = CharToFloat ( cmpstr ) ;
2019-08-05 12:01:23 +01:00
}
switch ( lastop ) {
case OPER_EQU :
if ( glob_script_mem . var_not_found ) {
2020-07-02 05:46:04 +01:00
if ( ! jo ) toLogEOL ( " var not found: " , lp ) ;
2019-08-05 12:01:23 +01:00
goto next_line ;
}
2020-09-11 14:44:16 +01:00
* dfvar = fvar ;
2019-08-05 12:01:23 +01:00
break ;
case OPER_PLSEQU :
2020-09-11 14:44:16 +01:00
* dfvar + = fvar ;
2019-08-05 12:01:23 +01:00
break ;
case OPER_MINEQU :
2020-09-11 14:44:16 +01:00
* dfvar - = fvar ;
2019-08-05 12:01:23 +01:00
break ;
case OPER_MULEQU :
2020-09-11 14:44:16 +01:00
* dfvar * = fvar ;
2019-08-05 12:01:23 +01:00
break ;
case OPER_DIVEQU :
2020-09-11 14:44:16 +01:00
* dfvar / = fvar ;
2019-08-05 12:01:23 +01:00
break ;
case OPER_PERCEQU :
2020-09-11 14:44:16 +01:00
* dfvar = fmodf ( * dfvar , fvar ) ;
2019-08-05 12:01:23 +01:00
break ;
case OPER_ANDEQU :
2020-09-11 14:44:16 +01:00
* dfvar = ( uint32_t ) * dfvar & ( uint32_t ) fvar ;
2019-08-05 12:01:23 +01:00
break ;
case OPER_OREQU :
2020-09-11 14:44:16 +01:00
* dfvar = ( uint32_t ) * dfvar | ( uint32_t ) fvar ;
2019-08-05 12:01:23 +01:00
break ;
case OPER_XOREQU :
2020-09-11 14:44:16 +01:00
* dfvar = ( uint32_t ) * dfvar ^ ( uint32_t ) fvar ;
2019-08-05 12:01:23 +01:00
break ;
default :
// error
break ;
}
// var was changed
2020-09-11 14:44:16 +01:00
glob_script_mem . type [ globvindex ] . bits . changed = 1 ;
2020-06-13 12:05:25 +01:00
# ifdef USE_SCRIPT_GLOBVARS
if ( glob_script_mem . type [ globvindex ] . bits . global ) {
2020-09-11 14:44:16 +01:00
script_udp_sendvar ( varname , dfvar , 0 ) ;
2020-06-13 12:05:25 +01:00
}
2020-09-11 14:44:16 +01:00
# endif //USE_SCRIPT_GLOBVARS
2019-08-05 12:01:23 +01:00
if ( glob_script_mem . type [ globvindex ] . bits . is_filter ) {
if ( globaindex > = 0 ) {
2020-09-11 14:44:16 +01:00
Set_MFVal ( glob_script_mem . type [ globvindex ] . index , globaindex , * dfvar ) ;
2019-08-05 12:01:23 +01:00
} else {
2020-09-11 14:44:16 +01:00
Set_MFilter ( glob_script_mem . type [ globvindex ] . index , * dfvar ) ;
2019-08-05 12:01:23 +01:00
}
}
2019-05-18 08:45:04 +01:00
2019-08-05 12:01:23 +01:00
if ( sysv_type ) {
switch ( sysv_type ) {
case SCRIPT_LOGLEVEL :
2020-09-11 14:44:16 +01:00
glob_script_mem . script_loglevel = * dfvar ;
2019-08-05 12:01:23 +01:00
break ;
case SCRIPT_TELEPERIOD :
2020-09-11 14:44:16 +01:00
if ( * dfvar < 10 ) * dfvar = 10 ;
if ( * dfvar > 300 ) * dfvar = 300 ;
Settings . tele_period = * dfvar ;
2019-08-05 12:01:23 +01:00
break ;
2020-07-16 16:15:12 +01:00
case SCRIPT_EVENT_HANDLED :
2020-09-11 14:44:16 +01:00
event_handeled = * dfvar ;
2020-07-16 16:15:12 +01:00
break ;
2019-05-18 08:45:04 +01:00
}
2020-09-11 14:44:16 +01:00
sysv_type = 0 ;
2019-08-05 12:01:23 +01:00
}
2019-05-22 11:33:51 +01:00
} else {
2019-08-05 12:01:23 +01:00
// string result
2020-09-11 14:44:16 +01:00
numeric = 0 ;
sindex = index ;
saindex = last_sindex ;
2019-08-05 12:01:23 +01:00
// string result
char str [ SCRIPT_MAXSSIZE ] ;
2020-09-11 14:44:16 +01:00
lp = getop ( lp , & lastop ) ;
char * slp = lp ;
glob_script_mem . glob_error = 0 ;
lp = GetStringArgument ( lp , OPER_EQU , str , jo ) ;
2020-07-02 05:46:04 +01:00
if ( ! jo & & glob_script_mem . glob_error ) {
2019-08-05 12:01:23 +01:00
// mismatch
2020-09-11 14:44:16 +01:00
lp = GetNumericArgument ( slp , OPER_EQU , & fvar , 0 ) ;
dtostrfd ( fvar , 6 , str ) ;
glob_script_mem . glob_error = 0 ;
2019-08-05 12:01:23 +01:00
}
2019-05-18 08:45:04 +01:00
2019-08-05 12:01:23 +01:00
if ( ! glob_script_mem . var_not_found ) {
// var was changed
2020-09-11 14:44:16 +01:00
glob_script_mem . type [ globvindex ] . bits . changed = 1 ;
2020-06-13 12:05:25 +01:00
# ifdef USE_SCRIPT_GLOBVARS
if ( glob_script_mem . type [ globvindex ] . bits . global ) {
2020-09-11 14:44:16 +01:00
script_udp_sendvar ( varname , 0 , str ) ;
2020-06-13 12:05:25 +01:00
}
2020-09-11 14:44:16 +01:00
# endif //USE_SCRIPT_GLOBVARS
2020-06-29 06:06:08 +01:00
if ( saindex > = 0 ) {
if ( lastop = = OPER_EQU ) {
2020-09-23 11:51:35 +01:00
strlcpy ( glob_script_mem . last_index_string [ glob_script_mem . sind_num ] + ( saindex * glob_script_mem . max_ssize ) , str , glob_script_mem . max_ssize ) ;
2020-06-29 06:06:08 +01:00
} else if ( lastop = = OPER_PLSEQU ) {
2020-09-23 11:51:35 +01:00
strncat ( glob_script_mem . last_index_string [ glob_script_mem . sind_num ] + ( saindex * glob_script_mem . max_ssize ) , str , glob_script_mem . max_ssize ) ;
2020-06-29 06:06:08 +01:00
}
2020-09-11 14:44:16 +01:00
last_sindex = - 1 ;
2020-06-29 06:06:08 +01:00
} else {
if ( lastop = = OPER_EQU ) {
2020-09-11 14:44:16 +01:00
strlcpy ( glob_script_mem . glob_snp + ( sindex * glob_script_mem . max_ssize ) , str , glob_script_mem . max_ssize ) ;
2020-06-29 06:06:08 +01:00
} else if ( lastop = = OPER_PLSEQU ) {
2020-09-11 14:44:16 +01:00
strncat ( glob_script_mem . glob_snp + ( sindex * glob_script_mem . max_ssize ) , str , glob_script_mem . max_ssize ) ;
2020-06-29 06:06:08 +01:00
}
2019-08-05 12:01:23 +01:00
}
}
2019-05-18 08:45:04 +01:00
}
2019-08-05 12:01:23 +01:00
}
SCRIPT_SKIP_SPACES
if ( * lp = = ' { ' & & if_state [ ifstck ] = = 3 ) {
2020-09-11 14:44:16 +01:00
lp + = 1 ; // else
2019-08-05 12:01:23 +01:00
//if_state[ifstck]=3;
}
goto next_line ;
}
2019-05-18 08:45:04 +01:00
} else {
2020-05-25 14:49:03 +01:00
//Serial.printf(">> decode %s\n",lp );
2019-05-18 08:45:04 +01:00
// decode line
if ( * lp = = ' > ' & & tlen = = 1 ) {
// called from cmdline
lp + + ;
2020-09-11 14:44:16 +01:00
section = 1 ;
fromscriptcmd = 1 ;
2019-05-18 08:45:04 +01:00
goto startline ;
}
2020-09-11 14:44:16 +01:00
if ( ! strncmp ( lp , type , tlen ) ) {
2019-05-18 08:45:04 +01:00
// found section
2020-09-11 14:44:16 +01:00
section = 1 ;
glob_script_mem . section_ptr = lp ;
2019-08-31 09:10:16 +01:00
if ( check ) {
return 99 ;
}
2019-05-18 08:45:04 +01:00
// check for subroutine
2020-09-11 14:44:16 +01:00
char * ctype = ( char * ) type ;
2019-09-24 07:25:32 +01:00
if ( * ctype = = ' # ' ) {
2019-05-18 08:45:04 +01:00
// check for parameter
2020-09-11 14:44:16 +01:00
ctype + = tlen ;
2021-01-12 04:12:46 +00:00
char nxttok = ' ( ' ;
char * argptr = ctype + tlen ;
2021-01-20 07:49:10 +00:00
2021-01-12 04:12:46 +00:00
lp + = tlen ;
do {
if ( * ctype = = nxttok & & * lp = = nxttok ) {
float fparam ;
numeric = 1 ;
glob_script_mem . glob_error = 0 ;
argptr = GetNumericArgument ( ( char * ) ctype + 1 , OPER_EQU , & fparam , 0 ) ;
if ( glob_script_mem . glob_error = = 1 ) {
// was string, not number
numeric = 0 ;
// get the string
argptr = GetStringArgument ( ( char * ) ctype + 1 , OPER_EQU , cmpstr , 0 ) ;
}
if ( * lp = = nxttok ) {
// fetch destination
lp + + ;
lp = isvar ( lp , & vtype , & ind , 0 , 0 , 0 ) ;
if ( vtype ! = VAR_NV ) {
// found variable as result
uint8_t index = glob_script_mem . type [ ind . index ] . index ;
if ( ( vtype & STYPE ) = = 0 ) {
// numeric result
dfvar = & glob_script_mem . fvars [ index ] ;
if ( numeric ) {
* dfvar = fparam ;
} else {
// mismatch
* dfvar = CharToFloat ( cmpstr ) ;
}
} else {
// string result
sindex = index ;
if ( ! numeric ) {
strlcpy ( glob_script_mem . glob_snp + ( sindex * glob_script_mem . max_ssize ) , cmpstr , glob_script_mem . max_ssize ) ;
} else {
// mismatch
dtostrfd ( fparam , 6 , glob_script_mem . glob_snp + ( sindex * glob_script_mem . max_ssize ) ) ;
}
}
2019-05-18 08:45:04 +01:00
}
}
2021-01-12 04:12:46 +00:00
} else {
if ( * ctype = = nxttok | | ( * lp ! = SCRIPT_EOL & & * lp ! = ' ? ' ) ) {
// revert
section = 0 ;
}
2019-05-18 08:45:04 +01:00
}
2021-01-12 04:12:46 +00:00
nxttok = ' ' ;
ctype = argptr ;
} while ( * lp = = ' ' & & ( section = = 1 ) ) ;
2019-05-18 08:45:04 +01:00
}
}
}
// next line
next_line :
if ( * lp = = SCRIPT_EOL ) {
lp + + ;
} else {
lp = strchr ( lp , SCRIPT_EOL ) ;
2019-09-24 07:25:32 +01:00
if ( ! lp ) {
if ( section ) {
return 0 ;
} else {
return - 1 ;
}
}
2019-05-18 08:45:04 +01:00
lp + + ;
}
}
2019-09-24 07:25:32 +01:00
return - 1 ;
2019-05-18 08:45:04 +01:00
}
uint8_t script_xsns_index = 0 ;
2019-05-30 12:23:54 +01:00
void ScripterEvery100ms ( void ) {
2020-10-28 16:32:07 +00:00
if ( Settings . rule_enabled & & ( TasmotaGlobal . uptime > 4 ) ) {
2020-10-30 11:29:48 +00:00
ResponseClear ( ) ;
2020-10-29 12:37:09 +00:00
uint16_t script_tele_period_save = TasmotaGlobal . tele_period ;
TasmotaGlobal . tele_period = 2 ;
2019-05-18 08:45:04 +01:00
XsnsNextCall ( FUNC_JSON_APPEND , script_xsns_index ) ;
2020-10-29 12:37:09 +00:00
TasmotaGlobal . tele_period = script_tele_period_save ;
2020-10-30 11:29:48 +00:00
if ( strlen ( TasmotaGlobal . mqtt_data ) ) {
TasmotaGlobal . mqtt_data [ 0 ] = ' { ' ;
snprintf_P ( TasmotaGlobal . mqtt_data , sizeof ( TasmotaGlobal . mqtt_data ) , PSTR ( " %s} " ) , TasmotaGlobal . mqtt_data ) ;
Run_Scripter ( " >T " , 2 , TasmotaGlobal . mqtt_data ) ;
2019-05-18 08:45:04 +01:00
}
}
2020-07-16 16:15:12 +01:00
if ( Settings . rule_enabled ) {
2020-09-11 14:44:16 +01:00
if ( fast_script = = 99 ) Run_Scripter ( " >F " , 2 , 0 ) ;
2020-07-16 16:15:12 +01:00
}
2019-05-18 08:45:04 +01:00
}
2019-12-22 14:23:52 +00:00
//mems[5] is 50 bytes in 6.5
2019-05-18 08:45:04 +01:00
// can hold 11 floats or floats + strings
// should report overflow later
void Scripter_save_pvars ( void ) {
2020-09-11 14:44:16 +01:00
int16_t mlen = 0 ;
float * fp = ( float * ) glob_script_mem . script_pram ;
2019-05-18 08:45:04 +01:00
mlen + = sizeof ( float ) ;
2020-09-11 14:44:16 +01:00
struct T_INDEX * vtp = glob_script_mem . type ;
for ( uint8_t count = 0 ; count < glob_script_mem . numvars ; count + + ) {
2019-05-18 08:45:04 +01:00
if ( vtp [ count ] . bits . is_permanent & & ! vtp [ count ] . bits . is_string ) {
2020-09-11 14:44:16 +01:00
uint8_t index = vtp [ count ] . index ;
2020-09-03 11:26:03 +01:00
if ( vtp [ count ] . bits . is_filter ) {
// save array
2020-09-11 14:44:16 +01:00
uint16_t len = 0 ;
float * fa = Get_MFAddr ( index , & len , 0 ) ;
mlen + = sizeof ( float ) * len ;
2020-09-03 11:26:03 +01:00
if ( mlen > glob_script_mem . script_pram_size ) {
2020-09-11 14:44:16 +01:00
vtp [ count ] . bits . is_permanent = 0 ;
2020-09-03 11:26:03 +01:00
return ;
}
while ( len - - ) {
2020-09-11 14:44:16 +01:00
* fp + + = * fa + + ;
2020-09-03 11:26:03 +01:00
}
} else {
2020-09-11 14:44:16 +01:00
mlen + = sizeof ( float ) ;
2020-09-03 11:26:03 +01:00
if ( mlen > glob_script_mem . script_pram_size ) {
2020-09-11 14:44:16 +01:00
vtp [ count ] . bits . is_permanent = 0 ;
2020-09-03 11:26:03 +01:00
return ;
}
2020-09-11 14:44:16 +01:00
* fp + + = glob_script_mem . fvars [ index ] ;
2019-05-18 08:45:04 +01:00
}
}
}
2020-09-11 14:44:16 +01:00
char * cp = ( char * ) fp ;
for ( uint8_t count = 0 ; count < glob_script_mem . numvars ; count + + ) {
2019-05-18 08:45:04 +01:00
if ( vtp [ count ] . bits . is_permanent & & vtp [ count ] . bits . is_string ) {
2020-09-11 14:44:16 +01:00
uint8_t index = vtp [ count ] . index ;
char * sp = glob_script_mem . glob_snp + ( index * glob_script_mem . max_ssize ) ;
uint8_t slen = strlen ( sp ) ;
mlen + = slen + 1 ;
2020-09-03 11:26:03 +01:00
if ( mlen > glob_script_mem . script_pram_size ) {
2020-09-11 14:44:16 +01:00
vtp [ count ] . bits . is_permanent = 0 ;
2019-05-18 08:45:04 +01:00
return ;
}
2020-09-11 14:44:16 +01:00
strcpy ( cp , sp ) ;
cp + = slen + 1 ;
2019-05-18 08:45:04 +01:00
}
}
}
// works only with webserver
# ifdef USE_WEBSERVER
# define WEB_HANDLE_SCRIPT "s10"
const char HTTP_BTN_MENU_RULES [ ] PROGMEM =
" <p><form action=' " WEB_HANDLE_SCRIPT " ' method='get'><button> " D_CONFIGURE_SCRIPT " </button></form></p> " ;
const char HTTP_FORM_SCRIPT [ ] PROGMEM =
2019-05-30 12:23:54 +01:00
" <fieldset><legend><b> " D_SCRIPT " </b></legend> "
2019-05-18 08:45:04 +01:00
" <form method='post' action=' " WEB_HANDLE_SCRIPT " '> " ;
const char HTTP_FORM_SCRIPT1 [ ] PROGMEM =
2019-05-30 12:23:54 +01:00
" <div style='text-align:right' id='charNum'> </div> "
2020-04-05 13:11:49 +01:00
" <label><input style='width:3%%;' id='c%d' name='c%d' type='checkbox'%s><b> " D_SCRIPT_ENABLE " </b></label><br/> "
2019-06-15 06:02:34 +01:00
" <br><textarea id='t1' name='t1' rows='8' cols='80' maxlength='%d' style='font-size: 12pt' > " ;
2019-05-30 12:23:54 +01:00
2019-05-18 08:45:04 +01:00
const char HTTP_FORM_SCRIPT1b [ ] PROGMEM =
2019-05-30 12:23:54 +01:00
" </textarea> "
" <script type='text/javascript'> "
2019-05-31 18:51:24 +01:00
" eb('charNum').innerHTML='-'; "
2019-10-15 19:07:12 +01:00
" var ta=eb('t1'); "
" ta.addEventListener('keydown',function(e){ "
" e = e || window.event; "
2019-05-30 12:23:54 +01:00
" var ml=this.getAttribute('maxlength'); "
" var cl=this.value.length; "
" if(cl>=ml){ "
2019-12-28 17:25:43 +00:00
" eb('charNum').innerHTML=' " D_SCRIPT_CHARS_NO_MORE " '; "
2019-05-30 12:23:54 +01:00
" }else{ "
2019-12-28 17:25:43 +00:00
" eb('charNum').innerHTML=ml-cl+' " D_SCRIPT_CHARS_LEFT " '; "
2019-05-30 12:23:54 +01:00
" } "
2019-10-15 19:07:12 +01:00
#if 0
// catch shift ctrl v
" if ((e.metaKey || e.ctrlKey) && e.shiftKey && e.which === 86) { "
// clipboard fails here
" var paste = window.clipboardData.getData('Text'); "
//"var paste = e.view.clipboardData.getData('Text');"
" var out= \" \" ; "
" var re=/ \\ r \\ n| \\ n \\ r| \\ n| \\ r/g; "
" var allLines=paste.replace(re, \" \\ n \" ).split( \" \\ n \" ); "
" allLines.forEach((line) => { "
" if(line.length>0) { "
" if(line.charAt(0)!=';'){ "
" out+=line+' \\ n'; "
" } "
" } "
" }); "
" alert(out); "
" } "
# endif
" return true; "
2019-05-30 12:23:54 +01:00
" }); "
2019-10-15 19:07:12 +01:00
// this works only once on a reloaded page
# ifdef SCRIPT_STRIP_COMMENTS
" ta.addEventListener('paste',function(e){ "
" let paste = (e.clipboardData || window.clipboardData).getData('text'); "
" var ml=this.getAttribute('maxlength'); "
" if(paste.length>=ml){ "
" var out= \" \" ; "
" var re=/ \\ r \\ n| \\ n \\ r| \\ n| \\ r/g; "
" var allLines=paste.replace(re, \" \\ n \" ).split( \" \\ n \" ); "
" allLines.forEach((line) => { "
" if(line.length>0) { "
" if(line.charAt(0)!=';'){ "
" out+=line+' \\ n'; "
" } "
" } "
" }); "
" event.preventDefault(); "
" eb('t1').textContent=out; "
" } "
// "alert(out);"
// this pastes the text on the wrong position ????
//"const selection = Window.getSelection();"
//"if (!selection.rangeCount) return false;"
//"selection.deleteFromDocument();"
//"selection.getRangeAt(0).insertNode(document.createTextNode(paste));"
//"return true;"
" }); "
2020-09-11 14:44:16 +01:00
# endif //SCRIPT_STRIP_COMMENTS
2019-10-15 19:07:12 +01:00
2019-05-30 12:23:54 +01:00
" </script> " ;
2019-07-09 09:20:11 +01:00
const char HTTP_SCRIPT_FORM_END [ ] PROGMEM =
" <br/> "
" <button name='save' type='submit' formmethod='post' formenctype='multipart/form-data' formaction='/ta' class='button bgrn'> " D_SAVE " </button> "
" </form></fieldset> " ;
2019-06-15 06:02:34 +01:00
2019-05-30 12:23:54 +01:00
# ifdef USE_SCRIPT_FATFS
const char HTTP_FORM_SCRIPT1c [ ] PROGMEM =
2019-12-28 17:25:43 +00:00
" <button name='d%d' type='submit' class='button bgrn'> " D_SCRIPT_DOWNLOAD " '%s'</button> " ;
2021-01-05 15:37:22 +00:00
2019-06-15 06:02:34 +01:00
const char HTTP_FORM_SCRIPT1d [ ] PROGMEM =
2019-12-28 17:25:43 +00:00
" <button method='post' name='upl' type='submit' class='button bgrn'> " D_SCRIPT_UPLOAD_FILES " </button> " ;
2019-05-30 12:23:54 +01:00
2019-06-15 06:02:34 +01:00
const char S_SCRIPT_FILE_UPLOAD [ ] PROGMEM = D_SDCARD_UPLOAD ;
# endif
2020-06-08 08:24:49 +01:00
uint8_t * script_ex_ptr ;
uint16_t uplsize ;
uint8_t sc_state ;
// upload script and start immediately
void script_upload_start ( void ) {
2021-01-01 05:43:50 +00:00
//Script_AddLog_P(LOG_LEVEL_INFO, PSTR("HTP: file upload execute"));
2020-06-08 08:24:49 +01:00
HTTPUpload & upload = Webserver - > upload ( ) ;
if ( upload . status = = UPLOAD_FILE_START ) {
2021-01-01 05:43:50 +00:00
//Script_AddLog_P(LOG_LEVEL_INFO, PSTR("HTP: upload start"));
2020-09-11 14:44:16 +01:00
script_ex_ptr = ( uint8_t * ) glob_script_mem . script_ram ;
2021-01-01 05:43:50 +00:00
//Script_AddLog_P(LOG_LEVEL_INFO, PSTR("HTP: upload file %s, %d"),upload.filename.c_str(),upload.totalSize);
2020-06-08 08:24:49 +01:00
2020-09-11 14:44:16 +01:00
if ( strcmp ( upload . filename . c_str ( ) , " execute_script " ) ) {
Web . upload_error = 1 ;
2020-06-08 08:24:49 +01:00
WSSend ( 500 , CT_PLAIN , F ( " 500: wrong filename " ) ) ;
return ;
}
if ( upload . totalSize > = glob_script_mem . script_size ) {
2020-09-11 14:44:16 +01:00
Web . upload_error = 1 ;
2020-06-08 08:24:49 +01:00
WSSend ( 500 , CT_PLAIN , F ( " 500: file to large " ) ) ;
return ;
}
2020-09-11 14:44:16 +01:00
uplsize = 0 ;
2020-06-08 08:24:49 +01:00
sc_state = bitRead ( Settings . rule_enabled , 0 ) ;
2020-09-11 14:44:16 +01:00
bitWrite ( Settings . rule_enabled , 0 , 0 ) ;
2020-06-08 08:24:49 +01:00
} else if ( upload . status = = UPLOAD_FILE_WRITE ) {
2021-01-01 05:43:50 +00:00
//Script_AddLog_P(LOG_LEVEL_INFO, PSTR("HTP: upload write"));
2020-09-11 14:44:16 +01:00
uint32_t csiz = upload . currentSize ;
uint32_t tsiz = glob_script_mem . script_size - 1 ;
2020-06-08 08:24:49 +01:00
if ( uplsize < tsiz ) {
2020-09-11 14:44:16 +01:00
if ( uplsize + csiz < tsiz ) {
memcpy ( script_ex_ptr , upload . buf , csiz ) ;
script_ex_ptr + = csiz ;
uplsize + = csiz ;
2020-06-08 08:24:49 +01:00
} else {
2020-09-11 14:44:16 +01:00
csiz = tsiz - uplsize ;
memcpy ( script_ex_ptr , upload . buf , csiz ) ;
script_ex_ptr + = csiz ;
uplsize + = csiz ;
2020-06-08 08:24:49 +01:00
}
2021-01-01 05:43:50 +00:00
//Script_AddLog_P(LOG_LEVEL_INFO, PSTR("HTP: write %d - %d"),csiz,uplsize);
2020-06-08 08:24:49 +01:00
}
//if (upload_file) upload_file.write(upload.buf,upload.currentSize);
} else if ( upload . status = = UPLOAD_FILE_END ) {
//if (upload_file) upload_file.close();
if ( Web . upload_error ) {
2021-01-01 05:43:50 +00:00
Script_AddLog_P ( LOG_LEVEL_INFO , PSTR ( " HTP: upload error " ) ) ;
2020-06-08 08:24:49 +01:00
} else {
2020-09-11 14:44:16 +01:00
* script_ex_ptr = 0 ;
bitWrite ( Settings . rule_enabled , 0 , sc_state ) ;
2020-06-08 08:24:49 +01:00
SaveScript ( ) ;
SaveScriptEnd ( ) ;
2021-01-01 05:43:50 +00:00
//Script_AddLog_P(LOG_LEVEL_INFO, PSTR("HTP: upload success"));
2020-06-08 08:24:49 +01:00
}
} else {
2020-09-11 14:44:16 +01:00
Web . upload_error = 1 ;
2020-06-08 08:24:49 +01:00
WSSend ( 500 , CT_PLAIN , F ( " 500: couldn't create file " ) ) ;
}
}
void ScriptExecuteUploadSuccess ( void ) {
WSSend ( 200 , CT_PLAIN , F ( " transfer OK " ) ) ;
}
2019-06-15 06:02:34 +01:00
2019-05-30 12:23:54 +01:00
# ifdef USE_SCRIPT_FATFS
2019-06-15 06:02:34 +01:00
uint8_t DownloadFile ( char * file ) {
File download_file ;
WiFiClient download_Client ;
2021-01-05 15:37:22 +00:00
if ( ! ufsp - > exists ( file ) ) {
2021-01-01 05:43:50 +00:00
Script_AddLog_P ( LOG_LEVEL_INFO , PSTR ( " file not found " ) ) ;
2019-06-15 06:02:34 +01:00
return 0 ;
}
2021-01-05 15:37:22 +00:00
download_file = ufsp - > open ( file , FS_FILE_READ ) ;
2019-06-15 06:02:34 +01:00
if ( ! download_file ) {
2021-01-01 05:43:50 +00:00
Script_AddLog_P ( LOG_LEVEL_INFO , PSTR ( " could not open file " ) ) ;
2019-06-15 06:02:34 +01:00
return 0 ;
}
if ( download_file . isDirectory ( ) ) {
download_file . close ( ) ;
return 1 ;
}
2020-09-11 14:44:16 +01:00
uint32_t flen = download_file . size ( ) ;
2019-06-15 06:02:34 +01:00
2020-04-15 08:58:38 +01:00
download_Client = Webserver - > client ( ) ;
Webserver - > setContentLength ( flen ) ;
2019-06-15 06:02:34 +01:00
char attachment [ 100 ] ;
char * cp ;
2020-09-11 14:44:16 +01:00
for ( uint8_t cnt = strlen ( file ) ; cnt > = 0 ; cnt - - ) {
2019-06-15 06:02:34 +01:00
if ( file [ cnt ] = = ' / ' ) {
2020-09-11 14:44:16 +01:00
cp = & file [ cnt + 1 ] ;
2019-06-15 06:02:34 +01:00
break ;
}
}
2020-09-11 14:44:16 +01:00
snprintf_P ( attachment , sizeof ( attachment ) , PSTR ( " attachment; filename=%s " ) , cp ) ;
2020-04-15 08:58:38 +01:00
Webserver - > sendHeader ( F ( " Content-Disposition " ) , attachment ) ;
2019-06-15 06:02:34 +01:00
WSSend ( 200 , CT_STREAM , " " ) ;
uint8_t buff [ 512 ] ;
uint16_t bread ;
// transfer is about 150kb/s
2020-09-11 14:44:16 +01:00
uint8_t cnt = 0 ;
2019-06-15 06:02:34 +01:00
while ( download_file . available ( ) ) {
2020-09-11 14:44:16 +01:00
bread = download_file . read ( buff , sizeof ( buff ) ) ;
uint16_t bw = download_Client . write ( ( const char * ) buff , bread ) ;
2019-06-15 06:02:34 +01:00
if ( ! bw ) break ;
cnt + + ;
if ( cnt > 7 ) {
2020-09-11 14:44:16 +01:00
cnt = 0 ;
if ( glob_script_mem . script_loglevel & 0x80 ) {
2019-06-15 06:02:34 +01:00
// this indeed multitasks, but is slower 50 kB/s
loop ( ) ;
}
}
}
download_file . close ( ) ;
download_Client . stop ( ) ;
return 0 ;
}
2019-05-30 12:23:54 +01:00
# endif
2019-05-18 08:45:04 +01:00
2019-07-09 09:20:11 +01:00
void HandleScriptTextareaConfiguration ( void ) {
if ( ! HttpCheckPriviledgedAccess ( ) ) { return ; }
2020-04-15 08:58:38 +01:00
if ( Webserver - > hasArg ( " save " ) ) {
2019-07-09 09:20:11 +01:00
ScriptSaveSettings ( ) ;
HandleConfiguration ( ) ;
return ;
}
}
2020-05-02 07:10:23 +01:00
2019-07-09 09:20:11 +01:00
void HandleScriptConfiguration ( void ) {
2019-09-16 18:52:53 +01:00
2019-05-18 08:45:04 +01:00
if ( ! HttpCheckPriviledgedAccess ( ) ) { return ; }
2021-01-01 05:43:50 +00:00
Script_AddLog_P ( LOG_LEVEL_DEBUG , PSTR ( D_LOG_HTTP D_CONFIGURE_SCRIPT ) ) ;
2019-05-18 08:45:04 +01:00
2019-05-30 12:23:54 +01:00
# ifdef USE_SCRIPT_FATFS
2020-04-15 08:58:38 +01:00
if ( Webserver - > hasArg ( " d1 " ) ) {
2019-06-15 06:02:34 +01:00
DownloadFile ( glob_script_mem . flink [ 0 ] ) ;
2019-05-30 12:23:54 +01:00
}
2020-04-15 08:58:38 +01:00
if ( Webserver - > hasArg ( " d2 " ) ) {
2019-06-15 06:02:34 +01:00
DownloadFile ( glob_script_mem . flink [ 1 ] ) ;
}
2019-05-30 12:23:54 +01:00
# endif
2020-11-06 16:09:13 +00:00
WSContentStart_P ( PSTR ( D_CONFIGURE_SCRIPT ) ) ;
2019-05-18 08:45:04 +01:00
WSContentSendStyle ( ) ;
WSContentSend_P ( HTTP_FORM_SCRIPT ) ;
2019-10-15 19:07:12 +01:00
# ifdef xSCRIPT_STRIP_COMMENTS
2020-09-11 14:44:16 +01:00
uint16_t ssize = glob_script_mem . script_size ;
if ( bitRead ( Settings . rule_enabled , 1 ) ) ssize * = 2 ;
2021-01-12 18:31:15 +00:00
WSContentSend_P ( HTTP_FORM_SCRIPT1 , 1 , 1 , bitRead ( Settings . rule_enabled , 0 ) ? PSTR ( " checked " ) : " " , ssize ) ;
2019-10-15 19:07:12 +01:00
# else
2021-01-12 18:31:15 +00:00
WSContentSend_P ( HTTP_FORM_SCRIPT1 , 1 , 1 , bitRead ( Settings . rule_enabled , 0 ) ? PSTR ( " checked " ) : " " , glob_script_mem . script_size ) ;
2019-10-15 19:07:12 +01:00
# endif
2019-05-18 08:45:04 +01:00
2020-12-21 14:55:01 +00:00
// script is to large for WSContentSend_P
2019-05-30 12:23:54 +01:00
if ( glob_script_mem . script_ram [ 0 ] ) {
2020-12-21 14:55:01 +00:00
WSContentFlush ( ) ;
2019-05-30 12:23:54 +01:00
_WSContentSend ( glob_script_mem . script_ram ) ;
2019-05-18 08:45:04 +01:00
}
WSContentSend_P ( HTTP_FORM_SCRIPT1b ) ;
2019-05-30 12:23:54 +01:00
# ifdef USE_SCRIPT_FATFS
2019-06-15 06:02:34 +01:00
if ( glob_script_mem . script_sd_found ) {
WSContentSend_P ( HTTP_FORM_SCRIPT1d ) ;
2020-09-11 14:44:16 +01:00
if ( glob_script_mem . flink [ 0 ] [ 0 ] ) WSContentSend_P ( HTTP_FORM_SCRIPT1c , 1 , glob_script_mem . flink [ 0 ] ) ;
if ( glob_script_mem . flink [ 1 ] [ 0 ] ) WSContentSend_P ( HTTP_FORM_SCRIPT1c , 2 , glob_script_mem . flink [ 1 ] ) ;
2019-06-15 06:02:34 +01:00
}
2020-09-11 14:44:16 +01:00
# endif //USE_SCRIPT_FATFS
2019-05-30 12:23:54 +01:00
2019-07-09 09:20:11 +01:00
WSContentSend_P ( HTTP_SCRIPT_FORM_END ) ;
2019-05-18 08:45:04 +01:00
WSContentSpaceButton ( BUTTON_CONFIGURATION ) ;
WSContentStop ( ) ;
2020-06-08 08:24:49 +01:00
}
void SaveScript ( void ) {
2021-01-05 15:37:22 +00:00
# ifdef USE_UFILESYS
if ( glob_script_mem . FLAGS . fsys = = true ) {
ufsp - > remove ( FAT_SCRIPT_NAME ) ;
File file = ufsp - > open ( FAT_SCRIPT_NAME , FS_FILE_WRITE ) ;
file . write ( ( const uint8_t * ) glob_script_mem . script_ram , strlen ( glob_script_mem . script_ram ) ) ;
file . close ( ) ;
} else {
// fallback to compressed mode
script_compress ( Settings . rules [ 0 ] , MAX_SCRIPT_SIZE - 1 ) ;
}
# else // USE_UFILESYS
2020-06-08 08:24:49 +01:00
# ifdef EEP_SCRIPT_SIZE
2021-01-05 15:37:22 +00:00
// here we handle EEPROM modes
if ( glob_script_mem . FLAGS . eeprom = = true ) {
if ( EEP_SCRIPT_SIZE ! = SPECIAL_EEPMODE_SIZE ) {
EEP_WRITE ( 0 , EEP_SCRIPT_SIZE , glob_script_mem . script_ram ) ;
} else {
uint8_t * ucs ;
ucs = ( uint8_t * ) calloc ( SPI_FLASH_SEC_SIZE + 4 , 1 ) ;
if ( ! script_compress ( ( char * ) ucs , EEP_SCRIPT_SIZE - 1 ) ) {
alt_eeprom_writeBytes ( 0 , EEP_SCRIPT_SIZE , ucs ) ;
}
if ( ucs ) free ( ucs ) ;
2020-12-13 06:32:09 +00:00
}
2020-06-08 08:24:49 +01:00
}
2021-01-05 15:37:22 +00:00
# else
// default mode is compression
script_compress ( Settings . rules [ 0 ] , MAX_SCRIPT_SIZE - 1 ) ;
2020-06-08 08:24:49 +01:00
# endif // EEP_SCRIPT_SIZE
2019-05-18 08:45:04 +01:00
2021-01-05 15:37:22 +00:00
# endif // USE_UFILESYS
2020-06-08 08:24:49 +01:00
}
2019-05-18 08:45:04 +01:00
void ScriptSaveSettings ( void ) {
2020-04-15 08:58:38 +01:00
if ( Webserver - > hasArg ( " c1 " ) ) {
2020-09-11 14:44:16 +01:00
bitWrite ( Settings . rule_enabled , 0 , 1 ) ;
2019-05-18 08:45:04 +01:00
} else {
2020-09-11 14:44:16 +01:00
bitWrite ( Settings . rule_enabled , 0 , 0 ) ;
2019-05-18 08:45:04 +01:00
}
2020-04-15 08:58:38 +01:00
String str = Webserver - > arg ( " t1 " ) ;
2019-05-18 08:45:04 +01:00
if ( * str . c_str ( ) ) {
2019-07-09 09:20:11 +01:00
2020-09-11 14:44:16 +01:00
str . replace ( " \r \n " , " \n " ) ;
str . replace ( " \r " , " \n " ) ;
2019-07-09 09:20:11 +01:00
2020-09-11 14:44:16 +01:00
strlcpy ( glob_script_mem . script_ram , str . c_str ( ) , glob_script_mem . script_size ) ;
2019-05-30 12:23:54 +01:00
2020-05-23 09:24:08 +01:00
if ( glob_script_mem . script_ram [ 0 ] ! = ' > ' & & glob_script_mem . script_ram [ 1 ] ! = ' D ' ) {
2021-01-01 05:43:50 +00:00
Script_AddLog_P ( LOG_LEVEL_INFO , PSTR ( " script error: must start with >D " ) ) ;
2020-05-23 09:24:08 +01:00
bitWrite ( Settings . rule_enabled , 0 , 0 ) ;
}
2020-06-08 08:24:49 +01:00
SaveScript ( ) ;
2020-05-23 09:24:08 +01:00
2019-05-18 08:45:04 +01:00
}
2020-06-08 08:24:49 +01:00
SaveScriptEnd ( ) ;
}
2020-12-13 06:32:09 +00:00
//
uint32_t script_compress ( char * dest , uint32_t size ) {
2021-01-01 05:43:50 +00:00
//Script_AddLog_P(LOG_LEVEL_INFO,PSTR("in string: %s len = %d"),glob_script_mem.script_ram,strlen(glob_script_mem.script_ram));
2020-12-13 06:32:09 +00:00
uint32_t len_compressed = SCRIPT_COMPRESS ( glob_script_mem . script_ram , strlen ( glob_script_mem . script_ram ) , dest , size ) ;
if ( len_compressed > 0 ) {
dest [ len_compressed ] = 0 ;
2021-01-01 05:43:50 +00:00
Script_AddLog_P ( LOG_LEVEL_INFO , PSTR ( " script compressed to %d bytes = %d %% " ) , len_compressed , len_compressed * 100 / strlen ( glob_script_mem . script_ram ) ) ;
2020-12-13 06:32:09 +00:00
return 0 ;
} else {
2021-01-01 05:43:50 +00:00
Script_AddLog_P ( LOG_LEVEL_INFO , PSTR ( " script compress error: %d " ) , len_compressed ) ;
2020-12-13 06:32:09 +00:00
return 1 ;
}
}
//#endif // USE_SCRIPT_COMPRESSION
2020-06-08 08:24:49 +01:00
void SaveScriptEnd ( void ) {
2020-09-17 08:11:24 +01:00
# ifdef USE_SCRIPT_GLOBVARS
Script_Stop_UDP ( ) ;
# endif //USE_SCRIPT_GLOBVARS
2019-05-18 08:45:04 +01:00
if ( glob_script_mem . script_mem ) {
Scripter_save_pvars ( ) ;
free ( glob_script_mem . script_mem ) ;
2020-09-11 14:44:16 +01:00
glob_script_mem . script_mem = 0 ;
glob_script_mem . script_mem_size = 0 ;
2019-05-18 08:45:04 +01:00
}
if ( bitRead ( Settings . rule_enabled , 0 ) ) {
2020-09-17 08:11:24 +01:00
2020-09-11 14:44:16 +01:00
int16_t res = Init_Scripter ( ) ;
2019-05-18 08:45:04 +01:00
if ( res ) {
2021-01-01 05:43:50 +00:00
Script_AddLog_P ( LOG_LEVEL_INFO , PSTR ( " script init error: %d " ) , res ) ;
2019-05-18 08:45:04 +01:00
return ;
}
2020-07-02 05:46:04 +01:00
2020-09-11 14:44:16 +01:00
Run_Scripter ( " >B \n " , 3 , 0 ) ;
Run_Scripter ( " >BS " , 3 , 0 ) ;
2020-07-02 05:46:04 +01:00
2020-09-11 14:44:16 +01:00
fast_script = Run_Scripter ( " >F " , - 2 , 0 ) ;
2019-05-18 08:45:04 +01:00
}
}
2020-09-11 14:44:16 +01:00
# endif // USE_WEBSERVER
2019-05-18 08:45:04 +01:00
2019-09-24 07:25:32 +01:00
2019-10-02 12:38:05 +01:00
# if defined(USE_SCRIPT_HUE) && defined(USE_WEBSERVER) && defined(USE_EMULATION) && defined(USE_EMULATION_HUE) && defined(USE_LIGHT)
2019-09-30 09:25:02 +01:00
# define HUE_DEV_MVNUM 5
# define HUE_DEV_NSIZE 16
struct HUE_SCRIPT {
char name [ HUE_DEV_NSIZE ] ;
uint8_t type ;
uint8_t index [ HUE_DEV_MVNUM ] ;
uint8_t vindex [ HUE_DEV_MVNUM ] ;
} hue_script [ 32 ] ;
const char SCRIPT_HUE_LIGHTS_STATUS_JSON1 [ ] PROGMEM =
" { \" state \" : "
" { \" on \" :{state}, "
" {light_status} "
" \" alert \" : \" none \" , "
" \" effect \" : \" none \" , "
" \" reachable \" :true} "
" , \" type \" : \" {type} \" , "
" \" name \" : \" {j1 \" , "
2019-10-10 12:39:52 +01:00
" \" modelid \" : \" {m1} \" , "
2019-09-30 09:25:02 +01:00
" \" uniqueid \" : \" {j2 \" , "
" \" swversion \" : \" 5.50.1.19085 \" } " ;
2019-10-02 12:38:05 +01:00
/*
const char SCRIPT_HUE_LIGHTS_STATUS_JSON2 [ ] PROGMEM =
" { \" state \" : "
" { \" temperature \" : 2674, "
" \" lastupdated \" : \" 2019-08-04T12:13:04 \" }, "
" \" config \" : { "
" \" on \" : true, "
" \" battery \" : 100, "
" \" reachable \" : true, "
" \" alert \" : \" none \" , "
" \" ledindication \" : false, "
" \" usertest \" : false, "
" \" pending \" : [] "
" }, "
" \" name \" : \" {j1 \" , "
" \" type \" : \" ZLLTemperature \" , "
" \" modelid \" : \" SML001 \" , "
" \" manufacturername \" : \" Philips \" , "
" \" swversion \" : \" 6.1.0.18912 \" , "
" \" uniqueid \" : \" {j2 \" } " ;
*/
const char SCRIPT_HUE_LIGHTS_STATUS_JSON2 [ ] PROGMEM =
" { \" state \" :{ "
" \" presence \" :{state}, "
" \" lastupdated \" : \" 2017-10-01T12:37:30 \" "
" }, "
" \" swupdate \" :{ "
" \" state \" : \" noupdates \" , "
" \" lastinstall \" : null "
" }, "
" \" config \" :{ "
" \" on \" :true, "
" \" battery \" :100, "
" \" reachable \" :true, "
" \" alert \" : \" none \" , "
" \" ledindication \" :false, "
" \" usertest \" :false, "
" \" sensitivity \" :2, "
" \" sensitivitymax \" :2, "
" \" pending \" :[] "
" }, "
" \" name \" : \" {j1 \" , "
" \" type \" : \" ZLLPresence \" , "
" \" modelid \" : \" SML001 \" , "
" \" manufacturername \" : \" Philips \" , "
" \" swversion \" : \" 6.1.0.18912 \" , "
" \" uniqueid \" : \" {j2 \" "
" } " ;
/*
2019-10-10 12:39:52 +01:00
Color Ligh
Dimmable Light
Color Temperature Light
Extended Color Light
On / Off light
ZGPSwitch
ZLLSwitch
CLIPSwitch
CLIPOpenClose
CLIPPresence
CLIPTemperature
CLIPHumidity
Daylight
CLIPLightlevel
2019-10-02 12:38:05 +01:00
temperature ZLLTemperature
lightlevel ZLLLightLevel
presence ZLLPresence
*/
2019-10-10 12:39:52 +01:00
/*
case ' T ' :
response - > replace ( " {type} " , " ZLLTemperature " ) ;
temp = glob_script_mem . fvars [ hue_script [ hue_devs ] . index [ 2 ] - 1 ] ;
light_status + = " \" temperature \" : " ;
light_status + = String ( temp * 100 ) ;
light_status + = " , " ;
break ;
case ' L ' :
response - > replace ( " {type} " , " ZLLLightLevel " ) ;
temp = glob_script_mem . fvars [ hue_script [ hue_devs ] . index [ 2 ] - 1 ] ;
light_status + = " \" lightlevel \" : " ;
light_status + = String ( temp ) ;
light_status + = " , " ;
break ;
case ' P ' :
response - > replace ( " {type} " , " ZLLPresence " ) ;
temp = glob_script_mem . fvars [ hue_script [ hue_devs ] . index [ 0 ] - 1 ] ;
light_status + = " \" presence \" : " ;
if ( temp = = 0 ) light_status + = " false " ;
else light_status + = " true " ;
light_status + = " , " ;
break ;
*/
2019-09-30 09:25:02 +01:00
void Script_HueStatus ( String * response , uint16_t hue_devs ) {
2019-10-02 12:38:05 +01:00
2019-10-10 12:39:52 +01:00
if ( hue_script [ hue_devs ] . type = = ' p ' ) {
2020-09-11 14:44:16 +01:00
* response + = FPSTR ( SCRIPT_HUE_LIGHTS_STATUS_JSON2 ) ;
response - > replace ( " {j1 " , hue_script [ hue_devs ] . name ) ;
2019-10-02 12:38:05 +01:00
response - > replace ( " {j2 " , GetHueDeviceId ( hue_devs ) ) ;
2020-09-11 14:44:16 +01:00
uint8_t pwr = glob_script_mem . fvars [ hue_script [ hue_devs ] . index [ 0 ] - 1 ] ;
2019-10-02 12:38:05 +01:00
response - > replace ( " {state} " , ( pwr ? " true " : " false " ) ) ;
return ;
}
2020-09-11 14:44:16 +01:00
* response + = FPSTR ( SCRIPT_HUE_LIGHTS_STATUS_JSON1 ) ;
uint8_t pwr = glob_script_mem . fvars [ hue_script [ hue_devs ] . index [ 0 ] - 1 ] ;
2019-09-30 09:25:02 +01:00
response - > replace ( " {state} " , ( pwr ? " true " : " false " ) ) ;
String light_status = " " ;
if ( hue_script [ hue_devs ] . index [ 1 ] > 0 ) {
// bri
light_status + = " \" bri \" : " ;
2020-09-11 14:44:16 +01:00
uint32_t bri = glob_script_mem . fvars [ hue_script [ hue_devs ] . index [ 1 ] - 1 ] ;
2019-09-30 09:25:02 +01:00
if ( bri > 254 ) bri = 254 ;
if ( bri < 1 ) bri = 1 ;
light_status + = String ( bri ) ;
light_status + = " , " ;
}
if ( hue_script [ hue_devs ] . index [ 2 ] > 0 ) {
// hue
2020-09-11 14:44:16 +01:00
uint32_t hue = glob_script_mem . fvars [ hue_script [ hue_devs ] . index [ 2 ] - 1 ] ;
2019-09-30 09:25:02 +01:00
//hue = changeUIntScale(hue, 0, 359, 0, 65535);
light_status + = " \" hue \" : " ;
light_status + = String ( hue ) ;
light_status + = " , " ;
}
if ( hue_script [ hue_devs ] . index [ 3 ] > 0 ) {
// sat
2020-09-11 14:44:16 +01:00
uint32_t sat = glob_script_mem . fvars [ hue_script [ hue_devs ] . index [ 3 ] - 1 ] ;
2019-09-30 09:25:02 +01:00
if ( sat > 254 ) sat = 254 ;
if ( sat < 1 ) sat = 1 ;
light_status + = " \" sat \" : " ;
light_status + = String ( sat ) ;
light_status + = " , " ;
}
if ( hue_script [ hue_devs ] . index [ 4 ] > 0 ) {
// ct
2020-09-11 14:44:16 +01:00
uint32_t ct = glob_script_mem . fvars [ hue_script [ hue_devs ] . index [ 4 ] - 1 ] ;
2019-09-30 09:25:02 +01:00
light_status + = " \" ct \" : " ;
light_status + = String ( ct ) ;
light_status + = " , " ;
}
2019-10-02 12:38:05 +01:00
float temp ;
switch ( hue_script [ hue_devs ] . type ) {
2019-10-10 12:39:52 +01:00
case ' C ' :
response - > replace ( " {type} " , " Color Ligh " ) ; // alexa ok
response - > replace ( " {m1 " , " LST001 " ) ;
2019-10-02 12:38:05 +01:00
break ;
2019-10-10 12:39:52 +01:00
case ' D ' :
response - > replace ( " {type} " , " Dimmable Light " ) ; // alexa NO
response - > replace ( " {m1 " , " LWB004 " ) ;
2019-10-02 12:38:05 +01:00
break ;
case ' T ' :
2019-10-10 12:39:52 +01:00
response - > replace ( " {type} " , " Color Temperature Light " ) ; // alexa NO
response - > replace ( " {m1 " , " LTW011 " ) ;
2019-10-02 12:38:05 +01:00
break ;
2019-10-10 12:39:52 +01:00
case ' E ' :
response - > replace ( " {type} " , " Extended color light " ) ; // alexa ok
response - > replace ( " {m1 " , " LCT007 " ) ;
2019-10-02 12:38:05 +01:00
break ;
2019-10-10 12:39:52 +01:00
case ' S ' :
response - > replace ( " {type} " , " On/Off light " ) ; // alexa ok
response - > replace ( " {m1 " , " LCT007 " ) ;
2019-10-02 12:38:05 +01:00
break ;
default :
response - > replace ( " {type} " , " color light " ) ;
2019-10-10 12:39:52 +01:00
response - > replace ( " {m1 " , " LST001 " ) ;
2019-10-02 12:38:05 +01:00
break ;
2019-09-30 09:25:02 +01:00
}
2019-10-02 12:38:05 +01:00
response - > replace ( " {light_status} " , light_status ) ;
2020-09-11 14:44:16 +01:00
response - > replace ( " {j1 " , hue_script [ hue_devs ] . name ) ;
2019-10-02 12:38:05 +01:00
response - > replace ( " {j2 " , GetHueDeviceId ( hue_devs ) ) ;
2019-09-30 09:25:02 +01:00
}
void Script_Check_Hue ( String * response ) {
if ( ! bitRead ( Settings . rule_enabled , 0 ) ) return ;
2020-09-11 14:44:16 +01:00
uint8_t hue_script_found = Run_Scripter ( " >H " , - 2 , 0 ) ;
2019-09-30 09:25:02 +01:00
if ( hue_script_found ! = 99 ) return ;
2020-05-30 09:48:12 +01:00
char tmp [ 256 ] ;
2020-09-11 14:44:16 +01:00
uint8_t hue_devs = 0 ;
uint8_t vindex = 0 ;
2019-09-30 09:25:02 +01:00
char * cp ;
2020-09-11 14:44:16 +01:00
char * lp = glob_script_mem . section_ptr + 2 ;
2019-09-30 09:25:02 +01:00
while ( lp ) {
SCRIPT_SKIP_SPACES
while ( * lp = = SCRIPT_EOL ) {
lp + + ;
}
if ( ! * lp | | * lp = = ' # ' | | * lp = = ' > ' ) {
break ;
}
if ( * lp ! = ' ; ' ) {
// check this line
2020-09-11 14:44:16 +01:00
Replace_Cmd_Vars ( lp , 1 , tmp , sizeof ( tmp ) ) ;
2019-09-30 09:25:02 +01:00
// check for hue defintions
// NAME, TYPE , vars
2020-09-11 14:44:16 +01:00
cp = tmp ;
cp = strchr ( cp , ' , ' ) ;
2019-09-30 09:25:02 +01:00
if ( ! cp ) break ;
2020-09-11 14:44:16 +01:00
* cp = 0 ;
2019-09-30 09:25:02 +01:00
// copy name
2020-09-11 14:44:16 +01:00
strlcpy ( hue_script [ hue_devs ] . name , tmp , HUE_DEV_NSIZE ) ;
2019-09-30 09:25:02 +01:00
cp + + ;
while ( * cp = = ' ' ) cp + + ;
// get type
2020-09-11 14:44:16 +01:00
hue_script [ hue_devs ] . type = * cp ;
2019-09-30 09:25:02 +01:00
2020-09-11 14:44:16 +01:00
for ( vindex = 0 ; vindex < HUE_DEV_MVNUM ; vindex + + ) {
hue_script [ hue_devs ] . index [ vindex ] = 0 ;
2019-09-30 09:25:02 +01:00
}
2020-09-11 14:44:16 +01:00
vindex = 0 ;
2019-09-30 09:25:02 +01:00
while ( 1 ) {
2020-09-11 14:44:16 +01:00
cp = strchr ( cp , ' , ' ) ;
2019-09-30 09:25:02 +01:00
if ( ! cp ) break ;
// get vars, on,hue,sat,bri,ct,
cp + + ;
while ( * cp = = ' ' ) cp + + ;
2020-09-11 14:44:16 +01:00
vindex = = 0xff ;
if ( ! strncmp ( cp , " on= " , 3 ) ) {
cp + = 3 ;
vindex = 0 ;
} else if ( ! strncmp ( cp , " bri= " , 4 ) ) {
cp + = 4 ;
vindex = 1 ;
} else if ( ! strncmp ( cp , " hue= " , 4 ) ) {
cp + = 4 ;
vindex = 2 ;
} else if ( ! strncmp ( cp , " sat= " , 4 ) ) {
cp + = 4 ;
vindex = 3 ;
} else if ( ! strncmp ( cp , " ct= " , 3 ) ) {
cp + = 3 ;
vindex = 4 ;
2019-09-30 09:25:02 +01:00
} else {
// error
2020-09-11 14:44:16 +01:00
vindex = = 0xff ;
2019-09-30 09:25:02 +01:00
break ;
}
if ( vindex ! = 0xff ) {
struct T_INDEX ind ;
uint8_t vtype ;
char vname [ 16 ] ;
2020-09-11 14:44:16 +01:00
for ( uint32_t cnt = 0 ; cnt < sizeof ( vname ) - 1 ; cnt + + ) {
2019-09-30 09:25:02 +01:00
if ( * cp = = ' , ' | | * cp = = 0 ) {
2020-09-11 14:44:16 +01:00
vname [ cnt ] = 0 ;
2019-09-30 09:25:02 +01:00
break ;
}
2020-09-11 14:44:16 +01:00
vname [ cnt ] = * cp + + ;
2019-09-30 09:25:02 +01:00
}
2020-09-11 14:44:16 +01:00
isvar ( vname , & vtype , & ind , 0 , 0 , 0 ) ;
2019-09-30 09:25:02 +01:00
if ( vtype ! = VAR_NV ) {
// found variable as result
if ( vtype = = NUM_RES | | ( vtype & STYPE ) = = 0 ) {
2020-09-11 14:44:16 +01:00
hue_script [ hue_devs ] . vindex [ vindex ] = ind . index ;
hue_script [ hue_devs ] . index [ vindex ] = glob_script_mem . type [ ind . index ] . index + 1 ;
2019-09-30 09:25:02 +01:00
} else {
// break;
}
}
}
}
// append response
if ( response ) {
2020-10-30 11:29:48 +00:00
if ( TasmotaGlobal . devices_present ) {
2020-09-11 14:44:16 +01:00
* response + = " , \" " ;
2019-10-02 12:38:05 +01:00
}
else {
2020-09-11 14:44:16 +01:00
if ( hue_devs > 0 ) * response + = " , \" " ;
else * response + = " \" " ;
2019-10-02 12:38:05 +01:00
}
2020-10-30 11:29:48 +00:00
* response + = String ( EncodeLightId ( hue_devs + TasmotaGlobal . devices_present + 1 ) ) + " \" : " ;
2020-09-11 14:44:16 +01:00
Script_HueStatus ( response , hue_devs ) ;
2021-01-01 05:43:50 +00:00
//Script_AddLog_P(LOG_LEVEL_INFO, PSTR("Hue: %s - %d "),response->c_str(), hue_devs);
2019-09-30 09:25:02 +01:00
}
hue_devs + + ;
}
if ( * lp = = SCRIPT_EOL ) {
lp + + ;
} else {
lp = strchr ( lp , SCRIPT_EOL ) ;
if ( ! lp ) break ;
lp + + ;
}
}
2019-10-10 12:39:52 +01:00
#if 0
2019-10-02 12:38:05 +01:00
if ( response ) {
2021-01-01 05:43:50 +00:00
Script_AddLog_P ( LOG_LEVEL_DEBUG , PSTR ( " Hue: %d " ) , hue_devs ) ;
2019-10-02 12:38:05 +01:00
toLog ( " >>>> " ) ;
toLog ( response - > c_str ( ) ) ;
2021-01-02 15:20:15 +00:00
toLog ( response - > c_str ( ) + MAX_LOGSZ ) ;
2019-10-02 12:38:05 +01:00
}
2019-09-30 09:25:02 +01:00
# endif
}
const char sHUE_LIGHT_RESPONSE_JSON [ ] PROGMEM =
" { \" success \" :{ \" /lights/{id/state/{cm \" :{re}} " ;
2019-10-02 12:38:05 +01:00
const char sHUE_SENSOR_RESPONSE_JSON [ ] PROGMEM =
" { \" success \" :{ \" /lights/{id/state/{cm \" :{re}} " ;
2019-09-30 09:25:02 +01:00
const char sHUE_ERROR_JSON [ ] PROGMEM =
" [{ \" error \" :{ \" type \" :901, \" address \" : \" / \" , \" description \" : \" Internal Error \" }}] " ;
// get alexa arguments
void Script_Handle_Hue ( String * path ) {
String response ;
int code = 200 ;
uint16_t tmp = 0 ;
uint16_t hue = 0 ;
uint8_t sat = 0 ;
uint8_t bri = 254 ;
uint16_t ct = 0 ;
bool resp = false ;
uint8_t device = DecodeLightId ( atoi ( path - > c_str ( ) ) ) ;
2020-10-30 11:29:48 +00:00
uint8_t index = device - TasmotaGlobal . devices_present - 1 ;
2019-09-30 09:25:02 +01:00
2020-04-15 08:58:38 +01:00
if ( Webserver - > args ( ) ) {
2019-09-30 09:25:02 +01:00
response = " [ " ;
2020-09-25 07:52:28 +01:00
JsonParser parser ( ( char * ) Webserver - > arg ( ( Webserver - > args ( ) ) - 1 ) . c_str ( ) ) ;
JsonParserObject root = parser . getRootObject ( ) ;
JsonParserToken hue_on = root [ PSTR ( " on " ) ] ;
if ( hue_on ) {
2019-09-30 09:25:02 +01:00
response + = FPSTR ( sHUE_LIGHT_RESPONSE_JSON ) ;
response . replace ( " {id " , String ( EncodeLightId ( device ) ) ) ;
response . replace ( " {cm " , " on " ) ;
2020-09-25 07:52:28 +01:00
bool on = hue_on . getBool ( ) ;
2020-06-21 08:13:51 +01:00
if ( on = = false ) {
2020-09-11 14:44:16 +01:00
glob_script_mem . fvars [ hue_script [ index ] . index [ 0 ] - 1 ] = 0 ;
2020-06-21 08:13:51 +01:00
response . replace ( " {re " , " false " ) ;
} else {
2020-09-11 14:44:16 +01:00
glob_script_mem . fvars [ hue_script [ index ] . index [ 0 ] - 1 ] = 1 ;
2020-06-21 08:13:51 +01:00
response . replace ( " {re " , " true " ) ;
2019-09-30 09:25:02 +01:00
}
2020-09-11 14:44:16 +01:00
glob_script_mem . type [ hue_script [ index ] . vindex [ 0 ] ] . bits . changed = 1 ;
2019-09-30 09:25:02 +01:00
resp = true ;
}
2020-09-25 07:52:28 +01:00
parser . setCurrent ( ) ;
JsonParserToken hue_bri = root [ PSTR ( " bri " ) ] ;
if ( hue_bri ) { // Brightness is a scale from 1 (the minimum the light is capable of) to 254 (the maximum). Note: a brightness of 1 is not off.
tmp = hue_bri . getUInt ( ) ;
2020-09-11 14:44:16 +01:00
bri = tmp ;
2019-09-30 09:25:02 +01:00
if ( 254 < = bri ) { bri = 255 ; }
if ( resp ) { response + = " , " ; }
response + = FPSTR ( sHUE_LIGHT_RESPONSE_JSON ) ;
response . replace ( " {id " , String ( EncodeLightId ( device ) ) ) ;
response . replace ( " {cm " , " bri " ) ;
response . replace ( " {re " , String ( tmp ) ) ;
2020-09-11 14:44:16 +01:00
glob_script_mem . fvars [ hue_script [ index ] . index [ 1 ] - 1 ] = bri ;
glob_script_mem . type [ hue_script [ index ] . vindex [ 1 ] ] . bits . changed = 1 ;
2019-09-30 09:25:02 +01:00
resp = true ;
}
2020-09-25 07:52:28 +01:00
JsonParserToken hue_xy = root [ PSTR ( " xy " ) ] ;
if ( hue_xy ) { // Saturation of the light. 254 is the most saturated (colored) and 0 is the least saturated (white).
2019-10-02 12:38:05 +01:00
float x , y ;
2020-09-25 07:52:28 +01:00
JsonParserArray arr_xy = JsonParserArray ( hue_xy ) ;
JsonParserToken tok_x = arr_xy [ 0 ] ;
JsonParserToken tok_y = arr_xy [ 1 ] ;
x = tok_x . getFloat ( ) ;
y = tok_y . getFloat ( ) ;
2020-09-25 10:04:22 +01:00
String x_str = tok_x . getStr ( ) ;
String y_str = tok_y . getStr ( ) ;
2019-10-02 12:38:05 +01:00
uint8_t rr , gg , bb ;
2021-01-03 07:17:24 +00:00
XyToRgb ( x , y , & rr , & gg , & bb ) ;
RgbToHsb ( rr , gg , bb , & hue , & sat , nullptr ) ;
2019-10-02 12:38:05 +01:00
if ( resp ) { response + = " , " ; }
response + = FPSTR ( sHUE_LIGHT_RESPONSE_JSON ) ;
response . replace ( " {id " , String ( device ) ) ;
response . replace ( " {cm " , " xy " ) ;
response . replace ( " {re " , " [ " + x_str + " , " + y_str + " ] " ) ;
2020-09-11 14:44:16 +01:00
glob_script_mem . fvars [ hue_script [ index ] . index [ 2 ] - 1 ] = hue ;
glob_script_mem . type [ hue_script [ index ] . vindex [ 2 ] ] . bits . changed = 1 ;
glob_script_mem . fvars [ hue_script [ index ] . index [ 3 ] - 1 ] = sat ;
glob_script_mem . type [ hue_script [ index ] . vindex [ 3 ] ] . bits . changed = 1 ;
2019-10-02 12:38:05 +01:00
resp = true ;
}
2020-09-25 07:52:28 +01:00
JsonParserToken hue_hue = root [ PSTR ( " hue " ) ] ;
if ( hue_hue ) { // The hue value is a wrapping value between 0 and 65535. Both 0 and 65535 are red, 25500 is green and 46920 is blue.
tmp = hue_hue . getUInt ( ) ;
2019-09-30 09:25:02 +01:00
//hue = changeUIntScale(tmp, 0, 65535, 0, 359);
//tmp = changeUIntScale(hue, 0, 359, 0, 65535);
2020-09-11 14:44:16 +01:00
hue = tmp ;
2019-09-30 09:25:02 +01:00
if ( resp ) { response + = " , " ; }
response + = FPSTR ( sHUE_LIGHT_RESPONSE_JSON ) ;
response . replace ( " {id " , String ( EncodeLightId ( device ) ) ) ;
response . replace ( " {cm " , " hue " ) ;
response . replace ( " {re " , String ( tmp ) ) ;
2020-09-11 14:44:16 +01:00
glob_script_mem . fvars [ hue_script [ index ] . index [ 2 ] - 1 ] = hue ;
glob_script_mem . type [ hue_script [ index ] . vindex [ 2 ] ] . bits . changed = 1 ;
2019-09-30 09:25:02 +01:00
resp = true ;
}
2020-09-25 07:52:28 +01:00
JsonParserToken hue_sat = root [ PSTR ( " sat " ) ] ;
if ( hue_sat ) { // Saturation of the light. 254 is the most saturated (colored) and 0 is the least saturated (white).
tmp = hue_sat . getUInt ( ) ;
2020-09-11 14:44:16 +01:00
sat = tmp ;
2019-09-30 09:25:02 +01:00
if ( 254 < = sat ) { sat = 255 ; }
if ( resp ) { response + = " , " ; }
response + = FPSTR ( sHUE_LIGHT_RESPONSE_JSON ) ;
response . replace ( " {id " , String ( EncodeLightId ( device ) ) ) ;
response . replace ( " {cm " , " sat " ) ;
response . replace ( " {re " , String ( tmp ) ) ;
2020-09-11 14:44:16 +01:00
glob_script_mem . fvars [ hue_script [ index ] . index [ 3 ] - 1 ] = sat ;
glob_script_mem . type [ hue_script [ index ] . vindex [ 3 ] ] . bits . changed = 1 ;
2019-09-30 09:25:02 +01:00
resp = true ;
}
2020-09-25 07:52:28 +01:00
JsonParserToken hue_ct = root [ PSTR ( " ct " ) ] ;
if ( hue_ct ) { // Color temperature 153 (Cold) to 500 (Warm)
ct = hue_ct . getUInt ( ) ;
2019-09-30 09:25:02 +01:00
if ( resp ) { response + = " , " ; }
response + = FPSTR ( sHUE_LIGHT_RESPONSE_JSON ) ;
response . replace ( " {id " , String ( EncodeLightId ( device ) ) ) ;
response . replace ( " {cm " , " ct " ) ;
response . replace ( " {re " , String ( ct ) ) ;
2020-09-11 14:44:16 +01:00
glob_script_mem . fvars [ hue_script [ index ] . index [ 4 ] - 1 ] = ct ;
glob_script_mem . type [ hue_script [ index ] . vindex [ 4 ] ] . bits . changed = 1 ;
2019-09-30 09:25:02 +01:00
resp = true ;
}
response + = " ] " ;
} else {
response = FPSTR ( sHUE_ERROR_JSON ) ;
}
2021-01-01 05:43:50 +00:00
Script_AddLog_P ( LOG_LEVEL_DEBUG_MORE , PSTR ( D_LOG_HTTP D_HUE " Result (%s) " ) , response . c_str ( ) ) ;
2019-09-30 09:25:02 +01:00
WSSend ( code , CT_JSON , response ) ;
if ( resp ) {
2020-09-11 14:44:16 +01:00
Run_Scripter ( " >E " , 2 , 0 ) ;
2019-09-30 09:25:02 +01:00
}
}
# endif // hue interface
2019-09-24 07:25:32 +01:00
# ifdef USE_SCRIPT_SUB_COMMAND
bool Script_SubCmd ( void ) {
if ( ! bitRead ( Settings . rule_enabled , 0 ) ) return false ;
2019-09-30 09:25:02 +01:00
if ( tasm_cmd_activ ) return false ;
2021-01-01 05:43:50 +00:00
//Script_AddLog_P(LOG_LEVEL_INFO,PSTR(">> %s, %s, %d, %d "),XdrvMailbox.topic, XdrvMailbox.data, XdrvMailbox.payload, XdrvMailbox.index);
2019-09-30 09:25:02 +01:00
char command [ CMDSZ ] ;
2020-09-11 14:44:16 +01:00
strlcpy ( command , XdrvMailbox . topic , CMDSZ ) ;
2020-12-19 07:09:14 +00:00
if ( XdrvMailbox . index > 1 ) {
char ind [ 2 ] ;
ind [ 0 ] = XdrvMailbox . index | 0x30 ;
ind [ 1 ] = 0 ;
strcat ( command , ind ) ;
}
int32_t pl = XdrvMailbox . payload ;
2019-09-30 09:25:02 +01:00
2019-09-24 07:25:32 +01:00
char cmdbuff [ 128 ] ;
2020-09-11 14:44:16 +01:00
char * cp = cmdbuff ;
* cp + + = ' # ' ;
2020-12-19 07:09:14 +00:00
strcpy ( cp , command ) ;
uint8_t tlen = strlen ( command ) ;
2020-09-11 14:44:16 +01:00
cp + = tlen ;
2020-12-19 07:09:14 +00:00
if ( XdrvMailbox . data_len > 0 ) {
2020-09-11 14:44:16 +01:00
* cp + + = ' ( ' ;
strncpy ( cp , XdrvMailbox . data , XdrvMailbox . data_len ) ;
cp + = XdrvMailbox . data_len ;
* cp + + = ' ) ' ;
* cp = 0 ;
2019-09-24 07:25:32 +01:00
}
//toLog(cmdbuff);
2020-09-11 14:44:16 +01:00
uint32_t res = Run_Scripter ( cmdbuff , tlen + 1 , 0 ) ;
2021-01-01 05:43:50 +00:00
//Script_AddLog_P(LOG_LEVEL_INFO,">>%d",res);
2020-12-19 07:09:14 +00:00
if ( res ) {
return false ;
}
2019-09-30 09:25:02 +01:00
else {
2020-12-19 07:09:14 +00:00
cp = XdrvMailbox . data ;
while ( * cp = = ' ' ) cp + + ;
if ( isdigit ( * cp ) | | * cp = = ' - ' ) {
Response_P ( S_JSON_COMMAND_NVALUE , command , XdrvMailbox . payload ) ;
2019-09-30 09:25:02 +01:00
} else {
2020-12-19 07:09:14 +00:00
Response_P ( S_JSON_COMMAND_SVALUE , command , XdrvMailbox . data ) ;
2019-09-30 09:25:02 +01:00
}
}
return true ;
2019-09-24 07:25:32 +01:00
}
2020-09-11 14:44:16 +01:00
# endif //USE_SCRIPT_SUB_COMMAND
2019-09-24 07:25:32 +01:00
2019-05-18 08:45:04 +01:00
void execute_script ( char * script ) {
2020-09-11 14:44:16 +01:00
char * svd_sp = glob_script_mem . scriptptr ;
strcat ( script , " \n # " ) ;
glob_script_mem . scriptptr = script ;
Run_Scripter ( " > " , 1 , 0 ) ;
glob_script_mem . scriptptr = svd_sp ;
2019-05-18 08:45:04 +01:00
}
2019-07-23 06:01:17 +01:00
# define D_CMND_SCRIPT "Script"
# define D_CMND_SUBSCRIBE "Subscribe"
# define D_CMND_UNSUBSCRIBE "Unsubscribe"
2019-05-18 08:45:04 +01:00
2020-12-21 14:55:01 +00:00
enum ScriptCommands { CMND_SCRIPT , CMND_SUBSCRIBE , CMND_UNSUBSCRIBE , CMND_SUBTEST } ;
const char kScriptCommands [ ] PROGMEM = D_CMND_SCRIPT " | " D_CMND_SUBSCRIBE " | " D_CMND_UNSUBSCRIBE
# ifdef DEBUG_MQTT_EVENT
" | " " SUBTEST "
# endif
;
2019-05-18 08:45:04 +01:00
bool ScriptCommand ( void ) {
char command [ CMDSZ ] ;
bool serviced = true ;
uint8_t index = XdrvMailbox . index ;
2019-09-30 09:25:02 +01:00
if ( tasm_cmd_activ ) return false ;
2019-05-18 08:45:04 +01:00
int command_code = GetCommandCode ( command , sizeof ( command ) , XdrvMailbox . topic , kScriptCommands ) ;
if ( - 1 = = command_code ) {
serviced = false ; // Unknown command
}
else if ( ( CMND_SCRIPT = = command_code ) & & ( index > 0 ) ) {
2019-10-15 19:07:12 +01:00
if ( ( XdrvMailbox . payload > = 0 ) & & ( XdrvMailbox . payload < 4 ) ) {
2019-05-18 08:45:04 +01:00
switch ( XdrvMailbox . payload ) {
case 0 : // Off
case 1 : // On
2019-10-15 19:07:12 +01:00
bitWrite ( Settings . rule_enabled , index - 1 , XdrvMailbox . payload ) ;
break ;
# ifdef xSCRIPT_STRIP_COMMENTS
case 2 :
2020-09-11 14:44:16 +01:00
bitWrite ( Settings . rule_enabled , 1 , 0 ) ;
2019-10-15 19:07:12 +01:00
break ;
case 3 :
2020-09-11 14:44:16 +01:00
bitWrite ( Settings . rule_enabled , 1 , 1 ) ;
2019-10-15 19:07:12 +01:00
break ;
2020-09-11 14:44:16 +01:00
# endif //xSCRIPT_STRIP_COMMENTS
2019-05-18 08:45:04 +01:00
}
} else {
if ( ' > ' = = XdrvMailbox . data [ 0 ] ) {
// execute script
2020-10-30 11:29:48 +00:00
snprintf_P ( TasmotaGlobal . mqtt_data , sizeof ( TasmotaGlobal . mqtt_data ) , PSTR ( " { \" %s \" : \" %s \" } " ) , command , XdrvMailbox . data ) ;
2019-07-09 09:20:11 +01:00
if ( bitRead ( Settings . rule_enabled , 0 ) ) {
2020-09-11 14:44:16 +01:00
for ( uint8_t count = 0 ; count < XdrvMailbox . data_len ; count + + ) {
if ( XdrvMailbox . data [ count ] = = ' ; ' ) XdrvMailbox . data [ count ] = ' \n ' ;
2019-07-09 09:20:11 +01:00
}
execute_script ( XdrvMailbox . data ) ;
}
2019-05-18 08:45:04 +01:00
}
2020-08-02 06:35:25 +01:00
if ( ' ? ' = = XdrvMailbox . data [ 0 ] ) {
2020-09-11 14:44:16 +01:00
char * lp = XdrvMailbox . data ;
2020-08-02 06:35:25 +01:00
lp + + ;
while ( * lp = = ' ' ) lp + + ;
float fvar ;
char str [ SCRIPT_MAXSSIZE ] ;
2020-09-11 14:44:16 +01:00
glob_script_mem . glob_error = 0 ;
GetNumericArgument ( lp , OPER_EQU , & fvar , 0 ) ;
2020-08-02 06:35:25 +01:00
if ( glob_script_mem . glob_error = = 1 ) {
// was string, not number
2020-09-11 14:44:16 +01:00
GetStringArgument ( lp , OPER_EQU , str , 0 ) ;
2020-10-30 11:29:48 +00:00
snprintf_P ( TasmotaGlobal . mqtt_data , sizeof ( TasmotaGlobal . mqtt_data ) , PSTR ( " { \" script \" :{ \" %s \" : \" %s \" }} " ) , lp , str ) ;
2020-08-02 06:35:25 +01:00
} else {
2020-09-11 14:44:16 +01:00
dtostrfd ( fvar , 6 , str ) ;
2020-10-30 11:29:48 +00:00
snprintf_P ( TasmotaGlobal . mqtt_data , sizeof ( TasmotaGlobal . mqtt_data ) , PSTR ( " { \" script \" :{ \" %s \" :%s}} " ) , lp , str ) ;
2020-08-02 06:35:25 +01:00
}
}
2019-07-09 09:20:11 +01:00
return serviced ;
2019-05-18 08:45:04 +01:00
}
2020-10-30 11:29:48 +00:00
snprintf_P ( TasmotaGlobal . mqtt_data , sizeof ( TasmotaGlobal . mqtt_data ) , PSTR ( " { \" %s \" : \" %s \" , \" Free \" :%d} " ) , command , GetStateText ( bitRead ( Settings . rule_enabled , 0 ) ) , glob_script_mem . script_size - strlen ( glob_script_mem . script_ram ) ) ;
2019-09-24 07:25:32 +01:00
# ifdef SUPPORT_MQTT_EVENT
2019-07-23 06:01:17 +01:00
} else if ( CMND_SUBSCRIBE = = command_code ) { //MQTT Subscribe command. Subscribe <Event>, <Topic> [, <Key>]
String result = ScriptSubscribe ( XdrvMailbox . data , XdrvMailbox . data_len ) ;
Response_P ( S_JSON_COMMAND_SVALUE , command , result . c_str ( ) ) ;
} else if ( CMND_UNSUBSCRIBE = = command_code ) { //MQTT Un-subscribe command. UnSubscribe <Event>
String result = ScriptUnsubscribe ( XdrvMailbox . data , XdrvMailbox . data_len ) ;
Response_P ( S_JSON_COMMAND_SVALUE , command , result . c_str ( ) ) ;
2020-12-21 14:55:01 +00:00
# ifdef DEBUG_MQTT_EVENT
} else if ( CMND_SUBTEST = = command_code ) {
XdrvMailbox . topic = ( char * ) " tele " ;
ScriptMqttData ( ) ;
serviced = true ;
# endif
2020-09-11 14:44:16 +01:00
# endif //SUPPORT_MQTT_EVENT
2020-12-21 14:55:01 +00:00
}
2019-05-18 08:45:04 +01:00
return serviced ;
}
2019-06-15 06:02:34 +01:00
# ifdef USE_SCRIPT_FATFS
2019-07-16 15:50:52 +01:00
uint16_t xFAT_DATE ( uint16_t year , uint8_t month , uint8_t day ) {
return ( year - 1980 ) < < 9 | month < < 5 | day ;
}
uint16_t xFAT_TIME ( uint8_t hour , uint8_t minute , uint8_t second ) {
return hour < < 11 | minute < < 5 | second > > 1 ;
}
2019-06-15 06:02:34 +01:00
void dateTime ( uint16_t * date , uint16_t * time ) {
// return date using FAT_DATE macro to format fields
2019-07-16 15:50:52 +01:00
* date = xFAT_DATE ( RtcTime . year , RtcTime . month , RtcTime . day_of_month ) ;
2019-06-15 06:02:34 +01:00
// return time using FAT_TIME macro to format fields
2019-07-16 15:50:52 +01:00
* time = xFAT_TIME ( RtcTime . hour , RtcTime . minute , RtcTime . second ) ;
2019-06-15 06:02:34 +01:00
}
2019-07-16 15:50:52 +01:00
2020-09-11 14:44:16 +01:00
# endif //USE_SCRIPT_FATFS
2019-06-15 06:02:34 +01:00
2021-01-01 05:43:50 +00:00
2019-07-23 06:01:17 +01:00
# ifdef SUPPORT_MQTT_EVENT
2020-05-02 07:10:23 +01:00
2021-01-01 05:43:50 +00:00
//#define DEBUG_MQTT_EVENT
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
// Script_AddLog_P(LOG_LEVEL_INFO, PSTR("Script: 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_MQTT_EVENT
Script_AddLog_P ( LOG_LEVEL_INFO , PSTR ( " Script: 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_MQTT_EVENT
Script_AddLog_P ( LOG_LEVEL_INFO , PSTR ( " Script: 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_MQTT_EVENT
Script_AddLog_P ( LOG_LEVEL_INFO , PSTR ( " Script: token invalid: %s " ) , selem ) ;
# endif
break ;
}
if ( obj . isObject ( ) ) {
lastobj = obj ;
continue ;
}
if ( ! * cp ) break ;
}
strlcpy ( sres , value . c_str ( ) , slen ) ;
return res ;
}
2020-05-02 07:10:23 +01:00
# ifndef MQTT_EVENT_MSIZE
# define MQTT_EVENT_MSIZE 256
# endif
2020-12-21 14:55:01 +00:00
2020-05-02 07:10:23 +01:00
2019-07-23 06:01:17 +01:00
/********************************************************************************************/
/*
* Script : Process received MQTT message .
* If the message is in our subscription list , trigger an event with the value parsed from MQTT data
* Input :
* void - We are going to access XdrvMailbox data directly .
* Return :
* true - The message is consumed .
* false - The message is not in our list .
*/
bool ScriptMqttData ( void )
{
bool serviced = false ;
//toLog(">>> 1");
2020-05-02 07:10:23 +01:00
//toLog(XdrvMailbox.data);
if ( XdrvMailbox . data_len < 1 | | XdrvMailbox . data_len > MQTT_EVENT_MSIZE ) {
2019-07-23 06:01:17 +01:00
return false ;
}
String sTopic = XdrvMailbox . topic ;
String sData = XdrvMailbox . data ;
2020-12-21 14:55:01 +00:00
# ifdef DEBUG_MQTT_EVENT
2021-01-01 05:43:50 +00:00
Script_AddLog_P ( LOG_LEVEL_INFO , PSTR ( " Script: MQTT Topic %s, Event %s " ) , XdrvMailbox . topic , XdrvMailbox . data ) ;
2020-12-21 14:55:01 +00:00
# endif
2019-07-23 06:01:17 +01:00
MQTT_Subscription event_item ;
//Looking for matched topic
for ( uint32_t index = 0 ; index < subscriptions . size ( ) ; index + + ) {
event_item = subscriptions . get ( index ) ;
2020-12-21 14:55:01 +00:00
uint8_t json_valid = 0 ;
2019-07-23 06:01:17 +01:00
2020-12-21 14:55:01 +00:00
# ifdef DEBUG_MQTT_EVENT
2021-01-01 05:43:50 +00:00
Script_AddLog_P ( LOG_LEVEL_INFO , PSTR ( " Script: Match MQTT message Topic %s with subscription topic %s and key %s " ) , sTopic . c_str ( ) , event_item . Topic . c_str ( ) , event_item . Key . c_str ( ) ) ;
2020-12-21 14:55:01 +00:00
# endif
2019-07-23 06:01:17 +01:00
if ( sTopic . startsWith ( event_item . Topic ) ) {
//This topic is subscribed by us, so serve it
serviced = true ;
String value ;
2019-08-31 09:10:16 +01:00
String lkey ;
2019-07-23 06:01:17 +01:00
if ( event_item . Key . length ( ) = = 0 ) { //If did not specify Key
value = sData ;
2021-01-01 05:43:50 +00:00
json_valid = 1 ;
2019-07-23 06:01:17 +01:00
} else { //If specified Key, need to parse Key/Value from JSON data
2020-12-21 14:55:01 +00:00
# ifndef SUPPORT_MQTT_EVENT_MORE
2020-09-25 07:52:28 +01:00
JsonParser parser ( ( char * ) sData . c_str ( ) ) ;
JsonParserObject jsonData = parser . getRootObject ( ) ;
2019-07-23 06:01:17 +01:00
String key1 = event_item . Key ;
String key2 ;
2020-09-25 07:52:28 +01:00
if ( ! jsonData ) break ; //Failed to parse JSON data, ignore this message.
2019-07-23 06:01:17 +01:00
int dot ;
if ( ( dot = key1 . indexOf ( ' . ' ) ) > 0 ) {
key2 = key1 . substring ( dot + 1 ) ;
key1 = key1 . substring ( 0 , dot ) ;
2020-09-11 14:44:16 +01:00
lkey = key2 ;
2020-09-25 07:52:28 +01:00
JsonParserToken val = jsonData [ key1 . c_str ( ) ] . getObject ( ) [ key2 . c_str ( ) ] ;
if ( ! val ) break ; //Failed to get the key/value, ignore this message.
value = val . getStr ( ) ;
2020-12-21 14:55:01 +00:00
json_valid = 1 ;
2019-07-23 06:01:17 +01:00
} else {
2020-09-25 07:52:28 +01:00
JsonParserToken val = jsonData [ key1 . c_str ( ) ] ;
if ( ! val ) break ;
value = val . getStr ( ) ;
2020-09-11 14:44:16 +01:00
lkey = key1 ;
2020-12-21 14:55:01 +00:00
json_valid = 1 ;
}
# else
2021-01-01 05:43:50 +00:00
2020-12-21 14:55:01 +00:00
JsonParser parser ( ( char * ) sData . c_str ( ) ) ;
JsonParserObject obj = parser . getRootObject ( ) ;
2021-01-01 05:43:50 +00:00
char sres [ 64 ] ;
uint32_t res = JsonParsePath ( & obj , event_item . Key . c_str ( ) , ' . ' , NULL , sres , sizeof ( sres ) ) ;
if ( res ) {
json_valid = 1 ;
value = sres ;
2019-07-23 06:01:17 +01:00
}
2020-12-21 14:55:01 +00:00
# endif
2021-01-01 05:43:50 +00:00
if ( json_valid ) {
value . trim ( ) ;
char sbuffer [ 128 ] ;
2019-08-31 09:10:16 +01:00
2021-01-01 05:43:50 +00:00
if ( ! strncmp ( lkey . c_str ( ) , " Epoch " , 5 ) ) {
uint32_t ep = atoi ( value . c_str ( ) ) - ( uint32_t ) EPOCH_OFFSET ;
snprintf_P ( sbuffer , sizeof ( sbuffer ) , PSTR ( " >%s=%d \n " ) , event_item . Event . c_str ( ) , ep ) ;
} else {
snprintf_P ( sbuffer , sizeof ( sbuffer ) , PSTR ( " >%s= \" %s \" \n " ) , event_item . Event . c_str ( ) , value . c_str ( ) ) ;
}
2020-12-21 14:55:01 +00:00
# ifdef DEBUG_MQTT_EVENT
2021-01-01 05:43:50 +00:00
Script_AddLog_P ( LOG_LEVEL_INFO , PSTR ( " Script: setting script var %s " ) , sbuffer ) ;
2020-12-21 14:55:01 +00:00
# endif
2021-01-01 05:43:50 +00:00
//toLog(sbuffer);
execute_script ( sbuffer ) ;
}
2019-08-31 09:10:16 +01:00
}
2019-07-23 06:01:17 +01:00
}
}
return serviced ;
}
/********************************************************************************************/
/*
* Subscribe a MQTT topic ( with or without key ) and assign an event name to it
* Command Subscribe format :
* Subscribe < event_name > , < topic > [ , < key > ]
* This command will subscribe a < topic > and give it an event name < event_name > .
* The optional parameter < key > is for parse the specified key / value from MQTT message
* payload with JSON format .
* Subscribe
* Subscribe command without any parameter will list all topics currently subscribed .
* Input :
* data - A char buffer with all the parameters
* data_len - Length of the parameters
* Return :
* A string include subscribed event , topic and key .
*/
String ScriptSubscribe ( const char * data , int data_len )
{
MQTT_Subscription subscription_item ;
String events ;
if ( data_len > 0 ) {
2020-09-11 14:44:16 +01:00
char parameters [ data_len + 1 ] ;
2019-07-23 06:01:17 +01:00
memcpy ( parameters , data , data_len ) ;
parameters [ data_len ] = ' \0 ' ;
String event_name , topic , key ;
char * pos = strtok ( parameters , " , " ) ;
if ( pos ) {
event_name = Trim ( pos ) ;
pos = strtok ( nullptr , " , " ) ;
if ( pos ) {
topic = Trim ( pos ) ;
pos = strtok ( nullptr , " , " ) ;
if ( pos ) {
key = Trim ( pos ) ;
}
}
}
2021-01-01 05:43:50 +00:00
//Script_AddLog_P(LOG_LEVEL_DEBUG, PSTR("Script: Subscribe command with parameters: %s, %s, %s."), event_name.c_str(), topic.c_str(), key.c_str());
2019-07-23 06:01:17 +01:00
//event_name.toUpperCase();
if ( event_name . length ( ) > 0 & & topic . length ( ) > 0 ) {
//Search all subscriptions
2020-09-11 14:44:16 +01:00
for ( uint32_t index = 0 ; index < subscriptions . size ( ) ; index + + ) {
2019-07-23 06:01:17 +01:00
if ( subscriptions . get ( index ) . Event . equals ( event_name ) ) {
//If find exists one, remove it.
String stopic = subscriptions . get ( index ) . Topic + " /# " ;
MqttUnsubscribe ( stopic . c_str ( ) ) ;
subscriptions . remove ( index ) ;
break ;
}
}
//Add "/#" to the topic
if ( ! topic . endsWith ( " # " ) ) {
if ( topic . endsWith ( " / " ) ) {
topic . concat ( " # " ) ;
} else {
topic . concat ( " /# " ) ;
}
}
2021-01-01 05:43:50 +00:00
// Script_AddLog_P(LOG_LEVEL_DEBUG, PSTR("Script: New topic: %s."), topic.c_str());
2019-07-23 06:01:17 +01:00
//MQTT Subscribe
subscription_item . Event = event_name ;
subscription_item . Topic = topic . substring ( 0 , topic . length ( ) - 2 ) ; //Remove "/#" so easy to match
subscription_item . Key = key ;
subscriptions . add ( subscription_item ) ;
MqttSubscribe ( topic . c_str ( ) ) ;
events . concat ( event_name + " , " + topic
+ ( key . length ( ) > 0 ? " , " : " " )
+ key ) ;
} else {
events = D_JSON_WRONG_PARAMETERS ;
}
} else {
//If did not specify the event name, list all subscribed event
2020-09-11 14:44:16 +01:00
for ( uint32_t index = 0 ; index < subscriptions . size ( ) ; index + + ) {
2019-07-23 06:01:17 +01:00
subscription_item = subscriptions . get ( index ) ;
events . concat ( subscription_item . Event + " , " + subscription_item . Topic
+ ( subscription_item . Key . length ( ) > 0 ? " , " : " " )
+ subscription_item . Key + " ; " ) ;
}
}
return events ;
}
/********************************************************************************************/
/*
* Unsubscribe specified MQTT event . If no event specified , Unsubscribe all .
* Command Unsubscribe format :
* Unsubscribe [ < event_name > ]
* Input :
* data - Event name
* data_len - Length of the parameters
* Return :
* list all the events unsubscribed .
*/
String ScriptUnsubscribe ( const char * data , int data_len )
{
MQTT_Subscription subscription_item ;
String events ;
if ( data_len > 0 ) {
for ( uint32_t index = 0 ; index < subscriptions . size ( ) ; index + + ) {
subscription_item = subscriptions . get ( index ) ;
if ( subscription_item . Event . equalsIgnoreCase ( data ) ) {
String stopic = subscription_item . Topic + " /# " ;
MqttUnsubscribe ( stopic . c_str ( ) ) ;
events = subscription_item . Event ;
subscriptions . remove ( index ) ;
break ;
}
}
} else {
//If did not specify the event name, unsubscribe all event
String stopic ;
while ( subscriptions . size ( ) > 0 ) {
events . concat ( subscriptions . get ( 0 ) . Event + " ; " ) ;
stopic = subscriptions . get ( 0 ) . Topic + " /# " ;
MqttUnsubscribe ( stopic . c_str ( ) ) ;
subscriptions . remove ( 0 ) ;
}
}
return events ;
}
# endif // SUPPORT_MQTT_EVENT
2019-09-16 18:52:53 +01:00
2019-10-20 10:21:25 +01:00
# ifdef USE_SCRIPT_WEB_DISPLAY
2020-06-26 08:22:57 +01:00
# ifdef SCRIPT_FULL_WEBPAGE
const char HTTP_WEB_FULL_DISPLAY [ ] PROGMEM =
" <p><form action=' " " sfd " " ' method='get'><button> " " %s " " </button></form></p> " ;
const char HTTP_SCRIPT_FULLPAGE1 [ ] PROGMEM =
" <!DOCTYPE html><html lang= \" " D_HTML_LANGUAGE " \" class= \" \" > "
" <head> "
" <meta charset='utf-8'> "
" <meta name= \" viewport \" content= \" width=device-width,initial-scale=1,user-scalable=no \" /> "
" <title>%s - %s</title> "
" <script> "
" var x=null,lt,to,tp,pc=''; " // x=null allow for abortion
" function eb(s){ "
" return document.getElementById(s); " // Alias to save code space
" } "
" function qs(s){ " // Alias to save code space
" return document.querySelector(s); "
" } "
" function wl(f){ " // Execute multiple window.onload
" window.addEventListener('load',f); "
" } "
" var rfsh=1; "
" function la(p){ "
" var a=''; "
" if(la.arguments.length==1){ "
" a=p; "
" clearTimeout(lt); "
" } "
" if(x!=null){x.abort();} " // Abort if no response within 2 seconds (happens on restart 1)
" x=new XMLHttpRequest(); "
" x.onreadystatechange=function(){ "
" if(x.readyState==4&&x.status==200){ "
" var s=x.responseText.replace(/{t}/g, \" <table style='width:100%%'> \" ).replace(/{s}/g, \" <tr><th> \" ).replace(/{m}/g, \" </th><td> \" ).replace(/{e}/g, \" </td></tr> \" ).replace(/{c}/g, \" %%'><div style='text-align:center;font-weight: \" ); "
" eb('l1').innerHTML=s; "
" } "
" }; "
" if (rfsh) { "
" x.open('GET','./sfd?m=1'+a,true); " // ?m related to Webserver->hasArg("m")
" x.send(); "
" lt=setTimeout(la,%d); " // Settings.web_refresh
" } "
" } " ;
const char HTTP_SCRIPT_FULLPAGE2 [ ] PROGMEM =
" function seva(par,ivar){ "
" la('&sv='+ivar+'_'+par); "
" } "
" function siva(par,ivar){ "
" rfsh=1; "
" la('&sv='+ivar+'_'+par); "
" rfsh=0; "
" } "
" function pr(f){ "
" if (f) { "
" lt=setTimeout(la,%d); "
" rfsh=1; "
" } else { "
" clearTimeout(lt); "
" rfsh=0; "
" } "
" } "
" </script> " ;
# ifdef USE_SCRIPT_FATFS
const char HTTP_SCRIPT_MIMES [ ] PROGMEM =
" HTTP/1.1 200 OK \r \n "
" Content-disposition: inline; filename=%s "
" Content-type: %s \r \n \r \n " ;
void ScriptGetSDCard ( void ) {
2020-08-02 06:35:25 +01:00
2020-06-26 08:22:57 +01:00
if ( ! HttpCheckPriviledgedAccess ( ) ) { return ; }
String stmp = Webserver - > uri ( ) ;
2020-09-11 14:44:16 +01:00
char * cp = strstr_P ( stmp . c_str ( ) , PSTR ( " /sdc/ " ) ) ;
2020-06-26 08:22:57 +01:00
// if (cp) Serial.printf(">>>%s\n",cp);
if ( cp ) {
# ifdef ESP32
2020-09-11 14:44:16 +01:00
cp + = 4 ;
2020-06-26 08:22:57 +01:00
# else
2020-09-11 14:44:16 +01:00
cp + = 5 ;
2020-06-26 08:22:57 +01:00
# endif
2020-09-11 14:44:16 +01:00
if ( strstr_P ( cp , PSTR ( " scrdmp.bmp " ) ) ) {
2020-06-26 08:22:57 +01:00
SendFile ( cp ) ;
return ;
2020-08-02 06:35:25 +01:00
} else {
2021-01-05 15:37:22 +00:00
if ( ufsp - > exists ( cp ) ) {
2020-08-02 06:35:25 +01:00
SendFile ( cp ) ;
return ;
}
2020-06-26 08:22:57 +01:00
}
}
HandleNotFound ( ) ;
}
2020-08-02 06:35:25 +01:00
extern uint8_t * buffer ;
2020-06-26 08:22:57 +01:00
void SendFile ( char * fname ) {
char buff [ 512 ] ;
const char * mime ;
2020-09-11 14:44:16 +01:00
uint8_t sflg = 0 ;
char * jpg = strstr ( fname , " .jpg " ) ;
2020-06-26 08:22:57 +01:00
if ( jpg ) {
2020-09-11 14:44:16 +01:00
mime = " image/jpeg " ;
2020-06-26 08:22:57 +01:00
}
2020-08-02 06:35:25 +01:00
# ifdef USE_DISPLAY_DUMP
2020-09-11 14:44:16 +01:00
char * sbmp = strstr_P ( fname , PSTR ( " scrdmp.bmp " ) ) ;
2020-08-02 06:35:25 +01:00
if ( sbmp ) {
2020-09-11 14:44:16 +01:00
mime = " image/bmp " ;
sflg = 1 ;
2020-08-02 06:35:25 +01:00
}
# endif // USE_DISPLAY_DUMP
2020-09-11 14:44:16 +01:00
char * bmp = strstr ( fname , " .bmp " ) ;
2020-08-02 06:35:25 +01:00
if ( bmp ) {
2020-09-11 14:44:16 +01:00
mime = " image/bmp " ;
2020-08-02 06:35:25 +01:00
}
2020-09-11 14:44:16 +01:00
char * html = strstr ( fname , " .html " ) ;
2020-06-26 08:22:57 +01:00
if ( html ) {
2020-09-11 14:44:16 +01:00
mime = " text/html " ;
2020-06-26 08:22:57 +01:00
}
2020-09-11 14:44:16 +01:00
char * txt = strstr ( fname , " .txt " ) ;
2020-06-26 08:22:57 +01:00
if ( txt ) {
2020-09-11 14:44:16 +01:00
mime = " text/plain " ;
2020-06-26 08:22:57 +01:00
}
2020-09-11 14:44:16 +01:00
WSContentSend_P ( HTTP_SCRIPT_MIMES , fname , mime ) ;
2020-06-26 08:22:57 +01:00
2020-08-02 06:35:25 +01:00
if ( sflg ) {
# ifdef USE_DISPLAY_DUMP
// screen copy
# define fileHeaderSize 14
# define infoHeaderSize 40
if ( buffer ) {
2020-09-11 14:44:16 +01:00
uint8_t * bp = buffer ;
uint8_t * lbuf = ( uint8_t * ) calloc ( Settings . display_width + 2 , 3 ) ;
2020-08-02 06:35:25 +01:00
uint8_t * lbp ;
uint8_t fileHeader [ fileHeaderSize ] ;
createBitmapFileHeader ( Settings . display_height , Settings . display_width , fileHeader ) ;
Webserver - > client ( ) . write ( ( uint8_t * ) fileHeader , fileHeaderSize ) ;
uint8_t infoHeader [ infoHeaderSize ] ;
createBitmapInfoHeader ( Settings . display_height , Settings . display_width , infoHeader ) ;
Webserver - > client ( ) . write ( ( uint8_t * ) infoHeader , infoHeaderSize ) ;
2020-09-11 14:44:16 +01:00
for ( uint32_t lins = 0 ; lins < Settings . display_height ; lins + + ) {
lbp = lbuf + ( Settings . display_width * 3 ) ;
for ( uint32_t cols = 0 ; cols < Settings . display_width ; cols + = 8 ) {
uint8_t bits = 0x80 ;
2020-08-02 06:35:25 +01:00
while ( bits ) {
2020-09-11 14:44:16 +01:00
if ( ! ( ( * bp ) & bits ) ) {
* - - lbp = 0xff ;
* - - lbp = 0xff ;
* - - lbp = 0xff ;
2020-08-02 06:35:25 +01:00
} else {
2020-09-11 14:44:16 +01:00
* - - lbp = 0 ;
* - - lbp = 0 ;
* - - lbp = 0 ;
2020-08-02 06:35:25 +01:00
}
2020-09-11 14:44:16 +01:00
bits = bits > > 1 ;
2020-08-02 06:35:25 +01:00
}
bp + + ;
}
2020-09-11 14:44:16 +01:00
Webserver - > client ( ) . write ( ( const char * ) lbuf , Settings . display_width * 3 ) ;
2020-08-02 06:35:25 +01:00
}
if ( lbuf ) free ( lbuf ) ;
Webserver - > client ( ) . stop ( ) ;
}
# endif // USE_DISPLAY_DUMP
} else {
2021-01-05 15:37:22 +00:00
File file = ufsp - > open ( fname , FS_FILE_READ ) ;
2020-08-02 06:35:25 +01:00
uint32_t siz = file . size ( ) ;
2020-09-11 14:44:16 +01:00
uint32_t len = sizeof ( buff ) ;
2020-08-02 06:35:25 +01:00
while ( siz > 0 ) {
2020-09-11 14:44:16 +01:00
if ( len > siz ) len = siz ;
file . read ( ( uint8_t * ) buff , len ) ;
2020-06-26 08:22:57 +01:00
Webserver - > client ( ) . write ( ( const char * ) buff , len ) ;
siz - = len ;
2020-08-02 06:35:25 +01:00
}
file . close ( ) ;
2020-06-26 08:22:57 +01:00
}
Webserver - > client ( ) . stop ( ) ;
}
2020-06-29 06:06:08 +01:00
# endif // USE_SCRIPT_FATFS
2020-06-26 08:22:57 +01:00
void ScriptFullWebpage ( void ) {
uint32_t fullpage_refresh = 10000 ;
if ( ! HttpCheckPriviledgedAccess ( ) ) { return ; }
String stmp = Webserver - > uri ( ) ;
if ( Webserver - > hasArg ( " m " ) ) { // Status refresh requested
if ( Webserver - > hasArg ( " sv " ) ) {
Script_Check_HTML_Setvars ( ) ;
}
WSContentBegin ( 200 , CT_HTML ) ;
ScriptWebShow ( ' w ' ) ;
WSContentEnd ( ) ;
2021-01-01 05:43:50 +00:00
//Serial.printf("fwp update sv %s\n",stmp.c_str() );
2020-06-26 08:22:57 +01:00
return ; //goto redraw;
// } else {
// Serial.printf("fwp update %s\n",stmp.c_str() );
// }
return ;
} else {
2021-01-01 05:43:50 +00:00
//Serial.printf("fwp other %s\n",stmp.c_str() );
2020-06-26 08:22:57 +01:00
}
WSContentBegin ( 200 , CT_HTML ) ;
2020-09-11 14:44:16 +01:00
const char * title = " Full Screen " ;
2020-06-26 08:22:57 +01:00
WSContentSend_P ( HTTP_SCRIPT_FULLPAGE1 , SettingsText ( SET_DEVICENAME ) , title , fullpage_refresh ) ;
WSContentSend_P ( HTTP_SCRIPT_FULLPAGE2 , fullpage_refresh ) ;
//WSContentSend_P(PSTR("<div id='l1' name='l1'></div>"));
//WSContentSendStyle();
WSContentSend_P ( PSTR ( " <div id='l1' name='l1'> " ) ) ;
ScriptWebShow ( ' w ' ) ;
WSContentSend_P ( PSTR ( " </div> " ) ) ;
ScriptWebShow ( ' x ' ) ;
WSContentStop ( ) ;
}
# endif //SCRIPT_FULL_WEBPAGE
2019-09-16 18:52:53 +01:00
void Script_Check_HTML_Setvars ( void ) {
if ( ! HttpCheckPriviledgedAccess ( ) ) { return ; }
2020-04-15 08:58:38 +01:00
if ( Webserver - > hasArg ( " sv " ) ) {
String stmp = Webserver - > arg ( " sv " ) ;
2021-01-01 05:43:50 +00:00
//Serial.printf("fwp has arg dv %s\n", stmp.c_str());
2019-09-16 18:52:53 +01:00
char cmdbuf [ 64 ] ;
2020-09-11 14:44:16 +01:00
memset ( cmdbuf , 0 , sizeof ( cmdbuf ) ) ;
char * cp = cmdbuf ;
* cp + + = ' > ' ;
strncpy ( cp , stmp . c_str ( ) , sizeof ( cmdbuf ) - 1 ) ;
char * cp1 = strchr ( cp , ' _ ' ) ;
2019-09-16 18:52:53 +01:00
if ( ! cp1 ) return ;
2020-09-11 14:44:16 +01:00
* cp1 = 0 ;
2019-09-16 18:52:53 +01:00
char vname [ 32 ] ;
2020-09-11 14:44:16 +01:00
strncpy ( vname , cp , sizeof ( vname ) ) ;
* cp1 = ' = ' ;
2019-09-16 18:52:53 +01:00
cp1 + + ;
struct T_INDEX ind ;
uint8_t vtype ;
2020-09-11 14:44:16 +01:00
isvar ( vname , & vtype , & ind , 0 , 0 , 0 ) ;
2019-09-16 18:52:53 +01:00
if ( vtype ! = NUM_RES & & vtype & STYPE ) {
// string type must insert quotes
2020-09-11 14:44:16 +01:00
uint8_t tlen = strlen ( cp1 ) ;
memmove ( cp1 + 1 , cp1 , tlen ) ;
* cp1 = ' \" ' ;
* ( cp1 + tlen + 1 ) = ' \" ' ;
2019-09-16 18:52:53 +01:00
}
//toLog(cmdbuf);
execute_script ( cmdbuf ) ;
2020-09-11 14:44:16 +01:00
Run_Scripter ( " >E " , 2 , 0 ) ;
2019-09-16 18:52:53 +01:00
}
}
2019-09-24 07:25:32 +01:00
const char SCRIPT_MSG_BUTTONa [ ] PROGMEM =
" <button type='submit' style= \" width:%d%% \" onclick='seva(%d, \" %s \" )'>%s</button> " ;
const char SCRIPT_MSG_BUTTONa_TBL [ ] PROGMEM =
" <td style= \" width:%d%% \" ><button type='submit' onclick='seva(%d, \" %s \" )'>%s</button></td> " ;
const char SCRIPT_MSG_BUTTONb [ ] PROGMEM =
2019-10-02 12:38:05 +01:00
" <img width= \" %d%% \" ></img> " ;
2019-09-24 07:25:32 +01:00
const char SCRIPT_MSG_BUT_START [ ] PROGMEM =
" <div> " ;
const char SCRIPT_MSG_BUT_START_TBL [ ] PROGMEM =
" <table style='width:100%%'><tr> " ;
const char SCRIPT_MSG_BUT_STOP [ ] PROGMEM =
" </div> " ;
const char SCRIPT_MSG_BUT_STOP_TBL [ ] PROGMEM =
" </tr></table> " ;
2019-09-16 18:52:53 +01:00
const char SCRIPT_MSG_SLIDER [ ] PROGMEM =
" <div><span class='p'>%s</span><center><b>%s</b><span class='q'>%s</span></div> "
" <div><input type='range' min='%d' max='%d' value='%d' onchange='seva(value, \" %s \" )'></div> " ;
const char SCRIPT_MSG_CHKBOX [ ] PROGMEM =
" <div><center><label><b>%s</b><input type='checkbox' %s onchange='seva(%d, \" %s \" )'></label></div> " ;
const char SCRIPT_MSG_TEXTINP [ ] PROGMEM =
2019-09-24 07:25:32 +01:00
" <div><center><label><b>%s</b><input type='text' value='%s' style='width:200px' onfocusin='pr(0)' onfocusout='pr(1)' onchange='siva(value, \" %s \" )'></label></div> " ;
const char SCRIPT_MSG_NUMINP [ ] PROGMEM =
" <div><center><label><b>%s</b><input min='%s' max='%s' step='%s' value='%s' type='number' style='width:200px' onfocusin='pr(0)' onfocusout='pr(1)' onchange='siva(value, \" %s \" )'></label></div> " ;
2019-09-16 18:52:53 +01:00
2020-05-23 09:24:08 +01:00
# ifdef USE_GOOGLE_CHARTS
2020-05-18 09:29:32 +01:00
const char SCRIPT_MSG_GTABLE [ ] PROGMEM =
" <script type='text/javascript' src='https://www.gstatic.com/charts/loader.js'></script> "
" <script type='text/javascript'>google.charts.load('current',{packages:['corechart']});</script> "
2020-05-23 09:24:08 +01:00
" <style>.hRow{font-weight:bold;color:black;background-color:lightblue;}.hCol{font-weight:bold;color:black;background-color:lightblue;}.tCell{color:black}</style> "
" <style>#chart1{display: inline-block;margin: 0 auto;#timeline text{fill:magenta;}}</style> " ;
const char SCRIPT_MSG_TABLE [ ] PROGMEM =
" <script type='text/javascript'>google.charts.load('current',{packages:['table']});</script> " ;
const char SCRIPT_MSG_GAUGE [ ] PROGMEM =
" <script type='text/javascript'>google.charts.load('current',{packages:['gauge']});</script> " ;
const char SCRIPT_MSG_TIMELINE [ ] PROGMEM =
" <script type='text/javascript'>google.charts.load('current',{packages:['timeline']});</script> " ;
2020-05-19 15:44:01 +01:00
const char SCRIPT_MSG_GTABLEa [ ] PROGMEM =
" <script language='JavaScript'>function drawChart(){ "
" var cssc={'headerRow':'hRow','rowNumberCell':'hCol','tableCell':'tCell'}; "
" var data=google.visualization.arrayToDataTable([ " ;
2020-05-18 09:29:32 +01:00
2020-05-23 09:24:08 +01:00
const char SCRIPT_MSG_GTABLEd [ ] PROGMEM =
" ['Timeline','start','end'], " ;
2020-12-04 07:57:52 +00:00
const char SCRIPT_MSG_GTABLEe [ ] PROGMEM =
" ['Timeline','Label','start','end'], " ;
2020-05-23 09:24:08 +01:00
//#define CHART_EXTRA_OPTIONS ",width:'640px',height:'480px'"
# define CHART_EXTRA_OPTIONS
2020-05-18 09:29:32 +01:00
const char SCRIPT_MSG_GTABLEb [ ] PROGMEM =
2020-05-19 15:44:01 +01:00
" ]); "
2020-09-11 14:44:16 +01:00
" var options={%s " CHART_EXTRA_OPTIONS " }; " ;
const char SCRIPT_MSG_GTABLEbx [ ] PROGMEM =
2020-05-19 15:44:01 +01:00
" var chart=new google.visualization.%s(document.getElementById('chart%1d')); "
" chart.draw(data,options);} "
2020-05-18 09:29:32 +01:00
" google.charts.setOnLoadCallback(drawChart);</script> " ;
2020-05-19 15:44:01 +01:00
const char SCRIPT_MSG_GOPT1 [ ] PROGMEM =
" title:'%s',isStacked:false " ;
2020-05-18 09:29:32 +01:00
2020-05-25 14:49:03 +01:00
const char SCRIPT_MSG_GAUGEOPT [ ] PROGMEM =
" max:%d,redFrom:%d,redTo:%d,yellowFrom:%d,yellowTo:%d " ;
2020-05-23 09:24:08 +01:00
const char SCRIPT_MSG_GOPT2 [ ] PROGMEM =
" showRowNumber:true,sort:'disable',allowHtml:true,width:'100%%',height:'100%%',cssClassNames:cssc " ;
2020-05-21 05:06:42 +01:00
const char SCRIPT_MSG_GOPT3 [ ] PROGMEM =
2020-05-23 09:24:08 +01:00
" title:'%s',isStacked:false,vAxes:{0:{maxValue:%d},1:{maxValue:%d}},series:{0:{targetAxisIndex:0},1:{targetAxisIndex:1}}%s " ;
2020-05-21 05:06:42 +01:00
2020-05-23 09:24:08 +01:00
const char SCRIPT_MSG_GOPT4 [ ] PROGMEM =
//"hAxis:{minValue:new Date(0,1,1,0,0),maxValue:new Date(0,1,2,0,0),format:'HH:mm'}";
2020-12-04 07:57:52 +00:00
" hAxis:{format:'HH:mm',minValue:new Date(0,0,0,0,0),maxValue:new Date(0,0,0,23,59)},theme: 'maximized' " ;
2020-05-21 05:06:42 +01:00
2020-05-23 09:24:08 +01:00
const char SCRIPT_MSG_GOPT5 [ ] PROGMEM =
2020-12-04 07:57:52 +00:00
" new Date(0,0,0,%d,%d) " ;
2020-05-19 15:44:01 +01:00
2020-09-03 11:26:03 +01:00
const char SCRIPT_MSG_GOPT6 [ ] PROGMEM =
" title:'%s',isStacked:false,vAxis:{viewWindow:{min:%d,max:%d}}%s " ;
2020-05-19 15:44:01 +01:00
const char SCRIPT_MSG_GTE1 [ ] PROGMEM = " '%s' " ;
2019-09-16 18:52:53 +01:00
2020-05-23 09:24:08 +01:00
# define GLIBS_MAIN 1<<0
# define GLIBS_TABLE 1<<1
# define GLIBS_GAUGE 1<<2
# define GLIBS_TIMELINE 1<<3
2020-12-04 07:57:52 +00:00
# ifndef MAX_GARRAY
2020-05-23 09:24:08 +01:00
# define MAX_GARRAY 4
2020-12-04 07:57:52 +00:00
# endif
2020-05-23 09:24:08 +01:00
2020-09-23 11:51:35 +01:00
2020-09-03 11:26:03 +01:00
char * gc_get_arrays ( char * lp , float * * arrays , uint8_t * ranum , uint16_t * rentries , uint16_t * ipos ) {
2020-05-23 09:24:08 +01:00
struct T_INDEX ind ;
uint8_t vtype ;
2020-09-11 14:44:16 +01:00
uint16 entries = 0 ;
uint16_t cipos = 0 ;
2020-05-23 09:24:08 +01:00
2020-09-11 14:44:16 +01:00
uint8_t anum = 0 ;
2020-05-23 09:24:08 +01:00
while ( anum < MAX_GARRAY ) {
if ( * lp = = ' ) ' | | * lp = = 0 ) break ;
2020-09-11 14:44:16 +01:00
char * lp1 = lp ;
2020-05-25 14:49:03 +01:00
float sysvar ;
2020-09-11 14:44:16 +01:00
lp = isvar ( lp , & vtype , & ind , & sysvar , 0 , 0 ) ;
2020-05-23 09:24:08 +01:00
if ( vtype ! = VAR_NV ) {
SCRIPT_SKIP_SPACES
2020-09-11 14:44:16 +01:00
uint8_t index = glob_script_mem . type [ ind . index ] . index ;
2020-05-23 09:24:08 +01:00
if ( ( vtype & STYPE ) = = 0 ) {
// numeric result
//Serial.printf("numeric %d - %d \n",ind.index,index);
if ( glob_script_mem . type [ ind . index ] . bits . is_filter ) {
//Serial.printf("numeric array\n");
2020-09-11 14:44:16 +01:00
uint16_t len = 0 ;
float * fa = Get_MFAddr ( index , & len , & cipos ) ;
2020-09-03 11:26:03 +01:00
//Serial.printf(">> 2 %d\n",len);
2020-05-23 09:24:08 +01:00
if ( fa & & len > = entries ) {
2020-06-05 19:15:16 +01:00
if ( ! entries ) {
entries = len ;
}
2020-05-23 09:24:08 +01:00
// add array to list
2020-09-11 14:44:16 +01:00
arrays [ anum ] = fa ;
2020-05-23 09:24:08 +01:00
anum + + ;
}
2020-05-25 14:49:03 +01:00
} else {
// single numeric
2020-09-11 14:44:16 +01:00
arrays [ anum ] = & glob_script_mem . fvars [ index ] ;
2020-05-25 14:49:03 +01:00
anum + + ;
2020-09-11 14:44:16 +01:00
entries = 1 ;
2020-05-23 09:24:08 +01:00
}
} else {
2020-09-11 14:44:16 +01:00
lp = lp1 ;
2020-05-23 09:24:08 +01:00
break ;
}
}
}
2020-05-25 14:49:03 +01:00
//Serial.printf(">> %d - %d - %d\n",anum,entries,(uint32_t)*arrays[0]);
2020-09-11 14:44:16 +01:00
* ranum = anum ;
* rentries = entries ;
* ipos = cipos ;
2020-05-23 09:24:08 +01:00
return lp ;
}
char * gc_send_labels ( char * lp , uint32_t anum ) {
WSContentSend_PD ( " [ " ) ;
2020-09-11 14:44:16 +01:00
for ( uint32_t cnt = 0 ; cnt < anum + 1 ; cnt + + ) {
2020-05-23 09:24:08 +01:00
char label [ SCRIPT_MAXSSIZE ] ;
2020-09-11 14:44:16 +01:00
lp = GetStringArgument ( lp , OPER_EQU , label , 0 ) ;
2020-05-23 09:24:08 +01:00
SCRIPT_SKIP_SPACES
2020-09-11 14:44:16 +01:00
WSContentSend_PD ( SCRIPT_MSG_GTE1 , label ) ;
2020-05-23 09:24:08 +01:00
//Serial.printf("labels %s\n",label);
if ( cnt < anum ) { WSContentSend_PD ( " , " ) ; }
}
WSContentSend_PD ( " ], " ) ;
return lp ;
}
# endif // USE_GOOGLE_CHARTS
2019-09-16 18:52:53 +01:00
void ScriptGetVarname ( char * nbuf , char * sp , uint32_t blen ) {
uint32_t cnt ;
2020-09-11 14:44:16 +01:00
for ( cnt = 0 ; cnt < blen - 1 ; cnt + + ) {
2019-09-16 18:52:53 +01:00
if ( * sp = = ' ' | | * sp = = ' ) ' ) {
break ;
}
2020-09-11 14:44:16 +01:00
nbuf [ cnt ] = * sp + + ;
2019-09-16 18:52:53 +01:00
}
2020-09-11 14:44:16 +01:00
nbuf [ cnt ] = 0 ;
2019-09-16 18:52:53 +01:00
}
2020-05-02 07:10:23 +01:00
void ScriptWebShow ( char mc ) {
2020-10-23 06:45:35 +01:00
uint8_t web_script ;
glob_script_mem . web_mode = mc ;
2020-06-26 08:22:57 +01:00
if ( mc = = ' w ' | | mc = = ' x ' ) {
if ( mc = = ' x ' ) {
mc = ' $ ' ;
}
2020-09-11 14:44:16 +01:00
web_script = Run_Scripter ( " >w " , - 2 , 0 ) ;
2020-06-26 08:22:57 +01:00
} else {
2020-09-11 14:44:16 +01:00
web_script = Run_Scripter ( " >W " , - 2 , 0 ) ;
2020-06-26 08:22:57 +01:00
}
2019-08-31 09:10:16 +01:00
if ( web_script = = 99 ) {
2020-05-25 14:49:03 +01:00
char tmp [ 256 ] ;
2020-09-11 14:44:16 +01:00
uint8_t optflg = 0 ;
uint8_t chartindex = 1 ;
uint8_t google_libs = 0 ;
char * lp = glob_script_mem . section_ptr + 2 ;
2020-06-26 08:22:57 +01:00
if ( mc = = ' w ' ) {
while ( * lp ) {
if ( * lp = = ' \n ' ) break ;
lp + + ;
}
}
2020-10-19 06:24:18 +01:00
char * cv_ptr ;
float cv_max = 0 ;
float cv_inc = 0 ;
float * cv_count = 0 ;
2019-08-31 09:10:16 +01:00
while ( lp ) {
while ( * lp = = SCRIPT_EOL ) {
lp + + ;
}
if ( ! * lp | | * lp = = ' # ' | | * lp = = ' > ' ) {
break ;
}
2019-09-08 11:14:28 +01:00
if ( * lp ! = ' ; ' ) {
// send this line to web
2020-10-19 06:24:18 +01:00
SCRIPT_SKIP_SPACES
if ( ! strncmp ( lp , " %for " , 5 ) ) {
// for next loop
struct T_INDEX ind ;
uint8_t vtype ;
lp = isvar ( lp + 5 , & vtype , & ind , 0 , 0 , 0 ) ;
if ( ( vtype ! = VAR_NV ) & & ( vtype & STYPE ) = = 0 ) {
uint16_t index = glob_script_mem . type [ ind . index ] . index ;
cv_count = & glob_script_mem . fvars [ index ] ;
SCRIPT_SKIP_SPACES
lp = GetNumericArgument ( lp , OPER_EQU , cv_count , 0 ) ;
SCRIPT_SKIP_SPACES
lp = GetNumericArgument ( lp , OPER_EQU , & cv_max , 0 ) ;
SCRIPT_SKIP_SPACES
lp = GetNumericArgument ( lp , OPER_EQU , & cv_inc , 0 ) ;
cv_ptr = lp ;
goto nextwebline ;
} else {
continue ;
}
} else if ( ! strncmp ( lp , " %next " , 5 ) ) {
if ( cv_count ) {
// for next loop
* cv_count + = cv_inc ;
if ( * cv_count < = cv_max ) {
lp = cv_ptr ;
} else {
cv_count = 0 ;
goto nextwebline ;
}
} else {
goto nextwebline ;
}
2020-10-23 06:45:35 +01:00
} else if ( ! strncmp ( lp , " %=# " , 3 ) ) {
// subroutine
lp = scripter_sub ( lp + 1 , 0 ) ;
goto nextwebline ;
2020-10-19 06:24:18 +01:00
}
2020-09-11 14:44:16 +01:00
Replace_Cmd_Vars ( lp , 1 , tmp , sizeof ( tmp ) ) ;
char * lin = tmp ;
2020-06-26 08:22:57 +01:00
if ( ( ! mc & & ( * lin ! = ' $ ' ) ) | | ( mc = = ' w ' & & ( * lin ! = ' $ ' ) ) ) {
2020-10-23 06:45:35 +01:00
/*if (!mc || mc=='w') {
if ( * lin = = ' $ ' ) {
lin + + ;
if ( ! strncmp ( lin , " gc( " , 3 ) ) {
goto exgc ;
}
} */
2020-05-25 14:49:03 +01:00
// normal web section
if ( * lin = = ' @ ' ) {
lin + + ;
2020-09-11 14:44:16 +01:00
optflg = 1 ;
2019-09-16 18:52:53 +01:00
} else {
2020-09-11 14:44:16 +01:00
optflg = 0 ;
2019-09-16 18:52:53 +01:00
}
2020-05-25 14:49:03 +01:00
// check for input elements
2020-09-11 14:44:16 +01:00
if ( ! strncmp ( lin , " sl( " , 3 ) ) {
2020-05-25 14:49:03 +01:00
// insert slider sl(min max var left mid right)
2020-09-11 14:44:16 +01:00
char * lp = lin ;
2020-05-25 14:49:03 +01:00
float min ;
2020-09-11 14:44:16 +01:00
lp = GetNumericArgument ( lp + 3 , OPER_EQU , & min , 0 ) ;
2020-05-25 14:49:03 +01:00
SCRIPT_SKIP_SPACES
// arg2
float max ;
2020-09-11 14:44:16 +01:00
lp = GetNumericArgument ( lp , OPER_EQU , & max , 0 ) ;
2020-05-25 14:49:03 +01:00
SCRIPT_SKIP_SPACES
2019-09-24 07:25:32 +01:00
float val ;
2020-09-11 14:44:16 +01:00
char * slp = lp ;
lp = GetNumericArgument ( lp , OPER_EQU , & val , 0 ) ;
2019-09-24 07:25:32 +01:00
SCRIPT_SKIP_SPACES
2019-09-16 18:52:53 +01:00
2019-09-24 07:25:32 +01:00
char vname [ 16 ] ;
2020-09-11 14:44:16 +01:00
ScriptGetVarname ( vname , slp , sizeof ( vname ) ) ;
2019-09-16 18:52:53 +01:00
2020-05-25 14:49:03 +01:00
char left [ SCRIPT_MAXSSIZE ] ;
2020-09-11 14:44:16 +01:00
lp = GetStringArgument ( lp , OPER_EQU , left , 0 ) ;
2020-05-25 14:49:03 +01:00
SCRIPT_SKIP_SPACES
char mid [ SCRIPT_MAXSSIZE ] ;
2020-09-11 14:44:16 +01:00
lp = GetStringArgument ( lp , OPER_EQU , mid , 0 ) ;
2019-09-24 07:25:32 +01:00
SCRIPT_SKIP_SPACES
2020-05-25 14:49:03 +01:00
char right [ SCRIPT_MAXSSIZE ] ;
2020-09-11 14:44:16 +01:00
lp = GetStringArgument ( lp , OPER_EQU , right , 0 ) ;
2019-09-24 07:25:32 +01:00
SCRIPT_SKIP_SPACES
2020-09-11 14:44:16 +01:00
WSContentSend_PD ( SCRIPT_MSG_SLIDER , left , mid , right , ( uint32_t ) min , ( uint32_t ) max , ( uint32_t ) val , vname ) ;
2020-05-25 14:49:03 +01:00
2020-09-11 14:44:16 +01:00
} else if ( ! strncmp ( lin , " ck( " , 3 ) ) {
char * lp = lin + 3 ;
char * slp = lp ;
2020-05-25 14:49:03 +01:00
float val ;
2020-09-11 14:44:16 +01:00
lp = GetNumericArgument ( lp , OPER_EQU , & val , 0 ) ;
2020-05-25 14:49:03 +01:00
SCRIPT_SKIP_SPACES
char vname [ 16 ] ;
2020-09-11 14:44:16 +01:00
ScriptGetVarname ( vname , slp , sizeof ( vname ) ) ;
2020-05-25 14:49:03 +01:00
char label [ SCRIPT_MAXSSIZE ] ;
2020-09-11 14:44:16 +01:00
lp = GetStringArgument ( lp , OPER_EQU , label , 0 ) ;
2020-05-25 14:49:03 +01:00
const char * cp ;
2019-09-24 07:25:32 +01:00
uint8_t uval ;
if ( val > 0 ) {
2020-09-11 14:44:16 +01:00
cp = " checked='checked' " ;
uval = 0 ;
2019-09-24 07:25:32 +01:00
} else {
2020-09-11 14:44:16 +01:00
cp = " " ;
uval = 1 ;
2019-09-24 07:25:32 +01:00
}
2020-09-11 14:44:16 +01:00
WSContentSend_PD ( SCRIPT_MSG_CHKBOX , label , ( char * ) cp , uval , vname ) ;
2020-05-25 14:49:03 +01:00
2020-09-11 14:44:16 +01:00
} else if ( ! strncmp ( lin , " bu( " , 3 ) ) {
char * lp = lin + 3 ;
uint8_t bcnt = 0 ;
char * found = lin ;
2020-05-25 14:49:03 +01:00
while ( bcnt < 4 ) {
2020-09-11 14:44:16 +01:00
found = strstr ( found , " bu( " ) ;
2020-05-25 14:49:03 +01:00
if ( ! found ) break ;
2020-09-11 14:44:16 +01:00
found + = 3 ;
2020-05-25 14:49:03 +01:00
bcnt + + ;
2019-09-24 07:25:32 +01:00
}
2020-09-11 14:44:16 +01:00
uint8_t proz = 100 / bcnt ;
if ( ! optflg & & bcnt > 1 ) proz - = 2 ;
2020-05-25 14:49:03 +01:00
if ( optflg ) WSContentSend_PD ( SCRIPT_MSG_BUT_START_TBL ) ;
else WSContentSend_PD ( SCRIPT_MSG_BUT_START ) ;
2020-09-11 14:44:16 +01:00
for ( uint32_t cnt = 0 ; cnt < bcnt ; cnt + + ) {
2020-05-25 14:49:03 +01:00
float val ;
2020-09-11 14:44:16 +01:00
char * slp = lp ;
lp = GetNumericArgument ( lp , OPER_EQU , & val , 0 ) ;
2020-05-25 14:49:03 +01:00
SCRIPT_SKIP_SPACES
char vname [ 16 ] ;
2020-09-11 14:44:16 +01:00
ScriptGetVarname ( vname , slp , sizeof ( vname ) ) ;
2020-05-25 14:49:03 +01:00
SCRIPT_SKIP_SPACES
char ontxt [ SCRIPT_MAXSSIZE ] ;
2020-09-11 14:44:16 +01:00
lp = GetStringArgument ( lp , OPER_EQU , ontxt , 0 ) ;
2020-05-25 14:49:03 +01:00
SCRIPT_SKIP_SPACES
char offtxt [ SCRIPT_MAXSSIZE ] ;
2020-09-11 14:44:16 +01:00
lp = GetStringArgument ( lp , OPER_EQU , offtxt , 0 ) ;
2020-05-25 14:49:03 +01:00
char * cp ;
uint8_t uval ;
if ( val > 0 ) {
2020-09-11 14:44:16 +01:00
cp = ontxt ;
uval = 0 ;
2020-05-25 14:49:03 +01:00
} else {
2020-09-11 14:44:16 +01:00
cp = offtxt ;
uval = 1 ;
2020-05-25 14:49:03 +01:00
}
if ( bcnt > 1 & & cnt = = bcnt - 1 ) {
2020-09-11 14:44:16 +01:00
if ( ! optflg ) proz + = 2 ;
2020-05-25 14:49:03 +01:00
}
if ( ! optflg ) {
2020-09-11 14:44:16 +01:00
WSContentSend_PD ( SCRIPT_MSG_BUTTONa , proz , uval , vname , cp ) ;
2020-05-25 14:49:03 +01:00
} else {
2020-09-11 14:44:16 +01:00
WSContentSend_PD ( SCRIPT_MSG_BUTTONa_TBL , proz , uval , vname , cp ) ;
2020-05-25 14:49:03 +01:00
}
if ( bcnt > 1 & & cnt < bcnt - 1 ) {
2020-09-11 14:44:16 +01:00
if ( ! optflg ) WSContentSend_PD ( SCRIPT_MSG_BUTTONb , 2 ) ;
2020-05-25 14:49:03 +01:00
}
2020-09-11 14:44:16 +01:00
lp + = 4 ;
2019-09-24 07:25:32 +01:00
}
2020-05-25 14:49:03 +01:00
if ( optflg ) WSContentSend_PD ( SCRIPT_MSG_BUT_STOP_TBL ) ;
else WSContentSend_PD ( SCRIPT_MSG_BUT_STOP ) ;
2019-09-16 18:52:53 +01:00
2020-09-11 14:44:16 +01:00
} else if ( ! strncmp ( lin , " tx( " , 3 ) ) {
char * lp = lin + 3 ;
char * slp = lp ;
2020-05-25 14:49:03 +01:00
char str [ SCRIPT_MAXSSIZE ] ;
2020-09-11 14:44:16 +01:00
lp = ForceStringVar ( lp , str ) ;
2020-05-25 14:49:03 +01:00
SCRIPT_SKIP_SPACES
char label [ SCRIPT_MAXSSIZE ] ;
2020-09-11 14:44:16 +01:00
lp = GetStringArgument ( lp , OPER_EQU , label , 0 ) ;
2019-09-16 18:52:53 +01:00
2020-05-25 14:49:03 +01:00
char vname [ 16 ] ;
2020-09-11 14:44:16 +01:00
ScriptGetVarname ( vname , slp , sizeof ( vname ) ) ;
2019-09-16 18:52:53 +01:00
2020-09-11 14:44:16 +01:00
WSContentSend_PD ( SCRIPT_MSG_TEXTINP , label , str , vname ) ;
2019-09-24 07:25:32 +01:00
2020-09-11 14:44:16 +01:00
} else if ( ! strncmp ( lin , " nm( " , 3 ) ) {
char * lp = lin ;
2020-05-25 14:49:03 +01:00
float min ;
2020-09-11 14:44:16 +01:00
lp = GetNumericArgument ( lp + 3 , OPER_EQU , & min , 0 ) ;
2020-05-25 14:49:03 +01:00
SCRIPT_SKIP_SPACES
float max ;
2020-09-11 14:44:16 +01:00
lp = GetNumericArgument ( lp , OPER_EQU , & max , 0 ) ;
2020-05-25 14:49:03 +01:00
SCRIPT_SKIP_SPACES
float step ;
2020-09-11 14:44:16 +01:00
lp = GetNumericArgument ( lp , OPER_EQU , & step , 0 ) ;
2020-05-25 14:49:03 +01:00
SCRIPT_SKIP_SPACES
float val ;
2020-09-11 14:44:16 +01:00
char * slp = lp ;
lp = GetNumericArgument ( lp , OPER_EQU , & val , 0 ) ;
2020-05-25 14:49:03 +01:00
SCRIPT_SKIP_SPACES
char vname [ 16 ] ;
2020-09-11 14:44:16 +01:00
ScriptGetVarname ( vname , slp , sizeof ( vname ) ) ;
2020-05-25 14:49:03 +01:00
char label [ SCRIPT_MAXSSIZE ] ;
2020-09-11 14:44:16 +01:00
lp = GetStringArgument ( lp , OPER_EQU , label , 0 ) ;
2020-05-25 14:49:03 +01:00
char vstr [ 16 ] , minstr [ 16 ] , maxstr [ 16 ] , stepstr [ 16 ] ;
2020-09-11 14:44:16 +01:00
dtostrfd ( val , 4 , vstr ) ;
dtostrfd ( min , 4 , minstr ) ;
dtostrfd ( max , 4 , maxstr ) ;
dtostrfd ( step , 4 , stepstr ) ;
WSContentSend_PD ( SCRIPT_MSG_NUMINP , label , minstr , maxstr , stepstr , vstr , vname ) ;
2019-09-24 07:25:32 +01:00
2019-09-16 18:52:53 +01:00
} else {
2020-06-26 08:22:57 +01:00
if ( mc = = ' w ' ) {
2020-09-11 14:44:16 +01:00
WSContentSend_PD ( PSTR ( " %s " ) , lin ) ;
2020-05-25 14:49:03 +01:00
} else {
2020-06-26 08:22:57 +01:00
if ( optflg ) {
2020-09-11 14:44:16 +01:00
WSContentSend_PD ( PSTR ( " <div>%s</div> " ) , lin ) ;
2020-06-26 08:22:57 +01:00
} else {
2020-09-11 14:44:16 +01:00
WSContentSend_PD ( PSTR ( " {s}%s{e} " ) , lin ) ;
2020-06-26 08:22:57 +01:00
}
2020-05-25 14:49:03 +01:00
}
2019-09-16 18:52:53 +01:00
}
2020-05-25 14:49:03 +01:00
// end standard web interface
2020-05-02 07:10:23 +01:00
} else {
2020-05-25 14:49:03 +01:00
// main section interface
2020-05-02 07:10:23 +01:00
if ( * lin = = mc ) {
2020-06-26 08:22:57 +01:00
2020-05-23 09:24:08 +01:00
# ifdef USE_GOOGLE_CHARTS
2020-05-18 09:29:32 +01:00
lin + + ;
2020-06-26 08:22:57 +01:00
exgc :
2020-05-25 14:49:03 +01:00
char * lp ;
2020-09-11 14:44:16 +01:00
if ( ! strncmp ( lin , " gc( " , 3 ) ) {
2020-05-23 09:24:08 +01:00
// get google table
2020-09-11 14:44:16 +01:00
lp = lin + 3 ;
2020-05-18 09:29:32 +01:00
SCRIPT_SKIP_SPACES
const char * type ;
2020-05-23 09:24:08 +01:00
const char * func ;
2020-05-25 14:49:03 +01:00
char options [ 312 ] ;
2020-09-11 14:44:16 +01:00
uint8_t nanum = MAX_GARRAY ;
uint8_t y2f = 0 ;
uint8_t tonly = 0 ;
2020-05-23 09:24:08 +01:00
char ctype ;
2020-09-11 14:44:16 +01:00
ctype = * lp ;
2020-05-23 09:24:08 +01:00
lp + + ;
2020-09-11 14:44:16 +01:00
if ( ! ( google_libs & GLIBS_MAIN ) ) {
google_libs | = GLIBS_MAIN ;
2020-05-23 09:24:08 +01:00
WSContentSend_PD ( SCRIPT_MSG_GTABLE ) ;
}
switch ( ctype ) {
2020-05-18 09:29:32 +01:00
case ' l ' :
2020-09-11 14:44:16 +01:00
type = PSTR ( " LineChart " ) ;
2020-05-18 09:29:32 +01:00
break ;
case ' b ' :
2020-09-11 14:44:16 +01:00
type = PSTR ( " BarChart " ) ;
2020-05-18 09:29:32 +01:00
break ;
case ' p ' :
2020-09-11 14:44:16 +01:00
type = PSTR ( " PieChart " ) ;
2020-05-19 15:44:01 +01:00
break ;
case ' g ' :
2020-09-11 14:44:16 +01:00
type = PSTR ( " Gauge " ) ;
if ( ! ( google_libs & GLIBS_GAUGE ) ) {
google_libs | = GLIBS_GAUGE ;
2020-05-23 09:24:08 +01:00
WSContentSend_PD ( SCRIPT_MSG_GAUGE ) ;
}
2020-05-18 09:29:32 +01:00
break ;
2020-05-19 15:44:01 +01:00
case ' t ' :
2020-09-11 14:44:16 +01:00
type = PSTR ( " Table " ) ;
if ( ! ( google_libs & GLIBS_TABLE ) ) {
google_libs | = GLIBS_TABLE ;
2020-05-23 09:24:08 +01:00
WSContentSend_PD ( SCRIPT_MSG_TABLE ) ;
}
break ;
case ' T ' :
2020-09-11 14:44:16 +01:00
type = PSTR ( " Timeline " ) ;
if ( ! ( google_libs & GLIBS_TIMELINE ) ) {
google_libs | = GLIBS_TIMELINE ;
2020-05-23 09:24:08 +01:00
WSContentSend_PD ( SCRIPT_MSG_TIMELINE ) ;
}
2020-05-19 15:44:01 +01:00
break ;
case ' h ' :
2020-09-11 14:44:16 +01:00
type = PSTR ( " Histogram " ) ;
2020-05-23 09:24:08 +01:00
break ;
case ' c ' :
2020-09-11 14:44:16 +01:00
type = PSTR ( " ColumnChart " ) ;
break ;
case ' C ' :
type = PSTR ( " ComboChart " ) ;
break ;
case ' e ' :
WSContentSend_PD ( SCRIPT_MSG_GTABLEbx , type , chartindex ) ;
chartindex + + ;
goto nextwebline ;
2020-05-18 09:29:32 +01:00
break ;
2020-05-23 09:24:08 +01:00
default :
// error
goto nextwebline ;
break ;
}
if ( ctype = = ' l ' & & * lp = = ' f ' ) {
lp + + ;
2020-09-11 14:44:16 +01:00
func = PSTR ( " ,curveType:'function' " ) ;
2020-05-18 09:29:32 +01:00
} else {
2020-09-11 14:44:16 +01:00
func = " " ;
2020-05-18 09:29:32 +01:00
}
2020-05-23 09:24:08 +01:00
if ( * lp = = ' 2 ' ) {
lp + + ;
2020-09-11 14:44:16 +01:00
nanum = 2 ;
y2f = 1 ;
}
if ( * lp = = ' t ' ) {
lp + + ;
tonly = 1 ;
2020-05-23 09:24:08 +01:00
}
SCRIPT_SKIP_SPACES
//Serial.printf("type %d\n",ctype);
2020-05-18 09:29:32 +01:00
2020-05-23 09:24:08 +01:00
float * arrays [ MAX_GARRAY ] ;
2020-09-11 14:44:16 +01:00
uint8_t anum = 0 ;
uint16_t entries = 0 ;
uint16_t ipos = 0 ;
lp = gc_get_arrays ( lp , & arrays [ 0 ] , & anum , & entries , & ipos ) ;
2020-05-23 09:24:08 +01:00
if ( anum > nanum ) {
goto nextwebline ;
}
// we know how many arrays and the number of entries
//Serial.printf("arrays %d\n",anum);
//Serial.printf("entries %d\n",entries);
if ( ctype = = ' T ' ) {
2020-09-11 14:44:16 +01:00
if ( anum & & ! ( entries & 1 ) ) {
2020-05-23 09:24:08 +01:00
WSContentSend_PD ( SCRIPT_MSG_GTABLEa ) ;
char label [ SCRIPT_MAXSSIZE ] ;
2020-09-11 14:44:16 +01:00
lp = GetStringArgument ( lp , OPER_EQU , label , 0 ) ;
2020-05-23 09:24:08 +01:00
SCRIPT_SKIP_SPACES
2020-12-04 07:57:52 +00:00
char lab2 [ SCRIPT_MAXSSIZE ] ;
lab2 [ 0 ] = 0 ;
if ( * lp ! = ' ) ' ) {
lp = GetStringArgument ( lp , OPER_EQU , lab2 , 0 ) ;
WSContentSend_PD ( SCRIPT_MSG_GTABLEe ) ;
} else {
WSContentSend_PD ( SCRIPT_MSG_GTABLEd ) ;
}
2020-09-11 14:44:16 +01:00
for ( uint32_t ind = 0 ; ind < anum ; ind + + ) {
2020-05-23 09:24:08 +01:00
char lbl [ 16 ] ;
2020-12-04 07:57:52 +00:00
float * fp = arrays [ ind ] ;
2020-05-25 14:49:03 +01:00
GetTextIndexed ( lbl , sizeof ( lbl ) , ind , label ) ;
2020-12-04 07:57:52 +00:00
char lbl2 [ 16 ] ;
if ( lab2 [ 0 ] ) {
GetTextIndexed ( lbl2 , sizeof ( lbl2 ) , ind , lab2 ) ;
}
uint32_t ventries = 0 ;
2020-09-11 14:44:16 +01:00
for ( uint32_t cnt = 0 ; cnt < entries ; cnt + = 2 ) {
2020-12-04 07:57:52 +00:00
if ( fp [ cnt ] ! = 0 & & fp [ cnt + 1 ] ! = 0 ) {
ventries + = 2 ;
} else {
break ;
}
}
for ( uint32_t cnt = 0 ; cnt < ventries ; cnt + = 2 ) {
2020-05-23 09:24:08 +01:00
WSContentSend_PD ( " ['%s', " , lbl ) ;
2020-12-04 07:57:52 +00:00
if ( lab2 [ 0 ] ) {
WSContentSend_PD ( " '%s', " , lbl2 ) ;
}
2020-09-11 14:44:16 +01:00
uint32_t time = fp [ cnt ] ;
WSContentSend_PD ( SCRIPT_MSG_GOPT5 , time / 60 , time % 60 ) ;
2020-05-23 09:24:08 +01:00
WSContentSend_PD ( " , " ) ;
2020-09-11 14:44:16 +01:00
time = fp [ cnt + 1 ] ;
WSContentSend_PD ( SCRIPT_MSG_GOPT5 , time / 60 , time % 60 ) ;
2020-05-23 09:24:08 +01:00
WSContentSend_PD ( " ] " ) ;
2020-12-04 07:57:52 +00:00
if ( cnt < ventries - 2 ) { WSContentSend_PD ( " , " ) ; }
}
if ( ind < anum - 1 ) {
if ( ventries ) {
WSContentSend_PD ( " , " ) ;
}
2020-05-23 09:24:08 +01:00
}
}
2020-09-11 14:44:16 +01:00
snprintf_P ( options , sizeof ( options ) , SCRIPT_MSG_GOPT4 ) ;
2020-05-23 09:24:08 +01:00
}
} else {
// we need to fetch the labels now
WSContentSend_PD ( SCRIPT_MSG_GTABLEa ) ;
2020-09-11 14:44:16 +01:00
lp = gc_send_labels ( lp , anum ) ;
2020-05-23 09:24:08 +01:00
// now we have to export the values
// fetch label part only once in combo string
char label [ SCRIPT_MAXSSIZE ] ;
2020-09-11 14:44:16 +01:00
lp = GetStringArgument ( lp , OPER_EQU , label , 0 ) ;
2020-05-23 09:24:08 +01:00
SCRIPT_SKIP_SPACES
2020-05-25 14:49:03 +01:00
2020-09-11 14:44:16 +01:00
int16_t divflg = 1 ;
int16_t todflg = - 1 ;
if ( ! strncmp ( label , " cnt " , 3 ) ) {
char * cp = & label [ 3 ] ;
//todflg=atoi(&label[3]);
todflg = strtol ( cp , & cp , 10 ) ;
2020-12-26 08:45:59 +00:00
if ( todflg > = entries ) todflg = entries - 1 ;
if ( todflg < 0 ) todflg = 0 ;
2020-09-11 14:44:16 +01:00
if ( * cp = = ' / ' ) {
cp + + ;
divflg = strtol ( cp , & cp , 10 ) ;
}
2020-09-03 11:26:03 +01:00
} else {
2020-09-11 14:44:16 +01:00
char * lp = label ;
if ( ! strncmp ( label , " wdh: " , 4 ) ) {
// one week hours
todflg = - 2 ;
lp + = 4 ;
}
uint16 segments = 1 ;
for ( uint32_t cnt = 0 ; cnt < strlen ( lp ) ; cnt + + ) {
if ( lp [ cnt ] = = ' | ' ) {
2020-09-03 11:26:03 +01:00
segments + + ;
}
}
2020-09-11 14:44:16 +01:00
divflg = entries / segments ;
2020-05-25 14:49:03 +01:00
}
2020-05-23 09:24:08 +01:00
2020-09-11 14:44:16 +01:00
uint32_t aind = ipos ;
if ( aind > = entries ) aind = entries - 1 ;
for ( uint32_t cnt = 0 ; cnt < entries ; cnt + + ) {
2020-05-23 09:24:08 +01:00
WSContentSend_PD ( " [' " ) ;
char lbl [ 16 ] ;
2020-05-25 14:49:03 +01:00
if ( todflg > = 0 ) {
2020-12-13 06:32:09 +00:00
sprintf ( lbl , " %d:%02d " , todflg / divflg , ( todflg % divflg ) * ( 60 / divflg ) ) ;
2020-05-25 14:49:03 +01:00
todflg + + ;
2020-09-11 14:44:16 +01:00
if ( todflg > = entries ) {
todflg = 0 ;
2020-06-05 19:15:16 +01:00
}
2020-05-25 14:49:03 +01:00
} else {
2020-09-11 14:44:16 +01:00
if ( todflg = = - 1 ) {
GetTextIndexed ( lbl , sizeof ( lbl ) , aind / divflg , label ) ;
} else {
// day,hours,mins
GetTextIndexed ( lbl , sizeof ( lbl ) , aind / divflg , label + 4 ) ;
sprintf ( lbl , " %s-%02d " , lbl , aind % divflg ) ;
}
2020-05-23 09:24:08 +01:00
}
WSContentSend_PD ( lbl ) ;
WSContentSend_PD ( " ', " ) ;
2020-09-11 14:44:16 +01:00
for ( uint32_t ind = 0 ; ind < anum ; ind + + ) {
2020-05-23 09:24:08 +01:00
char acbuff [ 32 ] ;
2020-09-11 14:44:16 +01:00
float * fp = arrays [ ind ] ;
2020-09-23 11:51:35 +01:00
f2char ( fp [ aind ] , glob_script_mem . script_dprec , glob_script_mem . script_lzero , acbuff ) ;
2020-09-11 14:44:16 +01:00
WSContentSend_PD ( " %s " , acbuff ) ;
if ( ind < anum - 1 ) { WSContentSend_PD ( " , " ) ; }
2020-05-23 09:24:08 +01:00
}
WSContentSend_PD ( " ] " ) ;
2020-09-11 14:44:16 +01:00
if ( cnt < entries - 1 ) { WSContentSend_PD ( " , " ) ; }
2020-06-05 19:15:16 +01:00
aind + + ;
if ( aind > = entries ) {
2020-09-11 14:44:16 +01:00
aind = 0 ;
2020-06-05 19:15:16 +01:00
}
2020-05-23 09:24:08 +01:00
}
2020-09-11 14:44:16 +01:00
// table complete
if ( tonly ) {
WSContentSend_PD ( " ]); " ) ;
goto nextwebline ;
}
2020-05-23 09:24:08 +01:00
// get header
char header [ SCRIPT_MAXSSIZE ] ;
2020-09-11 14:44:16 +01:00
lp = GetStringArgument ( lp , OPER_EQU , header , 0 ) ;
2020-05-23 09:24:08 +01:00
SCRIPT_SKIP_SPACES
switch ( ctype ) {
case ' t ' :
2020-09-11 14:44:16 +01:00
snprintf_P ( options , sizeof ( options ) , SCRIPT_MSG_GOPT2 ) ;
2020-05-23 09:24:08 +01:00
break ;
default :
2020-09-11 14:44:16 +01:00
snprintf_P ( options , sizeof ( options ) , SCRIPT_MSG_GOPT1 , header ) ;
2020-05-23 09:24:08 +01:00
break ;
}
// check for 2 axis option
if ( y2f ) {
// 2 y axes variant
SCRIPT_SKIP_SPACES
float max1 ;
2020-09-11 14:44:16 +01:00
lp = GetNumericArgument ( lp , OPER_EQU , & max1 , 0 ) ;
2020-05-23 09:24:08 +01:00
SCRIPT_SKIP_SPACES
float max2 ;
2020-09-11 14:44:16 +01:00
lp = GetNumericArgument ( lp , OPER_EQU , & max2 , 0 ) ;
2020-05-23 09:24:08 +01:00
SCRIPT_SKIP_SPACES
2020-09-11 14:44:16 +01:00
snprintf_P ( options , sizeof ( options ) , SCRIPT_MSG_GOPT3 , header , ( uint32_t ) max1 , ( uint32_t ) max2 , func ) ;
2020-09-03 11:26:03 +01:00
} else {
SCRIPT_SKIP_SPACES
2020-09-11 14:44:16 +01:00
if ( ctype ! = ' g ' ) {
if ( * lp ! = ' ) ' ) {
float max1 ;
lp = GetNumericArgument ( lp , OPER_EQU , & max1 , 0 ) ;
SCRIPT_SKIP_SPACES
float max2 ;
lp = GetNumericArgument ( lp , OPER_EQU , & max2 , 0 ) ;
SCRIPT_SKIP_SPACES
snprintf_P ( options , sizeof ( options ) , SCRIPT_MSG_GOPT6 , header , ( uint32_t ) max1 , ( uint32_t ) max2 , func ) ;
}
2020-09-03 11:26:03 +01:00
}
2020-05-23 09:24:08 +01:00
}
2020-05-25 14:49:03 +01:00
if ( ctype = = ' g ' ) {
float yellowFrom ;
2020-09-11 14:44:16 +01:00
lp = GetNumericArgument ( lp , OPER_EQU , & yellowFrom , 0 ) ;
2020-05-25 14:49:03 +01:00
SCRIPT_SKIP_SPACES
float redFrom ;
2020-09-11 14:44:16 +01:00
lp = GetNumericArgument ( lp , OPER_EQU , & redFrom , 0 ) ;
2020-05-25 14:49:03 +01:00
SCRIPT_SKIP_SPACES
float maxValue ;
2020-09-11 14:44:16 +01:00
lp = GetNumericArgument ( lp , OPER_EQU , & maxValue , 0 ) ;
2020-05-25 14:49:03 +01:00
SCRIPT_SKIP_SPACES
2020-09-11 14:44:16 +01:00
float redTo = maxValue ;
float yellowTo = redFrom ;
snprintf_P ( options , sizeof ( options ) , SCRIPT_MSG_GAUGEOPT , ( uint32_t ) maxValue , ( uint32_t ) redFrom , ( uint32_t ) redTo ,
( uint32_t ) yellowFrom , ( uint32_t ) yellowTo ) ;
2020-05-25 14:49:03 +01:00
}
2020-05-23 09:24:08 +01:00
}
2020-09-11 14:44:16 +01:00
WSContentSend_PD ( SCRIPT_MSG_GTABLEb , options ) ;
WSContentSend_PD ( SCRIPT_MSG_GTABLEbx , type , chartindex ) ;
2020-05-18 09:29:32 +01:00
chartindex + + ;
} else {
2020-09-11 14:44:16 +01:00
WSContentSend_PD ( PSTR ( " %s " ) , lin ) ;
2020-05-18 09:29:32 +01:00
}
2020-05-23 09:24:08 +01:00
# else
2020-06-26 08:22:57 +01:00
lin + + ;
2020-09-11 14:44:16 +01:00
WSContentSend_PD ( PSTR ( " %s " ) , lin ) ;
2020-05-23 09:24:08 +01:00
} else {
2020-05-25 14:49:03 +01:00
// WSContentSend_PD(PSTR("%s"),lin);
2020-05-23 09:24:08 +01:00
# endif //USE_GOOGLE_CHARTS
2020-05-02 07:10:23 +01:00
}
}
2019-08-31 09:10:16 +01:00
}
2020-05-23 09:24:08 +01:00
nextwebline :
2019-08-31 09:10:16 +01:00
if ( * lp = = SCRIPT_EOL ) {
lp + + ;
} else {
lp = strchr ( lp , SCRIPT_EOL ) ;
if ( ! lp ) break ;
lp + + ;
}
}
}
}
# endif //USE_SCRIPT_WEB_DISPLAY
2019-10-20 10:21:25 +01:00
# ifdef USE_SENDMAIL
2020-04-12 18:28:19 +01:00
2020-05-02 07:10:23 +01:00
void script_send_email_body ( void ( * func ) ( char * ) ) {
2020-09-11 14:44:16 +01:00
uint8_t msect = Run_Scripter ( " >m " , - 2 , 0 ) ;
2019-10-20 10:21:25 +01:00
if ( msect = = 99 ) {
2020-05-30 09:48:12 +01:00
char tmp [ 256 ] ;
2020-09-11 14:44:16 +01:00
char * lp = glob_script_mem . section_ptr + 2 ;
2019-10-20 10:21:25 +01:00
while ( lp ) {
while ( * lp = = SCRIPT_EOL ) {
lp + + ;
}
if ( ! * lp | | * lp = = ' # ' | | * lp = = ' > ' ) {
break ;
}
if ( * lp ! = ' ; ' ) {
// send this line to smtp
2020-09-11 14:44:16 +01:00
Replace_Cmd_Vars ( lp , 1 , tmp , sizeof ( tmp ) ) ;
2020-05-02 07:10:23 +01:00
//client->println(tmp);
func ( tmp ) ;
2019-10-20 10:21:25 +01:00
}
if ( * lp = = SCRIPT_EOL ) {
lp + + ;
} else {
lp = strchr ( lp , SCRIPT_EOL ) ;
if ( ! lp ) break ;
lp + + ;
}
}
} else {
2020-05-02 07:10:23 +01:00
//client->println("*");
func ( ( char * ) " * " ) ;
2019-10-20 10:21:25 +01:00
}
}
2020-09-11 14:44:16 +01:00
# endif //USE_SENDMAIL
2019-10-20 10:21:25 +01:00
2019-08-31 09:10:16 +01:00
# ifdef USE_SCRIPT_JSON_EXPORT
void ScriptJsonAppend ( void ) {
2020-09-11 14:44:16 +01:00
uint8_t web_script = Run_Scripter ( " >J " , - 2 , 0 ) ;
2019-08-31 09:10:16 +01:00
if ( web_script = = 99 ) {
2020-05-30 09:48:12 +01:00
char tmp [ 256 ] ;
2020-09-11 14:44:16 +01:00
char * lp = glob_script_mem . section_ptr + 2 ;
2019-08-31 09:10:16 +01:00
while ( lp ) {
while ( * lp = = SCRIPT_EOL ) {
lp + + ;
}
if ( ! * lp | | * lp = = ' # ' | | * lp = = ' > ' ) {
break ;
}
2019-09-08 11:14:28 +01:00
if ( * lp ! = ' ; ' ) {
// send this line to mqtt
2020-09-11 14:44:16 +01:00
Replace_Cmd_Vars ( lp , 1 , tmp , sizeof ( tmp ) ) ;
ResponseAppend_P ( PSTR ( " %s " ) , tmp ) ;
2019-08-31 09:10:16 +01:00
}
if ( * lp = = SCRIPT_EOL ) {
lp + + ;
} else {
lp = strchr ( lp , SCRIPT_EOL ) ;
if ( ! lp ) break ;
lp + + ;
}
}
}
}
# endif //USE_SCRIPT_JSON_EXPORT
2020-04-26 11:01:13 +01:00
bool RulesProcessEvent ( char * json_event ) {
2020-09-11 14:44:16 +01:00
if ( bitRead ( Settings . rule_enabled , 0 ) ) Run_Scripter ( " >E " , 2 , json_event ) ;
2020-07-15 08:44:52 +01:00
return true ;
2020-04-26 11:01:13 +01:00
}
2020-05-07 15:16:46 +01:00
# ifdef ESP32
# ifdef USE_SCRIPT_TASK
2020-05-30 09:48:12 +01:00
# ifndef STASK_STACK
2021-01-20 07:49:10 +00:00
# define STASK_STACK 8192-2048
2020-05-30 09:48:12 +01:00
# endif
# if 1
struct ESP32_Task {
uint16_t task_timer ;
TaskHandle_t task_t ;
} esp32_tasks [ 2 ] ;
void script_task1 ( void * arg ) {
//uint32_t lastms=millis();
//uint32_t time;
while ( 1 ) {
//time=millis()-lastms;
//lastms=millis();
//time=esp32_tasks[0].task_timer-time;
//if (time<esp32_tasks[1].task_timer) {delay(time); }
//if (time<=esp32_tasks[0].task_timer) {vTaskDelay( pdMS_TO_TICKS( time ) ); }
delay ( esp32_tasks [ 0 ] . task_timer ) ;
2020-06-08 08:24:49 +01:00
if ( bitRead ( Settings . rule_enabled , 0 ) ) {
2020-09-11 14:44:16 +01:00
Run_Scripter ( " >t1 " , 3 , 0 ) ;
2020-06-08 08:24:49 +01:00
}
2020-05-30 09:48:12 +01:00
}
}
void script_task2 ( void * arg ) {
//uint32_t lastms=millis();
//uint32_t time;
while ( 1 ) {
//time=millis()-lastms;
//lastms=millis();
//time=esp32_tasks[1].task_timer-time;
//if (time<esp32_tasks[1].task_timer) {delay(time); }
//if (time<=esp32_tasks[1].task_timer) {vTaskDelay( pdMS_TO_TICKS( time ) ); }
delay ( esp32_tasks [ 1 ] . task_timer ) ;
2020-06-08 08:24:49 +01:00
if ( bitRead ( Settings . rule_enabled , 0 ) ) {
2020-09-11 14:44:16 +01:00
Run_Scripter ( " >t2 " , 3 , 0 ) ;
2020-06-08 08:24:49 +01:00
}
2020-05-30 09:48:12 +01:00
}
}
2020-10-19 06:24:18 +01:00
uint32_t scripter_create_task ( uint32_t num , uint32_t time , uint32_t core , uint32_t prio ) {
2020-05-30 09:48:12 +01:00
//return 0;
BaseType_t res = 0 ;
if ( core > 1 ) { core = 1 ; }
if ( num = = 1 ) {
if ( esp32_tasks [ 0 ] . task_t ) { vTaskDelete ( esp32_tasks [ 0 ] . task_t ) ; }
2020-10-19 06:24:18 +01:00
res = xTaskCreatePinnedToCore ( script_task1 , " T1 " , STASK_STACK , NULL , prio , & esp32_tasks [ 0 ] . task_t , core ) ;
2020-05-30 09:48:12 +01:00
esp32_tasks [ 0 ] . task_timer = time ;
} else {
if ( esp32_tasks [ 1 ] . task_t ) { vTaskDelete ( esp32_tasks [ 1 ] . task_t ) ; }
2020-10-19 06:24:18 +01:00
res = xTaskCreatePinnedToCore ( script_task2 , " T2 " , STASK_STACK , NULL , prio , & esp32_tasks [ 1 ] . task_t , core ) ;
2020-05-30 09:48:12 +01:00
esp32_tasks [ 1 ] . task_timer = time ;
}
return res ;
}
# else
2020-05-07 15:16:46 +01:00
uint16_t task_timer1 ;
uint16_t task_timer2 ;
2020-05-10 16:51:22 +01:00
TaskHandle_t task_t1 ;
TaskHandle_t task_t2 ;
2020-05-07 15:16:46 +01:00
void script_task1 ( void * arg ) {
while ( 1 ) {
delay ( task_timer1 ) ;
2020-09-11 14:44:16 +01:00
Run_Scripter ( " >t1 " , 3 , 0 ) ;
2020-05-07 15:16:46 +01:00
}
}
void script_task2 ( void * arg ) {
while ( 1 ) {
delay ( task_timer2 ) ;
2020-09-11 14:44:16 +01:00
Run_Scripter ( " >t2 " , 3 , 0 ) ;
2020-05-07 15:16:46 +01:00
}
}
2020-10-19 06:24:18 +01:00
uint32_t scripter_create_task ( uint32_t num , uint32_t time , uint32_t core , uint32_t prio ) {
2020-05-07 15:16:46 +01:00
//return 0;
2020-05-10 16:51:22 +01:00
BaseType_t res = 0 ;
if ( core > 1 ) { core = 1 ; }
2020-05-07 15:16:46 +01:00
if ( num = = 1 ) {
2020-05-10 16:51:22 +01:00
if ( task_t1 ) { vTaskDelete ( task_t1 ) ; }
2020-10-19 06:24:18 +01:00
res = xTaskCreatePinnedToCore ( script_task1 , " T1 " , STASK_STACK , NULL , prio , & task_t1 , core ) ;
2020-05-10 16:51:22 +01:00
task_timer1 = time ;
2020-05-07 15:16:46 +01:00
} else {
2020-05-10 16:51:22 +01:00
if ( task_t2 ) { vTaskDelete ( task_t2 ) ; }
2020-10-19 06:24:18 +01:00
res = xTaskCreatePinnedToCore ( script_task2 , " T2 " , STASK_STACK , NULL , prio , & task_t2 , core ) ;
2020-05-10 16:51:22 +01:00
task_timer2 = time ;
2020-05-07 15:16:46 +01:00
}
return res ;
}
2020-05-30 09:48:12 +01:00
# endif
2020-05-07 15:16:46 +01:00
# endif // USE_SCRIPT_TASK
# endif // ESP32
2020-06-15 16:20:50 +01:00
# ifdef SCRIPT_GET_HTTPS_JP
# ifdef ESP8266
# include "WiFiClientSecureLightBearSSL.h"
# else
# include <WiFiClientSecure.h>
2020-09-11 14:44:16 +01:00
# endif //ESP8266
2020-06-15 16:20:50 +01:00
// get tesla powerwall info page json string
uint32_t call2https ( const char * host , const char * path ) {
2020-10-30 11:29:48 +00:00
if ( TasmotaGlobal . global_state . wifi_down ) return 1 ;
2020-09-11 14:44:16 +01:00
uint32_t status = 0 ;
2020-06-15 16:20:50 +01:00
# ifdef ESP32
WiFiClientSecure * httpsClient ;
httpsClient = new WiFiClientSecure ;
# else
BearSSL : : WiFiClientSecure_light * httpsClient ;
httpsClient = new BearSSL : : WiFiClientSecure_light ( 1024 , 1024 ) ;
# endif
httpsClient - > setTimeout ( 1500 ) ;
2020-09-11 14:44:16 +01:00
uint32_t retry = 0 ;
2020-06-15 16:20:50 +01:00
while ( ( ! httpsClient - > connect ( host , 443 ) ) & & ( retry < 5 ) ) {
delay ( 100 ) ;
retry + + ;
}
if ( retry = = 5 ) {
return 2 ;
}
String request = String ( " GET " ) + path +
" HTTP/1.1 \r \n " +
" Host: " + host +
" \r \n " + " Connection: close \r \n \r \n " ;
httpsClient - > print ( request ) ;
while ( httpsClient - > connected ( ) ) {
String line = httpsClient - > readStringUntil ( ' \n ' ) ;
if ( line = = " \r " ) {
break ;
}
}
2020-09-11 14:44:16 +01:00
String result ;
2020-06-15 16:20:50 +01:00
while ( httpsClient - > available ( ) ) {
String line = httpsClient - > readStringUntil ( ' \n ' ) ;
if ( line ! = " " ) {
result + = line ;
}
}
httpsClient - > stop ( ) ;
2020-08-29 10:34:00 +01:00
delete httpsClient ;
2020-09-11 14:44:16 +01:00
Run_Scripter ( " >jp " , 3 , ( char * ) result . c_str ( ) ) ;
2020-06-15 16:20:50 +01:00
return 0 ;
}
# endif // SCRIPT_GET_HTTPS_JP
2020-06-26 08:22:57 +01:00
2020-09-11 14:44:16 +01:00
void cpy2lf ( char * dst , uint32_t dstlen , char * src ) {
2020-06-26 08:22:57 +01:00
for ( uint32_t cnt = 0 ; cnt < dstlen ; cnt + + ) {
if ( src [ cnt ] = = 0 | | src [ cnt ] = = ' \n ' ) {
2020-09-11 14:44:16 +01:00
dst [ cnt ] = 0 ;
2020-06-26 08:22:57 +01:00
break ;
}
2020-09-11 14:44:16 +01:00
dst [ cnt ] = src [ cnt ] ;
2020-06-26 08:22:57 +01:00
}
}
2019-05-18 08:45:04 +01:00
/*********************************************************************************************\
* Interface
\ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2020-06-05 19:15:16 +01:00
//const esp_partition_t *esp32_part;
2020-05-19 15:44:01 +01:00
2021-01-05 15:37:22 +00:00
2019-05-30 12:23:54 +01:00
bool Xdrv10 ( uint8_t function )
2019-05-18 08:45:04 +01:00
{
bool result = false ;
2020-07-16 16:15:12 +01:00
event_handeled = false ;
2020-05-21 05:06:42 +01:00
char * sprt ;
2019-05-18 08:45:04 +01:00
switch ( function ) {
2021-01-03 07:08:28 +00:00
//case FUNC_PRE_INIT:
case FUNC_INIT :
2019-05-30 12:23:54 +01:00
// set defaults to rules memory
2020-05-02 07:10:23 +01:00
//bitWrite(Settings.rule_enabled,0,0);
2020-09-11 14:44:16 +01:00
glob_script_mem . script_ram = Settings . rules [ 0 ] ;
glob_script_mem . script_size = MAX_SCRIPT_SIZE ;
2021-01-05 15:37:22 +00:00
glob_script_mem . FLAGS . fsys = false ;
glob_script_mem . FLAGS . eeprom = false ;
2020-09-11 14:44:16 +01:00
glob_script_mem . script_pram = ( uint8_t * ) Settings . script_pram [ 0 ] ;
glob_script_mem . script_pram_size = PMEM_SIZE ;
2019-05-30 12:23:54 +01:00
2021-01-05 15:37:22 +00:00
# ifdef USE_UFILESYS
if ( ufs_type ) {
// we have a file system
Script_AddLog_P ( LOG_LEVEL_INFO , PSTR ( " UFILESYSTEM OK! " ) ) ;
char * script ;
script = ( char * ) calloc ( UFSYS_SIZE + 4 , 1 ) ;
if ( ! script ) break ;
glob_script_mem . script_ram = script ;
glob_script_mem . script_size = UFSYS_SIZE ;
if ( ufsp - > exists ( FAT_SCRIPT_NAME ) ) {
File file = ufsp - > open ( FAT_SCRIPT_NAME , FS_FILE_READ ) ;
file . read ( ( uint8_t * ) script , UFSYS_SIZE ) ;
file . close ( ) ;
}
script [ UFSYS_SIZE - 1 ] = 0 ;
// use rules storage for permanent vars
glob_script_mem . script_pram = ( uint8_t * ) Settings . rules [ 0 ] ;
glob_script_mem . script_pram_size = MAX_SCRIPT_SIZE ;
glob_script_mem . FLAGS . fsys = true ;
// indicates scripter use no compression
bitWrite ( Settings . rule_once , 6 , 0 ) ;
} else {
Script_AddLog_P ( LOG_LEVEL_INFO , PSTR ( " UFILESYSTEM fail, using compression! " ) ) ;
int32_t len_decompressed ;
sprt = ( char * ) calloc ( UNISHOXRSIZE + 8 , 1 ) ;
if ( ! sprt ) { break ; }
glob_script_mem . script_ram = sprt ;
glob_script_mem . script_size = UNISHOXRSIZE ;
len_decompressed = SCRIPT_DECOMPRESS ( Settings . rules [ 0 ] , strlen ( Settings . rules [ 0 ] ) , glob_script_mem . script_ram , glob_script_mem . script_size ) ;
if ( len_decompressed > 0 ) glob_script_mem . script_ram [ len_decompressed ] = 0 ;
// indicates scripter use compression
bitWrite ( Settings . rule_once , 6 , 1 ) ;
2019-10-15 19:07:12 +01:00
}
2021-01-05 15:37:22 +00:00
# else // USE_UFILESYS
2019-10-15 19:07:12 +01:00
2020-06-05 19:15:16 +01:00
# ifdef EEP_SCRIPT_SIZE
2021-01-05 15:37:22 +00:00
2020-12-13 06:32:09 +00:00
if ( EEP_INIT ( EEP_SCRIPT_SIZE ) ) {
// found 32kb eeprom,
2019-05-30 12:23:54 +01:00
char * script ;
2021-01-05 15:37:22 +00:00
if ( EEP_SCRIPT_SIZE ! = SPECIAL_EEPMODE_SIZE ) {
script = ( char * ) calloc ( EEP_SCRIPT_SIZE + 4 , 1 ) ;
if ( ! script ) break ;
glob_script_mem . script_ram = script ;
glob_script_mem . script_size = EEP_SCRIPT_SIZE ;
EEP_READ ( 0 , EEP_SCRIPT_SIZE , script ) ;
if ( * script = = 0xff ) {
memset ( script , EEP_SCRIPT_SIZE , 0 ) ;
}
script [ EEP_SCRIPT_SIZE - 1 ] = 0 ;
} else {
uint8_t * ucs ;
ucs = ( uint8_t * ) calloc ( SPI_FLASH_SEC_SIZE + 4 , 1 ) ;
if ( ! ucs ) break ;
alt_eeprom_readBytes ( 0 , SPI_FLASH_SEC_SIZE , ucs ) ;
if ( * ucs = = 0xff ) {
memset ( ucs , SPI_FLASH_SEC_SIZE , 0 ) ;
}
ucs [ SPI_FLASH_SEC_SIZE - 1 ] = 0 ;
2020-12-13 06:32:09 +00:00
2021-01-05 15:37:22 +00:00
script = ( char * ) calloc ( EEP_SCRIPT_SIZE + 4 , 1 ) ;
if ( ! script ) break ;
glob_script_mem . script_ram = script ;
glob_script_mem . script_size = EEP_SCRIPT_SIZE ;
2020-12-13 06:32:09 +00:00
2021-01-05 15:37:22 +00:00
int32_t len_decompressed ;
len_decompressed = SCRIPT_DECOMPRESS ( ( char * ) ucs , strlen ( ( char * ) ucs ) , glob_script_mem . script_ram , glob_script_mem . script_size ) ;
if ( len_decompressed > 0 ) glob_script_mem . script_ram [ len_decompressed ] = 0 ;
2020-12-13 06:32:09 +00:00
2021-01-05 15:37:22 +00:00
if ( ucs ) free ( ucs ) ;
}
2020-12-13 06:32:09 +00:00
2019-05-30 12:23:54 +01:00
// use rules storage for permanent vars
2020-09-11 14:44:16 +01:00
glob_script_mem . script_pram = ( uint8_t * ) Settings . rules [ 0 ] ;
glob_script_mem . script_pram_size = MAX_SCRIPT_SIZE ;
2019-05-30 12:23:54 +01:00
2021-01-10 18:43:03 +00:00
glob_script_mem . FLAGS . eeprom = true ;
2019-05-30 12:23:54 +01:00
}
2021-01-05 15:37:22 +00:00
# else // EEP_SCRIPT_SIZE
2019-05-30 12:23:54 +01:00
2021-01-05 15:37:22 +00:00
// default mode is compression
int32_t len_decompressed ;
sprt = ( char * ) calloc ( UNISHOXRSIZE + 8 , 1 ) ;
if ( ! sprt ) { break ; }
glob_script_mem . script_ram = sprt ;
glob_script_mem . script_size = UNISHOXRSIZE ;
len_decompressed = SCRIPT_DECOMPRESS ( Settings . rules [ 0 ] , strlen ( Settings . rules [ 0 ] ) , glob_script_mem . script_ram , glob_script_mem . script_size ) ;
if ( len_decompressed > 0 ) glob_script_mem . script_ram [ len_decompressed ] = 0 ;
// indicates scripter use compression
bitWrite ( Settings . rule_once , 6 , 1 ) ;
2020-05-30 14:29:47 +01:00
2021-01-05 15:37:22 +00:00
# endif
2021-01-03 07:08:28 +00:00
2021-01-20 14:06:34 +00:00
# endif // USE_UFILESYS
2020-12-26 08:45:59 +00:00
2019-05-30 12:23:54 +01:00
2021-01-05 15:37:22 +00:00
// indicates scripter enabled (use rules[][] as single array)
bitWrite ( Settings . rule_once , 7 , 1 ) ;
2019-07-09 09:20:11 +01:00
2021-01-05 15:37:22 +00:00
# ifdef USE_BUTTON_EVENT
for ( uint32_t cnt = 0 ; cnt < MAX_KEYS ; cnt + + ) {
script_button [ cnt ] = - 1 ;
2019-05-30 12:23:54 +01:00
}
2021-01-05 15:37:22 +00:00
# endif //USE_BUTTON_EVENT
2020-04-15 07:11:54 +01:00
2021-01-05 15:37:22 +00:00
// a valid script MUST start with >D
if ( glob_script_mem . script_ram [ 0 ] ! = ' > ' & & glob_script_mem . script_ram [ 1 ] ! = ' D ' ) {
// clr all
memset ( glob_script_mem . script_ram , 0 , glob_script_mem . script_size ) ;
strcpy_P ( glob_script_mem . script_ram , PSTR ( " >D \n script error must start with >D " ) ) ;
bitWrite ( Settings . rule_enabled , 0 , 0 ) ;
}
2020-05-23 09:24:08 +01:00
2019-05-30 12:23:54 +01:00
// assure permanent memory is 4 byte aligned
2020-09-11 14:44:16 +01:00
{ uint32_t ptr = ( uint32_t ) glob_script_mem . script_pram ;
ptr & = 0xfffffffc ;
ptr + = 4 ;
glob_script_mem . script_pram = ( uint8_t * ) ptr ;
glob_script_mem . script_pram_size - = 4 ;
2019-05-30 12:23:54 +01:00
}
if ( bitRead ( Settings . rule_enabled , 0 ) ) Init_Scripter ( ) ;
2021-01-05 15:37:22 +00:00
2021-01-03 07:08:28 +00:00
// break;
//case FUNC_INIT:
2019-07-16 15:50:52 +01:00
if ( bitRead ( Settings . rule_enabled , 0 ) ) {
2020-09-11 14:44:16 +01:00
Run_Scripter ( " >B \n " , 3 , 0 ) ;
fast_script = Run_Scripter ( " >F " , - 2 , 0 ) ;
2019-10-02 12:38:05 +01:00
# if defined(USE_SCRIPT_HUE) && defined(USE_WEBSERVER) && defined(USE_EMULATION) && defined(USE_EMULATION_HUE) && defined(USE_LIGHT)
2019-09-30 09:25:02 +01:00
Script_Check_Hue ( 0 ) ;
2020-09-11 14:44:16 +01:00
# endif //USE_SCRIPT_HUE
2019-07-16 15:50:52 +01:00
}
2019-05-18 08:45:04 +01:00
break ;
case FUNC_EVERY_100_MSECOND :
ScripterEvery100ms ( ) ;
break ;
case FUNC_EVERY_SECOND :
ScriptEverySecond ( ) ;
break ;
case FUNC_COMMAND :
result = ScriptCommand ( ) ;
break ;
case FUNC_SET_POWER :
2019-12-16 05:52:25 +00:00
# ifdef SCRIPT_POWER_SECTION
2020-09-11 14:44:16 +01:00
if ( bitRead ( Settings . rule_enabled , 0 ) ) Run_Scripter ( " >P " , 2 , 0 ) ;
2019-12-16 05:52:25 +00:00
# else
2020-07-16 16:15:12 +01:00
if ( bitRead ( Settings . rule_enabled , 0 ) ) {
2020-09-11 14:44:16 +01:00
Run_Scripter ( " >E " , 2 , 0 ) ;
result = event_handeled ;
2020-07-16 16:15:12 +01:00
}
2020-09-11 14:44:16 +01:00
# endif //SCRIPT_POWER_SECTION
2019-12-16 05:52:25 +00:00
break ;
2019-05-18 08:45:04 +01:00
case FUNC_RULES_PROCESS :
2020-07-16 16:15:12 +01:00
if ( bitRead ( Settings . rule_enabled , 0 ) ) {
2020-10-30 11:29:48 +00:00
Run_Scripter ( " >E " , 2 , TasmotaGlobal . mqtt_data ) ;
2020-09-11 14:44:16 +01:00
result = event_handeled ;
2020-07-16 16:15:12 +01:00
}
2019-05-18 08:45:04 +01:00
break ;
# ifdef USE_WEBSERVER
case FUNC_WEB_ADD_BUTTON :
WSContentSend_P ( HTTP_BTN_MENU_RULES ) ;
break ;
2020-05-05 08:36:43 +01:00
# ifdef USE_SCRIPT_WEB_DISPLAY
2020-05-02 07:10:23 +01:00
case FUNC_WEB_ADD_MAIN_BUTTON :
2020-05-06 19:37:05 +01:00
if ( bitRead ( Settings . rule_enabled , 0 ) ) {
2020-05-25 14:49:03 +01:00
ScriptWebShow ( ' $ ' ) ;
2020-06-26 08:22:57 +01:00
# ifdef SCRIPT_FULL_WEBPAGE
2020-09-11 14:44:16 +01:00
uint8_t web_script = Run_Scripter ( " >w " , - 2 , 0 ) ;
2020-06-26 08:22:57 +01:00
if ( web_script = = 99 ) {
char bname [ 48 ] ;
2020-09-11 14:44:16 +01:00
cpy2lf ( bname , sizeof ( bname ) , glob_script_mem . section_ptr + 3 ) ;
WSContentSend_PD ( HTTP_WEB_FULL_DISPLAY , bname ) ;
2020-06-26 08:22:57 +01:00
Webserver - > on ( " /sfd " , ScriptFullWebpage ) ;
}
# endif // SCRIPT_FULL_WEBPAGE
2020-05-06 19:37:05 +01:00
}
2020-05-02 07:10:23 +01:00
break ;
2020-05-05 10:40:50 +01:00
# endif // USE_SCRIPT_WEB_DISPLAY
2019-05-18 08:45:04 +01:00
case FUNC_WEB_ADD_HANDLER :
2020-04-15 08:58:38 +01:00
Webserver - > on ( " / " WEB_HANDLE_SCRIPT , HandleScriptConfiguration ) ;
Webserver - > on ( " /ta " , HTTP_POST , HandleScriptTextareaConfiguration ) ;
2020-09-11 14:44:16 +01:00
Webserver - > on ( " /exs " , HTTP_POST , [ ] ( ) { Webserver - > sendHeader ( " Location " , " /exs " ) ; Webserver - > send ( 303 ) ; } , script_upload_start ) ;
Webserver - > on ( " /exs " , HTTP_GET , ScriptExecuteUploadSuccess ) ;
2019-05-18 08:45:04 +01:00
break ;
# endif // USE_WEBSERVER
case FUNC_SAVE_BEFORE_RESTART :
if ( bitRead ( Settings . rule_enabled , 0 ) ) {
2020-09-11 14:44:16 +01:00
Run_Scripter ( " >R " , 2 , 0 ) ;
2019-05-18 08:45:04 +01:00
Scripter_save_pvars ( ) ;
}
2020-06-21 08:13:51 +01:00
# ifdef USE_SCRIPT_GLOBVARS
Script_Stop_UDP ( ) ;
2020-09-11 14:44:16 +01:00
# endif //USE_SCRIPT_GLOBVARS
2019-05-18 08:45:04 +01:00
break ;
2019-07-23 06:01:17 +01:00
# ifdef SUPPORT_MQTT_EVENT
case FUNC_MQTT_DATA :
2019-09-18 17:50:25 +01:00
if ( bitRead ( Settings . rule_enabled , 0 ) ) {
result = ScriptMqttData ( ) ;
}
2019-07-23 06:01:17 +01:00
break ;
# endif //SUPPORT_MQTT_EVENT
2019-08-31 09:10:16 +01:00
# ifdef USE_SCRIPT_WEB_DISPLAY
case FUNC_WEB_SENSOR :
2019-09-18 17:50:25 +01:00
if ( bitRead ( Settings . rule_enabled , 0 ) ) {
2020-05-02 07:10:23 +01:00
ScriptWebShow ( 0 ) ;
2019-09-18 17:50:25 +01:00
}
2019-08-31 09:10:16 +01:00
break ;
# endif //USE_SCRIPT_WEB_DISPLAY
# ifdef USE_SCRIPT_JSON_EXPORT
case FUNC_JSON_APPEND :
2019-10-15 19:07:12 +01:00
if ( bitRead ( Settings . rule_enabled , 0 ) ) {
ScriptJsonAppend ( ) ;
}
2019-08-31 09:10:16 +01:00
break ;
# endif //USE_SCRIPT_JSON_EXPORT
2019-10-15 19:07:12 +01:00
# ifdef USE_BUTTON_EVENT
case FUNC_BUTTON_PRESSED :
if ( bitRead ( Settings . rule_enabled , 0 ) ) {
2019-10-16 04:33:22 +01:00
if ( ( script_button [ XdrvMailbox . index ] & 1 ) ! = ( XdrvMailbox . payload & 1 ) ) {
2020-09-11 14:44:16 +01:00
script_button [ XdrvMailbox . index ] = XdrvMailbox . payload ;
Run_Scripter ( " >b " , 2 , 0 ) ;
2019-10-15 19:07:12 +01:00
}
}
break ;
2020-09-11 14:44:16 +01:00
# endif //USE_BUTTON_EVENT
2019-08-31 09:10:16 +01:00
2020-06-13 12:05:25 +01:00
# ifdef USE_SCRIPT_GLOBVARS
case FUNC_LOOP :
Script_PollUdp ( ) ;
break ;
2020-09-11 14:44:16 +01:00
# endif //USE_SCRIPT_GLOBVARS
2020-06-13 12:05:25 +01:00
2019-05-18 08:45:04 +01:00
}
return result ;
}
2019-10-15 19:07:12 +01:00
2019-05-18 12:34:52 +01:00
# endif // Do not USE_RULES
2019-05-18 08:45:04 +01:00
# endif // USE_SCRIPT