Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion data/default_conn.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
"user":"admin",
"pwd":"admin",
"ota_enabled":false,
"ota_password":"changeit!",
"ota_password":"changeit",
"accesspoint":false,
"ap_ssid":"esp32cam",
"ap_pass":"123456789",
Expand Down
7 changes: 7 additions & 0 deletions partitions.csv
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# Name, Type, SubType, Offset, Size, Flags
nvs, data, nvs, 0x9000, 0x5000,
otadata, data, ota, 0xe000, 0x2000,
app0, app, ota_0, 0x10000, 0x1A0000,
app1, app, ota_1, , 0x1A0000,
spiffs, data, spiffs, , 0x0A0000,
coredump, data, coredump,0x3F0000, 0x10000,
86 changes: 49 additions & 37 deletions platformio.ini
Original file line number Diff line number Diff line change
@@ -1,53 +1,65 @@
; PlatformIO Project Configuration File
; https://docs.platformio.org/page/projectconf.html

; ================================================================
; = =
; = DO NOT USE PLATFORMIO FOR THIS PROJECT =
; = =
; = 14 March 2022 : When built with Platformio this project =
; = does not run properly; any streams you start will fail =
; = with 'ESP_ERR_HTTPD_RESP_SEND' in the serial console and =
; = ERR_INVALID_CHUNK_ENCODING 200 (OK) in the browser console.=
; = =
; = This is a difficult issue, and currently unresolved. =
; = See: =
; = https://github.com/easytarget/esp32-cam-webserver/issues/218 =
; = =
; = The focus of thei project is to show a expanded example =
; = using the official Arduino IDE. PlatformIO is, and has =
; = always been, a nice-to-have; so I will be releasing 4.x =
; = without platformio support. See the above github issue if =
; = you are able to help fixing this. =
; = =
; ================================================================
;

; The esp32-cam-webserver project is intended to be easily compilable
; with the stock Arduino IDE.
; - Maintaining compatibility with other development environments
; is important, but I wont accept changes to the PlatformIO build that
; break compatibilty with the stock IDE. Eg by using non-standard
; partition schemes or overriding Arduino defined limits, etc.
[env]
monitor_speed = 115200
upload_speed = 921600
platform = espressif32
framework = arduino
monitor_rts = 0
monitor_dtr = 0
; https://registry.platformio.org/tools/espressif/toolchain-riscv32-esp/versions
;platform_packages = espressif/toolchain-riscv32-esp
board_build.partitions = partitions.csv
;board_build.partitions = min_spiffs.csv
board_build.filesystem = littlefs
monitor_filters = esp32_exception_decoder
build_flags =
!python scripts/build_flags.py git_branch
!python scripts/build_flags.py git_repo
!python scripts/build_flags.py git_owner
-D GITHUB_RUN=\"${sysenv.GITHUB_RUN}\"
; -D WIFISSID=\"gast\" ; use fixed WiFi credentials if Improv-WiFi-Library isn´t supported by your board
; -D WIFIPASSWORD=\"12345678\" ; use fixed WiFi credentials if Improv-WiFi-Library isn´t supported by your board
lib_deps =
https://github.com/mathieucarbou/ESPAsyncWebServer ; installing by ElegantOTA
https://github.com/espressif/json_generator.git
https://github.com/espressif/json_parser.git
bblanchon/ArduinoJson@>6.19.0
;https://github.com/tobiasfaust/Improv-WiFi-Library.git
;https://github.com/tobiasfaust/ElegantOTA.git


[env:firmware_ESP32]
board = esp32dev
build_flags = ${env.build_flags}
-DBOARD_HAS_PSRAM
-mfix-esp32-psram-cache-issue
-D USE_LittleFS=1
-D CAMERA_MODEL_AI_THINKER=1

[platformio]
src_dir = ./

[env:esp32dev]
platform = https://github.com/platformio/platform-espressif32.git#feature/arduino-upstream
platform_packages = framework-arduinoespressif32@https://github.com/espressif/arduino-esp32.git#2.0.3
platform = espressif32
board = esp32dev
board_build.partitions = min_spiffs.csv
framework = arduino
board_build.filesystem = littlefs
build_flags =
-DBOARD_HAS_PSRAM
-mfix-esp32-psram-cache-issue
-D USE_LittleFS=1
-D CAMERA_MODEL_AI_THINKER=1
; -D CAMERA_MODEL_WROVER_KIT=1 # default
; -D CAMERA_MODEL_ESP_EYE=1
; -D CAMERA_MODEL_M5STACK_PSRAM=1
; -D CAMERA_MODEL_M5STACK_V2_PSRAM=1
; -D CAMERA_MODEL_M5STACK_WIDE=1
; -D CAMERA_MODEL_M5STACK_ESP32CAM=1 # Originally: CAMERA_MODEL_M5STACK_NO_PSRAM
; -D CAMERA_MODEL_TTGO_T_JOURNAL=1
; -D CAMERA_MODEL_ARDUCAM_ESP32S_UNO=1
; -D CAMERA_MODEL_LILYGO_T_SIMCAM=1

; using the latest version of libraries
lib_deps =
https://github.com/me-no-dev/ESPAsyncWebServer.git
https://github.com/espressif/json_generator.git
https://github.com/espressif/json_parser.git

; For OTA uploading uncomment the next lines and add the IP address or mDNS name of the camera module, and the OTA password
;upload_protocol = espota
Expand Down
21 changes: 21 additions & 0 deletions scripts/build_flags.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import subprocess;
import sys;
import os, re;

def git_branch():
print('-D GIT_BRANCH=\\"%s\\"' % subprocess.check_output(['git', 'rev-parse', '--abbrev-ref', 'HEAD']).strip().decode())

def git_repo():
output = subprocess.check_output(['git', 'rev-parse', '--show-toplevel'])
repo = os.path.basename(output).strip().decode()
print('-D GIT_REPO=\\"%s\\"' % repo);

def git_owner():
# get the github owner of the origin repo
output = subprocess.check_output(['git', 'config', '--get', 'remote.origin.url'])
owner = re.search(r'github.com[:/](.*)/', output.decode()).group(1)
print('-D GIT_OWNER=\\"%s\\"' % owner);


if __name__ == '__main__':
globals()[sys.argv[1]]()
171 changes: 81 additions & 90 deletions src/app_cam.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,8 @@ int CLAppCam::start() {
config.pin_pclk = PCLK_GPIO_NUM;
config.pin_vsync = VSYNC_GPIO_NUM;
config.pin_href = HREF_GPIO_NUM;
config.pin_sscb_sda = SIOD_GPIO_NUM;
config.pin_sscb_scl = SIOC_GPIO_NUM;
config.pin_sccb_sda = SIOD_GPIO_NUM;
config.pin_sccb_scl = SIOC_GPIO_NUM;
config.pin_pwdn = PWDN_GPIO_NUM;
config.pin_reset = RESET_GPIO_NUM;
config.xclk_freq_hz = xclk * 1000000;
Expand Down Expand Up @@ -81,91 +81,85 @@ int CLAppCam::stop() {
}

int CLAppCam::loadPrefs() {
jparse_ctx_t jctx;
int ret = parsePrefs(&jctx);
JsonDocument json;
int ret = parsePrefs(json);
if(ret != OS_SUCCESS) {
return ret;
}

// process local settings

json_obj_get_int(&jctx, (char*)"frame_rate", &frameRate);
json_obj_get_int(&jctx, (char*)"xclk", &xclk);
json_obj_get_int(&jctx, (char*)"rotate", &myRotation);
this->frameRate = json["frame_rate"];
this->xclk = json["xclk"];
this->myRotation = json["rotate"];

// get sensor reference
sensor_t * s = esp_camera_sensor_get();
// process camera settings
if(s) {
s->set_framesize(s, (framesize_t)readJsonIntVal(&jctx, "framesize"));
s->set_quality(s, readJsonIntVal(&jctx, "quality"));
s->set_framesize(s, (framesize_t)json["framesize"]);
s->set_quality(s, json["quality"]);
s->set_xclk(s, LEDC_TIMER_0, xclk);
s->set_brightness(s, readJsonIntVal(&jctx, "brightness"));
s->set_contrast(s, readJsonIntVal(&jctx, "contrast"));
s->set_saturation(s, readJsonIntVal(&jctx, "saturation"));
s->set_sharpness(s, readJsonIntVal(&jctx, "sharpness"));
s->set_denoise(s, readJsonIntVal(&jctx, "denoise"));
s->set_special_effect(s, readJsonIntVal(&jctx, "special_effect"));
s->set_wb_mode(s, readJsonIntVal(&jctx, "wb_mode"));
s->set_whitebal(s, readJsonIntVal(&jctx, "awb"));
s->set_awb_gain(s, readJsonIntVal(&jctx, "awb_gain"));
s->set_exposure_ctrl(s, readJsonIntVal(&jctx, "aec"));
s->set_aec2(s, readJsonIntVal(&jctx, "aec2"));
s->set_ae_level(s, readJsonIntVal(&jctx, "ae_level"));
s->set_aec_value(s, readJsonIntVal(&jctx, "aec_value"));
s->set_gain_ctrl(s, readJsonIntVal(&jctx, "agc"));
s->set_agc_gain(s, readJsonIntVal(&jctx, "agc_gain"));
s->set_gainceiling(s, (gainceiling_t)readJsonIntVal(&jctx, "gainceiling"));
s->set_bpc(s, readJsonIntVal(&jctx, "bpc"));
s->set_wpc(s, readJsonIntVal(&jctx, "wpc"));
s->set_raw_gma(s, readJsonIntVal(&jctx, "raw_gma"));
s->set_lenc(s, readJsonIntVal(&jctx, "lenc"));
s->set_vflip(s, readJsonIntVal(&jctx, "vflip"));
s->set_hmirror(s, readJsonIntVal(&jctx, "hmirror"));
s->set_dcw(s, readJsonIntVal(&jctx, "dcw"));
s->set_colorbar(s, readJsonIntVal(&jctx, "colorbar"));
s->set_brightness(s, json["brightness"]);
s->set_contrast(s, json["contrast"]);
s->set_saturation(s, json["saturation"]);
s->set_sharpness(s, json["sharpness"]);
s->set_denoise(s, json["denoise"]);
s->set_special_effect(s, json["special_effect"]);
s->set_wb_mode(s, json["wb_mode"]);
s->set_whitebal(s, json["awb"]);
s->set_awb_gain(s, json["awb_gain"]);
s->set_exposure_ctrl(s, json["aec"]);
s->set_aec2(s, json["aec2"]);
s->set_ae_level(s, json["ae_level"]);
s->set_aec_value(s, json["aec_value"]);
s->set_gain_ctrl(s, json["agc"]);
s->set_agc_gain(s, json["agc_gain"]);
s->set_gainceiling(s, (gainceiling_t)json["gainceiling"]);
s->set_bpc(s, json["bpc"]);
s->set_wpc(s, json["wpc"]);
s->set_raw_gma(s, json["raw_gma"]);
s->set_lenc(s, json["lenc"]);
s->set_vflip(s, json["vflip"]);
s->set_hmirror(s, json["hmirror"]);
s->set_dcw(s, json["dcw"]);
s->set_colorbar(s, json["colorbar"]);

if(json["debug_mode"]) setDebugMode(json["debug_mode"]);

bool dbg;
if(json_obj_get_bool(&jctx, (char*)"debug_mode", &dbg) == OS_SUCCESS)
setDebugMode(dbg);
}
else {
Serial.println("Failed to get camera handle. Camera settings skipped");
}

// close the file
json_parse_end(&jctx);

return ret;
}

int CLAppCam::savePrefs(){
char * prefs_file = getPrefsFileName(true);
JsonDocument json;
char* prefs_file = getPrefsFileName(true);

if (Storage.exists(prefs_file)) {
Serial.print("Updating ");
Serial.printf("Updating %s\r\n", prefs_file);
} else {
Serial.print("Creating ");
Serial.printf("Creating %s\r\n", prefs_file);
}
Serial.println(prefs_file);

char buf[CAM_DUMP_BUFFER_SIZE];
json_gen_str_t jstr;
json_gen_str_start(&jstr, buf, sizeof(buf), NULL, NULL);
json_gen_start_object(&jstr);

dumpStatusToJson(&jstr);

json_gen_end_object(&jstr);
json_gen_str_end(&jstr);
dumpStatusToJson(json);

File file = Storage.open(prefs_file, FILE_WRITE);
if(file) {
file.print(buf);
serializeJson(json, file);
serializeJsonPretty(json, Serial);
Serial.println();

file.close();
Serial.printf("File %s updated\r\n", prefs_file);

return OK;
}
else {
Serial.print("Failed to save camera preferences to file "); Serial.println(prefs_file);
Serial.printf("Failed to save camery preferences to file %s\r\n", prefs_file);
return FAIL;
}

Expand All @@ -184,50 +178,47 @@ void IRAM_ATTR CLAppCam::releaseBuffer() {
}
}

void CLAppCam::dumpStatusToJson(json_gen_str_t * jstr, bool full_status) {

void CLAppCam::dumpStatusToJson(JsonDocument& json, bool full_status) {

json_gen_obj_set_int(jstr, (char*)"rotate", myRotation);
json["rotate"] = this->myRotation;

if(getLastErr()) return;

sensor_t * s = esp_camera_sensor_get();
json_gen_obj_set_int(jstr, (char*)"cam_pid", s->id.PID);
json_gen_obj_set_int(jstr, (char*)"cam_ver", s->id.VER);
json_gen_obj_set_int(jstr, (char*)"framesize", s->status.framesize);
json_gen_obj_set_int(jstr, (char*)"frame_rate", frameRate);
json["cam_pid"] = s->id.PID;
json["cam_ver"] = s->id.VER;
json["framesize"] = s->status.framesize;
json["frame_rate"] = this->frameRate;

if(!full_status) return;

json_gen_obj_set_int(jstr, (char*)"quality", s->status.quality);
json_gen_obj_set_int(jstr, (char*)"brightness", s->status.brightness);
json_gen_obj_set_int(jstr, (char*)"contrast", s->status.contrast);
json_gen_obj_set_int(jstr, (char*)"saturation", s->status.saturation);
json_gen_obj_set_int(jstr, (char*)"sharpness", s->status.sharpness);
json_gen_obj_set_int(jstr, (char*)"denoise", s->status.denoise);
json_gen_obj_set_int(jstr, (char*)"special_effect", s->status.special_effect);
json_gen_obj_set_int(jstr, (char*)"wb_mode", s->status.wb_mode);
json_gen_obj_set_int(jstr, (char*)"awb", s->status.awb);
json_gen_obj_set_int(jstr, (char*)"awb_gain", s->status.awb_gain);
json_gen_obj_set_int(jstr, (char*)"aec", s->status.aec);
json_gen_obj_set_int(jstr, (char*)"aec2", s->status.aec2);
json_gen_obj_set_int(jstr, (char*)"ae_level", s->status.ae_level);
json_gen_obj_set_int(jstr, (char*)"aec_value", s->status.aec_value);
json_gen_obj_set_int(jstr, (char*)"agc", s->status.agc);
json_gen_obj_set_int(jstr, (char*)"agc_gain", s->status.agc_gain);
json_gen_obj_set_int(jstr, (char*)"gainceiling", s->status.gainceiling);
json_gen_obj_set_int(jstr, (char*)"bpc", s->status.bpc);
json_gen_obj_set_int(jstr, (char*)"wpc", s->status.wpc);
json_gen_obj_set_int(jstr, (char*)"raw_gma", s->status.raw_gma);
json_gen_obj_set_int(jstr, (char*)"lenc", s->status.lenc);
json_gen_obj_set_int(jstr, (char*)"vflip", s->status.vflip);
json_gen_obj_set_int(jstr, (char*)"hmirror", s->status.hmirror);
json_gen_obj_set_int(jstr, (char*)"dcw", s->status.dcw);
json_gen_obj_set_int(jstr, (char*)"colorbar", s->status.colorbar);
json_gen_obj_set_bool(jstr, (char*)"debug_mode", isDebugMode());

json_gen_obj_set_int(jstr, (char*)"xclk", xclk);

json["quality"] = s->status.quality;
json["brightness"] = s->status.brightness;
json["contrast"] = s->status.contrast;
json["saturation"] = s->status.saturation;
json["sharpness"] = s->status.sharpness;
json["denoise"] = s->status.denoise;
json["special_effect"] = s->status.special_effect;
json["wb_mode"] = s->status.wb_mode;
json["awb"] = s->status.awb;
json["awb_gain"] = s->status.awb_gain;
json["aec"] = s->status.aec;
json["aec2"] = s->status.aec2;
json["ae_level"] = s->status.ae_level;
json["aec_value"] = s->status.aec_value;
json["agc"] = s->status.agc;
json["agc_gain"] = s->status.agc_gain;
json["gainceiling"] = s->status.gainceiling;
json["bpc"] = s->status.bpc;
json["wpc"] = s->status.wpc;
json["raw_gma"] = s->status.raw_gma;
json["lenc"] = s->status.lenc;
json["vflip"] = s->status.vflip;
json["hmirror"] = s->status.hmirror;
json["dcw"] = s->status.dcw;
json["colorbar"] = s->status.colorbar;
json["debug_mode"] = this->isDebugMode();
json["xclk"] = this->xclk;
}


Expand Down
3 changes: 2 additions & 1 deletion src/app_cam.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
#include <esp_camera.h>
#include <esp_int_wdt.h>
#include <esp_task_wdt.h>
#include <ArduinoJson.h>

#include "app_component.h"
#include "camera_pins.h"
Expand Down Expand Up @@ -44,7 +45,7 @@ class CLAppCam : public CLAppComponent {
bool IRAM_ATTR isJPEGinBuffer() {return (fb?fb->format == PIXFORMAT_JPEG:false);};
void releaseBuffer();

void dumpStatusToJson(json_gen_str_t * jstr, bool full_status = true);
void dumpStatusToJson(JsonDocument& json, bool full_status = true);

private:
// Camera config structure
Expand Down
Loading