$(function(){ init(); }); function parseURL(){ var parameters=location.href.replace(/\?/ig,"&").split("&"); for (var i=0;i<parameters.length;i++) parameters[i]=parameters[i].split("="); for (var i=1;i<parameters.length;i++) { switch (parameters[i][0]) { case "ip": ips_from_url = true; ips_str = parameters[i][1]; ips_str = ips_str.replace(/,|;/gm,'\n'); addrs_str2ips(ips_str); break; } } } function init(){ parseURL(); if (ips.length==0){ ips.push(location.host); } for(var i=0;i<ips.length;i++){ get_system_info(ips[i]); } } var ips = []; var sysinfo = []; function addrs_str2ips(str){ var tmp_ips = str.split("\n"); for(var i=0;i<tmp_ips.length;i++){ str = tmp_ips[i].replace(/,|;|^\s+|\s+$/gm,''); if (str!==""){ ips.push(str); } } } function get_system_info(ip){ $.ajax({ url: "http://"+ip+"/diagnostics.php", ip: ip, success:function(res){ sysinfo.push(res); if (sysinfo.length==ips.length){ analyze_sysinfo(); } } }).fail(function(e){ console.log("ERROR: Failed to get system info for "+this.ip); sysinfo.push(""); }); } function analyze_sysinfo(){ // filter out empty for(var i=0;i<sysinfo.length;i++){ if (sysinfo[i]==""){ sysinfo.splice(i,1); } } for(var i=0;i<sysinfo.length;i++){ var f = $(sysinfo[i]); var tr = [ '<tr>', ' <td>'+f.find("camera").attr('ip')+'</td>', ' <td title=\''+f.find("systime").text()+'\'>'+f.find("systimestamp").text()+'</td>', ' <td>'+f.find("uptime").text()+'</td>', ' <td class=\'right\'>'+parse_temperature(f.find("temperature"))+'</td>', ' <td class=\'right\'>'+parse_storage(f.find("storage"))+'</td>', ' <td class=\'right\'>'+parse_recorder(f.find("recorder").text())+'</td>', ' <td class=\'right\'>'+f.find("master_port").text()+'</td>', ' <td class=\'right\'>'+parse_gps(f.find("gps"))+'</td>', ' <td class=\'right\'></td>', '', '</tr>' ].join('\n'); $("#gen_table").append(tr); var colspan = $("#pars_table").find("th").length; var tr2 = [ '<tr><td style=\'background:rgba(240,240,240,0.5);\' class=\'left\' colspan=\''+colspan+'\'><b>'+f.find("camera").attr('ip')+'</b></td></tr>' ]; var ports = f.find('port'); for(var j=0;j<ports.length;j++){ tr2.push(parse_port(ports[j])); } $("#pars_table").append(tr2.join('\n')); } parse_timestamps(); } function parse_timestamps(){ var thead = []; thead.push('<tr>'); thead.push([ '<th>port</th>', '<th title=\'Frames period matches programmed trigger period\'>period</th>', '<th title=\'Period is not uniform?\'>skipped</th>', '<th title=\'In sync with other ports/cameras\'>sync</th>', '<th title=\'Timestamps data, mouse over\'>data</th>', ].join('\n')); //for(var j=0;j<ports.length;j++){ // thead.push('<th>p</th><th>frame</th><th>timestamp</th>'); //} thead.push('</tr>'); $("#ts_table").append(thead); for(var i=0;i<sysinfo.length;i++){ var f = $(sysinfo[i]); var ports = f.find('port'); var colspan = $("#ts_table").find("th").length; var tr3 = [ '<tr><td style=\'background:rgba(240,240,240,0.5);\' class=\'left\' colspan=\''+colspan+'\'><b>'+f.find("camera").attr('ip')+'</b></td></tr>' ]; tr3.push('<tr>'); for(var j=0;j<ports.length;j++){ tr3.push(pt_parse_port(i,ports[j])); } tr3.push('</tr>'); $("#ts_table").append(tr3.join('\n')); } // analyze, search forware analyze_timestamps(); } // timetamps var BAT = []; // frame numbers var BAF = []; // trig periods, in seconds var BAP = []; var TOTAL_PORTS = 0; var RES = []; function analyze_timestamps(){ // create an array for(var i=0;i<sysinfo.length;i++){ var f = $(sysinfo[i]); var ports = f.find('port'); BAT[i] = []; BAF[i] = []; BAP[i] = []; TOTAL_PORTS += ports.length; for(var j=0;j<ports.length;j++){ var ts = $(ports[j]).find('ts'); BAP[i][j] = pp_calc_trig_period($(ports[j]).find('trig_period').text()); BAT[i][j] = []; BAF[i][j] = []; for(var k=0;k<ts.length;k++){ BAT[i][j][k] = $(ts[k]).text(); BAF[i][j][k] = $(ts[k]).attr('frame'); } } } for(var i=0;i<BAT.length;i++){ for(var j=0;j<BAT[i].length;j++){ for(var k=0;k<BAT[i][j].length;k++){ var res = process_timestamp(BAT[i][j][k],BAF[i][j][k]); } } } for(var i=0;i<BAT.length;i++){ for(var j=0;j<BAT[i].length;j++){ // RES is ready var tmp = process_ts_periods(i,j); } } /* var color_inc = 256/(sysinfo.length*TOTAL_PORTS); for(var ts in RES){ var count = RES[ts].count; var r = (count==1)?200:0; var g = parseInt((count-1)*color_inc); var b = 0; color = "rgba("+r+","+g+","+b+",1)"; //console.log(ts+" "+count+" "+color); $(".timestamps[ts='"+ts+"']").css({ color: color }); } */ } function process_ts_periods(cam_i,port_i){ var tp = BAP[cam_i][port_i]; var tses = BAT[cam_i][port_i]; var fnums = BAF[cam_i][port_i]; var data = []; for(var i=0;i<tses.length;i++){ data.push(fnums[i]+": "+tses[i]); } $("#tses_c"+cam_i+"p"+port_i).find(".ts_data").html("<span title='"+data.join('\n')+"'>data</span>"); var diffs = []; for(var i=0;i<tses.length-1;i++){ diffs.push(Math.round((tses[i+1]-tses[i])*1000000)/1000000); } var count = 0; var all_match = true; for(var i=0;i<diffs.length;i++){ if (tp==diffs[i]){ count++; }else{ if(diffs[i]%tp==0){ all_match = false; } } if (diffs[i]!=diffs[0]){ // fps is not uniform all_match = false; } } //more than half match if (count==diffs.length){ // print ok $("#tses_c"+cam_i+"p"+port_i).find(".ts_period").html("<span title='matches with TRIG_PERIOD'>ok</span>"); }else{ // print error color = "rgb(230,0,0)"; $("#tses_c"+cam_i+"p"+port_i).find(".ts_period").html("<span title='not match with TRIG_PERIOD or some frames are skipped' style='color:"+color+";'>error</span>"); } if (all_match){ $("#tses_c"+cam_i+"p"+port_i).find(".ts_skipped").html("<span title=''>ok</span>"); }else{ color = "rgb(230,0,0)"; $("#tses_c"+cam_i+"p"+port_i).find(".ts_skipped").html("<span title='some frames might be skipped' style='color:"+color+";'>error</span>"); console.log(diffs); } // now check tses var sync = false; for(var i=0;i<tses.length;i++){ if (RES[tses[i]].count==TOTAL_PORTS){ sync = true; } } if (sync){ color = ""; msg = "ok"; }else{ color = "rgb(230,0,0)"; msg = "error"; console.log("Printing timestamps stats:"); console.log(RES); } $("#tses_c"+cam_i+"p"+port_i).find(".ts_sync").html("<span title='Check debug output' style='color:"+color+"'>"+msg+"</span>"); } function process_timestamp(ts,fr){ if (RES[ts]==null){ RES[ts] = {count: 1, frame:[fr]} }else{ RES[ts].count++; RES[ts].frame.push(fr); } } function pt_parse_port(cn,port){ var p = $(port); var pn = p.attr('index'); var mux = p.attr('mux'); var sensors = p.attr('sensor'); var res = [ '<tr id=\'tses_c'+cn+'p'+pn+'\'>', ' <td class=\'ts_port center\'>'+pn+'</td>', ' <td class=\'ts_period center vtop\'></td>', ' <td class=\'ts_skipped center vtop\'></td>', //' <td class=\'center vtop\'>'+pt_parse_framenumbers(cn,pn,p.find('ts'))+'</td>', //' <td class=\'center vtop\'>'+pt_parse_timestamps(cn,pn,p.find('ts'))+'</td>', ' <td class=\'ts_sync\'></td>', ' <td class=\'ts_data\'></td>', '</tr>', ].join('\n'); return res; } function pt_parse_timestamps(cn,pn,ts){ res = []; for(var i=0;i<ts.length;i++){ var frame = $(ts[i]).attr('frame'); var timestamp = $(ts[i]).text(); res.push("<span class='timestamps' ts='"+timestamp+"' fn='"+frame+"'>"+timestamp+"</span>"); } return res.join('<br/>'); } function pt_parse_framenumbers(cn,pn,ts){ res = []; for(var i=0;i<ts.length;i++){ var frame = $(ts[i]).attr('frame'); var timestamp = $(ts[i]).text(); res.push("<span class='framenumbers' ts='"+timestamp+"' fn='"+frame+"'>"+frame+"</span>"); } return res.join('<br/>'); } function parse_port(port){ var p = $(port); var pn = p.attr('index'); var mux = p.attr('mux'); var sensors = p.attr('sensor'); var res = [ '<tr>', ' <td class=\'center\'>'+pn+'</td>', ' <td>'+mux+'</td>', ' <td>'+sensors+'</td>', ' <td class=\'center\'>'+pp_parse_sensor_run(p.find('sensor_run'))+'</td>', ' <td class=\'center\'>'+pp_parse_sensor_run(p.find('compressor_run'))+'</td>', ' <td class=\'center\'>'+pp_parse_format(p.find('color'))+'</td>', ' <td class=\'center\'>'+p.find('quality').text()+'%</td>', ' <td class=\'center\'>'+p.find('woi_width').text()+'x'+p.find('woi_height').text()+'</td>', ' <td class=\'center\'>'+p.find('trig').text()+'</td>', ' <td class=\'center\'>'+p.find('trig_master').text()+'</td>', ' <td class=\'center\'>'+pp_parse_trig_period(p.find('trig_period').text(),p.find('expos').text())+'</td>', ' <td class=\'center\'>'+pp_parse_trig_p(p.find('trig_out').text())+'</td>', ' <td class=\'center\'>'+pp_parse_trig_p(p.find('trig_condition').text())+'</td>', ' <td class=\'right\'>'+pp_parse_expos(p.find('expos').text(),p.find('trig_period').text())+'</td>', ' <td class=\'center\'>'+pp_parse_gain(p.find('gainr').text())+'</td>', ' <td class=\'center\'>'+pp_parse_gain(p.find('gaing').text())+'</td>', ' <td class=\'center\'>'+pp_parse_gain(p.find('gainb').text())+'</td>', ' <td class=\'center\'>'+pp_parse_gain(p.find('gaingb').text())+'</td>', '</tr>' ].join('\n'); return res; } function pp_parse_expos(str,period){ var exp = pp_calc_exposure(str); var per = pp_calc_trig_period(period); /* if (v>100){ color = "rgb(240,160,0)"; } */ var color = ""; if (exp>per*1000){ color = "rgb(230,0,0)"; } var res = "<span style='color:"+color+";'>"+exp+" ms</span>"; return res; } function pp_parse_gain(str){ var v = parseInt(str); v = v/0x10000; color = ""; if (v>5){ color = "rgb(240,160,0)"; } res = "<span style='color:"+color+";'>"+v.toFixed(2)+"</span>"; return res; } function pp_parse_trig_p(str){ var v = parseInt(str); return "0x"+v.toString(16); } function pp_calc_trig_period(str){ var clock = 100000000; var v = parseInt(str); v = v/clock; return v; } function pp_calc_exposure(str){ var v = parseInt(str); v = v/1000; return v; } function pp_parse_trig_period(period,str){ var per = pp_calc_trig_period(period); var exp = pp_calc_exposure(str); var fps = (1/per); if (per<1){ res = (per*1000)+" ms"; }else{ res = per+" s"; } var color = ""; if (exp>per*1000){ color = "rgb(230,0,0)"; } res = "<span style='color:"+color+";'>"+res+" ("+fps+" fps)</span>"; return res; } function pp_parse_format(str){ var fmt = $(str).text(); color = ""; if (fmt==5){ fmt = "jp4"; }else if (fmt==0){ color = "rgb(240,160,0)"; fmt = "jpeg"; }else{ color = "rgb(230,0,0)"; fmt = "else"; } res = "<span style='color:"+color+";'>"+fmt+"</span>"; return res; } function pp_parse_sensor_run(str){ var v = parseInt($(str).text()); if (v==2){ color = "rgb(0,0,0)"; v = "ok"; } if (v==1){ color = "rgb(240,160,0)"; v = "idle"; } if (v==0){ v = "stopped"; color = "rgb(230,0,0)"; } res = "<span style='color:"+color+"'>"+v+"</span>"; return res; } function parse_temperature(str){ temps = ["cpu","b10389","sda","sdb"]; res = []; for(var i=0;i<temps.length;i++){ res.push(color_temperature(str.find(temps[i]).text(),temps[i])); } return res.join(', '); } function color_temperature(str,title){ color = "rgb(0,0,0)"; if (str!="-"){ var t = parseFloat(str); if (t>85){ color = "rgb(230,0,0)"; }else if(t>70){ color = "rgb(240,160,0)"; }else{ color = "rgb(0,150,0)"; } } temp = "<span title='"+title+"' style='color:"+color+";'>"+str+"°</span>"; return temp; } function parse_storage(str){ var devs = str.find("device"); var res = ""; ds = []; for(var i=0;i<devs.length;i++){ var ds_str = ""; var devname = $(devs[i]).attr('name'); var devsize = (parseFloat($(devs[i]).attr('size'))/1024/1024).toFixed(2); var parts = $(devs[i]).find("partition"); ds_str += "<b>"+devname+"("+devsize+"G)</b>: "; if (parts.length==0){ ds_str += "unpartitioned"; }else{ ps = [] for (var j=0;j<parts.length;j++){ pname = $(parts[j]).attr('name'); psize = (parseFloat($(parts[j]).attr('size'))/1024/1024).toFixed(2); ps.push(pname+"("+psize+"G)"); } ds_str += ps.join(', '); } ds.push(ds_str); } res = ds.join('; '); return res; } function parse_recorder(str){ color = "rgb(0,0,0)"; if (str!="on"){ color = "rgb(230,0,0)"; } res = "<span style='color:"+color+";'>"+str+"</span>"; return res; } function parse_gps(str){ var lat = $(str).find("lat"); var lon = $(str).find("lon"); var na = $(str).text(); if ((lat.length==0)||(lon.length==0)){ res = "<span style='color:rgb(230,0,0)'>"+na.toLowerCase()+"</span>"; }else{ res = "<span>"+$(lat).text()+", "+$(lon).text()+"</span>"; } return res; }