- add second pcb board_control, currently copy of previous board - not enough pins -> board_control handle ui send motorcommands via uart board_motorctl handle motors
246 lines
8.2 KiB
JavaScript
246 lines
8.2 KiB
JavaScript
import { Joystick } from 'react-joystick-component';
|
|
import React, { useState} from 'react';
|
|
//import { w3cwebsocket as W3CWebSocket } from "websocket";
|
|
|
|
|
|
|
|
|
|
function App() {
|
|
//declare variables that can be used and updated in html
|
|
const [x_html, setX_html] = useState(0);
|
|
const [y_html, setY_html] = useState(0);
|
|
const [ip, setIp] = useState("10.0.0.66");
|
|
|
|
|
|
|
|
//===============================
|
|
//=========== config ============
|
|
//===============================
|
|
const decimalPlaces = 3;
|
|
const joystickSize = 250; //affects scaling of coordinates and size of joystick on website
|
|
const throttle = 300; //throtthe interval the joystick sends data while moving (ms)
|
|
const toleranceSnapToZeroPer = 20;//percentage of moveable range the joystick can be moved from the axix and value stays at 0
|
|
|
|
|
|
|
|
//-------------------------------------------------
|
|
//------- Scale coordinate, apply tolerance -------
|
|
//-------------------------------------------------
|
|
//function that:
|
|
// - scales the coodinate to a range of -1 to 1
|
|
// - snaps 0 zero for a given tolerance in percent
|
|
// - rounds value do given decimal places
|
|
// - TODO: add threshold it snaps to 1 / -1 (100%) toleranceEnd
|
|
const ScaleCoordinateTolerance = (input) => {
|
|
//calc tolerance threshold and available range
|
|
const tolerance = joystickSize/2 * toleranceSnapToZeroPer/100;
|
|
const range = joystickSize/2 - tolerance;
|
|
let result = 0;
|
|
|
|
//console.log("value:",input,"tolerance:",tolerance," range:",range);
|
|
|
|
//input positive and above 'snap to zero' threshold
|
|
if ( input > 0 && input > tolerance ){
|
|
result = ((input-tolerance)/range).toFixed(decimalPlaces);
|
|
}
|
|
//input negative and blow 'snap to zero' threshold
|
|
else if ( input < 0 && input < -tolerance ){
|
|
result = ((input+tolerance)/range).toFixed(decimalPlaces);
|
|
}
|
|
//inside threshold around zero
|
|
else {
|
|
result = 0;
|
|
}
|
|
|
|
//return result
|
|
//console.log("result:", result, "\n");
|
|
return result;
|
|
}
|
|
|
|
|
|
|
|
//----------------------------------------
|
|
//----------- Scale coordinate -----------
|
|
//----------------------------------------
|
|
//simply scale coordinate from joystick to a value of -1 to 1 without applying any tolerances
|
|
const ScaleCoordinate = (input) => {
|
|
return ( input / (joystickSize/2) ).toFixed(decimalPlaces);
|
|
}
|
|
|
|
|
|
|
|
//-------------------------------------------
|
|
//------- Senda data via POST request -------
|
|
//-------------------------------------------
|
|
//function that sends an object as json to the esp32 with a http post request
|
|
const httpSendObject = async (object_data) => {
|
|
//debug log
|
|
console.log("Sending:", object_data);
|
|
|
|
let json = JSON.stringify(object_data);
|
|
//console.log("json string:", json);
|
|
//remove quotes around numbers:
|
|
//so cJSON parses the values as actua[l numbers than strings
|
|
const regex2 = /"(-?[0-9]+\.{0,1}[0-9]*)"/g
|
|
json = json.replace(regex2, '$1')
|
|
//console.log("json removed quotes:", json);
|
|
|
|
//--- API url / ip ---
|
|
//await fetch("http://10.0.1.69/api/joystick", {
|
|
//await fetch("http://10.0.1.72/api/joystick", {
|
|
await fetch("api/joystick", {
|
|
method: "POST",
|
|
//apparently browser sends OPTIONS request before actual POST request, this OPTIONS request was not handled by esp32
|
|
//also the custom set Access-Control-Allow-Origin header in esp32 url header was not read because of that
|
|
//changed content type to text/plain to workaround this
|
|
//https://stackoverflow.com/questions/1256593/why-am-i-getting-an-options-request-instead-of-a-get-request
|
|
headers: {
|
|
//"Content-Type": "application/json",
|
|
"Content-Type": "text/plain",
|
|
},
|
|
body: json,
|
|
})
|
|
//.then((response) => console.log(response));
|
|
};
|
|
|
|
|
|
|
|
|
|
//---------------------------------------
|
|
//--- function when joystick is moved ---
|
|
//---------------------------------------
|
|
//function that is run for each move event
|
|
//evaluate coordinates and send to esp32
|
|
const handleMove = (e) => {
|
|
//console.log("data from joystick-element X:" + e.x + " Y:" + e.y + " distance:" + e.distance);
|
|
|
|
//--- convert coordinates ---
|
|
//Note: tolerance (snap to zero) now handled by controller -> send raw coordinates
|
|
//const x = ScaleCoordinateTolerance(e.x);
|
|
//const y = ScaleCoordinateTolerance(e.y);
|
|
const x = ScaleCoordinate(e.x);
|
|
const y = ScaleCoordinate(e.y);
|
|
|
|
//create object with necessary data
|
|
const joystick_data={
|
|
x: x,
|
|
y: y
|
|
}
|
|
|
|
//send object with joystick data as json to controller
|
|
httpSendObject(joystick_data);
|
|
|
|
//update variables for html
|
|
setX_html(joystick_data.x);
|
|
setY_html(joystick_data.y);
|
|
};
|
|
|
|
|
|
|
|
//------------------------------------------
|
|
//--- function when joystick is released ---
|
|
//------------------------------------------
|
|
const handleStop = (e) => {
|
|
//create object with all values 0
|
|
const joystick_data={
|
|
x: 0,
|
|
y: 0,
|
|
}
|
|
|
|
//update variables for html
|
|
setX_html(0);
|
|
setY_html(0);
|
|
//send object with joystick data as json to controller
|
|
httpSendObject(joystick_data);
|
|
};
|
|
|
|
|
|
|
|
//=============================
|
|
//======== return html ========
|
|
//=============================
|
|
return (
|
|
<>
|
|
|
|
<div style={{display:'flex', justifyContent:'center', alignItems:'center', height:'100vh'}}>
|
|
<div>
|
|
<div style={{position: 'absolute', top: '0', left: '0', width: '100%'}}>
|
|
<h1 style={{width:'100%', textAlign:'center'}}>Armchair ctl</h1>
|
|
</div>
|
|
<Joystick
|
|
size={joystickSize}
|
|
sticky={false}
|
|
baseColor="#8d0801"
|
|
stickColor="#708d81"
|
|
throttle={throttle}
|
|
move={handleMove}
|
|
stop={handleStop}
|
|
>
|
|
</Joystick>
|
|
<ul>
|
|
<li> x={x_html} </li>
|
|
<li> y={y_html} </li>
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
|
|
{/*
|
|
buttons for changing the api IP
|
|
<div>
|
|
<a>current ip used: {ip}</a>
|
|
<button onClick={() => {setIp("10.0.0.66")}} >10.0.0.66 (BKA-network)</button>
|
|
</div>
|
|
*/}
|
|
|
|
</>
|
|
);
|
|
}
|
|
|
|
export default App;
|
|
|
|
|
|
|
|
|
|
//del, testing, unused code
|
|
//---------------------------------------------
|
|
//--------- Send data via websocket -----------
|
|
//---------------------------------------------
|
|
//moved to normal POST request since websocket connection was unreliable on esp32
|
|
// //create websocket
|
|
// const websocket = useRef(null);
|
|
// //const socketUrl = "ws://" + window.location.host + "/ws-api/servo";
|
|
// const socketUrl = "ws://10.0.1.69/ws-api/joystick";
|
|
// useEffect(() => {
|
|
// websocket.current = new W3CWebSocket(socketUrl);
|
|
// websocket.current.onmessage = (message) => {
|
|
// console.log('got reply! ', message);
|
|
// };
|
|
// websocket.current.onopen = (event) => {
|
|
// console.log('OPENED WEBSOCKET', event);
|
|
// //sendJoystickData(0, 0, 0, 0);
|
|
// websocket.current.send("");
|
|
// };
|
|
// websocket.current.onclose = (event) => {
|
|
// console.log('CLOSED WEBSOCKET', event);
|
|
// };
|
|
// return () => websocket.current.close();
|
|
// }, [])
|
|
//
|
|
//
|
|
//
|
|
// //function for sending joystick data (provided as parameters) to controller via websocket
|
|
// const sendJoystickDataWebsocket = (x, y, radius, angle) => {
|
|
// //debug log
|
|
// console.log("Sending:\n X:" + x + "\n Y:" + y + "\n radius:" + radius + "\n angle: " + angle);
|
|
//
|
|
// websocket.current.send(
|
|
// JSON.stringify({
|
|
// x: x,
|
|
// y: y,
|
|
// radius: radius,
|
|
// angle: angle
|
|
// })
|
|
// );
|
|
// }
|
|
|