Merge branch 'master' of github.com:espruino/BangleApps

pull/1093/head
Gordon Williams 2021-12-15 10:11:11 +00:00
commit c419425ea0
6 changed files with 155 additions and 23 deletions

View File

@ -1699,14 +1699,15 @@
"id": "rtorch", "id": "rtorch",
"name": "Red Torch", "name": "Red Torch",
"shortName": "RedTorch", "shortName": "RedTorch",
"version": "0.01", "version": "0.02",
"description": "Turns screen RED to help you see in the dark without breaking your night vision. Select from the launcher or press BTN3,BTN1,BTN3,BTN1 quickly to start when in any app that shows widgets", "description": "Turns screen RED to help you see in the dark without breaking your night vision. Select from the launcher or on Bangle 1 press BTN3,BTN1,BTN3,BTN1 quickly to start when in any app that shows widgets",
"icon": "app.png", "icon": "app.png",
"tags": "tool,torch", "tags": "tool,torch",
"supports": ["BANGLEJS"], "supports": ["BANGLEJS","BANGLEJS2"],
"allow_emulator": true,
"storage": [ "storage": [
{"name":"rtorch.app.js","url":"app.js"}, {"name":"rtorch.app.js","url":"app.js"},
{"name":"rtorch.wid.js","url":"widget.js"}, {"name":"rtorch.wid.js","url":"widget.js", "supports": ["BANGLEJS"]},
{"name":"rtorch.img","url":"app-icon.js","evaluate":true} {"name":"rtorch.img","url":"app-icon.js","evaluate":true}
] ]
}, },
@ -4649,7 +4650,7 @@
"id": "sensible", "id": "sensible",
"name": "SensiBLE", "name": "SensiBLE",
"shortName": "SensiBLE", "shortName": "SensiBLE",
"version": "0.03", "version": "0.04",
"description": "Collect, display and advertise real-time sensor data.", "description": "Collect, display and advertise real-time sensor data.",
"icon": "sensible.png", "icon": "sensible.png",
"screenshots": [ "screenshots": [

View File

@ -1 +1,2 @@
0.01: Cloning torch and making it red :D 0.01: Cloning torch and making it red :D
0.02: Modify for setUI and Bangle 2

View File

@ -2,21 +2,38 @@ Bangle.setLCDPower(1);
Bangle.setLCDTimeout(0); Bangle.setLCDTimeout(0);
g.reset(); g.reset();
c = 1; c = 1;
function setColor(delta){ function setColor(delta){
c+=delta; c+=delta;
c = Math.max(c,0); c = Math.max(c,0);
c = Math.min(c,2); c = Math.min(c,2);
if (c<1){ if (c<1){
g.setColor(c,0,0); g.setColor(c,0,0);
Bangle.setLCDBrightness(c >= 0.1 ? c : 0.1);
}else{ }else{
g.setColor(1,c-1,c-1); g.setColor(1,c-1,c-1);
Bangle.setLCDBrightness(1);
} }
g.fillRect(0,0,g.getWidth(),g.getHeight()); g.fillRect(0,0,g.getWidth(),g.getHeight());
} }
setColor(0)
// BTN1 light up toward white function updownHandler(direction){
// BTN3 light down to red if (direction == undefined){
// BTN2 to reset c=1;
setWatch(()=>setColor(0.1), BTN1, { repeat:true, edge:"rising", debounce: 50 }); setColor(0);
setWatch(()=>load(), BTN2); } else {
setWatch(()=>setColor(-0.1), BTN3, { repeat:true, edge:"rising", debounce: 50 }); setColor(-direction * 0.1);
}
}
setColor(0);
// Bangle 1:
// BTN1: light up toward white
// BTN3: light down to red
// BTN2: reset
// Bangle 2:
// Swipe up: light up toward white
// Swipe down: light down to red
// BTN1: reset
Bangle.setUI("updown", updownHandler);

View File

@ -1,3 +1,4 @@
0.01: New App! 0.01: New App!
0.02: Corrected variable initialisation 0.02: Corrected variable initialisation
0.03: Advertise app name, added screenshots 0.03: Advertise app name, added screenshots
0.04: Advertise bar, GPS, HRM and mag services

View File

@ -17,7 +17,7 @@ Currently implements:
- Heart Rate Monitor - Heart Rate Monitor
- Magnetometer - Magnetometer
in the menu display but NOT YET in Bluetooth Low Energy advertising (which will be implemented in a subsequent version). in the menu display, and broadcasts all sensor data readings _except_ acceleration in Bluetooth Low Energy advertising packets as GATT characteristic services.
## Controls ## Controls

View File

@ -7,6 +7,9 @@
// Non-user-configurable constants // Non-user-configurable constants
const APP_ID = 'sensible'; const APP_ID = 'sensible';
const ESPRUINO_COMPANY_CODE = 0x0590; const ESPRUINO_COMPANY_CODE = 0x0590;
const APP_ADVERTISING_DATA = [ 0x12, 0xff, 0x90, 0x05, 0x7b, 0x6e, 0x61, 0x6d,
0x65, 0x3a, 0x73, 0x65, 0x6e, 0x73, 0x69, 0x62,
0x6c, 0x65, 0x7d ];
// Global variables // Global variables
@ -20,6 +23,12 @@ let isBarEnabled = true;
let isGpsEnabled = true; let isGpsEnabled = true;
let isHrmEnabled = true; let isHrmEnabled = true;
let isMagEnabled = true; let isMagEnabled = true;
let isNewAccData = false;
let isNewBarData = false;
let isNewGpsData = false;
let isNewHrmData = false;
let isNewMagData = false;
// Menus // Menus
@ -91,22 +100,121 @@ let magMenu = {
}; };
// Transmit the app name under the Espruino company code to facilitate discovery // Check for new sensor data and update the advertising sequence
function transmitAppName() { function transmitUpdatedSensorData() {
let options = { let data = [ APP_ADVERTISING_DATA ]; // Always advertise at least app name
showName: false,
manufacturer: ESPRUINO_COMPANY_CODE, if(isNewBarData) {
manufacturerData: JSON.stringify({ name: APP_ID }), data.push(encodeBarServiceData());
interval: 2000 isNewBarData = false;
} }
NRF.setAdvertising({}, options); if(isNewGpsData && gps.lat && gps.lon) {
data.push(encodeGpsServiceData());
isNewGpsData = false;
}
if(isNewHrmData) {
data.push({ 0x2a37: [ 0, hrm.bpm ] });
isNewHrmData = false;
}
if(isNewMagData) {
data.push(encodeMagServiceData());
isNewMagData = false;
}
NRF.setAdvertising(data, { showName: false, interval: 200 });
}
// Encode the bar service data to fit in a Bluetooth PDU
function encodeBarServiceData() {
let tEncoded = Math.round(bar.temperature * 100);
let pEncoded = Math.round(bar.pressure * 100);
let eEncoded = Math.round(bar.altitude * 100);
if(bar.temperature < 0) {
tEncoded += 0x10000;
}
if(bar.altitude < 0) {
eEncoded += 0x1000000;
}
let t = [ tEncoded & 0xff, (tEncoded >> 8) & 0xff ];
let p = [ pEncoded & 0xff, (pEncoded >> 8) & 0xff, (pEncoded >> 16) & 0xff,
(pEncoded >> 24) & 0xff ];
let e = [ eEncoded & 0xff, (eEncoded >> 8) & 0xff, (eEncoded >> 16) & 0xff ];
return [
0x02, 0x01, 0x06, // Flags
0x05, 0x16, 0x6e, 0x2a, t[0], t[1], // Temperature
0x07, 0x16, 0x6d, 0x2a, p[0], p[1], p[2], p[3], // Pressure
0x06, 0x16, 0x6c, 0x2a, e[0], e[1], e[2] // Elevation
];
}
// Encode the GPS service data using the Location and Speed characteristic
function encodeGpsServiceData() {
let latEncoded = Math.round(gps.lat * 10000000);
let lonEncoded = Math.round(gps.lon * 10000000);
let hEncoded = Math.round(gps.course * 100);
let sEncoded = Math.round(1000 * gps.speed / 36);
if(gps.lat < 0) {
latEncoded += 0x100000000;
}
if(gps.lon < 0) {
lonEncoded += 0x100000000;
}
let s = [ sEncoded & 0xff, (sEncoded >> 8) & 0xff ];
let lat = [ latEncoded & 0xff, (latEncoded >> 8) & 0xff,
(latEncoded >> 16) & 0xff, (latEncoded >> 24) & 0xff ];
let lon = [ lonEncoded & 0xff, (lonEncoded >> 8) & 0xff,
(lonEncoded >> 16) & 0xff, (lonEncoded >> 24) & 0xff ];
let h = [ hEncoded & 0xff, (hEncoded >> 8) & 0xff ];
return [
0x02, 0x01, 0x06, // Flags
0x11, 0x16, 0x67, 0x2a, 0x95, 0x02, s[0], s[1], lat[0], lat[1], lat[2],
lat[3], lon[0], lon[1], lon[2], lon[3], h[0], h[1] // Location and Speed
];
}
// Encode the mag service data using the magnetic flux density 3D characteristic
function encodeMagServiceData() {
let xEncoded = mag.x; // TODO: units???
let yEncoded = mag.y;
let zEncoded = mag.z;
if(xEncoded < 0) {
xEncoded += 0x10000;
}
if(yEncoded < 0) {
yEncoded += 0x10000;
}
if(yEncoded < 0) {
yEncoded += 0x10000;
}
let x = [ xEncoded & 0xff, (xEncoded >> 8) & 0xff ];
let y = [ yEncoded & 0xff, (yEncoded >> 8) & 0xff ];
let z = [ zEncoded & 0xff, (zEncoded >> 8) & 0xff ];
return [
0x02, 0x01, 0x06, // Flags
0x09, 0x16, 0xa1, 0x2a, x[0], x[1], y[0], y[1], z[0], z[1] // Mag 3D
];
} }
// Update acceleration // Update acceleration
Bangle.on('accel', function(newAcc) { Bangle.on('accel', function(newAcc) {
acc = newAcc; acc = newAcc;
isNewAccData = true;
if(isAccMenu) { if(isAccMenu) {
accMenu.x.value = acc.x.toFixed(2); accMenu.x.value = acc.x.toFixed(2);
@ -119,6 +227,7 @@ Bangle.on('accel', function(newAcc) {
// Update barometer // Update barometer
Bangle.on('pressure', function(newBar) { Bangle.on('pressure', function(newBar) {
bar = newBar; bar = newBar;
isNewBarData = true;
if(isBarMenu) { if(isBarMenu) {
barMenu.Altitude.value = bar.altitude.toFixed(1) + 'm'; barMenu.Altitude.value = bar.altitude.toFixed(1) + 'm';
@ -131,6 +240,7 @@ Bangle.on('pressure', function(newBar) {
// Update GPS // Update GPS
Bangle.on('GPS', function(newGps) { Bangle.on('GPS', function(newGps) {
gps = newGps; gps = newGps;
isNewGpsData = true;
if(isGpsMenu) { if(isGpsMenu) {
gpsMenu.Lat.value = gps.lat.toFixed(4); gpsMenu.Lat.value = gps.lat.toFixed(4);
@ -145,6 +255,7 @@ Bangle.on('GPS', function(newGps) {
// Update heart rate monitor // Update heart rate monitor
Bangle.on('HRM', function(newHrm) { Bangle.on('HRM', function(newHrm) {
hrm = newHrm; hrm = newHrm;
isNewHrmData = true;
if(isHrmMenu) { if(isHrmMenu) {
hrmMenu.BPM.value = hrm.bpm; hrmMenu.BPM.value = hrm.bpm;
@ -156,6 +267,7 @@ Bangle.on('HRM', function(newHrm) {
// Update magnetometer // Update magnetometer
Bangle.on('mag', function(newMag) { Bangle.on('mag', function(newMag) {
mag = newMag; mag = newMag;
isNewMagData = true;
if(isMagMenu) { if(isMagMenu) {
magMenu.x.value = mag.x; magMenu.x.value = mag.x;
@ -169,9 +281,9 @@ Bangle.on('mag', function(newMag) {
// On start: enable sensors and display main menu // On start: enable sensors and display main menu
g.clear(); g.clear();
transmitAppName();
Bangle.setBarometerPower(isBarEnabled, APP_ID); Bangle.setBarometerPower(isBarEnabled, APP_ID);
Bangle.setGPSPower(isGpsEnabled, APP_ID); Bangle.setGPSPower(isGpsEnabled, APP_ID);
Bangle.setHRMPower(isHrmEnabled, APP_ID); Bangle.setHRMPower(isHrmEnabled, APP_ID);
Bangle.setCompassPower(isMagEnabled, APP_ID); Bangle.setCompassPower(isMagEnabled, APP_ID);
E.showMenu(mainMenu); E.showMenu(mainMenu);
setInterval(transmitUpdatedSensorData, 1000);