From 348ddac0caa3f5619add0c49649e053f5c6d39df Mon Sep 17 00:00:00 2001 From: virmaior <70625876+virmaior@users.noreply.github.com> Date: Sun, 1 Oct 2023 03:44:09 +0900 Subject: [PATCH] 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). --- SD_ROOT/wz_mini/etc/network.d/S10httpd | 2 +- SD_ROOT/wz_mini/usr/bin/app.ver | 2 +- SD_ROOT/wz_mini/www/cgi-bin/status.cgi | 50 +++- SD_ROOT/wz_mini/www/multicam/index.css | 129 +++++++++ SD_ROOT/wz_mini/www/multicam/index.html | 39 +++ SD_ROOT/wz_mini/www/multicam/index.js | 342 ++++++++++++++++++++++++ file.chk | 9 +- 7 files changed, 566 insertions(+), 7 deletions(-) create mode 100644 SD_ROOT/wz_mini/www/multicam/index.css create mode 100644 SD_ROOT/wz_mini/www/multicam/index.html create mode 100644 SD_ROOT/wz_mini/www/multicam/index.js diff --git a/SD_ROOT/wz_mini/etc/network.d/S10httpd b/SD_ROOT/wz_mini/etc/network.d/S10httpd index d745a7b..c0235f0 100644 --- a/SD_ROOT/wz_mini/etc/network.d/S10httpd +++ b/SD_ROOT/wz_mini/etc/network.d/S10httpd @@ -23,7 +23,7 @@ compose_home() config) echo 'Wz Mini Configuration' >> $target ;; car) echo 'Car Tool' >> $target ;; current) echo 'Current Screen' >> $target ;; - multicam) echo 'Multi-Cam Viewer' >> $target ;; + multicam) echo 'Multi-Cam Viewer' >> $target ;; diag) echo 'Diagnostics' >> $target ;; status) echo 'Check Recording' >> $target ;; esac diff --git a/SD_ROOT/wz_mini/usr/bin/app.ver b/SD_ROOT/wz_mini/usr/bin/app.ver index 6ba35a3..451cf82 100644 --- a/SD_ROOT/wz_mini/usr/bin/app.ver +++ b/SD_ROOT/wz_mini/usr/bin/app.ver @@ -1 +1 @@ -Tue Sep 26 01:38:01 AM PDT 2023 +Sat Sep 30 11:46:23 AM PDT 2023 diff --git a/SD_ROOT/wz_mini/www/cgi-bin/status.cgi b/SD_ROOT/wz_mini/www/cgi-bin/status.cgi index c2e8220..98caa9d 100644 --- a/SD_ROOT/wz_mini/www/cgi-bin/status.cgi +++ b/SD_ROOT/wz_mini/www/cgi-bin/status.cgi @@ -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 - diff --git a/SD_ROOT/wz_mini/www/multicam/index.css b/SD_ROOT/wz_mini/www/multicam/index.css new file mode 100644 index 0000000..a18e43a --- /dev/null +++ b/SD_ROOT/wz_mini/www/multicam/index.css @@ -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%; + } +} diff --git a/SD_ROOT/wz_mini/www/multicam/index.html b/SD_ROOT/wz_mini/www/multicam/index.html new file mode 100644 index 0000000..28456c1 --- /dev/null +++ b/SD_ROOT/wz_mini/www/multicam/index.html @@ -0,0 +1,39 @@ + + +Multicam Tool + + + + + + +
+
+ + +
0
+
+
Auto
+
Manual: + +
+
+ + + + + diff --git a/SD_ROOT/wz_mini/www/multicam/index.js b/SD_ROOT/wz_mini/www/multicam/index.js new file mode 100644 index 0000000..706e5fb --- /dev/null +++ b/SD_ROOT/wz_mini/www/multicam/index.js @@ -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 = ' '; + 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) + } + +} diff --git a/file.chk b/file.chk index fdac45c..4eb0a15 100644 --- a/file.chk +++ b/file.chk @@ -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