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",
"name": "Red Torch",
"shortName": "RedTorch",
"version": "0.01",
"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",
"version": "0.02",
"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",
"tags": "tool,torch",
"supports": ["BANGLEJS"],
"supports": ["BANGLEJS","BANGLEJS2"],
"allow_emulator": true,
"storage": [
{"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}
]
},
@ -4649,7 +4650,7 @@
"id": "sensible",
"name": "SensiBLE",
"shortName": "SensiBLE",
"version": "0.03",
"version": "0.04",
"description": "Collect, display and advertise real-time sensor data.",
"icon": "sensible.png",
"screenshots": [

View File

@ -1 +1,2 @@
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);
g.reset();
c = 1;
function setColor(delta){
c+=delta;
c = Math.max(c,0);
c = Math.min(c,2);
if (c<1){
g.setColor(c,0,0);
Bangle.setLCDBrightness(c >= 0.1 ? c : 0.1);
}else{
g.setColor(1,c-1,c-1);
Bangle.setLCDBrightness(1);
}
g.fillRect(0,0,g.getWidth(),g.getHeight());
}
setColor(0)
// BTN1 light up toward white
// BTN3 light down to red
// BTN2 to reset
setWatch(()=>setColor(0.1), BTN1, { repeat:true, edge:"rising", debounce: 50 });
setWatch(()=>load(), BTN2);
setWatch(()=>setColor(-0.1), BTN3, { repeat:true, edge:"rising", debounce: 50 });
function updownHandler(direction){
if (direction == undefined){
c=1;
setColor(0);
} else {
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.02: Corrected variable initialisation
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
- 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

View File

@ -7,6 +7,9 @@
// Non-user-configurable constants
const APP_ID = 'sensible';
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
@ -20,6 +23,12 @@ let isBarEnabled = true;
let isGpsEnabled = true;
let isHrmEnabled = true;
let isMagEnabled = true;
let isNewAccData = false;
let isNewBarData = false;
let isNewGpsData = false;
let isNewHrmData = false;
let isNewMagData = false;
// Menus
@ -91,22 +100,121 @@ let magMenu = {
};
// Transmit the app name under the Espruino company code to facilitate discovery
function transmitAppName() {
let options = {
showName: false,
manufacturer: ESPRUINO_COMPANY_CODE,
manufacturerData: JSON.stringify({ name: APP_ID }),
interval: 2000
// Check for new sensor data and update the advertising sequence
function transmitUpdatedSensorData() {
let data = [ APP_ADVERTISING_DATA ]; // Always advertise at least app name
if(isNewBarData) {
data.push(encodeBarServiceData());
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
Bangle.on('accel', function(newAcc) {
acc = newAcc;
isNewAccData = true;
if(isAccMenu) {
accMenu.x.value = acc.x.toFixed(2);
@ -119,6 +227,7 @@ Bangle.on('accel', function(newAcc) {
// Update barometer
Bangle.on('pressure', function(newBar) {
bar = newBar;
isNewBarData = true;
if(isBarMenu) {
barMenu.Altitude.value = bar.altitude.toFixed(1) + 'm';
@ -131,6 +240,7 @@ Bangle.on('pressure', function(newBar) {
// Update GPS
Bangle.on('GPS', function(newGps) {
gps = newGps;
isNewGpsData = true;
if(isGpsMenu) {
gpsMenu.Lat.value = gps.lat.toFixed(4);
@ -145,6 +255,7 @@ Bangle.on('GPS', function(newGps) {
// Update heart rate monitor
Bangle.on('HRM', function(newHrm) {
hrm = newHrm;
isNewHrmData = true;
if(isHrmMenu) {
hrmMenu.BPM.value = hrm.bpm;
@ -156,6 +267,7 @@ Bangle.on('HRM', function(newHrm) {
// Update magnetometer
Bangle.on('mag', function(newMag) {
mag = newMag;
isNewMagData = true;
if(isMagMenu) {
magMenu.x.value = mag.x;
@ -169,9 +281,9 @@ Bangle.on('mag', function(newMag) {
// On start: enable sensors and display main menu
g.clear();
transmitAppName();
Bangle.setBarometerPower(isBarEnabled, APP_ID);
Bangle.setGPSPower(isGpsEnabled, APP_ID);
Bangle.setHRMPower(isHrmEnabled, APP_ID);
Bangle.setCompassPower(isMagEnabled, APP_ID);
E.showMenu(mainMenu);
setInterval(transmitUpdatedSensorData, 1000);