pxt-calliope/clients/chrome/background.ts

104 lines
3.1 KiB
TypeScript
Raw Normal View History

declare var chrome: any;
declare class TextDecoder {
constructor(encoding: string);
decode(data: DataView): string;
}
2016-06-22 18:43:03 +02:00
// 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: ArrayBuffer, id: string) {
2016-06-22 18:43:03 +02:00
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
2016-06-22 18:43:03 +02:00
}));
}
function findNewDevices() {
chrome.serial.getDevices(function (serialPorts) {
serialPorts.forEach(function (serialPort) {
if (byPath(serialPort.path).length == 0 &&
serialPort.displayName == "mbed Serial Port") {
try {
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
});
});
} catch (e) {
console.log(`failed to connect to ${serialPort.displayName}`)
}
2016-06-22 18:43:03 +02:00
}
});
});
}
function main() {
// Register new clients in the [ports] global variable.
chrome.runtime.onConnectExternal.addListener(function (port) {
console.log('connection to port ' + port.name)
if (/^serial$/.test(port.name)) {
2016-06-22 18:43:03 +02:00
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);