mirror of
https://github.com/cesanta/mongoose.git
synced 2024-12-16 10:29:22 +08:00
638892ca70
Check a new config element is present before acting on the previous one Correctly update config local copy Fix TCP buffering for ever
154 lines
5.8 KiB
JavaScript
154 lines
5.8 KiB
JavaScript
'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) {
|
|
const [cfg, setCfg] = useState({tcp: {}, ws: {}, mqtt: {}});
|
|
const [messages, setMessages] = useState([]);
|
|
const [connected, setConnected] = useState(false);
|
|
const [txt, setTxt] = useState('');
|
|
const [ws, setWs] = useState(null);
|
|
|
|
const refresh = () =>
|
|
fetch('/api/config/get').then(r => r.json()).then(r => setCfg(r));
|
|
|
|
const getport = (url, v) => ((url || '').match(/.*:(\d+)/) || ['', v])[1];
|
|
|
|
const watchWebsocket = function() {
|
|
// Connect to websocker port, to implement WS console
|
|
var reconnect = function() {
|
|
var port = getport(cfg.ws.url, 4002);
|
|
var l = window.location, proto = l.protocol.replace('http', 'ws');
|
|
var tid, url = `${proto}//${l.hostname}:${port}/ws`;
|
|
// console.log(url);
|
|
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('');
|
|
};
|
|
|
|
const onchange = ev => fetch('/api/config/set', {
|
|
method: 'POST',
|
|
headers: {'Content-Type': 'application/json'},
|
|
body: JSON.stringify(cfg),
|
|
}).then(r => ws && ws.close());
|
|
|
|
const set = obj => setCfg(x => Object.assign(x, obj));
|
|
const nset = (n,obj) => setCfg(x => Object.assign(x, {[n]: Object.assign(x[n],obj)}));
|
|
const setTx = ev => set({tx: parseInt(ev.target.value)});
|
|
const setRx = ev => set({rx: parseInt(ev.target.value)});
|
|
const setBaud = ev => set({baud: parseInt(ev.target.value)});
|
|
const setTcpUrl = ev => nset('tcp', {url: `tcp://0.0.0.0:${ev.target.value}`});
|
|
const setWsUrl = ev => nset('ws',{url: `ws://0.0.0.0:${ev.target.value}`});
|
|
const setMqttUrl = ev => nset('mqtt',{url: ev.target.value});
|
|
const setTcpEna = ev => (nset('tcp',{enable: ev.target.checked}), onchange());
|
|
const setWsEna = ev => (nset('ws',{enable: ev.target.checked}), onchange());
|
|
const setMqttEna = ev =>(nset('mqtt', {enable: ev.target.checked}), onchange());
|
|
|
|
return html`
|
|
<div class="container">
|
|
<h1 style="margin-bottom: 0;">UART \u27F7 network bridge </h1>
|
|
<pre class="d-none">${JSON.stringify(cfg, null, 2)}</pre>
|
|
<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=${cfg.tx} onchange=${onchange}
|
|
oninput=${setTx} />
|
|
</div><div class="d-flex pr-1 my-1">
|
|
<label class="addon">UART RX pin</label>
|
|
<input style="width: 5em;" value=${cfg.rx} onchange=${onchange}
|
|
oninput=${setRx} />
|
|
</div><div class="d-flex pr-1 my-y">
|
|
<label class="addon">UART Baud</label>
|
|
<input style="width: 5em;" value=${cfg.baud} onchange=${onchange}
|
|
oninput=${setBaud} />
|
|
</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=${getport(cfg.tcp.url, 4001)} onchange=${onchange}
|
|
oninput=${setTcpUrl} />
|
|
<label class="ml-1 d-flex label"><input type="checkbox"
|
|
checked=${cfg.tcp.enable} onchange=${setTcpEna} /> enable</label>
|
|
</div><div class="d-flex my-1">
|
|
<label class="addon">Local WS port</label>
|
|
<input style="flex: 1 100%;"
|
|
value=${getport(cfg.ws.url, 4002)} onchange=${onchange}
|
|
oninput=${setWsUrl} />
|
|
<label class="ml-1 d-flex label"><input type="checkbox"
|
|
checked=${cfg.ws.enable} onchange=${setWsEna} /> enable</label>
|
|
</div><div class="d-flex my-1">
|
|
<label class="addon">Remote MQTT</label>
|
|
<input style="flex: 1 100%;"
|
|
value=${cfg.mqtt.url} onchange=${onchange}
|
|
oninput=${setMqttUrl} />
|
|
<label class="ml-1 d-flex label"><input type="checkbox"
|
|
checked=${cfg.mqtt.enable} onchange=${setMqttEna} /> enable</label>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="msg">
|
|
Note: to connect over MQTT,
|
|
open <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} ${getport(cfg.tcp.url, 4001)}
|
|
</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>
|
|
<div style="margin: 0.5em 0; display: flex">
|
|
<input placeholder="to send data, type and press enter..." style="flex: 1 100%;"
|
|
value=${txt} onchange=${sendmessage}
|
|
oninput=${ev => setTxt(ev.target.value)} />
|
|
<button style="margin-left: 1em;"
|
|
onclick=${ev => setMessages([])}>clear</button>
|
|
</div>
|
|
<pre style="height: 15em; overflow: auto;">
|
|
${messages.map(message => h(Message, {message}))}
|
|
</pre>
|
|
|
|
</div>`;
|
|
};
|
|
|
|
window.onload = () => render(h(App), document.body);
|