Add demo mode (#1720)

* move main part to cam file

* added demo mode

* .

* add a define to configure the logfile handling (#1709)

Co-authored-by: CaCO3 <caco@ruinelli.ch>

* Move Logfile Switch to define.h

* Update Reboot Algo

* Update server_ota.cpp

* Avoid loading of status infos twice (#1711)

* Force a reboot even reboot task cannot be created due to lack of heap (#1713)

* Deinit all components before reboot

* Update

* Update

* Force reboot when reboot task cannot be created

* Improve log message when web UI is incomplete (#1716)

* improve warning if version.txt is missing

* typo

* show round duration in log

Co-authored-by: CaCO3 <caco@ruinelli.ch>

* .

* .

* .

* creade demo dir

* fix static IP in UP, improve explanation for HA (#1719)

* fix static IP in UP, improve explanation for HA

* Update edit_config_param.html

Co-authored-by: CaCO3 <caco@ruinelli.ch>

* Create demo folder at startup (if not present)

* move demo files

* Update defines.h (#1726)

* updated description

* moved to expert section

* fixed broken enabled state

Co-authored-by: CaCO3 <caco@ruinelli.ch>
Co-authored-by: jomjol <30766535+jomjol@users.noreply.github.com>
Co-authored-by: Slider0007 <115730895+Slider0007@users.noreply.github.com>
This commit is contained in:
CaCO3
2022-12-30 21:57:56 +01:00
committed by GitHub
parent 4121416743
commit 58cbd680e8
26 changed files with 178 additions and 15 deletions

View File

@@ -27,6 +27,7 @@
#include "esp_camera.h"
#include "driver/ledc.h"
#include "server_tflite.h"
static const char *TAG = "CAM";
@@ -66,16 +67,33 @@ static camera_config_t camera_config = {
};
CCamera Camera;
uint8_t *demoImage = NULL; // Buffer holding the demo image in bytes
#define DEMO_IMAGE_SIZE 30000 // Max size of demo image in bytes
typedef struct {
httpd_req_t *req;
size_t len;
} jpg_chunking_t;
bool CCamera::testCamera(void) {
bool success;
camera_fb_t *fb = esp_camera_fb_get();
if (fb) {
success = true;
}
else {
success = false;
}
esp_camera_fb_return(fb);
return success;
}
void CCamera::ledc_init(void)
{
#ifdef USE_PWM_LEDFLASH
@@ -219,6 +237,7 @@ void CCamera::EnableAutoExposure(int flash_duration)
esp_err_t CCamera::CaptureToBasisImage(CImageBasis *_Image, int delay)
{
string ftype;
int _size;
uint8_t *zwischenspeicher = NULL;
@@ -255,7 +274,12 @@ esp_err_t CCamera::CaptureToBasisImage(CImageBasis *_Image, int delay)
return ESP_FAIL;
}
int _size = fb->len;
if (demoMode) { // Use images stored on SD-Card instead of camera image
/* Replace Framebuffer with image from SD-Card */
loadNextDemoImage(fb);
}
_size = fb->len;
zwischenspeicher = (uint8_t*) malloc(_size);
if (!zwischenspeicher)
{
@@ -454,6 +478,14 @@ esp_err_t CCamera::CaptureToHTTP(httpd_req_t *req, int delay)
}
if(res == ESP_OK){
if (demoMode) { // Use images stored on SD-Card instead of camera image
LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "Using Demo image!");
/* Replace Framebuffer with image from SD-Card */
loadNextDemoImage(fb);
res = httpd_resp_send(req, (const char *)fb->buf, fb->len);
}
else {
if(fb->format == PIXFORMAT_JPEG){
fb_len = fb->len;
res = httpd_resp_send(req, (const char *)fb->buf, fb->len);
@@ -464,6 +496,7 @@ esp_err_t CCamera::CaptureToHTTP(httpd_req_t *req, int delay)
fb_len = jchunk.len;
}
}
}
esp_camera_fb_return(fb);
int64_t fr_end = esp_timer_get_time();
@@ -640,3 +673,84 @@ bool CCamera::getCameraInitSuccessful()
{
return CameraInitSuccessful;
}
std::vector<std::string> demoFiles;
void CCamera::useDemoMode()
{
char line[50];
FILE *fd = fopen("/sdcard/demo/files.txt", "r");
if (!fd) {
LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "Please provide the demo files first!");
return;
}
demoImage = (uint8_t*)malloc(DEMO_IMAGE_SIZE);
if (demoImage == NULL) {
LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "Unable to acquire required memory for demo image!");
return;
}
while (fgets(line, sizeof(line), fd) != NULL) {
line[strlen(line) - 1] = '\0';
demoFiles.push_back(line);
}
fclose(fd);
LogFile.WriteToFile(ESP_LOG_INFO, TAG, "Using Demo mode (" + std::to_string(demoFiles.size()) +
" files) instead of real camera image!");
for (auto file : demoFiles) {
LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, file);
}
demoMode = true;
}
bool CCamera::loadNextDemoImage(camera_fb_t *fb) {
char filename[50];
int readBytes;
long fileSize;
snprintf(filename, sizeof(filename), "/sdcard/demo/%s", demoFiles[getCountFlowRounds() % demoFiles.size()].c_str());
LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "Using " + std::string(filename) + " as demo image");
/* Inject saved image */
FILE * fp = fopen(filename, "rb");
if (!fp) {
LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "Failed to read file: " + std::string(filename) +"!");
return false;
}
fileSize = GetFileSize(filename);
if (fileSize > DEMO_IMAGE_SIZE) {
char buf[100];
snprintf(buf, sizeof(buf), "Demo Image (%d bytes) is larger than provided buffer (%d bytes)!",
(int)fileSize, DEMO_IMAGE_SIZE);
LogFile.WriteToFile(ESP_LOG_ERROR, TAG, std::string(buf));
return false;
}
readBytes = fread(demoImage, 1, DEMO_IMAGE_SIZE, fp);
LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "read " + std::to_string(readBytes) + " bytes");
fclose(fp);
fb->buf = demoImage; // Update pointer
fb->len = readBytes;
// ToDo do we also need to set height, width, format and timestamp?
return true;
}
long CCamera::GetFileSize(std::string filename)
{
struct stat stat_buf;
long rc = stat(filename.c_str(), &stat_buf);
return rc == 0 ? stat_buf.st_size : -1;
}

View File

@@ -26,6 +26,10 @@ class CCamera {
void ledc_init(void);
bool CameraInitSuccessful = false;
bool demoMode = false;
bool loadNextDemoImage(camera_fb_t *fb);
long GetFileSize(std::string filename);
public:
int image_height, image_width;
@@ -40,8 +44,10 @@ class CCamera {
bool SetBrightnessContrastSaturation(int _brightness, int _contrast, int _saturation);
void GetCameraParameter(httpd_req_t *req, int &qual, framesize_t &resol);
void SetLEDIntensity(float _intrel);
bool testCamera(void);
void EnableAutoExposure(int flash_duration);
bool getCameraInitSuccessful();
void useDemoMode(void);
framesize_t TextToFramesize(const char * text);

View File

@@ -140,6 +140,12 @@ bool ClassFlowMakeImage::ReadParameter(FILE* pfile, string& aktparamgraph)
ledintensity = max((float) 0, ledintensity);
Camera.SetLEDIntensity(ledintensity);
}
if ((toUpper(splitted[0]) == "DEMO") && (splitted.size() > 1))
{
if (toUpper(splitted[1]) == "TRUE")
Camera.useDemoMode();
}
}
Camera.SetBrightnessContrastSaturation(_brightness, _contrast, _saturation);

View File

@@ -273,8 +273,7 @@ extern "C" void app_main(void)
setSystemStatusFlag(SYSTEM_STATUS_CAM_BAD);
}
} else { // Test Camera
camera_fb_t * fb = esp_camera_fb_get();
if (!fb) {
if (!Camera.testCamera()) {
LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "Camera Framebuffer cannot be initialized!");
/* Easiest would be to simply restart here and try again,
how ever there seem to be systems where it fails at startup but still work corectly later.
@@ -282,7 +281,6 @@ extern "C" void app_main(void)
setSystemStatusFlag(SYSTEM_STATUS_CAM_FB_BAD);
}
else {
esp_camera_fb_return(fb);
Camera.LightOnOff(false);
}
}

View File

@@ -339,6 +339,7 @@ esp_err_t upload_post_handlerAP(httpd_req_t *req)
MakeDir("/sdcard/html");
MakeDir("/sdcard/img_tmp");
MakeDir("/sdcard/log");
MakeDir("/sdcard/demo");
printf("Nach Start des Post Handlers\n");
LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "upload_post_handlerAP");

2
demo-images/readme.md Normal file
View File

@@ -0,0 +1,2 @@
# Images for Demo Mode
See https://github.com/jomjol/AI-on-the-edge-device/wiki/Demo-Mode for details

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

View File

@@ -0,0 +1,15 @@
520.8983.jpg
520.9086.jpg
520.9351.jpg
520.9787.jpg
521.0213.jpg
521.0465.jpg
521.0929.jpg
521.1232.jpg
521.1708.jpg
521.2043.jpg
521.2170.jpg
521.2413.jpg
521.2575.jpg
521.2853.jpg
521.3027.jpg

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

View File

@@ -9,6 +9,7 @@ LEDIntensity = 50
ImageQuality = 12
ImageSize = VGA
FixedExposure = false
;Demo = false
[Alignment]
InitialRotate = 179

View File

@@ -122,6 +122,23 @@ textarea {
Time to keep the raw image (in days, resp. "0" = forever)
</td>
</tr>
<tr class="expert" id="ex1">
<td class="indent1">
<input type="checkbox" id="MakeImage_Demo_enabled" value="1" onclick = 'InvertEnableItem("MakeImage", "Demo")' unchecked >
<label for=MakeImage_Demo_enabled><class id="MakeImage_Demo_text" style="color:black;">Demo Mode</class></label>
</td>
<td>
<select id="MakeImage_Demo_value1">
<option value="true">true</option>
<option value="false" selected>false</option>
</select>
</td>
<td style="font-size: 80%;">
Enable to use demo images instead of the real camera images.<br>
Make sore to have a demo folder on your SD-Card!
See Details on <a href="https://github.com/jomjol/AI-on-the-edge-device/wiki/Demo-Mode" target="_blank">Demo Mode</a>.
</td>
</tr>
<tr class="expert" id="ex1">
<td class="indent1">
@@ -1778,6 +1795,7 @@ function UpdateInput() {
WriteParameter(param, category, "MakeImage", "LogImageLocation", true);
WriteParameter(param, category, "MakeImage", "LogfileRetentionInDays", true);
WriteParameter(param, category, "MakeImage", "Demo", true);
WriteParameter(param, category, "MakeImage", "WaitBeforeTakingPicture", false);
WriteParameter(param, category, "MakeImage", "ImageQuality", false);
WriteParameter(param, category, "MakeImage", "Brightness", false);
@@ -1898,6 +1916,7 @@ function ReadParameterAll()
ReadParameter(param, "MakeImage", "LogImageLocation", true);
ReadParameter(param, "MakeImage", "LogfileRetentionInDays", true);
ReadParameter(param, "MakeImage", "Demo", true);
ReadParameter(param, "MakeImage", "WaitBeforeTakingPicture", false);
ReadParameter(param, "MakeImage", "ImageQuality", false);
ReadParameter(param, "MakeImage", "Brightness", false);

View File

@@ -119,6 +119,7 @@ function ParseConfig() {
ParamAddValue(param, catname, "LogImageLocation");
ParamAddValue(param, catname, "WaitBeforeTakingPicture");
ParamAddValue(param, catname, "LogfileRetentionInDays");
ParamAddValue(param, catname, "Demo");
ParamAddValue(param, catname, "Brightness");
ParamAddValue(param, catname, "Contrast");
ParamAddValue(param, catname, "Saturation");