Jak jsem přislíbil, tak pokračuji se Serial API, tentokráte využití v obousměrné komunikaci. Po připojení Arduino posílá co deset sekund hlášení o běhu (asynchronně) a při odeslání textového řetězce ho pošle zpět na sériový port.
Důležité upozornění: Soubor HTML je nutno otevřít buď lokálně nebo ze zabezpečeného HTTPS, jinak je Serial API prohlížečem blokováno!

https://www.ctvrtky.info/wp-content/uploads/2025/06/Serial-API-bidirectional.html
Sketch do Arduina
unsigned long previousMillis = 0; unsigned long currentMillis = 0; const long interval = 10000; String instr; void setup() { instr.reserve(800); Serial.begin(115200); } void loop() { currentMillis = millis(); if (currentMillis - previousMillis >= interval) { previousMillis = currentMillis; Serial.print("{\"time\":"); Serial.print(millis()); Serial.println("}"); } if (Serial.available()) { instr = Serial.readStringUntil(char(10)); if (instr != "") { Serial.print("{\"out\":\""); Serial.print(instr); Serial.println("\"}"); } } }
HTML + JS
<!DOCTYPE html> <html> <head> <title>Serial API - bidirectional</title> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"> <meta charset="UTF-8"> </head> <style> body { font-family: Arial, Helvetica, sans-serif; font-size: 0.8em; } #p_out { height: 50vh; overflow: auto; border: 1px solid; } .in { color: green; } .out { color: blue; } .success { color: orange; } div>span { color: black; } </style> <body> <h1>Serial API - bidirectional communication</h1> <select id="sel_baudrate"> <option value="9600">9600 bauds</option> <option value="115200" selected="selected">115200 bauds</option> </select> <button id="btn_open">Open port</button><br><br> <button id="btn_send">Send to port</button> <input type="text" id="text_send" maxlength="19"><br><br> <p id="p_out"></p> <button id="btn_clear">Clear serial monitor</button> <script> select_baudrate = document.getElementById('sel_baudrate'); button_open = document.getElementById('btn_open'); button_send = document.getElementById('btn_send'); text_output = document.getElementById('p_out'); text_output.innerHTML = ""; text_send = document.getElementById('text_send'); button_clear = document.getElementById('btn_clear'); let port; let reader; let inputDone; let outputDone; let inputStream; let outputStream; if (!navigator.serial){ alert("Your browser does not support Serial API or page is opened from insecured HTTP!") }; button_open.addEventListener('click', async () => { try { port = await navigator.serial.requestPort(); const baudRate = select_baudrate.value; await port.open({ baudRate: baudRate }); var d = new Date(); text_output.innerHTML = "<div class='success'><span>" + d.toLocaleTimeString() + "</span><b> Successfully connected!</b>"; let decoder = new TextDecoderStream(); inputDone = port.readable.pipeTo(decoder.writable); inputStream = decoder.readable; reader = inputStream.getReader(); readLoop(text_output); const encoder = new TextEncoderStream(); outputDone = encoder.readable.pipeTo(port.writable); outputStream = encoder.writable; } catch (error) { alert("Error during port opening!"); } }); button_send.addEventListener('click', async () => { writeToStream(text_send.value); text_send.value = ""; text_send.focus(); }); text_send.addEventListener('keyup', function(event) { if (event.key === "Enter") { writeToStream(text_send.value); text_send.value = ""; text_send.focus(); } }); button_clear.addEventListener('click', async () => { text_output.innerHTML = ""; }); async function readLoop(el_output) { while (true) { const { value, done } = await reader.read(); if (value) { try { var o = JSON.parse(value); if (o && typeof o === "object") { var d = new Date(); if (o.time) { el_output.innerHTML += "<div class='in'><span>" + d.toLocaleTimeString() + "</span> Program is running <b>" + o.time / 1000 + ' seconds</b></div>'; } if (o.out) { el_output.innerHTML += "<div class='out'><span>" + d.toLocaleTimeString() + "</span> Answer from arduino <b>" + o.out + "</b></div>"; } el_output.scrollTop = el_output.scrollHeight; } } catch (e) { console.log(value); } } if (done) { reader.releaseLock(); break; } } } async function writeToStream(line) { const writer = outputStream.getWriter(); writer.write(line); writer.write('\n'); writer.releaseLock(); } </script> </body> </html>