From 822062fa899817c9df33c886564627ecc4b4df4b Mon Sep 17 00:00:00 2001 From: device111 <48546979+device111@users.noreply.github.com> Date: Sun, 24 May 2020 18:55:35 +0200 Subject: [PATCH 1/6] Consolidate FastPrecisePowf in veml7700 lib --- lib/Adafruit_VEML7700/Adafruit_VEML7700.cpp | 8 ++++---- lib/Adafruit_VEML7700/Adafruit_VEML7700.h | 3 ++- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/lib/Adafruit_VEML7700/Adafruit_VEML7700.cpp b/lib/Adafruit_VEML7700/Adafruit_VEML7700.cpp index 27a9fc3a6..254d74788 100644 --- a/lib/Adafruit_VEML7700/Adafruit_VEML7700.cpp +++ b/lib/Adafruit_VEML7700/Adafruit_VEML7700.cpp @@ -109,7 +109,7 @@ float Adafruit_VEML7700::normalize_resolution(float value) { * @returns Floating point Lux data (ALS multiplied by 0.0576) */ float Adafruit_VEML7700::readLux() { - return ( normalize_resolution(ALS_Data->read()) * 0.0576); // see app note lux table on page 5 + return ( normalize_resolution(ALS_Data->read()) * 0.0576f); // see app note lux table on page 5 } /*! @@ -122,7 +122,7 @@ float Adafruit_VEML7700::readLuxNormalized() { // user-provided correction for non-linearities at high lux/white values: // https://forums.adafruit.com/viewtopic.php?f=19&t=152997&p=758582#p759346 if ((getGain() == VEML7700_GAIN_1_8) && (getIntegrationTime() == VEML7700_IT_25MS)){ - lux = 6.0135e-13*alternate_pow(lux,4) - 9.3924e-9*alternate_pow(lux,3) + 8.1488e-5*alternate_pow(lux,2) + 1.0023*lux; + lux = 6.0135e-13f * pow(lux,4) - 9.3924e-9f * pow(lux,3) + 8.1488e-5f * pow(lux,2) + 1.0023f * lux; } return lux; @@ -142,7 +142,7 @@ uint16_t Adafruit_VEML7700::readALS() { */ float Adafruit_VEML7700::readWhite() { // white_corrected= 2E-15*pow(VEML_white,4) + 4E-12*pow(VEML_white,3) + 9E-06*pow(VEML_white,)2 + 1.0179*VEML_white - 11.052; - return normalize_resolution(White_Data->read()) * 0.0576; // Unclear if this is the right multiplier + return normalize_resolution(White_Data->read()) * 0.0576f; // Unclear if this is the right multiplier } /*! @@ -155,7 +155,7 @@ float Adafruit_VEML7700::readWhiteNormalized() { // user-provided correction for non-linearities at high lux values: // https://forums.adafruit.com/viewtopic.php?f=19&t=152997&p=758582#p759346 if ((getGain() == VEML7700_GAIN_1_8) && (getIntegrationTime() == VEML7700_IT_25MS)){ - white = 2E-15*alternate_pow(white,4) + 4E-12*alternate_pow(white,3) + 9E-06*alternate_pow(white,2) + 1.0179*white - 11.052; + white = 2E-15f * pow(white,4) + 4E-12f * pow(white,3) + 9E-06f * pow(white,2) + 1.0179f * white - 11.052f; } return white; diff --git a/lib/Adafruit_VEML7700/Adafruit_VEML7700.h b/lib/Adafruit_VEML7700/Adafruit_VEML7700.h index 4ff8f3f78..5ae23f3b6 100644 --- a/lib/Adafruit_VEML7700/Adafruit_VEML7700.h +++ b/lib/Adafruit_VEML7700/Adafruit_VEML7700.h @@ -62,6 +62,7 @@ #define VEML7700_POWERSAVE_MODE3 0x02 ///< Power saving mode 3 #define VEML7700_POWERSAVE_MODE4 0x03 ///< Power saving mode 4 +// FastPrecisePowf from tasmota/support_float.ino extern float FastPrecisePowf(const float x, const float y); /*! @@ -111,7 +112,7 @@ private: *PowerSave_Enable, *PowerSave_Mode; float normalize_resolution(float value); - static inline float alternate_pow(float a, float b) { return FastPrecisePowf(a, b); } + static inline float pow(float a, float b) { return FastPrecisePowf(a, b); } Adafruit_I2CDevice *i2c_dev; From eb6de5362804e44beeafd936ad56026048f1098c Mon Sep 17 00:00:00 2001 From: Norbert Richter Date: Sun, 24 May 2020 20:07:25 +0200 Subject: [PATCH 2/6] Fix setting addr typo --- tasmota/settings.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tasmota/settings.h b/tasmota/settings.h index 6ff0c4213..d524153aa 100644 --- a/tasmota/settings.h +++ b/tasmota/settings.h @@ -515,7 +515,7 @@ struct { uint8_t ot_hot_water_setpoint; // E8C uint8_t ot_boiler_setpoint; // E8D uint8_t ot_flags; // E8E - uint8_t ledpwm_mask; // F8F + uint8_t ledpwm_mask; // E8F uint16_t dimmer_hw_min; // E90 uint16_t dimmer_hw_max; // E92 uint32_t deepsleep; // E94 From c333b67669da0d72b0fb542d17ed8606b8850475 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Mon, 25 May 2020 10:21:36 +0200 Subject: [PATCH 3/6] Fix DisplaySevenSegment compilation error --- tasmota/settings.h | 2 +- tasmota/xdsp_11_sevenseg.ino | 6 ++++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/tasmota/settings.h b/tasmota/settings.h index d524153aa..23a477e12 100644 --- a/tasmota/settings.h +++ b/tasmota/settings.h @@ -515,7 +515,7 @@ struct { uint8_t ot_hot_water_setpoint; // E8C uint8_t ot_boiler_setpoint; // E8D uint8_t ot_flags; // E8E - uint8_t ledpwm_mask; // E8F + uint8_t ledpwm_mask; // E8F uint16_t dimmer_hw_min; // E90 uint16_t dimmer_hw_max; // E92 uint32_t deepsleep; // E94 diff --git a/tasmota/xdsp_11_sevenseg.ino b/tasmota/xdsp_11_sevenseg.ino index 80056aa6e..20193e54e 100644 --- a/tasmota/xdsp_11_sevenseg.ino +++ b/tasmota/xdsp_11_sevenseg.ino @@ -239,8 +239,6 @@ void SevensegTime(boolean time_24) sevenseg.writeDisplay(); } -#endif // USE_DISPLAY_MODES1TO5 - void SevensegRefresh(void) // Every second { if (disp_power) { @@ -262,6 +260,8 @@ void SevensegRefresh(void) // Every second } } +#endif // USE_DISPLAY_MODES1TO5 + /*********************************************************************************************\ * Interface \*********************************************************************************************/ @@ -286,9 +286,11 @@ bool Xdsp11(uint8_t function) case FUNC_DISPLAY_CLEAR: SevensegClear(); break; +#ifdef USE_DISPLAY_MODES1TO5 case FUNC_DISPLAY_EVERY_SECOND: SevensegRefresh(); break; +#endif // USE_DISPLAY_MODES1TO5 case FUNC_DISPLAY_ONOFF: case FUNC_DISPLAY_POWER: SevensegOnOff(); From 90d3cd45c4c6043bff73b06d02fd0144528e57f5 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Mon, 25 May 2020 11:44:17 +0200 Subject: [PATCH 4/6] Add command ``Time 4`` Add command ``Time 4`` to display timestamp using milliseconds (#8537) --- RELEASENOTES.md | 1 + tasmota/CHANGELOG.md | 3 ++- tasmota/support.ino | 3 +++ tasmota/support_command.ino | 4 ++-- tasmota/support_rtc.ino | 7 +++++++ 5 files changed, 15 insertions(+), 3 deletions(-) diff --git a/RELEASENOTES.md b/RELEASENOTES.md index f376168d1..f78f518d5 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -59,6 +59,7 @@ The following binary downloads have been compiled with ESP8266/Arduino library c - Change Energy JSON Total field from ``"Total":[33.736,11.717,16.978]`` to ``"Total":33.736,"TotalTariff":[11.717,16.978]`` - Change Energy JSON ExportActive field from ``"ExportActive":[33.736,11.717,16.978]`` to ``"ExportActive":33.736,"ExportTariff":[11.717,16.978]`` - Add command ``Rule0`` to change global rule parameters +- Add command ``Time 4`` to display timestamp using milliseconds (#8537) - Add commands ``LedPwmOn 0..255``, ``LedPwmOff 0..255`` and ``LedPwmMode1 0/1`` to control led brightness by George (#8491) - Add more functionality to ``Switchmode`` 11 and 12 (#8450) - Add wildcard pattern ``?`` for JSON matching in rules diff --git a/tasmota/CHANGELOG.md b/tasmota/CHANGELOG.md index 472cb9ffa..91ddbf196 100644 --- a/tasmota/CHANGELOG.md +++ b/tasmota/CHANGELOG.md @@ -5,8 +5,9 @@ - Change Energy JSON Total field from ``"Total":[33.736,11.717,16.978]`` to ``"Total":33.736,"TotalTariff":[11.717,16.978]`` - Change Energy JSON ExportActive field from ``"ExportActive":[33.736,11.717,16.978]`` to ``"ExportActive":33.736,"ExportTariff":[11.717,16.978]`` - Change Adafruit_SGP30 library from v1.0.3 to v1.2.0 (#8519) -- Add Three Phase Export Active Energy to SDM630 driver +- Add command ``Time 4`` to display timestamp using milliseconds (#8537) - Add commands ``LedPwmOn 0..255``, ``LedPwmOff 0..255`` and ``LedPwmMode1 0/1`` to control led brightness by George (#8491) +- Add Three Phase Export Active Energy to SDM630 driver - Add wildcard pattern ``?`` for JSON matching in rules ### 8.3.1.1 20200518 diff --git a/tasmota/support.ino b/tasmota/support.ino index c5006cf6c..21d79b510 100644 --- a/tasmota/support.ino +++ b/tasmota/support.ino @@ -996,6 +996,9 @@ char* ResponseGetTime(uint32_t format, char* time_str) case 2: snprintf_P(time_str, TIMESZ, PSTR("{\"" D_JSON_TIME "\":%u"), UtcTime()); break; + case 3: + snprintf_P(time_str, TIMESZ, PSTR("{\"" D_JSON_TIME "\":\"%s.%d\""), GetDateAndTime(DT_LOCAL).c_str(), RtcMillis()); + break; default: snprintf_P(time_str, TIMESZ, PSTR("{\"" D_JSON_TIME "\":\"%s\""), GetDateAndTime(DT_LOCAL).c_str()); } diff --git a/tasmota/support_command.ino b/tasmota/support_command.ino index 9851a5654..9d9fbfa19 100644 --- a/tasmota/support_command.ino +++ b/tasmota/support_command.ino @@ -1641,12 +1641,12 @@ void CmndTime(void) // payload 1 = Time format {"Time":"2019-09-04T14:31:29"} // payload 2 = Time format {"Time":"2019-09-04T14:31:29","Epoch":1567600289} // payload 3 = Time format {"Time":1567600289} -// payload 4 = reserved +// payload 4 = Time format {"Time":"2019-09-04T14:31:29.123"} // payload 1451602800 - disable NTP and set time to epoch uint32_t format = Settings.flag2.time_format; if (XdrvMailbox.data_len > 0) { - if ((XdrvMailbox.payload > 0) && (XdrvMailbox.payload < 4)) { + if ((XdrvMailbox.payload > 0) && (XdrvMailbox.payload < 5)) { Settings.flag2.time_format = XdrvMailbox.payload -1; format = Settings.flag2.time_format; } else { diff --git a/tasmota/support_rtc.ino b/tasmota/support_rtc.ino index 0b2249ec2..44e7dad29 100644 --- a/tasmota/support_rtc.ino +++ b/tasmota/support_rtc.ino @@ -47,6 +47,7 @@ struct RTC { uint32_t ntp_time = 0; uint32_t midnight = 0; uint32_t restart_time = 0; + uint32_t millis = 0; int32_t time_timezone = 0; uint8_t ntp_sync_minute = 0; bool midnight_now = false; @@ -239,6 +240,10 @@ uint32_t MinutesPastMidnight(void) return minutes; } +uint32_t RtcMillis(void) { + return (millis() - Rtc.millis) % 1000; +} + void BreakTime(uint32_t time_input, TIME_T &tm) { // break the given time_input into time components @@ -362,6 +367,8 @@ void RtcSecond(void) { TIME_T tmpTime; + Rtc.millis = millis(); + if (!Rtc.user_time_entry && !global_state.wifi_down) { uint8_t uptime_minute = (uptime / 60) % 60; // 0 .. 59 if ((Rtc.ntp_sync_minute > 59) && (uptime_minute > 2)) { From c1979cbd1839dafa9950440c2a0dc193224230c7 Mon Sep 17 00:00:00 2001 From: gemu2015 Date: Mon, 25 May 2020 15:49:03 +0200 Subject: [PATCH 5/6] fix >W section bug, some refactoring --- tasmota/xdrv_10_scripter.ino | 410 ++++++++++++++++++----------------- 1 file changed, 214 insertions(+), 196 deletions(-) diff --git a/tasmota/xdrv_10_scripter.ino b/tasmota/xdrv_10_scripter.ino index cf148c97b..434028092 100755 --- a/tasmota/xdrv_10_scripter.ino +++ b/tasmota/xdrv_10_scripter.ino @@ -1993,12 +1993,13 @@ chknext: goto exit; } #endif + #if defined(USE_SML_M) && defined (USE_SML_SCRIPT_CMD) if (!strncmp(vname,"sml[",4)) { lp+=4; lp=GetNumericResult(lp,OPER_EQU,&fvar,0); SCRIPT_SKIP_SPACES - fvar=SML_GetVal[fvar]; + fvar=SML_GetVal(fvar); lp++; len=0; goto exit; @@ -2786,6 +2787,7 @@ int16_t Run_Scripter(const char *type, int8_t tlen, char *js) { if (tasm_cmd_activ && tlen>0) return 0; uint8_t vtype=0,sindex,xflg,floop=0,globvindex,fromscriptcmd=0; + char *lp_next; int8_t globaindex; struct T_INDEX ind; uint8_t operand,lastop,numeric=1,if_state[IF_NEST],if_exe[IF_NEST],if_result[IF_NEST],and_or,ifstck=0; @@ -2925,6 +2927,7 @@ int16_t Run_Scripter(const char *type, int8_t tlen, char *js) { // simple implementation, zero loop count not supported lp+=3; SCRIPT_SKIP_SPACES + lp_next=0; lp=isvar(lp,&vtype,&ind,0,0,0); if ((vtype!=VAR_NV) && (vtype&STYPE)==0) { // numeric var @@ -2947,22 +2950,26 @@ int16_t Run_Scripter(const char *type, int8_t tlen, char *js) { // error toLogEOL("for error",lp); } - } else if (!strncmp(lp,"next",4) && floop>0) { - // for next loop - *cv_count+=cv_inc; - if (floop==1) { - if (*cv_count<=cv_max) { - lp=cv_ptr; + } else if (!strncmp(lp,"next",4)) { + lp+=4; + lp_next=lp; + if (floop>0) { + // for next loop + *cv_count+=cv_inc; + if (floop==1) { + if (*cv_count<=cv_max) { + lp=cv_ptr; + } else { + lp+=4; + floop=0; + } } else { - lp+=4; - floop=0; - } - } else { - if (*cv_count>=cv_max) { - lp=cv_ptr; - } else { - lp+=4; - floop=0; + if (*cv_count>=cv_max) { + lp=cv_ptr; + } else { + lp+=4; + floop=0; + } } } } @@ -3022,13 +3029,15 @@ int16_t Run_Scripter(const char *type, int8_t tlen, char *js) { #endif if (!strncmp(lp,"break",5)) { - if (floop) { + lp+=5; + if (floop && lp_next) { // should break loop + lp=lp_next; floop=0; } else { section=0; } - break; + goto next_line; } else if (!strncmp(lp,"dp",2) && isdigit(*(lp+2))) { lp+=2; // number precision @@ -3357,6 +3366,7 @@ int16_t Run_Scripter(const char *type, int8_t tlen, char *js) { goto next_line; } } else { + //Serial.printf(">> decode %s\n",lp ); // decode line if (*lp=='>' && tlen==1) { // called from cmdline @@ -4998,6 +5008,9 @@ const char SCRIPT_MSG_GTABLEb[] PROGMEM = const char SCRIPT_MSG_GOPT1[] PROGMEM = "title:'%s',isStacked:false"; +const char SCRIPT_MSG_GAUGEOPT[] PROGMEM = +"max:%d,redFrom:%d,redTo:%d,yellowFrom:%d,yellowTo:%d"; + const char SCRIPT_MSG_GOPT2[] PROGMEM = "showRowNumber:true,sort:'disable',allowHtml:true,width:'100%%',height:'100%%',cssClassNames:cssc"; @@ -5029,7 +5042,8 @@ uint8 entries=0; while (anum> %d - %d - %d\n",anum,entries,(uint32_t)*arrays[0]); *ranum=anum; *rentries=entries; return lp; @@ -5089,8 +5109,7 @@ uint32_t cnt; void ScriptWebShow(char mc) { uint8_t web_script=Run_Scripter(">W",-2,0); if (web_script==99) { - char line[128]; - char tmp[128]; + char tmp[256]; uint8_t optflg=0; uint8_t chartindex=1; uint8_t google_libs=0; @@ -5104,96 +5123,27 @@ void ScriptWebShow(char mc) { } if (*lp!=';') { // send this line to web - memcpy(line,lp,sizeof(line)); - line[sizeof(line)-1]=0; - char *cp=line; - for (uint32_t i=0; i0) { - cp="checked='checked'"; - uval=0; + Replace_Cmd_Vars(lp,1,tmp,sizeof(tmp)); + char *lin=tmp; + if (!mc && (*lin!='$')) { + // normal web section + if (*lin=='@') { + lin++; + optflg=1; } else { - cp=""; - uval=1; + optflg=0; } - WSContentSend_PD(SCRIPT_MSG_CHKBOX,label,(char*)cp,uval,vname); - - } else if (!strncmp(lin,"bu(",3)) { - char *lp=lin+3; - uint8_t bcnt=0; - char *found=lin; - while (bcnt<4) { - found=strstr(found,"bu("); - if (!found) break; - found+=3; - bcnt++; - } - uint8_t proz=100/bcnt; - if (!optflg && bcnt>1) proz-=2; - if (optflg) WSContentSend_PD(SCRIPT_MSG_BUT_START_TBL); - else WSContentSend_PD(SCRIPT_MSG_BUT_START); - for (uint32_t cnt=0;cnt0) { - cp=ontxt; + cp="checked='checked'"; uval=0; } else { - cp=offtxt; + cp=""; uval=1; } - if (bcnt>1 && cnt==bcnt-1) { - if (!optflg) proz+=2; + WSContentSend_PD(SCRIPT_MSG_CHKBOX,label,(char*)cp,uval,vname); + + } else if (!strncmp(lin,"bu(",3)) { + char *lp=lin+3; + uint8_t bcnt=0; + char *found=lin; + while (bcnt<4) { + found=strstr(found,"bu("); + if (!found) break; + found+=3; + bcnt++; } - if (!optflg) { - WSContentSend_PD(SCRIPT_MSG_BUTTONa,proz,uval,vname,cp); - } else { - WSContentSend_PD(SCRIPT_MSG_BUTTONa_TBL,proz,uval,vname,cp); + uint8_t proz=100/bcnt; + if (!optflg && bcnt>1) proz-=2; + if (optflg) WSContentSend_PD(SCRIPT_MSG_BUT_START_TBL); + else WSContentSend_PD(SCRIPT_MSG_BUT_START); + for (uint32_t cnt=0;cnt0) { + cp=ontxt; + uval=0; + } else { + cp=offtxt; + uval=1; + } + if (bcnt>1 && cnt==bcnt-1) { + if (!optflg) proz+=2; + } + if (!optflg) { + WSContentSend_PD(SCRIPT_MSG_BUTTONa,proz,uval,vname,cp); + } else { + WSContentSend_PD(SCRIPT_MSG_BUTTONa_TBL,proz,uval,vname,cp); + } + if (bcnt>1 && cnt1 && cnt%s"),tmp); } else { - WSContentSend_PD(PSTR("{s}%s{e}"),tmp); + if (optflg) { + WSContentSend_PD(PSTR("
%s
"),tmp); + } else { + WSContentSend_PD(PSTR("{s}%s{e}"),tmp); + } } - } + // end standard web interface } else { + // main section interface if (*lin==mc) { #ifdef USE_GOOGLE_CHARTS lin++; + char *lp; if (!strncmp(lin,"gc(",3)) { // get google table lp=lin+3; SCRIPT_SKIP_SPACES const char *type; const char *func; - char options[256]; + char options[312]; uint8_t nanum=MAX_GARRAY; uint8_t y2f=0; char ctype; @@ -5377,18 +5389,9 @@ void ScriptWebShow(char mc) { char label[SCRIPT_MAXSSIZE]; lp=GetStringResult(lp,OPER_EQU,label,0); SCRIPT_SKIP_SPACES - char *lblp=label; for (uint32_t ind=0; ind=0) { + sprintf(lbl,"%d",todflg); + todflg++; + } else { + GetTextIndexed(lbl, sizeof(lbl), cnt, label); } WSContentSend_PD(lbl); WSContentSend_PD("',"); @@ -5466,17 +5470,31 @@ void ScriptWebShow(char mc) { SCRIPT_SKIP_SPACES snprintf_P(options,sizeof(options),SCRIPT_MSG_GOPT3,header,(uint32_t)max1,(uint32_t)max2,func); } + + if (ctype=='g') { + float yellowFrom; + lp=GetNumericResult(lp,OPER_EQU,&yellowFrom,0); + SCRIPT_SKIP_SPACES + float redFrom; + lp=GetNumericResult(lp,OPER_EQU,&redFrom,0); + SCRIPT_SKIP_SPACES + float maxValue; + lp=GetNumericResult(lp,OPER_EQU,&maxValue,0); + SCRIPT_SKIP_SPACES + 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); + } } WSContentSend_PD(SCRIPT_MSG_GTABLEb,options,type,chartindex); chartindex++; } else { - Replace_Cmd_Vars(lin,0,tmp,sizeof(tmp)); - WSContentSend_PD(PSTR("%s"),tmp); + WSContentSend_PD(PSTR("%s"),lin); } #else } else { - Replace_Cmd_Vars(lin,0,tmp,sizeof(tmp)); - WSContentSend_PD(PSTR("%s"),tmp); + // WSContentSend_PD(PSTR("%s"),lin); #endif //USE_GOOGLE_CHARTS } } @@ -5809,7 +5827,7 @@ bool Xdrv10(uint8_t function) #ifdef USE_SCRIPT_WEB_DISPLAY case FUNC_WEB_ADD_MAIN_BUTTON: if (bitRead(Settings.rule_enabled, 0)) { - ScriptWebShow('&'); + ScriptWebShow('$'); } break; #endif // USE_SCRIPT_WEB_DISPLAY From 2e88ced738c7264764b8a1265526c9689c8982bc Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Mon, 25 May 2020 17:25:47 +0200 Subject: [PATCH 6/6] Fix exception due to webcam problem Fix exception due to webcam problem (#8534) --- tasmota/xdrv_81_webcam.ino | 88 ++++++++++++++++++++------------------ 1 file changed, 47 insertions(+), 41 deletions(-) diff --git a/tasmota/xdrv_81_webcam.ino b/tasmota/xdrv_81_webcam.ino index fb2c86161..a43685e4c 100644 --- a/tasmota/xdrv_81_webcam.ino +++ b/tasmota/xdrv_81_webcam.ino @@ -94,14 +94,16 @@ WiFiClient client; #define HREF_GPIO_NUM 23 #define PCLK_GPIO_NUM 22 -uint8_t wc_up; -uint16_t wc_width; -uint16_t wc_height; -uint8_t wc_stream_active; +struct { + uint8_t up; + uint16_t width; + uint16_t height; + uint8_t stream_active; #ifdef USE_FACE_DETECT -uint8_t faces; -uint16_t face_detect_time; + uint8_t faces; + uint16_t face_detect_time; #endif +} Wc; /*********************************************************************************************/ @@ -128,18 +130,18 @@ bool WcPinUsed(void) { uint32_t WcSetup(int32_t fsiz) { if (fsiz > 10) { fsiz = 10; } - wc_stream_active = 0; + Wc.stream_active = 0; if (fsiz < 0) { esp_camera_deinit(); - wc_up = 0; + Wc.up = 0; return 0; } - if (wc_up) { + if (Wc.up) { esp_camera_deinit(); AddLog_P2(LOG_LEVEL_DEBUG, PSTR("CAM: Deinit")); - //return wc_up; + //return Wc.up; } //esp_log_level_set("*", ESP_LOG_VERBOSE); @@ -239,8 +241,12 @@ uint32_t WcSetup(int32_t fsiz) { wc_s->set_framesize(wc_s, (framesize_t)fsiz); camera_fb_t *wc_fb = esp_camera_fb_get(); - wc_width = wc_fb->width; - wc_height = wc_fb->height; + if (!wc_fb) { + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("CAM: Failed to get the frame on time")); + return 0; + } + Wc.width = wc_fb->width; + Wc.height = wc_fb->height; esp_camera_fb_return(wc_fb); #ifdef USE_FACE_DETECT @@ -249,10 +255,10 @@ uint32_t WcSetup(int32_t fsiz) { AddLog_P2(LOG_LEVEL_DEBUG, PSTR("CAM: Initialized")); - wc_up = 1; - if (psram) { wc_up=2; } + Wc.up = 1; + if (psram) { Wc.up=2; } - return wc_up; + return Wc.up; } /*********************************************************************************************/ @@ -299,17 +305,17 @@ int32_t WcSetOptions(uint32_t sel, int32_t value) { uint32_t WcGetWidth(void) { camera_fb_t *wc_fb = esp_camera_fb_get(); if (!wc_fb) { return 0; } - wc_width = wc_fb->width; + Wc.width = wc_fb->width; esp_camera_fb_return(wc_fb); - return wc_width; + return Wc.width; } uint32_t WcGetHeight(void) { camera_fb_t *wc_fb = esp_camera_fb_get(); if (!wc_fb) { return 0; } - wc_height = wc_fb->height; + Wc.height = wc_fb->height; esp_camera_fb_return(wc_fb); - return wc_height; + return Wc.height; } /*********************************************************************************************/ @@ -447,8 +453,8 @@ void draw_face_boxes(dl_matrix3du_t *image_matrix, box_array_t *boxes, int face_ #define DL_SPIRAM_SUPPORT uint32_t WcSetFaceDetect(int32_t value) { - if (value >= 0) { face_detect_time = value; } - return faces; + if (value >= 0) { Wc.face_detect_time = value; } + return Wc.faces; } uint32_t face_ltime; @@ -464,7 +470,7 @@ uint32_t WcDetectFace(void) { int face_id = 0; camera_fb_t *fb; - if ((millis() - face_ltime) > face_detect_time) { + if ((millis() - face_ltime) > Wc.face_detect_time) { face_ltime = millis(); fb = esp_camera_fb_get(); if (!fb) { return ESP_FAIL; } @@ -492,7 +498,7 @@ uint32_t WcDetectFace(void) { box_array_t *net_boxes = face_detect(image_matrix, &mtmn_config); if (net_boxes){ detected = true; - faces = net_boxes->len; + Wc.faces = net_boxes->len; //if(recognition_enabled){ // face_id = run_face_recognition(image_matrix, net_boxes); //} @@ -502,10 +508,10 @@ uint32_t WcDetectFace(void) { free(net_boxes->landmark); free(net_boxes); } else { - faces = 0; + Wc.faces = 0; } dl_matrix3du_free(image_matrix); - //Serial.printf("face detected: %d",faces); + //Serial.printf("face detected: %d",Wc.faces); } } @@ -564,8 +570,8 @@ uint32_t WcGetFrame(int32_t bnum) { return 0; } if (!bnum) { - wc_width = wc_fb->width; - wc_height = wc_fb->height; + Wc.width = wc_fb->width; + Wc.height = wc_fb->height; esp_camera_fb_return(wc_fb); return 0; } @@ -691,9 +697,9 @@ void HandleImageBasic(void) { void HandleWebcamMjpeg(void) { AddLog_P2(LOG_LEVEL_DEBUG, PSTR("CAM: Handle camserver")); -// if (!wc_stream_active) { +// if (!Wc.stream_active) { // always restart stream - wc_stream_active = 1; + Wc.stream_active = 1; client = CamServer->client(); AddLog_P2(LOG_LEVEL_DEBUG, PSTR("CAM: Create client")); // } @@ -710,25 +716,25 @@ void HandleWebcamMjpegTask(void) { if (!client.connected()) { AddLog_P2(LOG_LEVEL_DEBUG, PSTR("CAM: Client fail")); - wc_stream_active = 0; + Wc.stream_active = 0; } - if (1 == wc_stream_active) { + if (1 == Wc.stream_active) { client.flush(); client.setTimeout(3); AddLog_P2(LOG_LEVEL_DEBUG, PSTR("CAM: Start stream")); client.print("HTTP/1.1 200 OK\r\n" "Content-Type: multipart/x-mixed-replace;boundary=" BOUNDARY "\r\n" "\r\n"); - wc_stream_active = 2; + Wc.stream_active = 2; } - if (2 == wc_stream_active) { + if (2 == Wc.stream_active) { wc_fb = esp_camera_fb_get(); if (!wc_fb) { AddLog_P2(LOG_LEVEL_DEBUG, PSTR("CAM: Frame fail")); - wc_stream_active = 0; + Wc.stream_active = 0; } } - if (2 == wc_stream_active) { + if (2 == Wc.stream_active) { if (wc_fb->format != PIXFORMAT_JPEG) { jpeg_converted = frame2jpg(wc_fb, 80, &_jpg_buf, &_jpg_buf_len); if (!jpeg_converted){ @@ -748,7 +754,7 @@ void HandleWebcamMjpegTask(void) { /* if (tlen!=_jpg_buf_len) { esp_camera_fb_return(wc_fb); - wc_stream_active=0; + Wc.stream_active=0; AddLog_P2(LOG_LEVEL_DEBUG, PSTR("CAM: Send fail")); }*/ client.print("\r\n--" BOUNDARY "\r\n"); @@ -768,7 +774,7 @@ void HandleWebcamMjpegTask(void) { esp_camera_fb_return(wc_fb); //AddLog_P2(LOG_LEVEL_DEBUG, PSTR("CAM: send frame")); } - if (0 == wc_stream_active) { + if (0 == Wc.stream_active) { AddLog_P2(LOG_LEVEL_DEBUG, PSTR("CAM: Stream exit")); client.flush(); client.stop(); @@ -787,7 +793,7 @@ void HandleWebcamRoot(void) { uint32_t WcSetStreamserver(uint32_t flag) { if (global_state.wifi_down) { return 0; } - wc_stream_active = 0; + Wc.stream_active = 0; if (flag) { if (!CamServer) { @@ -821,11 +827,11 @@ void WcStreamControl() { void WcLoop(void) { if (CamServer) { CamServer->handleClient(); - if (wc_stream_active) { HandleWebcamMjpegTask(); } + if (Wc.stream_active) { HandleWebcamMjpegTask(); } } if (motion_detect) { WcDetectMotion(); } #ifdef USE_FACE_DETECT - if (face_detect_time) { WcDetectFace(); } + if (Wc.face_detect_time) { WcDetectFace(); } #endif } @@ -841,7 +847,7 @@ void WcShowStream(void) { WcStreamControl(); delay(50); // Give the webcam webserver some time to prepare the stream } - if (CamServer) { + if (CamServer && Wc.up) { WSContentSend_P(PSTR("

Webcam stream

"), WiFi.localIP().toString().c_str()); }