added saving image snapshot to micro SD card
parent
b32f0e7a86
commit
55bdcecf84
|
|
@ -123,6 +123,7 @@ void setup() {
|
||||||
xTaskCreatePinnedToCore(System_TaskStreamTelemetry, "PrintStreamTelemetry", 3300, NULL, 6, &Task_StreamTelemetry, 0); /*function, description, stack size, parameters, priority, task handle, core*/
|
xTaskCreatePinnedToCore(System_TaskStreamTelemetry, "PrintStreamTelemetry", 3300, NULL, 6, &Task_StreamTelemetry, 0); /*function, description, stack size, parameters, priority, task handle, core*/
|
||||||
xTaskCreatePinnedToCore(System_TaskSysLed, "SystemLed", 3000, NULL, 7, &Task_SysLed, 0); /*function, description, stack size, parameters, priority, task handle, core*/
|
xTaskCreatePinnedToCore(System_TaskSysLed, "SystemLed", 3000, NULL, 7, &Task_SysLed, 0); /*function, description, stack size, parameters, priority, task handle, core*/
|
||||||
xTaskCreatePinnedToCore(System_TaskWiFiWatchdog, "WiFiWatchdog", 3500, NULL, 8, &Task_WiFiWatchdog, 0); /*function, description, stack size, parameters, priority, task handle, core*/
|
xTaskCreatePinnedToCore(System_TaskWiFiWatchdog, "WiFiWatchdog", 3500, NULL, 8, &Task_WiFiWatchdog, 0); /*function, description, stack size, parameters, priority, task handle, core*/
|
||||||
|
//xTaskCreatePinnedToCore(System_TaskSdCardRemove, "SdCardRemove", 3000, NULL, 9, &Task_SdCardFileRemove, 0); /*function, description, stack size, parameters, priority, task handle, core*/
|
||||||
|
|
||||||
/* init wdg */
|
/* init wdg */
|
||||||
SystemLog.AddEvent(LogLevel_Info, F("Init WDG"));
|
SystemLog.AddEvent(LogLevel_Info, F("Init WDG"));
|
||||||
|
|
@ -136,6 +137,7 @@ void setup() {
|
||||||
esp_task_wdt_add(Task_StreamTelemetry);
|
esp_task_wdt_add(Task_StreamTelemetry);
|
||||||
esp_task_wdt_add(Task_SysLed);
|
esp_task_wdt_add(Task_SysLed);
|
||||||
esp_task_wdt_add(Task_WiFiWatchdog);
|
esp_task_wdt_add(Task_WiFiWatchdog);
|
||||||
|
//esp_task_wdt_add(Task_SdCardFileRemove);
|
||||||
esp_task_wdt_reset(); /* reset wdg */
|
esp_task_wdt_reset(); /* reset wdg */
|
||||||
|
|
||||||
SystemLog.AddEvent(LogLevel_Info, F("MCU configuration done"));
|
SystemLog.AddEvent(LogLevel_Info, F("MCU configuration done"));
|
||||||
|
|
|
||||||
|
|
@ -14,13 +14,13 @@
|
||||||
#ifndef _WEB_PAGE_H_
|
#ifndef _WEB_PAGE_H_
|
||||||
#define _WEB_PAGE_H_
|
#define _WEB_PAGE_H_
|
||||||
|
|
||||||
#define MSG_REBOOT_MCU "Reboot process started, wait several seconds for mcu to boot up. You can close this window now."
|
#define MSG_REBOOT_MCU "Reboot process started, wait several seconds for mcu to boot up. You can close this window now"
|
||||||
#define MSG_SAVE_OK_REBOOT "Save OK. Please reboot MCU" ///< WEB app msg save OK
|
#define MSG_SAVE_OK_REBOOT "Save OK. Please reboot MCU" ///< WEB app msg save OK
|
||||||
#define MSG_SAVE_OK_WIFI "Save OK. Connecting to Wi-Fi. Please wait several second."
|
#define MSG_SAVE_OK_WIFI "Save OK. Connecting to Wi-Fi. Please wait several second"
|
||||||
#define MSG_SAVE_OK "Save cfg OK" ///< WEB app msg save OK
|
#define MSG_SAVE_OK "Save cfg OK" ///< WEB app msg save OK
|
||||||
#define MSG_SAVE_NOTOK "Save cfg NOT OK!" ///< WEB app msg save NOT OK
|
#define MSG_SAVE_NOTOK "Save cfg NOT OK!" ///< WEB app msg save NOT OK
|
||||||
#define MSG_SCANNING "Scanning Wi-Fi networks. Wait 8s..." ///< WEB app msg Scanning wifi
|
#define MSG_SCANNING "Scanning Wi-Fi networks. Wait 8s..." ///< WEB app msg Scanning wifi
|
||||||
#define MSG_UPDATE_START "Start updating."
|
#define MSG_UPDATE_START "Start updating"
|
||||||
|
|
||||||
/* ------------------------------------------------------------------------------------------------------------ */
|
/* ------------------------------------------------------------------------------------------------------------ */
|
||||||
const char index_html[] PROGMEM = R"rawliteral(
|
const char index_html[] PROGMEM = R"rawliteral(
|
||||||
|
|
@ -40,7 +40,6 @@ const char index_html[] PROGMEM = R"rawliteral(
|
||||||
$("#content").load(page);
|
$("#content").load(page);
|
||||||
setActive(this);
|
setActive(this);
|
||||||
});
|
});
|
||||||
|
|
||||||
$("#content").load("page_config.html", function() {
|
$("#content").load("page_config.html", function() {
|
||||||
var defaultLink = document.querySelector('a[href="page_config.html"]');
|
var defaultLink = document.querySelector('a[href="page_config.html"]');
|
||||||
setActive(defaultLink);
|
setActive(defaultLink);
|
||||||
|
|
@ -48,7 +47,6 @@ const char index_html[] PROGMEM = R"rawliteral(
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
<nav>
|
<nav>
|
||||||
<img src="esp32_cam.svg" id=logo alt="Logo image" style="margin-left: 10px;" />
|
<img src="esp32_cam.svg" id=logo alt="Logo image" style="margin-left: 10px;" />
|
||||||
|
|
@ -62,7 +60,6 @@ const char index_html[] PROGMEM = R"rawliteral(
|
||||||
</ul>
|
</ul>
|
||||||
</nav>
|
</nav>
|
||||||
<hr>
|
<hr>
|
||||||
|
|
||||||
<section class="container">
|
<section class="container">
|
||||||
<div class="container_left-half">
|
<div class="container_left-half">
|
||||||
<article>
|
<article>
|
||||||
|
|
@ -78,23 +75,20 @@ const char index_html[] PROGMEM = R"rawliteral(
|
||||||
</article>
|
</article>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
<br>
|
<br>
|
||||||
<cfg>
|
<div id="cfg">
|
||||||
<cfg_bar>
|
<div id="cfg_bar">
|
||||||
<div id="links">
|
<div id="links">
|
||||||
<li ><a href="page_config.html">Camera configuration</a></li>
|
<li><a href="page_config.html">Camera configuration</a></li>
|
||||||
<li ><a href="page_wifi.html">Wi-Fi configuration</a></li>
|
<li><a href="page_wifi.html">Wi-Fi configuration</a></li>
|
||||||
<li ><a href="page_auth.html">Authentication</a></li>
|
<li><a href="page_auth.html">Authentication</a></li>
|
||||||
<li ><a href="page_system.html">System</a></li>
|
<li><a href="page_system.html">System</a></li>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</cfg_bar>
|
|
||||||
</cfg>
|
|
||||||
<hr>
|
<hr>
|
||||||
|
|
||||||
<div id="content">
|
<div id="content">
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<br><br><br><br>
|
<br><br><br><br>
|
||||||
<table id=botton><tr>
|
<table id=botton><tr>
|
||||||
<td><p class=p2>Prusa Connect ESP32 cam</p> </td>
|
<td><p class=p2>Prusa Connect ESP32 cam</p> </td>
|
||||||
|
|
@ -103,7 +97,6 @@ const char index_html[] PROGMEM = R"rawliteral(
|
||||||
<td><a href="https://github.com/Prusa-Development/Prusa-Firmware-ESP32-Cam/" id="github-link"><svg height="25"><image href="github-icon.svg"></svg></a></td>
|
<td><a href="https://github.com/Prusa-Development/Prusa-Firmware-ESP32-Cam/" id="github-link"><svg height="25"><image href="github-icon.svg"></svg></a></td>
|
||||||
</tr></table>
|
</tr></table>
|
||||||
</body>
|
</body>
|
||||||
|
|
||||||
<script src="scripts.js"></script>
|
<script src="scripts.js"></script>
|
||||||
<script>
|
<script>
|
||||||
sliderCheck();
|
sliderCheck();
|
||||||
|
|
@ -118,7 +111,6 @@ const char index_html[] PROGMEM = R"rawliteral(
|
||||||
const char page_auth_html[] PROGMEM = R"rawliteral(
|
const char page_auth_html[] PROGMEM = R"rawliteral(
|
||||||
<style>@import url("styles.css");</style>
|
<style>@import url("styles.css");</style>
|
||||||
<script src="jquery-3.7.0.min.js"></script>
|
<script src="jquery-3.7.0.min.js"></script>
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
<center>
|
<center>
|
||||||
<table>
|
<table>
|
||||||
|
|
@ -131,7 +123,6 @@ const char page_auth_html[] PROGMEM = R"rawliteral(
|
||||||
</table>
|
</table>
|
||||||
</center>
|
</center>
|
||||||
</body>
|
</body>
|
||||||
|
|
||||||
<script src="scripts.js"></script>
|
<script src="scripts.js"></script>
|
||||||
<script>
|
<script>
|
||||||
get_data("auth");
|
get_data("auth");
|
||||||
|
|
@ -145,7 +136,6 @@ const char page_auth_html[] PROGMEM = R"rawliteral(
|
||||||
const char page_wifi_html[] PROGMEM = R"rawliteral(
|
const char page_wifi_html[] PROGMEM = R"rawliteral(
|
||||||
<style>@import url("styles.css");</style>
|
<style>@import url("styles.css");</style>
|
||||||
<script src="jquery-3.7.0.min.js"></script>
|
<script src="jquery-3.7.0.min.js"></script>
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
<table id="center_tb">
|
<table id="center_tb">
|
||||||
<tr><td></td><td style="width:40%">
|
<tr><td></td><td style="width:40%">
|
||||||
|
|
@ -156,12 +146,10 @@ const char page_wifi_html[] PROGMEM = R"rawliteral(
|
||||||
<p class="w2">IP Address: <span id="ip"></span></p>
|
<p class="w2">IP Address: <span id="ip"></span></p>
|
||||||
<p class="w2">mDNS: http://<span id="mdns"></span>.local</p>
|
<p class="w2">mDNS: http://<span id="mdns"></span>.local</p>
|
||||||
</td><td></td></tr>
|
</td><td></td></tr>
|
||||||
|
|
||||||
<tr><td></td><td style="width:40%">
|
<tr><td></td><td style="width:40%">
|
||||||
<br>
|
<br>
|
||||||
<p class="w1">Available networks</p>
|
<p class="w1">Available networks</p>
|
||||||
</td><td></td></tr>
|
</td><td></td></tr>
|
||||||
|
|
||||||
<tr><td></td><td style="width:40%">
|
<tr><td></td><td style="width:40%">
|
||||||
<table id="wifi_ntw">
|
<table id="wifi_ntw">
|
||||||
<colgroup>
|
<colgroup>
|
||||||
|
|
@ -178,12 +166,10 @@ const char page_wifi_html[] PROGMEM = R"rawliteral(
|
||||||
</tr>
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
</td><td></td></tr>
|
</td><td></td></tr>
|
||||||
|
|
||||||
<tr><td></td><td style="width:40%" align="right">
|
<tr><td></td><td style="width:40%" align="right">
|
||||||
<button class="btn" onclick="scanWifi()">Scan Wi-Fi networks</button>
|
<button class="btn" onclick="scanWifi()">Scan Wi-Fi networks</button>
|
||||||
<br>
|
<br>
|
||||||
</td><td></td></tr>
|
</td><td></td></tr>
|
||||||
|
|
||||||
<tr><td></td><td style="width:40%">
|
<tr><td></td><td style="width:40%">
|
||||||
<br>
|
<br>
|
||||||
<table>
|
<table>
|
||||||
|
|
@ -193,9 +179,7 @@ const char page_wifi_html[] PROGMEM = R"rawliteral(
|
||||||
<tr><td></td><td align="center"><button class="btn_save_w" onclick="setWifi(document.getElementById('wifi_ssid_id').value, document.getElementById('wifi_pass_id').value)">Save & Connect</button></td></tr>
|
<tr><td></td><td align="center"><button class="btn_save_w" onclick="setWifi(document.getElementById('wifi_ssid_id').value, document.getElementById('wifi_pass_id').value)">Save & Connect</button></td></tr>
|
||||||
</table>
|
</table>
|
||||||
</td><td></td></tr>
|
</td><td></td></tr>
|
||||||
|
|
||||||
</table>
|
</table>
|
||||||
|
|
||||||
<br>
|
<br>
|
||||||
<center>
|
<center>
|
||||||
<button class="btn_collapsible_wifi">Advanced Wi-Fi settings</button>
|
<button class="btn_collapsible_wifi">Advanced Wi-Fi settings</button>
|
||||||
|
|
@ -219,9 +203,7 @@ const char page_wifi_html[] PROGMEM = R"rawliteral(
|
||||||
<tr><td></td><td align="center"><button class="btn_save_w" onclick="setWifiNet(document.getElementById('net_ip_id').value, document.getElementById('net_mask_id').value, document.getElementById('net_gw_id').value, document.getElementById('net_dns_id').value)">Save</button></td></tr>
|
<tr><td></td><td align="center"><button class="btn_save_w" onclick="setWifiNet(document.getElementById('net_ip_id').value, document.getElementById('net_mask_id').value, document.getElementById('net_gw_id').value, document.getElementById('net_dns_id').value)">Save</button></td></tr>
|
||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</body>
|
</body>
|
||||||
|
|
||||||
<script src="scripts.js"></script>
|
<script src="scripts.js"></script>
|
||||||
<script>
|
<script>
|
||||||
setTimeout(function(){GetDataAndPrintTableWiFi();}, 500);
|
setTimeout(function(){GetDataAndPrintTableWiFi();}, 500);
|
||||||
|
|
@ -236,7 +218,7 @@ const char page_config_html[] PROGMEM = R"rawliteral(
|
||||||
<script src="jquery-3.7.0.min.js"></script>
|
<script src="jquery-3.7.0.min.js"></script>
|
||||||
<body>
|
<body>
|
||||||
<center><table id="data">
|
<center><table id="data">
|
||||||
<tr><td class="ps3">Basic image settings</td><td></td></tr>
|
<tr><td class="ps3">Basic settings</td><td></td></tr>
|
||||||
<tr><td class="pc1">Connect Token</td><td ><input type="text" name="token" id=tokenid > <button class="btn_save" onclick="changeValue(encodeURIComponent(document.getElementById('tokenid').value), 'set_token?token=', 'config')">Save</button></td></tr>
|
<tr><td class="pc1">Connect Token</td><td ><input type="text" name="token" id=tokenid > <button class="btn_save" onclick="changeValue(encodeURIComponent(document.getElementById('tokenid').value), 'set_token?token=', 'config')">Save</button></td></tr>
|
||||||
<tr><td class="pc1">Fingerprint</td><td class=pc2 id="fingerprint"></td></tr>
|
<tr><td class="pc1">Fingerprint</td><td class=pc2 id="fingerprint"></td></tr>
|
||||||
<tr><td class="pc1">Trigger Interval [s]</td><td ><input type="text" name="refresh" id=refreshid > <button class="btn_save" onclick="changeValue(document.getElementById('refreshid').value, 'set_int?refresh=', 'config')">Save</button></td></tr>
|
<tr><td class="pc1">Trigger Interval [s]</td><td ><input type="text" name="refresh" id=refreshid > <button class="btn_save" onclick="changeValue(document.getElementById('refreshid').value, 'set_int?refresh=', 'config')">Save</button></td></tr>
|
||||||
|
|
@ -261,7 +243,7 @@ const char page_config_html[] PROGMEM = R"rawliteral(
|
||||||
<tr><td class="pc1">Saturation</td><td class="pc2">Low <input type="range" class="slider" name="saturation" id=saturationid min="-2" max="2" step="1" onchange="changeValue(this.value, 'set_int?saturation=', 'config')"> High</td></tr>
|
<tr><td class="pc1">Saturation</td><td class="pc2">Low <input type="range" class="slider" name="saturation" id=saturationid min="-2" max="2" step="1" onchange="changeValue(this.value, 'set_int?saturation=', 'config')"> High</td></tr>
|
||||||
<tr><td style="height: 1px;"></td><td style="height: 1px;"></td></tr>
|
<tr><td style="height: 1px;"></td><td style="height: 1px;"></td></tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td class="pc1">Image rotation</td><td><label for="image_rotation"></label>
|
<td class="pc1">Image Rotation</td><td><label for="image_rotation"></label>
|
||||||
<select class="select" id="image_rotationid" name="image_rotation" onchange="changeValue(this.value, 'set_int?image_rotation=', 'config')">
|
<select class="select" id="image_rotationid" name="image_rotation" onchange="changeValue(this.value, 'set_int?image_rotation=', 'config')">
|
||||||
<option value="1">0°</option>
|
<option value="1">0°</option>
|
||||||
<option value="6">90°</option>
|
<option value="6">90°</option>
|
||||||
|
|
@ -278,13 +260,14 @@ const char page_config_html[] PROGMEM = R"rawliteral(
|
||||||
<tr><td class="pc1">Flash duration</td><td class="pc2">Low <input type="range" class="slider" name="flash_time" id=flash_timeid min="50" max="1500" step="50" onchange="changeValue(this.value, 'set_int?flash_time=', 'config')">High</td></tr>
|
<tr><td class="pc1">Flash duration</td><td class="pc2">Low <input type="range" class="slider" name="flash_time" id=flash_timeid min="50" max="1500" step="50" onchange="changeValue(this.value, 'set_int?flash_time=', 'config')">High</td></tr>
|
||||||
<tr><td class="pc1">Flash duration</td><td class="pc2"><span id="flash_time_value"></span> ms</td></tr>
|
<tr><td class="pc1">Flash duration</td><td class="pc2"><span id="flash_time_value"></span> ms</td></tr>
|
||||||
<tr><td style="height: 1px;"></td><td style="height: 1px;"></td></tr>
|
<tr><td style="height: 1px;"></td><td style="height: 1px;"></td></tr>
|
||||||
|
<tr><td class="pc1">Save images to micro SD</td><td class="pc2"><label class="switch"><input type="checkbox" name="timelaps" id=timelapsid onchange="changeValue(this.checked, 'set_bool?timelaps_enable=', 'config')"><span class="checkbox_slider round"></span></label> <span id="status_timelaps"></span></td></tr>
|
||||||
|
<tr><td style="height: 1px;"></td><td style="height: 1px;"></td></tr>
|
||||||
</table></center>
|
</table></center>
|
||||||
|
<center><button class="btn_collapsible">Advanced settings</button></center>
|
||||||
<center><button class="btn_collapsible">Advanced image settings</button></center>
|
|
||||||
<div class="content">
|
<div class="content">
|
||||||
<center><table id="data">
|
<center><table id="data">
|
||||||
<tr><td style="height: 1px;"></td><td style="height: 1px;"></td></tr>
|
<tr><td style="height: 1px;"></td><td style="height: 1px;"></td></tr>
|
||||||
<tr><td class="ps3">Advanced image settings</td><td></td></tr>
|
<tr><td class="ps3">Advanced settings</td><td></td></tr>
|
||||||
<tr><td class="pc1">Automatic white balancing</td><td class="pc2"><label class="switch"><input type="checkbox" name="awb" id=awbid onchange="changeValue(this.checked, 'set_bool?awb=', 'config')"><span class="checkbox_slider round"></span></label> <span id="status_awb"></span></td></tr>
|
<tr><td class="pc1">Automatic white balancing</td><td class="pc2"><label class="switch"><input type="checkbox" name="awb" id=awbid onchange="changeValue(this.checked, 'set_bool?awb=', 'config')"><span class="checkbox_slider round"></span></label> <span id="status_awb"></span></td></tr>
|
||||||
<tr><td class="pc1">Automatic white balancing gain</td><td class="pc2"><label class="switch"><input type="checkbox" name="awb_gain" id=awb_gainid onchange="changeValue(this.checked, 'set_bool?awb_gain=', 'config')"><span class="checkbox_slider round"></span></label> <span id="status_awb_gain"></span></td></tr>
|
<tr><td class="pc1">Automatic white balancing gain</td><td class="pc2"><label class="switch"><input type="checkbox" name="awb_gain" id=awb_gainid onchange="changeValue(this.checked, 'set_bool?awb_gain=', 'config')"><span class="checkbox_slider round"></span></label> <span id="status_awb_gain"></span></td></tr>
|
||||||
<tr>
|
<tr>
|
||||||
|
|
@ -315,7 +298,6 @@ const char page_config_html[] PROGMEM = R"rawliteral(
|
||||||
</table></center>
|
</table></center>
|
||||||
</div>
|
</div>
|
||||||
</body>
|
</body>
|
||||||
|
|
||||||
<script src="scripts.js"></script>
|
<script src="scripts.js"></script>
|
||||||
<script>
|
<script>
|
||||||
get_data("config");
|
get_data("config");
|
||||||
|
|
@ -331,16 +313,18 @@ const char page_system_html[] PROGMEM = R"rawliteral(
|
||||||
<center>
|
<center>
|
||||||
<table id="data">
|
<table id="data">
|
||||||
<tr><td class="ps3">System status</td><td></td></tr>
|
<tr><td class="ps3">System status</td><td></td></tr>
|
||||||
<tr><td class="ps1">PrusaConnect Status</td><td class="ps2" id="last_upload_status"></td></tr>
|
<tr><td class="ps1">Prusa Connect Status</td><td class="ps2" id="last_upload_status"></td></tr>
|
||||||
<tr><td class="ps1">Wi-Fi mode</td><td class="ps2" id="wifi_mode"></td></tr>
|
<tr><td class="ps1">Wi-Fi mode</td><td class="ps2" id="wifi_mode"></td></tr>
|
||||||
<tr><td class="ps1">Wi-Fi service AP SSID</td><td class="ps2" id="service_ap_ssid"></td></tr>
|
<tr><td class="ps1">Wi-Fi service AP SSID</td><td class="ps2" id="service_ap_ssid"></td></tr>
|
||||||
<tr><td class="ps1">Uptime</td><td class="ps2" id="uptime"></td></tr>
|
<tr><td class="ps1">Uptime</td><td class="ps2" id="uptime"></td></tr>
|
||||||
<tr><td class="ps1">Software version</td><td class="ps2" id="sw_ver"></td></tr>
|
<tr><td style="height: 1px;"></td><td style="height: 1px;"></td></tr>
|
||||||
<tr><td class="ps1">Software build</td><td class="ps2" id="sw_build"></td></tr>
|
<tr><td class="ps3">Firmware</td><td></td></tr>
|
||||||
<tr><td class="ps1">Available software update</td><td class="ps2"><span id="sw_new_ver"></span> <span class="underlined-text" onclick="checkUpdate()">Check update from cloud</span></td></tr>
|
<tr><td class="ps1">Version</td><td class="ps2" id="sw_ver"></td></tr>
|
||||||
|
<tr><td class="ps1">Build</td><td class="ps2" id="sw_build"></td></tr>
|
||||||
|
<tr><td class="ps1">Available update</td><td class="ps2"><span id="sw_new_ver"></span> <span class="underlined-text" onclick="checkUpdate()">Check update from cloud</span></td></tr>
|
||||||
<tr><td style="height: 1px;"></td><td style="height: 1px;"></td></tr>
|
<tr><td style="height: 1px;"></td><td style="height: 1px;"></td></tr>
|
||||||
<tr><td class="ps3">System configuration</td><td></td></tr>
|
<tr><td class="ps3">System configuration</td><td></td></tr>
|
||||||
<tr><td class="pc1">Cam name & mDNS record</td><td ><input type="text" name="mdns" id=mdnsid ><span class=pc1>.local</span> <button class="btn_save" onclick="changeValue(document.getElementById('mdnsid').value, 'set_mdns?mdns=', 'system')">Save</button></td></tr>
|
<tr><td class="pc1">Camera name & mDNS record</td><td ><input type="text" name="mdns" id=mdnsid ><span class=pc1>.local</span> <button class="btn_save" onclick="changeValue(document.getElementById('mdnsid').value, 'set_mdns?mdns=', 'system')">Save</button></td></tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td class="pc1">Log level</td><td><label for="loglevel"></label>
|
<td class="pc1">Log level</td><td><label for="loglevel"></label>
|
||||||
<select class="select" id="loglevelid" name="loglevel" onchange="changeValue(this.value, 'set_int?log_level=', 'system')">
|
<select class="select" id="loglevelid" name="loglevel" onchange="changeValue(this.value, 'set_int?log_level=', 'system')">
|
||||||
|
|
@ -352,21 +336,26 @@ const char page_system_html[] PROGMEM = R"rawliteral(
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr><td class="pc1">Get logs</td><td ><button class="btn_update" onclick="window.open('get_logs')">Get logs</button></td></tr>
|
<tr><td class="pc1">Get logs</td><td ><button class="btn_update" onclick="window.open('get_logs')">Get logs</button></td></tr>
|
||||||
|
<tr><td style="height: 1px;"></td><td style="height: 1px;"></td></tr>
|
||||||
|
<tr><td class="ps3">Micro SD card</td><td></td></tr>
|
||||||
|
<tr><td class="ps1">Card status</td><td class="ps2" id="sd_status"></td></tr>
|
||||||
|
<tr><td class="ps1">Capacity</td><td class="ps2"><span id="sd_total"></span> MB</td></tr>
|
||||||
|
<tr><td class="ps1">Available</td><td class="ps2"><div class="progress-container"><div class="progress-bar" id="progress_bar_sd_free">0%</div></div></td></tr>
|
||||||
|
<tr><td class="ps1">Used</td><td class="ps2"><div class="progress-container"><div class="progress-bar" id="progress_bar_sd_used">0%</div></div></td></tr>
|
||||||
</table>
|
</table>
|
||||||
</center>
|
</center>
|
||||||
<br>
|
<br>
|
||||||
<center>
|
<center>
|
||||||
<table id="update">
|
<table id="update">
|
||||||
<tr><td class="ps3">Firmware update</td><td></td></tr>
|
<tr><td class="ps3">Firmware update</td><td></td></tr>
|
||||||
<tr><td class="ps1">Status:</td><td><span class="ps2" id="status">Ready</span></td></tr>
|
<tr><td class="ps1">Status</td><td><span class="ps2" id="status">Ready</span></td></tr>
|
||||||
<tr><td class="ps1">Processing:</td><td class="ps2"><div class="progress-container"><div class="progress-bar" id="myProgressBar">0%</div></div><!--<span class="ps2" id="progressValue">0</span>%--></td></tr>
|
<tr><td class="ps1">Progress</td><td class="ps2"><div class="progress-container"><div class="progress-bar" id="myProgressBar">0%</div></div></td></tr>
|
||||||
<tr><td></td><td style="width:50%"><input type="file" id="firmwareInput" accept=".bin"></td></tr>
|
<tr><td></td><td><input type="file" id="firmwareInput" accept=".bin"></td></tr>
|
||||||
<tr><td></td><td><input type="submit" class="btn_update" value="Update from file" onclick="uploadFile()"></td></tr>
|
<tr><td></td><td><input type="submit" class="btn_update" value="Update from file" onclick="uploadFile()"></td></tr>
|
||||||
<tr><td></td><td><input type="submit" class="btn_update" value="Update from cloud" onclick="updateWeb()"></td></tr>
|
<tr><td></td><td><input type="submit" class="btn_update" value="Update from cloud" onclick="updateWeb()"></td></tr>
|
||||||
</table>
|
</table>
|
||||||
</center>
|
</center>
|
||||||
</body>
|
</body>
|
||||||
|
|
||||||
<script src="scripts.js"></script>
|
<script src="scripts.js"></script>
|
||||||
<script>
|
<script>
|
||||||
var updateCompleted = false;
|
var updateCompleted = false;
|
||||||
|
|
@ -380,14 +369,13 @@ const char styles_css[] PROGMEM = R"rawliteral(
|
||||||
body {
|
body {
|
||||||
font-family: sans-serif;
|
font-family: sans-serif;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* index styles */
|
/* index styles */
|
||||||
.p1 {
|
.p1 {
|
||||||
color: #797979;
|
color: #797979;
|
||||||
font: normal normal normal 18px/5px sans-serif;
|
font: normal normal normal 18px/5px sans-serif;
|
||||||
letter-spacing: 0px;
|
letter-spacing: 0px;
|
||||||
}
|
}
|
||||||
.p2 {
|
.p2 {
|
||||||
text-align: left;
|
text-align: left;
|
||||||
font: normal normal bold 14px/20px sans-serif;
|
font: normal normal bold 14px/20px sans-serif;
|
||||||
letter-spacing: 0px;
|
letter-spacing: 0px;
|
||||||
|
|
@ -395,7 +383,7 @@ body {
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
}
|
}
|
||||||
.p3 {
|
.p3 {
|
||||||
text-align: left;
|
text-align: left;
|
||||||
font: normal normal normal 14px/20px sans-serif;
|
font: normal normal normal 14px/20px sans-serif;
|
||||||
letter-spacing: 0px;
|
letter-spacing: 0px;
|
||||||
|
|
@ -403,14 +391,14 @@ body {
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
}
|
}
|
||||||
.p4 {
|
.p4 {
|
||||||
text-align: left;
|
text-align: left;
|
||||||
font: normal normal normal 14px/20px sans-serif;
|
font: normal normal normal 14px/20px sans-serif;
|
||||||
letter-spacing: 0px;
|
letter-spacing: 0px;
|
||||||
color: #808080;
|
color: #808080;
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
}
|
}
|
||||||
.p5 {
|
.p5 {
|
||||||
text-align: center;
|
text-align: center;
|
||||||
font: normal normal bold 14px/20px sans-serif;
|
font: normal normal bold 14px/20px sans-serif;
|
||||||
letter-spacing: 0px;
|
letter-spacing: 0px;
|
||||||
|
|
@ -418,38 +406,38 @@ body {
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
}
|
}
|
||||||
/* NAVIGATION BAR */
|
/* NAVIGATION BAR */
|
||||||
nav {
|
nav {
|
||||||
display: flex;
|
display: flex;
|
||||||
background-color: transparent;
|
background-color: transparent;
|
||||||
}
|
}
|
||||||
.top_bar {
|
.top_bar {
|
||||||
display: flex;
|
display: flex;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
.top_bar li {
|
.top_bar li {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
padding: 5px;
|
padding: 5px;
|
||||||
}
|
}
|
||||||
.top_bar li a {
|
.top_bar li a {
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
}
|
}
|
||||||
.top_bar li a:hover {
|
.top_bar li a:hover {
|
||||||
text-decoration: underline #fa6831;
|
text-decoration: underline #fa6831;
|
||||||
text-underline-position: under;
|
text-underline-position: under;
|
||||||
text-underline-offset: 8px;
|
text-underline-offset: 8px;
|
||||||
text-decoration-thickness: 2px;
|
text-decoration-thickness: 2px;
|
||||||
}
|
}
|
||||||
#links li a.active {
|
#links li a.active {
|
||||||
text-decoration: underline #fa6831;
|
text-decoration: underline #fa6831;
|
||||||
text-underline-position: under;
|
text-underline-position: under;
|
||||||
text-underline-offset: 8px;
|
text-underline-offset: 8px;
|
||||||
text-decoration-thickness: 2px;
|
text-decoration-thickness: 2px;
|
||||||
}
|
}
|
||||||
/* CFG BAR */
|
/* CFG BAR */
|
||||||
cfg {
|
#cfg {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
|
|
@ -458,18 +446,18 @@ cfg {
|
||||||
color: #2A2A2A;
|
color: #2A2A2A;
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
}
|
}
|
||||||
cfg_bar li {
|
#cfg_bar li {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
padding: 14px;
|
padding: 14px;
|
||||||
font-size: 16px;
|
font-size: 16px;
|
||||||
left: 50%;
|
left: 50%;
|
||||||
}
|
}
|
||||||
cfg_bar li a {
|
#cfg_bar li a {
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
color: #212529;
|
color: #212529;
|
||||||
}
|
}
|
||||||
cfg_bar li a:hover {
|
#cfg_bar li a:hover {
|
||||||
color: #fa6831;
|
color: #fa6831;
|
||||||
}
|
}
|
||||||
/* CONTAINER */
|
/* CONTAINER */
|
||||||
|
|
@ -478,33 +466,33 @@ cfg_bar li a:hover {
|
||||||
height: 100%;
|
height: 100%;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
.container_left-half {
|
.container_left-half {
|
||||||
grid-column: 1;
|
grid-column: 1;
|
||||||
display: table-cell;
|
display: table-cell;
|
||||||
vertical-align: middle;
|
vertical-align: middle;
|
||||||
width: 50%;
|
width: 50%;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
}
|
}
|
||||||
.container_right-half {
|
.container_right-half {
|
||||||
grid-column: 2;
|
grid-column: 2;
|
||||||
display: table-cell;
|
display: table-cell;
|
||||||
vertical-align: middle;
|
vertical-align: middle;
|
||||||
width: 50%;
|
width: 50%;
|
||||||
}
|
}
|
||||||
/* CHECKBOX SLIDER */
|
/* CHECKBOX SLIDER */
|
||||||
.switch {
|
.switch {
|
||||||
position: relative;
|
position: relative;
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
width: 30px;
|
width: 30px;
|
||||||
height: 17px;
|
height: 17px;
|
||||||
vertical-align: middle;
|
vertical-align: middle;
|
||||||
}
|
}
|
||||||
.switch input {
|
.switch input {
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
width: 0;
|
width: 0;
|
||||||
height: 0;
|
height: 0;
|
||||||
}
|
}
|
||||||
.checkbox_slider {
|
.checkbox_slider {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
top: 0;
|
top: 0;
|
||||||
|
|
@ -515,7 +503,7 @@ cfg_bar li a:hover {
|
||||||
-webkit-transition: .4s;
|
-webkit-transition: .4s;
|
||||||
transition: .4s;
|
transition: .4s;
|
||||||
}
|
}
|
||||||
.checkbox_slider:before {
|
.checkbox_slider:before {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
content: "";
|
content: "";
|
||||||
height: 13px;
|
height: 13px;
|
||||||
|
|
@ -526,25 +514,25 @@ cfg_bar li a:hover {
|
||||||
-webkit-transition: .4s;
|
-webkit-transition: .4s;
|
||||||
transition: .4s;
|
transition: .4s;
|
||||||
}
|
}
|
||||||
input:checked+.checkbox_slider {
|
input:checked+.checkbox_slider {
|
||||||
background-color: #797979;
|
background-color: #797979;
|
||||||
}
|
}
|
||||||
input:focus+.checkbox_slider {
|
input:focus+.checkbox_slider {
|
||||||
box-shadow: 0 0 1px #797979;
|
box-shadow: 0 0 1px #797979;
|
||||||
}
|
}
|
||||||
input:checked+.checkbox_slider:before {
|
input:checked+.checkbox_slider:before {
|
||||||
-webkit-transform: translateX(13px);
|
-webkit-transform: translateX(13px);
|
||||||
-ms-transform: translateX(13px);
|
-ms-transform: translateX(13px);
|
||||||
transform: translateX(13px);
|
transform: translateX(13px);
|
||||||
}
|
}
|
||||||
.checkbox_slider.round {
|
.checkbox_slider.round {
|
||||||
border-radius: 13px;
|
border-radius: 13px;
|
||||||
}
|
}
|
||||||
.checkbox_slider.round:before {
|
.checkbox_slider.round:before {
|
||||||
border-radius: 50%;
|
border-radius: 50%;
|
||||||
}
|
}
|
||||||
/* BUTTON */
|
/* BUTTON */
|
||||||
.btn {
|
.btn {
|
||||||
width: 306px;
|
width: 306px;
|
||||||
height: 30px;
|
height: 30px;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
|
|
@ -554,12 +542,12 @@ cfg_bar li a:hover {
|
||||||
border-radius: 5px;
|
border-radius: 5px;
|
||||||
border: 1px solid #343a40;
|
border: 1px solid #343a40;
|
||||||
}
|
}
|
||||||
.btn:hover {
|
.btn:hover {
|
||||||
background-color: #FA6831;
|
background-color: #FA6831;
|
||||||
color: white;
|
color: white;
|
||||||
}
|
}
|
||||||
/* BOTTON table */
|
/* BOTTON table */
|
||||||
#botton {
|
#botton {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
background: #F5F5F5 0% 0% no-repeat padding-box;
|
background: #F5F5F5 0% 0% no-repeat padding-box;
|
||||||
|
|
@ -567,21 +555,21 @@ cfg_bar li a:hover {
|
||||||
bottom: 0;
|
bottom: 0;
|
||||||
}
|
}
|
||||||
/* ----- styles config ----- */
|
/* ----- styles config ----- */
|
||||||
.pc1 {
|
.pc1 {
|
||||||
text-align: right;
|
text-align: right;
|
||||||
font: normal normal normal 11px/5px sans-serif;
|
font: normal normal normal 11px/5px sans-serif;
|
||||||
letter-spacing: 0px;
|
letter-spacing: 0px;
|
||||||
color: #797979;
|
color: #797979;
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
}
|
}
|
||||||
.pc2 {
|
.pc2 {
|
||||||
text-align: left;
|
text-align: left;
|
||||||
font: normal normal normal 12px/5px sans-serif;
|
font: normal normal normal 12px/5px sans-serif;
|
||||||
letter-spacing: 0px;
|
letter-spacing: 0px;
|
||||||
color: #000000;
|
color: #000000;
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
}
|
}
|
||||||
.pc3 {
|
.pc3 {
|
||||||
text-align: right;
|
text-align: right;
|
||||||
font: normal normal normal bold 12px/17px sans-serif;
|
font: normal normal normal bold 12px/17px sans-serif;
|
||||||
letter-spacing: 0px;
|
letter-spacing: 0px;
|
||||||
|
|
@ -589,22 +577,22 @@ cfg_bar li a:hover {
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
}
|
}
|
||||||
/* data table */
|
/* data table */
|
||||||
#data {
|
#data {
|
||||||
font-family: Arial, Helvetica, sans-serif;
|
font-family: Arial, Helvetica, sans-serif;
|
||||||
border-collapse: collapse;
|
border-collapse: collapse;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
table-layout: fixed;
|
table-layout: fixed;
|
||||||
}
|
}
|
||||||
#data td, #data th {
|
#data td, #data th {
|
||||||
padding: 8px;
|
padding: 8px;
|
||||||
}
|
}
|
||||||
#data th {
|
#data th {
|
||||||
padding-top: 12px;
|
padding-top: 12px;
|
||||||
padding-bottom: 12px;
|
padding-bottom: 12px;
|
||||||
text-align: left;
|
text-align: left;
|
||||||
}
|
}
|
||||||
/* BUTTON */
|
/* BUTTON */
|
||||||
.btn_save {
|
.btn_save {
|
||||||
width: 69px;
|
width: 69px;
|
||||||
height: 24px;
|
height: 24px;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
|
|
@ -614,12 +602,12 @@ cfg_bar li a:hover {
|
||||||
border-radius: 5px;
|
border-radius: 5px;
|
||||||
border: 1px solid #343a40;
|
border: 1px solid #343a40;
|
||||||
}
|
}
|
||||||
.btn_save:hover {
|
.btn_save:hover {
|
||||||
background-color: #FA6831;
|
background-color: #FA6831;
|
||||||
color: white;
|
color: white;
|
||||||
}
|
}
|
||||||
/* RANGE */
|
/* RANGE */
|
||||||
.slider {
|
.slider {
|
||||||
-webkit-appearance: none;
|
-webkit-appearance: none;
|
||||||
width: 133px;
|
width: 133px;
|
||||||
height: 10px;
|
height: 10px;
|
||||||
|
|
@ -627,7 +615,7 @@ cfg_bar li a:hover {
|
||||||
background: linear-gradient(to right, #d3d3d3 50%, #FA6831 50%);
|
background: linear-gradient(to right, #d3d3d3 50%, #FA6831 50%);
|
||||||
outline: none;
|
outline: none;
|
||||||
}
|
}
|
||||||
.slider::-webkit-slider-thumb {
|
.slider::-webkit-slider-thumb {
|
||||||
-webkit-appearance: none;
|
-webkit-appearance: none;
|
||||||
appearance: none;
|
appearance: none;
|
||||||
width: 16px;
|
width: 16px;
|
||||||
|
|
@ -636,7 +624,7 @@ cfg_bar li a:hover {
|
||||||
background: #FA6831;
|
background: #FA6831;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
.slider::-moz-range-thumb {
|
.slider::-moz-range-thumb {
|
||||||
width: 16px;
|
width: 16px;
|
||||||
height: 16px;
|
height: 16px;
|
||||||
border-radius: 50%;
|
border-radius: 50%;
|
||||||
|
|
@ -644,23 +632,23 @@ cfg_bar li a:hover {
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
/* ----- styles wifi ----- */
|
/* ----- styles wifi ----- */
|
||||||
.w1 {
|
.w1 {
|
||||||
text-align: left;
|
text-align: left;
|
||||||
font: normal normal bold 12px/17px sans-serif;
|
font: normal normal bold 12px/17px sans-serif;
|
||||||
letter-spacing: 0px;
|
letter-spacing: 0px;
|
||||||
color: #2A2A2A;
|
color: #2A2A2A;
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
}
|
}
|
||||||
.w2 {
|
.w2 {
|
||||||
font: normal normal normal 11px/5px sans-serif;
|
font: normal normal normal 11px/5px sans-serif;
|
||||||
letter-spacing: 0px;
|
letter-spacing: 0px;
|
||||||
color: #797979;
|
color: #797979;
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
}
|
}
|
||||||
.w2 span {
|
.w2 span {
|
||||||
vertical-align: middle;
|
vertical-align: middle;
|
||||||
}
|
}
|
||||||
#center_tb {
|
#center_tb {
|
||||||
border-collapse: collapse;
|
border-collapse: collapse;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
table-layout: fixed;
|
table-layout: fixed;
|
||||||
|
|
@ -670,24 +658,24 @@ cfg_bar li a:hover {
|
||||||
margin-left: 30%;
|
margin-left: 30%;
|
||||||
}
|
}
|
||||||
/* wifi_ntw table */
|
/* wifi_ntw table */
|
||||||
#wifi_ntw {
|
#wifi_ntw {
|
||||||
font: normal normal normal 12px/5px sans-serif;
|
font: normal normal normal 12px/5px sans-serif;
|
||||||
border-collapse: collapse;
|
border-collapse: collapse;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
table-layout: fixed;
|
table-layout: fixed;
|
||||||
text-align: left;
|
text-align: left;
|
||||||
}
|
}
|
||||||
#wifi_ntw td {
|
#wifi_ntw td {
|
||||||
border-bottom: 1px solid #ddd;
|
border-bottom: 1px solid #ddd;
|
||||||
padding: 8px;
|
padding: 8px;
|
||||||
}
|
}
|
||||||
#wifi_ntw tr:nth-child(even) {
|
#wifi_ntw tr:nth-child(even) {
|
||||||
background: #F8F8F8 0% 0% no-repeat padding-box;
|
background: #F8F8F8 0% 0% no-repeat padding-box;
|
||||||
}
|
}
|
||||||
#wifi_ntw tr:hover {
|
#wifi_ntw tr:hover {
|
||||||
background-color: #ddd;
|
background-color: #ddd;
|
||||||
}
|
}
|
||||||
#wifi_ntw th {
|
#wifi_ntw th {
|
||||||
background-color: transparent;
|
background-color: transparent;
|
||||||
text-align: left;
|
text-align: left;
|
||||||
font: normal normal bold 13px/11px sans-serif;
|
font: normal normal bold 13px/11px sans-serif;
|
||||||
|
|
@ -695,15 +683,15 @@ cfg_bar li a:hover {
|
||||||
color: #2A2A2A;
|
color: #2A2A2A;
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
}
|
}
|
||||||
#wifi_ntw tr {
|
#wifi_ntw tr {
|
||||||
border-bottom: 1px solid #ccc;
|
border-bottom: 1px solid #ccc;
|
||||||
}
|
}
|
||||||
#wifi_ntw img {
|
#wifi_ntw img {
|
||||||
width: 19px;
|
width: 19px;
|
||||||
height: 12px;
|
height: 12px;
|
||||||
}
|
}
|
||||||
/* BUTTON */
|
/* BUTTON */
|
||||||
.btn_save_w {
|
.btn_save_w {
|
||||||
width: 178px;
|
width: 178px;
|
||||||
height: 24px;
|
height: 24px;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
|
|
@ -713,19 +701,19 @@ cfg_bar li a:hover {
|
||||||
border-radius: 5px;
|
border-radius: 5px;
|
||||||
border: 1px solid #343a40;
|
border: 1px solid #343a40;
|
||||||
}
|
}
|
||||||
.btn_save_w:hover {
|
.btn_save_w:hover {
|
||||||
background-color: #FA6831;
|
background-color: #FA6831;
|
||||||
color: white;
|
color: white;
|
||||||
}
|
}
|
||||||
/* ----- styles auth ----- */
|
/* ----- styles auth ----- */
|
||||||
.pa1 {
|
.pa1 {
|
||||||
text-align: right;
|
text-align: right;
|
||||||
font: normal normal normal 11px/5px sans-serif;
|
font: normal normal normal 11px/5px sans-serif;
|
||||||
letter-spacing: 0px;
|
letter-spacing: 0px;
|
||||||
color: #797979;
|
color: #797979;
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
}
|
}
|
||||||
.pa2 {
|
.pa2 {
|
||||||
text-align: left;
|
text-align: left;
|
||||||
font: normal normal bold 12px/17px sans-serif;
|
font: normal normal bold 12px/17px sans-serif;
|
||||||
letter-spacing: 0px;
|
letter-spacing: 0px;
|
||||||
|
|
@ -739,9 +727,8 @@ cfg_bar li a:hover {
|
||||||
color: #2A2A2A;
|
color: #2A2A2A;
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* BUTTON */
|
/* BUTTON */
|
||||||
.btn_save_a {
|
.btn_save_a {
|
||||||
width: 178px;
|
width: 178px;
|
||||||
height: 24px;
|
height: 24px;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
|
|
@ -751,39 +738,39 @@ cfg_bar li a:hover {
|
||||||
border-radius: 5px;
|
border-radius: 5px;
|
||||||
border: 1px solid #343a40;
|
border: 1px solid #343a40;
|
||||||
}
|
}
|
||||||
.btn_save_a:hover {
|
.btn_save_a:hover {
|
||||||
background-color: #FA6831;
|
background-color: #FA6831;
|
||||||
color: white;
|
color: white;
|
||||||
}
|
}
|
||||||
.toggle-password {
|
.toggle-password {
|
||||||
position: relative;
|
position: relative;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
.toggle-password img {
|
.toggle-password img {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 50%;
|
top: 50%;
|
||||||
right: 0;
|
right: 0;
|
||||||
transform: translateY(-50%);
|
transform: translateY(-50%);
|
||||||
}
|
}
|
||||||
.password-container {
|
.password-container {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
}
|
}
|
||||||
#auth_password.reveal {
|
#auth_password.reveal {
|
||||||
-webkit-text-security: none;
|
-webkit-text-security: none;
|
||||||
}
|
}
|
||||||
#auth_password {
|
#auth_password {
|
||||||
-webkit-text-security: disc;
|
-webkit-text-security: disc;
|
||||||
}
|
}
|
||||||
/* ----- styles system ----- */
|
/* ----- styles system ----- */
|
||||||
.ps1 {
|
.ps1 {
|
||||||
text-align: right;
|
text-align: right;
|
||||||
font: normal normal normal 11px/5px sans-serif;
|
font: normal normal normal 11px/5px sans-serif;
|
||||||
letter-spacing: 0px;
|
letter-spacing: 0px;
|
||||||
color: #797979;
|
color: #797979;
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
}
|
}
|
||||||
.ps2 {
|
.ps2 {
|
||||||
text-align: left;
|
text-align: left;
|
||||||
font: normal normal normal 12px/5px sans-serif;
|
font: normal normal normal 12px/5px sans-serif;
|
||||||
letter-spacing: 0px;
|
letter-spacing: 0px;
|
||||||
|
|
@ -797,38 +784,23 @@ cfg_bar li a:hover {
|
||||||
color: #2A2A2A;
|
color: #2A2A2A;
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
}
|
}
|
||||||
/* data table */
|
|
||||||
#data {
|
|
||||||
font-family: Arial, Helvetica, sans-serif;
|
|
||||||
border-collapse: collapse;
|
|
||||||
width: 100%;
|
|
||||||
table-layout: fixed;
|
|
||||||
}
|
|
||||||
#data td, #data th {
|
|
||||||
padding: 8px;
|
|
||||||
}
|
|
||||||
#data th {
|
|
||||||
padding-top: 12px;
|
|
||||||
padding-bottom: 12px;
|
|
||||||
text-align: left;
|
|
||||||
}
|
|
||||||
/* update table */
|
/* update table */
|
||||||
update {
|
#update {
|
||||||
font-family: Arial, Helvetica, sans-serif;
|
font-family: Arial, Helvetica, sans-serif;
|
||||||
border-collapse: collapse;
|
border-collapse: collapse;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
table-layout: fixed;
|
table-layout: fixed;
|
||||||
}
|
}
|
||||||
#update td, #update th {
|
#update td, #update th {
|
||||||
padding: 8px;
|
padding: 8px;
|
||||||
}
|
}
|
||||||
#update th {
|
#update th {
|
||||||
padding-top: 12px;
|
padding-top: 12px;
|
||||||
padding-bottom: 12px;
|
padding-bottom: 12px;
|
||||||
text-align: left;
|
text-align: left;
|
||||||
}
|
}
|
||||||
/* BUTTON */
|
/* BUTTON */
|
||||||
.btn_update {
|
.btn_update {
|
||||||
width: 178px;
|
width: 178px;
|
||||||
height: 24px;
|
height: 24px;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
|
|
@ -838,34 +810,33 @@ cfg_bar li a:hover {
|
||||||
border-radius: 5px;
|
border-radius: 5px;
|
||||||
border: 1px solid #343a40;
|
border: 1px solid #343a40;
|
||||||
}
|
}
|
||||||
.btn_update:hover {
|
.btn_update:hover {
|
||||||
background-color: #FA6831;
|
background-color: #FA6831;
|
||||||
color: white;
|
color: white;
|
||||||
}
|
}
|
||||||
.underlined-text {
|
.underlined-text {
|
||||||
text-decoration: underline;
|
text-decoration: underline;
|
||||||
color: blue;
|
color: blue;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
/* progress bar*/
|
/* progress bar*/
|
||||||
.progress-container {
|
.progress-container {
|
||||||
width: 100%;
|
width: 30%;
|
||||||
background-color: #ccc;
|
background-color: #ccc;
|
||||||
}
|
}
|
||||||
.progress-bar {
|
.progress-bar {
|
||||||
width: 0px;
|
width: 0px;
|
||||||
height: 15px;
|
height: 15px;
|
||||||
background-color: #FA6831;
|
background-color: #FA6831;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
line-height: 15px;
|
line-height: 15px;
|
||||||
color: white;
|
color: white;
|
||||||
|
padding-left: 3px;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* advanced cam cfg */
|
/* advanced cam cfg */
|
||||||
.content {
|
.content {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.btn_collapsible {
|
.btn_collapsible {
|
||||||
width: 300px;
|
width: 300px;
|
||||||
height: 24px;
|
height: 24px;
|
||||||
|
|
@ -880,12 +851,10 @@ cfg_bar li a:hover {
|
||||||
background-color: #FA6831;
|
background-color: #FA6831;
|
||||||
color: white;
|
color: white;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* advanced wifi cfg */
|
/* advanced wifi cfg */
|
||||||
.content_wifi {
|
.content_wifi {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.btn_collapsible_wifi {
|
.btn_collapsible_wifi {
|
||||||
width: 300px;
|
width: 300px;
|
||||||
height: 24px;
|
height: 24px;
|
||||||
|
|
@ -952,6 +921,7 @@ function get_data(val) {
|
||||||
document.getElementById('agc_gainid').value = obj.agc_gain;
|
document.getElementById('agc_gainid').value = obj.agc_gain;
|
||||||
document.getElementById("flash_time_value").innerText = obj.flash_time;
|
document.getElementById("flash_time_value").innerText = obj.flash_time;
|
||||||
document.getElementById("aec_value_value").innerText = obj.aec_value;
|
document.getElementById("aec_value_value").innerText = obj.aec_value;
|
||||||
|
document.getElementById('timelapsid').checked = obj.timelaps;
|
||||||
$("#status_hmirror").text((obj.hmirror == "true") ? "On" : "Off");
|
$("#status_hmirror").text((obj.hmirror == "true") ? "On" : "Off");
|
||||||
$("#status_vflip").text((obj.vflip == "true") ? "On" : "Off");
|
$("#status_vflip").text((obj.vflip == "true") ? "On" : "Off");
|
||||||
$("#status_lensc").text((obj.lensc == "true") ? "On" : "Off");
|
$("#status_lensc").text((obj.lensc == "true") ? "On" : "Off");
|
||||||
|
|
@ -965,6 +935,7 @@ function get_data(val) {
|
||||||
$("#status_raw_gama").text((obj.raw_gama == "true") ? "On" : "Off");
|
$("#status_raw_gama").text((obj.raw_gama == "true") ? "On" : "Off");
|
||||||
$("#status_aec2").text((obj.aec2 == "true") ? "On" : "Off");
|
$("#status_aec2").text((obj.aec2 == "true") ? "On" : "Off");
|
||||||
$("#status_gain_ctrl").text((obj.gain_ctrl == "true") ? "On" : "Off");
|
$("#status_gain_ctrl").text((obj.gain_ctrl == "true") ? "On" : "Off");
|
||||||
|
$("#status_timelaps").text((obj.timelaps == "true") ? "On" : "Off");
|
||||||
sliderCheck();
|
sliderCheck();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1006,6 +977,19 @@ function get_data(val) {
|
||||||
$("#wifi_mode").text(obj.wifi_mode);
|
$("#wifi_mode").text(obj.wifi_mode);
|
||||||
$("#sw_new_ver").text(obj.sw_new_ver);
|
$("#sw_new_ver").text(obj.sw_new_ver);
|
||||||
$("#service_ap_ssid").text(obj.service_ap_ssid);
|
$("#service_ap_ssid").text(obj.service_ap_ssid);
|
||||||
|
$("#sd_status").text(obj.sd_status);
|
||||||
|
$("#sd_total").text(obj.sd_total);
|
||||||
|
$("#sd_free_p").text(obj.sd_free_p);
|
||||||
|
$("#sd_used_p").text(obj.sd_used_p);
|
||||||
|
|
||||||
|
var sd_free_prog = document.getElementById("progress_bar_sd_free");
|
||||||
|
sd_free_prog.style.width = obj.sd_free_p + "%";
|
||||||
|
sd_free_prog.innerHTML = obj.sd_free_p + "%";
|
||||||
|
|
||||||
|
var sd_free_prog = document.getElementById("progress_bar_sd_used");
|
||||||
|
sd_free_prog.style.width = obj.sd_used_p + "%";
|
||||||
|
sd_free_prog.innerHTML = obj.sd_used_p + "%";
|
||||||
|
|
||||||
document.getElementById('mdnsid').value = obj.mdns;
|
document.getElementById('mdnsid').value = obj.mdns;
|
||||||
document.getElementById('loglevelid').value = obj.log_level;
|
document.getElementById('loglevelid').value = obj.log_level;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -30,6 +30,7 @@ Camera::Camera(Configuration* i_conf, Logs* i_log, uint8_t i_FlashPin) {
|
||||||
PhotoExifData.header = NULL;
|
PhotoExifData.header = NULL;
|
||||||
PhotoExifData.len = 0;
|
PhotoExifData.len = 0;
|
||||||
PhotoExifData.offset = 0;
|
PhotoExifData.offset = 0;
|
||||||
|
PhotoSending = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -185,6 +186,10 @@ framesize_t Camera::TransformFrameSizeDataType(uint8_t i_data) {
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Camera::SetPhotoSending(bool i_data) {
|
||||||
|
PhotoSending = i_data;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@brief Function set flash status
|
@brief Function set flash status
|
||||||
@param bool i_data - true = on, false = off
|
@param bool i_data - true = on, false = off
|
||||||
|
|
@ -268,6 +273,11 @@ void Camera::ReinitCameraModule() {
|
||||||
@return none
|
@return none
|
||||||
*/
|
*/
|
||||||
void Camera::CapturePhoto() {
|
void Camera::CapturePhoto() {
|
||||||
|
|
||||||
|
if (true == PhotoSending) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (false == StreamOnOff) {
|
if (false == StreamOnOff) {
|
||||||
if (!xSemaphoreTake(frameBufferSemaphore, portMAX_DELAY)) {
|
if (!xSemaphoreTake(frameBufferSemaphore, portMAX_DELAY)) {
|
||||||
log->AddEvent(LogLevel_Error, F("Failed to take frame buffer semaphore"));
|
log->AddEvent(LogLevel_Error, F("Failed to take frame buffer semaphore"));
|
||||||
|
|
@ -313,13 +323,21 @@ void Camera::CapturePhoto() {
|
||||||
if (ControlFlag != 0x00) {
|
if (ControlFlag != 0x00) {
|
||||||
log->AddEvent(LogLevel_Error, "Camera capture failed! photo " + String(ControlFlag, HEX));
|
log->AddEvent(LogLevel_Error, "Camera capture failed! photo " + String(ControlFlag, HEX));
|
||||||
FrameBuffer->len = 0;
|
FrameBuffer->len = 0;
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
log->AddEvent(LogLevel_Info, "Photo OK! " + String(ControlFlag, HEX));
|
log->AddEvent(LogLevel_Info, "Photo OK! " + String(ControlFlag, HEX));
|
||||||
|
|
||||||
|
/* generate exif header */
|
||||||
update_exif_from_cfg(imageExifRotation);
|
update_exif_from_cfg(imageExifRotation);
|
||||||
get_exif_header(FrameBuffer, &PhotoExifData.header, &PhotoExifData.len);
|
get_exif_header(FrameBuffer, &PhotoExifData.header, &PhotoExifData.len);
|
||||||
PhotoExifData.offset = get_jpeg_data_offset(FrameBuffer);
|
PhotoExifData.offset = get_jpeg_data_offset(FrameBuffer);
|
||||||
CameraCaptureSuccess = true;
|
CameraCaptureSuccess = true;
|
||||||
|
|
||||||
|
if (PhotoExifData.header != NULL) {
|
||||||
|
log->AddEvent(LogLevel_Info, "Exif header OK! Len: " + String(PhotoExifData.len));
|
||||||
|
} else {
|
||||||
|
log->AddEvent(LogLevel_Error, "Exif header failed! " + String(PhotoExifData.len));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
attempts++;
|
attempts++;
|
||||||
|
|
@ -335,33 +353,6 @@ void Camera::CapturePhoto() {
|
||||||
ledcWrite(FLASH_PWM_CHANNEL, FLASH_OFF_STATUS);
|
ledcWrite(FLASH_PWM_CHANNEL, FLASH_OFF_STATUS);
|
||||||
}
|
}
|
||||||
xSemaphoreGive(frameBufferSemaphore);
|
xSemaphoreGive(frameBufferSemaphore);
|
||||||
/*
|
|
||||||
// Save picture
|
|
||||||
File file = SD_MMC.open("/photo.jpg", FILE_WRITE);
|
|
||||||
|
|
||||||
if (file) {
|
|
||||||
size_t ret = 0;
|
|
||||||
if (PhotoExifData.header != NULL) {
|
|
||||||
ret = file.write(PhotoExifData.header, PhotoExifData.len);
|
|
||||||
if (ret != PhotoExifData.len) {
|
|
||||||
Serial.println("Failed\nError while writing header to file");
|
|
||||||
PhotoExifData.offset = 0;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
PhotoExifData.offset = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
ret = file.write(&FrameBuffer->buf[PhotoExifData.offset], FrameBuffer->len - PhotoExifData.offset);
|
|
||||||
if (ret != FrameBuffer->len - PhotoExifData.offset) {
|
|
||||||
Serial.println("Failed\nError while writing to file");
|
|
||||||
} else {
|
|
||||||
Serial.printf("Saved as %s\n", "photo.jpg");
|
|
||||||
}
|
|
||||||
file.close();
|
|
||||||
} else {
|
|
||||||
Serial.printf("Failed\nCould not open file: %s\n", "photo.jpg");
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -64,6 +64,7 @@ private:
|
||||||
uint8_t imageExifRotation; ///< image rotation. 0 degree: value 1, 90 degree: value 6, 180 degree: value 3, 270 degree: value 8
|
uint8_t imageExifRotation; ///< image rotation. 0 degree: value 1, 90 degree: value 6, 180 degree: value 3, 270 degree: value 8
|
||||||
|
|
||||||
bool CameraCaptureSuccess; ///< camera capture success
|
bool CameraCaptureSuccess; ///< camera capture success
|
||||||
|
bool PhotoSending; ///< photo sending
|
||||||
|
|
||||||
/* OV2640 camera module pinout and cfg*/
|
/* OV2640 camera module pinout and cfg*/
|
||||||
camera_config_t CameraConfig; ///< camera configuration
|
camera_config_t CameraConfig; ///< camera configuration
|
||||||
|
|
@ -109,6 +110,7 @@ public:
|
||||||
camera_fb_t *GetPhotoFb();
|
camera_fb_t *GetPhotoFb();
|
||||||
PhotoExifData_t * GetPhotoExifData();
|
PhotoExifData_t * GetPhotoExifData();
|
||||||
framesize_t TransformFrameSizeDataType(uint8_t);
|
framesize_t TransformFrameSizeDataType(uint8_t);
|
||||||
|
void SetPhotoSending(bool);
|
||||||
|
|
||||||
void SetFlashStatus(bool);
|
void SetFlashStatus(bool);
|
||||||
bool GetFlashStatus();
|
bool GetFlashStatus();
|
||||||
|
|
|
||||||
|
|
@ -83,6 +83,13 @@ void Configuration::ReadCfg() {
|
||||||
LoadGainCtrl();
|
LoadGainCtrl();
|
||||||
LoadAgcGain();
|
LoadAgcGain();
|
||||||
LoadPrusaConnectHostname();
|
LoadPrusaConnectHostname();
|
||||||
|
LoadNetworkIpMethod();
|
||||||
|
LoadNetworkIp();
|
||||||
|
LoadNetworkMask();
|
||||||
|
LoadNetworkGateway();
|
||||||
|
LoadNetworkDns();
|
||||||
|
LoadCameraImageExifRotation();
|
||||||
|
LoadTimeLapseFunctionStatus();
|
||||||
Log->AddEvent(LogLevel_Info, "Active WiFi client cfg: " + String(CheckActifeWifiCfgFlag() ? "true" : "false"));
|
Log->AddEvent(LogLevel_Info, "Active WiFi client cfg: " + String(CheckActifeWifiCfgFlag() ? "true" : "false"));
|
||||||
Log->AddEvent(LogLevel_Info, F("Load CFG from EEPROM done"));
|
Log->AddEvent(LogLevel_Info, F("Load CFG from EEPROM done"));
|
||||||
}
|
}
|
||||||
|
|
@ -167,6 +174,7 @@ void Configuration::DefaultCfg() {
|
||||||
SaveNetworkGateway(FACTORY_CFG_NETWORK_STATIC_GATEWAY);
|
SaveNetworkGateway(FACTORY_CFG_NETWORK_STATIC_GATEWAY);
|
||||||
SaveNetworkDns(FACTORY_CFG_NETWORK_STATIC_DNS);
|
SaveNetworkDns(FACTORY_CFG_NETWORK_STATIC_DNS);
|
||||||
SaveCameraImageExifRotation(FACTORY_CFG_IMAGE_EXIF_ROTATION);
|
SaveCameraImageExifRotation(FACTORY_CFG_IMAGE_EXIF_ROTATION);
|
||||||
|
SaveTimeLapseFunctionStatus(FACTORY_CFG_TIMELAPS_ENABLE);
|
||||||
Log->AddEvent(LogLevel_Warning, F("+++++++++++++++++++++++++++"));
|
Log->AddEvent(LogLevel_Warning, F("+++++++++++++++++++++++++++"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -651,7 +659,6 @@ void Configuration::SaveBasicAuthUsername(String i_data) {
|
||||||
SaveString(EEPROM_ADDR_BASIC_AUTH_USERNAME_START, EEPROM_ADDR_BASIC_AUTH_USERNAME_LENGTH, i_data);
|
SaveString(EEPROM_ADDR_BASIC_AUTH_USERNAME_START, EEPROM_ADDR_BASIC_AUTH_USERNAME_LENGTH, i_data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@info save password fof BasicAuth to EEPROM
|
@info save password fof BasicAuth to EEPROM
|
||||||
@param string - password
|
@param string - password
|
||||||
|
|
@ -834,6 +841,16 @@ void Configuration::SaveCameraImageExifRotation(uint8_t i_data) {
|
||||||
SaveUint8(EEPROM_ADDR_IMAGE_ROTATION_START, i_data);
|
SaveUint8(EEPROM_ADDR_IMAGE_ROTATION_START, i_data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
@info Save time lapse function status
|
||||||
|
@param bool - value
|
||||||
|
@return none
|
||||||
|
*/
|
||||||
|
void Configuration::SaveTimeLapseFunctionStatus(bool i_data) {
|
||||||
|
Log->AddEvent(LogLevel_Verbose, "Save time lapse function status: " + String(i_data));
|
||||||
|
SaveBool(EEPROM_ADDR_TIMELAPS_ENABLE_START, i_data);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@info load refresh interval from eeprom
|
@info load refresh interval from eeprom
|
||||||
@param none
|
@param none
|
||||||
|
|
@ -1311,6 +1328,11 @@ String Configuration::LoadNetworkDns() {
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Load camera image rotation from EEPROM
|
||||||
|
*
|
||||||
|
* @return uint8_t - rotation
|
||||||
|
*/
|
||||||
uint8_t Configuration::LoadCameraImageExifRotation() {
|
uint8_t Configuration::LoadCameraImageExifRotation() {
|
||||||
uint8_t ret = EEPROM.read(EEPROM_ADDR_IMAGE_ROTATION_START);
|
uint8_t ret = EEPROM.read(EEPROM_ADDR_IMAGE_ROTATION_START);
|
||||||
|
|
||||||
|
|
@ -1324,4 +1346,20 @@ uint8_t Configuration::LoadCameraImageExifRotation() {
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Load time lapse function status
|
||||||
|
*
|
||||||
|
* @return bool - status
|
||||||
|
*/
|
||||||
|
bool Configuration::LoadTimeLapseFunctionStatus() {
|
||||||
|
uint8_t ret = EEPROM.read(EEPROM_ADDR_TIMELAPS_ENABLE_START);
|
||||||
|
Log->AddEvent(LogLevel_Info, F("Time lapse function status: "), String(ret));
|
||||||
|
|
||||||
|
if (ret == 255) {
|
||||||
|
ret = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (bool) ret;
|
||||||
|
}
|
||||||
|
|
||||||
/* EOF */
|
/* EOF */
|
||||||
|
|
@ -25,7 +25,7 @@
|
||||||
|
|
||||||
class Configuration {
|
class Configuration {
|
||||||
public:
|
public:
|
||||||
Configuration(Logs*);
|
Configuration(Logs *);
|
||||||
~Configuration(){};
|
~Configuration(){};
|
||||||
void Init();
|
void Init();
|
||||||
bool CheckActifeWifiCfgFlag();
|
bool CheckActifeWifiCfgFlag();
|
||||||
|
|
@ -72,6 +72,7 @@ public:
|
||||||
void SaveNetworkGateway(String);
|
void SaveNetworkGateway(String);
|
||||||
void SaveNetworkDns(String);
|
void SaveNetworkDns(String);
|
||||||
void SaveCameraImageExifRotation(uint8_t);
|
void SaveCameraImageExifRotation(uint8_t);
|
||||||
|
void SaveTimeLapseFunctionStatus(bool);
|
||||||
|
|
||||||
uint8_t LoadRefreshInterval();
|
uint8_t LoadRefreshInterval();
|
||||||
String LoadToken();
|
String LoadToken();
|
||||||
|
|
@ -113,6 +114,7 @@ public:
|
||||||
String LoadNetworkGateway();
|
String LoadNetworkGateway();
|
||||||
String LoadNetworkDns();
|
String LoadNetworkDns();
|
||||||
uint8_t LoadCameraImageExifRotation();
|
uint8_t LoadCameraImageExifRotation();
|
||||||
|
bool LoadTimeLapseFunctionStatus();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Logs *Log; ///< Pointer to Logs object
|
Logs *Log; ///< Pointer to Logs object
|
||||||
|
|
|
||||||
|
|
@ -37,6 +37,7 @@ PrusaConnect::PrusaConnect(Configuration *i_conf, Logs *i_log, Camera *i_camera,
|
||||||
*/
|
*/
|
||||||
void PrusaConnect::Init() {
|
void PrusaConnect::Init() {
|
||||||
log->AddEvent(LogLevel_Info, F("Init PrusaConnect lib"));
|
log->AddEvent(LogLevel_Info, F("Init PrusaConnect lib"));
|
||||||
|
BackendReceivedStatus = F("Wait for first connection");
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -51,6 +52,7 @@ void PrusaConnect::LoadCfgFromEeprom() {
|
||||||
Fingerprint = config->LoadFingerprint();
|
Fingerprint = config->LoadFingerprint();
|
||||||
RefreshInterval = config->LoadRefreshInterval();
|
RefreshInterval = config->LoadRefreshInterval();
|
||||||
PrusaConnectHostname = config->LoadPrusaConnectHostname();
|
PrusaConnectHostname = config->LoadPrusaConnectHostname();
|
||||||
|
EnableTimelapsPhotoSave = config->LoadTimeLapseFunctionStatus();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -138,7 +140,7 @@ bool PrusaConnect::SendDataToBackend(String *i_data, int i_data_length, String i
|
||||||
}
|
}
|
||||||
|
|
||||||
/* sending photo */
|
/* sending photo */
|
||||||
for (size_t i=0; i < fbLen; i += PHOTO_FRAGMENT_SIZE) {
|
for (size_t i = 0; i < fbLen; i += PHOTO_FRAGMENT_SIZE) {
|
||||||
if ((i + PHOTO_FRAGMENT_SIZE) < fbLen) {
|
if ((i + PHOTO_FRAGMENT_SIZE) < fbLen) {
|
||||||
sendet_data += client.write(fbBuf, PHOTO_FRAGMENT_SIZE);
|
sendet_data += client.write(fbBuf, PHOTO_FRAGMENT_SIZE);
|
||||||
fbBuf += PHOTO_FRAGMENT_SIZE;
|
fbBuf += PHOTO_FRAGMENT_SIZE;
|
||||||
|
|
@ -171,7 +173,7 @@ bool PrusaConnect::SendDataToBackend(String *i_data, int i_data_length, String i
|
||||||
/* read response from server */
|
/* read response from server */
|
||||||
String response = "";
|
String response = "";
|
||||||
String fullResponse = "";
|
String fullResponse = "";
|
||||||
log->AddEvent(LogLevel_Verbose, "Response:");
|
log->AddEvent(LogLevel_Verbose, F("Response:"));
|
||||||
while (client.connected()) {
|
while (client.connected()) {
|
||||||
if (client.available()) {
|
if (client.available()) {
|
||||||
response = client.readStringUntil('\n');
|
response = client.readStringUntil('\n');
|
||||||
|
|
@ -219,6 +221,7 @@ bool PrusaConnect::SendDataToBackend(String *i_data, int i_data_length, String i
|
||||||
*/
|
*/
|
||||||
void PrusaConnect::SendPhotoToBackend() {
|
void PrusaConnect::SendPhotoToBackend() {
|
||||||
log->AddEvent(LogLevel_Info, F("Start sending photo to prusaconnect"));
|
log->AddEvent(LogLevel_Info, F("Start sending photo to prusaconnect"));
|
||||||
|
camera->SetPhotoSending(true);
|
||||||
String Photo = "";
|
String Photo = "";
|
||||||
size_t total_len = 0;
|
size_t total_len = 0;
|
||||||
|
|
||||||
|
|
@ -227,7 +230,8 @@ void PrusaConnect::SendPhotoToBackend() {
|
||||||
} else {
|
} else {
|
||||||
total_len = camera->GetPhotoFb()->len;
|
total_len = camera->GetPhotoFb()->len;
|
||||||
}
|
}
|
||||||
SendDataToBackend(&Photo, total_len, "image/jpg", "Photo", HOST_URL_CAM_PATH, SendPhoto);
|
SendDataToBackend(&Photo, total_len, F("image/jpg"), F("Photo"), HOST_URL_CAM_PATH, SendPhoto);
|
||||||
|
camera->SetPhotoSending(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -258,7 +262,7 @@ void PrusaConnect::SendInfoToBackend() {
|
||||||
|
|
||||||
serializeJson(json_data, json_string);
|
serializeJson(json_data, json_string);
|
||||||
log->AddEvent(LogLevel_Info, "Data: " + json_string);
|
log->AddEvent(LogLevel_Info, "Data: " + json_string);
|
||||||
bool response = SendDataToBackend(&json_string, json_string.length(), "application/json", "Info", HOST_URL_INFO_PATH, SendInfo);
|
bool response = SendDataToBackend(&json_string, json_string.length(), F("application/json"), F("Info"), HOST_URL_INFO_PATH, SendInfo);
|
||||||
|
|
||||||
if (true == response) {
|
if (true == response) {
|
||||||
SendDeviceInformationToBackend = false;
|
SendDeviceInformationToBackend = false;
|
||||||
|
|
@ -274,11 +278,22 @@ void PrusaConnect::SendInfoToBackend() {
|
||||||
*/
|
*/
|
||||||
void PrusaConnect::TakePictureAndSendToBackend() {
|
void PrusaConnect::TakePictureAndSendToBackend() {
|
||||||
camera->CapturePhoto();
|
camera->CapturePhoto();
|
||||||
|
|
||||||
|
/* check if photo was captured */
|
||||||
if (camera->GetCameraCaptureSuccess() == true) {
|
if (camera->GetCameraCaptureSuccess() == true) {
|
||||||
|
|
||||||
|
/* send photo to backend */
|
||||||
SendPhotoToBackend();
|
SendPhotoToBackend();
|
||||||
|
|
||||||
|
/* save photo to SD card */
|
||||||
|
if (false == camera->GetStreamStatus()) {
|
||||||
|
SavePhotoToSdCard();
|
||||||
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
log->AddEvent(LogLevel_Error, F("Error capturing photo. Stop sending to backend!"));
|
log->AddEvent(LogLevel_Error, F("Error capturing photo. Stop sending to backend!"));
|
||||||
}
|
}
|
||||||
|
|
||||||
camera->CaptureReturnFrameBuffer();
|
camera->CaptureReturnFrameBuffer();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -428,6 +443,51 @@ void PrusaConnect::SetPrusaConnectHostname(String i_data) {
|
||||||
config->SavePrusaConnectHostname(PrusaConnectHostname);
|
config->SavePrusaConnectHostname(PrusaConnectHostname);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Set time laps photo save status
|
||||||
|
*
|
||||||
|
* @param bool - status
|
||||||
|
*/
|
||||||
|
void PrusaConnect::SetTimeLapsPhotoSaveStatus(bool i_data) {
|
||||||
|
EnableTimelapsPhotoSave = i_data;
|
||||||
|
config->SaveTimeLapseFunctionStatus(EnableTimelapsPhotoSave);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
@brief Function for saving photo to SD card
|
||||||
|
@param none
|
||||||
|
@return none
|
||||||
|
*/
|
||||||
|
void PrusaConnect::SavePhotoToSdCard() {
|
||||||
|
if (EnableTimelapsPhotoSave == true) {
|
||||||
|
log->AddEvent(LogLevel_Info, F("Save TimeLaps photo to SD card"));
|
||||||
|
if (false == log->CheckDir(SD_MMC, TIMELAPS_PHOTO_FOLDER)) {
|
||||||
|
log->AddEvent(LogLevel_Info, F("Create folder for TimeLaps photos"));
|
||||||
|
log->CreateDir(SD_MMC, TIMELAPS_PHOTO_FOLDER);
|
||||||
|
}
|
||||||
|
|
||||||
|
String FileName = String(TIMELAPS_PHOTO_FOLDER) + "/" + String(TIMELAPS_PHOTO_PREFIX) + "_";
|
||||||
|
FileName += log->GetSystemTime();
|
||||||
|
FileName += TIMELAPS_PHOTO_SUFFIX;
|
||||||
|
log->AddEvent(LogLevel_Verbose, "Saving file: " + FileName);
|
||||||
|
|
||||||
|
if (camera->GetPhotoExifData()->header != NULL) {
|
||||||
|
if (log->WritePicture(FileName, camera->GetPhotoFb()->buf + camera->GetPhotoExifData()->offset, camera->GetPhotoFb()->len - camera->GetPhotoExifData()->offset, camera->GetPhotoExifData()->header, camera->GetPhotoExifData()->len) == true) {
|
||||||
|
log->AddEvent(LogLevel_Info, F("Photo saved to SD card. EXIF"));
|
||||||
|
} else {
|
||||||
|
log->AddEvent(LogLevel_Error, F("Error saving photo to SD card. EXIF"));
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
if (log->WritePicture(FileName, camera->GetPhotoFb()->buf, camera->GetPhotoFb()->len) == true) {
|
||||||
|
log->AddEvent(LogLevel_Info, F("Photo saved to SD card"));
|
||||||
|
} else {
|
||||||
|
log->AddEvent(LogLevel_Error, F("Error saving photo to SD card"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Get refresh interval
|
* @brief Get refresh interval
|
||||||
*
|
*
|
||||||
|
|
@ -512,6 +572,10 @@ String PrusaConnect::CovertBackendAvailabilitStatusToString(BackendAvailabilitSt
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool PrusaConnect::GetTimeLapsPhotoSaveStatus() {
|
||||||
|
return EnableTimelapsPhotoSave;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Increase sending interval counter
|
* @brief Increase sending interval counter
|
||||||
*
|
*
|
||||||
|
|
|
||||||
|
|
@ -55,6 +55,7 @@ private:
|
||||||
BackendAvailabilitStatus BackendAvailability; ///< status of backend availability
|
BackendAvailabilitStatus BackendAvailability; ///< status of backend availability
|
||||||
bool SendDeviceInformationToBackend; ///< flag for sending device information to backend
|
bool SendDeviceInformationToBackend; ///< flag for sending device information to backend
|
||||||
uint8_t SendingIntervalCounter; ///< counter for sending interval, represents seconds
|
uint8_t SendingIntervalCounter; ///< counter for sending interval, represents seconds
|
||||||
|
bool EnableTimelapsPhotoSave; ///< flag for saving photo to SD card
|
||||||
|
|
||||||
String Token; ///< token for backend communication
|
String Token; ///< token for backend communication
|
||||||
String Fingerprint; ///< fingerprint for backend communication
|
String Fingerprint; ///< fingerprint for backend communication
|
||||||
|
|
@ -86,6 +87,9 @@ public:
|
||||||
void SetToken(String);
|
void SetToken(String);
|
||||||
void SetBackendAvailabilitStatus(BackendAvailabilitStatus);
|
void SetBackendAvailabilitStatus(BackendAvailabilitStatus);
|
||||||
void SetPrusaConnectHostname(String);
|
void SetPrusaConnectHostname(String);
|
||||||
|
void SetTimeLapsPhotoSaveStatus(bool);
|
||||||
|
|
||||||
|
void SavePhotoToSdCard();
|
||||||
|
|
||||||
uint8_t GetRefreshInterval();
|
uint8_t GetRefreshInterval();
|
||||||
String GetBackendReceivedStatus();
|
String GetBackendReceivedStatus();
|
||||||
|
|
@ -94,6 +98,7 @@ public:
|
||||||
String GetPrusaConnectHostname();
|
String GetPrusaConnectHostname();
|
||||||
BackendAvailabilitStatus GetBackendAvailabilitStatus();
|
BackendAvailabilitStatus GetBackendAvailabilitStatus();
|
||||||
String CovertBackendAvailabilitStatusToString(BackendAvailabilitStatus);
|
String CovertBackendAvailabilitStatusToString(BackendAvailabilitStatus);
|
||||||
|
bool GetTimeLapsPhotoSaveStatus();
|
||||||
|
|
||||||
void IncreaseSendingIntervalCounter();
|
void IncreaseSendingIntervalCounter();
|
||||||
void SetSendingIntervalCounter(uint8_t);
|
void SetSendingIntervalCounter(uint8_t);
|
||||||
|
|
|
||||||
|
|
@ -101,13 +101,7 @@ void Logs::Init() {
|
||||||
|
|
||||||
if (true == GetCardDetectedStatus()) {
|
if (true == GetCardDetectedStatus()) {
|
||||||
/* check maximum log file size */
|
/* check maximum log file size */
|
||||||
uint32_t FileSize = GetFileSize(SD_MMC, FilePath + FileName);
|
CheckMaxLogFileSize();
|
||||||
Serial.printf("Log file size: %d\n", FileSize);
|
|
||||||
if (FileSize >= LOGS_FILE_MAX_SIZE) {
|
|
||||||
uint16_t file_count = FileCount(SD_MMC, FilePath, FileName);
|
|
||||||
Serial.printf("Maximum log file size.\nFile count: %d\n", file_count);
|
|
||||||
RenameFile(SD_MMC, FilePath + FileName, FilePath + FileName + String(file_count));
|
|
||||||
}
|
|
||||||
|
|
||||||
/* added first message to log file after start MCU */
|
/* added first message to log file after start MCU */
|
||||||
String msg = F("----------------------------------------------------------------\n");
|
String msg = F("----------------------------------------------------------------\n");
|
||||||
|
|
@ -169,6 +163,30 @@ void Logs::AddEvent(LogLevel_enum level, String msg, bool newLine, bool date) {
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Logs::AddEvent(LogLevel_enum level, const __FlashStringHelper *msg, String parameters, bool newLine, bool date) {
|
||||||
|
if (LogLevel >= level) {
|
||||||
|
String LogMsg = "";
|
||||||
|
|
||||||
|
if (true == date) {
|
||||||
|
LogMsg += GetSystemTime();
|
||||||
|
LogMsg += " - ";
|
||||||
|
}
|
||||||
|
LogMsg += msg;
|
||||||
|
LogMsg += parameters;
|
||||||
|
if (true == newLine) {
|
||||||
|
LogMsg += "\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
AppendFile(SD_MMC, FilePath + FileName, LogMsg);
|
||||||
|
Serial.print(LogMsg);
|
||||||
|
}
|
||||||
|
#if (true == CONSOLE_VERBOSE_DEBUG)
|
||||||
|
else {
|
||||||
|
Serial.println(msg);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@info Set file name
|
@info Set file name
|
||||||
@param String - file name
|
@param String - file name
|
||||||
|
|
@ -242,6 +260,21 @@ bool Logs::GetNtpTimeSynced() {
|
||||||
return NtpTimeSynced;
|
return NtpTimeSynced;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
@info Check maximum log file size
|
||||||
|
@param none
|
||||||
|
@return none
|
||||||
|
*/
|
||||||
|
void Logs::CheckMaxLogFileSize() {
|
||||||
|
uint32_t FileSize = GetFileSize(SD_MMC, FilePath + FileName);
|
||||||
|
Serial.printf("Log file size: %d bytes\n", FileSize);
|
||||||
|
if (FileSize >= LOGS_FILE_MAX_SIZE) {
|
||||||
|
uint16_t file_count = FileCount(SD_MMC, FilePath, FileName);
|
||||||
|
Serial.printf("Maximum log file size.\nFile count: %d\n", file_count);
|
||||||
|
RenameFile(SD_MMC, FilePath + FileName, FilePath + FileName + String(file_count));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@info Get system time
|
@info Get system time
|
||||||
@param none
|
@param none
|
||||||
|
|
|
||||||
|
|
@ -43,6 +43,7 @@ public:
|
||||||
|
|
||||||
void Init();
|
void Init();
|
||||||
void AddEvent(LogLevel_enum, String, bool = true, bool = true);
|
void AddEvent(LogLevel_enum, String, bool = true, bool = true);
|
||||||
|
void AddEvent(LogLevel_enum, const __FlashStringHelper*, String, bool = true, bool = true);
|
||||||
void SetLogLevel(LogLevel_enum);
|
void SetLogLevel(LogLevel_enum);
|
||||||
void SetFileName(String);
|
void SetFileName(String);
|
||||||
void SetFilePath(String);
|
void SetFilePath(String);
|
||||||
|
|
@ -53,8 +54,8 @@ public:
|
||||||
String GetFilePath();
|
String GetFilePath();
|
||||||
LogLevel_enum GetLogLevel();
|
LogLevel_enum GetLogLevel();
|
||||||
bool GetNtpTimeSynced();
|
bool GetNtpTimeSynced();
|
||||||
|
void CheckMaxLogFileSize();
|
||||||
|
|
||||||
protected:
|
|
||||||
String GetSystemTime();
|
String GetSystemTime();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -14,7 +14,7 @@
|
||||||
#define _MCU_CFG_H_
|
#define _MCU_CFG_H_
|
||||||
|
|
||||||
/* ---------------- BASIC MCU CFG --------------*/
|
/* ---------------- BASIC MCU CFG --------------*/
|
||||||
#define SW_VERSION "1.0.2-rc3" ///< SW version
|
#define SW_VERSION "1.0.3-rc1" ///< SW version
|
||||||
#define SW_BUILD __DATE__ " " __TIME__ ///< build number
|
#define SW_BUILD __DATE__ " " __TIME__ ///< build number
|
||||||
#define CONSOLE_VERBOSE_DEBUG false ///< enable/disable verbose debug log level for console
|
#define CONSOLE_VERBOSE_DEBUG false ///< enable/disable verbose debug log level for console
|
||||||
#define DEVICE_HOSTNAME "Prusa-ESP32cam" ///< device hostname
|
#define DEVICE_HOSTNAME "Prusa-ESP32cam" ///< device hostname
|
||||||
|
|
@ -50,12 +50,13 @@
|
||||||
#define TASK_STREAM_TELEMETRY 30000 ///< stream telemetry task interval [ms]
|
#define TASK_STREAM_TELEMETRY 30000 ///< stream telemetry task interval [ms]
|
||||||
#define TASK_WIFI_WATCHDOG 20000 ///< wifi watchdog task interval [ms]
|
#define TASK_WIFI_WATCHDOG 20000 ///< wifi watchdog task interval [ms]
|
||||||
#define TASK_PHOTO_SEND 1000 ///< photo send task interval [ms]
|
#define TASK_PHOTO_SEND 1000 ///< photo send task interval [ms]
|
||||||
|
#define TASK_SDCARD_FILE_REMOVE 30000 ///< sd card file remove task interval [ms]
|
||||||
|
|
||||||
/* --------------- WEB SERVER CFG --------------*/
|
/* --------------- WEB SERVER CFG --------------*/
|
||||||
#define WEB_SERVER_PORT 80 ///< WEB server port
|
#define WEB_SERVER_PORT 80 ///< WEB server port
|
||||||
#define SERIAL_PORT_SPEED 115200 ///< baud rate
|
#define SERIAL_PORT_SPEED 115200 ///< baud rate
|
||||||
#define WDG_TIMEOUT 40 ///< wdg timeout [second]
|
#define WDG_TIMEOUT 40 ///< wdg timeout [second]
|
||||||
#define PHOTO_FRAGMENT_SIZE 1024 ///< photo fragmentation size [bytes]
|
#define PHOTO_FRAGMENT_SIZE 2048 ///< photo fragmentation size [bytes]
|
||||||
#define LOOP_DELAY 100 ///< loop delay [ms]
|
#define LOOP_DELAY 100 ///< loop delay [ms]
|
||||||
#define WIFI_CLIENT_WAIT_CON false ///< wait for connecting to WiFi network
|
#define WIFI_CLIENT_WAIT_CON false ///< wait for connecting to WiFi network
|
||||||
#define DYNMIC_JSON_SIZE 1024 ///< maximum size for dynamic json [bytes]
|
#define DYNMIC_JSON_SIZE 1024 ///< maximum size for dynamic json [bytes]
|
||||||
|
|
@ -63,8 +64,8 @@
|
||||||
|
|
||||||
/* --------------- OTA UPDATE CFG --------------*/
|
/* --------------- OTA UPDATE CFG --------------*/
|
||||||
#define OTA_UPDATE_API_SERVER "api.github.com" ///< OTA update server URL
|
#define OTA_UPDATE_API_SERVER "api.github.com" ///< OTA update server URL
|
||||||
#define OTA_UPDATE_API_URL "/repos/prusa3d/Prusa-Firmware-ESP32-Cam/releases/latest" ///< path to file with OTA update
|
#define OTA_UPDATE_API_URL F("/repos/prusa3d/Prusa-Firmware-ESP32-Cam/releases/latest") ///< path to file with OTA update
|
||||||
#define OTA_UPDATE_FW_FILE "ESP32_PrusaConnectCam.ino.bin" ///< OTA update firmware file name
|
#define OTA_UPDATE_FW_FILE PSTR("ESP32_PrusaConnectCam.ino.bin") ///< OTA update firmware file name
|
||||||
|
|
||||||
/* ---------- RESET CFG CONFIGURATION ----------*/
|
/* ---------- RESET CFG CONFIGURATION ----------*/
|
||||||
#define CFG_RESET_PIN 12 ///< GPIO 16 is for reset CFG to default
|
#define CFG_RESET_PIN 12 ///< GPIO 16 is for reset CFG to default
|
||||||
|
|
@ -74,18 +75,19 @@
|
||||||
/* ---------------- MicroSD Logs ----------------*/
|
/* ---------------- MicroSD Logs ----------------*/
|
||||||
#define LOGS_FILE_NAME "SysLog.log" ///< syslog file name
|
#define LOGS_FILE_NAME "SysLog.log" ///< syslog file name
|
||||||
#define LOGS_FILE_PATH "/" ///< directory for log files
|
#define LOGS_FILE_PATH "/" ///< directory for log files
|
||||||
#define LOGS_FILE_MAX_SIZE 1024 ///< maximum file size in the [kb]
|
#define LOGS_FILE_MAX_SIZE 512 ///< maximum file size in the [kb]
|
||||||
|
#define FILE_REMOVE_MAX_COUNT 5 ///< maximum count for remove files from sd card
|
||||||
|
|
||||||
/* ---------------- AP MODE CFG ----------------*/
|
/* ---------------- AP MODE CFG ----------------*/
|
||||||
#define STA_AP_MODE_TIMEOUT 300000 ///< how long is AP enable after start, when is module in the STA mode [ms]
|
#define STA_AP_MODE_TIMEOUT 300000 ///< how long is AP enable after start, when is module in the STA mode [ms]
|
||||||
#define SERVICE_WIFI_SSID_UID true ///< enable/disable added UID to service SSID name
|
#define SERVICE_WIFI_SSID_UID true ///< enable/disable added UID to service SSID name
|
||||||
#define SERVICE_WIFI_SSID "ESP32_camera" ///< service WI-FI SSID name. Maximum length SERVICE_WIFI_SSID + UID = 32
|
#define SERVICE_WIFI_SSID F("ESP32_camera") ///< service WI-FI SSID name. Maximum length SERVICE_WIFI_SSID + UID = 32
|
||||||
#define SERVICE_WIFI_PASS "12345678" ///< service WI-FI password
|
#define SERVICE_WIFI_PASS F("12345678") ///< service WI-FI password
|
||||||
#define SERVICE_WIFI_CHANNEL 10 ///< service WI-FI channel
|
#define SERVICE_WIFI_CHANNEL 10 ///< service WI-FI channel
|
||||||
#define SERVICE_LOCAL_IP "192.168.0.1" ///< service WI-FI module IP address
|
#define SERVICE_LOCAL_IP F("192.168.0.1") ///< service WI-FI module IP address
|
||||||
#define SERVICE_LOCAL_GATEWAY "192.168.0.1" ///< service WI-FI module gateway
|
#define SERVICE_LOCAL_GATEWAY F("192.168.0.1") ///< service WI-FI module gateway
|
||||||
#define SERVICE_LOCAL_MASK "255.255.255.0" ///< service WI-FI module mask
|
#define SERVICE_LOCAL_MASK F("255.255.255.0") ///< service WI-FI module mask
|
||||||
#define SERVICE_LOCAL_DNS "192.168.0.1" ///< service WI-FI module DNS
|
#define SERVICE_LOCAL_DNS F("192.168.0.1") ///< service WI-FI module DNS
|
||||||
|
|
||||||
/* ----------------- IPv4 CFG -------------------*/
|
/* ----------------- IPv4 CFG -------------------*/
|
||||||
#define IPV4_ADDR_MAX_LENGTH 15 ///< maximum length for IPv4 address
|
#define IPV4_ADDR_MAX_LENGTH 15 ///< maximum length for IPv4 address
|
||||||
|
|
@ -104,6 +106,11 @@
|
||||||
#define CAMERA_MODEL "OV2640" ///< Camera model string
|
#define CAMERA_MODEL "OV2640" ///< Camera model string
|
||||||
#define CAMERA_SOFTWARE "Prusa ESP32-cam" ///< Camera software string
|
#define CAMERA_SOFTWARE "Prusa ESP32-cam" ///< Camera software string
|
||||||
|
|
||||||
|
/* ---------------- TIMELAPS CFG ----------------*/
|
||||||
|
#define TIMELAPS_PHOTO_FOLDER "/timelaps" ///< folder for timelaps photos
|
||||||
|
#define TIMELAPS_PHOTO_PREFIX "photo" ///< photo name for timelaps
|
||||||
|
#define TIMELAPS_PHOTO_SUFFIX ".jpg" ///< photo file type for timelaps
|
||||||
|
|
||||||
/* ---------------- FACTORY CFG ----------------*/
|
/* ---------------- FACTORY CFG ----------------*/
|
||||||
#define FACTORY_CFG_PHOTO_REFRESH_INTERVAL 30 ///< in the second
|
#define FACTORY_CFG_PHOTO_REFRESH_INTERVAL 30 ///< in the second
|
||||||
#define FACTORY_CFG_PHOTO_QUALITY 10 ///< 10-63, lower is better
|
#define FACTORY_CFG_PHOTO_QUALITY 10 ///< 10-63, lower is better
|
||||||
|
|
@ -121,25 +128,26 @@
|
||||||
#define FACTORY_CFG_BPC 1 ///< bad pixel detection
|
#define FACTORY_CFG_BPC 1 ///< bad pixel detection
|
||||||
#define FACTORY_CFG_WPC 1 ///< white pixel correction
|
#define FACTORY_CFG_WPC 1 ///< white pixel correction
|
||||||
#define FACTORY_CFG_RAW_GAMA 1 ///< raw gama
|
#define FACTORY_CFG_RAW_GAMA 1 ///< raw gama
|
||||||
#define FACTORY_CFG_WEB_AUTH_USERNAME "admin" ///< user name for login to WEB interface. definition WEB_ENABLE_BASIC_AUTH must be true
|
#define FACTORY_CFG_WEB_AUTH_USERNAME F("admin") ///< user name for login to WEB interface. definition WEB_ENABLE_BASIC_AUTH must be true
|
||||||
#define FACTORY_CFG_WEB_AUTH_PASSWORD "admin" ///< password for login to WEB interface. definition WEB_ENABLE_BASIC_AUTH must be true
|
#define FACTORY_CFG_WEB_AUTH_PASSWORD F("admin") ///< password for login to WEB interface. definition WEB_ENABLE_BASIC_AUTH must be true
|
||||||
#define FACTORY_CFG_WEB_AUTH_ENABLE false ///< enable web auth for login to WEB interface. definition WEB_ENABLE_BASIC_AUTH must be
|
#define FACTORY_CFG_WEB_AUTH_ENABLE false ///< enable web auth for login to WEB interface. definition WEB_ENABLE_BASIC_AUTH must be
|
||||||
#define FACTORY_CFG_CAMERA_FLASH_ENABLE false ///< enable camera flash functionality
|
#define FACTORY_CFG_CAMERA_FLASH_ENABLE false ///< enable camera flash functionality
|
||||||
#define FACTORY_CFG_CAMERA_FLASH_TIME 200 ///< time for camera flash duration time [ms]
|
#define FACTORY_CFG_CAMERA_FLASH_TIME 200 ///< time for camera flash duration time [ms]
|
||||||
#define FACTORY_CFG_MDNS_RECORD_HOST "prusa-esp32cam" ///< mdns record http://MDNS_RECORD_HOST.local
|
#define FACTORY_CFG_MDNS_RECORD_HOST F("prusa-esp32cam") ///< mdns record http://MDNS_RECORD_HOST.local
|
||||||
#define FACTORY_CFG_AEC2 0 ///< enable automatic exposition
|
#define FACTORY_CFG_AEC2 0 ///< enable automatic exposition
|
||||||
#define FACTORY_CFG_AE_LEVEL 0 ///< automatic exposition level
|
#define FACTORY_CFG_AE_LEVEL 0 ///< automatic exposition level
|
||||||
#define FACTORY_CFG_AEC_VALUE 300 ///< automatic exposition time
|
#define FACTORY_CFG_AEC_VALUE 300 ///< automatic exposition time
|
||||||
#define FACTORY_CFG_GAIN_CTRL 1 ///< enable automatic gain
|
#define FACTORY_CFG_GAIN_CTRL 1 ///< enable automatic gain
|
||||||
#define FACTORY_CFG_AGC_GAIN 0 ///< automatic gain controll gain
|
#define FACTORY_CFG_AGC_GAIN 0 ///< automatic gain controll gain
|
||||||
#define FACTORY_CFG_HOSTNAME "connect.prusa3d.com" ///< hostname for Prusa Connect
|
#define FACTORY_CFG_HOSTNAME F("connect.prusa3d.com") ///< hostname for Prusa Connect
|
||||||
#define FACTORY_CFG_ENABLE_SERVICE_AP 1 ///< enable service AP mode
|
#define FACTORY_CFG_ENABLE_SERVICE_AP 1 ///< enable service AP mode
|
||||||
#define FACTORY_CFG_NETWORK_IP_METHOD 0 ///< 0 - DHCP, 1 - Static IP
|
#define FACTORY_CFG_NETWORK_IP_METHOD 0 ///< 0 - DHCP, 1 - Static IP
|
||||||
#define FACTORY_CFG_NETWORK_STATIC_IP "255.255.255.255" ///< Static IP address
|
#define FACTORY_CFG_NETWORK_STATIC_IP F("255.255.255.255") ///< Static IP address
|
||||||
#define FACTORY_CFG_NETWORK_STATIC_MASK "255.255.255.255" ///< Static Mask
|
#define FACTORY_CFG_NETWORK_STATIC_MASK F("255.255.255.255") ///< Static Mask
|
||||||
#define FACTORY_CFG_NETWORK_STATIC_GATEWAY "255.255.255.255" ///< Static Gateway
|
#define FACTORY_CFG_NETWORK_STATIC_GATEWAY F("255.255.255.255") ///< Static Gateway
|
||||||
#define FACTORY_CFG_NETWORK_STATIC_DNS "255.255.255.255" ///< Static DNS
|
#define FACTORY_CFG_NETWORK_STATIC_DNS F("255.255.255.255") ///< Static DNS
|
||||||
#define FACTORY_CFG_IMAGE_EXIF_ROTATION 1 ///< Image rotation 1 - 0°, 6 - 90°, 3 - 180°, 8 - 270°
|
#define FACTORY_CFG_IMAGE_EXIF_ROTATION 1 ///< Image rotation 1 - 0°, 6 - 90°, 3 - 180°, 8 - 270°
|
||||||
|
#define FACTORY_CFG_TIMELAPS_ENABLE 0 ///< enable timelaps functionality
|
||||||
|
|
||||||
/* ---------------- CFG FLAGS ------------------*/
|
/* ---------------- CFG FLAGS ------------------*/
|
||||||
#define CFG_WIFI_SETTINGS_SAVED 0x0A ///< flag saved config
|
#define CFG_WIFI_SETTINGS_SAVED 0x0A ///< flag saved config
|
||||||
|
|
@ -275,6 +283,9 @@
|
||||||
#define EEPROM_ADDR_IMAGE_ROTATION_START (EEPROM_ADDR_NETWORK_STATIC_DNS_START + EEPROM_ADDR_NETWORK_STATIC_DNS_LENGTH)
|
#define EEPROM_ADDR_IMAGE_ROTATION_START (EEPROM_ADDR_NETWORK_STATIC_DNS_START + EEPROM_ADDR_NETWORK_STATIC_DNS_LENGTH)
|
||||||
#define EEPROM_ADDR_IMAGE_ROTATION_LENGTH 1
|
#define EEPROM_ADDR_IMAGE_ROTATION_LENGTH 1
|
||||||
|
|
||||||
|
#define EEPROM_ADDR_TIMELAPS_ENABLE_START (EEPROM_ADDR_IMAGE_ROTATION_START + EEPROM_ADDR_IMAGE_ROTATION_LENGTH)
|
||||||
|
#define EEPROM_ADDR_TIMELAPS_ENABLE_LENGTH 1
|
||||||
|
|
||||||
#define EEPROM_SIZE (EEPROM_ADDR_REFRESH_INTERVAL_LENGTH + EEPROM_ADDR_FINGERPRINT_LENGTH + EEPROM_ADDR_TOKEN_LENGTH + \
|
#define EEPROM_SIZE (EEPROM_ADDR_REFRESH_INTERVAL_LENGTH + EEPROM_ADDR_FINGERPRINT_LENGTH + EEPROM_ADDR_TOKEN_LENGTH + \
|
||||||
EEPROM_ADDR_FRAMESIZE_LENGTH + EEPROM_ADDR_BRIGHTNESS_LENGTH + EEPROM_ADDR_CONTRAST_LENGTH + \
|
EEPROM_ADDR_FRAMESIZE_LENGTH + EEPROM_ADDR_BRIGHTNESS_LENGTH + EEPROM_ADDR_CONTRAST_LENGTH + \
|
||||||
EEPROM_ADDR_SATURATION_LENGTH + EEPROM_ADDR_HMIRROR_LENGTH + EEPROM_ADDR_VFLIP_LENGTH + \
|
EEPROM_ADDR_SATURATION_LENGTH + EEPROM_ADDR_HMIRROR_LENGTH + EEPROM_ADDR_VFLIP_LENGTH + \
|
||||||
|
|
@ -289,7 +300,7 @@
|
||||||
EEPROM_ADDR_AEC_VALUE_LENGTH + EEPROM_ADDR_GAIN_CTRL_LENGTH + EEPROM_ADDR_AGC_GAIN_LENGTH + EEPROM_ADDR_LOG_LEVEL_LENGTH + \
|
EEPROM_ADDR_AEC_VALUE_LENGTH + EEPROM_ADDR_GAIN_CTRL_LENGTH + EEPROM_ADDR_AGC_GAIN_LENGTH + EEPROM_ADDR_LOG_LEVEL_LENGTH + \
|
||||||
EEPROM_ADDR_HOSTNAME_LENGTH + EEPROM_ADDR_SERVICE_AP_ENABLE_LENGTH + EEPROM_ADDR_NETWORK_IP_METHOD_LENGTH +\
|
EEPROM_ADDR_HOSTNAME_LENGTH + EEPROM_ADDR_SERVICE_AP_ENABLE_LENGTH + EEPROM_ADDR_NETWORK_IP_METHOD_LENGTH +\
|
||||||
EEPROM_ADDR_NETWORK_STATIC_IP_LENGTH + EEPROM_ADDR_NETWORK_STATIC_MASK_LENGTH + EEPROM_ADDR_NETWORK_STATIC_GATEWAY_LENGTH + \
|
EEPROM_ADDR_NETWORK_STATIC_IP_LENGTH + EEPROM_ADDR_NETWORK_STATIC_MASK_LENGTH + EEPROM_ADDR_NETWORK_STATIC_GATEWAY_LENGTH + \
|
||||||
EEPROM_ADDR_NETWORK_STATIC_DNS_LENGTH + EEPROM_ADDR_IMAGE_ROTATION_LENGTH) ///< how many bits do we need for eeprom memory
|
EEPROM_ADDR_NETWORK_STATIC_DNS_LENGTH + EEPROM_ADDR_IMAGE_ROTATION_LENGTH + EEPROM_ADDR_TIMELAPS_ENABLE_LENGTH) ///< how many bits do we need for eeprom memory
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -18,7 +18,6 @@
|
||||||
*/
|
*/
|
||||||
MicroSd::MicroSd() {
|
MicroSd::MicroSd() {
|
||||||
CardDetected = false;
|
CardDetected = false;
|
||||||
CardSize = 0;
|
|
||||||
DetectAfterBoot = false;
|
DetectAfterBoot = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -50,7 +49,7 @@ void MicroSd::InitSdCard() {
|
||||||
if (!SD_MMC.begin("/sdcard", true)) {
|
if (!SD_MMC.begin("/sdcard", true)) {
|
||||||
Serial.println(F("SD Card Mount Failed"));
|
Serial.println(F("SD Card Mount Failed"));
|
||||||
CardDetected = false;
|
CardDetected = false;
|
||||||
CardSize = 0;
|
CardSizeMB = 0;
|
||||||
//DetectAfterBoot = false;
|
//DetectAfterBoot = false;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -60,7 +59,7 @@ void MicroSd::InitSdCard() {
|
||||||
if (cardType == CARD_NONE) {
|
if (cardType == CARD_NONE) {
|
||||||
Serial.println(F("No SD_MMC card attached"));
|
Serial.println(F("No SD_MMC card attached"));
|
||||||
CardDetected = false;
|
CardDetected = false;
|
||||||
CardSize = 0;
|
CardSizeMB = 0;
|
||||||
//DetectAfterBoot = false;
|
//DetectAfterBoot = false;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -77,11 +76,11 @@ void MicroSd::InitSdCard() {
|
||||||
Serial.print(F("UNKNOWN"));
|
Serial.print(F("UNKNOWN"));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* calculation card size */
|
|
||||||
CardSize = SD_MMC.cardSize() / (1024 * 1024);
|
|
||||||
Serial.printf(", Card Size: %d MB\n", CardSize);
|
|
||||||
CardDetected = true;
|
CardDetected = true;
|
||||||
DetectAfterBoot = true;
|
DetectAfterBoot = true;
|
||||||
|
|
||||||
|
/* calculation card size */
|
||||||
|
CheckCardUsedStatus();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -124,6 +123,27 @@ void MicroSd::ListDir(fs::FS &fs, String DirName, uint8_t levels) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
@brief Check directory on the micro SD card
|
||||||
|
@param fs::FS - card
|
||||||
|
@param String - dir name
|
||||||
|
@return bool - status
|
||||||
|
*/
|
||||||
|
bool MicroSd::CheckDir(fs::FS &fs, String path) {
|
||||||
|
bool status = false;
|
||||||
|
if (true == CardDetected) {
|
||||||
|
#if (true == CONSOLE_VERBOSE_DEBUG)
|
||||||
|
Serial.printf("Checking Dir: %s... ", path.c_str());
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (fs.exists(path.c_str())) {
|
||||||
|
status = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@brief List directory on the micro SD card
|
@brief List directory on the micro SD card
|
||||||
@param fs::FS - card
|
@param fs::FS - card
|
||||||
|
|
@ -389,6 +409,140 @@ uint16_t MicroSd::FileCount(fs::FS &fs, String DirName, String FileName) {
|
||||||
return FileCount;
|
return FileCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
@brief Remove files in directory
|
||||||
|
@param fs::FS - card
|
||||||
|
@param String - dir name
|
||||||
|
@param int - max files
|
||||||
|
@return bool - status
|
||||||
|
*/
|
||||||
|
bool MicroSd::RemoveFilesInDir(fs::FS &fs, String path, int maxFiles) {
|
||||||
|
bool ret = false;
|
||||||
|
File dir = fs.open(path.c_str());
|
||||||
|
if (!dir) {
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
int fileCount = 0;
|
||||||
|
File file = dir.openNextFile();
|
||||||
|
while (file) {
|
||||||
|
ret = true;
|
||||||
|
String fileName = path + "/" + file.name();
|
||||||
|
fs.remove(fileName.c_str());
|
||||||
|
Serial.printf("Removing file: %s\n", fileName.c_str());
|
||||||
|
fileCount++;
|
||||||
|
if (fileCount >= maxFiles) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
file = dir.openNextFile();
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int MicroSd::CountFilesInDir(fs::FS &fs, String path) {
|
||||||
|
uint16_t file_count = FileCount(fs, path, "");
|
||||||
|
return file_count;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
@brief Check card used status
|
||||||
|
@param none
|
||||||
|
@return bool - status
|
||||||
|
*/
|
||||||
|
bool MicroSd::CheckCardUsedStatus() {
|
||||||
|
|
||||||
|
CardSizeMB = SD_MMC.cardSize() / (1024 * 1024);
|
||||||
|
CardTotalMB = SD_MMC.totalBytes() / (1024 * 1024);
|
||||||
|
CardUsedMB = SD_MMC.usedBytes() / (1024 * 1024);
|
||||||
|
CardFreeMB = CardSizeMB - CardUsedMB;
|
||||||
|
FreeSpacePercent = (CardFreeMB * 100) / CardSizeMB;
|
||||||
|
UsedSpacePercent = 100 - FreeSpacePercent;
|
||||||
|
|
||||||
|
Serial.printf("Card size: %d MB, Total: %d MB, Used: %d MB, Free: %d GB, Free: %d %% \n", CardSizeMB, CardTotalMB, CardUsedMB, CardFreeMB, FreeSpacePercent);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
@brief Write picture to the SD card
|
||||||
|
@param fs::FS - card
|
||||||
|
@param String - file name
|
||||||
|
@return String - data
|
||||||
|
*/
|
||||||
|
bool MicroSd::WritePicture(String i_PhotoName, uint8_t *i_PhotoData, size_t i_PhotoLen) {
|
||||||
|
#if (true == CONSOLE_VERBOSE_DEBUG)
|
||||||
|
Serial.println(f("WritePicture"));
|
||||||
|
#endif
|
||||||
|
bool ret_stat = false;
|
||||||
|
|
||||||
|
File file = SD_MMC.open(i_PhotoName, FILE_WRITE);
|
||||||
|
|
||||||
|
if (file) {
|
||||||
|
size_t ret = 0;
|
||||||
|
|
||||||
|
ret = file.write(i_PhotoData, i_PhotoLen);
|
||||||
|
if (ret != i_PhotoLen) {
|
||||||
|
Serial.println(F("Failed. Error while writing to file"));
|
||||||
|
} else {
|
||||||
|
Serial.printf("Saved as %s\n", i_PhotoName.c_str());
|
||||||
|
ret_stat = true;
|
||||||
|
}
|
||||||
|
file.close();
|
||||||
|
} else {
|
||||||
|
Serial.printf("Failed. Could not open file: %s\n", i_PhotoName.c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret_stat;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
@brief Write picture to the SD card with EXIF data
|
||||||
|
@param fs::FS - card
|
||||||
|
@param String - file name
|
||||||
|
@param uint8_t - data
|
||||||
|
@param size_t - data length
|
||||||
|
@param const uint8_t - EXIF data
|
||||||
|
@param size_t - EXIF data length
|
||||||
|
@return bool - status
|
||||||
|
*/
|
||||||
|
bool MicroSd::WritePicture(String i_PhotoName, uint8_t *i_PhotoData, size_t i_PhotoLen, const uint8_t *i_PtohoExif, size_t i_PhotoExifLen) {
|
||||||
|
|
||||||
|
#if (true == CONSOLE_VERBOSE_DEBUG)
|
||||||
|
Serial.println(F("WritePicture EXIF"));
|
||||||
|
#endif
|
||||||
|
bool ret_stat = false;
|
||||||
|
|
||||||
|
File file = SD_MMC.open(i_PhotoName, FILE_WRITE);
|
||||||
|
|
||||||
|
if (file) {
|
||||||
|
size_t ret = 0;
|
||||||
|
|
||||||
|
ret = file.write(i_PtohoExif, i_PhotoExifLen);
|
||||||
|
ret += file.write(i_PhotoData, i_PhotoLen);
|
||||||
|
if (ret != (i_PhotoLen + i_PhotoExifLen)) {
|
||||||
|
#if (true == CONSOLE_VERBOSE_DEBUG)
|
||||||
|
Serial.println(F("Failed. Error while writing to file"));
|
||||||
|
#endif
|
||||||
|
ret_stat = false;
|
||||||
|
} else {
|
||||||
|
#if (true == CONSOLE_VERBOSE_DEBUG)
|
||||||
|
Serial.printf("Saved as %s\n", i_PhotoName.c_str());
|
||||||
|
#endif
|
||||||
|
ret_stat = true;
|
||||||
|
}
|
||||||
|
file.close();
|
||||||
|
} else {
|
||||||
|
#if (true == CONSOLE_VERBOSE_DEBUG)
|
||||||
|
Serial.printf("Failed. Could not open file: %s\n", i_PhotoName.c_str());
|
||||||
|
#endif
|
||||||
|
ret_stat = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret_stat;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@brief Get card detected status
|
@brief Get card detected status
|
||||||
@param none
|
@param none
|
||||||
|
|
@ -403,8 +557,8 @@ bool MicroSd::GetCardDetectedStatus() {
|
||||||
@param none
|
@param none
|
||||||
@return uint16_t - size
|
@return uint16_t - size
|
||||||
*/
|
*/
|
||||||
uint16_t MicroSd::GetCardSize() {
|
uint16_t MicroSd::GetCardSizeMB() {
|
||||||
return CardSize;
|
return CardSizeMB;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -416,4 +570,49 @@ bool MicroSd::GetCardDetectAfterBoot() {
|
||||||
return DetectAfterBoot;
|
return DetectAfterBoot;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
@brief Get card total MB
|
||||||
|
@param none
|
||||||
|
@return uint16_t - size
|
||||||
|
*/
|
||||||
|
uint16_t MicroSd::GetCardTotalMB() {
|
||||||
|
return CardTotalMB;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
@brief Get card used MB
|
||||||
|
@param none
|
||||||
|
@return uint16_t - size
|
||||||
|
*/
|
||||||
|
uint16_t MicroSd::GetCardUsedMB() {
|
||||||
|
return CardUsedMB;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
@brief Get card free MB
|
||||||
|
@param none
|
||||||
|
@return uint16_t - size
|
||||||
|
*/
|
||||||
|
uint16_t MicroSd::GetCardFreeMB() {
|
||||||
|
return CardFreeMB;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
@brief Get free space percent
|
||||||
|
@param none
|
||||||
|
@return uint8_t - percent
|
||||||
|
*/
|
||||||
|
uint8_t MicroSd::GetFreeSpacePercent() {
|
||||||
|
return FreeSpacePercent;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
@brief Get used space percent
|
||||||
|
@param none
|
||||||
|
@return uint8_t - percent
|
||||||
|
*/
|
||||||
|
uint8_t MicroSd::GetUsedSpacePercent() {
|
||||||
|
return UsedSpacePercent;
|
||||||
|
}
|
||||||
|
|
||||||
/* EOF */
|
/* EOF */
|
||||||
|
|
@ -34,8 +34,13 @@
|
||||||
class MicroSd {
|
class MicroSd {
|
||||||
private:
|
private:
|
||||||
bool CardDetected; ///< Card detected status
|
bool CardDetected; ///< Card detected status
|
||||||
uint16_t CardSize; ///< Card size
|
|
||||||
bool DetectAfterBoot; ///< Card detect after boot
|
bool DetectAfterBoot; ///< Card detect after boot
|
||||||
|
uint32_t CardSizeMB; ///< Card size
|
||||||
|
uint32_t CardTotalMB;
|
||||||
|
uint32_t CardUsedMB;
|
||||||
|
uint32_t CardFreeMB;
|
||||||
|
uint8_t FreeSpacePercent;
|
||||||
|
uint8_t UsedSpacePercent;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
MicroSd();
|
MicroSd();
|
||||||
|
|
@ -45,6 +50,7 @@ public:
|
||||||
void ReinitCard();
|
void ReinitCard();
|
||||||
|
|
||||||
void ListDir(fs::FS &, String, uint8_t);
|
void ListDir(fs::FS &, String, uint8_t);
|
||||||
|
bool CheckDir(fs::FS &, String);
|
||||||
bool CreateDir(fs::FS &, String);
|
bool CreateDir(fs::FS &, String);
|
||||||
bool RemoveDir(fs::FS &, String);
|
bool RemoveDir(fs::FS &, String);
|
||||||
void ReadFileConsole(fs::FS &, String);
|
void ReadFileConsole(fs::FS &, String);
|
||||||
|
|
@ -54,10 +60,23 @@ public:
|
||||||
bool DeleteFile(fs::FS &, String);
|
bool DeleteFile(fs::FS &, String);
|
||||||
uint32_t GetFileSize(fs::FS &, String);
|
uint32_t GetFileSize(fs::FS &, String);
|
||||||
uint16_t FileCount(fs::FS &, String, String);
|
uint16_t FileCount(fs::FS &, String, String);
|
||||||
|
bool RemoveFilesInDir(fs::FS &, String, int );
|
||||||
|
int CountFilesInDir(fs::FS &, String );
|
||||||
|
|
||||||
|
bool WritePicture(String, uint8_t *, size_t);
|
||||||
|
bool WritePicture(String, uint8_t *, size_t, const uint8_t *, size_t);
|
||||||
|
|
||||||
|
bool CheckCardUsedStatus();
|
||||||
|
|
||||||
bool GetCardDetectedStatus();
|
bool GetCardDetectedStatus();
|
||||||
uint16_t GetCardSize();
|
|
||||||
bool GetCardDetectAfterBoot();
|
bool GetCardDetectAfterBoot();
|
||||||
|
uint16_t GetCardSizeMB();
|
||||||
|
uint16_t GetCardTotalMB();
|
||||||
|
uint16_t GetCardUsedMB();
|
||||||
|
uint16_t GetCardFreeMB();
|
||||||
|
uint32_t GetFreeSpaceMB();
|
||||||
|
uint8_t GetFreeSpacePercent();
|
||||||
|
uint8_t GetUsedSpacePercent();
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
|
|
@ -44,6 +44,7 @@ void Server_InitWebServer() {
|
||||||
request->send_P(404, "text/plain", "Photo not found!");
|
request->send_P(404, "text/plain", "Photo not found!");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
SystemCamera.SetPhotoSending(true);
|
||||||
|
|
||||||
SystemLog.AddEvent(LogLevel_Verbose, "Photo size: " + String(SystemCamera.GetPhotoFb()->len) + " bytes");
|
SystemLog.AddEvent(LogLevel_Verbose, "Photo size: " + String(SystemCamera.GetPhotoFb()->len) + " bytes");
|
||||||
|
|
||||||
|
|
@ -62,6 +63,8 @@ void Server_InitWebServer() {
|
||||||
SystemLog.AddEvent(LogLevel_Verbose, F("Send photo without EXIF data"));
|
SystemLog.AddEvent(LogLevel_Verbose, F("Send photo without EXIF data"));
|
||||||
request->send_P(200, "image/jpg", SystemCamera.GetPhotoFb()->buf, SystemCamera.GetPhotoFb()->len);
|
request->send_P(200, "image/jpg", SystemCamera.GetPhotoFb()->buf, SystemCamera.GetPhotoFb()->len);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SystemCamera.SetPhotoSending(false);
|
||||||
});
|
});
|
||||||
|
|
||||||
/* route to jquery */
|
/* route to jquery */
|
||||||
|
|
@ -434,6 +437,17 @@ void Server_InitWebServer_Actions() {
|
||||||
delay(100); /* wait for sending data */
|
delay(100); /* wait for sending data */
|
||||||
ESP.restart();
|
ESP.restart();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
/* route for change LED status */
|
||||||
|
server.on("/action_sderase", HTTP_GET, [](AsyncWebServerRequest* request) {
|
||||||
|
SystemLog.AddEvent(LogLevel_Verbose, F("WEB server: /action_sderase remove files from SD card"));
|
||||||
|
if (Server_CheckBasicAuth(request) == false)
|
||||||
|
return;
|
||||||
|
|
||||||
|
StartRemoveSdCard = 1;
|
||||||
|
|
||||||
|
request->send_P(200, F("text/plain"), "Starting remove files from SD card");
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -680,6 +694,12 @@ void Server_InitWebServer_Sets() {
|
||||||
response = true;
|
response = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (request->hasParam("timelaps_enable")) {
|
||||||
|
SystemLog.AddEvent(LogLevel_Verbose, F("Set timelaps enable"));
|
||||||
|
Connect.SetTimeLapsPhotoSaveStatus(Server_TransfeStringToBool(request->getParam("timelaps_enable")->value()));
|
||||||
|
response = true;
|
||||||
|
}
|
||||||
|
|
||||||
if (true == response) {
|
if (true == response) {
|
||||||
request->send_P(200, F("text/html"), MSG_SAVE_OK);
|
request->send_P(200, F("text/html"), MSG_SAVE_OK);
|
||||||
}
|
}
|
||||||
|
|
@ -1004,7 +1024,7 @@ void Server_resume() {
|
||||||
* @param const char* - content type
|
* @param const char* - content type
|
||||||
* @param const char* - data
|
* @param const char* - data
|
||||||
*/
|
*/
|
||||||
void Server_handleCacheRequest(AsyncWebServerRequest* request, const char* contentType, const char* data) {
|
void Server_handleCacheRequest(AsyncWebServerRequest* request, const char *contentType, const char *data) {
|
||||||
AsyncWebServerResponse *response = request->beginResponse_P(200, contentType, data);
|
AsyncWebServerResponse *response = request->beginResponse_P(200, contentType, data);
|
||||||
response->addHeader("Cache-Control", "public, max-age=" + String(WEB_CACHE_INTERVAL));
|
response->addHeader("Cache-Control", "public, max-age=" + String(WEB_CACHE_INTERVAL));
|
||||||
request->send(response);
|
request->send(response);
|
||||||
|
|
@ -1019,14 +1039,14 @@ void Server_handleNotFound(AsyncWebServerRequest* request) {
|
||||||
String message = "URL not Found\n\n";
|
String message = "URL not Found\n\n";
|
||||||
|
|
||||||
message += "URI: " + request->url() + "\nMethod: ";
|
message += "URI: " + request->url() + "\nMethod: ";
|
||||||
message += (request->method() == HTTP_GET) ? "GET" : "POST";
|
message += (request->method() == HTTP_GET) ? F("GET") : F("POST");
|
||||||
message += "\nArguments: " + String(request->args()) + "\n";
|
message += "\nArguments: " + String(request->args()) + "\n";
|
||||||
|
|
||||||
for (uint8_t i = 0; i < request->args(); i++) {
|
for (uint8_t i = 0; i < request->args(); i++) {
|
||||||
message += " " + request->argName(i) + ": " + request->arg(i) + "\n";
|
message += " " + request->argName(i) + ": " + request->arg(i) + "\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
request->send(404, "text/plain", message);
|
request->send(404, F("text/plain"), message);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -1048,23 +1068,23 @@ String Server_GetJsonData() {
|
||||||
doc_json["brightness"] = String(SystemCamera.GetBrightness());
|
doc_json["brightness"] = String(SystemCamera.GetBrightness());
|
||||||
doc_json["contrast"] = String(SystemCamera.GetContrast());
|
doc_json["contrast"] = String(SystemCamera.GetContrast());
|
||||||
doc_json["saturation"] = String(SystemCamera.GetSaturation());
|
doc_json["saturation"] = String(SystemCamera.GetSaturation());
|
||||||
doc_json["hmirror"] = (SystemCamera.GetHMirror() == true) ? "true" : "";
|
doc_json["hmirror"] = Server_TranslateBoolToString(SystemCamera.GetHMirror());
|
||||||
doc_json["vflip"] = (SystemCamera.GetVFlip() == true) ? "true" : "";
|
doc_json["vflip"] = Server_TranslateBoolToString(SystemCamera.GetVFlip());
|
||||||
doc_json["lensc"] = (SystemCamera.GetLensC() == true) ? "true" : "";
|
doc_json["lensc"] = Server_TranslateBoolToString(SystemCamera.GetLensC());
|
||||||
doc_json["exposure_ctrl"] = (SystemCamera.GetExposureCtrl() == true) ? "true" : "";
|
doc_json["exposure_ctrl"] = Server_TranslateBoolToString(SystemCamera.GetExposureCtrl());
|
||||||
doc_json["awb"] = (SystemCamera.GetAwb() == true) ? "true" : "";
|
doc_json["awb"] = Server_TranslateBoolToString(SystemCamera.GetAwb());
|
||||||
doc_json["awb_gain"] = (SystemCamera.GetAwbGain() == true) ? "true" : "";
|
doc_json["awb_gain"] = Server_TranslateBoolToString(SystemCamera.GetAwbGain());
|
||||||
doc_json["wb_mode"] = String(SystemCamera.GetAwbMode());
|
doc_json["wb_mode"] = String(SystemCamera.GetAwbMode());
|
||||||
doc_json["bpc"] = (SystemCamera.GetBpc() == true) ? "true" : "";
|
doc_json["bpc"] = Server_TranslateBoolToString(SystemCamera.GetBpc());
|
||||||
doc_json["wpc"] = (SystemCamera.GetWpc() == true) ? "true" : "";
|
doc_json["wpc"] = Server_TranslateBoolToString(SystemCamera.GetWpc());
|
||||||
doc_json["raw_gama"] = (SystemCamera.GetRawGama() == true) ? "true" : "";
|
doc_json["raw_gama"] = Server_TranslateBoolToString(SystemCamera.GetRawGama());
|
||||||
doc_json["aec2"] = (SystemCamera.GetAec2() == true) ? "true" : "";
|
doc_json["aec2"] = Server_TranslateBoolToString(SystemCamera.GetAec2());
|
||||||
doc_json["ae_level"] = SystemCamera.GetAeLevel();
|
doc_json["ae_level"] = SystemCamera.GetAeLevel();
|
||||||
doc_json["aec_value"] = SystemCamera.GetAecValue();
|
doc_json["aec_value"] = SystemCamera.GetAecValue();
|
||||||
doc_json["gain_ctrl"] = (SystemCamera.GetGainCtrl() == true) ? "true" : "";
|
doc_json["gain_ctrl"] = Server_TranslateBoolToString(SystemCamera.GetGainCtrl());
|
||||||
doc_json["agc_gain"] = SystemCamera.GetAgcGaint();
|
doc_json["agc_gain"] = SystemCamera.GetAgcGaint();
|
||||||
doc_json["led"] = (SystemCamera.GetFlashStatus() == true) ? "true" : "";
|
doc_json["led"] = Server_TranslateBoolToString(SystemCamera.GetFlashStatus());
|
||||||
doc_json["flash"] = (SystemCamera.GetCameraFlashEnable() == true) ? "true" : "";
|
doc_json["flash"] = Server_TranslateBoolToString(SystemCamera.GetCameraFlashEnable());
|
||||||
doc_json["flash_time"] = SystemCamera.GetCameraFlashTime();
|
doc_json["flash_time"] = SystemCamera.GetCameraFlashTime();
|
||||||
doc_json["ssid"] = SystemWifiMngt.GetStaSsid();
|
doc_json["ssid"] = SystemWifiMngt.GetStaSsid();
|
||||||
doc_json["bssid"] = SystemWifiMngt.GetStaBssid();
|
doc_json["bssid"] = SystemWifiMngt.GetStaBssid();
|
||||||
|
|
@ -1075,8 +1095,8 @@ String Server_GetJsonData() {
|
||||||
doc_json["wifi_mode"] = SystemWifiMngt.GetWiFiMode();
|
doc_json["wifi_mode"] = SystemWifiMngt.GetWiFiMode();
|
||||||
doc_json["mdns"] = SystemWifiMngt.GetMdns();
|
doc_json["mdns"] = SystemWifiMngt.GetMdns();
|
||||||
doc_json["service_ap_ssid"] = SystemWifiMngt.GetServiceApSsid();
|
doc_json["service_ap_ssid"] = SystemWifiMngt.GetServiceApSsid();
|
||||||
doc_json["serviceap"] = (SystemWifiMngt.GetEnableServiceAp() == true) ? "true" : "";
|
doc_json["serviceap"] = Server_TranslateBoolToString(SystemWifiMngt.GetEnableServiceAp());
|
||||||
doc_json["auth"] = (WebBasicAuth.EnableAuth == true) ? "true" : "";
|
doc_json["auth"] = Server_TranslateBoolToString(WebBasicAuth.EnableAuth);
|
||||||
doc_json["auth_username"] = WebBasicAuth.UserName;
|
doc_json["auth_username"] = WebBasicAuth.UserName;
|
||||||
doc_json["last_upload_status"] = Connect.GetBackendReceivedStatus();
|
doc_json["last_upload_status"] = Connect.GetBackendReceivedStatus();
|
||||||
doc_json["wifi_network_status"] = SystemWifiMngt.GetStaStatus();
|
doc_json["wifi_network_status"] = SystemWifiMngt.GetStaStatus();
|
||||||
|
|
@ -1090,6 +1110,11 @@ String Server_GetJsonData() {
|
||||||
doc_json["net_gw"] = SystemWifiMngt.GetNetStaticGateway();
|
doc_json["net_gw"] = SystemWifiMngt.GetNetStaticGateway();
|
||||||
doc_json["net_dns"] = SystemWifiMngt.GetNetStaticDns();
|
doc_json["net_dns"] = SystemWifiMngt.GetNetStaticDns();
|
||||||
doc_json["image_rotation"] = SystemCamera.GetCameraImageRotation();
|
doc_json["image_rotation"] = SystemCamera.GetCameraImageRotation();
|
||||||
|
doc_json["timelaps"] = Server_TranslateBoolToString(Connect.GetTimeLapsPhotoSaveStatus());
|
||||||
|
doc_json["sd_status"] = (SystemLog.GetCardDetectedStatus() == true) ? F("Card detected") : F("No card detected");
|
||||||
|
doc_json["sd_total"] = SystemLog.GetCardSizeMB();
|
||||||
|
doc_json["sd_free_p"] = SystemLog.GetFreeSpacePercent();
|
||||||
|
doc_json["sd_used_p"] = SystemLog.GetUsedSpacePercent();
|
||||||
doc_json["sw_build"] = SW_BUILD;
|
doc_json["sw_build"] = SW_BUILD;
|
||||||
doc_json["sw_ver"] = SW_VERSION;
|
doc_json["sw_ver"] = SW_VERSION;
|
||||||
doc_json["sw_new_ver"] = FirmwareUpdate.NewVersionFw;
|
doc_json["sw_new_ver"] = FirmwareUpdate.NewVersionFw;
|
||||||
|
|
@ -1185,4 +1210,15 @@ bool Server_TransfeStringToBool(String data) {
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
String Server_TranslateBoolToString(bool i_data) {
|
||||||
|
String ret = "";
|
||||||
|
if (true == i_data) {
|
||||||
|
ret = "true";
|
||||||
|
} else {
|
||||||
|
ret = "";
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
/* EOF */
|
/* EOF */
|
||||||
|
|
|
||||||
|
|
@ -65,6 +65,8 @@ void Server_streamJpg(AsyncWebServerRequest *);
|
||||||
void Server_GetModuleUptime(String &);
|
void Server_GetModuleUptime(String &);
|
||||||
bool Server_TransfeStringToBool(String);
|
bool Server_TransfeStringToBool(String);
|
||||||
|
|
||||||
|
String Server_TranslateBoolToString(bool);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* EOF */
|
/* EOF */
|
||||||
|
|
|
||||||
|
|
@ -117,14 +117,14 @@ void System_CheckNewVersion() {
|
||||||
WiFiClientSecure client;
|
WiFiClientSecure client;
|
||||||
client.setCACert(root_CAs_ota);
|
client.setCACert(root_CAs_ota);
|
||||||
//client.setInsecure();
|
//client.setInsecure();
|
||||||
FirmwareUpdate.CheckNewVersionFwStatus = "N/A";
|
FirmwareUpdate.CheckNewVersionFwStatus = F("N/A");
|
||||||
FirmwareUpdate.NewVersionFw = "Unknown";
|
FirmwareUpdate.NewVersionFw = F("Unknown");
|
||||||
FirmwareUpdate.OtaUpdateFwUrl = "";
|
FirmwareUpdate.OtaUpdateFwUrl = "";
|
||||||
FirmwareUpdate.OtaUpdateFwAvailable = false;
|
FirmwareUpdate.OtaUpdateFwAvailable = false;
|
||||||
|
|
||||||
/* connect to server and get json */
|
/* connect to server and get json */
|
||||||
if (!client.connect("api.github.com", 443)) {
|
if (!client.connect(OTA_UPDATE_API_SERVER, 443)) {
|
||||||
FirmwareUpdate.CheckNewVersionFwStatus = "Failed connect to OTA server!";
|
FirmwareUpdate.CheckNewVersionFwStatus = F("Failed connect to OTA server!");
|
||||||
SystemLog.AddEvent(LogLevel_Info, FirmwareUpdate.CheckNewVersionFwStatus);
|
SystemLog.AddEvent(LogLevel_Info, FirmwareUpdate.CheckNewVersionFwStatus);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -181,7 +181,7 @@ void System_CheckNewVersion() {
|
||||||
SystemLog.AddEvent(LogLevel_Info, "Assets[" + String(i) + "]: " + String(name));
|
SystemLog.AddEvent(LogLevel_Info, "Assets[" + String(i) + "]: " + String(name));
|
||||||
|
|
||||||
/* get FW file and URL */
|
/* get FW file and URL */
|
||||||
if (strcmp(name, OTA_UPDATE_FW_FILE) == 0) {
|
if (strcmp_P(name, OTA_UPDATE_FW_FILE) == 0) {
|
||||||
/* get download URL */
|
/* get download URL */
|
||||||
const char* download_url = asset["browser_download_url"];
|
const char* download_url = asset["browser_download_url"];
|
||||||
FirmwareUpdate.OtaUpdateFwUrl = download_url;
|
FirmwareUpdate.OtaUpdateFwUrl = download_url;
|
||||||
|
|
@ -544,6 +544,19 @@ void System_TaskSdCardCheck(void *pvParameters) {
|
||||||
SystemLog.ReinitCard();
|
SystemLog.ReinitCard();
|
||||||
SystemLog.AddEvent(LogLevel_Warning, F("Reinit micro SD card done!"));
|
SystemLog.AddEvent(LogLevel_Warning, F("Reinit micro SD card done!"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* check card free space */
|
||||||
|
if (true == SystemLog.GetCardDetectedStatus()) {
|
||||||
|
SystemLog.AddEvent(LogLevel_Verbose, "Check card free space");
|
||||||
|
SystemLog.CheckCardUsedStatus();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* check maximum log file size */
|
||||||
|
if (true == SystemLog.GetCardDetectedStatus()) {
|
||||||
|
SystemLog.AddEvent(LogLevel_Verbose, "Check maximum log file size");
|
||||||
|
SystemLog.CheckMaxLogFileSize();
|
||||||
|
}
|
||||||
|
|
||||||
SystemLog.AddEvent(LogLevel_Verbose, "MicroSdCard task. Stack free size: " + String(uxTaskGetStackHighWaterMark(NULL)) + " bytes");
|
SystemLog.AddEvent(LogLevel_Verbose, "MicroSdCard task. Stack free size: " + String(uxTaskGetStackHighWaterMark(NULL)) + " bytes");
|
||||||
|
|
||||||
/* reset wdg */
|
/* reset wdg */
|
||||||
|
|
@ -649,4 +662,44 @@ void System_TaskWiFiWatchdog(void *pvParameters) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Function for micro SD card remove files task
|
||||||
|
*
|
||||||
|
* @param void *pvParameters
|
||||||
|
* @return none
|
||||||
|
*/
|
||||||
|
void System_TaskSdCardRemove(void *pvParameters) {
|
||||||
|
SystemLog.AddEvent(LogLevel_Info, "TaskSdCardRemove. core: " + String(xPortGetCoreID()));
|
||||||
|
TickType_t xLastWakeTime = xTaskGetTickCount();
|
||||||
|
SdCardRemoveTime = TASK_SDCARD_FILE_REMOVE;
|
||||||
|
|
||||||
|
while (1) {
|
||||||
|
esp_task_wdt_reset();
|
||||||
|
if (0 != StartRemoveSdCard) {
|
||||||
|
if (1 == StartRemoveSdCard) {
|
||||||
|
SdCardRemoveTime = 5000;
|
||||||
|
SystemLog.AddEvent(LogLevel_Info, "Start remove timelaps photo");
|
||||||
|
uint16_t file_count = SystemLog.CountFilesInDir(SD_MMC, TIMELAPS_PHOTO_FOLDER);
|
||||||
|
SystemLog.AddEvent(LogLevel_Info, "Files in dir: " + String(file_count));
|
||||||
|
esp_task_wdt_reset();
|
||||||
|
StartRemoveSdCard = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( false == SystemLog.RemoveFilesInDir(SD_MMC, TIMELAPS_PHOTO_FOLDER, FILE_REMOVE_MAX_COUNT)) {
|
||||||
|
SystemLog.AddEvent(LogLevel_Info, "Remove files in dir done");
|
||||||
|
StartRemoveSdCard = 0;
|
||||||
|
SdCardRemoveTime = TASK_SDCARD_FILE_REMOVE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SystemLog.AddEvent(LogLevel_Verbose, "MicroSdCard task. Stack free size: " + String(uxTaskGetStackHighWaterMark(NULL)) + " bytes");
|
||||||
|
|
||||||
|
/* reset wdg */
|
||||||
|
esp_task_wdt_reset();
|
||||||
|
|
||||||
|
/* next start task */
|
||||||
|
vTaskDelayUntil(&xLastWakeTime, SdCardRemoveTime / portTICK_PERIOD_MS);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* EOF */
|
/* EOF */
|
||||||
|
|
@ -33,10 +33,10 @@
|
||||||
#include "serial_cfg.h"
|
#include "serial_cfg.h"
|
||||||
#include "sys_led.h"
|
#include "sys_led.h"
|
||||||
|
|
||||||
#define SYSTEM_MSG_UPDATE_DONE "FW update successfully done! Please reboot the MCU."
|
#define SYSTEM_MSG_UPDATE_DONE F("FW update successfully done! Please reboot the MCU.")
|
||||||
#define SYSTEM_MSG_UPDATE_FAIL "FW update failed! Please reboot MCU, and try again."
|
#define SYSTEM_MSG_UPDATE_FAIL F("FW update failed! Please reboot MCU, and try again.")
|
||||||
#define SYSTEM_MSG_UPDATE_PROCESS "FW update in progress"
|
#define SYSTEM_MSG_UPDATE_PROCESS F("FW update in progress")
|
||||||
#define SYSTEM_MSG_UPDATE_NO_FW "No new FW version available!"
|
#define SYSTEM_MSG_UPDATE_NO_FW F("No new FW version available!")
|
||||||
|
|
||||||
void System_Init();
|
void System_Init();
|
||||||
void System_LoadCfg();
|
void System_LoadCfg();
|
||||||
|
|
@ -63,6 +63,7 @@ void System_TaskSerialCfg(void *);
|
||||||
void System_TaskStreamTelemetry(void *);
|
void System_TaskStreamTelemetry(void *);
|
||||||
void System_TaskSysLed(void *);
|
void System_TaskSysLed(void *);
|
||||||
void System_TaskWiFiWatchdog(void *);
|
void System_TaskWiFiWatchdog(void *);
|
||||||
|
void System_TaskSdCardRemove(void *);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
/* EOF */
|
/* EOF */
|
||||||
|
|
@ -22,5 +22,9 @@ TaskHandle_t Task_SerialCfg;
|
||||||
TaskHandle_t Task_StreamTelemetry;
|
TaskHandle_t Task_StreamTelemetry;
|
||||||
TaskHandle_t Task_SysLed;
|
TaskHandle_t Task_SysLed;
|
||||||
TaskHandle_t Task_WiFiWatchdog;
|
TaskHandle_t Task_WiFiWatchdog;
|
||||||
|
//TaskHandle_t Task_SdCardFileRemove;
|
||||||
|
|
||||||
|
uint8_t StartRemoveSdCard = 0;
|
||||||
|
uint32_t SdCardRemoveTime = 0;
|
||||||
|
|
||||||
/* EOF */
|
/* EOF */
|
||||||
|
|
@ -48,6 +48,10 @@ extern TaskHandle_t Task_SerialCfg; ///< task handle for serial
|
||||||
extern TaskHandle_t Task_StreamTelemetry; ///< task handle for stream telemetry
|
extern TaskHandle_t Task_StreamTelemetry; ///< task handle for stream telemetry
|
||||||
extern TaskHandle_t Task_SysLed; ///< task handle for system led
|
extern TaskHandle_t Task_SysLed; ///< task handle for system led
|
||||||
extern TaskHandle_t Task_WiFiWatchdog; ///< task handle for wifi watchdog
|
extern TaskHandle_t Task_WiFiWatchdog; ///< task handle for wifi watchdog
|
||||||
|
//extern TaskHandle_t Task_SdCardFileRemove; ///< task handle for remove file from sd card
|
||||||
|
|
||||||
|
extern uint8_t StartRemoveSdCard;
|
||||||
|
extern uint32_t SdCardRemoveTime;
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -74,14 +74,14 @@ void WiFiMngt::Init() {
|
||||||
ServiceMode = true;
|
ServiceMode = true;
|
||||||
WiFi.softAPConfig(Service_LocalIp, Service_Gateway, Service_Subnet);
|
WiFi.softAPConfig(Service_LocalIp, Service_Gateway, Service_Subnet);
|
||||||
WiFi.softAP(SericeApSsid.c_str(), SERVICE_WIFI_PASS, SERVICE_WIFI_CHANNEL);
|
WiFi.softAP(SericeApSsid.c_str(), SERVICE_WIFI_PASS, SERVICE_WIFI_CHANNEL);
|
||||||
WiFiMode = "AP + Client";
|
WiFiMode = F("AP + Client");
|
||||||
log->AddEvent(LogLevel_Info, "Service IP Address: http://" + WiFi.softAPIP().toString());
|
log->AddEvent(LogLevel_Info, "Service IP Address: http://" + WiFi.softAPIP().toString());
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
log->AddEvent(LogLevel_Warning, F("Service AP mode disabled!"));
|
log->AddEvent(LogLevel_Warning, F("Service AP mode disabled!"));
|
||||||
WiFi.mode(WIFI_STA);
|
WiFi.mode(WIFI_STA);
|
||||||
ServiceMode = false;
|
ServiceMode = false;
|
||||||
WiFiMode = "Client";
|
WiFiMode = F("Client");
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Set STA IP method. Static or DHCP */
|
/* Set STA IP method. Static or DHCP */
|
||||||
|
|
@ -150,7 +150,7 @@ void WiFiMngt::WifiManagement() {
|
||||||
esp_wifi_set_ps(WIFI_PS_NONE);
|
esp_wifi_set_ps(WIFI_PS_NONE);
|
||||||
WiFiStaConnect();
|
WiFiStaConnect();
|
||||||
//WiFi.begin(WifiSsid, WifiPassword);
|
//WiFi.begin(WifiSsid, WifiPassword);
|
||||||
WiFiMode = "Client";
|
WiFiMode = F("Client");
|
||||||
|
|
||||||
#if (WIFI_CLIENT_WAIT_CON == true)
|
#if (WIFI_CLIENT_WAIT_CON == true)
|
||||||
while (WiFi.status() != WL_CONNECTED) {
|
while (WiFi.status() != WL_CONNECTED) {
|
||||||
|
|
|
||||||
|
|
@ -14,7 +14,6 @@
|
||||||
$("#content").load(page);
|
$("#content").load(page);
|
||||||
setActive(this);
|
setActive(this);
|
||||||
});
|
});
|
||||||
|
|
||||||
$("#content").load("page_config.html", function() {
|
$("#content").load("page_config.html", function() {
|
||||||
var defaultLink = document.querySelector('a[href="page_config.html"]');
|
var defaultLink = document.querySelector('a[href="page_config.html"]');
|
||||||
setActive(defaultLink);
|
setActive(defaultLink);
|
||||||
|
|
@ -22,7 +21,6 @@
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
<nav>
|
<nav>
|
||||||
<img src="esp32_cam.svg" id=logo alt="Logo image" style="margin-left: 10px;" />
|
<img src="esp32_cam.svg" id=logo alt="Logo image" style="margin-left: 10px;" />
|
||||||
|
|
@ -36,7 +34,6 @@
|
||||||
</ul>
|
</ul>
|
||||||
</nav>
|
</nav>
|
||||||
<hr>
|
<hr>
|
||||||
|
|
||||||
<section class="container">
|
<section class="container">
|
||||||
<div class="container_left-half">
|
<div class="container_left-half">
|
||||||
<article>
|
<article>
|
||||||
|
|
@ -52,23 +49,20 @@
|
||||||
</article>
|
</article>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
<br>
|
<br>
|
||||||
<cfg>
|
<div id="cfg">
|
||||||
<cfg_bar>
|
<div id="cfg_bar">
|
||||||
<div id="links">
|
<div id="links">
|
||||||
<li ><a href="page_config.html">Camera configuration</a></li>
|
<li><a href="page_config.html">Camera configuration</a></li>
|
||||||
<li ><a href="page_wifi.html">Wi-Fi configuration</a></li>
|
<li><a href="page_wifi.html">Wi-Fi configuration</a></li>
|
||||||
<li ><a href="page_auth.html">Authentication</a></li>
|
<li><a href="page_auth.html">Authentication</a></li>
|
||||||
<li ><a href="page_system.html">System</a></li>
|
<li><a href="page_system.html">System</a></li>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</cfg_bar>
|
|
||||||
</cfg>
|
|
||||||
<hr>
|
<hr>
|
||||||
|
|
||||||
<div id="content">
|
<div id="content">
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<br><br><br><br>
|
<br><br><br><br>
|
||||||
<table id=botton><tr>
|
<table id=botton><tr>
|
||||||
<td><p class=p2>Prusa Connect ESP32 cam</p> </td>
|
<td><p class=p2>Prusa Connect ESP32 cam</p> </td>
|
||||||
|
|
@ -77,7 +71,6 @@
|
||||||
<td><a href="https://github.com/Prusa-Development/Prusa-Firmware-ESP32-Cam/" id="github-link"><svg height="25"><image href="github-icon.svg"></svg></a></td>
|
<td><a href="https://github.com/Prusa-Development/Prusa-Firmware-ESP32-Cam/" id="github-link"><svg height="25"><image href="github-icon.svg"></svg></a></td>
|
||||||
</tr></table>
|
</tr></table>
|
||||||
</body>
|
</body>
|
||||||
|
|
||||||
<script src="scripts.js"></script>
|
<script src="scripts.js"></script>
|
||||||
<script>
|
<script>
|
||||||
sliderCheck();
|
sliderCheck();
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,5 @@
|
||||||
<style>@import url("styles.css");</style>
|
<style>@import url("styles.css");</style>
|
||||||
<script src="jquery-3.7.0.min.js"></script>
|
<script src="jquery-3.7.0.min.js"></script>
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
<center>
|
<center>
|
||||||
<table>
|
<table>
|
||||||
|
|
@ -13,7 +12,6 @@
|
||||||
</table>
|
</table>
|
||||||
</center>
|
</center>
|
||||||
</body>
|
</body>
|
||||||
|
|
||||||
<script src="scripts.js"></script>
|
<script src="scripts.js"></script>
|
||||||
<script>
|
<script>
|
||||||
get_data("auth");
|
get_data("auth");
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
<script src="jquery-3.7.0.min.js"></script>
|
<script src="jquery-3.7.0.min.js"></script>
|
||||||
<body>
|
<body>
|
||||||
<center><table id="data">
|
<center><table id="data">
|
||||||
<tr><td class="ps3">Basic image settings</td><td></td></tr>
|
<tr><td class="ps3">Basic settings</td><td></td></tr>
|
||||||
<tr><td class="pc1">Connect Token</td><td ><input type="text" name="token" id=tokenid > <button class="btn_save" onclick="changeValue(encodeURIComponent(document.getElementById('tokenid').value), 'set_token?token=', 'config')">Save</button></td></tr>
|
<tr><td class="pc1">Connect Token</td><td ><input type="text" name="token" id=tokenid > <button class="btn_save" onclick="changeValue(encodeURIComponent(document.getElementById('tokenid').value), 'set_token?token=', 'config')">Save</button></td></tr>
|
||||||
<tr><td class="pc1">Fingerprint</td><td class=pc2 id="fingerprint"></td></tr>
|
<tr><td class="pc1">Fingerprint</td><td class=pc2 id="fingerprint"></td></tr>
|
||||||
<tr><td class="pc1">Trigger Interval [s]</td><td ><input type="text" name="refresh" id=refreshid > <button class="btn_save" onclick="changeValue(document.getElementById('refreshid').value, 'set_int?refresh=', 'config')">Save</button></td></tr>
|
<tr><td class="pc1">Trigger Interval [s]</td><td ><input type="text" name="refresh" id=refreshid > <button class="btn_save" onclick="changeValue(document.getElementById('refreshid').value, 'set_int?refresh=', 'config')">Save</button></td></tr>
|
||||||
|
|
@ -27,7 +27,7 @@
|
||||||
<tr><td class="pc1">Saturation</td><td class="pc2">Low <input type="range" class="slider" name="saturation" id=saturationid min="-2" max="2" step="1" onchange="changeValue(this.value, 'set_int?saturation=', 'config')"> High</td></tr>
|
<tr><td class="pc1">Saturation</td><td class="pc2">Low <input type="range" class="slider" name="saturation" id=saturationid min="-2" max="2" step="1" onchange="changeValue(this.value, 'set_int?saturation=', 'config')"> High</td></tr>
|
||||||
<tr><td style="height: 1px;"></td><td style="height: 1px;"></td></tr>
|
<tr><td style="height: 1px;"></td><td style="height: 1px;"></td></tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td class="pc1">Image rotation</td><td><label for="image_rotation"></label>
|
<td class="pc1">Image Rotation</td><td><label for="image_rotation"></label>
|
||||||
<select class="select" id="image_rotationid" name="image_rotation" onchange="changeValue(this.value, 'set_int?image_rotation=', 'config')">
|
<select class="select" id="image_rotationid" name="image_rotation" onchange="changeValue(this.value, 'set_int?image_rotation=', 'config')">
|
||||||
<option value="1">0°</option>
|
<option value="1">0°</option>
|
||||||
<option value="6">90°</option>
|
<option value="6">90°</option>
|
||||||
|
|
@ -44,13 +44,14 @@
|
||||||
<tr><td class="pc1">Flash duration</td><td class="pc2">Low <input type="range" class="slider" name="flash_time" id=flash_timeid min="50" max="1500" step="50" onchange="changeValue(this.value, 'set_int?flash_time=', 'config')">High</td></tr>
|
<tr><td class="pc1">Flash duration</td><td class="pc2">Low <input type="range" class="slider" name="flash_time" id=flash_timeid min="50" max="1500" step="50" onchange="changeValue(this.value, 'set_int?flash_time=', 'config')">High</td></tr>
|
||||||
<tr><td class="pc1">Flash duration</td><td class="pc2"><span id="flash_time_value"></span> ms</td></tr>
|
<tr><td class="pc1">Flash duration</td><td class="pc2"><span id="flash_time_value"></span> ms</td></tr>
|
||||||
<tr><td style="height: 1px;"></td><td style="height: 1px;"></td></tr>
|
<tr><td style="height: 1px;"></td><td style="height: 1px;"></td></tr>
|
||||||
|
<tr><td class="pc1">Save images to micro SD</td><td class="pc2"><label class="switch"><input type="checkbox" name="timelaps" id=timelapsid onchange="changeValue(this.checked, 'set_bool?timelaps_enable=', 'config')"><span class="checkbox_slider round"></span></label> <span id="status_timelaps"></span></td></tr>
|
||||||
|
<tr><td style="height: 1px;"></td><td style="height: 1px;"></td></tr>
|
||||||
</table></center>
|
</table></center>
|
||||||
|
<center><button class="btn_collapsible">Advanced settings</button></center>
|
||||||
<center><button class="btn_collapsible">Advanced image settings</button></center>
|
|
||||||
<div class="content">
|
<div class="content">
|
||||||
<center><table id="data">
|
<center><table id="data">
|
||||||
<tr><td style="height: 1px;"></td><td style="height: 1px;"></td></tr>
|
<tr><td style="height: 1px;"></td><td style="height: 1px;"></td></tr>
|
||||||
<tr><td class="ps3">Advanced image settings</td><td></td></tr>
|
<tr><td class="ps3">Advanced settings</td><td></td></tr>
|
||||||
<tr><td class="pc1">Automatic white balancing</td><td class="pc2"><label class="switch"><input type="checkbox" name="awb" id=awbid onchange="changeValue(this.checked, 'set_bool?awb=', 'config')"><span class="checkbox_slider round"></span></label> <span id="status_awb"></span></td></tr>
|
<tr><td class="pc1">Automatic white balancing</td><td class="pc2"><label class="switch"><input type="checkbox" name="awb" id=awbid onchange="changeValue(this.checked, 'set_bool?awb=', 'config')"><span class="checkbox_slider round"></span></label> <span id="status_awb"></span></td></tr>
|
||||||
<tr><td class="pc1">Automatic white balancing gain</td><td class="pc2"><label class="switch"><input type="checkbox" name="awb_gain" id=awb_gainid onchange="changeValue(this.checked, 'set_bool?awb_gain=', 'config')"><span class="checkbox_slider round"></span></label> <span id="status_awb_gain"></span></td></tr>
|
<tr><td class="pc1">Automatic white balancing gain</td><td class="pc2"><label class="switch"><input type="checkbox" name="awb_gain" id=awb_gainid onchange="changeValue(this.checked, 'set_bool?awb_gain=', 'config')"><span class="checkbox_slider round"></span></label> <span id="status_awb_gain"></span></td></tr>
|
||||||
<tr>
|
<tr>
|
||||||
|
|
@ -81,7 +82,6 @@
|
||||||
</table></center>
|
</table></center>
|
||||||
</div>
|
</div>
|
||||||
</body>
|
</body>
|
||||||
|
|
||||||
<script src="scripts.js"></script>
|
<script src="scripts.js"></script>
|
||||||
<script>
|
<script>
|
||||||
get_data("config");
|
get_data("config");
|
||||||
|
|
|
||||||
|
|
@ -4,16 +4,18 @@
|
||||||
<center>
|
<center>
|
||||||
<table id="data">
|
<table id="data">
|
||||||
<tr><td class="ps3">System status</td><td></td></tr>
|
<tr><td class="ps3">System status</td><td></td></tr>
|
||||||
<tr><td class="ps1">PrusaConnect Status</td><td class="ps2" id="last_upload_status"></td></tr>
|
<tr><td class="ps1">Prusa Connect Status</td><td class="ps2" id="last_upload_status"></td></tr>
|
||||||
<tr><td class="ps1">Wi-Fi mode</td><td class="ps2" id="wifi_mode"></td></tr>
|
<tr><td class="ps1">Wi-Fi mode</td><td class="ps2" id="wifi_mode"></td></tr>
|
||||||
<tr><td class="ps1">Wi-Fi service AP SSID</td><td class="ps2" id="service_ap_ssid"></td></tr>
|
<tr><td class="ps1">Wi-Fi service AP SSID</td><td class="ps2" id="service_ap_ssid"></td></tr>
|
||||||
<tr><td class="ps1">Uptime</td><td class="ps2" id="uptime"></td></tr>
|
<tr><td class="ps1">Uptime</td><td class="ps2" id="uptime"></td></tr>
|
||||||
<tr><td class="ps1">Software version</td><td class="ps2" id="sw_ver"></td></tr>
|
<tr><td style="height: 1px;"></td><td style="height: 1px;"></td></tr>
|
||||||
<tr><td class="ps1">Software build</td><td class="ps2" id="sw_build"></td></tr>
|
<tr><td class="ps3">Firmware</td><td></td></tr>
|
||||||
<tr><td class="ps1">Available software update</td><td class="ps2"><span id="sw_new_ver"></span> <span class="underlined-text" onclick="checkUpdate()">Check update from cloud</span></td></tr>
|
<tr><td class="ps1">Version</td><td class="ps2" id="sw_ver"></td></tr>
|
||||||
|
<tr><td class="ps1">Build</td><td class="ps2" id="sw_build"></td></tr>
|
||||||
|
<tr><td class="ps1">Available update</td><td class="ps2"><span id="sw_new_ver"></span> <span class="underlined-text" onclick="checkUpdate()">Check update from cloud</span></td></tr>
|
||||||
<tr><td style="height: 1px;"></td><td style="height: 1px;"></td></tr>
|
<tr><td style="height: 1px;"></td><td style="height: 1px;"></td></tr>
|
||||||
<tr><td class="ps3">System configuration</td><td></td></tr>
|
<tr><td class="ps3">System configuration</td><td></td></tr>
|
||||||
<tr><td class="pc1">Cam name & mDNS record</td><td ><input type="text" name="mdns" id=mdnsid ><span class=pc1>.local</span> <button class="btn_save" onclick="changeValue(document.getElementById('mdnsid').value, 'set_mdns?mdns=', 'system')">Save</button></td></tr>
|
<tr><td class="pc1">Camera name & mDNS record</td><td ><input type="text" name="mdns" id=mdnsid ><span class=pc1>.local</span> <button class="btn_save" onclick="changeValue(document.getElementById('mdnsid').value, 'set_mdns?mdns=', 'system')">Save</button></td></tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td class="pc1">Log level</td><td><label for="loglevel"></label>
|
<td class="pc1">Log level</td><td><label for="loglevel"></label>
|
||||||
<select class="select" id="loglevelid" name="loglevel" onchange="changeValue(this.value, 'set_int?log_level=', 'system')">
|
<select class="select" id="loglevelid" name="loglevel" onchange="changeValue(this.value, 'set_int?log_level=', 'system')">
|
||||||
|
|
@ -25,21 +27,26 @@
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr><td class="pc1">Get logs</td><td ><button class="btn_update" onclick="window.open('get_logs')">Get logs</button></td></tr>
|
<tr><td class="pc1">Get logs</td><td ><button class="btn_update" onclick="window.open('get_logs')">Get logs</button></td></tr>
|
||||||
|
<tr><td style="height: 1px;"></td><td style="height: 1px;"></td></tr>
|
||||||
|
<tr><td class="ps3">Micro SD card</td><td></td></tr>
|
||||||
|
<tr><td class="ps1">Card status</td><td class="ps2" id="sd_status"></td></tr>
|
||||||
|
<tr><td class="ps1">Capacity</td><td class="ps2"><span id="sd_total"></span> MB</td></tr>
|
||||||
|
<tr><td class="ps1">Available</td><td class="ps2"><div class="progress-container"><div class="progress-bar" id="progress_bar_sd_free">0%</div></div></td></tr>
|
||||||
|
<tr><td class="ps1">Used</td><td class="ps2"><div class="progress-container"><div class="progress-bar" id="progress_bar_sd_used">0%</div></div></td></tr>
|
||||||
</table>
|
</table>
|
||||||
</center>
|
</center>
|
||||||
<br>
|
<br>
|
||||||
<center>
|
<center>
|
||||||
<table id="update">
|
<table id="update">
|
||||||
<tr><td class="ps3">Firmware update</td><td></td></tr>
|
<tr><td class="ps3">Firmware update</td><td></td></tr>
|
||||||
<tr><td class="ps1">Status:</td><td><span class="ps2" id="status">Ready</span></td></tr>
|
<tr><td class="ps1">Status</td><td><span class="ps2" id="status">Ready</span></td></tr>
|
||||||
<tr><td class="ps1">Processing:</td><td class="ps2"><div class="progress-container"><div class="progress-bar" id="myProgressBar">0%</div></div><!--<span class="ps2" id="progressValue">0</span>%--></td></tr>
|
<tr><td class="ps1">Progress</td><td class="ps2"><div class="progress-container"><div class="progress-bar" id="myProgressBar">0%</div></div></td></tr>
|
||||||
<tr><td></td><td style="width:50%"><input type="file" id="firmwareInput" accept=".bin"></td></tr>
|
<tr><td></td><td><input type="file" id="firmwareInput" accept=".bin"></td></tr>
|
||||||
<tr><td></td><td><input type="submit" class="btn_update" value="Update from file" onclick="uploadFile()"></td></tr>
|
<tr><td></td><td><input type="submit" class="btn_update" value="Update from file" onclick="uploadFile()"></td></tr>
|
||||||
<tr><td></td><td><input type="submit" class="btn_update" value="Update from cloud" onclick="updateWeb()"></td></tr>
|
<tr><td></td><td><input type="submit" class="btn_update" value="Update from cloud" onclick="updateWeb()"></td></tr>
|
||||||
</table>
|
</table>
|
||||||
</center>
|
</center>
|
||||||
</body>
|
</body>
|
||||||
|
|
||||||
<script src="scripts.js"></script>
|
<script src="scripts.js"></script>
|
||||||
<script>
|
<script>
|
||||||
var updateCompleted = false;
|
var updateCompleted = false;
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,5 @@
|
||||||
<style>@import url("styles.css");</style>
|
<style>@import url("styles.css");</style>
|
||||||
<script src="jquery-3.7.0.min.js"></script>
|
<script src="jquery-3.7.0.min.js"></script>
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
<table id="center_tb">
|
<table id="center_tb">
|
||||||
<tr><td></td><td style="width:40%">
|
<tr><td></td><td style="width:40%">
|
||||||
|
|
@ -11,12 +10,10 @@
|
||||||
<p class="w2">IP Address: <span id="ip"></span></p>
|
<p class="w2">IP Address: <span id="ip"></span></p>
|
||||||
<p class="w2">mDNS: http://<span id="mdns"></span>.local</p>
|
<p class="w2">mDNS: http://<span id="mdns"></span>.local</p>
|
||||||
</td><td></td></tr>
|
</td><td></td></tr>
|
||||||
|
|
||||||
<tr><td></td><td style="width:40%">
|
<tr><td></td><td style="width:40%">
|
||||||
<br>
|
<br>
|
||||||
<p class="w1">Available networks</p>
|
<p class="w1">Available networks</p>
|
||||||
</td><td></td></tr>
|
</td><td></td></tr>
|
||||||
|
|
||||||
<tr><td></td><td style="width:40%">
|
<tr><td></td><td style="width:40%">
|
||||||
<table id="wifi_ntw">
|
<table id="wifi_ntw">
|
||||||
<colgroup>
|
<colgroup>
|
||||||
|
|
@ -33,12 +30,10 @@
|
||||||
</tr>
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
</td><td></td></tr>
|
</td><td></td></tr>
|
||||||
|
|
||||||
<tr><td></td><td style="width:40%" align="right">
|
<tr><td></td><td style="width:40%" align="right">
|
||||||
<button class="btn" onclick="scanWifi()">Scan Wi-Fi networks</button>
|
<button class="btn" onclick="scanWifi()">Scan Wi-Fi networks</button>
|
||||||
<br>
|
<br>
|
||||||
</td><td></td></tr>
|
</td><td></td></tr>
|
||||||
|
|
||||||
<tr><td></td><td style="width:40%">
|
<tr><td></td><td style="width:40%">
|
||||||
<br>
|
<br>
|
||||||
<table>
|
<table>
|
||||||
|
|
@ -48,9 +43,7 @@
|
||||||
<tr><td></td><td align="center"><button class="btn_save_w" onclick="setWifi(document.getElementById('wifi_ssid_id').value, document.getElementById('wifi_pass_id').value)">Save & Connect</button></td></tr>
|
<tr><td></td><td align="center"><button class="btn_save_w" onclick="setWifi(document.getElementById('wifi_ssid_id').value, document.getElementById('wifi_pass_id').value)">Save & Connect</button></td></tr>
|
||||||
</table>
|
</table>
|
||||||
</td><td></td></tr>
|
</td><td></td></tr>
|
||||||
|
|
||||||
</table>
|
</table>
|
||||||
|
|
||||||
<br>
|
<br>
|
||||||
<center>
|
<center>
|
||||||
<button class="btn_collapsible_wifi">Advanced Wi-Fi settings</button>
|
<button class="btn_collapsible_wifi">Advanced Wi-Fi settings</button>
|
||||||
|
|
@ -74,9 +67,7 @@
|
||||||
<tr><td></td><td align="center"><button class="btn_save_w" onclick="setWifiNet(document.getElementById('net_ip_id').value, document.getElementById('net_mask_id').value, document.getElementById('net_gw_id').value, document.getElementById('net_dns_id').value)">Save</button></td></tr>
|
<tr><td></td><td align="center"><button class="btn_save_w" onclick="setWifiNet(document.getElementById('net_ip_id').value, document.getElementById('net_mask_id').value, document.getElementById('net_gw_id').value, document.getElementById('net_dns_id').value)">Save</button></td></tr>
|
||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</body>
|
</body>
|
||||||
|
|
||||||
<script src="scripts.js"></script>
|
<script src="scripts.js"></script>
|
||||||
<script>
|
<script>
|
||||||
setTimeout(function(){GetDataAndPrintTableWiFi();}, 500);
|
setTimeout(function(){GetDataAndPrintTableWiFi();}, 500);
|
||||||
|
|
|
||||||
|
|
@ -46,6 +46,7 @@ function get_data(val) {
|
||||||
document.getElementById('agc_gainid').value = obj.agc_gain;
|
document.getElementById('agc_gainid').value = obj.agc_gain;
|
||||||
document.getElementById("flash_time_value").innerText = obj.flash_time;
|
document.getElementById("flash_time_value").innerText = obj.flash_time;
|
||||||
document.getElementById("aec_value_value").innerText = obj.aec_value;
|
document.getElementById("aec_value_value").innerText = obj.aec_value;
|
||||||
|
document.getElementById('timelapsid').checked = obj.timelaps;
|
||||||
$("#status_hmirror").text((obj.hmirror == "true") ? "On" : "Off");
|
$("#status_hmirror").text((obj.hmirror == "true") ? "On" : "Off");
|
||||||
$("#status_vflip").text((obj.vflip == "true") ? "On" : "Off");
|
$("#status_vflip").text((obj.vflip == "true") ? "On" : "Off");
|
||||||
$("#status_lensc").text((obj.lensc == "true") ? "On" : "Off");
|
$("#status_lensc").text((obj.lensc == "true") ? "On" : "Off");
|
||||||
|
|
@ -59,6 +60,7 @@ function get_data(val) {
|
||||||
$("#status_raw_gama").text((obj.raw_gama == "true") ? "On" : "Off");
|
$("#status_raw_gama").text((obj.raw_gama == "true") ? "On" : "Off");
|
||||||
$("#status_aec2").text((obj.aec2 == "true") ? "On" : "Off");
|
$("#status_aec2").text((obj.aec2 == "true") ? "On" : "Off");
|
||||||
$("#status_gain_ctrl").text((obj.gain_ctrl == "true") ? "On" : "Off");
|
$("#status_gain_ctrl").text((obj.gain_ctrl == "true") ? "On" : "Off");
|
||||||
|
$("#status_timelaps").text((obj.timelaps == "true") ? "On" : "Off");
|
||||||
sliderCheck();
|
sliderCheck();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -100,6 +102,19 @@ function get_data(val) {
|
||||||
$("#wifi_mode").text(obj.wifi_mode);
|
$("#wifi_mode").text(obj.wifi_mode);
|
||||||
$("#sw_new_ver").text(obj.sw_new_ver);
|
$("#sw_new_ver").text(obj.sw_new_ver);
|
||||||
$("#service_ap_ssid").text(obj.service_ap_ssid);
|
$("#service_ap_ssid").text(obj.service_ap_ssid);
|
||||||
|
$("#sd_status").text(obj.sd_status);
|
||||||
|
$("#sd_total").text(obj.sd_total);
|
||||||
|
$("#sd_free_p").text(obj.sd_free_p);
|
||||||
|
$("#sd_used_p").text(obj.sd_used_p);
|
||||||
|
|
||||||
|
var sd_free_prog = document.getElementById("progress_bar_sd_free");
|
||||||
|
sd_free_prog.style.width = obj.sd_free_p + "%";
|
||||||
|
sd_free_prog.innerHTML = obj.sd_free_p + "%";
|
||||||
|
|
||||||
|
var sd_free_prog = document.getElementById("progress_bar_sd_used");
|
||||||
|
sd_free_prog.style.width = obj.sd_used_p + "%";
|
||||||
|
sd_free_prog.innerHTML = obj.sd_used_p + "%";
|
||||||
|
|
||||||
document.getElementById('mdnsid').value = obj.mdns;
|
document.getElementById('mdnsid').value = obj.mdns;
|
||||||
document.getElementById('loglevelid').value = obj.log_level;
|
document.getElementById('loglevelid').value = obj.log_level;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,14 +1,13 @@
|
||||||
body {
|
body {
|
||||||
font-family: sans-serif;
|
font-family: sans-serif;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* index styles */
|
/* index styles */
|
||||||
.p1 {
|
.p1 {
|
||||||
color: #797979;
|
color: #797979;
|
||||||
font: normal normal normal 18px/5px sans-serif;
|
font: normal normal normal 18px/5px sans-serif;
|
||||||
letter-spacing: 0px;
|
letter-spacing: 0px;
|
||||||
}
|
}
|
||||||
.p2 {
|
.p2 {
|
||||||
text-align: left;
|
text-align: left;
|
||||||
font: normal normal bold 14px/20px sans-serif;
|
font: normal normal bold 14px/20px sans-serif;
|
||||||
letter-spacing: 0px;
|
letter-spacing: 0px;
|
||||||
|
|
@ -16,7 +15,7 @@ body {
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
}
|
}
|
||||||
.p3 {
|
.p3 {
|
||||||
text-align: left;
|
text-align: left;
|
||||||
font: normal normal normal 14px/20px sans-serif;
|
font: normal normal normal 14px/20px sans-serif;
|
||||||
letter-spacing: 0px;
|
letter-spacing: 0px;
|
||||||
|
|
@ -24,14 +23,14 @@ body {
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
}
|
}
|
||||||
.p4 {
|
.p4 {
|
||||||
text-align: left;
|
text-align: left;
|
||||||
font: normal normal normal 14px/20px sans-serif;
|
font: normal normal normal 14px/20px sans-serif;
|
||||||
letter-spacing: 0px;
|
letter-spacing: 0px;
|
||||||
color: #808080;
|
color: #808080;
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
}
|
}
|
||||||
.p5 {
|
.p5 {
|
||||||
text-align: center;
|
text-align: center;
|
||||||
font: normal normal bold 14px/20px sans-serif;
|
font: normal normal bold 14px/20px sans-serif;
|
||||||
letter-spacing: 0px;
|
letter-spacing: 0px;
|
||||||
|
|
@ -39,38 +38,38 @@ body {
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
}
|
}
|
||||||
/* NAVIGATION BAR */
|
/* NAVIGATION BAR */
|
||||||
nav {
|
nav {
|
||||||
display: flex;
|
display: flex;
|
||||||
background-color: transparent;
|
background-color: transparent;
|
||||||
}
|
}
|
||||||
.top_bar {
|
.top_bar {
|
||||||
display: flex;
|
display: flex;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
.top_bar li {
|
.top_bar li {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
padding: 5px;
|
padding: 5px;
|
||||||
}
|
}
|
||||||
.top_bar li a {
|
.top_bar li a {
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
}
|
}
|
||||||
.top_bar li a:hover {
|
.top_bar li a:hover {
|
||||||
text-decoration: underline #fa6831;
|
text-decoration: underline #fa6831;
|
||||||
text-underline-position: under;
|
text-underline-position: under;
|
||||||
text-underline-offset: 8px;
|
text-underline-offset: 8px;
|
||||||
text-decoration-thickness: 2px;
|
text-decoration-thickness: 2px;
|
||||||
}
|
}
|
||||||
#links li a.active {
|
#links li a.active {
|
||||||
text-decoration: underline #fa6831;
|
text-decoration: underline #fa6831;
|
||||||
text-underline-position: under;
|
text-underline-position: under;
|
||||||
text-underline-offset: 8px;
|
text-underline-offset: 8px;
|
||||||
text-decoration-thickness: 2px;
|
text-decoration-thickness: 2px;
|
||||||
}
|
}
|
||||||
/* CFG BAR */
|
/* CFG BAR */
|
||||||
cfg {
|
#cfg {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
|
|
@ -79,18 +78,18 @@ cfg {
|
||||||
color: #2A2A2A;
|
color: #2A2A2A;
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
}
|
}
|
||||||
cfg_bar li {
|
#cfg_bar li {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
padding: 14px;
|
padding: 14px;
|
||||||
font-size: 16px;
|
font-size: 16px;
|
||||||
left: 50%;
|
left: 50%;
|
||||||
}
|
}
|
||||||
cfg_bar li a {
|
#cfg_bar li a {
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
color: #212529;
|
color: #212529;
|
||||||
}
|
}
|
||||||
cfg_bar li a:hover {
|
#cfg_bar li a:hover {
|
||||||
color: #fa6831;
|
color: #fa6831;
|
||||||
}
|
}
|
||||||
/* CONTAINER */
|
/* CONTAINER */
|
||||||
|
|
@ -99,33 +98,33 @@ cfg_bar li a:hover {
|
||||||
height: 100%;
|
height: 100%;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
.container_left-half {
|
.container_left-half {
|
||||||
grid-column: 1;
|
grid-column: 1;
|
||||||
display: table-cell;
|
display: table-cell;
|
||||||
vertical-align: middle;
|
vertical-align: middle;
|
||||||
width: 50%;
|
width: 50%;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
}
|
}
|
||||||
.container_right-half {
|
.container_right-half {
|
||||||
grid-column: 2;
|
grid-column: 2;
|
||||||
display: table-cell;
|
display: table-cell;
|
||||||
vertical-align: middle;
|
vertical-align: middle;
|
||||||
width: 50%;
|
width: 50%;
|
||||||
}
|
}
|
||||||
/* CHECKBOX SLIDER */
|
/* CHECKBOX SLIDER */
|
||||||
.switch {
|
.switch {
|
||||||
position: relative;
|
position: relative;
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
width: 30px;
|
width: 30px;
|
||||||
height: 17px;
|
height: 17px;
|
||||||
vertical-align: middle;
|
vertical-align: middle;
|
||||||
}
|
}
|
||||||
.switch input {
|
.switch input {
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
width: 0;
|
width: 0;
|
||||||
height: 0;
|
height: 0;
|
||||||
}
|
}
|
||||||
.checkbox_slider {
|
.checkbox_slider {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
top: 0;
|
top: 0;
|
||||||
|
|
@ -136,7 +135,7 @@ cfg_bar li a:hover {
|
||||||
-webkit-transition: .4s;
|
-webkit-transition: .4s;
|
||||||
transition: .4s;
|
transition: .4s;
|
||||||
}
|
}
|
||||||
.checkbox_slider:before {
|
.checkbox_slider:before {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
content: "";
|
content: "";
|
||||||
height: 13px;
|
height: 13px;
|
||||||
|
|
@ -147,25 +146,25 @@ cfg_bar li a:hover {
|
||||||
-webkit-transition: .4s;
|
-webkit-transition: .4s;
|
||||||
transition: .4s;
|
transition: .4s;
|
||||||
}
|
}
|
||||||
input:checked+.checkbox_slider {
|
input:checked+.checkbox_slider {
|
||||||
background-color: #797979;
|
background-color: #797979;
|
||||||
}
|
}
|
||||||
input:focus+.checkbox_slider {
|
input:focus+.checkbox_slider {
|
||||||
box-shadow: 0 0 1px #797979;
|
box-shadow: 0 0 1px #797979;
|
||||||
}
|
}
|
||||||
input:checked+.checkbox_slider:before {
|
input:checked+.checkbox_slider:before {
|
||||||
-webkit-transform: translateX(13px);
|
-webkit-transform: translateX(13px);
|
||||||
-ms-transform: translateX(13px);
|
-ms-transform: translateX(13px);
|
||||||
transform: translateX(13px);
|
transform: translateX(13px);
|
||||||
}
|
}
|
||||||
.checkbox_slider.round {
|
.checkbox_slider.round {
|
||||||
border-radius: 13px;
|
border-radius: 13px;
|
||||||
}
|
}
|
||||||
.checkbox_slider.round:before {
|
.checkbox_slider.round:before {
|
||||||
border-radius: 50%;
|
border-radius: 50%;
|
||||||
}
|
}
|
||||||
/* BUTTON */
|
/* BUTTON */
|
||||||
.btn {
|
.btn {
|
||||||
width: 306px;
|
width: 306px;
|
||||||
height: 30px;
|
height: 30px;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
|
|
@ -175,12 +174,12 @@ cfg_bar li a:hover {
|
||||||
border-radius: 5px;
|
border-radius: 5px;
|
||||||
border: 1px solid #343a40;
|
border: 1px solid #343a40;
|
||||||
}
|
}
|
||||||
.btn:hover {
|
.btn:hover {
|
||||||
background-color: #FA6831;
|
background-color: #FA6831;
|
||||||
color: white;
|
color: white;
|
||||||
}
|
}
|
||||||
/* BOTTON table */
|
/* BOTTON table */
|
||||||
#botton {
|
#botton {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
background: #F5F5F5 0% 0% no-repeat padding-box;
|
background: #F5F5F5 0% 0% no-repeat padding-box;
|
||||||
|
|
@ -188,21 +187,21 @@ cfg_bar li a:hover {
|
||||||
bottom: 0;
|
bottom: 0;
|
||||||
}
|
}
|
||||||
/* ----- styles config ----- */
|
/* ----- styles config ----- */
|
||||||
.pc1 {
|
.pc1 {
|
||||||
text-align: right;
|
text-align: right;
|
||||||
font: normal normal normal 11px/5px sans-serif;
|
font: normal normal normal 11px/5px sans-serif;
|
||||||
letter-spacing: 0px;
|
letter-spacing: 0px;
|
||||||
color: #797979;
|
color: #797979;
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
}
|
}
|
||||||
.pc2 {
|
.pc2 {
|
||||||
text-align: left;
|
text-align: left;
|
||||||
font: normal normal normal 12px/5px sans-serif;
|
font: normal normal normal 12px/5px sans-serif;
|
||||||
letter-spacing: 0px;
|
letter-spacing: 0px;
|
||||||
color: #000000;
|
color: #000000;
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
}
|
}
|
||||||
.pc3 {
|
.pc3 {
|
||||||
text-align: right;
|
text-align: right;
|
||||||
font: normal normal normal bold 12px/17px sans-serif;
|
font: normal normal normal bold 12px/17px sans-serif;
|
||||||
letter-spacing: 0px;
|
letter-spacing: 0px;
|
||||||
|
|
@ -210,22 +209,22 @@ cfg_bar li a:hover {
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
}
|
}
|
||||||
/* data table */
|
/* data table */
|
||||||
#data {
|
#data {
|
||||||
font-family: Arial, Helvetica, sans-serif;
|
font-family: Arial, Helvetica, sans-serif;
|
||||||
border-collapse: collapse;
|
border-collapse: collapse;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
table-layout: fixed;
|
table-layout: fixed;
|
||||||
}
|
}
|
||||||
#data td, #data th {
|
#data td, #data th {
|
||||||
padding: 8px;
|
padding: 8px;
|
||||||
}
|
}
|
||||||
#data th {
|
#data th {
|
||||||
padding-top: 12px;
|
padding-top: 12px;
|
||||||
padding-bottom: 12px;
|
padding-bottom: 12px;
|
||||||
text-align: left;
|
text-align: left;
|
||||||
}
|
}
|
||||||
/* BUTTON */
|
/* BUTTON */
|
||||||
.btn_save {
|
.btn_save {
|
||||||
width: 69px;
|
width: 69px;
|
||||||
height: 24px;
|
height: 24px;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
|
|
@ -235,12 +234,12 @@ cfg_bar li a:hover {
|
||||||
border-radius: 5px;
|
border-radius: 5px;
|
||||||
border: 1px solid #343a40;
|
border: 1px solid #343a40;
|
||||||
}
|
}
|
||||||
.btn_save:hover {
|
.btn_save:hover {
|
||||||
background-color: #FA6831;
|
background-color: #FA6831;
|
||||||
color: white;
|
color: white;
|
||||||
}
|
}
|
||||||
/* RANGE */
|
/* RANGE */
|
||||||
.slider {
|
.slider {
|
||||||
-webkit-appearance: none;
|
-webkit-appearance: none;
|
||||||
width: 133px;
|
width: 133px;
|
||||||
height: 10px;
|
height: 10px;
|
||||||
|
|
@ -248,7 +247,7 @@ cfg_bar li a:hover {
|
||||||
background: linear-gradient(to right, #d3d3d3 50%, #FA6831 50%);
|
background: linear-gradient(to right, #d3d3d3 50%, #FA6831 50%);
|
||||||
outline: none;
|
outline: none;
|
||||||
}
|
}
|
||||||
.slider::-webkit-slider-thumb {
|
.slider::-webkit-slider-thumb {
|
||||||
-webkit-appearance: none;
|
-webkit-appearance: none;
|
||||||
appearance: none;
|
appearance: none;
|
||||||
width: 16px;
|
width: 16px;
|
||||||
|
|
@ -257,7 +256,7 @@ cfg_bar li a:hover {
|
||||||
background: #FA6831;
|
background: #FA6831;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
.slider::-moz-range-thumb {
|
.slider::-moz-range-thumb {
|
||||||
width: 16px;
|
width: 16px;
|
||||||
height: 16px;
|
height: 16px;
|
||||||
border-radius: 50%;
|
border-radius: 50%;
|
||||||
|
|
@ -265,23 +264,23 @@ cfg_bar li a:hover {
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
/* ----- styles wifi ----- */
|
/* ----- styles wifi ----- */
|
||||||
.w1 {
|
.w1 {
|
||||||
text-align: left;
|
text-align: left;
|
||||||
font: normal normal bold 12px/17px sans-serif;
|
font: normal normal bold 12px/17px sans-serif;
|
||||||
letter-spacing: 0px;
|
letter-spacing: 0px;
|
||||||
color: #2A2A2A;
|
color: #2A2A2A;
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
}
|
}
|
||||||
.w2 {
|
.w2 {
|
||||||
font: normal normal normal 11px/5px sans-serif;
|
font: normal normal normal 11px/5px sans-serif;
|
||||||
letter-spacing: 0px;
|
letter-spacing: 0px;
|
||||||
color: #797979;
|
color: #797979;
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
}
|
}
|
||||||
.w2 span {
|
.w2 span {
|
||||||
vertical-align: middle;
|
vertical-align: middle;
|
||||||
}
|
}
|
||||||
#center_tb {
|
#center_tb {
|
||||||
border-collapse: collapse;
|
border-collapse: collapse;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
table-layout: fixed;
|
table-layout: fixed;
|
||||||
|
|
@ -291,24 +290,24 @@ cfg_bar li a:hover {
|
||||||
margin-left: 30%;
|
margin-left: 30%;
|
||||||
}
|
}
|
||||||
/* wifi_ntw table */
|
/* wifi_ntw table */
|
||||||
#wifi_ntw {
|
#wifi_ntw {
|
||||||
font: normal normal normal 12px/5px sans-serif;
|
font: normal normal normal 12px/5px sans-serif;
|
||||||
border-collapse: collapse;
|
border-collapse: collapse;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
table-layout: fixed;
|
table-layout: fixed;
|
||||||
text-align: left;
|
text-align: left;
|
||||||
}
|
}
|
||||||
#wifi_ntw td {
|
#wifi_ntw td {
|
||||||
border-bottom: 1px solid #ddd;
|
border-bottom: 1px solid #ddd;
|
||||||
padding: 8px;
|
padding: 8px;
|
||||||
}
|
}
|
||||||
#wifi_ntw tr:nth-child(even) {
|
#wifi_ntw tr:nth-child(even) {
|
||||||
background: #F8F8F8 0% 0% no-repeat padding-box;
|
background: #F8F8F8 0% 0% no-repeat padding-box;
|
||||||
}
|
}
|
||||||
#wifi_ntw tr:hover {
|
#wifi_ntw tr:hover {
|
||||||
background-color: #ddd;
|
background-color: #ddd;
|
||||||
}
|
}
|
||||||
#wifi_ntw th {
|
#wifi_ntw th {
|
||||||
background-color: transparent;
|
background-color: transparent;
|
||||||
text-align: left;
|
text-align: left;
|
||||||
font: normal normal bold 13px/11px sans-serif;
|
font: normal normal bold 13px/11px sans-serif;
|
||||||
|
|
@ -316,15 +315,15 @@ cfg_bar li a:hover {
|
||||||
color: #2A2A2A;
|
color: #2A2A2A;
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
}
|
}
|
||||||
#wifi_ntw tr {
|
#wifi_ntw tr {
|
||||||
border-bottom: 1px solid #ccc;
|
border-bottom: 1px solid #ccc;
|
||||||
}
|
}
|
||||||
#wifi_ntw img {
|
#wifi_ntw img {
|
||||||
width: 19px;
|
width: 19px;
|
||||||
height: 12px;
|
height: 12px;
|
||||||
}
|
}
|
||||||
/* BUTTON */
|
/* BUTTON */
|
||||||
.btn_save_w {
|
.btn_save_w {
|
||||||
width: 178px;
|
width: 178px;
|
||||||
height: 24px;
|
height: 24px;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
|
|
@ -334,19 +333,19 @@ cfg_bar li a:hover {
|
||||||
border-radius: 5px;
|
border-radius: 5px;
|
||||||
border: 1px solid #343a40;
|
border: 1px solid #343a40;
|
||||||
}
|
}
|
||||||
.btn_save_w:hover {
|
.btn_save_w:hover {
|
||||||
background-color: #FA6831;
|
background-color: #FA6831;
|
||||||
color: white;
|
color: white;
|
||||||
}
|
}
|
||||||
/* ----- styles auth ----- */
|
/* ----- styles auth ----- */
|
||||||
.pa1 {
|
.pa1 {
|
||||||
text-align: right;
|
text-align: right;
|
||||||
font: normal normal normal 11px/5px sans-serif;
|
font: normal normal normal 11px/5px sans-serif;
|
||||||
letter-spacing: 0px;
|
letter-spacing: 0px;
|
||||||
color: #797979;
|
color: #797979;
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
}
|
}
|
||||||
.pa2 {
|
.pa2 {
|
||||||
text-align: left;
|
text-align: left;
|
||||||
font: normal normal bold 12px/17px sans-serif;
|
font: normal normal bold 12px/17px sans-serif;
|
||||||
letter-spacing: 0px;
|
letter-spacing: 0px;
|
||||||
|
|
@ -360,9 +359,8 @@ cfg_bar li a:hover {
|
||||||
color: #2A2A2A;
|
color: #2A2A2A;
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* BUTTON */
|
/* BUTTON */
|
||||||
.btn_save_a {
|
.btn_save_a {
|
||||||
width: 178px;
|
width: 178px;
|
||||||
height: 24px;
|
height: 24px;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
|
|
@ -372,39 +370,39 @@ cfg_bar li a:hover {
|
||||||
border-radius: 5px;
|
border-radius: 5px;
|
||||||
border: 1px solid #343a40;
|
border: 1px solid #343a40;
|
||||||
}
|
}
|
||||||
.btn_save_a:hover {
|
.btn_save_a:hover {
|
||||||
background-color: #FA6831;
|
background-color: #FA6831;
|
||||||
color: white;
|
color: white;
|
||||||
}
|
}
|
||||||
.toggle-password {
|
.toggle-password {
|
||||||
position: relative;
|
position: relative;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
.toggle-password img {
|
.toggle-password img {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 50%;
|
top: 50%;
|
||||||
right: 0;
|
right: 0;
|
||||||
transform: translateY(-50%);
|
transform: translateY(-50%);
|
||||||
}
|
}
|
||||||
.password-container {
|
.password-container {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
}
|
}
|
||||||
#auth_password.reveal {
|
#auth_password.reveal {
|
||||||
-webkit-text-security: none;
|
-webkit-text-security: none;
|
||||||
}
|
}
|
||||||
#auth_password {
|
#auth_password {
|
||||||
-webkit-text-security: disc;
|
-webkit-text-security: disc;
|
||||||
}
|
}
|
||||||
/* ----- styles system ----- */
|
/* ----- styles system ----- */
|
||||||
.ps1 {
|
.ps1 {
|
||||||
text-align: right;
|
text-align: right;
|
||||||
font: normal normal normal 11px/5px sans-serif;
|
font: normal normal normal 11px/5px sans-serif;
|
||||||
letter-spacing: 0px;
|
letter-spacing: 0px;
|
||||||
color: #797979;
|
color: #797979;
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
}
|
}
|
||||||
.ps2 {
|
.ps2 {
|
||||||
text-align: left;
|
text-align: left;
|
||||||
font: normal normal normal 12px/5px sans-serif;
|
font: normal normal normal 12px/5px sans-serif;
|
||||||
letter-spacing: 0px;
|
letter-spacing: 0px;
|
||||||
|
|
@ -418,38 +416,23 @@ cfg_bar li a:hover {
|
||||||
color: #2A2A2A;
|
color: #2A2A2A;
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
}
|
}
|
||||||
/* data table */
|
|
||||||
#data {
|
|
||||||
font-family: Arial, Helvetica, sans-serif;
|
|
||||||
border-collapse: collapse;
|
|
||||||
width: 100%;
|
|
||||||
table-layout: fixed;
|
|
||||||
}
|
|
||||||
#data td, #data th {
|
|
||||||
padding: 8px;
|
|
||||||
}
|
|
||||||
#data th {
|
|
||||||
padding-top: 12px;
|
|
||||||
padding-bottom: 12px;
|
|
||||||
text-align: left;
|
|
||||||
}
|
|
||||||
/* update table */
|
/* update table */
|
||||||
update {
|
#update {
|
||||||
font-family: Arial, Helvetica, sans-serif;
|
font-family: Arial, Helvetica, sans-serif;
|
||||||
border-collapse: collapse;
|
border-collapse: collapse;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
table-layout: fixed;
|
table-layout: fixed;
|
||||||
}
|
}
|
||||||
#update td, #update th {
|
#update td, #update th {
|
||||||
padding: 8px;
|
padding: 8px;
|
||||||
}
|
}
|
||||||
#update th {
|
#update th {
|
||||||
padding-top: 12px;
|
padding-top: 12px;
|
||||||
padding-bottom: 12px;
|
padding-bottom: 12px;
|
||||||
text-align: left;
|
text-align: left;
|
||||||
}
|
}
|
||||||
/* BUTTON */
|
/* BUTTON */
|
||||||
.btn_update {
|
.btn_update {
|
||||||
width: 178px;
|
width: 178px;
|
||||||
height: 24px;
|
height: 24px;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
|
|
@ -459,34 +442,33 @@ cfg_bar li a:hover {
|
||||||
border-radius: 5px;
|
border-radius: 5px;
|
||||||
border: 1px solid #343a40;
|
border: 1px solid #343a40;
|
||||||
}
|
}
|
||||||
.btn_update:hover {
|
.btn_update:hover {
|
||||||
background-color: #FA6831;
|
background-color: #FA6831;
|
||||||
color: white;
|
color: white;
|
||||||
}
|
}
|
||||||
.underlined-text {
|
.underlined-text {
|
||||||
text-decoration: underline;
|
text-decoration: underline;
|
||||||
color: blue;
|
color: blue;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
/* progress bar*/
|
/* progress bar*/
|
||||||
.progress-container {
|
.progress-container {
|
||||||
width: 100%;
|
width: 30%;
|
||||||
background-color: #ccc;
|
background-color: #ccc;
|
||||||
}
|
}
|
||||||
.progress-bar {
|
.progress-bar {
|
||||||
width: 0px;
|
width: 0px;
|
||||||
height: 15px;
|
height: 15px;
|
||||||
background-color: #FA6831;
|
background-color: #FA6831;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
line-height: 15px;
|
line-height: 15px;
|
||||||
color: white;
|
color: white;
|
||||||
|
padding-left: 3px;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* advanced cam cfg */
|
/* advanced cam cfg */
|
||||||
.content {
|
.content {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.btn_collapsible {
|
.btn_collapsible {
|
||||||
width: 300px;
|
width: 300px;
|
||||||
height: 24px;
|
height: 24px;
|
||||||
|
|
@ -501,12 +483,10 @@ cfg_bar li a:hover {
|
||||||
background-color: #FA6831;
|
background-color: #FA6831;
|
||||||
color: white;
|
color: white;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* advanced wifi cfg */
|
/* advanced wifi cfg */
|
||||||
.content_wifi {
|
.content_wifi {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.btn_collapsible_wifi {
|
.btn_collapsible_wifi {
|
||||||
width: 300px;
|
width: 300px;
|
||||||
height: 24px;
|
height: 24px;
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue