Skip to content

Commit

Permalink
v9.1.2
Browse files Browse the repository at this point in the history
  • Loading branch information
s60sc authored Nov 24, 2023
1 parent a606ba5 commit 4f52428
Show file tree
Hide file tree
Showing 11 changed files with 108 additions and 76 deletions.
3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,9 @@ Changes in version 9.1:
* All web traffic now uses single port.
* RTC ram log added to persist over soft resets

Changes in version 9.1.2
* New stream terminates older stream except NVR


## Purpose

Expand Down
12 changes: 6 additions & 6 deletions appGlobals.h
Original file line number Diff line number Diff line change
Expand Up @@ -48,8 +48,6 @@ CAMERA_MODEL_ESP32S3_CAM_LCD
// web server ports
#define HTTP_PORT 80 // insecure app access
#define HTTPS_PORT 443 // secure app access
#define STREAM_PORT (HTTP_PORT + 1)
#define STREAMS_PORT (HTTPS_PORT + 1)


/*********************** Fixed defines leave as is ***********************/
Expand All @@ -67,7 +65,7 @@ CAMERA_MODEL_ESP32S3_CAM_LCD
//#define REPORT_IDLE // core processor idle time monitoring

#define APP_NAME "ESP-CAM_MJPEG" // max 15 chars
#define APP_VER "9.1"
#define APP_VER "9.1.2"

#define HTTP_CLIENTS 2 // http, ws
#define MAX_STREAMS 2 // stream, playback, download / NVR
Expand All @@ -85,6 +83,7 @@ CAMERA_MODEL_ESP32S3_CAM_LCD
#define MAX_RAM 4096 // max object size stored in ram instead of PSRAM default is 4096
#define WARN_HEAP (32 * 1024) // low free heap warning
#define WARN_ALLOC (16 * 1024) // low free max allocatable free heap block
#define MAX_FRAME_WAIT 1200

#ifdef SIDE_ALARM
#define STORAGE LittleFS
Expand All @@ -105,9 +104,9 @@ CAMERA_MODEL_ESP32S3_CAM_LCD
#define EXTPIN 100

// to determine if newer data files need to be loaded
#define CFG_VER 4
#define HTM_VER 6
#define JS_VER 3
#define CFG_VER 5
#define HTM_VER 7
#define JS_VER 4

#define AVI_EXT "avi"
#define CSV_EXT "csv"
Expand Down Expand Up @@ -265,6 +264,7 @@ extern bool doKeepFrame;
extern int alertFrame; // which captured frame number to use for email image
extern int alertMax; // too many could cause account suspension (daily emails)
extern bool nvrStream;
extern uint8_t numStreams;

// buffers
extern uint8_t iSDbuffer[];
Expand Down
30 changes: 15 additions & 15 deletions appSpecific.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -205,20 +205,17 @@ esp_err_t appSpecificWebHandler(httpd_req_t *req, const char* variable, const ch
}
else if (!strcmp(variable, "still")) {
// send single jpeg to browser
size_t jpgLen = 0;
uint8_t* jpgBuf = NULL;
uint32_t startTime = millis();
camera_fb_t* fb = esp_camera_fb_get();
if (fb == NULL) return ESP_FAIL;
jpgLen = fb->len;
jpgBuf = fb->buf;
httpd_resp_set_type(req, "image/jpeg");
httpd_resp_set_hdr(req, "Content-Disposition", "inline; filename=capture.jpg");
httpd_resp_send(req, (const char*)jpgBuf, jpgLen);
esp_camera_fb_return(fb);
fb = NULL;
uint32_t jpegTime = millis() - startTime;
LOG_INF("JPEG: %uB in %ums", jpgLen, jpegTime);
doKeepFrame = true;
while (doKeepFrame && millis() - startTime < MAX_FRAME_WAIT) delay(100);
if (!doKeepFrame && alertBufferSize) {
httpd_resp_set_type(req, "image/jpeg");
httpd_resp_set_hdr(req, "Content-Disposition", "inline; filename=capture.jpg");
httpd_resp_send(req, (const char*)alertBuffer, alertBufferSize);
uint32_t jpegTime = millis() - startTime;
LOG_INF("JPEG: %uB in %ums", alertBufferSize, jpegTime);
alertBufferSize = 0;
} else LOG_ERR("Failed to get still");
}
return ESP_OK;
}
Expand Down Expand Up @@ -286,7 +283,8 @@ void buildAppJsonString(bool filter) {
p += sprintf(p, "\"allowReverse\":\"%d\",", allowReverse);
p += sprintf(p, "\"autoControl\":\"%d\",", autoControl);
p += sprintf(p, "\"waitTime\":\"%d\",", waitTime);

p += sprintf(p, "\"sustainId\":\"%u\",", sustainId);

// Extend info
uint8_t cardType = SD_MMC.cardType();
if (cardType == CARD_NONE) p += sprintf(p, "\"card\":\"%s\",", "NO card");
Expand Down Expand Up @@ -337,7 +335,7 @@ void currentStackUsage() {
checkStackUse(telemetryHandle, 12);
checkStackUse(uartClientHandle, 13);
// 14: http webserver
for (int i=0; i < MAX_STREAMS; i++) checkStackUse(sustainHandle[i], 15 + i);
for (int i=0; i < numStreams; i++) checkStackUse(sustainHandle[i], 15 + i);
}

void doAppPing() {
Expand All @@ -352,6 +350,7 @@ void doAppPing() {
emailCount = 0;
LOG_INF("Reset daily email allowance");
}
LOG_INF("Daily rollover");
}
doIOExtPing();
// check for night time actions
Expand Down Expand Up @@ -403,6 +402,7 @@ void appSpecificTelegramTask(void* p) {
snprintf(tgramHdr, FILE_NAME_LEN - 1, "%s\n Ver: " APP_VER "\n\n/snap", hostName);
sendTgramMessage("Rebooted", "", "");
char userCmd[FILE_NAME_LEN];
doGetExtIP = true;

while (true) {
// service requests from Telegram
Expand Down
2 changes: 2 additions & 0 deletions globals.h
Original file line number Diff line number Diff line change
Expand Up @@ -207,6 +207,7 @@ extern bool dataFilesChecked;
extern char ipExtAddr[];
extern bool usePing; // set to false if problems related to this issue occur: https://github.com/s60sc/ESP32-CAM_MJPEG2SD/issues/221
extern bool wsLog;
extern uint32_t sustainId;

// ftp server
extern char ftp_server[];
Expand Down Expand Up @@ -272,6 +273,7 @@ extern const char* otaPage_html;
extern SemaphoreHandle_t wsSendMutex;
extern char startupFailure[];
extern bool whichExt;
extern time_t currEpoch;

extern UBaseType_t uxHighWaterMarkArr[];

Expand Down
7 changes: 4 additions & 3 deletions mjpeg2sd.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -366,7 +366,7 @@ static boolean processFrame() {
camera_fb_t* fb = esp_camera_fb_get();
if (fb == NULL || !fb->len || fb->len > MAX_JPEG) return false;
timeLapse(fb);
for (int i = 0; i < MAX_STREAMS; i++) {
for (int i = 0; i < numStreams; i++) {
if (!streamBufferSize[i] && streamBuffer[i] != NULL) {
memcpy(streamBuffer[i], fb->buf, fb->len);
streamBufferSize[i] = fb->len;
Expand Down Expand Up @@ -635,7 +635,7 @@ void stopPlaying() {
stopPlayback = true;
// wait till stopped cleanly, but prevent infinite loop
uint32_t timeOut = millis();
while (doPlayback && millis() - timeOut < 2000) delay(10);
while (doPlayback && millis() - timeOut < MAX_FRAME_WAIT) delay(10);
if (doPlayback) {
// not yet closed, so force close
logLine();
Expand Down Expand Up @@ -678,7 +678,7 @@ bool prepRecording() {
playbackSemaphore = xSemaphoreCreateBinary();
aviMutex = xSemaphoreCreateMutex();
motionSemaphore = xSemaphoreCreateBinary();
for (int i = 0; i < MAX_STREAMS; i++) frameSemaphore[i] = xSemaphoreCreateBinary();
for (int i = 0; i < numStreams; i++) frameSemaphore[i] = xSemaphoreCreateBinary();
if (alertBuffer == NULL) alertBuffer = (byte*)ps_malloc(MAX_JPEG);
camera_fb_t* fb = esp_camera_fb_get();
if (fb == NULL) LOG_WRN("failed to get camera frame");
Expand Down Expand Up @@ -707,6 +707,7 @@ static void deleteTask(TaskHandle_t thisTaskHandle) {
}

void endTasks() {
for (int i = 0; i < numStreams; i++) deleteTask(sustainHandle[i]);
deleteTask(captureHandle);
deleteTask(playbackHandle);
deleteTask(DS18B20handle);
Expand Down
2 changes: 1 addition & 1 deletion motionDetect.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -190,7 +190,7 @@ void resetMotionMapSize() {

bool fetchMoveMap(uint8_t **out, size_t *out_len) {
// return change map jpeg for streaming
if (useMotion) {
if (useMotion && jpgImgSize) {
*out = jpgImg;
*out_len = jpgImgSize;
static size_t lastImgLen = 0;
Expand Down
3 changes: 2 additions & 1 deletion prefs.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ static bool updatedVers = false;
static char appId[16];
static char variable[FILE_NAME_LEN] = {0,};
static char value[FILE_NAME_LEN] = {0,};
time_t currEpoch = 0;

/********************* generic Config functions ****************************/

Expand Down Expand Up @@ -394,7 +395,7 @@ void buildJsonString(uint8_t filter) {
p += sprintf(p, "\"alertMsg\":\"%s\",", alertMsg);
alertMsg[0] = 0;
// generic footer
time_t currEpoch = getEpoch();
currEpoch = getEpoch();
p += sprintf(p, "\"clockUTC\":\"%u\",", (uint32_t)currEpoch);
char timeBuff[20];
strftime(timeBuff, 20, "%Y-%m-%d %H:%M:%S", localtime(&currEpoch));
Expand Down
31 changes: 23 additions & 8 deletions setupAssist.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -112,22 +112,34 @@ function Config(){
</html>
)~";

// in case app html file is not present, or corrupted
// <ip address>/web?OTA.htm
const char* otaPage_html = R"~(
<html>
<head>
<title>Built In OTA</title>
<title>OTA</title>
<style>
html body {height: 100%;}
body {
font-family: Helvetica !important;
background: #181818;
color: WhiteSmoke;
font-size: 1rem;;
}
</style>
</head>
<body>
<br></br>
<br>
<h3>Upload data file or bin file to ESP32</h3>
<br>
<a href="javascript:history.back()" style="color: WhiteSmoke;">Go Back</a>
<br><br><br>
<form id="upload_form" enctype="multipart/form-data" method="post">
<input type="file" name="otafile" id="otafile" onchange="otaUploadFile()"><br>
<br></br>
<progress id="progressBar" value="0" max="100" style="width:300px;"></progress>
<br>
<progress id="progressOta" value="0" max="100" style="width:200px;"></progress>%
<h3 id="status"></h3>
<p id="loaded_n_total"></p>
</form>
<script>
const defaultPort = window.location.protocol == 'http:' ? 80 : 443;
const webPort = !window.location.port ? defaultPort : window.location.port; // in case alternative ports specified
Expand All @@ -147,27 +159,30 @@ const char* otaPage_html = R"~(
xhr.addEventListener("abort", abortHandler, false);
xhr.open("POST", webServer + '/upload');
xhr.send(file);
} else console.log(response.status);
} else alert(response.status + ": " + response.statusText);
}
function progressHandler(event) {
$("#loaded_n_total").innerHTML = "Uploaded " + event.loaded + " of " + event.total + " bytes";
let percent = (event.loaded / event.total) * 100;
$("#progressBar").value = Math.round(percent);
$("#progressOta").value = Math.round(percent);
$("#status").innerHTML = Math.round(percent) + "% transferred";
if (event.loaded == event.total) $("#status").innerHTML = 'Uploaded, wait for completion result';
}
function completeHandler(event) {
$("#status").innerHTML = event.target.responseText;
$("#progressOta").value = 0;
}
function errorHandler(event) {
$("#status").innerHTML = "Upload Failed";
$("#progressOta").value = 0;
}
function abortHandler(event) {
$("#status").innerHTML = "Upload Aborted";
$("#progressOta").value = 0;
}
</script>
</body>
Expand Down
Loading

0 comments on commit 4f52428

Please sign in to comment.