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",
|
||||
"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": [
|
||||
|
|
|
@ -1 +1,2 @@
|
|||
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);
|
||||
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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
Loading…
Reference in New Issue