forked from FOSS/BangleApps
commit
d6179b955f
47
apps.json
47
apps.json
|
@ -337,5 +337,52 @@
|
|||
{"name":".tfmodel","url":"gesture-tfmodel.js","evaluate":true},
|
||||
{"name":"*gesture","url":"gesture-icon.js","evaluate":true}
|
||||
]
|
||||
},
|
||||
{ "id": "pparrot",
|
||||
"name": "Party Parrot",
|
||||
"icon": "party-parrot.png",
|
||||
"description": "Party with a parrot on your wrist",
|
||||
"tags": "party,parrot,lol",
|
||||
"type":"app",
|
||||
"storage": [
|
||||
{"name":"+pparrot","url":"party-parrot.json"},
|
||||
{"name":"-pparrot","url":"party-parrot.js"},
|
||||
{"name":"*pparrot","url":"party-parrot-icon.js","evaluate":true}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "blescan",
|
||||
"name": "BLE Scanner",
|
||||
"icon": "blescan.png",
|
||||
"description": "Scan for advertising BLE devices",
|
||||
"tags" : "bluetooth",
|
||||
"storage" : [
|
||||
{"name":"+blescan","url":"blescan.json"},
|
||||
{"name":"-blescan","url":"blescan.js"},
|
||||
{"name":"*blescan","url":"blescan-icon.js", "evaluate":true}
|
||||
]
|
||||
},
|
||||
{ "id": "mmonday",
|
||||
"name": "Manic Monday Tone",
|
||||
"icon": "manic-monday-icon.png",
|
||||
"description": "The Bangles make a comeback",
|
||||
"tags": "sound",
|
||||
"storage": [
|
||||
{"name":"+mmonday","url":"manic-monday.json"},
|
||||
{"name":"-mmonday","url":"manic-monday.js"},
|
||||
{"name":"*mmonday","url":"manic-monday-icon.js","evaluate":true}
|
||||
]
|
||||
},
|
||||
{ "id": "jbells",
|
||||
"name": "Jingle Bells",
|
||||
"icon": "jbells.png",
|
||||
"description": "Play Jingle Bells",
|
||||
"tags": "sound",
|
||||
"type":"app",
|
||||
"storage": [
|
||||
{"name":"+jbells","url":"jbells.json"},
|
||||
{"name":"-jbells","url":"jbells.js"},
|
||||
{"name":"*jbells","url":"jbells-icon.js","evaluate":true}
|
||||
]
|
||||
}
|
||||
]
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
require("heatshrink").decompress(atob("mEwxH+AH4A/AH4ATmIABrdbAgQrmAAYvEAAYtkF5QxcEZAvLGDAhJF5oxWFhYAFCBFaFzQsHAAk3CQmE1wwRFxiPFMY4uBwiSRI4uEQo4GIAAIVBxTCRFwoABJITvNrYTHRqIuCAAIvPxQSBBQwvQL6aMCBQ7sQVIQuGdIjqIGCIOEm4XHForqFIAYHBm4vTFxYMDAQKeHDIwvVRAoEDdRAvPE5QcHAoTqJDQ5eZAwS7DIZovWAodaRQLqGF6bhDABouCXYIAQF+6PUrQUQd7oMKF6wbLApYaIF45gSAgxeUF5olDBIICECJIvTm4wLAAoPHm4vTC4OK12EGJYLFI5IvJGAuE1wABGAycIBRQuKF4ouCAAIvPIgOFF6QwEL6c3IRAuMGA+EWw4GIwuusAuTeQzqGF4r0LF6AwIm4mEAA03FzAwJLAxbKFygwLd5IuaMRwthGBYvKFzQxJF5AtdGZAvEFcYA/AH4AvA=="))
|
|
@ -0,0 +1,52 @@
|
|||
// ble-scanner
|
||||
// Scan the airwaves every three seconds (which seems safe for a large number of devices)
|
||||
// Using the menu feature, display a scrollable list of BLE devices on the watch
|
||||
|
||||
// Dummy menu item to display until we find something
|
||||
const NODEVICE = 'No devices found';
|
||||
|
||||
const SCAN_INTERVAL = 3000;
|
||||
|
||||
const menu = {
|
||||
};
|
||||
|
||||
menu[NODEVICE] = {
|
||||
value : "",
|
||||
onchange : () => {}
|
||||
};
|
||||
|
||||
|
||||
function draw() {
|
||||
Bangle.menu(menu);
|
||||
}
|
||||
|
||||
function scan() {
|
||||
NRF.findDevices(devices => {
|
||||
for (let device of devices) {
|
||||
|
||||
// Only display devices that advertise a name
|
||||
|
||||
if (device.name) {
|
||||
// Remove no devices found message if it is present
|
||||
if (menu[NODEVICE]) {
|
||||
delete menu[NODEVICE];
|
||||
}
|
||||
menu[device.name] = {
|
||||
value : device.rssi,
|
||||
onchange : () => {}
|
||||
};
|
||||
}
|
||||
}
|
||||
draw();
|
||||
}, { active: true });
|
||||
}
|
||||
|
||||
|
||||
function waitMessage() {
|
||||
E.showMessage('scanning');
|
||||
}
|
||||
|
||||
scan();
|
||||
waitMessage();
|
||||
|
||||
setInterval(scan, SCAN_INTERVAL);
|
|
@ -0,0 +1,7 @@
|
|||
|
||||
{
|
||||
"name": "BLE Scanner",
|
||||
"type":"app",
|
||||
"icon": "*blescan",
|
||||
"src": "-blescan"
|
||||
}
|
Binary file not shown.
After Width: | Height: | Size: 2.4 KiB |
|
@ -3,13 +3,11 @@ g.clear();
|
|||
var minuteDate = new Date();
|
||||
var secondDate = new Date();
|
||||
|
||||
function line(angle, r1,r2) {
|
||||
function seconds(angle, r) {
|
||||
var a = angle*Math.PI/180;
|
||||
g.drawLine(
|
||||
120+Math.sin(a)*r1,
|
||||
120-Math.cos(a)*r1,
|
||||
120+Math.sin(a)*r2,
|
||||
120-Math.cos(a)*r2);
|
||||
var x = 120+Math.sin(a)*r;
|
||||
var y = 120-Math.cos(a)*r;
|
||||
g.fillRect(x-1,y-1,x+1,y+1);
|
||||
}
|
||||
function hand(angle, r1,r2) {
|
||||
var a = angle*Math.PI/180;
|
||||
|
@ -28,20 +26,20 @@ function hand(angle, r1,r2) {
|
|||
|
||||
function drawAll() {
|
||||
g.clear();
|
||||
g.setColor(0,0,0.3);
|
||||
g.setColor(0,0,0.6);
|
||||
for (var i=0;i<60;i++)
|
||||
line(360*i/60, 92, 95);
|
||||
seconds(360*i/60, 90);
|
||||
secondDate = minuteDate = new Date();
|
||||
onSecond();
|
||||
onMinute();
|
||||
}
|
||||
|
||||
function onSecond() {
|
||||
g.setColor(0,0,0.3);
|
||||
line(360*secondDate.getSeconds()/60, 92, 95);
|
||||
g.setColor(0,0,0.6);
|
||||
seconds(360*secondDate.getSeconds()/60, 90);
|
||||
g.setColor(1,0,0);
|
||||
secondDate = new Date();
|
||||
line(360*secondDate.getSeconds()/60, 92, 95);
|
||||
seconds(360*secondDate.getSeconds()/60, 90);
|
||||
g.setColor(1,1,1);
|
||||
|
||||
}
|
||||
|
@ -49,11 +47,11 @@ function onSecond() {
|
|||
function onMinute() {
|
||||
g.setColor(0,0,0);
|
||||
hand(360*minuteDate.getHours()/12, -10, 50);
|
||||
hand(360*minuteDate.getMinutes()/60, -10, 85);
|
||||
hand(360*minuteDate.getMinutes()/60, -10, 82);
|
||||
oldMinute = new Date();
|
||||
g.setColor(1,1,1);
|
||||
hand(360*minuteDate.getHours()/12, -10, 50);
|
||||
hand(360*minuteDate.getMinutes()/60, -10, 85);
|
||||
hand(360*minuteDate.getMinutes()/60, -10, 82);
|
||||
}
|
||||
|
||||
setInterval(onSecond,1000);
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
E.toArrayBuffer(atob("MDCEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEQAAAAAAABEAAAAAAAAAAAAAAAAAAAAAERAAAAAAAREAAAAAAAAAAAAAAAAAAAABERAAAAAAAREQAAAAAAAAAAAAAAAQAAAREREAAAAAERERAAABAAAAAAAAAAARERERERFMwAzEERERERERAAAAAAAAAAARERERERHMzMzMERERERERAAAAAAAAAAARERERERHMzdzMERERERERAAAAAAAAAAERERERER3d3d3d0REREREREAAAAAAAAAEREREWYe7u3d3u7hZhEREREAAAAAAAABERFmZmHu7u3d3u7uFmZmEREQAAAAAAARFmZmZm3u7u3d3u7u1mZmZmERAAAAAAFmZmZmZh7u7u7u7u7u4WZmZmZmYAAAAABmZmZmZk7u7u7u7u7u5GZmZmZmAAAAAAAABmZmZt7u7u7u7u7u7WZmZmAAAAAAAAAAAGZmZu7u7u7u7u7u7mZmZgAAAAAAAAAAAAZmYO7u7u7u7u7u7gZmYAAAAAAAAAAAAABmAO7u7u7u7u7u7gBmAAAAAAAAAAAAAAAAAO7u7u7u7u7u7gAAAAAAAAAAAAAAAAAAAO7u7u7u7u7u7gAAAAAAAAAAAAAAAAAAAO7u7u7u7u7u7gAAAAAAAAAAAAAAAAAAAO7u7u7u7u7u7gAAAAAAAAAAAAAAAAAADu7u7u7u7u7u7uAAAAAAAAAAAAAAAAAA7u7u7u7u7u7u7u4AAAAAAAAAAAAAAAAO7u7u7u7u7u7u7u7gAAAAAAAAAAAAAAAO7u7u7u7u7u7u7u7gAAAAAAAAAAAAAADu7u7u7u7u7u7u7u7uAAAAAAAAAAAAAA7u7u7u7u7u7u7u7u7u4AAAAAAAAAAAAO7u7u7u7u7u7u7u7u7u7gAAAAAAAAAADjM+7u7u7u7u7u7u7u7uM+AAAAAAAAAADuMzMz7u7u7u7u7u7jMzPuAAAAAAAAAA7u7u4zMzMzMzMzMzMzPu7u4AAAAAAAAA7u7u7u7uMzMzMzM+7u7u7u4AAAAAAAAADu7u7u7u7u7u7u7u7u7u7uAAAAAAAAAAAADu7u7u7u7u7u7u7u7uAAAAAAAAAAAAAAAAAA7u7u7u7u7u4AAAAAAAAAAAAAAAAAAAAAAABEREREAAAAAAAAAAAAAAAAAAAAAAAAAABEREREAAAAAAAAAAAAAAAAAAAAAAAAAADd3d3dAAAAAAAAAAAAAAAAAAAAAAAAAAAN3d3QAAAAAAAAAAAAAAAAAAAAAAAAAAAA3d0AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=="))
|
|
@ -0,0 +1,38 @@
|
|||
E.showMessage("Jingle Bells");
|
||||
|
||||
var eventEmitter = new Object();
|
||||
|
||||
function strofa(notes, times, current, next){
|
||||
eventEmitter.on(current, () => {
|
||||
if (notes.length == 0) {
|
||||
eventEmitter.emit(next);
|
||||
return;
|
||||
}
|
||||
let note = notes.shift();
|
||||
let time = times.shift();
|
||||
Bangle.beep(time, note).then(() => {
|
||||
setTimeout(() => {
|
||||
eventEmitter.emit(current);
|
||||
}, time);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
var one = [2637, 2637, 2637, 2637, 2637, 2637, 2637, 3135, 2093, 2349, 2637];
|
||||
var one_t = [160, 160, 320, 160, 160, 320, 160, 160, 160, 160, 320];
|
||||
|
||||
var two = [2793, 2793, 2793, 2637, 2637, 2637, 2349, 2349, 2349, 2637, 2349, 3135];
|
||||
var two_t = [160, 160, 320, 160, 160, 320, 160, 160, 160, 160, 320, 320];
|
||||
|
||||
var three = [2637, 2637, 2637, 2637, 2637, 2637, 2637, 3135, 2093, 2349, 2637];
|
||||
var three_t = [160, 160, 320, 160, 160, 320, 160, 160, 160, 160, 320];
|
||||
|
||||
var four = [2793, 2793, 2793, 2637, 2637, 2637, 3135, 2793, 2637, 2349, 2093];
|
||||
var four_t = [160, 160, 320, 160, 160, 320, 160, 160, 160, 160, 320];
|
||||
|
||||
strofa(one, one_t, "one", "two");
|
||||
strofa(two, two_t, "two", "three");
|
||||
strofa(three, three_t, "three", "four");
|
||||
strofa(four, four_t, "four", "stop");
|
||||
|
||||
eventEmitter.emit("one");
|
|
@ -0,0 +1,5 @@
|
|||
{
|
||||
"name":"Jingle Bells","type":"app",
|
||||
"icon":"*jbells",
|
||||
"src":"-jbells"
|
||||
}
|
Binary file not shown.
After Width: | Height: | Size: 1.8 KiB |
|
@ -0,0 +1 @@
|
|||
require("heatshrink").decompress(atob("MDABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"))
|
Binary file not shown.
After Width: | Height: | Size: 1.8 KiB |
|
@ -0,0 +1,46 @@
|
|||
// made using https://www.espruino.com/Making+Music
|
||||
// Manic Monday tone by The Bangles
|
||||
|
||||
var SPEAKER_PIN = D18;
|
||||
|
||||
function freq(f) {
|
||||
if (f===0) digitalWrite(SPEAKER_PIN, 0);
|
||||
else analogWrite(SPEAKER_PIN, 0.5, {freq: f});
|
||||
}
|
||||
freq(1000);
|
||||
freq(1500);
|
||||
freq(0);
|
||||
|
||||
var pitches = {
|
||||
'G': 207.65,
|
||||
'a': 220.00,
|
||||
'b': 246.94,
|
||||
'c': 261.63,
|
||||
'd': 293.66,
|
||||
'e': 329.63,
|
||||
'f': 369.99,
|
||||
'g': 392.00,
|
||||
'A': 440.00,
|
||||
'B': 493.88,
|
||||
'C': 523.25,
|
||||
'D': 587.33,
|
||||
'E': 659.26,
|
||||
'F': 698.46
|
||||
};
|
||||
|
||||
function step() {
|
||||
var ch = tune[pos];
|
||||
if (ch !== undefined) pos++;
|
||||
if (ch in pitches) freq(pitches[ch]);
|
||||
else freq(0); // off
|
||||
}
|
||||
|
||||
var tune = "aggffefed";
|
||||
var pos = 0;
|
||||
|
||||
setWatch(() => {
|
||||
var playing = setInterval(step, 500);
|
||||
if(playing === 0) clearInterval(playing);
|
||||
}, BTN1);
|
||||
|
||||
E.showMessage('BTN1 to start', 'Manic Monday');
|
|
@ -0,0 +1,5 @@
|
|||
{
|
||||
"name":"Manic Monday tone",
|
||||
"icon": "*mmonday",
|
||||
"src":"-mmonday"
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
require("heatshrink").decompress(atob("mEwxH+AH4A/AH4A/AH4A/AH4A5wNcp8AgEswFdFktVFYMAp9QudPgwGBldWF0ErEoPJz3J5PI4YDB4WlMwMrFz1cgF05Gl4fI5ICC5OfAYN0gGHFzhcBLYOeAYQABA4RhC5IQBriMcEQV6GgiXCRgPCBYUALzZTDF4i5Bq0xqA9BuYvcqwgBL4WkK4K9BgElrmArskp/JvOfHAIuXwJeE0oyCYYVcveArj8BCAQKBF64eBK4IfBz4DBAwJVBrmBF4KZBvRACgGHXq7tDMIulQoKOBwGAgCQBBYMrSC8AknJ0phDR4gvDOAN6TYouU1kAuZdCYQYCB4YvBd4IBBR4SbDlYvUlclLYqPCEgKbBwIuBqzvDL4TxULwItD0owC5HDAYMrgC9BrouCHgSbCFyYhBFwy/E5NPMAMxkgOEpMG1gvSbYIvBdgRaB5DzDAQOlKoLtEAQJeU/wuBbgQfEeQYGCvRACNokALycAlfCU4OfeAQsCEoRfCK4IKBBgY3BFyWBJYLlBGYLpDMBJeFp8HFyKqBuYaCuaREcYbBCNAwUCwIuSvJYBE4ZhBzwtN4T2BRyUAp4YCD4ZMBYYgwCMpAvRXYK8BFgaKCboYACLQozEOQQuSJIYfGdwqLFAwYvQFwIfCL4gfEG54vORg/I4elAQIJE0gGF5GfCYQJCX5ysHLYgCCLYYQDSYprCkgvM1kAp6sLGCVWgGsF5UrF4IAGpNPlYJIAAQMEBIjAMq0GkqRBAb9cYJgA/AH4A/AH4A/ABA"))
|
|
@ -0,0 +1,22 @@
|
|||
var imgs = [
|
||||
atob("qE5xH+AH4A/AH4A/AH4A/AHeBq1WlcAAAUrqwJBwJM/IQJLEABBUBw5N8IotPAAhRHJu+HJolPvWe4XJAAvCz1zkhRDeuuBdIdzzxLGAA+eUwUreeacDJqCkDuah0JwUkJoTiBdg4AJKAZO2z0kA4KjH4RbGUAcAqxOtwJOCHgY6Dp5FEz1PBQUAuYLCvQIDlesJ1eHlaWGJ4YJEzwIDAARlCCYkAwLtucopPH4SdCldWqxmCp5PGlbttGwJPMTwVWrgACW4aqDLwSgqTxBHBkjiE5I/CJwYABNIeeud6KYSgp1iFBTwzoCvQ7BAoQ+CJ4qgCLwS4EUFDuCTwwAHdw4ABXQ4RDd2JPReAV6CQigqaYMkJxpPNuYSId1AyFJ61PCYskgErd25PUeAWsJ8/Cd8Lwow7uRAAITBlZPIvRPIeEjuSAANPCgJOFDpJPCgBPjlcAkhOQ5N6eA5PwwLQIABY8CJ4ptJJ8usGALuSeBCeCNo5iDT0kA4RPSHoUrJwlPDo96BYOBJ0GHTwRPUUAbxBXhYQBlesJ8CACJ63CkhQCAQNzB5DujdoaCKeJ5rLBwTuhZ4VzAQN6J6nJDIQaKf4WHT0TPBFAMkJ6oZDTxDujJwQwCZATwVDISeJvTuhwLtCJIaGLKBwXJEgMr1hOhP4igCp7xWVRTuf1lWEQNzZZAJGADFzdz5ODSpDMBBYLyWAAwgBlaedJwZCJKAUkzzudTzpONZ4gQBzyjYvRPewKPCHhuekhRCKQNzAAJUTNwWsJzsAbx/CvRREDCIADp8AlZPaJyajEudPKYQZTCwJPaJy6mFdyafcJzgAWJ7ROz5NzGYJPWJ2nJvQ0BwJOUw8rJ2fJzxPXqwYBvROxAAI2BqyeUC4NPJ2fJuY4Bw5PSwLt0eAqgTlafCAGo4BleBJ6gA5lZPRqxP7eJY"),
|
||||
atob("qE5xH+AH4A/AH4A/ABOBq0AAAcrq2B1hK/JgcrJogAFmOBwJN9mJMKAAtWdH8rrliAA1cm8GB4b13wLpDm9ixoALsQTCegJO1JoUxJpoADmLy2JwdcJqBQ4wMGGwKcCrgABUQ1irk3mM3MAgZCeONWTolieYZOFIoQAClZdClagydoU3IoVcIYagDLAcGKQcrCYqgu1iDBgyVDHYjkDmKTCwAABAwVcCYiguTwRFDJ5CeCmJIBAAOAdYQTEUFyHCJwbmEJ4ZDCqxPDrlWBAKkDUFyeCm5PEJAcrdwkGJwjsDDINisSmBlesJ9SFCsRPFUQQEDH4WAJwjwCgxmFeFZPCJw4AFUoSfGDQwQCUFOsg0AmJPaWIagCmKhowIsBrhPNMAJPOxs3KFRPCGYgAJlZPQxsxBANWJ8wzCJxqNDwBPICYxQCUEyNBgxPOriMCJwmADYJPHsUGEwOsd003J51iJ5AbKMgZPmrhPOxqWBlbwEdwQbIMgZPjGYViJ57wGdwYbJT9JPQRYSgDNQTuIWgdW66f2xs3RgRQBKoQTKJ4SfjaZg8KHoMxDJpdCJ/LxCAAUxCJqfkd6gABdgQYNJ9VcJ6WNdoU3CBiuCJ8eBaxqPJgy3Olafl/wnBgBPTKAKeNxs3E4OseHZfQE4KgkeAUrJ8eNmJQl1gmBUE0GKAWBJ8HXlZQCsRQkFIdW1hQfqwlCmLxksU3FQUrUT5PDgE3KEiiGJ8AlCKE2NrjzgJ4VimJTCsSipULgfBlYlBm7zDKMx8CKDWBDoNcOwcGKIUGmM3KkShDwLucEwlcKIalCeUQlBlaeamInIrk3lcrVgYAfrigY1i7CcMIAQUDDtCcESgodoUrJ2WNsQ3BqyeWduQAClaHB65OR1kGT2rwXdwVcJ+rwCJ6Tu4J4dWJ6MrCoMxAGxPUCoQA5mLvUAHZIJA=="),
|
||||
atob("qE5xH+AH4A/AH4A/AH4A/AEOswMrgAACleB1hJ/AAeBqxMDAAsrq1WwJN+TQgALKPesTYkyq9eAAtXlhR9TghMBwYAKr0yewZQ1JwcyJphRIqxOzTgZNPAAdXDAShxToZOUUQTyy1hOCdaChKeN6dZAAcseN+BGAMybQgABcg4KKeIZPsJwUrHIczA4L1Fr0yBIQTBBYdeXQK5BBYRPrqxGFxLXCgEsIYoAFJIOJLIdeNASgqTwUzSoZPELIZDCldWAAIMDCYj6BCARQo1iNBdohPIHodcAARQCmSfFCQhQnTwTXBAAjWCHgdXAgNWJ4dcewSaBNooaCqxPmTw4ABrygCmSmDTwigEfoRSBDYYaCUEqeJKIY7DdwwACBIMzDJAVCJ8iEFABbuHeAcsxIVHq6gmGYRONRIRPJlYWMJ0WsaZSfSgAWJljwkwIyBq5PlmQMB1hPhqwlBrxONxLlCd6WDq5PkQQRPOwczCQJPIlmJJ9wkBJ6FeeBAIBmZmMJ/1WDZkyJ++DlkAlbuGDZYNBqxOh/wzNUBieCmQVKCgRPiwJPSHQRQDXRpkDJ8tXJ6A7CeIKeCNJZPm1jUNAA0zKAQCBlhjOJ80rJ6ODljsCTxgSDlesKESHCG5qNHW56gmqxPUwdXCyKzCwJPkRBw9GCqCgClZQhwLZCUCdeCiKzCKEJPDligTACUzFYRQf1krEgTxUKC1WKLxPDgFXKE1eFgZRdqwiDKFMsKL5PCq4kCmZQmKI0rKTGBJ4QjDlleKNqkX1krNgIjBmQgCmZRpmY0BKLCgCJAVXEAcyrwACUlUrKCZPClggDUQYADUs5REKCdWIY1eq7FEq71naYahTUAUyOY7wpKA1WUDQAxmTxUUAUzxODxIAFA4IJCAQg7ODgojGAgYSCwcrKCgVClgA1HAJPTeAQA5lafUAHZIJA"),
|
||||
atob("qE5xH+AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4AdwOBlcAAAsrq2BJn+BqxMHKX5NFJhgAFqxO5TYcruug0HLAAoIBvdQCIZN11icDqBLHAA+gMYRQ0TgcrvhNOAAaiCeWWBTgZNSKAuBJ17rDvZOVeQK4C1hOxdaYAFvbxvdgZOGbgMlLCF8DwSgrJxSKCKALvRUFmslbsJJ4YMG0F1qElld10ATGgGBJ9BOCvaLHHYgNEIoqsBKAIJFUFDtCurbIvhPHcgcrAAL9DBQclUFDtCGQIAJIIUAcYQHDq2ArmAqxsDfIL2BKFAxCvhPK0F7uoODSYVWrgACwBXCLwYQDlaekE4ROKAA97CwJODAAJuCfwYABuqglwKeNAA9QMoJPFrjwDAAjxBlesd0hOSHgeAJwjwDWRCgh1guBqBPTHYKfHOBIIBqxPhEgN7J6yfFJ5VQBILwgwJPWWwJPK0DwpJ66LBd6OgJ8TvXuoXBJ6HLBINWJ8VQJ6d8HYROEwD5BkpP/bYpPFrgIBuoUHqEAlZPiZxAAMHYWAdw18CY91BYOsJ8WgJ6d7UAzuBN5JPCwJPivagUC4MrJwoeJJ4VcJ72BJ4UrJ6igCKALtCqASJqDvhJ4bwVHodWTwQcJ0AQCJz3+QASCMABclDYd1MBmBJ76ABkrYCvZPUR4QABBxInCT0DuCJYJ3CeKt1NJZdClesd0RKBFIbxVqEldtusdwJJDvgqBqDxVTxjtgdwd8Fgd7KC77MT0H+TwLQGKAT4CJ/9WTwxQGupPbd4QABldWq2B1hPbTwwvDVYJRCUbRxDAAhTCJyusSRowEktQAAKhXvd1qBSHKKmBdxIwFuotFUjQjBvgkElZPWlaOCABRPFChwAPEYpPSqy9GAGlWJ6JO7UJgA=="),
|
||||
atob("qE5xH+AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4AtwNWlcAAAUrq2BJP5MJAApS/JoRMJAApR7JotPumfAA10VQlWJ2+AHwZMB4nDABHEz9PeoesJ2icDp5NLKIpkCKGesG4UlJoJOBKJQJBBYT1BeQRQwwJOCTgI/Bb4V0KAxIBp8llb+BCYlWJ2V0IYbzCgBCBJwgKDBoefkoFCUFuBGISWEIglPBI8rAAIYDCYeAJ2hPJcgmArmAqylGJ9ZODz5OEJ5IICq1cAAZQGlZOuJoiWFVQIICcgRPFrhLCuklAgOBJ0+AlZOJJAYABAwgUBJwtcDwMr4itCeE+sJwV0dgoAKU4UrwBPFeARuBUAMr1jslJyhPBIAMlJ5auCeEotCJyRPBMwRPLeAVWJ0eAE4NPJqLvR4iglwIlBFgQATH4ROFJ4qgmFYUAdqRPSWASghTwclJ6qPDJ4srBIIQGwCejT63DksAlZPHp4iD4gQCT0SfXb4ZPFA4N0CIl0eECeCZgSfWeA4hCz4QHJ7usEANPOgQtFeCagDOYV0OIpPCeDruCugkCZoqgUlbtDkpwGB4UAJ7mATYXEQoNPeC3EXYVWTwS/HJ8ErD4IlBeDXDEAQABNxBPfPQTqCEoSgXIIhtJf4ZOawIeBkomDUDYbCNhJPCwBOZwB6Hz8lK4oAT4lPNZRcCwJOheL10DJHEO4LuZdgUAugoHPAQ2JADDubToZOHAATVBBpb6YgGsJy1WdhJQIlYQMTylWJ05QEUQOfejd0EAOBJzElRh/EFwRRDAATuWkrBBJysrbaufKIhqCd1ydCJyZREQYIACDizuWJzLUDdoLyBDSq9CJ6eBJzYAbJ4WsTyuf4gAzT6usCoKfBp4AzlY4BwBPRCoQA5qxPRJ3ZQMA==")
|
||||
];
|
||||
|
||||
function drawImg (i) {
|
||||
g.drawImage({
|
||||
width: 80, height: 57, bpp: 8,
|
||||
buffer: require("heatshrink").decompress(imgs[i])
|
||||
}, 0, 0, {scale: 3});
|
||||
}
|
||||
|
||||
var currImg = 0;
|
||||
g.clear();
|
||||
drawImg(currImg);
|
||||
setInterval(function() {
|
||||
currImg = (currImg + 1) % imgs.length;
|
||||
drawImg(currImg);
|
||||
}, 200);
|
|
@ -0,0 +1,5 @@
|
|||
{
|
||||
"name":"Party Parrot","type":"app",
|
||||
"icon":"*pparrot",
|
||||
"src":"-pparrot"
|
||||
}
|
Binary file not shown.
After Width: | Height: | Size: 1001 B |
|
@ -15,12 +15,12 @@ Bangle.HID = E.toUint8Array(atob("BQEJBqEBhQIFBxngKecVACUBdQGVCIEClQF1CIEBlQV1AQ
|
|||
}
|
||||
setTimeout(function() {
|
||||
NRF.setServices({}, adv);
|
||||
if (s.ble) NRF.wake();
|
||||
else NRF.sleep();
|
||||
// we just reset, so BLE should be on
|
||||
if (!s.ble) NRF.sleep(); // disable advertising if BLE should be off
|
||||
},10);
|
||||
|
||||
if (!s.vibrate) Bangle.buzz=()=>Promise.resolve();
|
||||
if (!s.beep) Bangle.beep=()=>Promise.resolve();
|
||||
if (!s.vibrate) Bangle.buzz=Promise.resolve;
|
||||
if (!s.beep) Bangle.beep=Promise.resolve;
|
||||
Bangle.setLCDTimeout(s.timeout);
|
||||
if (!s.timeout) Bangle.setLCDPower(1);
|
||||
E.setTimeZone(s.timezone);
|
||||
|
|
20
comms.js
20
comms.js
|
@ -11,7 +11,7 @@ uploadApp : app => {
|
|||
Puck.write("\x03reset();\n", (result) => {
|
||||
if (result===null) return reject("");
|
||||
setTimeout(() => { // wait for reset
|
||||
Puck.write("\x10E.showMessage('Uploading...')\n"+fileContents+"load()\n",(result) => {
|
||||
Puck.write("\x10E.showMessage('Uploading...')\n"+fileContents+"\x10E.showMessage('Hold BTN3\\nto reload')\n",(result) => {
|
||||
if (result===null) return reject("");
|
||||
resolve();
|
||||
});
|
||||
|
@ -38,7 +38,7 @@ removeApp : app => { // expects an app structure
|
|||
}).join("");
|
||||
console.log("removeApp", cmds);
|
||||
return new Promise((resolve,reject) => {
|
||||
Puck.write("\x03"+cmds+"\x10load()\n",(result) => {
|
||||
Puck.write("\x03"+cmds+"\x10E.showMessage('Hold BTN3\\nto reload')\n",(result) => {
|
||||
if (result===null) return reject("");
|
||||
resolve();
|
||||
});
|
||||
|
@ -63,5 +63,21 @@ setTime : () => {
|
|||
resolve();
|
||||
});
|
||||
});
|
||||
},
|
||||
watchConnectionChange : cb => {
|
||||
var connected = Puck.isConnected();
|
||||
|
||||
//TODO Switch to an event listener when Puck will support it
|
||||
var interval = setInterval(() => {
|
||||
if (connected === Puck.isConnected()) return;
|
||||
|
||||
connected = Puck.isConnected();
|
||||
cb(connected);
|
||||
}, 1000);
|
||||
|
||||
//stop watching
|
||||
return () => {
|
||||
clearInterval(interval);
|
||||
};
|
||||
}
|
||||
};
|
||||
|
|
|
@ -35,6 +35,9 @@
|
|||
<a href="https://banglejs.com" class="navbar-brand mr-2"><img src="img/banglejs-logo-sml.png" alt="Bangle.js"> App Loader</a>
|
||||
<!-- <a href="#" class="btn btn-link">...</a> -->
|
||||
</section>
|
||||
<section class="navbar-section">
|
||||
<button class="btn" id="connectmydevice">Connect</button>
|
||||
</section>
|
||||
<!--<section class="navbar-section">
|
||||
<div class="input-group input-inline">
|
||||
<input class="form-input" type="text" placeholder="search">
|
||||
|
|
12
index.js
12
index.js
|
@ -252,6 +252,7 @@ function getInstalledApps() {
|
|||
// Get apps
|
||||
Comms.getInstalledApps().then(appIDs => {
|
||||
appsInstalled = appIDs;
|
||||
handleConnectionChange(true);
|
||||
refreshMyApps();
|
||||
refreshLibrary();
|
||||
}).catch(err => {
|
||||
|
@ -259,10 +260,15 @@ function getInstalledApps() {
|
|||
});
|
||||
}
|
||||
|
||||
var connectMyDeviceBtn = document.getElementById("connectmydevice");
|
||||
|
||||
document.getElementById("myappsrefresh").addEventListener("click",event=>{
|
||||
getInstalledApps();
|
||||
});
|
||||
function handleConnectionChange(connected) {
|
||||
connectMyDeviceBtn.style.display = connected ? 'none' : '';
|
||||
}
|
||||
|
||||
document.getElementById("myappsrefresh").addEventListener("click", getInstalledApps);
|
||||
connectMyDeviceBtn.addEventListener("click", getInstalledApps);
|
||||
Comms.watchConnectionChange(handleConnectionChange);
|
||||
|
||||
// =========================================== About
|
||||
|
||||
|
|
|
@ -0,0 +1,4 @@
|
|||
Testing
|
||||
=======
|
||||
|
||||
Bits of code that could maybe be apps, but that aren't finished yet
|
|
@ -0,0 +1,3 @@
|
|||
This code can take an image file, split it into tiles, and then render those tiles on the watch - making them fit with the GPS data.
|
||||
|
||||
Problem is right now I can't automate getting the rendered area of map, so can't turn it into a very useful tool for BangleApps.
|
|
@ -0,0 +1,83 @@
|
|||
require("Storage").write('+map',{
|
||||
name:"Map",
|
||||
icon:"*map",
|
||||
src:"-map"
|
||||
});
|
||||
require("Storage").write('*map',require("heatshrink").decompress(atob("mEwghC/AH4AWh//mcwBZIWI/4ABmYABBZAgIC4oyDBYggIC4wABBYoX/C90imcykYXUkYBB+YyDC5E/F5EykQXKHwYVCL4YXNkQ+BC4wICHgIvJ+QVBC4oYBkUvO5QXCU4wXBF5INCCwqMDAYTXUC6xHNC5Z3LI5UyF6oADF9ZfL+fTAIIUCkUjR5397s9C4LxBC4MykfzDYYvI7vdC4cyDIciO5c97s/C4QABF4IBBC5QvEAAk/+ZdBC5JfEX6XzmaPEa7oX8+AGBgYXHBYQXHBAoXFCowXCEA4yCBZIA/AH4AO")));
|
||||
|
||||
require("Storage").write("-map",`
|
||||
var s = require("Storage");
|
||||
var hs = require("heatshrink");
|
||||
var map = {
|
||||
imgx : 831,
|
||||
imgy : 656,
|
||||
tilesize : 64,
|
||||
scale : 20000,
|
||||
lat : 51.7075,
|
||||
lon : -1.2948
|
||||
};
|
||||
|
||||
|
||||
map.center = Bangle.project({lat:map.lat,lon:map.lon});
|
||||
var lat = map.lat, lon = map.lon;
|
||||
var fix = {};
|
||||
|
||||
|
||||
function redraw() {
|
||||
var cx = g.getWidth()/2;
|
||||
var cy = g.getHeight()/2;
|
||||
var p = Bangle.project({lat:lat,lon:lon});
|
||||
var ix = (p.x-map.center.x)*4096/map.scale + (map.imgx/2) - cx;
|
||||
var iy = (map.center.y-p.y)*4096/map.scale + (map.imgy/2) - cy;
|
||||
//console.log(ix,iy);
|
||||
var tx = 0|(ix/map.tilesize);
|
||||
var ty = 0|(iy/map.tilesize);
|
||||
var ox = (tx*map.tilesize)-ix;
|
||||
var oy = (ty*map.tilesize)-iy;
|
||||
for (var x=ox,ttx=tx;x<g.getWidth();x+=map.tilesize,ttx++) {
|
||||
for (var y=oy,tty=ty;y<g.getHeight();y+=map.tilesize,tty++) {
|
||||
var img = s.read("t"+ttx+"x"+tty);
|
||||
//print(x,y,ttx,tty,"t"+ttx+"x"+tty,img?"ok":"-");
|
||||
if (img) g.drawImage(hs.decompress(img),x,y);
|
||||
else g.clearRect(x,y,x+map.tilesize-1,y+map.tilesize-1);
|
||||
}
|
||||
}
|
||||
g.setColor(1,0,0);
|
||||
/*g.fillRect(cx-10,cy-1,cx+10,cy+1);
|
||||
g.fillRect(cx-1,cy-10,cx+1,cy+10);*/
|
||||
if (fix.fix)
|
||||
g.fillRect(cx-2,cy-2,cx+2,cy+2);
|
||||
}
|
||||
redraw();
|
||||
|
||||
var fix;
|
||||
Bangle.on('GPS',function(f) {
|
||||
fix=f;
|
||||
g.clearRect(0,0,240,8);
|
||||
g.setColor(1,1,1);
|
||||
g.setFont("6x8");
|
||||
g.setFontAlign(0,0);
|
||||
var txt = fix.satellites+" satellites";
|
||||
if (!fix.fix)
|
||||
txt += " - NO FIX";
|
||||
g.drawString(txt,120,4);
|
||||
if (fix.fix) {
|
||||
var p = Bangle.project({lat:lat,lon:lon});
|
||||
var q = Bangle.project(fix);
|
||||
var cx = g.getWidth()/2;
|
||||
var cy = g.getHeight()/2;
|
||||
var ix = (q.x-p.x)*4096/map.scale + cx;
|
||||
var iy = (q.y-p.y)*4096/map.scale + cy;
|
||||
g.fillRect(ix-2,iy-2,ix+2,iy+2);
|
||||
}
|
||||
});
|
||||
Bangle.setGPSPower(1);
|
||||
redraw();
|
||||
|
||||
setWatch(function() {
|
||||
if (!fix.fix) return;
|
||||
lat = fix.lat;
|
||||
lon = fix.lon;
|
||||
redraw();
|
||||
}, BTN2, {repeat:true});
|
||||
`);
|
|
@ -0,0 +1,155 @@
|
|||
<html>
|
||||
<head>
|
||||
</head>
|
||||
<body>
|
||||
<script src="https://espruino.github.io/EspruinoWebTools/heatshrink.js"></script>
|
||||
<script src="https://espruino.github.io/EspruinoWebTools/imageconverter.js"></script>
|
||||
<!--<script src="https://espruino.github.io/EspruinoWebTools/uart.js"></script>-->
|
||||
<script src="file:///home/gw/workspace/EspruinoWebTools/uart.js"></script>
|
||||
<p>An online map loader for Espruino...</p>
|
||||
Scale <input type="text" id="scale" value="20000"></input><br/>
|
||||
Geo URI <input type="text" id="uri" value="geo:51.7079,-1.2926?z=16"></input><br/>
|
||||
<button id="geturl">Get URL</button><a name="url"></a><br/>
|
||||
<input type="file" id="fileLoader"/><br/>
|
||||
<img id="mapimg"/><br/>
|
||||
<canvas id="canvas" style="display:none;"></canvas>
|
||||
<button id="upload" style="display:none;">Upload</button>
|
||||
<pre id="log"></pre>
|
||||
|
||||
<!--
|
||||
We can request this directly, eg:
|
||||
|
||||
https://render.openstreetmap.org/cgi-bin/export?bbox=-1.27,51.64,-1.26,51.65&scale=20000&format=png
|
||||
https://render.openstreetmap.org/cgi-bin/export?bbox=-1.2731999999999999,51.6472,-1.2632,51.6572&scale=20000&format=png
|
||||
then we need:
|
||||
|
||||
var map = {
|
||||
imgx : 361,
|
||||
imgy : 343,
|
||||
tilesize : 64,
|
||||
scale : 20000, // scale
|
||||
lat : 51.65270, // coords of center
|
||||
lon : -1.27052
|
||||
};
|
||||
|
||||
|
||||
find lat/lon? https://help.openstreetmap.org/questions/2702/extracting-coordinates-by-clicking-on-an-openstreetmap
|
||||
-->
|
||||
|
||||
<script>
|
||||
TILESIZE = 64;
|
||||
|
||||
var img;
|
||||
var tiles = [];
|
||||
|
||||
function log(x) {
|
||||
document.getElementById("log").innerText += x+"\n";
|
||||
console.log(x);
|
||||
}
|
||||
|
||||
function getURL() {
|
||||
var uri = document.getElementById("uri").value;
|
||||
var latlon = uri.match("geo:(-?[0-9\.]+),(-?[0-9\.]+)?");
|
||||
if (latlon==null) {
|
||||
log("Invalid URI!");
|
||||
return;
|
||||
}
|
||||
var map = {
|
||||
imgx :img?img.width:0,
|
||||
imgy : img?img.height:0,
|
||||
lat : parseFloat(latlon[1]),
|
||||
lon : parseFloat(latlon[2]),
|
||||
tilesize : TILESIZE,
|
||||
scale : parseInt(document.getElementById("scale").value)
|
||||
};
|
||||
log(JSON.stringify(map,null,2));
|
||||
var s = 0.005;
|
||||
var x1 = map.lon-s,
|
||||
x2 = map.lon+s,
|
||||
y1 = map.lat-s,
|
||||
y2 = map.lat+s;
|
||||
var url = "https://render.openstreetmap.org/cgi-bin/export?bbox="+x1+","+y1+","+x2+","+y2+"&scale="+map.scale+"&format=png"
|
||||
document.getElementById("url").href = url;
|
||||
document.getElementById("url").innerText = url;
|
||||
/*var mapimg = document.getElementById("mapimg");
|
||||
|
||||
|
||||
mapimg.src = url;
|
||||
mapimg.onload = function() {
|
||||
log("Image loaded!");
|
||||
}*/
|
||||
}
|
||||
|
||||
function imageLoaded() {
|
||||
if (img === undefined) return;
|
||||
var options = { compression:true, mode:"web", output:"string"};
|
||||
|
||||
var canvas = document.getElementById("canvas")
|
||||
canvas.width = TILESIZE*2;
|
||||
canvas.height = TILESIZE;
|
||||
canvas.style = "display:block;border:1px solid black;margin:8px;"
|
||||
var ctx = canvas.getContext("2d");
|
||||
console.log(img.width+"x"+img.height);
|
||||
var w = Math.round(img.width / TILESIZE);
|
||||
var h = Math.round(img.height / TILESIZE);
|
||||
console.log("->"+w+"x"+h);
|
||||
for (var y=0;y<h;y++) {
|
||||
for (var x=0;x<w;x++) {
|
||||
ctx.fillStyle = 'black';
|
||||
ctx.fillRect(0,0,TILESIZE,TILESIZE);
|
||||
ctx.drawImage(img,-x*TILESIZE,-y*TILESIZE);
|
||||
var imageData = ctx.getImageData(0, 0, TILESIZE, TILESIZE);
|
||||
var rgba = imageData.data;
|
||||
options.rgbaOut = rgba;
|
||||
options.width = TILESIZE;
|
||||
options.height = TILESIZE;
|
||||
var imgstr = imageconverter.RGBAtoString(rgba, options);
|
||||
ctx.putImageData(imageData,TILESIZE,0);
|
||||
var compress = 'require("heatshrink").decompress('
|
||||
if (!imgstr.startsWith(compress)) throw "Data in wrong format";
|
||||
imgstr = imgstr.slice(compress.length,-1);
|
||||
tiles.push({
|
||||
name:"t"+x+"x"+y,
|
||||
value:imgstr
|
||||
});
|
||||
}
|
||||
}
|
||||
log("Tiling finished. "+tiles.length+" tiles");
|
||||
document.getElementById("upload").style.display = "block";
|
||||
|
||||
}
|
||||
function handleFileSelect(event) {
|
||||
if (event.target.files.length != 1) return;
|
||||
var reader = new FileReader();
|
||||
reader.onload = function(event) {
|
||||
img = new Image();
|
||||
img.onload = imageLoaded;
|
||||
img.src = event.target.result;
|
||||
};
|
||||
reader.readAsDataURL(event.target.files[0]);
|
||||
};
|
||||
document.getElementById('fileLoader').addEventListener('change', handleFileSelect, false);
|
||||
|
||||
|
||||
document.getElementById('geturl').addEventListener('click', getURL);
|
||||
document.getElementById('upload').addEventListener('click', function() {
|
||||
UART.write("\x03s=require('Storage');\n", function() {
|
||||
log("Connected");
|
||||
function upload() {
|
||||
if (!tiles.length) {
|
||||
log("Success!");
|
||||
return;
|
||||
}
|
||||
var tile = tiles.shift();
|
||||
log("Uploading "+tile.name);
|
||||
UART.eval('s.write('+JSON.stringify(tile.name)+','+tile.value+')',function(r) {
|
||||
log("Returned "+r);
|
||||
upload();
|
||||
});
|
||||
}
|
||||
upload();
|
||||
});
|
||||
}, false);
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
Loading…
Reference in New Issue