mirror of
https://github.com/rzeldent/esp32cam-rtsp.git
synced 2025-11-14 12:08:02 +00:00
Added additional information in the status overview
This commit is contained in:
108
html/index.html
108
html/index.html
@@ -10,7 +10,7 @@
|
|||||||
|
|
||||||
<body>
|
<body>
|
||||||
<div class="container">
|
<div class="container">
|
||||||
<h1>{{ThingName}}</h1>
|
<h1 class="text-center">{{ThingName}}</h1>
|
||||||
<hr>
|
<hr>
|
||||||
|
|
||||||
{{#ConfigChanged}}
|
{{#ConfigChanged}}
|
||||||
@@ -21,21 +21,83 @@
|
|||||||
</div>
|
</div>
|
||||||
{{/ConfigChanged}}
|
{{/ConfigChanged}}
|
||||||
|
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-sm-6">
|
||||||
<div class="card bg-light mb-3">
|
<div class="card bg-light mb-3">
|
||||||
<h5 class="card-header">ESP32</h5>
|
<h5 class="card-header">ESP32</h5>
|
||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-4">CPU model:</div>
|
<div class="col-4">CPU model:</div>
|
||||||
<div class="col-8">{{ChipModel}}</div>
|
<div class="col-8">{{ChipModel}} rev. {{ChipRevision}}</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-4">CPU speed:</div>
|
<div class="col-4">CPU speed:</div>
|
||||||
<div class="col-8">{{CpuFreqMHz}}Mhz</div>
|
<div class="col-8">{{CpuFreqMHz}} Mhz</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-4">CPU cores:</div>
|
||||||
|
<div class="col-8">{{CpuCores}}</div>
|
||||||
|
</div>
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-4">RAM size:</div>
|
||||||
|
<div class="col-8">{{HeapSize}}</div>
|
||||||
|
</div>
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-4">PSRAM size:</div>
|
||||||
|
<div class="col-8">{{PsRamSize}}</div>
|
||||||
|
</div>
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-4">Flash size:</div>
|
||||||
|
<div class="col-8">{{FlashSize}}</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-sm-6">
|
||||||
|
<div class="card bg-light mb-3">
|
||||||
|
<h5 class="card-header">Diagnostics</h5>
|
||||||
|
<div class="card-body">
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-4">Uptime:</div>
|
||||||
|
<div class="col-8">{{Uptime}}</div>
|
||||||
|
</div>
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-4">RTSP sessions:</div>
|
||||||
|
<div class="col-8">{{NumRTSPSessions}}</div>
|
||||||
|
</div>
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-4">Free heap:</div>
|
||||||
|
<div class="col-8">{{FreeHeap}}</div>
|
||||||
|
</div>
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-4">Max free block:</div>
|
||||||
|
<div class="col-8">{{MaxAllocHeap}}</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-sm-6">
|
||||||
|
<div class="card bg-light mb-3">
|
||||||
|
<h5 class="card-header">Network</h5>
|
||||||
|
<div class="card-body">
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-4">Mac address:</div>
|
<div class="col-4">Mac address:</div>
|
||||||
<div class="col-8">{{MacAddress}}</div>
|
<div class="col-8">{{MacAddress}}</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-4">Wifi mode:</div>
|
||||||
|
<div class="col-8">{{WifiMode}}</div>
|
||||||
|
</div>
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-4">Access point:</div>
|
||||||
|
<div class="col-8">{{AccessPoint}}</div>
|
||||||
|
</div>
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-4">Signal strength:</div>
|
||||||
|
<div class="col-8">{{SignalStrength}} dbm</div>
|
||||||
|
</div>
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-4">IPv4 address:</div>
|
<div class="col-4">IPv4 address:</div>
|
||||||
<div class="col-8">{{IpV4}}</div>
|
<div class="col-8">{{IpV4}}</div>
|
||||||
@@ -46,7 +108,7 @@
|
|||||||
</div>
|
</div>
|
||||||
{{#NetworkState.ApMode}}
|
{{#NetworkState.ApMode}}
|
||||||
<div class="alert alert-warning" role="alert">
|
<div class="alert alert-warning" role="alert">
|
||||||
<p>Not connected to an access point. Please configure!</p>
|
<p>Not connected to an access point. Consider configuring the access point.</p>
|
||||||
</div>
|
</div>
|
||||||
{{/NetworkState.ApMode}}
|
{{/NetworkState.ApMode}}
|
||||||
{{#NetworkState.OnLine}}
|
{{#NetworkState.OnLine}}
|
||||||
@@ -56,7 +118,8 @@
|
|||||||
{{/NetworkState.OnLine}}
|
{{/NetworkState.OnLine}}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-sm-6">
|
||||||
<div class="card bg-light mb-3">
|
<div class="card bg-light mb-3">
|
||||||
<h5 class="card-header">Settings</h5>
|
<h5 class="card-header">Settings</h5>
|
||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
@@ -82,12 +145,7 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<p class="col-4">JPEG quality:</p>
|
<p class="col-4">JPEG quality:</p>
|
||||||
<div class="progress col-8">
|
<div class="col-8">{{JpegQuality}} (0-100)</div>
|
||||||
<div class="progress-bar" role="progressbar" style="width: 25%;" aria-valuenow="{{JpegQuality}}"
|
|
||||||
aria-valuemin="0" aria-valuemax="100">
|
|
||||||
{{JpegQuality}}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
{{#CameraInitialized}}
|
{{#CameraInitialized}}
|
||||||
<div class="alert alert-success" role="alert">
|
<div class="alert alert-success" role="alert">
|
||||||
@@ -99,33 +157,16 @@
|
|||||||
<p>Failed to initialize the camera!</p>
|
<p>Failed to initialize the camera!</p>
|
||||||
<p>Result: {{CameraInitResultText}} ({{CameraInitResult}})</p>
|
<p>Result: {{CameraInitResultText}} ({{CameraInitResult}})</p>
|
||||||
<p>Please check hardware or correct the camera settings and restart.</p>
|
<p>Please check hardware or correct the camera settings and restart.</p>
|
||||||
|
<button type="button" class="btn btn-danger"
|
||||||
|
onclick="location.href='restart'">Restart</button>
|
||||||
</div>
|
</div>
|
||||||
{{/CameraInitialized}}
|
{{/CameraInitialized}}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="card bg-light mb-3">
|
|
||||||
<h5 class="card-header">Diagnostics</h5>
|
|
||||||
<div class="card-body">
|
|
||||||
<div class="row">
|
|
||||||
<div class="col-4">Uptime:</div>
|
|
||||||
<div class="col-8">{{Uptime}}</div>
|
|
||||||
</div>
|
|
||||||
<div class="row">
|
|
||||||
<div class="col-4">RTSP sessions:</div>
|
|
||||||
<div class="col-8">{{NumRTSPSessions}}</div>
|
|
||||||
</div>
|
|
||||||
<div class="row">
|
|
||||||
<div class="col-4">Free heap:</div>
|
|
||||||
<div class="col-8">{{FreeHeap}}b</div>
|
|
||||||
</div>
|
|
||||||
<div class="row">
|
|
||||||
<div class="col-4">Max free block:</div>
|
|
||||||
<div class="col-8">{{MaxAllocHeap}}b</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div class="row">
|
||||||
<div class="card bg-light mb-3">
|
<div class="card bg-light mb-3">
|
||||||
<h5 class="card-header">Camera stream</h5>
|
<h5 class="card-header">Camera stream</h5>
|
||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
@@ -134,8 +175,11 @@
|
|||||||
href="rtsp://{{ThingName}}.local:{{RtspPort}}/mjpeg/1">rtsp://{{ThingName}}.local:{{RtspPort}}/mjpeg/1</a>
|
href="rtsp://{{ThingName}}.local:{{RtspPort}}/mjpeg/1">rtsp://{{ThingName}}.local:{{RtspPort}}/mjpeg/1</a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<button type="button" class="btn btn-warning" onclick="location.href='config'">Settings</button>
|
<div class="d-grid gap-2 col-6 mx-auto">
|
||||||
|
<button type="button" class="btn btn-lg btn-warning" onclick="location.href='config'">Settings</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
@@ -5,19 +5,21 @@
|
|||||||
<meta charset="utf-8">
|
<meta charset="utf-8">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
|
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
|
||||||
<link rel="stylesheet" href="bootstrap.min.css">
|
<link rel="stylesheet" href="bootstrap.min.css">
|
||||||
<meta http-equiv="refresh" content="10;url=/">
|
<meta http-equiv="refresh" content="30;url=/index.html">
|
||||||
<title>{{AppTitle}} v{{AppVersion}}</title>
|
<title>{{AppTitle}} v{{AppVersion}}</title>
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
<div class="container">
|
<div class="container">
|
||||||
<h1>{{ThingName}}</h1>
|
<h1 class="text-center">{{ThingName}}</h1>
|
||||||
<hr>
|
<hr>
|
||||||
|
|
||||||
<div class="jumbotron bg-light">
|
<div class="jumbotron bg-light">
|
||||||
<h1 class="display-4">Restart</h1>
|
<h1 class="display-4 text-center">Restart</h1>
|
||||||
<p class="lead">The device is restarting.</p>
|
<p class="lead text-center">The device is restarting.</p>
|
||||||
<hr class="my-4">
|
<hr class="my-4 ">
|
||||||
<p>In some cases, the device requires a hard reset (power cycle).</p>
|
<p class="text-center">In some cases, the device requires a hard reset (power cycle).</p>
|
||||||
|
<p class="text-center">If this page takes longer than a minute, consider performing a power cycle.</p>
|
||||||
<div class="d-flex justify-content-center">
|
<div class="d-flex justify-content-center">
|
||||||
<div class="spinner-border text-danger" role="status">
|
<div class="spinner-border text-danger" role="status">
|
||||||
<span class="visually-hidden">Restarting...</span>
|
<span class="visually-hidden">Restarting...</span>
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
#include <Arduino.h>
|
#include <Arduino.h>
|
||||||
|
|
||||||
String format_value(float value)
|
String format_value(double value)
|
||||||
{
|
{
|
||||||
if (value == 0.0)
|
if (value == 0.0)
|
||||||
return "0";
|
return "0";
|
||||||
@@ -13,11 +13,15 @@ String format_value(float value)
|
|||||||
// No decimal places
|
// No decimal places
|
||||||
if (value >= 1)
|
if (value >= 1)
|
||||||
return String(value, 0);
|
return String(value, 0);
|
||||||
if (value < 0.001f)
|
if (value < 0.00001)
|
||||||
|
return String(value, 6);
|
||||||
|
if (value < 0.0001)
|
||||||
|
return String(value, 5);
|
||||||
|
if (value < 0.001)
|
||||||
return String(value, 4);
|
return String(value, 4);
|
||||||
if (value < 0.01f)
|
if (value < 0.01)
|
||||||
return String(value, 3);
|
return String(value, 3);
|
||||||
if (value < 0.1f)
|
if (value < 0.1)
|
||||||
return String(value, 2);
|
return String(value, 2);
|
||||||
return String(value, 1);
|
return String(value, 1);
|
||||||
}
|
}
|
||||||
@@ -32,7 +36,7 @@ String format_si(double value, int decimal_places = 2)
|
|||||||
|
|
||||||
auto value_abs = fabs(value);
|
auto value_abs = fabs(value);
|
||||||
if (value_abs < 1E-9)
|
if (value_abs < 1E-9)
|
||||||
return String(value * 1E9, decimal_places) + "p";
|
return String(value * 1E12, decimal_places) + "p";
|
||||||
if (value_abs < 1E-6)
|
if (value_abs < 1E-6)
|
||||||
return String(value * 1E9, decimal_places) + "n";
|
return String(value * 1E9, decimal_places) + "n";
|
||||||
if (value_abs < 1E-3)
|
if (value_abs < 1E-3)
|
||||||
@@ -52,3 +56,17 @@ String format_si(double value, int decimal_places = 2)
|
|||||||
|
|
||||||
return "NaN";
|
return "NaN";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
String format_memory(size_t bytes, int decimal_places = 2)
|
||||||
|
{
|
||||||
|
const char *suffix[] = {"B", "KB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB"};
|
||||||
|
auto val = (double)bytes;
|
||||||
|
auto suffix_index = 0;
|
||||||
|
while (val >= 1024.0)
|
||||||
|
{
|
||||||
|
val /= 1024;
|
||||||
|
suffix_index++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return String(val, decimal_places) + " " + suffix[suffix_index];
|
||||||
|
}
|
||||||
File diff suppressed because one or more lines are too long
37
src/main.cpp
37
src/main.cpp
@@ -8,7 +8,7 @@
|
|||||||
#include <frame_size.h>
|
#include <frame_size.h>
|
||||||
#include <camera_config.h>
|
#include <camera_config.h>
|
||||||
#include <format_duration.h>
|
#include <format_duration.h>
|
||||||
#include <format_si.h>
|
#include <format_number.h>
|
||||||
#include <template_render.h>
|
#include <template_render.h>
|
||||||
#include <html_data.h>
|
#include <html_data.h>
|
||||||
#include <settings.h>
|
#include <settings.h>
|
||||||
@@ -55,15 +55,32 @@ void handle_root()
|
|||||||
if (iotWebConf.handleCaptivePortal())
|
if (iotWebConf.handleCaptivePortal())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
const char *wifi_modes[] = {"NULL", "STA", "AP", "STA+AP"};
|
||||||
|
|
||||||
const template_variable_t substitutions[] = {
|
const template_variable_t substitutions[] = {
|
||||||
|
// Config Changed?
|
||||||
|
{"ConfigChanged", String(config_changed)},
|
||||||
|
// Version / CPU
|
||||||
{"AppTitle", APP_TITLE},
|
{"AppTitle", APP_TITLE},
|
||||||
{"AppVersion", APP_VERSION},
|
{"AppVersion", APP_VERSION},
|
||||||
{"ThingName", iotWebConf.getThingName()},
|
{"ThingName", iotWebConf.getThingName()},
|
||||||
{"ChipModel", ESP.getChipModel()},
|
{"ChipModel", ESP.getChipModel()},
|
||||||
|
{"ChipRevision", String(ESP.getChipRevision())},
|
||||||
{"CpuFreqMHz", String(ESP.getCpuFreqMHz())},
|
{"CpuFreqMHz", String(ESP.getCpuFreqMHz())},
|
||||||
|
{"CpuCores", String(ESP.getChipCores())},
|
||||||
|
{"FlashSize", format_memory(ESP.getFlashChipSize(), 0)},
|
||||||
|
{"HeapSize", format_memory(ESP.getHeapSize())},
|
||||||
|
{"PsRamSize", format_memory(ESP.getPsramSize(), 0)},
|
||||||
|
// Network
|
||||||
{"MacAddress", WiFi.macAddress()},
|
{"MacAddress", WiFi.macAddress()},
|
||||||
|
{"AccessPoint", WiFi.SSID()},
|
||||||
|
{"SignalStrength", String(WiFi.RSSI())},
|
||||||
{"IpV4", WiFi.localIP().toString()},
|
{"IpV4", WiFi.localIP().toString()},
|
||||||
{"IpV6", WiFi.localIPv6().toString()},
|
{"IpV6", WiFi.localIPv6().toString()},
|
||||||
|
{"WifiMode", wifi_modes[WiFi.getMode()]},
|
||||||
|
{"NetworkState.ApMode", String(iotWebConf.getState() == iotwebconf::NetworkState::ApMode)},
|
||||||
|
{"NetworkState.OnLine", String(iotWebConf.getState() == iotwebconf::NetworkState::OnLine)},
|
||||||
|
// Camera
|
||||||
{"CameraType", camera_config_val},
|
{"CameraType", camera_config_val},
|
||||||
{"FrameSize", frame_size_val},
|
{"FrameSize", frame_size_val},
|
||||||
{"FrameDuration", frame_duration_val},
|
{"FrameDuration", frame_duration_val},
|
||||||
@@ -71,17 +88,16 @@ void handle_root()
|
|||||||
{"FrameBufferLocation", psramFound() ? "PSRAM" : "DRAM)"},
|
{"FrameBufferLocation", psramFound() ? "PSRAM" : "DRAM)"},
|
||||||
{"FrameBuffers", frame_buffers_val},
|
{"FrameBuffers", frame_buffers_val},
|
||||||
{"JpegQuality", jpeg_quality_val},
|
{"JpegQuality", jpeg_quality_val},
|
||||||
{"Uptime", String(format_duration(millis() / 1000))},
|
|
||||||
{"FreeHeap", format_si(ESP.getFreeHeap())},
|
|
||||||
{"MaxAllocHeap", format_si(ESP.getMaxAllocHeap())},
|
|
||||||
{"RtspPort", String(RTSP_PORT)},
|
|
||||||
{"ConfigChanged", String(config_changed)},
|
|
||||||
{"NetworkState.ApMode", String(iotWebConf.getState() == iotwebconf::NetworkState::ApMode)},
|
|
||||||
{"NetworkState.OnLine", String(iotWebConf.getState() == iotwebconf::NetworkState::OnLine)},
|
|
||||||
{"CameraInitialized", String(camera_init_result == ESP_OK)},
|
{"CameraInitialized", String(camera_init_result == ESP_OK)},
|
||||||
{"CameraInitResult", "0x" + String(camera_init_result, 16)},
|
{"CameraInitResult", "0x" + String(camera_init_result, 16)},
|
||||||
{"CameraInitResultText", esp_err_to_name(camera_init_result)},
|
{"CameraInitResultText", esp_err_to_name(camera_init_result)},
|
||||||
{"NumRTSPSessions", camera_server != nullptr ? String(camera_server->num_connected()) : "N/A"}};
|
// Diagnostics
|
||||||
|
{"Uptime", String(format_duration(millis() / 1000))},
|
||||||
|
{"FreeHeap", format_memory(ESP.getFreeHeap())},
|
||||||
|
{"MaxAllocHeap", format_memory(ESP.getMaxAllocHeap())},
|
||||||
|
{"NumRTSPSessions", camera_server != nullptr ? String(camera_server->num_connected()) : "N/A"},
|
||||||
|
// URL
|
||||||
|
{"RtspPort", String(RTSP_PORT)}};
|
||||||
|
|
||||||
web_server.sendHeader("Cache-Control", "no-cache, no-store, must-revalidate");
|
web_server.sendHeader("Cache-Control", "no-cache, no-store, must-revalidate");
|
||||||
auto html = template_render(file_data_index_html, substitutions);
|
auto html = template_render(file_data_index_html, substitutions);
|
||||||
@@ -91,7 +107,8 @@ void handle_root()
|
|||||||
void handle_restart()
|
void handle_restart()
|
||||||
{
|
{
|
||||||
log_v("Handle restart");
|
log_v("Handle restart");
|
||||||
if (!config_changed)
|
// If configuration is not changed and camera working, do not allow a restart
|
||||||
|
if (!config_changed && camera_init_result == ESP_OK)
|
||||||
{
|
{
|
||||||
// Redirect to root page
|
// Redirect to root page
|
||||||
web_server.sendHeader("Location", "/", true);
|
web_server.sendHeader("Location", "/", true);
|
||||||
|
|||||||
Reference in New Issue
Block a user