93 lines
2.8 KiB
TypeScript
93 lines
2.8 KiB
TypeScript
|
// A list of: {
|
||
|
// id: number;
|
||
|
// path: string;
|
||
|
// } where [id] is the [connectionId] (internal to Chrome) and [path] is the
|
||
|
// OS' name for the device (e.g. "COM4").
|
||
|
interface Connection {
|
||
|
id: string;
|
||
|
path: string;
|
||
|
}
|
||
|
let connections: Connection[] = [];
|
||
|
|
||
|
// A list of "ports", i.e. connected clients (such as web pages). Multiple web
|
||
|
// pages can connect to our service: they all receive the same data.
|
||
|
let ports = [];
|
||
|
|
||
|
interface Message {
|
||
|
type: string;
|
||
|
data: string;
|
||
|
id: string;
|
||
|
}
|
||
|
|
||
|
function byPath(path: string): Connection[] {
|
||
|
return connections.filter((x) => x.path == path);
|
||
|
}
|
||
|
|
||
|
function byId(id: string): Connection[] {
|
||
|
return connections.filter((x) => x.id == id);
|
||
|
}
|
||
|
|
||
|
function onReceive(data, id: string) {
|
||
|
if (ports.length == 0) return;
|
||
|
|
||
|
let view = new DataView(data);
|
||
|
let decoder = new TextDecoder("utf-8");
|
||
|
let decodedString = decoder.decode(view);
|
||
|
ports.forEach(port => port.postMessage(<Message>{
|
||
|
type: "serial",
|
||
|
data: decodedString,
|
||
|
id: id,
|
||
|
}));
|
||
|
}
|
||
|
|
||
|
function findNewDevices() {
|
||
|
chrome.serial.getDevices(function (serialPorts) {
|
||
|
serialPorts.forEach(function (serialPort) {
|
||
|
if (byPath(serialPort.path).length == 0 &&
|
||
|
serialPort.displayName == "mbed Serial Port") {
|
||
|
chrome.serial.connect(serialPort.path, { bitrate: 115200 }, function (info) {
|
||
|
// In case the [connect] operation takes more than five seconds...
|
||
|
if (info && byPath(serialPort.path).length == 0)
|
||
|
connections.push({
|
||
|
id: info.connectionId,
|
||
|
path: serialPort.path
|
||
|
});
|
||
|
});
|
||
|
}
|
||
|
});
|
||
|
});
|
||
|
}
|
||
|
|
||
|
function main() {
|
||
|
// Register new clients in the [ports] global variable.
|
||
|
chrome.runtime.onConnectExternal.addListener(function (port) {
|
||
|
if (/^(micro:bit|touchdevelop|yelm|pxt|codemicrobit|codethemicrobit)$/.test(port.name)) {
|
||
|
ports.push(port);
|
||
|
port.onDisconnect.addListener(function () {
|
||
|
ports = ports.filter(function (x) { return x != port });
|
||
|
});
|
||
|
}
|
||
|
});
|
||
|
|
||
|
// When receiving data for one of the connections that we're tracking, forward
|
||
|
// it to all connected clients.
|
||
|
chrome.serial.onReceive.addListener(function (info) {
|
||
|
if (byId(info.connectionId).length > 0)
|
||
|
onReceive(info.data, info.connectionId);
|
||
|
});
|
||
|
|
||
|
// When it looks like we've been disconnected, drop the corresponding
|
||
|
// connection object from the [connections] global variable.
|
||
|
chrome.serial.onReceiveError.addListener(function (info) {
|
||
|
if (info.error == "system_error" || info.error == "disconnected" || info.error == "device_lost")
|
||
|
connections = connections.filter((x) => x.id != info.connectionId);
|
||
|
});
|
||
|
|
||
|
// Probe serial connections at regular intervals. In case we find an mbed port
|
||
|
// we haven't yet connected to, connect to it.
|
||
|
setInterval(findNewDevices, 5000);
|
||
|
findNewDevices();
|
||
|
}
|
||
|
|
||
|
document.addEventListener("DOMContentLoaded", main);
|