2022-06-08 15:58:32 +08:00
|
|
|
'use strict';
|
|
|
|
import {Component, h, html, render, useEffect, useState, useRef} from './preact.min.js';
|
|
|
|
|
|
|
|
const Message = m => html`<span
|
|
|
|
style="color: ${m.message.uart ? '#444' : '#373'};">
|
|
|
|
${m.message.data}
|
|
|
|
</span>`;
|
|
|
|
|
|
|
|
const App = function(props) {
|
2022-06-18 11:25:05 +08:00
|
|
|
const [cfg, setCfg] = useState({tcp: {}, ws: {}, mqtt: {}});
|
2022-06-08 15:58:32 +08:00
|
|
|
const [messages, setMessages] = useState([]);
|
|
|
|
const [connected, setConnected] = useState(false);
|
2022-06-18 11:25:05 +08:00
|
|
|
const [txt, setTxt] = useState('');
|
2022-06-08 15:58:32 +08:00
|
|
|
const [ws, setWs] = useState(null);
|
2022-06-18 11:25:05 +08:00
|
|
|
const [rx, setRx] = useState('');
|
|
|
|
const [tx, setTx] = useState('');
|
|
|
|
const [baud, setBaud] = useState('');
|
|
|
|
const [tcpport, setTcpport] = useState(4001);
|
|
|
|
const [wsport, setWsport] = useState(4002);
|
|
|
|
const [mqtt, setMqtt] = useState('');
|
2022-06-08 15:58:32 +08:00
|
|
|
|
2022-06-18 11:25:05 +08:00
|
|
|
// const tcp_port = cfg.tcp.split(':')[2] || 4001;
|
|
|
|
// const ws_port = cfg.ws.split(':')[2] || 4002;
|
2022-06-08 15:58:32 +08:00
|
|
|
|
2022-06-18 11:25:05 +08:00
|
|
|
const refresh = () => fetch('/api/config/get').then(r => r.json()).then(r => {
|
|
|
|
setTx(r.tx), setRx(r.rx), setBaud(r.baud), setCfg(r);
|
|
|
|
setTcpport(r.tcp.url.split(':')[2] || 4001);
|
|
|
|
setWsport(r.ws.url.split(':')[2] || 4002);
|
|
|
|
setMqtt(r.mqtt.url);
|
|
|
|
});
|
2022-06-08 15:58:32 +08:00
|
|
|
|
|
|
|
const watchWebsocket = function() {
|
|
|
|
// Connect to websocker port, to implement WS console
|
|
|
|
var reconnect = function() {
|
2022-06-18 11:25:05 +08:00
|
|
|
var port;
|
|
|
|
setWsport(x => port = x);
|
|
|
|
var l = window.location, proto = l.protocol.replace('http', 'ws');
|
|
|
|
var tid, url = `${proto}//${l.hostname}:${port}/ws`;
|
|
|
|
// console.log(url);
|
2022-06-08 15:58:32 +08:00
|
|
|
var ws = new WebSocket(url);
|
|
|
|
ws.onopen = () => {
|
|
|
|
setConnected(true);
|
|
|
|
setWs(ws);
|
|
|
|
};
|
|
|
|
ws.onmessage = ev => {
|
|
|
|
// console.log(ev, ev.data);
|
|
|
|
setMessages(x => x.concat([{data: ev.data, uart: true}]));
|
|
|
|
};
|
|
|
|
ws.onclose = function() {
|
|
|
|
clearTimeout(tid);
|
|
|
|
tid = setTimeout(reconnect, 1000);
|
|
|
|
setConnected(false);
|
|
|
|
setWs(null);
|
|
|
|
};
|
|
|
|
};
|
|
|
|
reconnect();
|
|
|
|
};
|
|
|
|
|
|
|
|
useEffect(() => {
|
|
|
|
refresh();
|
|
|
|
watchWebsocket();
|
|
|
|
}, []);
|
|
|
|
|
|
|
|
|
|
|
|
const sendmessage = ev => {
|
|
|
|
setMessages(x => x.concat([{data: txt + '\n', uart: false}]));
|
|
|
|
if (ws) ws.send(txt + '\n');
|
|
|
|
setTxt('');
|
|
|
|
};
|
|
|
|
|
2022-06-18 11:25:05 +08:00
|
|
|
const onchange = ev => false;
|
|
|
|
|
2022-06-08 15:58:32 +08:00
|
|
|
return html`
|
|
|
|
<div class="container">
|
2022-06-18 11:25:05 +08:00
|
|
|
<h1 style="margin-bottom: 0;">UART \u27F7 network bridge </h1>
|
2022-06-08 15:58:32 +08:00
|
|
|
<pre class="d-none">${JSON.stringify(cfg, null, 2)}</pre>
|
2022-06-18 11:25:05 +08:00
|
|
|
<div class="row">
|
|
|
|
<div class="col col-4">
|
|
|
|
<h3>UART configuration</h3>
|
|
|
|
<div class="d-flex pr-1 my-1">
|
|
|
|
<label class="addon">UART TX pin</label>
|
|
|
|
<input style="width: 5em;" value=${tx} onchange=${onchange}
|
|
|
|
oninput=${ev => setTx(ev.target.value)} />
|
|
|
|
</div><div class="d-flex pr-1 my-1">
|
|
|
|
<label class="addon">UART RX pin</label>
|
|
|
|
<input style="width: 5em;" value=${rx} onchange=${onchange}
|
|
|
|
oninput=${ev => setRx(ev.target.value)} />
|
|
|
|
</div><div class="d-flex pr-1 my-y">
|
|
|
|
<label class="addon">UART Baud</label>
|
|
|
|
<input style="width: 5em;" value=${baud} onchange=${onchange}
|
|
|
|
oninput=${ev => setBaud(ev.target.value)} />
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
<div class="col col-8">
|
|
|
|
<h3>Network configuration</h3>
|
|
|
|
<div class="d-flex my-1">
|
|
|
|
<label class="addon">Local TCP port</label>
|
|
|
|
<input style="min-width: 4em; flex: 1 100%;"
|
|
|
|
value=${tcpport} onchange=${onchange}
|
|
|
|
oninput=${ev => setTcpport(ev.target.value)} />
|
|
|
|
<label class="ml-1 d-flex label"><input type="checkbox"
|
|
|
|
checked=${cfg.tcp.enable} /> enable</label>
|
|
|
|
</div><div class="d-flex my-1">
|
|
|
|
<label class="addon">Local WS port</label>
|
|
|
|
<input style="flex: 1 100%;"
|
|
|
|
value=${wsport} onchange=${onchange}
|
|
|
|
oninput=${ev => setWsport(ev.target.value)} />
|
|
|
|
<label class="ml-1 d-flex label"><input type="checkbox"
|
|
|
|
checked=${cfg.ws.enable} /> enable</label>
|
|
|
|
</div><div class="d-flex my-1">
|
|
|
|
<label class="addon">Remote MQTT</label>
|
|
|
|
<input style="flex: 1 100%;"
|
|
|
|
value=${mqtt} onchange=${onchange}
|
|
|
|
oninput=${ev => setMqtt(ev.target.value)} />
|
|
|
|
<label class="ml-1 d-flex label"><input type="checkbox"
|
|
|
|
checked=${cfg.mqtt.enable} /> enable</label>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
|
|
|
|
<div class="msg">
|
|
|
|
Note: to connect over MQTT,
|
|
|
|
go to <a href="http://www.hivemq.com/demos/websocket-client/">
|
|
|
|
console</a>, subscribe to b/tx and publish to b/rx<br/>
|
|
|
|
Note: to connect over TCP, use netcat utility:<br/>
|
|
|
|
$ nc ${location.hostname} ${tcpport}
|
|
|
|
</div>
|
|
|
|
|
|
|
|
<div style="margin-top: 2em;">
|
|
|
|
<b>UART console</b><span style="margin-left: 1em; color: #777;">works
|
|
|
|
over the local WS port. WebSocket status: </span><span
|
|
|
|
style="color: ${connected ? 'teal' : 'red'};">
|
|
|
|
\u25cf ${connected ? 'connected' : 'disconnected'} </span>
|
|
|
|
</div>
|
2022-06-08 15:58:32 +08:00
|
|
|
<div style="margin: 0.5em 0; display: flex">
|
2022-06-18 11:25:05 +08:00
|
|
|
<input placeholder="to send data, type and press enter..." style="flex: 1 100%;"
|
2022-06-08 15:58:32 +08:00
|
|
|
value=${txt} onchange=${sendmessage}
|
|
|
|
oninput=${ev => setTxt(ev.target.value)} />
|
2022-06-18 11:25:05 +08:00
|
|
|
<button style="margin-left: 1em;"
|
|
|
|
onclick=${ev => setMessages([])}>clear</button>
|
2022-06-08 15:58:32 +08:00
|
|
|
</div>
|
2022-06-18 11:25:05 +08:00
|
|
|
<pre style="height: 15em; overflow: auto;">
|
|
|
|
${messages.map(message => h(Message, {message}))}
|
|
|
|
</pre>
|
|
|
|
|
2022-06-08 15:58:32 +08:00
|
|
|
</div>`;
|
|
|
|
};
|
|
|
|
|
|
|
|
window.onload = () => render(h(App), document.body);
|