moniks_bot/client/index.html

215 lines
5.4 KiB
HTML

<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Contrôle du robot</title>
</head>
<body>
<h1>Contrôle du robot sans fils</h1>
<p>
Cette page permet de contrôler le robot depuis un PC portable
connecté au WiFi du robot. Elle est destinée aux personnes n'ayant
pas de smartphone.
</p>
<h2>Paramètres de contrôle</h2>
<p>
Ici vous pourrez paramétrer les contrôles du robot, rentrer son
adresse IP ainsi que lui indiquer la distance à parcourir ou l'angle
de rotation désiré.
</p>
<form class="settings" id="settings">
<label>
<span>Adresse IP du robot</span>
<input
type="text"
name="ip-address"
title="Adresse IP du robot (ex: 192.168.0.1)"
pattern="\d+\.\d+\.\d+\.\d+"
placeholder="192.168.0.0"
required
/>
</label>
<button>Se connecter</button>
</form>
<div class="controls">
<label>
<span>Rotation en degrés</span>
<input
id="rotate-input"
type="number"
title="Rotation en degrés (-360° à 360°)"
min="-360"
max="360"
step="1"
placeholder="90"
/>
</label>
<label>
<span>Distance en cm</span>
<input
id="move-input"
type="number"
title="Distance en cm (-2^31 à 2^31)"
min="-2147483647"
step="1"
max="2147483647"
placeholder="10"
/>
</label>
</div>
<h2>Contrôle</h2>
<p>
Amusez vous ! Pour contrôler le robot, utilisez les flèches
directionnelles pour le diriger et la barre espace pour le stopper.
</p>
</body>
<script type="module">
// Input handlers
document
.querySelector('#move-input')
.addEventListener('change', (event) =>
assignCommands('backward', 'forward', event)
)
document
.querySelector('#rotate-input')
.addEventListener('change', (event) =>
assignCommands('left', 'right', event)
)
// Keyboard handler
document.addEventListener('keydown', (event) => {
const key = event.keyCode
const { command, value } = keyMap[key]
const endpoint = getEndpoint()
sendCommand(endpoint, command, value)
})
// Settings handler
document
.querySelector('#settings')
.addEventListener('submit', async (event) => {
// Don't interrupt event if not form submitting
if (!(event instanceof SubmitEvent)) return true
if (event.target === null) return true
// Disable form sending
event.preventDefault()
const form = new FormData(event.target)
const ipAddress = form.get('ip-address')
if (ipAddress === null) return
const endpoint = `http://${ipAddress}`
await testEndpoint(endpoint)
setEndpoint(endpoint)
})
/**
* A command string.
* @typedef {('forward' | 'backward' | 'left' | 'right' | 'stop')} Command
*/
/**
* Send command to the robot.
*
* @param {string} endpoint Address IP of the robot.
* @param {Command} command Command to send.
* @param {number} value Value of the command if needed.
*
* @returns {Promise<void>}
*/
async function sendCommand(endpoint, command, value) {
const url = new URL(
`/get?command=${command}&value=${value}`,
endpoint
)
const response = await fetch(url)
const text = await response.text()
console.log(text)
}
/**
* Get robot endpoint address.
*
* @returns {string}
*/
function getEndpoint() {
const endpoint = sessionStorage.getItem('robot-endpoint')
if (endpoint === null) {
alert("Aucune adresse IP n'a été renseignée !")
throw new Error('no given ip address')
}
return endpoint
}
/**
* Set robot endpoint address.
*
* @param {string} ip Robot ip.
*
* @returns void
*/
function setEndpoint(ip) {
sessionStorage.setItem('robot-endpoint')
}
/**
* Test connection to endpoint.
*
* @param {string} endpoint Endpoint to test for.
*
* @returns {void}
* @throws {Error} Endpoint unreachable.
*/
async function testEndpoint(endpoint) {
try {
const response = await fetch(endpoint)
if (response.ok) return
} catch (cause) {
alert(`Impossible de joindre l'adresse "${endpoint}"`)
throw new Error(`unable to connect to robot at ${endpoint}`, {
cause,
})
}
}
/**
* Assign a command to an input.
* Do negative command if value < 0 else do positive command.
*
* @param {Command} negativeCommand Command if value < 0.
* @param {Command} positiveCommand Command if value >= 0.
* @param {event} event Event of the input.
*
* @returns {Promise<void>}
*/
function assignCommands(negativeCommand, positiveCommand, event) {
if (event.target === null) return
/** @type {HTMLInputElement} */
const target = event.target
const value = target.valueAsNumber
const endpoint = getEndpoint()
if (value < 0) {
return sendCommand(endpoint, negativeCommand, Math.abs(value))
}
return sendCommand(endpoint, positiveCommand, value)
}
function storeInput() {
ipInput = document.getElementById('ip').value
valueRot = document.getElementById('valueRot').value
valueLength = document.getElementById('valueLength').value
keyMap = {
38: { command: 'forward', value: valueLength },
40: { command: 'backward', value: valueLength },
37: { command: 'left', value: valueRot },
39: { command: 'right', value: valueRot },
32: { command: 'stop', value: 0 },
}
}
</script>
</html>