improve status.cgi and multicam tool (#627)

* add irled and night mode testing to status.cgi

* move multicam / update code to show night/day mode

* Create index.js

* Create index.css

* Update S10httpd to reflect move of multicam

* Update index.js

fix broken timer issue (would incorrectly calculate necessary update frequency).
This commit is contained in:
virmaior 2023-10-01 03:44:09 +09:00 committed by gtxaspec
parent 4719cb5634
commit 348ddac0ca
7 changed files with 566 additions and 7 deletions

View File

@ -23,7 +23,7 @@ compose_home()
config) echo '<a class="server_LINK" href="/cgi-bin/config.cgi" >Wz Mini Configuration</a>' >> $target ;;
car) echo '<a class="server_LINK" href="/car.html" >Car Tool</a>' >> $target ;;
current) echo '<a class="server_LINK" href="/cgi-bin/jpeg.cgi" >Current Screen</a>' >> $target ;;
multicam) echo '<a class="server_LINK" href="/multicam.html" >Multi-Cam Viewer</a>' >> $target ;;
multicam) echo '<a class="server_LINK" href="/multicam/" >Multi-Cam Viewer</a>' >> $target ;;
diag) echo '<a class="server_LINK" href="/cgi-bin/diagnostics.cgi" >Diagnostics</a>' >> $target ;;
status) echo '<a class="server_LINK" href="/cgi-bin/status.cgi?test=recording">Check Recording</a>' >> $target ;;
esac

View File

@ -1 +1 @@
Tue Sep 26 01:38:01 AM PDT 2023
Sat Sep 30 11:46:23 AM PDT 2023

View File

@ -2,13 +2,56 @@
# This serves a rudimentary webpage to test different items
. /opt/wz_mini/www/cgi-bin/shared.cgi
gpiopath="/sys/devices/virtual/gpio"
base='/opt/record/';
TZ=$(cat /configs/TZ)
test_gpio()
{
num=$1
#gpiodir=$(cat $gpiopath/gpio$num/direction)
#echo "gpiodir was $gpiodir for $num"
#newdir="in"
#echo $newdir > $gpiopath/gpio$num/direction
##echo "set to in on $num"
myval=$(cat "$gpiopath/gpio$num/value")
#echo "read value $myval for $num"
if [[ "$myval" -eq "0" ]]; then
echo "OFF"
else
echo "ON"
fi
#if [[ "$gpiodir" != "in" ]]; then
# echo $gpiodir > $gpiopath/gpio$num/direction
#fi
}
test_irled()
{
test_gpio 47
echo "IRLED Test"
}
test_night()
{
runmode=$(cat /proc/jz/isp/isp-m0 | grep "Runing Mode" | cut -d ":" -f 2 | sed -e 's/^[[:space:]]*//' )
if [[ "$runmode" = "Night" ]]; then
echo "OK$lb"
else
echo "NG$lb"
fi
echo "Test Night (Running Mode: $runmode)"
}
test_recording()
{
@ -107,5 +150,8 @@ fi
if [[ "$GET_test" = "recording" ]]; then
test_recording
elif [[ "$GET_test" = "irled" ]]; then
test_irled
elif [[ "$GET_test" = "night" ]]; then
test_night
fi

View File

@ -0,0 +1,129 @@
BODY {
--cc_bar_height: 20px;
--cam_height: 20%;
}
.za_images {
display:flex;
flex-direction:column;
flex-wrap:wrap;
height:calc(100% - var(--cc_bar_height));
width:100%;
background-color:#5a8dd8;
}
.za_images .cam_DIV {
border:2px solid blue;
border-radius:5px;
padding:2px;
margin:1px;
position:relative;
}
.za_images .cam_DIV:not(.first_CAM)
{
height:calc(var(--cam_height) - 10px);
text-align:center;
width:17%;
}
.cam_DIV::after {
position:absolute;
bottom:0;
right:0;
color:yellow;
font-size:3vh;
font-weight:bold;
content:attr(cam);
z-index:5;
}
.cam_DIV::before
{
z-index:5;
font-size:3vh;
position:absolute;
top:0;
right:0;
}
.cam_DIV[night=OK]::before {
color: #ccccff;
content:"\263d";
}
.cam_DIV[night=NG]::before {
color:yellow;
content:"\263c";
}
.za_images .first_CAM {
flex:0 0 calc(100% - 40px);
width:75%;
order:0;
width:calc(100% - 17% - 16px);
}
.broken_cam {
border:2px solid red;
}
.active_button {
background:green;
color:white;
}
.inactive_button {
background:grey;
color:black;
}
.full_CAM {
position:absolute;
top:0;
left:0;
width:100% !important;
height:100% !important;
}
.cam_DIV {
position:relative;
}
.za_images IMG {
max-height:100%;
max-width:100%;
position:absolute;
top:0;
left:0;
}
.cam_control {
width:calc(100% - 18px);
position:absolute;
bottom:0;
height:var(--cc_bar_height);
margin:1px;
padding:2px;
background-color:lightgreen;
border-radius:5px;
border:2px solid green;
}
.cam_control BUTTON {
width:calc(30% - 4px);
}
.cam_control DIV {
width:calc(20% - 4px);
display:inline-flex;
text-align:right;
}
@media (orientation: portrait) and (max-device-width: 450px) {
.cam_control {
top:0;
}
.za_images {
flex-direction:row;
flex-wrap:wrap;
margin-top:30px;
}
.za_images .cam_DIV:not(.first_CAM) {
width:calc(50% - 10px);
}
.za_images .cam_DIV.first_CAM {
width:calc(100% - 3px) !important;
flex:0 0 calc(100% - 5px) !important;
height:30%;
}
}

View File

@ -0,0 +1,39 @@
<html>
<head>
<title>Multicam Tool</title>
<meta name="viewport" content="width=device-width, height=device-height,initial-scale=1.0">
<link rel="stylesheet" type="text/css" href="index.css" />
<script src="index.js" ></script>
<script type="text/javascript">
window.onload = function()
{
cam_tool.compose(5,'/z%d/cgi-bin/jpeg.cgi?channel=0','v3');
cam_tool.add_camera(6,'/z7/cgi-bin/get_jpeg.cgi?base=0');
cam_tool.init(800);
};
</script>
</head>
<body>
<div class="za_images" id="za_images" ></div>
<div class="cam_control" >
<button action="start">Live</button>
<button action="pause">Pause</button>
<div id="load_average">0</div>
<div id="load_modes">
<div class="load_mode" mode="auto" >Auto</div>
<div class="load_mode" mode="manual" >Manual:
<input type="number" onchange="cam_tool.update_freq(event);" min="50" value="5000" />
</div>
</div>
<video width="1" height="1" loop style="position:absolute;top:0;right:0" >
<source src="/z1/cgi-bin/jpeg.cgi?channel=0" type="image/jpeg">
Your browser does not support the video tag.
</video>
</body>
</html>

View File

@ -0,0 +1,342 @@
const canWakeLock = () => 'wakeLock' in navigator;
function releaseWakeState() {
if(wakelock) wakelock.release();
wakelock = null;
}
let wakelock;
const requestWakeLock = async () => {
try {
const wakeLock = await navigator.wakeLock.request("screen");
} catch (err) {
// The wake lock request fails - usually system-related, such as low battery.
console.log(`${err.name}, ${err.message}`);
}
};
class helper_dad
{
me;
obj;
context = "";
set_me(x)
{
this.me = x;
}
get_me()
{
return this.me;
}
test()
{
console.log("parent");
}
log(x)
{
console.log( this.context + ' - ' + x)
}
}
class cam_obj extends helper_dad
{
jpeg_url = "";
status_url = false;
cam_id = 0;
set_obj(obj)
{
var me = super.get_me();
me.obj = obj;
me.obj.addEventListener('click',(e) => { me.click(); } );
}
mark_status(test,text)
{
var me = super.get_me();
var test_val = "OFF";
me.log(me.cam_id + ' - ' + text);
if (text.indexOf("ON") !== -1) { test_val = "ON"; }
else if (text.indexOf("OK") !== -1) { test_val = "OK"; }
me.obj.setAttribute(test,test_val);
}
first_init()
{
this.set_me(this);
}
constructor(cam_id,jpeg_url)
{
super();
this.set_me(this);
this.jpeg_url = jpeg_url;
this.cam_id = cam_id;
this.context = "cam " + cam_id;
}
status_test(test_type) {
return false;
}
night_test()
{
var me = super.get_me();
me.status_test('night');
}
irled_test()
{
var me = super.get_me();
me.status_test('irled');
}
recording_test()
{
var me = super.get_me();
me.status_test('recording');
}
unfocus()
{
var me = super.get_me();
me.obj.classList.remove("first_CAM");
me.obj.style.order = me.cam_id;
}
click() {
var me = super.get_me();
if (me.obj.classList.contains('first_CAM')) {
return cam_tool.focus_click(this);
}
for (var i = 0; i < cam_tool.cams.length; i++) {
cam_tool.cams[i].unfocus();
}
me.obj.classList.add("first_CAM");
me.obj.style.order = 0;
}
update()
{
var me = super.get_me();
var i = me.cam_id -1;
var cam1 = cam_tool.feeds[i];
if (cam1.getAttribute('current') == "y") {
cam1.setAttribute('current','n');
var cam = document.querySelector('img.cam_img2[cam="' + (i + 1) + '"]');
cam1.classList.remove('broken_cam');
} else if (document.querySelector('img.cam_img2[cam="' + (i + 1) + '"]').getAttribute('current') == "y")
{
var cam = cam_tool.feeds[i];
document.querySelector('img.cam_img2[cam="' + (i + 1) + '"]').setAttribute('current','n');
} else {
cam1.classList.add('broken_cam');
cam_tool.notify(i,'neither is loaded on camera ');
return false;
}
var load_start = new Date().getTime();
cam.setAttribute('load_start',load_start);
cam.src = cam_tool.feeds[i].src.split("&")[0] + "&load=" + load_start;
}
}
class v3_cam_obj extends cam_obj
{
constructor(cam_id,jpeg_url)
{
super(cam_id,jpeg_url);
super.set_me(this);
this.status_url = jpeg_url.substring(0,this.jpeg_url.lastIndexOf("/")+1) + 'status.cgi';
}
status_test(test_type) {
var me = super.get_me();
fetch(me.status_url + '?test=' + test_type)
.then( (response) => response.text())
.then( (text) => me.mark_status(test_type,text) );
}
}
const cam_tool = {
cam_count : 0,
feed_interval_frequency : 3000,
spacing:false,
feed_interval : false,
tick: 0,
feeds : false,
buttons: [],
loads: [],
cams: [],
load_sum :0,
load_fails:0,
focus_click:function(me) {
me.classList.toggle('full_CAM');
return false;
},
run_mode: function(e) {
e.preventDefault();
e.stopPropagation();
for (var i = 0; i < cam_tool.modes.length; i++) {
cam_tool.modes[i].classList.remove('active_button');
}
e.target.classList.add('active_button');
if (e.target.getAttribute("mode") == 'auto') {
var average = cam_tool.load_sum / cam_tool.loads.length;
var use = parseInt(average * 2 / 10) * 10;
cam_tool.feed_interval_frequency = use;
cam_tool.calc_spacing();
}
if (e.target.getAttribute("mode") == 'manual') {
cam_tool.feed_interval_frequency = document.querySelector("DIV.load_mode[mode='manual'] INPUT").value;
cam_tool.calc_spacing();
}
},
load_cam : function() {
var cam = this.getAttribute('cam');
if (this.classList.contains('cam_img2')) {
var cam_obj = cam_tool.feeds[cam -1];
} else {
var cam_obj = document.querySelector('img.cam_img2[cam="' + cam + '"]');
}
cam_obj.style.zIndex = 1;
cam_obj.setAttribute('current','n');
this.setAttribute('current','y');
this.style.zIndex = 2;
var load_time = new Date().getTime() - this.getAttribute('load_start');
if (load_time < 100000) {
cam_tool.load_sum += load_time;
cam_tool.loads.push(load_time);
var average = cam_tool.load_sum / cam_tool.loads.length;
document.getElementById('load_average').innerHTML = parseInt(average);
}
},
init : function(feed_interval_frequency) {
this.feed_interval_frequency = feed_interval_frequency;
var divs = document.getElementsByClassName('cam_DIV');
for (var i = 0; i < divs.length; i++) {
cam_tool.cams[i].set_obj(divs[i]);
}
cam_tool.feeds = document.getElementsByClassName('cam_img');
for (var i = 0; i < cam_tool.feeds.length; i++) {
cam_tool.feeds[i].addEventListener('load', cam_tool.load_cam);
}
var img2 = document.getElementsByClassName('cam_img2');
for (var i = 0; i < img2.length; i++) {
img2[i].addEventListener('load', cam_tool.load_cam);
}
cam_tool.buttons["start"] = document.querySelector("BUTTON[action='start']");
cam_tool.buttons["pause"] = document.querySelector("BUTTON[action='pause']");
cam_tool.buttons["start"].addEventListener('click',cam_tool.start);
cam_tool.buttons["pause"].addEventListener('click',cam_tool.pause);
cam_tool.modes = document.getElementsByClassName('load_mode');
for (var i = 0; i < cam_tool.modes.length; i++) {
cam_tool.modes[i].addEventListener('click', cam_tool.run_mode);
}
document.querySelector("DIV.load_mode[mode='manual'] INPUT").value = cam_tool.feed_interval_frequency;
cam_tool.cams[0].obj.click();
cam_tool.calc_spacing();
cam_tool.start();
},
notify:function(cam,message) {
console.log("camera " + cam + " - " + message);
},
update: function() {
for (var i= 0; i < cam_tool.feeds.length; i++) {
var current_tick = cam_tool.tick * 10;
var target_tick = cam_tool.spacing * i;
if (((current_tick) % cam_tool.feed_interval_frequency) == (target_tick )) {
cam_tool.cams[i].update();
console.log("i" + i + " tick " + cam_tool.tick + " % interval (" + cam_tool.feed_interval_frequency + ") " + ((current_tick) % cam_tool.feed_interval_frequency));
}
if (((current_tick) % (cam_tool.feed_interval_frequency * 10)) == (target_tick )) {
cam_tool.cams[i].night_test();
}
}
cam_tool.tick++;
},
calc_spacing:function() {
cam_tool.spacing = Math.floor( cam_tool.feed_interval_frequency / (cam_tool.cam_count *10 ) ) * 10;
console.log('updated frequency to ' + cam_tool.spacing );
},
update_freq(event) {
console.log('set frequency to ' + event.target.value);
cam_tool.feed_interval_frequency = event.target.value;
cam_tool.calc_spacing();
},
set_buttons:function(active)
{
for (let key in cam_tool.buttons) {
cam_tool.buttons[key].classList.remove('active_button');
cam_tool.buttons[key].classList.add('inactive_button');
}
cam_tool.buttons[active].classList.add("active_button");
cam_tool.buttons[active].classList.remove("inactive_button");
},
pause: function() {
cam_tool.set_buttons('pause');
clearInterval(cam_tool.feed_interval);
cam_tool.tick = 0;
releaseWakeState();
},
start : function() {
if (cam_tool.feed_interval) { cam_tool.pause(); }
cam_tool.set_buttons('start');
cam_tool.feed_interval = setInterval(cam_tool.update, 10);
requestWakeLock();
},
compose:function(cam_count,url,cam_type='other') {
for (var i = 1; i <= cam_count; i++)
{
this.add_camera(i,url.replace('%d',i) ,cam_type);
}
},
add_camera:function(i,url,cam_type='other')
{
cam_tool.cam_count++;
var zam = document.getElementById("za_images");
var id = document.createElement('DIV');
id.innerHTML = '<img class="cam_img" src="' + url + '" current="y" cam="' + i + '" > <img class="cam_img2" cam="' + i + '" src="" current="n" >';
id.setAttribute('cam',i);
id.className = "cam_DIV";
zam.appendChild(id);
cam_tool.calc_spacing();
if (cam_type == 'v3') {
var nc = new v3_cam_obj(i,url);
} else {
var nc = new cam_obj(i,url);
}
nc.first_init();
cam_tool.cams.push(nc)
}
}

View File

@ -5,7 +5,7 @@ dbf932aa317b95a18cb7df4516086a40 SD_ROOT/wz_mini/www/cgi-bin/cam-bitRate.md
23964b5a0dcf4863e94a4b0fce65e8b2 SD_ROOT/wz_mini/www/cgi-bin/diagnostics.cgi
e17a4aeac39b2dbb5a71d05c4ba0a067 SD_ROOT/wz_mini/www/cgi-bin/WEB_CAM_ENABLE.md
149ec81cc0bf19d7811d58a3b61c04ec SD_ROOT/wz_mini/www/cgi-bin/jpeg.cgi
fb32e872d57f1fe59b652933c06a934a SD_ROOT/wz_mini/www/cgi-bin/status.cgi
9c3f64781075d22bf8f0cb3e10ec8a73 SD_ROOT/wz_mini/www/cgi-bin/status.cgi
78e6caa4aa6a870f7cb58ce71265c2da SD_ROOT/wz_mini/www/cgi-bin/cam-NIGHT_LED_flag.md
42178fc8e88339b884463a1ce9caeaa9 SD_ROOT/wz_mini/www/cgi-bin/GO2RTC_SERVER_ENABLED.md
16394ca5c27c34b68142adb8e47a4434 SD_ROOT/wz_mini/www/cgi-bin/cam-drawBoxSwitch.md
@ -32,6 +32,9 @@ efcb5cd9751e6a7c1730e0116046ae70 SD_ROOT/wz_mini/www/cgi-bin/config.cgi
9e78c01564ae0c2c627f9f5c9ae4df91 SD_ROOT/wz_mini/www/cgi-bin/cam-res.md
9be803465aa134d010c79622bdae44c6 SD_ROOT/wz_mini/www/cgi-bin/cam-watermark_flag.md
042848359c3840f5973baffca2457a5d SD_ROOT/wz_mini/www/cgi-bin/ENABLE_USB_DIRECT.md
0a31310f2b8a824170b97750d525f887 SD_ROOT/wz_mini/www/multicam/index.css
f0df9f6d87b0751ff2a68a30a7c1451b SD_ROOT/wz_mini/www/multicam/index.js
698c24126b58704f3fbdd92b39a390f8 SD_ROOT/wz_mini/www/multicam/index.html
c4846ffbc108bfe26abfc0be9579ee82 SD_ROOT/wz_mini/www/feed.js
5e0bf72e53baf044b3cd89a3f5b120b5 SD_ROOT/wz_mini/www/config.js
e344ffc55222c029c5d324037a5aa1f3 SD_ROOT/wz_mini/www/car/car.js
@ -48,7 +51,7 @@ b77697b15e4d6e32e6e2c8c07cbceee2 SD_ROOT/wz_mini/etc/network.d/S04wireguard
720d337f4fd4cecdf63cfbdf5476cc14 SD_ROOT/wz_mini/etc/network.d/S12remoteaccessory
88cd61106fa526f82a812b02aea23ddc SD_ROOT/wz_mini/etc/network.d/S15v4l2rtspserver
d3ac671f88b6d639926b9f5f9a40da6e SD_ROOT/wz_mini/etc/network.d/S01wlanhw
758921d3c465ea9ecd578639dd33f774 SD_ROOT/wz_mini/etc/network.d/S10httpd
27a4b83bb3aa6d53dcd1b81cd280f397 SD_ROOT/wz_mini/etc/network.d/S10httpd
9969970dc82daa31b41730ee460514b0 SD_ROOT/wz_mini/etc/network.d/S03ipv6
edebe65d895650235f05291618814ebe SD_ROOT/wz_mini/etc/network.d/S08hostname
3f025fd89a69b99b0b2e235faf504930 SD_ROOT/wz_mini/etc/network.d/S17go2rtc
@ -192,7 +195,7 @@ b339aee882a5d1c943ad08e4282ec3fd SD_ROOT/wz_mini/usr/bin/iCamera-dbg
b10bdd54c56d8d8de2a27336f17285fe SD_ROOT/wz_mini/usr/bin/patch_icamera.sh
dafffcc1bd1e721d508400686338ceb8 SD_ROOT/wz_mini/usr/bin/imp_helper.sh
580b1b6e91e72b4a4fef7b21d8954403 SD_ROOT/wz_mini/usr/bin/getSensorType
a063e244bab90ab16fa0781e15250d48 SD_ROOT/wz_mini/usr/bin/app.ver
1116add42cb046e299a67abc0d04c2e5 SD_ROOT/wz_mini/usr/bin/app.ver
4c780f0455481d106d47d89f0ae04ed5 SD_ROOT/wz_mini/lib/uClibc.tar
9afeb088e4cbabbe0b04033b560204d0 SD_ROOT/wz_mini/lib/libimp.so
4100755cb6cc6e3b76da20c7e3690e16 SD_ROOT/wz_mini/lib/libalog.so