mirror of https://github.com/espruino/BangleApps
Merge branch 'master' into master
commit
0e5e96ab9b
52
apps.json
52
apps.json
|
@ -115,7 +115,7 @@
|
|||
{
|
||||
"id": "setting",
|
||||
"name": "Settings",
|
||||
"version": "0.31",
|
||||
"version": "0.33",
|
||||
"description": "A menu for setting up Bangle.js",
|
||||
"icon": "settings.png",
|
||||
"tags": "tool,system",
|
||||
|
@ -540,6 +540,21 @@
|
|||
],
|
||||
"data": [{"name":"trex.score","storageFile":true}]
|
||||
},
|
||||
{
|
||||
"id": "cubescramble",
|
||||
"name": "Cube Scramble",
|
||||
"version":"0.01",
|
||||
"description": "A random scramble generator for the 3x3 Rubik's cube",
|
||||
"icon": "cube-scramble.png",
|
||||
"tags": "",
|
||||
"supports" : ["BANGLEJS","BANGLEJS2"],
|
||||
"readme": "README.md",
|
||||
"allow_emulator": true,
|
||||
"storage": [
|
||||
{"name":"cubescramble.app.js","url":"cube-scramble.js"},
|
||||
{"name":"cubescramble.img","url":"cube-scramble-icon.js","evaluate":true}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "astroid",
|
||||
"name": "Asteroids!",
|
||||
|
@ -4216,7 +4231,40 @@
|
|||
],
|
||||
"data": [{ "name": "qalarm.json" }]
|
||||
},
|
||||
{ "id": "lcars",
|
||||
{
|
||||
"id": "emojuino",
|
||||
"name": "Emojuino",
|
||||
"shortName": "Emojuino",
|
||||
"version": "0.01",
|
||||
"description": "Emojis & Espruino: broadcast Unicode emojis via Bluetooth Low Energy.",
|
||||
"icon": "emojuino.png",
|
||||
"tags": "emoji",
|
||||
"supports" : [ "BANGLEJS2" ],
|
||||
"readme": "README.md",
|
||||
"storage": [
|
||||
{ "name": "emojuino.app.js", "url": "emojuino.js" },
|
||||
{ "name": "emojuino.img", "url": "emojuino-icon.js", "evaluate": true }
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "cliclockJS2Enhanced",
|
||||
"name": "Commandline-Clock JS2 Enhanced",
|
||||
"shortName": "CLI-Clock JS2",
|
||||
"version": "0.1",
|
||||
"description": "Simple CLI-Styled Clock with enhancements. Modes that are hard to use and unneded are removed (BPM, battery info, memory ect) credit to hughbarney for the original code and design",
|
||||
"icon": "app.png",
|
||||
"screenshots": [{"url":"screengrab.png"}],
|
||||
"type": "clock",
|
||||
"tags": "clock,cli,command,bash,shell",
|
||||
"supports": ["BANGLEJS","BANGLEJS2"],
|
||||
"allow_emulator": true,
|
||||
"storage": [
|
||||
{"name":"cliclockJS2Enhanced.app.js","url":"app.js"},
|
||||
{"name":"cliclockJS2Enhanced.img","url":"app.icon.js","evaluate":true}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "lcars",
|
||||
"name": "LCARS Clock",
|
||||
"shortName":"LCARS",
|
||||
"icon": "lcars.png",
|
||||
|
|
|
@ -103,7 +103,7 @@ if (Bangle.swipeHandler) {
|
|||
Bangle.removeListener("swipe", Bangle.swipeHandler);
|
||||
delete Bangle.swipeHandler;
|
||||
}
|
||||
if (Bangle.touchandler) {
|
||||
if (Bangle.touchHandler) {
|
||||
Bangle.removeListener("touch", Bangle.touchHandler);
|
||||
delete Bangle.touchHandler;
|
||||
}
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
require("heatshrink").decompress(atob("mEwwkBiIA/AH4A/AH4A8gAAKC8gKUC7Rf/C/PM5gDBjnBC6EcC4PBDIIbCC5/BAIIXVA4YXXAoRHUC6R3EC6KnEMAbv/C6oAKC8YA/AH4A/AH4Ax"))
|
|
@ -0,0 +1,216 @@
|
|||
var fontsize = g.getWidth()>200 ? 3 : 2;
|
||||
var fontsizeTime = g.getWidth()>200 ? 4 : 4;
|
||||
|
||||
var fontheight = 10*fontsize;
|
||||
var fontheightTime = 10*fontsizeTime;
|
||||
var locale = require("locale");
|
||||
var marginTop = 40;
|
||||
var flag = false;
|
||||
|
||||
var hrtOn = false;
|
||||
var hrtStr = "Hrt: ??? bpm";
|
||||
|
||||
const NONE_MODE = "none";
|
||||
const ID_MODE = "id";
|
||||
const VER_MODE = "ver";
|
||||
const BATT_MODE = "batt";
|
||||
const MEM_MODE = "mem";
|
||||
const STEPS_MODE = "step";
|
||||
const HRT_MODE = "hrt";
|
||||
const NONE_FN_MODE = "no_fn";
|
||||
const HRT_FN_MODE = "fn_hrt";
|
||||
|
||||
let infoMode = NONE_MODE;
|
||||
let functionMode = NONE_FN_MODE;
|
||||
|
||||
let textCol = g.theme.dark ? "#0f0" : "#080";
|
||||
|
||||
function drawAll(){
|
||||
updateTime();
|
||||
updateRest(new Date());
|
||||
}
|
||||
|
||||
function updateRest(now){
|
||||
writeLine(locale.dow(now),1);
|
||||
writeLine(locale.date(now,1),2);
|
||||
drawInfo(5);
|
||||
}
|
||||
function updateTime(){
|
||||
if (!Bangle.isLCDOn()) return;
|
||||
let now = new Date();
|
||||
writeLine(locale.time(now,1),0);
|
||||
writeLine(flag?" ":"_",3);
|
||||
flag = !flag;
|
||||
if(now.getMinutes() == 0)
|
||||
updateRest(now);
|
||||
}
|
||||
function writeLineStart(line){
|
||||
if (line==0){
|
||||
g.drawString(">",0,marginTop+(line)*fontheight);
|
||||
} else {
|
||||
g.drawString(">",4,marginTop+(line-1)*fontheight + fontheightTime);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
function writeLine(str,line){
|
||||
if (line == 0){
|
||||
var y = marginTop+line*fontheightTime;
|
||||
g.setFont("6x8",fontsizeTime);
|
||||
g.setColor(textCol).setFontAlign(-1,-1);
|
||||
g.clearRect(0,y,((str.length+1)*40),y+fontheightTime-1);
|
||||
writeLineStart(line);
|
||||
g.drawString(str,25,y);
|
||||
} else {
|
||||
var y = marginTop+(line-1)*fontheight+fontheightTime;
|
||||
g.setFont("6x8",fontsize);
|
||||
g.setColor(textCol).setFontAlign(-1,-1);
|
||||
g.clearRect(0,y,((str.length+1)*20),y+fontheight-1);
|
||||
writeLineStart(line);
|
||||
g.drawString(str,25,y);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
function drawInfo(line) {
|
||||
let val;
|
||||
let str = "";
|
||||
let col = textCol; // green
|
||||
|
||||
//console.log("drawInfo(), infoMode=" + infoMode + " funcMode=" + functionMode);
|
||||
|
||||
switch(functionMode) {
|
||||
case NONE_FN_MODE:
|
||||
break;
|
||||
case HRT_FN_MODE:
|
||||
col = g.theme.dark ? "#0ff": "#088"; // cyan
|
||||
str = "HRM: " + (hrtOn ? "ON" : "OFF");
|
||||
drawModeLine(line,str,col);
|
||||
return;
|
||||
}
|
||||
|
||||
switch(infoMode) {
|
||||
case NONE_MODE:
|
||||
col = g.theme.bg;
|
||||
str = "";
|
||||
break;
|
||||
case HRT_MODE:
|
||||
str = hrtStr;
|
||||
break;
|
||||
case STEPS_MODE:
|
||||
str = "Steps: " + stepsWidget().getSteps();
|
||||
break;
|
||||
case ID_MODE:
|
||||
val = NRF.getAddress().split(":");
|
||||
str = "Id: " + val[4] + val[5];
|
||||
break;
|
||||
case VER_MODE:
|
||||
str = "Fw: " + process.env.VERSION;
|
||||
break;
|
||||
case MEM_MODE:
|
||||
val = process.memory();
|
||||
str = "Memory: " + Math.round(val.usage*100/val.total) + "%";
|
||||
break;
|
||||
case BATT_MODE:
|
||||
default:
|
||||
str = "Battery: " + E.getBattery() + "%";
|
||||
}
|
||||
|
||||
drawModeLine(line,str,col);
|
||||
}
|
||||
|
||||
function drawModeLine(line, str, col) {
|
||||
g.setColor(col);
|
||||
var y = marginTop+line*fontheight;
|
||||
g.fillRect(0, y, 239, y+fontheight-1);
|
||||
g.setColor(g.theme.bg).setFontAlign(0, 0);
|
||||
g.drawString(str, g.getWidth()/2, y+fontheight/2);
|
||||
}
|
||||
|
||||
function changeInfoMode() {
|
||||
switch(functionMode) {
|
||||
case NONE_FN_MODE:
|
||||
break;
|
||||
case HRT_FN_MODE:
|
||||
hrtOn = !hrtOn;
|
||||
Bangle.buzz();
|
||||
Bangle.setHRMPower(hrtOn ? 1 : 0);
|
||||
if (hrtOn) infoMode = HRT_MODE;
|
||||
return;
|
||||
}
|
||||
|
||||
switch(infoMode) {
|
||||
case NONE_MODE:
|
||||
if (stepsWidget() !== undefined)
|
||||
infoMode = hrtOn ? HRT_MODE : STEPS_MODE;
|
||||
else
|
||||
infoMode = VER_MODE;
|
||||
break;
|
||||
case HRT_MODE:
|
||||
if (stepsWidget() !== undefined)
|
||||
infoMode = STEPS_MODE;
|
||||
else
|
||||
infoMode = VER_MODE;
|
||||
break;
|
||||
case STEPS_MODE:
|
||||
infoMode = ID_MODE;
|
||||
break;
|
||||
case ID_MODE:
|
||||
infoMode = VER_MODE;
|
||||
break;
|
||||
case VER_MODE:
|
||||
infoMode = BATT_MODE;
|
||||
break;
|
||||
case BATT_MODE:
|
||||
infoMode = MEM_MODE;
|
||||
break;
|
||||
case MEM_MODE:
|
||||
default:
|
||||
infoMode = NONE_MODE;
|
||||
}
|
||||
}
|
||||
|
||||
function changeFunctionMode() {
|
||||
//console.log("changeFunctionMode()");
|
||||
switch(functionMode) {
|
||||
case NONE_FN_MODE:
|
||||
functionMode = HRT_FN_MODE;
|
||||
break;
|
||||
case HRT_FN_MODE:
|
||||
default:
|
||||
functionMode = NONE_FN_MODE;
|
||||
}
|
||||
//console.log(functionMode);
|
||||
|
||||
}
|
||||
|
||||
function stepsWidget() {
|
||||
if (WIDGETS.activepedom !== undefined) {
|
||||
return WIDGETS.activepedom;
|
||||
} else if (WIDGETS.wpedom !== undefined) {
|
||||
return WIDGETS.wpedom;
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
Bangle.on('HRM', function(hrm) {
|
||||
if(hrm.confidence > 90){
|
||||
hrtStr = "Hrt: " + hrm.bpm + " bpm";
|
||||
} else {
|
||||
hrtStr = "Hrt: ??? bpm";
|
||||
}
|
||||
});
|
||||
|
||||
g.clear();
|
||||
Bangle.loadWidgets();
|
||||
Bangle.drawWidgets();
|
||||
drawAll();
|
||||
Bangle.on('lcdPower',function(on) {
|
||||
if (on) drawAll();
|
||||
});
|
||||
var click = setInterval(updateTime, 1000);
|
||||
// Show launcher when button pressed
|
||||
Bangle.setUI("clockupdown", btn=>{
|
||||
if (btn<0) changeInfoMode();
|
||||
drawAll();
|
||||
});
|
Binary file not shown.
After Width: | Height: | Size: 6.0 KiB |
Binary file not shown.
After Width: | Height: | Size: 421 B |
Binary file not shown.
After Width: | Height: | Size: 2.3 KiB |
|
@ -0,0 +1 @@
|
|||
0.01: Initial Release
|
|
@ -0,0 +1,18 @@
|
|||
# Cube Scramble
|
||||
|
||||
A random scramble generator for the 3x3 Rubik's cube
|
||||
|
||||
## Future features
|
||||
|
||||
I'm keen to complete this project with
|
||||
|
||||
* Add a timer
|
||||
* Add the ability for times to be stored and exported
|
||||
|
||||
## Requests
|
||||
|
||||
Please reach out if you have feature requests or notice bugs.
|
||||
|
||||
## Creator
|
||||
|
||||
Made by [Nathan Lisgo](https://github.com/nlisgo)
|
|
@ -0,0 +1 @@
|
|||
require("heatshrink").decompress(atob("3YANB54AFgf/+ULCqOw/4ACC6EAxEAC4fwCp2YxGIwEPC4XxGBewqEICwIABGAUQRJWwp3u9xFBAAQUCr3u8gwHgAVBC4ugCwIKDC5nghGAgEODoIKEC44PBBgUAggFDBQZIHhAMB8j4CMgQHBgoDBoB5H3BuC5nM4AqDJAIABgnd7owF3GAhgWBAAJbD8oWBCoIABoAXLqBIBCoNmC4nQC4xGCJAQVBs93u9ghoYDJAmwwFwFwYWBCoIABuBeC7oLBGAmBu0MFgMFDIMHDAZIB6AhBiCoFBgIVBJAQXFAAMv//wI4kBKoJgDSIIVBuwVBgP/AAIXEJoNnuCRFg9gCoPwh4XHTwMHvxHDPQc///xC5PgC4PgCoPFLIQSC+QXEVAb9CunggpYCwMDC4/9C4bnBqFldQWIAAIXH+FNC4deJAMAC4IWCxECC4nybQQXDh3u8vQC4qiEHILxCC4ewF4PdJQIXDO4UwgEYC42wgEOC4NeoAXE+IsBhAFBC4u16EAC4PV8AWCwCpCCwIXDoBGD7rPB7vUC4UQCwRmDBoPQuwXE6ghCgAVEgsBC4fQu4XFD4MN7tE8oWD7oXEu4XE3YXCqHdovuoCgDI4WBC4VwC4YsB6HMgjBBYQKHCC4OKhnAC4K+DJAQXB4DxB9wfBC4cFBYN3tYWDAAO9C4PMC48ABQPAIogADqAMCpwXFhgKCIohJErgNBgoXDqHxC4QWIAAINCg1errmBh4XC4AWJAAIwBg9gonQgf/+QXBFxRJCC4N2OYP/C4VQCxZJCg61Bh4XB+cACxoABC4VvC4PxCx5JBC4k7C6AwCuf/+AWRAANnuX/RZhJIuBFSAAaLMA="))
|
|
@ -0,0 +1,74 @@
|
|||
|
||||
// Scramble code from: https://raw.githubusercontent.com/bjcarlson42/blog-post-sample-code/master/Rubik's%20Cube%20JavaScript%20Scrambler/part_two.js
|
||||
const makeScramble = () => {
|
||||
const options = ["F", "F2", "F'", "R", "R2", "R'", "U", "U2", "U'", "B", "B2", "B'", "L", "L2", "L'", "D", "D2", "D'"];
|
||||
const numOptions = [0, 1, 2, 3, 4, 5]; // 0 = F, 1 = R, 2 = U, 3 = B, 4 = L, 5 = D
|
||||
const scrambleMoves = [];
|
||||
let bad = true;
|
||||
|
||||
while (bad) {
|
||||
let scramble = [];
|
||||
for (let i = 0; i < 20; i++) {
|
||||
scramble.push(numOptions[getRandomInt(6)]);
|
||||
}
|
||||
// check if moves directly next to each other involve the same letter
|
||||
for (let i = 0; i < 20 - 1; i++) {
|
||||
if (scramble[i] == scramble[i + 1]) {
|
||||
bad = true;
|
||||
break;
|
||||
} else {
|
||||
bad = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
// switch numbers to letters
|
||||
let move;
|
||||
for (let i = 0; i < 20; i++) {
|
||||
switch (scramble[i]) {
|
||||
case 0:
|
||||
move = options[getRandomInt(3)]; // 0,1,2
|
||||
scrambleMoves.push(move);
|
||||
break;
|
||||
case 1:
|
||||
move = options[getRandomIntBetween(3, 6)]; // 3,4,5
|
||||
scrambleMoves.push(move);
|
||||
break;
|
||||
case 2:
|
||||
move = options[getRandomIntBetween(6, 9)]; // 6,7,8
|
||||
scrambleMoves.push(move);
|
||||
break;
|
||||
case 3:
|
||||
move = options[getRandomIntBetween(9, 12)]; // 9,10,11
|
||||
scrambleMoves.push(move);
|
||||
break;
|
||||
case 4:
|
||||
move = options[getRandomIntBetween(12, 15)]; // 12,13,14
|
||||
scrambleMoves.push(move);
|
||||
break;
|
||||
case 5:
|
||||
move = options[getRandomIntBetween(15, 18)]; // 15,16,17
|
||||
scrambleMoves.push(move);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return scrambleMoves;
|
||||
};
|
||||
|
||||
const getRandomInt = max => Math.floor(Math.random() * Math.floor(max)); // returns up to max - 1
|
||||
|
||||
const getRandomIntBetween = (min, max) => Math.floor(Math.random() * (max - min) + min);
|
||||
|
||||
const presentScramble = () => {
|
||||
g.clear();
|
||||
E.showMessage(makeScramble().join(" "));
|
||||
};
|
||||
|
||||
const init = () => {
|
||||
presentScramble();
|
||||
|
||||
setWatch(() => {
|
||||
presentScramble();
|
||||
}, BTN1, {repeat:true});
|
||||
};
|
||||
|
||||
init();
|
Binary file not shown.
After Width: | Height: | Size: 3.1 KiB |
|
@ -0,0 +1 @@
|
|||
0.01: New App!
|
|
@ -0,0 +1,28 @@
|
|||
# Emojuino
|
||||
|
||||
Emojis & Espruino!
|
||||
|
||||
|
||||
## Usage
|
||||
|
||||
Select an emoji and then tap to transmit! The emoji will be recognised by [Pareto Anywhere](https://www.reelyactive.com/pareto/anywhere/) open source middleware and any other program which observes the [InteroperaBLE Identifier](https://reelyactive.github.io/interoperable-identifier/) open standard.
|
||||
|
||||
|
||||
## Features
|
||||
|
||||
Currently implements a tiny subset of possible [Unicode emojis](https://unicode.org/emoji/charts/full-emoji-list.html) which are advertised as an [InteroperaBLE Identifier](https://reelyactive.github.io/interoperable-identifier/) encapsulated as Eddystone UID.
|
||||
|
||||
|
||||
## Controls
|
||||
|
||||
Swipe left/right to select the emoji to broadcast. Tap the screen to initiate the broadcast. Emoji will flash while broadcasting, which lasts for 5 seconds.
|
||||
|
||||
|
||||
## Requests
|
||||
|
||||
[Contact reelyActive](https://www.reelyactive.com/contact/) for support/updates.
|
||||
|
||||
|
||||
## Creator
|
||||
|
||||
Developed by [jeffyactive](https://github.com/jeffyactive) of [reelyActive](https://www.reelyactive.com)
|
|
@ -0,0 +1 @@
|
|||
require("heatshrink").decompress(atob("mEwwkBiIAHkUoxGIwUiBxAAGiQVCAAeCkIWNCooADDBYWKDBYWEkc////+cyDBhxDCoQAD+YLDCw0YBQQVFAAYYCwIXFHQRDElGCJYgOCFw8vBwPyOgoJFGAg4BIoQWGDAhJCIwoLBHgYAGJQIjCIwguCnCRFRoeDGAZICAgOPFwaRGDAQfB/AwDBAYuCX44wDAgTrDBoIDBGYP/manBmYFBFYQPDwJeBD4iRGRoQ/FC4QqBEYIbERooTBCAeBNAIjBBQIDDAAggBG4IDDwQXBEQIDDUAgcCHASaBAYQTFMQpcFDYp+EEII9DAARRDFIIfDHIwXBVISlDC4YzD9wA0osFpwIF8lQqgWK8kAgEEBItABIIhGAAfgBoMABIoIChwX0jwED8oNBgoXFqAJBrwHD8IXEBwQNEEIYgFC4wAQ8MRC6sRC+BgULwIwHSINVpwuLC43kaAQABqgaHC4bZHAAkFqhGHGAovFAAYyDCwgwFL4IwGFxAwNFxIwG8lVCoSTEFw7bPCxAYNCxT0LIpIxMCpoyHFhI"))
|
|
@ -0,0 +1,145 @@
|
|||
/**
|
||||
* Copyright reelyActive 2021
|
||||
* We believe in an open Internet of Things
|
||||
*/
|
||||
|
||||
|
||||
// Emojis are integer pairs with the form [ image, Unicode code point ]
|
||||
// For code points see https://unicode.org/emoji/charts/emoji-list.html
|
||||
const EMOJIS = [
|
||||
[ ':)', 0x1f642 ], // Slightly smiling
|
||||
[ ':|', 0x1f610 ], // Neutral
|
||||
[ ':(', 0x1f641 ], // Slightly frowning
|
||||
[ '+1', 0x1f44d ], // Thumbs up
|
||||
[ '-1', 0x1f44e ], // Thumbs down
|
||||
[ '<3', 0x02764 ], // Heart
|
||||
];
|
||||
const EMOJI_TRANSMISSION_MILLISECONDS = 5000;
|
||||
const BLINK_PERIOD_MILLISECONDS = 500;
|
||||
const TRANSMIT_BUZZ_MILLISECONDS = 200;
|
||||
const CYCLE_BUZZ_MILLISECONDS = 50;
|
||||
|
||||
// Non-user-configurable constants
|
||||
const IMAGE_INDEX = 0;
|
||||
const CODE_POINT_INDEX = 1;
|
||||
const BTN_WATCH_OPTIONS = { repeat: true, debounce: 20, edge: "falling" };
|
||||
const UNICODE_CODE_POINT_ELIDED_UUID = [ 0x49, 0x6f, 0x49, 0x44, 0x55,
|
||||
0x54, 0x46, 0x2d, 0x33, 0x32 ];
|
||||
|
||||
|
||||
// Global variables
|
||||
let emojiIndex = 0;
|
||||
let isToggleOn = false;
|
||||
let isTransmitting = false;
|
||||
let lastDragX = 0;
|
||||
let lastDragY = 0;
|
||||
|
||||
|
||||
// Cycle through emojis
|
||||
function cycleEmoji(isForward) {
|
||||
if(isTransmitting) { return; }
|
||||
|
||||
if(isForward) {
|
||||
emojiIndex = (emojiIndex + 1) % EMOJIS.length;
|
||||
}
|
||||
else if(--emojiIndex < 0) {
|
||||
emojiIndex = EMOJIS.length - 1;
|
||||
}
|
||||
|
||||
drawImage(EMOJIS[emojiIndex][IMAGE_INDEX]);
|
||||
Bangle.buzz(CYCLE_BUZZ_MILLISECONDS);
|
||||
}
|
||||
|
||||
|
||||
// Handle a touch: transmit displayed emoji
|
||||
function handleTouch(zone, event) {
|
||||
if(isTransmitting) { return; }
|
||||
|
||||
let emoji = EMOJIS[emojiIndex];
|
||||
transmitEmoji(emoji[IMAGE_INDEX], emoji[CODE_POINT_INDEX],
|
||||
EMOJI_TRANSMISSION_MILLISECONDS);
|
||||
Bangle.buzz(TRANSMIT_BUZZ_MILLISECONDS);
|
||||
}
|
||||
|
||||
|
||||
// Transmit the given code point for the given duration in milliseconds,
|
||||
// blinking the image once per second.
|
||||
function transmitEmoji(image, codePoint, duration) {
|
||||
let instance = [ 0x00, 0x00, (codePoint >> 24) & 0xff,
|
||||
(codePoint >> 16) & 0xff, (codePoint >> 8) & 0xff,
|
||||
codePoint & 0xff ];
|
||||
|
||||
require('ble_eddystone_uid').advertise(UNICODE_CODE_POINT_ELIDED_UUID,
|
||||
instance);
|
||||
isTransmitting = true;
|
||||
|
||||
let displayIntervalId = setInterval(toggleImage, BLINK_PERIOD_MILLISECONDS,
|
||||
image);
|
||||
|
||||
setTimeout(terminateEmoji, duration, displayIntervalId);
|
||||
}
|
||||
|
||||
|
||||
// Terminate the emoji transmission
|
||||
function terminateEmoji(displayIntervalId) {
|
||||
NRF.setAdvertising({ });
|
||||
isTransmitting = false;
|
||||
clearInterval(displayIntervalId);
|
||||
drawImage(EMOJIS[emojiIndex][IMAGE_INDEX]);
|
||||
}
|
||||
|
||||
|
||||
// Toggle the display between image/off
|
||||
function toggleImage(image) {
|
||||
if(isToggleOn) {
|
||||
drawImage(EMOJIS[emojiIndex][IMAGE_INDEX]);
|
||||
}
|
||||
else {
|
||||
g.clear();
|
||||
}
|
||||
isToggleOn = !isToggleOn;
|
||||
}
|
||||
|
||||
|
||||
// Draw the given emoji
|
||||
function drawImage(image) {
|
||||
g.clear();
|
||||
g.drawString(image, g.getWidth() / 2, g.getHeight() / 2);
|
||||
g.flip();
|
||||
}
|
||||
|
||||
|
||||
// Handle a drag event
|
||||
function handleDrag(event) {
|
||||
let isFingerReleased = (event.b === 0);
|
||||
|
||||
if(isFingerReleased) {
|
||||
let isHorizontalDrag = (Math.abs(lastDragX) >= Math.abs(lastDragY)) &&
|
||||
(lastDragX !== 0);
|
||||
|
||||
if(isHorizontalDrag) {
|
||||
cycleEmoji(lastDragX > 0);
|
||||
}
|
||||
}
|
||||
else {
|
||||
lastDragX = event.dx;
|
||||
lastDragY = event.dy;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Special function to handle display switch on
|
||||
Bangle.on('lcdPower', (on) => {
|
||||
if(on) {
|
||||
drawImage(EMOJIS[emojiIndex][IMAGE_INDEX]);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
// On start: display the first emoji and handle drag and touch events
|
||||
g.clear();
|
||||
g.setFont('Vector', 80);
|
||||
g.setFontAlign(0, 0);
|
||||
drawImage(EMOJIS[emojiIndex][IMAGE_INDEX]);
|
||||
Bangle.on('touch', handleTouch);
|
||||
Bangle.on('drag', handleDrag);
|
Binary file not shown.
After Width: | Height: | Size: 1.9 KiB |
|
@ -34,3 +34,5 @@
|
|||
0.29: Add Customize to Theme menu
|
||||
0.30: Move '< Back' to the top of menus
|
||||
0.31: Remove Bangle 1 settings when running on Bangle 2
|
||||
0.32: Fix 'beep' menu on Bangle.js 2
|
||||
0.33: Really fix 'beep' menu on Bangle.js 2 this time
|
||||
|
|
|
@ -38,7 +38,7 @@ function resetSettings() {
|
|||
quiet: 0, // quiet mode: 0: off, 1: priority only, 2: total silence
|
||||
timeout: 10, // Default LCD timeout in seconds
|
||||
vibrate: true, // Vibration enabled by default. App must support
|
||||
beep: "vib", // Beep enabled by default. App must support
|
||||
beep: BANGLEJS2?true:"vib", // Beep enabled by default. App must support
|
||||
timezone: 0, // Set the timezone for the device
|
||||
HID: false, // BLE HID mode, off by default
|
||||
clock: null, // a string for the default clock's name
|
||||
|
@ -72,8 +72,37 @@ if (!('qmOptions' in settings)) settings.qmOptions = {}; // easier if this alway
|
|||
const boolFormat = v => v ? "On" : "Off";
|
||||
|
||||
function showMainMenu() {
|
||||
var beepV = BANGLEJS2 ? [false,true] : [false, true, "vib"];
|
||||
var beepN = BANGLEJS2 ? ["Off","On"] : ["Off", "Piezo", "Vibrate"];
|
||||
var beepMenuItem;
|
||||
if (BANGLEJS2) {
|
||||
beepMenuItem = {
|
||||
value: settings.beep!=false,
|
||||
format: boolFormat,
|
||||
onchange: v => {
|
||||
settings.beep = v;
|
||||
updateSettings();
|
||||
if (settings.beep) {
|
||||
analogWrite(VIBRATE,0.1,{freq:2000});
|
||||
setTimeout(()=>VIBRATE.reset(),200);
|
||||
} // beep with vibration moter
|
||||
}
|
||||
};
|
||||
} else { // Bangle.js 1
|
||||
var beepV = [false, true, "vib"];
|
||||
var beepN = ["Off", "Piezo", "Vibrate"];
|
||||
beepMenuItem = {
|
||||
value: Math.max(0 | beepV.indexOf(settings.beep),0),
|
||||
min: 0, max: beepV.length-1,
|
||||
format: v => beepN[v],
|
||||
onchange: v => {
|
||||
settings.beep = beepV[v];
|
||||
if (v==1) { analogWrite(D18,0.5,{freq:2000});setTimeout(()=>D18.reset(),200); } // piezo on Bangle.js 1
|
||||
else if (v==2) { analogWrite(VIBRATE,0.1,{freq:2000});setTimeout(()=>VIBRATE.reset(),200); } // vibrate
|
||||
updateSettings();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
const mainmenu = {
|
||||
'': { 'title': 'Settings' },
|
||||
'< Back': ()=>load(),
|
||||
|
@ -88,17 +117,7 @@ function showMainMenu() {
|
|||
updateSettings();
|
||||
}
|
||||
},
|
||||
'Beep': {
|
||||
value: 0 | beepV.indexOf(settings.beep),
|
||||
min: 0, max: 2,
|
||||
format: v => beepN[v],
|
||||
onchange: v => {
|
||||
settings.beep = beepV[v];
|
||||
if (v==1) { analogWrite(D18,0.5,{freq:2000});setTimeout(()=>D18.reset(),200); } // piezo
|
||||
else if (v==2) { analogWrite(D13,0.1,{freq:2000});setTimeout(()=>D13.reset(),200); } // vibrate
|
||||
updateSettings();
|
||||
}
|
||||
},
|
||||
'Beep': beepMenuItem,
|
||||
'Vibration': {
|
||||
value: settings.vibrate,
|
||||
format: boolFormat,
|
||||
|
@ -146,7 +165,7 @@ function showBLEMenu() {
|
|||
}
|
||||
},
|
||||
'HID': {
|
||||
value: 0 | hidV.indexOf(settings.HID),
|
||||
value: Math.max(0,0 | hidV.indexOf(settings.HID)),
|
||||
min: 0, max: 3,
|
||||
format: v => hidN[v],
|
||||
onchange: v => {
|
||||
|
|
Loading…
Reference in New Issue