Merge branch 'espruino:master' into master
commit
e8918680b1
|
|
@ -2,3 +2,4 @@
|
|||
0.02: Stopped watchface from flashing every interval
|
||||
0.03: Move to Bangle.setUI to launcher support
|
||||
0.04: Tweaks for compatibility with BangleJS2
|
||||
0.05: Time-word now readable on Bangle.js 2
|
||||
|
|
|
|||
|
|
@ -46,7 +46,7 @@ const dy = big ? 22 : 16;
|
|||
const fontSize = big ? 3 : 2; // "6x8"
|
||||
const passivColor = 0x3186 /*grey*/ ;
|
||||
const activeColorNight = 0xF800 /*red*/ ;
|
||||
const activeColorDay = 0xFFFF /* white */;
|
||||
const activeColorDay = g.theme.fg;
|
||||
|
||||
var hidxPrev;
|
||||
var showDigitalTime = false;
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
{
|
||||
"id": "impwclock",
|
||||
"name": "Imprecise Word Clock",
|
||||
"version": "0.04",
|
||||
"version": "0.05",
|
||||
"description": "Imprecise word clock for vacations, weekends, and those who never need accurate time.",
|
||||
"icon": "clock-impword.png",
|
||||
"type": "clock",
|
||||
|
|
|
|||
|
|
@ -2,4 +2,5 @@
|
|||
0.02: Corrected variable initialisation
|
||||
0.03: Advertise app name, added screenshots
|
||||
0.04: Advertise bar, GPS, HRM and mag services
|
||||
0.05: Refactored for efficiency, corrected sensor value inaccuracies
|
||||
0.05: Refactored for efficiency, corrected sensor value inaccuracies
|
||||
0.06: User settings are written to persistent storage, loaded on app start
|
||||
|
|
@ -5,7 +5,9 @@ Collect all the sensor data from the Bangle.js 2, display the live readings in m
|
|||
|
||||
## Usage
|
||||
|
||||
The advertising packets will be recognised by [Pareto Anywhere](https://www.reelyactive.com/pareto/anywhere/) open source middleware and any other program which observes the standard packet types. Also convenient for testing individual sensors of the Bangle.js 2 via the menu interface.
|
||||
The advertising packets will be recognised by [Pareto Anywhere](https://www.reelyactive.com/pareto/anywhere/) open source middleware and any other program which observes the standard packet types. See our [Bangle.js Development Guide](https://reelyactive.github.io/diy/banglejs-dev/) for details. Also convenient for testing individual sensors of the Bangle.js 2 via the menu interface.
|
||||
|
||||

|
||||
|
||||
|
||||
## Features
|
||||
|
|
@ -22,7 +24,7 @@ in the menu display, and broadcasts all sensor data readings _except_ accelerati
|
|||
|
||||
## Controls
|
||||
|
||||
Browse and control sensors using the standard Espruino menu interface.
|
||||
Browse and control sensors using the standard Espruino menu interface. By default, all sensors _except_ the accelerometer are disabled. Sensors can be individually enabled/disabled via the menu. These settings are written to persistent storage (flash) and will be applied each time the SensiBLE app is loaded.
|
||||
|
||||
|
||||
## Requests
|
||||
|
|
|
|||
|
|
@ -1,25 +1,28 @@
|
|||
{
|
||||
"id": "sensible",
|
||||
"name": "SensiBLE",
|
||||
"shortName": "SensiBLE",
|
||||
"version": "0.05",
|
||||
"description": "Collect, display and advertise real-time sensor data.",
|
||||
"icon": "sensible.png",
|
||||
"screenshots": [
|
||||
{ "url": "screenshot-top.png" },
|
||||
{ "url": "screenshot-acc.png" },
|
||||
{ "url": "screenshot-bar.png" },
|
||||
{ "url": "screenshot-gps.png" },
|
||||
{ "url": "screenshot-hrm.png" },
|
||||
{ "url": "screenshot-mag.png" }
|
||||
],
|
||||
"type": "app",
|
||||
"tags": "tool,sensors,bluetooth",
|
||||
"supports" : [ "BANGLEJS2" ],
|
||||
"allow_emulator": true,
|
||||
"readme": "README.md",
|
||||
"storage": [
|
||||
{ "name": "sensible.app.js", "url": "sensible.js" },
|
||||
{ "name": "sensible.img", "url": "sensible-icon.js", "evaluate": true }
|
||||
]
|
||||
"id": "sensible",
|
||||
"name": "SensiBLE",
|
||||
"shortName": "SensiBLE",
|
||||
"version": "0.06",
|
||||
"description": "Collect, display and advertise real-time sensor data.",
|
||||
"icon": "sensible.png",
|
||||
"screenshots": [
|
||||
{ "url": "screenshot-top.png" },
|
||||
{ "url": "screenshot-acc.png" },
|
||||
{ "url": "screenshot-bar.png" },
|
||||
{ "url": "screenshot-gps.png" },
|
||||
{ "url": "screenshot-hrm.png" },
|
||||
{ "url": "screenshot-mag.png" }
|
||||
],
|
||||
"type": "app",
|
||||
"tags": "tool,sensors,bluetooth",
|
||||
"supports" : [ "BANGLEJS2" ],
|
||||
"allow_emulator": true,
|
||||
"readme": "README.md",
|
||||
"storage": [
|
||||
{ "name": "sensible.app.js", "url": "sensible.js" },
|
||||
{ "name": "sensible.img", "url": "sensible-icon.js", "evaluate": true }
|
||||
],
|
||||
"data": [
|
||||
{ "name": "sensible.data.json", "url": "settings.json", "storageFile": true }
|
||||
]
|
||||
}
|
||||
|
|
|
|||
Binary file not shown.
|
After Width: | Height: | Size: 45 KiB |
|
|
@ -1,5 +1,5 @@
|
|||
/**
|
||||
* Copyright reelyActive 2021
|
||||
* Copyright reelyActive 2021-2022
|
||||
* We believe in an open Internet of Things
|
||||
*/
|
||||
|
||||
|
|
@ -7,6 +7,8 @@
|
|||
// Non-user-configurable constants
|
||||
const APP_ID = 'sensible';
|
||||
const ESPRUINO_COMPANY_CODE = 0x0590;
|
||||
const SETTINGS_FILENAME = 'sensible.data.json';
|
||||
const UPDATE_MILLISECONDS = 1000;
|
||||
const APP_ADVERTISING_DATA = [ 0x12, 0xff, 0x90, 0x05, 0x7b, 0x6e, 0x61, 0x6d,
|
||||
0x65, 0x3a, 0x73, 0x65, 0x6e, 0x73, 0x69, 0x62,
|
||||
0x6c, 0x65, 0x7d ];
|
||||
|
|
@ -19,16 +21,12 @@ let isBarMenu = false;
|
|||
let isGpsMenu = false;
|
||||
let isHrmMenu = false;
|
||||
let isMagMenu = false;
|
||||
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;
|
||||
|
||||
let settings = require('Storage').readJSON(SETTINGS_FILENAME);
|
||||
|
||||
|
||||
// Menus
|
||||
|
|
@ -51,9 +49,9 @@ let accMenu = {
|
|||
let barMenu = {
|
||||
"": { "title" : "- Barometer -" },
|
||||
"State": {
|
||||
value: isBarEnabled,
|
||||
value: settings.isBarEnabled,
|
||||
format: v => v ? "On" : "Off",
|
||||
onchange: v => { isBarEnabled = v; Bangle.setBarometerPower(v, APP_ID); }
|
||||
onchange: v => { updateSetting('isBarEnabled', v); }
|
||||
},
|
||||
"Altitude": { value: null },
|
||||
"Press": { value: null },
|
||||
|
|
@ -63,9 +61,9 @@ let barMenu = {
|
|||
let gpsMenu = {
|
||||
"": { "title" : "- GPS -" },
|
||||
"State": {
|
||||
value: isGpsEnabled,
|
||||
value: settings.isGpsEnabled,
|
||||
format: v => v ? "On" : "Off",
|
||||
onchange: v => { isGpsEnabled = v; Bangle.setGPSPower(v, APP_ID); }
|
||||
onchange: v => { updateSetting('isGpsEnabled', v); }
|
||||
},
|
||||
"Lat": { value: null },
|
||||
"Lon": { value: null },
|
||||
|
|
@ -77,9 +75,9 @@ let gpsMenu = {
|
|||
let hrmMenu = {
|
||||
"": { "title" : "- Heart Rate -" },
|
||||
"State": {
|
||||
value: isHrmEnabled,
|
||||
value: settings.isHrmEnabled,
|
||||
format: v => v ? "On" : "Off",
|
||||
onchange: v => { isHrmEnabled = v; Bangle.setHRMPower(v, APP_ID); }
|
||||
onchange: v => { updateSetting('isHrmEnabled', v); }
|
||||
},
|
||||
"BPM": { value: null },
|
||||
"Confidence": { value: null },
|
||||
|
|
@ -88,9 +86,9 @@ let hrmMenu = {
|
|||
let magMenu = {
|
||||
"": { "title" : "- Magnetometer -" },
|
||||
"State": {
|
||||
value: isMagEnabled,
|
||||
value: settings.isMagEnabled,
|
||||
format: v => v ? "On" : "Off",
|
||||
onchange: v => { isMagEnabled = v; Bangle.setCompassPower(v, APP_ID); }
|
||||
onchange: v => { updateSetting('isMagEnabled', v); }
|
||||
},
|
||||
"x": { value: null },
|
||||
"y": { value: null },
|
||||
|
|
@ -124,7 +122,7 @@ function transmitUpdatedSensorData() {
|
|||
isNewMagData = false;
|
||||
}
|
||||
|
||||
let interval = 1000 / data.length;
|
||||
let interval = UPDATE_MILLISECONDS / data.length;
|
||||
NRF.setAdvertising(data, { showName: false, interval: interval });
|
||||
}
|
||||
|
||||
|
|
@ -190,6 +188,23 @@ function toByteArray(value, numberOfBytes, isSigned) {
|
|||
}
|
||||
|
||||
|
||||
// Enable the sensors as per the current settings
|
||||
function enableSensors() {
|
||||
Bangle.setBarometerPower(settings.isBarEnabled, APP_ID);
|
||||
Bangle.setGPSPower(settings.isGpsEnabled, APP_ID);
|
||||
Bangle.setHRMPower(settings.isHrmEnabled, APP_ID);
|
||||
Bangle.setCompassPower(settings.isMagEnabled, APP_ID);
|
||||
}
|
||||
|
||||
|
||||
// Update the given setting and write to persistent storage
|
||||
function updateSetting(name, value) {
|
||||
settings[name] = value;
|
||||
require('Storage').writeJSON(SETTINGS_FILENAME, settings);
|
||||
enableSensors();
|
||||
}
|
||||
|
||||
|
||||
// Update acceleration
|
||||
Bangle.on('accel', function(newAcc) {
|
||||
acc = newAcc;
|
||||
|
|
@ -260,9 +275,6 @@ Bangle.on('mag', function(newMag) {
|
|||
|
||||
// On start: enable sensors and display main menu
|
||||
g.clear();
|
||||
Bangle.setBarometerPower(isBarEnabled, APP_ID);
|
||||
Bangle.setGPSPower(isGpsEnabled, APP_ID);
|
||||
Bangle.setHRMPower(isHrmEnabled, APP_ID);
|
||||
Bangle.setCompassPower(isMagEnabled, APP_ID);
|
||||
enableSensors();
|
||||
E.showMenu(mainMenu);
|
||||
setInterval(transmitUpdatedSensorData, 1000);
|
||||
setInterval(transmitUpdatedSensorData, UPDATE_MILLISECONDS);
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
{
|
||||
"isBarEnabled": false,
|
||||
"isGpsEnabled": false,
|
||||
"isHrmEnabled": false,
|
||||
"isMagEnabled": false
|
||||
}
|
||||
|
|
@ -1,2 +1,3 @@
|
|||
0.01: New App!
|
||||
0.02: Respect Quiet Mode
|
||||
0.03: Add compatibility for Bangle.js 2 and new firmware, added "Alarm at " for the alarm time
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
const BANGLEJS2 = process.env.HWVERSION == 2; //# check for bangle 2
|
||||
const alarms = require("Storage").readJSON("alarm.json",1)||[];
|
||||
const active = alarms.filter(a=>a.on);
|
||||
|
||||
|
|
@ -52,21 +53,21 @@ active.forEach(alarm => {
|
|||
}
|
||||
});
|
||||
|
||||
function drawString(s, x, y) {
|
||||
g.clearRect(0,y-15,239,y+15);
|
||||
g.reset();
|
||||
g.setFont("Vector",20);
|
||||
g.setFontAlign(0,0); // align right bottom
|
||||
g.drawString(s, x, y);
|
||||
function drawString(s, y) { //# replaced x: always centered
|
||||
g.reset(); //# moved up to prevent blue background
|
||||
g.clearRect(0, y - 12, 239, y + 8); //# minimized upper+lower clearing
|
||||
g.setFont("Vector", 20);
|
||||
g.setFontAlign(0, 0); // align centered
|
||||
g.drawString(s, g.getWidth() / 2, y); //# set x to center
|
||||
}
|
||||
|
||||
function drawApp() {
|
||||
g.clearRect(0,24,239,215);
|
||||
g.clearRect(0,24,239,215); //# no problem
|
||||
var alarmHour = nextAlarm.getHours();
|
||||
var alarmMinute = nextAlarm.getMinutes();
|
||||
if (alarmHour < 10) alarmHour = "0" + alarmHour;
|
||||
if (alarmMinute < 10) alarmMinute = "0" + alarmMinute;
|
||||
const s = alarmHour + ":" + alarmMinute + "\n\n";
|
||||
const s = "Alarm at " + alarmHour + ":" + alarmMinute + "\n\n"; //# make distinct to time
|
||||
E.showMessage(s, "Sleep Phase Alarm");
|
||||
|
||||
function drawTime() {
|
||||
|
|
@ -78,12 +79,20 @@ function drawApp() {
|
|||
if (nowHour < 10) nowHour = "0" + nowHour;
|
||||
if (nowMinute < 10) nowMinute = "0" + nowMinute;
|
||||
if (nowSecond < 10) nowSecond = "0" + nowSecond;
|
||||
const time = nowHour + ":" + nowMinute + ":" + nowSecond;
|
||||
drawString(time, 120, 140);
|
||||
const time = nowHour + ":" + nowMinute + (BANGLEJS2 ? "" : ":" + nowSecond); //# hide seconds on bangle 2
|
||||
drawString(time, BANGLEJS2 ? 85 : 105); //# remove x, adjust height for bangle 2 an newer firmware
|
||||
}
|
||||
}
|
||||
|
||||
setInterval(drawTime, 500); // 2Hz
|
||||
if (BANGLEJS2) {
|
||||
drawTime();
|
||||
setTimeout(_ => {
|
||||
drawTime();
|
||||
setInterval(drawTime, 60000);
|
||||
}, 60000 - Date.now() % 60000); //# every new minute on bangle 2
|
||||
} else {
|
||||
setInterval(drawTime, 500); // 2Hz
|
||||
}
|
||||
}
|
||||
|
||||
var buzzCount = 19;
|
||||
|
|
@ -104,8 +113,8 @@ function buzz() {
|
|||
var minAlarm = new Date();
|
||||
var measure = true;
|
||||
if (nextAlarm !== undefined) {
|
||||
Bangle.loadWidgets(); //# correct widget load draw order
|
||||
Bangle.drawWidgets();
|
||||
Bangle.loadWidgets();
|
||||
|
||||
// minimum alert 30 minutes early
|
||||
minAlarm.setTime(nextAlarm.getTime() - (30*60*1000));
|
||||
|
|
@ -116,7 +125,7 @@ if (nextAlarm !== undefined) {
|
|||
|
||||
if (swest !== undefined) {
|
||||
if (Bangle.isLCDOn()) {
|
||||
drawString(swest ? "Sleep" : "Awake", 120, 180);
|
||||
drawString(swest ? "Sleep" : "Awake", BANGLEJS2 ? 150 : 180); //# remove x, adjust height
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -133,6 +142,6 @@ if (nextAlarm !== undefined) {
|
|||
E.showMessage('No Alarm');
|
||||
setTimeout(load, 1000);
|
||||
}
|
||||
// BTN2 to menu, BTN3 to main
|
||||
setWatch(Bangle.showLauncher, BTN2, { repeat: false, edge: "falling" });
|
||||
setWatch(() => load(), BTN3, { repeat: false, edge: "falling" });
|
||||
// BTN2 to menu, BTN3 to main # on bangle 2 only BTN to main
|
||||
if (!BANGLEJS2) setWatch(Bangle.showLauncher, BTN2, { repeat: false, edge: "falling" });
|
||||
setWatch(() => load(), BANGLEJS2 ? BTN : BTN3, { repeat: false, edge: "falling" });
|
||||
|
|
|
|||
|
|
@ -2,11 +2,11 @@
|
|||
"id": "sleepphasealarm",
|
||||
"name": "SleepPhaseAlarm",
|
||||
"shortName": "SleepPhaseAlarm",
|
||||
"version": "0.02",
|
||||
"version": "0.03",
|
||||
"description": "Uses the accelerometer to estimate sleep and wake states with the principle of Estimation of Stationary Sleep-segments (ESS, see https://ubicomp.eti.uni-siegen.de/home/datasets/ichi14/index.html.en). This app will read the next alarm from the alarm application and will wake you up to 30 minutes early at the best guessed time when you are almost already awake.",
|
||||
"icon": "app.png",
|
||||
"tags": "alarm",
|
||||
"supports": ["BANGLEJS"],
|
||||
"supports": ["BANGLEJS","BANGLEJS2"],
|
||||
"storage": [
|
||||
{"name":"sleepphasealarm.app.js","url":"app.js"},
|
||||
{"name":"sleepphasealarm.img","url":"app-icon.js","evaluate":true}
|
||||
|
|
|
|||
Loading…
Reference in New Issue