Files
openpilot-server/static/index.html
T
2026-08-15 19:17:12 +08:00

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();" />
&nbsp;&nbsp;
<input type="button" value="Location" class="button button1" onclick = "showLocation();" />
&nbsp;&nbsp;
<input type="button" value="Sentry" class="button button1" onclick = "showSentry();" />
</br></br>
<input type="button" value="Log" class="button button1" onclick = "showlog();" />
&nbsp;&nbsp;
<input type="button" value="AMap" class="button button1" onclick = "showAmap();" />
&nbsp;&nbsp;
<input type="button" value="Nav" class="button button1" onclick = "showNavigation();" />
</br></br>
<input type="button" value="Road Cam" class="button button1" onclick = "playH264('roadCameraState');" />
&nbsp;&nbsp;
<input type="button" value="Wide Cam" class="button button1" onclick = "playH264('wideRoadCameraState');" />
&nbsp;&nbsp;
<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>