forked from FOSS/BangleApps
Add Espruino terminal - to allow communications with Espruino devices via terminal
parent
da31affbea
commit
1369047259
|
@ -324,7 +324,7 @@ and which gives information about the app for the Launcher.
|
|||
```
|
||||
|
||||
* name, icon and description present the app in the app loader.
|
||||
* tags is used for grouping apps in the library, separate multiple entries by comma. Known tags are `tool`, `system`, `clock`, `game`, `sound`, `gps`, `widget`, `launcher` or empty.
|
||||
* tags is used for grouping apps in the library, separate multiple entries by comma. Known tags are `tool`, `system`, `clock`, `game`, `sound`, `gps`, `widget`, `launcher`, `bluetooth` or empty.
|
||||
* storage is used to identify the app files and how to handle them
|
||||
* data is used to clean up files when the app is uninstalled
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
"version": "0.01",
|
||||
"description": "Send commands to other Espruino devices via the Bluetooth UART interface. Customisable commands!",
|
||||
"icon": "app.png",
|
||||
"tags": "",
|
||||
"tags": "tool,bluetooth",
|
||||
"supports": ["BANGLEJS","BANGLEJS2"],
|
||||
"readme": "README.md",
|
||||
"custom": "custom.html",
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
0.01: New App!
|
|
@ -0,0 +1,22 @@
|
|||
# Espruino Terminal
|
||||
|
||||
Send commands to other Espruino devices via the Bluetooth UART interface and
|
||||
see the result on a terminal.
|
||||
|
||||
## Customising
|
||||
|
||||
Once installed and you're connected to the Bangle you can click the button next to the app in the app loader
|
||||
to change the commands (they will be read from the device).
|
||||
|
||||
When done, click `Save to Bangle.js` and your changes will be saved to the same device.
|
||||
|
||||
## Usage
|
||||
|
||||
* Load the app and after a few seconds you'll see a menu with Espruino devices
|
||||
in the vicinity.
|
||||
* Tap on the device you want to connect to
|
||||
* A terminal will pop up showing `Connecting...` and then `Connected`
|
||||
* Now tap on the right (or press the button) to bring up a menu with options for commands, or the option to disconnect.
|
||||
|
||||
You can also choose `Custom` in which case a keyboard (using the currently installed text input method) will
|
||||
be displayed and you can enter the command you would like to send.
|
|
@ -0,0 +1 @@
|
|||
require("heatshrink").decompress(atob("mEwwcCpMkyQC/AVW//4AK/oR/COD8LCP4R/CK8DCKNsCKFt2BHPhu2CJ8BCKAjQI4OQNaIUB23bsCPMCJzp/CP4Rf/4AKCKwC/AVIA=="))
|
|
@ -0,0 +1,101 @@
|
|||
var uart; // require("ble_uart")
|
||||
var device; // BluetoothDevice
|
||||
var customCommand = "";
|
||||
// Set up terminal
|
||||
Bangle.loadWidgets();
|
||||
var R = Bangle.appRect;
|
||||
var termg = Graphics.createArrayBuffer(R.w, R.h, 1, {msb:true});
|
||||
var termVisible = false;
|
||||
termg.setFont("6x8");
|
||||
term = require("VT100").connect(termg, {
|
||||
charWidth : 6,
|
||||
charHeight : 8
|
||||
});
|
||||
term.print = str => {
|
||||
for (var i of str) term.char(i);
|
||||
if (termVisible) g.reset().drawImage(termg,R.x,R.y).setFont("6x8").setFontAlign(0,-1,1).drawString("MORE",R.w-1,(R.y+R.y2)/2);
|
||||
};
|
||||
|
||||
function showConnectMenu() {
|
||||
termVisible = false;
|
||||
var m = { "" : {title:"Devices"} };
|
||||
E.showMessage("Scanning...");
|
||||
NRF.findDevices(devices => {
|
||||
devices.forEach(dev=>{
|
||||
m[dev.name||dev.id.substr(0,17)] = ()=>{
|
||||
connectTo(dev);
|
||||
};
|
||||
});
|
||||
m["< Back"] = () => showConnectMenu();
|
||||
E.showMenu(m);
|
||||
},{filters:[
|
||||
{ namePrefix: 'Puck.js' },
|
||||
{ namePrefix: 'Pixl.js' },
|
||||
{ namePrefix: 'MDBT42Q' },
|
||||
{ namePrefix: 'Bangle.js' },
|
||||
{ namePrefix: 'Espruino' },
|
||||
{ services: [ "6e400001-b5a3-f393-e0a9-e50e24dcca9e" ] }
|
||||
],active:true,timeout:4000});
|
||||
}
|
||||
|
||||
function showOptionsMenu() {
|
||||
if (!uart) showConnectMenu();
|
||||
termVisible = false;
|
||||
var menu = {"":{title:/*LANG*/"Options"},
|
||||
"< Back" : () => showTerminal(),
|
||||
};
|
||||
var json = require("Storage").readJSON("espruinoterm.json",1);
|
||||
if (Array.isArray(json)) {
|
||||
json.forEach(j => { menu[j.title] = () => sendCommand(j.cmd); });
|
||||
} else {
|
||||
Object.assign(menu,{
|
||||
"Version" : () => sendCommand("process.env.VERSION"),
|
||||
"Battery" : () => sendCommand("E.getBattery()"),
|
||||
"Flash LED" : () => sendCommand("LED.set();setTimeout(()=>LED.reset(),1000);")
|
||||
});
|
||||
}
|
||||
menu[/*LANG*/"Custom"] = () => { require("textinput").input({text:customCommand}).then(result => {
|
||||
customCommand = result;
|
||||
sendCommand(customCommand);
|
||||
})};
|
||||
menu[/*LANG*/"Disconnect"] = () => { showTerminal(); term.print("\r\nDisconnecting...\r\n"); uart.disconnect(); }
|
||||
|
||||
E.showMenu(menu);
|
||||
}
|
||||
|
||||
function showTerminal() {
|
||||
E.showMenu();
|
||||
Bangle.setUI({
|
||||
mode : "custom",
|
||||
btn : n=> { showOptionsMenu(); },
|
||||
touch : (n,e) => { if (n==2) showOptionsMenu(); }
|
||||
});
|
||||
termVisible = true;
|
||||
term.print(""); // redraw terminal
|
||||
}
|
||||
|
||||
function sendCommand(cmd) {
|
||||
showTerminal();
|
||||
uart.write(cmd+"\n");
|
||||
}
|
||||
|
||||
function connectTo(dev) {
|
||||
device = dev;
|
||||
showTerminal();
|
||||
term.print(`\r\nConnect to ${dev.name||dev.id.substr(0,17)}...\r\n`);
|
||||
device.on('gattserverdisconnected', function(reason) {
|
||||
term.print(`\r\nDISCONNECTED (${reason})\r\n`);
|
||||
uart = undefined;
|
||||
device = undefined;
|
||||
setTimeout(showConnectMenu, 1000);
|
||||
});
|
||||
require("ble_uart").connect(device).then(function(u) {
|
||||
uart = u;
|
||||
term.print("Connected...\r\n");
|
||||
uart.on('data', function(d) { term.print(d); });
|
||||
});
|
||||
}
|
||||
|
||||
// now start
|
||||
Bangle.drawWidgets();
|
||||
showConnectMenu();
|
|
@ -0,0 +1,5 @@
|
|||
[
|
||||
{"title":"Version", "cmd":"process.env.VERSION"},
|
||||
{"title":"Battery", "cmd":"E.getBattery()"},
|
||||
{"title":"Flash LED", "cmd":"LED.set();setTimeout(()=>LED.reset(),1000);"}
|
||||
]
|
Binary file not shown.
After Width: | Height: | Size: 523 B |
|
@ -0,0 +1,104 @@
|
|||
<html>
|
||||
<head>
|
||||
<link rel="stylesheet" href="../../css/spectre.min.css">
|
||||
<link rel="stylesheet" href="../../css/spectre-exp.min.css">
|
||||
<link rel="stylesheet" href="../../css/spectre-icons.min.css">
|
||||
<style>
|
||||
.badgeerror[data-badge]::after { background-color: red; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<p>Enter the menu items you'd like to see appear in the app below. When finished, click `Save to Bangle.js` to save the JavaScript back.</p>
|
||||
<div style="overflow-x:scroll">
|
||||
<table class="table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Title</th>
|
||||
<th>Command</th>
|
||||
<th></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody id="tbody">
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<p><button id="save" class="btn btn-primary">Save to Bangle.js</button></p>
|
||||
|
||||
<script src="../../core/lib/interface.js"></script>
|
||||
|
||||
<script>
|
||||
var options;
|
||||
setDefaults();
|
||||
|
||||
function setDefaults() {
|
||||
options = [
|
||||
{title:"Version", cmd:"process.env.VERSION"},
|
||||
{title:"Battery", cmd:"E.getBattery()"},
|
||||
{title:"Flash LED", cmd:"LED.set();setTimeout(()=>LED.reset(),1000);"}
|
||||
];
|
||||
}
|
||||
|
||||
function refresh() {
|
||||
var tbody = document.getElementById("tbody");
|
||||
tbody.innerHTML = "";
|
||||
options.forEach((option,idx)=>{
|
||||
var tr = document.createElement("tr");
|
||||
tr.innerHTML = `
|
||||
<td><input type="text" name="title"></td>
|
||||
<td><input type="text" name="command"></td>
|
||||
<td><button class="btn btn-action"><i class="icon icon-delete"></i></button></td>
|
||||
`;
|
||||
var titleInput = tr.children[0].firstChild;
|
||||
titleInput.value = option.title;
|
||||
titleInput.addEventListener("change", function(e) {
|
||||
option.title = titleInput.value;
|
||||
});
|
||||
var cmdInput = tr.children[1].firstChild;
|
||||
cmdInput.value = option.cmd;
|
||||
cmdInput.addEventListener("change", function(e) {
|
||||
option.cmd = cmdInput.value;
|
||||
});
|
||||
tr.children[2].firstChild.addEventListener("click", function() {
|
||||
options.splice(idx,1);
|
||||
refresh();
|
||||
});
|
||||
tbody.appendChild(tr);
|
||||
});
|
||||
var tr = document.createElement("tr");
|
||||
tr.innerHTML = `
|
||||
<td><button class="btn">Reset to Defaults</button></td>
|
||||
<td></td>
|
||||
<td><button class="btn btn-action"><i class="icon icon-plus"></i></button></td>
|
||||
`;
|
||||
tr.children[0].firstChild.addEventListener("click", function() {
|
||||
setDefaults();
|
||||
refresh();
|
||||
});
|
||||
tr.children[2].firstChild.addEventListener("click", function() {
|
||||
options.push({"title":"",cmd:""});
|
||||
refresh();
|
||||
});
|
||||
tbody.appendChild(tr);
|
||||
}
|
||||
|
||||
function onInit() {
|
||||
Util.showModal("Loading...");
|
||||
Util.readStorage("espruinoterm.json", function(j) {
|
||||
Util.hideModal();
|
||||
try {
|
||||
options = JSON.parse(j);
|
||||
} catch (e) {}
|
||||
if (!Array.isArray(options)) setDefaults();
|
||||
refresh();
|
||||
});
|
||||
}
|
||||
refresh();
|
||||
document.getElementById("save").addEventListener("click", function() {
|
||||
Util.showModal("Saving...");
|
||||
Util.writeStorage("espruinoterm.json", JSON.stringify(options), function() {
|
||||
Util.hideModal();
|
||||
});
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,20 @@
|
|||
{
|
||||
"id": "espruinoterm",
|
||||
"name": "Espruino Terminal",
|
||||
"shortName": "Espruino Term",
|
||||
"version": "0.01",
|
||||
"description": "Send commands to other Espruino devices via the Bluetooth UART interface, and see the result on a VT100 terminal. Customisable commands!",
|
||||
"icon": "app.png",
|
||||
"screenshots": [{"url":"screenshot.png"}],
|
||||
"tags": "tool,bluetooth",
|
||||
"supports": ["BANGLEJS","BANGLEJS2"],
|
||||
"readme": "README.md",
|
||||
"interface": "interface.html",
|
||||
"dependencies": {"textinput":"type"},
|
||||
"storage": [
|
||||
{"name":"espruinoterm.app.js","url":"app.js"},
|
||||
{"name":"espruinoterm.img","url":"app-icon.js","evaluate":true}
|
||||
],"data": [
|
||||
{"name":"espruinoterm.json","url":"app.json"}
|
||||
]
|
||||
}
|
Binary file not shown.
After Width: | Height: | Size: 2.2 KiB |
|
@ -11,5 +11,6 @@
|
|||
"storage": [
|
||||
{"name":"textinput","url":"lib.js"},
|
||||
{"name":"kbtouch.settings.js","url":"settings.js"}
|
||||
]
|
||||
],
|
||||
"sortorder":-1
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue