mirror of https://github.com/espruino/BangleApps
Merge branch 'master' of github.com:espruino/BangleApps
commit
c419425ea0
11
apps.json
11
apps.json
|
@ -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": [
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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);
|
Loading…
Reference in New Issue