mirror of
https://github.com/eatfishfish/openpilot-server.git
synced 2026-08-22 04:42:32 +00:00
429 lines
13 KiB
HTML
429 lines
13 KiB
HTML
<!Doctype html>
|
|
<html lang="en">
|
|
<head>
|
|
<meta charset="UTF-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=0, minimum-scale=1.0, maximum-scale=1.0">
|
|
<meta name="apple-mobile-web-app-capable" content="yes">
|
|
<meta name="apple-mobile-web-app-status-bar-style" content="black">
|
|
<meta name="format-detection" content="telephone=no">
|
|
<title>openpilot</title>
|
|
<script type="text/javascript">
|
|
window.onload = function() {
|
|
input_text = localStorage.getItem("dongleId");
|
|
document.forms["formDongleId"]["input_text"].value = input_text;
|
|
|
|
strSec = localStorage.getItem("operationTime")
|
|
now = Math.floor(Date.now() / 1000)
|
|
if (now - Number(strSec) < 180)
|
|
{
|
|
document.forms["formDongleId"].style.display="none";
|
|
document.getElementById('btnlist').style.display="";
|
|
}
|
|
}
|
|
</script>
|
|
<!--statistic-->
|
|
<script charset="UTF-8" id="LA_COLLECT" src="//sdk.51.la/js-sdk-pro.min.js"></script>
|
|
<script>LA.init({id:"3IjhGahfKXjHlq3b",ck:"3IjhGahfKXjHlq3b"})</script>
|
|
|
|
<link rel="stylesheet" href="css/form.min.css"/>
|
|
<style>
|
|
.button {
|
|
background-color: #6c9e1d; /* Green */
|
|
border: none;
|
|
color: white;
|
|
height: 45px;
|
|
width: 78px;
|
|
text-align: center;
|
|
text-decoration: none;
|
|
display: inline-block;
|
|
font-size: 16px;
|
|
margin: 4px 2px;
|
|
cursor: pointer;
|
|
-webkit-transition-duration: 0.4s; /* Safari */
|
|
transition-duration: 0.4s;
|
|
}
|
|
|
|
.button1 {
|
|
box-shadow: 0 8px 16px 0 rgba(0,0,0,0.2), 0 6px 20px 0 rgba(0,0,0,0.19);
|
|
}
|
|
|
|
.button2:hover {
|
|
box-shadow: 0 12px 16px 0 rgba(0,0,0,0.24),0 17px 50px 0 rgba(0,0,0,0.19);
|
|
}
|
|
|
|
</style>
|
|
</head>
|
|
<body>
|
|
<div id="subjects">
|
|
<div class="form_ctrl page_head" id="1" title="openpilot">
|
|
<h2>openpilot online</h2>
|
|
</div>
|
|
|
|
<form name="formDongleId" action="/nav/" onsubmit="return login()" method="post">
|
|
<div class="form_ctrl page_text" id="2" title="">
|
|
<p>openpilot is an open source advanced driver assistance system that works on 250+ car models of Toyota, Hyundai, Honda, and many other brands.</p>
|
|
</div>
|
|
|
|
<div name="div_input_text" class="form_ctrl input_text" id="dongleid" title="dongleid">
|
|
<label class="ctrl_title">Dongle ID</label>
|
|
<input type="text" id="dongleid_value" name="input_text" value="" placeholder="Please input dongle ID.Check your c3 device.">
|
|
</div>
|
|
|
|
<div class="form_ctrl form_submit" id="12" title="Login private openpilot server.">
|
|
<label class="ctrl_title">Login private openpilot server.</label>
|
|
<input type="submit" value="Submit" />
|
|
</div>
|
|
</form>
|
|
|
|
<div id="logo">
|
|
<div style="margin-bottom: 5px;"></div>
|
|
</div>
|
|
|
|
<script type="text/javascript">
|
|
function login() {
|
|
var input_text = document.forms["formDongleId"]["input_text"].value;
|
|
uri = '/check/'+input_text
|
|
|
|
const xhr = new XMLHttpRequest();
|
|
xhr.open('GET', uri, true);
|
|
xhr.onload = function() {
|
|
console.log(this.status);
|
|
if (this.status === 200) {
|
|
console.log(this.responseText);
|
|
if (this.responseText==="true")
|
|
{
|
|
localStorage.setItem("dongleId", input_text);
|
|
document.forms["formDongleId"].style.display="none";
|
|
document.getElementById('btnlist').style.display="";
|
|
}else {
|
|
alert("Dongle Id error.");
|
|
}
|
|
}
|
|
};
|
|
xhr.send();
|
|
|
|
return false;
|
|
}
|
|
|
|
function lastActive() {
|
|
var input_text = document.forms["formDongleId"]["input_text"].value;
|
|
uri = '/lastActive/'+input_text
|
|
|
|
const xhr = new XMLHttpRequest();
|
|
xhr.open('GET', uri, true);
|
|
xhr.onload = function() {
|
|
|
|
if (this.status === 200) {
|
|
console.log(this.responseText);
|
|
if (this.responseText.length > 0)
|
|
{
|
|
element = document.getElementById('lastActive')
|
|
element.innerText = "Last active " + this.responseText;
|
|
element.style.display="";
|
|
}
|
|
}
|
|
};
|
|
xhr.send();
|
|
|
|
setTimeout("lastActive()", 1500);
|
|
}
|
|
lastActive();
|
|
|
|
function showNavigation() {
|
|
dongleId = localStorage.getItem("dongleId");
|
|
document.getElementById('nav_home').style.display="";
|
|
document.getElementById('nav_home').action = "/nav/"+ dongleId + "/"
|
|
document.getElementById('nav_work').style.display="";
|
|
document.getElementById('nav_work').action = "/nav/"+ dongleId + "/"
|
|
document.getElementById('set_destination').style.display="";
|
|
document.getElementById('set_destination').action = "/nav/"+ dongleId + "/"
|
|
//document.getElementById('btnlist').style.display="none";
|
|
recordOperationTime()
|
|
}
|
|
|
|
function showlog() {
|
|
dongleId = localStorage.getItem("dongleId");
|
|
document.getElementById('nav_home').style.display="none";
|
|
document.getElementById('nav_work').style.display="none";
|
|
document.getElementById('set_destination').style.display="none";
|
|
|
|
url = "/op/"+ dongleId + "/"
|
|
window.location = url;
|
|
//document.getElementById('btnlist').style.display="none";
|
|
recordOperationTime()
|
|
}
|
|
|
|
function showAmap(){
|
|
url = "/static/amap.html"
|
|
window.location = url;
|
|
}
|
|
|
|
function showVOD(){
|
|
url = "/static/vod.html"
|
|
window.location = url;
|
|
}
|
|
|
|
function showLocation() {
|
|
did = localStorage.getItem("dongleId");
|
|
url = "/replaygps/"+String(did)+"/"
|
|
|
|
|
|
var date = new Date();
|
|
url = url+date.getFullYear()+"-"+(date.getMonth() + 1).toString().padStart(2,'0')+"-"+date.getDate();
|
|
console.log(url)
|
|
window.location = url;
|
|
}
|
|
|
|
function showSentry() {
|
|
did = localStorage.getItem("dongleId");
|
|
url = "http://192.168.1.113:10201/"+String(did)
|
|
console.log(url)
|
|
window.location = url;
|
|
}
|
|
|
|
let h264Ws = null;
|
|
let h264Decoder = null;
|
|
let h264Configured = false;
|
|
let h264Timestamp = 0;
|
|
let h264Frames = 0;
|
|
|
|
function findH264NalUnits(data) {
|
|
const units = [];
|
|
let start = -1;
|
|
let index = 0;
|
|
while (index + 3 < data.length) {
|
|
let prefixLength = 0;
|
|
if (data[index] === 0 && data[index + 1] === 0 && data[index + 2] === 1) {
|
|
prefixLength = 3;
|
|
} else if (index + 4 < data.length &&
|
|
data[index] === 0 && data[index + 1] === 0 &&
|
|
data[index + 2] === 0 && data[index + 3] === 1) {
|
|
prefixLength = 4;
|
|
}
|
|
if (!prefixLength) {
|
|
index += 1;
|
|
continue;
|
|
}
|
|
if (start >= 0) {
|
|
units.push(data.subarray(start, index));
|
|
}
|
|
start = index + prefixLength;
|
|
index = start;
|
|
}
|
|
if (start >= 0 && start < data.length) {
|
|
units.push(data.subarray(start));
|
|
}
|
|
return units;
|
|
}
|
|
|
|
function inspectH264(data) {
|
|
let key = false;
|
|
let codec = null;
|
|
for (const nal of findH264NalUnits(data)) {
|
|
if (!nal.length) {
|
|
continue;
|
|
}
|
|
const type = nal[0] & 0x1f;
|
|
key = key || type === 5;
|
|
if (type === 7 && nal.length >= 4) {
|
|
codec = "avc1." + [nal[1], nal[2], nal[3]]
|
|
.map(function(value) { return value.toString(16).padStart(2, "0"); })
|
|
.join("").toUpperCase();
|
|
}
|
|
}
|
|
return {key: key, codec: codec};
|
|
}
|
|
|
|
function closeH264Decoder() {
|
|
if (h264Decoder) {
|
|
try {
|
|
h264Decoder.close();
|
|
} catch (_) {
|
|
}
|
|
}
|
|
h264Decoder = null;
|
|
h264Configured = false;
|
|
h264Timestamp = 0;
|
|
}
|
|
|
|
function createH264Decoder(camera) {
|
|
if (!("VideoDecoder" in window)) {
|
|
document.getElementById("h264Status").innerText = "WebCodecs H.264 is not supported";
|
|
return false;
|
|
}
|
|
const canvas = document.getElementById("h264Frame");
|
|
const context = canvas.getContext("2d");
|
|
h264Decoder = new VideoDecoder({
|
|
output: function(frame) {
|
|
if (canvas.width !== frame.displayWidth || canvas.height !== frame.displayHeight) {
|
|
canvas.width = frame.displayWidth;
|
|
canvas.height = frame.displayHeight;
|
|
}
|
|
context.drawImage(frame, 0, 0, canvas.width, canvas.height);
|
|
frame.close();
|
|
h264Frames += 1;
|
|
document.getElementById("h264Status").innerText = "Live " + camera + " / " + h264Frames + " frames";
|
|
},
|
|
error: function(error) {
|
|
console.error("H.264 decoder error", error);
|
|
document.getElementById("h264Status").innerText = "H.264 decode error";
|
|
closeH264Decoder();
|
|
}
|
|
});
|
|
return true;
|
|
}
|
|
|
|
function playH264(camera) {
|
|
const dongleId = localStorage.getItem("dongleId");
|
|
if (!dongleId) {
|
|
alert("Please input dongle ID first.");
|
|
return;
|
|
}
|
|
stopH264();
|
|
document.getElementById("h264Panel").style.display = "";
|
|
document.getElementById("h264Status").innerText = "Connecting " + camera;
|
|
h264Frames = 0;
|
|
|
|
const protocol = location.protocol === "https:" ? "wss:" : "ws:";
|
|
h264Ws = new WebSocket(protocol + "//" + location.host + "/h264/stream?dongle_id=" + encodeURIComponent(dongleId) + "&camera=" + encodeURIComponent(camera));
|
|
h264Ws.binaryType = "arraybuffer";
|
|
h264Ws.onopen = function() {
|
|
document.getElementById("h264Status").innerText = "Waiting for H.264 keyframe " + camera;
|
|
};
|
|
h264Ws.onmessage = function(event) {
|
|
const data = new Uint8Array(event.data);
|
|
const info = inspectH264(data);
|
|
if (!h264Configured) {
|
|
if (!info.key || !info.codec || (!h264Decoder && !createH264Decoder(camera))) {
|
|
return;
|
|
}
|
|
try {
|
|
h264Decoder.configure({
|
|
codec: info.codec,
|
|
optimizeForLatency: true,
|
|
hardwareAcceleration: "prefer-hardware"
|
|
});
|
|
h264Configured = true;
|
|
} catch (error) {
|
|
console.error("H.264 decoder configure error", error);
|
|
document.getElementById("h264Status").innerText = "Unsupported H.264 stream";
|
|
closeH264Decoder();
|
|
return;
|
|
}
|
|
}
|
|
try {
|
|
h264Decoder.decode(new EncodedVideoChunk({
|
|
type: info.key ? "key" : "delta",
|
|
timestamp: h264Timestamp,
|
|
data: data
|
|
}));
|
|
h264Timestamp += 50000;
|
|
} catch (error) {
|
|
console.error("H.264 decode submission error", error);
|
|
closeH264Decoder();
|
|
}
|
|
};
|
|
h264Ws.onclose = function() {
|
|
document.getElementById("h264Status").innerText = "Stopped";
|
|
};
|
|
h264Ws.onerror = function() {
|
|
h264Ws.close();
|
|
};
|
|
recordOperationTime();
|
|
}
|
|
|
|
function stopH264() {
|
|
if (h264Ws) {
|
|
h264Ws.onclose = null;
|
|
h264Ws.close();
|
|
h264Ws = null;
|
|
}
|
|
closeH264Decoder();
|
|
const canvas = document.getElementById("h264Frame");
|
|
if (canvas) {
|
|
canvas.getContext("2d").clearRect(0, 0, canvas.width, canvas.height);
|
|
}
|
|
const status = document.getElementById("h264Status");
|
|
if (status) {
|
|
status.innerText = "Stopped";
|
|
}
|
|
}
|
|
|
|
|
|
function recordOperationTime(){
|
|
strSec = Math.floor(Date.now() / 1000)
|
|
localStorage.setItem("operationTime", strSec)
|
|
}
|
|
|
|
</script>
|
|
|
|
<form id="nav_home" action="/nav/" method="post" style="display: none;">
|
|
<div class="form_ctrl input_text">
|
|
<label class="ctrl_title">Home Address</label>
|
|
<input type="text" name="nav_home" placeholder="Please input home address."/>
|
|
</div>
|
|
<br/>
|
|
<div class="form_ctrl form_submit" id="12" title="Input your home address.">
|
|
<input type="submit" value="submit" />
|
|
</div>
|
|
</form>
|
|
|
|
<form id="nav_work" action="/nav/" method="post" style="display: none;">
|
|
<div class="form_ctrl input_text">
|
|
<label class="ctrl_title">Work Address</label>
|
|
<input type="text" name="nav_work" placeholder="Please input work address." />
|
|
</div>
|
|
<br/>
|
|
<div class="form_ctrl form_submit" title="Input your work address.">
|
|
<input type="submit" value="submit" />
|
|
</div>
|
|
</form>
|
|
|
|
<form id="set_destination" action="/nav/" method="post" style="display: none;">
|
|
<div class="form_ctrl input_text">
|
|
<label class="ctrl_title">Set Destination</label>
|
|
<input type="text" name="set_destination" placeholder="Please input destination."/>
|
|
</div>
|
|
<br/>
|
|
<div class="form_ctrl form_submit">
|
|
<input type="submit" value="submit" />
|
|
</div>
|
|
</form>
|
|
|
|
|
|
|
|
|
|
<div id="btnlist" style="display: none;text-align:center" title="" >
|
|
</br></br></br></br>
|
|
<input type="button" value="Vod" class="button button1" onclick = "showVOD();" />
|
|
|
|
<input type="button" value="Location" class="button button1" onclick = "showLocation();" />
|
|
|
|
<input type="button" value="Sentry" class="button button1" onclick = "showSentry();" />
|
|
</br></br>
|
|
<input type="button" value="Log" class="button button1" onclick = "showlog();" />
|
|
|
|
<input type="button" value="AMap" class="button button1" onclick = "showAmap();" />
|
|
|
|
<input type="button" value="Nav" class="button button1" onclick = "showNavigation();" />
|
|
</br></br>
|
|
<input type="button" value="Road Cam" class="button button1" onclick = "playH264('roadCameraState');" />
|
|
|
|
<input type="button" value="Wide Cam" class="button button1" onclick = "playH264('wideRoadCameraState');" />
|
|
|
|
<input type="button" value="Stop Cam" class="button button1" onclick = "stopH264();" />
|
|
</div>
|
|
|
|
</br></br></br></br>
|
|
<div id="h264Panel" style="display:none;text-align:center;margin:0 auto;max-width:960px;">
|
|
<div id="h264Status" style="margin-bottom:8px;">Stopped</div>
|
|
<canvas id="h264Frame" aria-label="H.264 preview" style="width:100%;background:#000;min-height:240px;object-fit:contain;"></canvas>
|
|
</div>
|
|
|
|
<div style="text-align:center"><label style="display: none;" id="lastActive" > </label ></div>
|
|
|
|
|
|
</body>
|
|
</html>
|
|
|