diff --git a/system/manager/process_config.py b/system/manager/process_config.py
index 84f031371..796e69eef 100644
--- a/system/manager/process_config.py
+++ b/system/manager/process_config.py
@@ -122,7 +122,6 @@ procs = [
# debug procs
NativeProcess("bridge", "cereal/messaging", ["./bridge"], notcar),
PythonProcess("webrtcd", "system.webrtc.webrtcd", or_(and_(livestream, not_(iscar)), notcar)),
- PythonProcess("webjoystick", "tools.bodyteleop.web", notcar),
PythonProcess("joystick", "tools.joystick.joystick_control", and_(joystick, iscar)),
]
diff --git a/tools/bodyteleop/static/index.html b/tools/bodyteleop/static/index.html
deleted file mode 100644
index 48672dbbf..000000000
--- a/tools/bodyteleop/static/index.html
+++ /dev/null
@@ -1,60 +0,0 @@
-
-
-
-
- commabody
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/tools/bodyteleop/static/js/controls.js b/tools/bodyteleop/static/js/controls.js
deleted file mode 100644
index 3a11f78b9..000000000
--- a/tools/bodyteleop/static/js/controls.js
+++ /dev/null
@@ -1,20 +0,0 @@
-const keyVals = {w: 0, a: 0, s: 0, d: 0}
-
-export function getXY() {
- let x = -keyVals.w + keyVals.s
- let y = -keyVals.d + keyVals.a
- return {x, y}
-}
-
-export const handleKeyX = (key, setValue) => {
- if (['w', 'a', 's', 'd'].includes(key)){
- keyVals[key] = setValue;
- let color = "#333";
- if (setValue === 1){
- color = "#e74c3c";
- }
- $("#key-"+key).css('background', color);
- const {x, y} = getXY();
- $("#pos-vals").text(x+","+y);
- }
-};
diff --git a/tools/bodyteleop/static/js/jsmain.js b/tools/bodyteleop/static/js/jsmain.js
deleted file mode 100644
index 0db1dcd9b..000000000
--- a/tools/bodyteleop/static/js/jsmain.js
+++ /dev/null
@@ -1,21 +0,0 @@
-import { handleKeyX } from "./controls.js";
-import { start, stop, lastChannelMessageTime } from "./webrtc.js";
-
-export var pc = null;
-export var dc = null;
-
-document.addEventListener('keydown', (e)=>(handleKeyX(e.key.toLowerCase(), 1)));
-document.addEventListener('keyup', (e)=>(handleKeyX(e.key.toLowerCase(), 0)));
-$(".keys").bind("mousedown touchstart", (e)=>handleKeyX($(e.target).attr('id').replace('key-', ''), 1));
-$(".keys").bind("mouseup touchend", (e)=>handleKeyX($(e.target).attr('id').replace('key-', ''), 0));
-setInterval( () => {
- const dt = new Date().getTime();
- if ((dt - lastChannelMessageTime) > 1000) {
- $(".pre-blob").removeClass('blob');
- $("#battery").text("-");
- $("#ping-time").text('-');
- $("video")[0].load();
- }
-}, 5000);
-
-start(pc, dc);
diff --git a/tools/bodyteleop/static/js/plots.js b/tools/bodyteleop/static/js/plots.js
deleted file mode 100644
index 5327bf71b..000000000
--- a/tools/bodyteleop/static/js/plots.js
+++ /dev/null
@@ -1,53 +0,0 @@
-export const pingPoints = [];
-export const batteryPoints = [];
-
-function getChartConfig(pts, color, title, ymax=100) {
- return {
- type: 'line',
- data: {
- datasets: [{
- label: title,
- data: pts,
- borderWidth: 1,
- borderColor: color,
- backgroundColor: color,
- fill: 'origin'
- }]
- },
- options: {
- scales: {
- x: {
- type: 'time',
- time: {
- unit: 'minute',
- displayFormats: {
- second: 'h:mm a'
- }
- },
- grid: {
- color: '#222', // Grid lines color
- },
- ticks: {
- source: 'data',
- fontColor: 'rgba(255, 255, 255, 1.0)', // Y-axis label color
- }
- },
- y: {
- beginAtZero: true,
- max: ymax,
- grid: {
- color: 'rgba(255, 255, 255, 0.1)', // Grid lines color
- },
- ticks: {
- fontColor: 'rgba(255, 255, 255, 0.7)', // Y-axis label color
- }
- }
- }
- }
- }
-}
-
-const ctxPing = document.getElementById('chart-ping');
-const ctxBattery = document.getElementById('chart-battery');
-export const chartPing = new Chart(ctxPing, getChartConfig(pingPoints, 'rgba(192, 57, 43, 0.7)', 'Controls Ping Time (ms)', 250));
-export const chartBattery = new Chart(ctxBattery, getChartConfig(batteryPoints, 'rgba(41, 128, 185, 0.7)', 'Battery %', 100));
diff --git a/tools/bodyteleop/static/js/webrtc.js b/tools/bodyteleop/static/js/webrtc.js
deleted file mode 100644
index 28bea238e..000000000
--- a/tools/bodyteleop/static/js/webrtc.js
+++ /dev/null
@@ -1,175 +0,0 @@
-import { getXY } from "./controls.js";
-import { pingPoints, batteryPoints, chartPing, chartBattery } from "./plots.js";
-
-export let controlCommandInterval = null;
-export let latencyInterval = null;
-export let lastChannelMessageTime = null;
-
-
-export function offerRtcRequest(sdp, type) {
- return fetch('/offer', {
- body: JSON.stringify({sdp: sdp, type: type}),
- headers: {'Content-Type': 'application/json'},
- method: 'POST'
- });
-}
-
-
-export function pingHeadRequest() {
- return fetch('/', {
- method: 'HEAD'
- });
-}
-
-
-export function createPeerConnection(pc) {
- var config = {
- sdpSemantics: 'unified-plan'
- };
-
- pc = new RTCPeerConnection(config);
-
- // connect video
- pc.addEventListener('track', function(evt) {
- console.log("Adding Tracks!")
- if (evt.track.kind == 'video')
- document.getElementById('video').srcObject = evt.streams[0];
- });
- return pc;
-}
-
-
-export function negotiate(pc) {
- return pc.createOffer({offerToReceiveVideo:true}).then(function(offer) {
- return pc.setLocalDescription(offer);
- }).then(function() {
- return new Promise(function(resolve) {
- if (pc.iceGatheringState === 'complete') {
- resolve();
- }
- else {
- function checkState() {
- if (pc.iceGatheringState === 'complete') {
- pc.removeEventListener('icegatheringstatechange', checkState);
- resolve();
- }
- }
- pc.addEventListener('icegatheringstatechange', checkState);
- }
- });
- }).then(function() {
- var offer = pc.localDescription;
- return offerRtcRequest(offer.sdp, offer.type);
- }).then(function(response) {
- console.log(response);
- return response.json();
- }).then(function(answer) {
- return pc.setRemoteDescription(answer);
- }).catch(function(e) {
- alert(e);
- });
-}
-
-
-function isMobile() {
- let check = false;
- (function(a){if(/(android|bb\d+|meego).+mobile|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge |maemo|midp|mmp|mobile.+firefox|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|series(4|6)0|symbian|treo|up\.(browser|link)|vodafone|wap|windows ce|xda|xiino/i.test(a)||/1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s\-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|\-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw\-(n|u)|c55\/|capi|ccwa|cdm\-|cell|chtm|cldc|cmd\-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc\-s|devi|dica|dmob|do(c|p)o|ds(12|\-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(\-|_)|g1 u|g560|gene|gf\-5|g\-mo|go(\.w|od)|gr(ad|un)|haie|hcit|hd\-(m|p|t)|hei\-|hi(pt|ta)|hp( i|ip)|hs\-c|ht(c(\-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i\-(20|go|ma)|i230|iac( |\-|\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\/)|klon|kpt |kwc\-|kyo(c|k)|le(no|xi)|lg( g|\/(k|l|u)|50|54|\-[a-w])|libw|lynx|m1\-w|m3ga|m50\/|ma(te|ui|xo)|mc(01|21|ca)|m\-cr|me(rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(\-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)\-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|\-([1-8]|c))|phil|pire|pl(ay|uc)|pn\-2|po(ck|rt|se)|prox|psio|pt\-g|qa\-a|qc(07|12|21|32|60|\-[2-7]|i\-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h\-|oo|p\-)|sdk\/|se(c(\-|0|1)|47|mc|nd|ri)|sgh\-|shar|sie(\-|m)|sk\-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h\-|v\-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl\-|tdg\-|tel(i|m)|tim\-|t\-mo|to(pl|sh)|ts(70|m\-|m3|m5)|tx\-9|up(\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|\-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(\-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|yas\-|your|zeto|zte\-/i.test(a.substr(0,4))) check = true;})(navigator.userAgent||navigator.vendor||window.opera);
- return check;
-};
-
-
-export const constraints = {
- video: isMobile()
-};
-
-
-export function start(pc, dc) {
- pc = createPeerConnection(pc);
-
- // add a local video track on mobile
- (constraints.video ? navigator.mediaDevices.getUserMedia(constraints) : Promise.resolve(null))
- .then(function(stream) {
- if (stream) {
- stream.getTracks().forEach(function(track) {
- pc.addTrack(track, stream);
- });
- }
-
- return negotiate(pc);
- })
- .catch(function(err) {
- alert('Could not acquire media: ' + err);
- });
-
- var parameters = {"ordered": true};
- dc = pc.createDataChannel('data', parameters);
- dc.onclose = function() {
- clearInterval(controlCommandInterval);
- clearInterval(latencyInterval);
- };
-
- function sendJoystickOverDataChannel() {
- const {x, y} = getXY();
- var message = JSON.stringify({type: "testJoystick", data: {axes: [x, y], buttons: [false]}})
- dc.send(message);
- }
- function checkLatency() {
- const initialTime = new Date().getTime();
- pingHeadRequest().then(function() {
- const currentTime = new Date().getTime();
- if (Math.abs(currentTime - lastChannelMessageTime) < 1000) {
- const pingtime = currentTime - initialTime;
- pingPoints.push({'x': currentTime, 'y': pingtime});
- if (pingPoints.length > 1000) {
- pingPoints.shift();
- }
- chartPing.update();
- $("#ping-time").text((pingtime) + "ms");
- }
- })
- }
- dc.onopen = function() {
- controlCommandInterval = setInterval(sendJoystickOverDataChannel, 50);
- latencyInterval = setInterval(checkLatency, 1000);
- sendJoystickOverDataChannel();
- };
-
- const textDecoder = new TextDecoder();
- var carStaterIndex = 0;
- dc.onmessage = function(evt) {
- const text = textDecoder.decode(evt.data);
- const msg = JSON.parse(text);
- if (carStaterIndex % 100 == 0 && msg.type === 'carState') {
- const batteryLevel = Math.round(msg.data.fuelGauge * 100);
- $("#battery").text(batteryLevel + "%");
- batteryPoints.push({'x': new Date().getTime(), 'y': batteryLevel});
- if (batteryPoints.length > 1000) {
- batteryPoints.shift();
- }
- chartBattery.update();
- }
- carStaterIndex += 1;
- lastChannelMessageTime = new Date().getTime();
- $(".pre-blob").addClass('blob');
- };
-}
-
-
-export function stop(pc, dc) {
- if (dc) {
- dc.close();
- }
- if (pc.getTransceivers) {
- pc.getTransceivers().forEach(function(transceiver) {
- if (transceiver.stop) {
- transceiver.stop();
- }
- });
- }
- pc.getSenders().forEach(function(sender) {
- sender.track.stop();
- });
- setTimeout(function() {
- pc.close();
- }, 500);
-}
diff --git a/tools/bodyteleop/static/main.css b/tools/bodyteleop/static/main.css
deleted file mode 100644
index 79fe8052f..000000000
--- a/tools/bodyteleop/static/main.css
+++ /dev/null
@@ -1,178 +0,0 @@
-body {
- background: #333 !important;
- color: #fff !important;
- display: flex;
- justify-content: center;
- align-items: start;
-}
-
-p {
- margin: 0px !important;
-}
-
-i {
- font-style: normal;
-}
-
-.small {
- font-size: 1em !important
-}
-
-.jumbo {
- font-size: 8rem;
-}
-
-
-@media (max-width: 600px) {
- .small {
- font-size: 0.5em !important
- }
- .jumbo {
- display: none;
- }
-
-}
-
-#main {
- display: flex;
- flex-direction: column;
- align-content: center;
- justify-content: center;
- align-items: center;
- font-size: 30px;
- width: 100%;
- max-width: 1200px;
-}
-
-video {
- width: 95%;
-}
-
-.pre-blob {
- display: flex;
- background: #333;
- border-radius: 50%;
- margin: 10px;
- height: 45px;
- width: 45px;
- justify-content: center;
- align-items: center;
- font-size: 1rem;
-}
-
-.blob {
- background: rgba(231, 76, 60,1.0);
- box-shadow: 0 0 0 0 rgba(231, 76, 60,1.0);
- animation: pulse 2s infinite;
-}
-
-@keyframes pulse {
- 0% {
- box-shadow: 0 0 0 0px rgba(192, 57, 43, 1);
- }
- 100% {
- box-shadow: 0 0 0 20px rgba(192, 57, 43, 0);
- }
-}
-
-
-.icon-sup-panel {
- display: flex;
- flex-direction: row;
- justify-content: space-around;
- align-items: center;
- background: #222;
- border-radius: 10px;
- padding: 5px;
- margin: 5px 0px 5px 0px;
-}
-
-.icon-sub-panel {
- display: flex;
- flex-direction: column;
- justify-content: space-between;
- align-items: center;
-}
-
-#icon-panel {
- display: flex;
- width: 100%;
- justify-content: space-between;
- margin-top: 5px;
-}
-
-.icon-sub-sub-panel {
- display: flex;
- flex-direction: row;
-}
-
-.keys, #key-val {
- background: #333;
- padding: 2rem;
- margin: 5px;
- color: #fff;
- display: flex;
- justify-content: center;
- align-items: center;
- border-radius: 10px;
- cursor: pointer;
-}
-
-#key-val {
- pointer-events: none;
- background: #fff;
- color: #333;
- line-height: 1;
- font-size: 20px;
- flex-direction: column;
-}
-
-.wasd-row {
- display: flex;
- flex-direction: row;
- justify-content: center;
- align-items: stretch;
-}
-
-#wasd {
- margin: 5px 0px 5px 0px;
- background: #222;
- border-radius: 10px;
- width: 100%;
- padding: 20px;
- display: flex;
- flex-direction: row;
- justify-content: space-around;
- align-items: stretch;
-
- user-select: none;
- -webkit-touch-callout: none;
- -webkit-user-select: none;
- -khtml-user-select: none;
- -moz-user-select: none;
- -ms-user-select: none;
- touch-action: manipulation;
-}
-
-.panel {
- display: flex;
- justify-content: center;
- margin: 5px 0px 5px 0px !important;
- background: #222;
- border-radius: 10px;
- width: 100%;
- padding: 10px;
-}
-
-#ping-time, #battery {
- font-size: 25px;
-}
-
-#stop {
- display: none;
-}
-
-.details {
- display: flex;
- padding: 0px 10px 0px 10px;
-}
diff --git a/tools/bodyteleop/static/poster.png b/tools/bodyteleop/static/poster.png
deleted file mode 100644
index 2f2b02dd8..000000000
--- a/tools/bodyteleop/static/poster.png
+++ /dev/null
@@ -1,3 +0,0 @@
-version https://git-lfs.github.com/spec/v1
-oid sha256:8740da2be7faac198b5e10780c646166056a76ebbe3d64499e0cdc49280c8a4f
-size 8297
diff --git a/tools/bodyteleop/web.py b/tools/bodyteleop/web.py
deleted file mode 100644
index d357561b2..000000000
--- a/tools/bodyteleop/web.py
+++ /dev/null
@@ -1,86 +0,0 @@
-import dataclasses
-import json
-import logging
-import os
-import ssl
-import subprocess
-
-from aiohttp import web
-from aiohttp import ClientSession
-
-from openpilot.common.basedir import BASEDIR
-from openpilot.system.webrtc.webrtcd import StreamRequestBody
-from openpilot.common.params import Params
-
-logger = logging.getLogger("bodyteleop")
-logging.basicConfig(level=logging.INFO)
-
-TELEOPDIR = f"{BASEDIR}/tools/bodyteleop"
-WEBRTCD_HOST, WEBRTCD_PORT = "localhost", 5001
-
-
-## SSL
-def create_ssl_cert(cert_path: str, key_path: str):
- try:
- proc = subprocess.run(f'openssl req -x509 -newkey rsa:4096 -nodes -out {cert_path} -keyout {key_path} \
- -days 365 -subj "/C=US/ST=California/O=commaai/OU=comma body"',
- capture_output=True, shell=True)
- proc.check_returncode()
- except subprocess.CalledProcessError as ex:
- raise ValueError(f"Error creating SSL certificate:\n[stdout]\n{proc.stdout.decode()}\n[stderr]\n{proc.stderr.decode()}") from ex
-
-
-def create_ssl_context():
- cert_path = os.path.join(TELEOPDIR, "cert.pem")
- key_path = os.path.join(TELEOPDIR, "key.pem")
- if not os.path.exists(cert_path) or not os.path.exists(key_path):
- logger.info("Creating certificate...")
- create_ssl_cert(cert_path, key_path)
- else:
- logger.info("Certificate exists!")
- ssl_context = ssl.SSLContext(protocol=ssl.PROTOCOL_TLS_SERVER)
- ssl_context.load_cert_chain(cert_path, key_path)
-
- return ssl_context
-
-## ENDPOINTS
-async def index(request: 'web.Request'):
- with open(os.path.join(TELEOPDIR, "static", "index.html")) as f:
- content = f.read()
- return web.Response(content_type="text/html", text=content)
-
-
-async def ping(request: 'web.Request'):
- return web.Response(text="pong")
-
-
-async def offer(request: 'web.Request'):
- params = await request.json()
- body = StreamRequestBody(params["sdp"], "driver", ["testJoystick"], ["carState"])
- body_json = json.dumps(dataclasses.asdict(body))
-
- logger.info("Sending offer to webrtcd...")
- webrtcd_url = f"http://{WEBRTCD_HOST}:{WEBRTCD_PORT}/stream"
- async with ClientSession() as session, session.post(webrtcd_url, data=body_json) as resp:
- assert resp.status == 200
- answer = await resp.json()
- return web.json_response(answer)
-
-
-def main():
- # Enable joystick debug mode
- Params().put_bool("JoystickDebugMode", True, block=True)
-
- # App needs to be HTTPS for WebRTC to work on the browser
- ssl_context = create_ssl_context()
-
- app = web.Application()
- app.router.add_get("/", index)
- app.router.add_get("/ping", ping, allow_head=True)
- app.router.add_post("/offer", offer)
- app.router.add_static('/static', os.path.join(TELEOPDIR, 'static'))
- web.run_app(app, access_log=None, host="0.0.0.0", port=5000, ssl_context=ssl_context)
-
-
-if __name__ == "__main__":
- main()