importing chrome extension
This commit is contained in:
parent
b150ee873f
commit
64826db4aa
26
clients/chrome/README.md
Normal file
26
clients/chrome/README.md
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
# microbit-chrome
|
||||||
|
Prototype chrome addon that exposes the micro:bit's serial output to webpages.
|
||||||
|
* watch the [demo video](https://vimeo.com/146207766)
|
||||||
|
|
||||||
|
# Installation
|
||||||
|
See [developer.chrome.com](https://developer.chrome.com/extensions/getstarted#unpacked)
|
||||||
|
for instructions on how to install the local version into your chrome browser.
|
||||||
|
|
||||||
|
# Requirements
|
||||||
|
* Chrome 48 or later.
|
||||||
|
|
||||||
|
# Sample page
|
||||||
|
The `demo.html` webpage goes along with the
|
||||||
|
https://github.com/Microsoft/microbit-touchdevelop/blob/master/examples/tcs34725.cpp
|
||||||
|
program. Run `http-server` from this directory, then visit
|
||||||
|
http://localhost:8080/demo.html
|
||||||
|
(keep in mind that pages served from `file://` cannot open ports).
|
||||||
|
|
||||||
|
# Building
|
||||||
|
|
||||||
|
Open a command prompt and run the following commands.
|
||||||
|
|
||||||
|
````
|
||||||
|
npm install
|
||||||
|
typings update
|
||||||
|
````
|
68
clients/chrome/background.js
Normal file
68
clients/chrome/background.js
Normal file
@ -0,0 +1,68 @@
|
|||||||
|
///<reference path='typings/browser.d.ts'/>
|
||||||
|
var connections = [];
|
||||||
|
// 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.
|
||||||
|
var ports = [];
|
||||||
|
function byPath(path) {
|
||||||
|
return connections.filter(function (x) { return x.path == path; });
|
||||||
|
}
|
||||||
|
function byId(id) {
|
||||||
|
return connections.filter(function (x) { return x.id == id; });
|
||||||
|
}
|
||||||
|
function onReceive(data, id) {
|
||||||
|
if (ports.length == 0)
|
||||||
|
return;
|
||||||
|
var view = new DataView(data);
|
||||||
|
var decoder = new TextDecoder("utf-8");
|
||||||
|
var decodedString = decoder.decode(view);
|
||||||
|
ports.forEach(function (port) { return port.postMessage({
|
||||||
|
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(function (x) { return 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);
|
92
clients/chrome/background.ts
Normal file
92
clients/chrome/background.ts
Normal file
@ -0,0 +1,92 @@
|
|||||||
|
// 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);
|
BIN
clients/chrome/logo128.png
Normal file
BIN
clients/chrome/logo128.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 5.9 KiB |
BIN
clients/chrome/logo48.png
Normal file
BIN
clients/chrome/logo48.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 2.2 KiB |
28
clients/chrome/manifest.json
Normal file
28
clients/chrome/manifest.json
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
{
|
||||||
|
"app": {
|
||||||
|
"background": {
|
||||||
|
"scripts": [ "background.js" ]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
"manifest_version": 2,
|
||||||
|
"name": "code the micro:bit",
|
||||||
|
"version": "0.1.0",
|
||||||
|
"author": "Microsoft Corporation",
|
||||||
|
"short_name": "code the micro:bit",
|
||||||
|
|
||||||
|
"description": "This extension reads the serial output from connected BBC micro:bit and sends it to https://codethemicrobit.com.",
|
||||||
|
"icons": {
|
||||||
|
"48": "logo48.png",
|
||||||
|
"128": "logo128.png"
|
||||||
|
},
|
||||||
|
|
||||||
|
"permissions": [
|
||||||
|
"serial",
|
||||||
|
"usb"
|
||||||
|
],
|
||||||
|
|
||||||
|
"externally_connectable": {
|
||||||
|
"matches": [ "*://localhost/*", "https://*.pxt.io/*", "https://codethemicrobit.com/*" ]
|
||||||
|
}
|
||||||
|
}
|
BIN
clients/chrome/screenshot.png
Normal file
BIN
clients/chrome/screenshot.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 138 KiB |
7
clients/chrome/tsconfig.json
Normal file
7
clients/chrome/tsconfig.json
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
{
|
||||||
|
"compiler-options": {
|
||||||
|
"target": "ES5",
|
||||||
|
"module": "amd",
|
||||||
|
"sourceMap": false
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user