Merge pull request #9575 from gemu2015/maintenance

some additions and bug fixes
This commit is contained in:
Theo Arends 2020-10-19 10:08:24 +02:00 committed by GitHub
commit 66be1ef198
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 150 additions and 23 deletions

View File

@ -462,6 +462,11 @@ void attach_Array(char *aname) {
char buff[64];
sprintf_P(buff,PSTR("Content-Disposition: attachment; filename=\"%s.txt\"\r\n\r\n"), aname);
g_client->write(buff);
// send timestamp
strcpy(buff, GetDateAndTime(DT_LOCAL).c_str());
strcat(buff,"\t");
g_client->write(buff);
float *fp=array;
for (uint32_t cnt = 0; cnt<alen; cnt++) {
// export array as tab gelimited text
@ -725,7 +730,7 @@ uint16_t SendMail(char *buffer) {
//Start sending Email, can be set callback function to track the status
if (!MailClient.sendMail(smtpData)) {
//Serial.println("Error sending Email, " + MailClient.smtpErrorReason());
AddLog_P2(LOG_LEVEL_INFO, PSTR("Error sending Email, %s"), MailClient.smtpErrorReason());
AddLog_P2(LOG_LEVEL_INFO, PSTR("Error sending Email, %s"), MailClient.smtpErrorReason().c_str());
} else {
status=0;

View File

@ -129,6 +129,10 @@ uint32_t DecodeLightId(uint32_t hue_id);
#endif
#endif // USE_SCRIPT_COMPRESSION
#ifndef STASK_PRIO
#define STASK_PRIO 1
#endif
#ifdef USE_SCRIPT_TIMER
#include <Ticker.h>
Ticker Script_ticker1;
@ -991,6 +995,11 @@ void form1000(uint32_t number, char *dp, char sc) {
#define SCRIPT_UDP_PORT 1999
IPAddress script_udp_remote_ip;
void Restart_globvars(void) {
Script_Stop_UDP();
Script_Init_UDP();
}
void Script_Stop_UDP(void) {
if (!glob_script_mem.udp_flags.udp_used) return;
if (glob_script_mem.udp_flags.udp_connected) {
@ -1862,8 +1871,12 @@ chknext:
while (*lp==' ') lp++;
float fvar2;
lp = GetNumericArgument(lp, OPER_EQU, &fvar2, 0);
float prio = STASK_PRIO;
if (*lp!=')') {
lp = GetNumericArgument(lp, OPER_EQU, &prio, 0);
}
lp++;
fvar = scripter_create_task(fvar, fvar1, fvar2);
fvar = scripter_create_task(fvar, fvar1, fvar2, prio);
len = 0;
goto exit;
}
@ -4042,12 +4055,20 @@ int16_t Run_script_sub(const char *type, int8_t tlen, JsonParserObject *jo) {
int8_t mode = fvar;
digitalWrite(pinnr, mode & 1);
goto next_line;
} else if (!strncmp(lp, "svars(", 5)) {
} else if (!strncmp(lp, "svars", 5)) {
lp += 5;
// save vars
Scripter_save_pvars();
goto next_line;
}
#ifdef USE_SCRIPT_GLOBVARS
else if (!strncmp(lp, "gvr", 3)) {
lp += 3;
// reset global vars udp server
Restart_globvars();
goto next_line;
}
#endif
#ifdef USE_LIGHT
#ifdef USE_WS2812
else if (!strncmp(lp, "ws2812(", 7)) {
@ -4712,7 +4733,6 @@ void script_upload_start(void) {
//if (upload_file) upload_file.write(upload.buf,upload.currentSize);
} else if(upload.status == UPLOAD_FILE_END) {
AddLog_P(LOG_LEVEL_INFO, PSTR("HTP: upload close"));
//if (upload_file) upload_file.close();
if (Web.upload_error) {
AddLog_P(LOG_LEVEL_INFO, PSTR("HTP: upload error"));
@ -4721,6 +4741,7 @@ void script_upload_start(void) {
bitWrite(Settings.rule_enabled, 0, sc_state);
SaveScript();
SaveScriptEnd();
//AddLog_P(LOG_LEVEL_INFO, PSTR("HTP: upload success"));
}
} else {
Web.upload_error = 1;
@ -6476,6 +6497,10 @@ void ScriptWebShow(char mc) {
lp++;
}
}
char *cv_ptr;
float cv_max=0;
float cv_inc=0;
float *cv_count=0;
while (lp) {
while (*lp==SCRIPT_EOL) {
lp++;
@ -6485,6 +6510,41 @@ void ScriptWebShow(char mc) {
}
if (*lp!=';') {
// send this line to web
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;
}
}
Replace_Cmd_Vars(lp, 1, tmp, sizeof(tmp));
char *lin = tmp;
if ((!mc && (*lin!='$')) || (mc=='w' && (*lin!='$'))) {
@ -7030,10 +7090,6 @@ bool RulesProcessEvent(char *json_event) {
#define STASK_STACK 8192
#endif
#ifndef STASK_PRIO
#define STASK_PRIO 1
#endif //ESP32
#if 1
struct ESP32_Task {
@ -7073,17 +7129,17 @@ void script_task2(void *arg) {
}
}
}
uint32_t scripter_create_task(uint32_t num, uint32_t time, uint32_t core) {
uint32_t scripter_create_task(uint32_t num, uint32_t time, uint32_t core, uint32_t prio) {
//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); }
res = xTaskCreatePinnedToCore(script_task1, "T1", STASK_STACK, NULL, STASK_PRIO, &esp32_tasks[0].task_t, core);
res = xTaskCreatePinnedToCore(script_task1, "T1", STASK_STACK, NULL, prio, &esp32_tasks[0].task_t, core);
esp32_tasks[0].task_timer = time;
} else {
if (esp32_tasks[1].task_t) { vTaskDelete(esp32_tasks[1].task_t); }
res = xTaskCreatePinnedToCore(script_task2, "T2", STASK_STACK, NULL, STASK_PRIO, &esp32_tasks[1].task_t, core);
res = xTaskCreatePinnedToCore(script_task2, "T2", STASK_STACK, NULL, prio, &esp32_tasks[1].task_t, core);
esp32_tasks[1].task_timer = time;
}
return res;
@ -7109,17 +7165,17 @@ void script_task2(void *arg) {
}
}
uint32_t scripter_create_task(uint32_t num, uint32_t time, uint32_t core) {
uint32_t scripter_create_task(uint32_t num, uint32_t time, uint32_t core, uint32_t prio) {
//return 0;
BaseType_t res = 0;
if (core > 1) { core = 1; }
if (num == 1) {
if (task_t1) { vTaskDelete(task_t1); }
res = xTaskCreatePinnedToCore(script_task1, "T1", STASK_STACK, NULL, STASK_PRIO, &task_t1, core);
res = xTaskCreatePinnedToCore(script_task1, "T1", STASK_STACK, NULL, prio, &task_t1, core);
task_timer1 = time;
} else {
if (task_t2) { vTaskDelete(task_t2); }
res = xTaskCreatePinnedToCore(script_task2, "T2", STASK_STACK, NULL, STASK_PRIO, &task_t2, core);
res = xTaskCreatePinnedToCore(script_task2, "T2", STASK_STACK, NULL, prio, &task_t2, core);
task_timer2 = time;
}
return res;

81
tasmota/xdrv_81_webcam.ino Normal file → Executable file
View File

@ -105,6 +105,19 @@ struct {
#endif
} Wc;
#ifdef ENABLE_RTSPSERVER
#include <OV2640.h>
#include <SimStreamer.h>
#include <OV2640Streamer.h>
#include <CRtspSession.h>
WiFiServer rtspServer(8554);
CStreamer *rtsp_streamer;
CRtspSession *rtsp_session;
WiFiClient rtsp_client;
uint8_t rtsp_start;
OV2640 cam;
#endif
/*********************************************************************************************/
bool WcPinUsed(void) {
@ -199,7 +212,6 @@ uint32_t WcSetup(int32_t fsiz) {
//esp_log_level_set("*", ESP_LOG_INFO);
// if PSRAM IC present, init with UXGA resolution and higher JPEG quality
// for larger pre-allocated frame buffer.
@ -216,11 +228,12 @@ uint32_t WcSetup(int32_t fsiz) {
AddLog_P2(LOG_LEVEL_DEBUG, PSTR("CAM: PSRAM not found"));
}
// AddLog_P2(LOG_LEVEL_INFO, PSTR("CAM: heap check 1: %d"),ESP_getFreeHeap());
// stupid workaround camera diver eats up static ram should prefer PSRAM
// so we steal static ram to force driver to alloc PSRAM
//ESP.getMaxAllocHeap()
// void *x=malloc(70000);
// uint32_t maxfram = ESP.getMaxAllocHeap();
// void *x=malloc(maxfram-4096);
void *x = 0;
esp_err_t err = esp_camera_init(&config);
if (x) { free(x); }
@ -230,6 +243,8 @@ uint32_t WcSetup(int32_t fsiz) {
return 0;
}
// AddLog_P2(LOG_LEVEL_INFO, PSTR("CAM: heap check 2: %d"),ESP_getFreeHeap());
sensor_t * wc_s = esp_camera_sensor_get();
wc_s->set_vflip(wc_s, Settings.webcam_config.flip);
@ -819,11 +834,16 @@ uint32_t WcSetStreamserver(uint32_t flag) {
void WcStreamControl() {
WcSetStreamserver(Settings.webcam_config.stream);
int resolution = (!Settings.webcam_config.stream) ? -1 : Settings.webcam_config.resolution;
WcSetup(resolution);
WcSetup(Settings.webcam_config.resolution);
}
/*********************************************************************************************/
#ifdef ENABLE_RTSPSERVER
static uint32_t rtsp_lastframe_time;
#ifndef RTSP_FRAME_TIME
#define RTSP_FRAME_TIME 100
#endif
#endif
void WcLoop(void) {
if (CamServer) {
@ -834,6 +854,45 @@ void WcLoop(void) {
#ifdef USE_FACE_DETECT
if (Wc.face_detect_time) { WcDetectFace(); }
#endif
#ifdef ENABLE_RTSPSERVER
if (!rtsp_start && !global_state.wifi_down && Wc.up) {
rtspServer.begin();
rtsp_start = 1;
AddLog_P2(LOG_LEVEL_INFO, PSTR("CAM: RTSP init"));
rtsp_lastframe_time = millis();
}
// If we have an active client connection, just service that until gone
if (rtsp_session) {
rtsp_session->handleRequests(0); // we don't use a timeout here,
// instead we send only if we have new enough frames
uint32_t now = millis();
if ((now-rtsp_lastframe_time) > RTSP_FRAME_TIME) {
rtsp_session->broadcastCurrentFrame(now);
rtsp_lastframe_time = now;
// AddLog_P2(LOG_LEVEL_INFO, PSTR("CAM: RTSP session frame"));
}
if (rtsp_session->m_stopped) {
delete rtsp_session;
delete rtsp_streamer;
rtsp_session = NULL;
rtsp_streamer = NULL;
AddLog_P2(LOG_LEVEL_INFO, PSTR("CAM: RTSP stopped"));
}
}
else {
rtsp_client = rtspServer.accept();
if (rtsp_client) {
rtsp_streamer = new OV2640Streamer(&rtsp_client, cam); // our streamer for UDP/TCP based RTP transport
rtsp_session = new CRtspSession(&rtsp_client, rtsp_streamer); // our threads RTSP session and state
AddLog_P2(LOG_LEVEL_INFO, PSTR("CAM: RTSP stream created"));
}
}
#endif
}
void WcPicSetup(void) {
@ -880,15 +939,16 @@ void WcInit(void) {
#define D_CMND_WC_SATURATION "Saturation"
#define D_CMND_WC_BRIGHTNESS "Brightness"
#define D_CMND_WC_CONTRAST "Contrast"
#define D_CMND_WC_INIT "Init"
const char kWCCommands[] PROGMEM = D_PRFX_WEBCAM "|" // Prefix
"|" D_CMND_WC_STREAM "|" D_CMND_WC_RESOLUTION "|" D_CMND_WC_MIRROR "|" D_CMND_WC_FLIP "|"
D_CMND_WC_SATURATION "|" D_CMND_WC_BRIGHTNESS "|" D_CMND_WC_CONTRAST
D_CMND_WC_SATURATION "|" D_CMND_WC_BRIGHTNESS "|" D_CMND_WC_CONTRAST "|" D_CMND_WC_INIT
;
void (* const WCCommand[])(void) PROGMEM = {
&CmndWebcam, &CmndWebcamStream, &CmndWebcamResolution, &CmndWebcamMirror, &CmndWebcamFlip,
&CmndWebcamSaturation, &CmndWebcamBrightness, &CmndWebcamContrast
&CmndWebcamSaturation, &CmndWebcamBrightness, &CmndWebcamContrast, &CmndWebcamInit
};
void CmndWebcam(void) {
@ -956,6 +1016,11 @@ void CmndWebcamContrast(void) {
ResponseCmndNumber(Settings.webcam_config.contrast -2);
}
void CmndWebcamInit(void) {
WcStreamControl();
ResponseCmndDone();
}
/*********************************************************************************************\
* Interface
\*********************************************************************************************/

View File

@ -108,7 +108,8 @@ void ST7789_InitDriver()
#endif
// init renderer, may use hardware spi
if (PinUsed(GPIO_SPI_CS) && (Pin(GPIO_SPI_MOSI)==HW_SPI_MOSI) && (Pin(GPIO_SPI_CLK)==HW_SPI_CLK) && PinUsed(GPIO_SPI_DC)) {
//if (PinUsed(GPIO_SPI_CS) && (Pin(GPIO_SPI_MOSI)==HW_SPI_MOSI) && (Pin(GPIO_SPI_CLK)==HW_SPI_CLK) && PinUsed(GPIO_SPI_DC)) {
if ((Pin(GPIO_SPI_MOSI)==HW_SPI_MOSI) && (Pin(GPIO_SPI_CLK)==HW_SPI_CLK) && PinUsed(GPIO_SPI_DC)) {
st7789 = new Arduino_ST7789(Pin(GPIO_SPI_DC), reset, cs, bppin);
} else {
if ((PinUsed(GPIO_SSPI_CS) || PinUsed(GPIO_OLED_RESET)) && PinUsed(GPIO_SSPI_MOSI) && PinUsed(GPIO_SSPI_SCLK) && PinUsed(GPIO_SSPI_DC)) {