Cleanup app and widget and fix B2 drawing compatibility

Add screenshot
pull/1189/head
Ivor Hewitt 2021-12-29 14:04:50 +00:00
parent f2a02642fd
commit 2d387c8e07
8 changed files with 90 additions and 92 deletions

View File

@ -4964,7 +4964,7 @@
{ {
"id": "coretemp", "id": "coretemp",
"name": "CoreTemp", "name": "CoreTemp",
"version": "0.03", "version": "0.02",
"description": "Display CoreTemp device sensor data", "description": "Display CoreTemp device sensor data",
"icon": "coretemp.png", "icon": "coretemp.png",
"type": "app", "type": "app",
@ -4978,7 +4978,8 @@
{"name":"coretemp.img","url":"coretemp-icon.js","evaluate":true}, {"name":"coretemp.img","url":"coretemp-icon.js","evaluate":true},
{"name":"coretemp.boot.js","url":"boot.js"} {"name":"coretemp.boot.js","url":"boot.js"}
], ],
"data": [{"name":"coretemp.json","url":"app-settings.json"}] "data": [{"name":"coretemp.json","url":"app-settings.json"}],
"screenshots": [{"url":"screenshot.png"}]
}, },
{ {
"id": "showimg", "id": "showimg",

View File

@ -1 +1,2 @@
0.01: New app 0.01: New app
0.02: Cleanup interface and add settings, widget, add skin temp reporting.

View File

@ -1,19 +1,18 @@
# CoreTemp display # CoreTemp display
Basic bare-bones example of connecting to a bluetooth [CoreTemp](https://corebodytemp.com/) device and displaying the current body core temperature readings. Basic example of connecting to a bluetooth [CoreTemp](https://corebodytemp.com/) device and displaying the current skin and body core temperature readings.
## Usage ## Usage
On startup connects to a CoreTemp device (1809/2A1C) and emits a "Core, temp" value for each reading. Background task connects to any CoreTemp device (2100/2101) and emits a CoreTemp signal value for each reading.
The app simply displays these readings on screen. Application contains three components, one is a background task that monitors the sensor and emits a 'CoreTemp' signal on activity if activated in settings.
The widget shows when the sensor is enabled with a mini value and blinks on use.
The app listens for 'CoreTemp' signals and shows the current skin and core temperatures in large numbers.
## TODO ## TODO
* Integrate with other tracking/sports apps to log data. * Integrate with other tracking/sports apps to log data.
* Add device selection * Add specific device selection
* Provide enable/disable option
* Check status, add Retry/reconnect
* Also provide skin temp reading
## Creator ## Creator

View File

@ -2,7 +2,7 @@
// If enabled in settings run constantly in background // If enabled in settings run constantly in background
// //
(function() { (function() {
var log = function() {};//print
var settings = {}; var settings = {};
var device; var device;
var gatt; var gatt;
@ -28,8 +28,16 @@ class CoreSensor {
this.unit = "C"; this.unit = "C";
} }
if (flags & 1) this.skin = (dv.buffer[4] * 256 + dv.buffer[3]) / 100; if (flags & 1) {
if (flags & 2) this.core = (dv.buffer[2] * 256 + dv.buffer[1]) / 100; this.skin = (dv.buffer[4] * 256 + dv.buffer[3]) / 100;
} else {
this.skin = 0;
}
if (flags & 2) {
this.core = (dv.buffer[2] * 256 + dv.buffer[1]) / 100;
} else {
this.core = 0;
}
Bangle.emit('CoreTemp', Bangle.emit('CoreTemp',
{core : this.core, skin : this.skin, unit : this.unit}); {core : this.core, skin : this.skin, unit : this.unit});
@ -55,11 +63,11 @@ function getSensorBatteryLevel(gatt) {
} }
function connection_setup() { function connection_setup() {
console.log("Scanning for CoreTemp sensor..."); log("Scanning for CoreTemp sensor...");
NRF.requestDevice({timeout : 20000, filters : [ {namePrefix : 'CORE'} ]}) NRF.requestDevice({timeout : 20000, filters : [ {namePrefix : 'CORE'} ]})
.then(function(d) { .then(function(d) {
device = d; device = d;
console.log("Found device"); log("Found device");
return device.gatt.connect(); return device.gatt.connect();
}) })
.then(function(g) { .then(function(g) {
@ -78,23 +86,24 @@ function connection_setup() {
return characteristic.startNotifications(); return characteristic.startNotifications();
}) })
.then(function() { .then(function() {
console.log("Done!"); log("Done!");
// getSensorBatteryLevel(gatt); // getSensorBatteryLevel(gatt);
// g.reset().clearRect(Bangle.appRect).flip(); // g.reset().clearRect(Bangle.appRect).flip();
}) })
.catch(function(e) { .catch(function(e) {
console.log(e.toString(), "ERROR"); log(e.toString(), "ERROR");
console.log(e); log(e);
}); });
} }
function connection_end() { function connection_end() {
if (gatt != undefined) gatt.disconnect(); if (gatt != undefined)
gatt.disconnect();
} }
settings = require("Storage").readJSON("coretemp.json", 1) || {}; settings = require("Storage").readJSON("coretemp.json", 1) || {};
console.log("Settings:"); log("Settings:");
console.log(settings); log(settings);
if (settings.enabled) { if (settings.enabled) {
connection_setup(); connection_setup();

View File

@ -1,76 +1,66 @@
// Simply listen for core events and show data // Simply listen for core events and show data
Bangle.setLCDPower(1);
Bangle.setLCDTimeout(0);
var btm = g.getHeight() - 1; var btm = g.getHeight() - 1;
var px = g.getWidth() / 2;
// Dark or light logo
var col = (process.env.HWVERSION == 1) ? 65535 : 0;
var corelogo = { var corelogo = {
width : 146, width : 146,
height : 48, height : 48,
bpp : 4, bpp : 4,
transparent : 0, transparent : 0,
palette : new Uint16Array([ 65535, 65535, 2854, 1419 ]), palette : new Uint16Array([ col, col, 2854, 1419 ]),
buffer : buffer :
require("heatshrink") require("heatshrink")
.decompress(atob( .decompress(atob(
"AEUDmczmBD/I4xJ/AAMCkBHFAAJG8kQABJAJHFSVURAAUQRphHCkQGBJAySngJHDJRhHEJALZDAgiSBEQ0RPBIAKHAwQQI4xIEaoQFEEZpIULSRHFkDZDBwZIMEYhITa44SKSAxIDSARIDJ4IjKJCpHNEoiQGJDA2CJCQSOCYaQGJDBsCGiKQGTZIJCI4xBEJBAAEFpQAPDQoMGBQyOGIJJPGF6AALC5glCbJAQEgZCEAoowTSBypJBwKQMIQaSBAgZIJWw5ITB5RTDSBLbEAAjDOPRIVabIiQFJBCQKPYhIVCRxIEBg7WDSBpIVbJ5IQJIqQBgZIiCh7ZLJIriDbhJI3JoxIebIZITI6BIjCZ5IRI4RIPHAYAJJH4AIUAJIzHIhI/SAwzBJH6QGJH5HIHApI2HCIAJL4pITkATOJQJIMHCJeFJD8zaZCQHJCEBJCUCJCKPBJBhWGJEcia5oACJBSfHJB4QMJA6SLI4ZIKPAg3QJCUAJCbbBJETbPJAbbKbIhIBYJpIQbZ5UDbZzZFPBxIVSRIOBJA5JISAhIIF4ZIUfQpJHEwQKDJAhJHbJbBJJCIZECY4KGSQoABBIZOBSBbbIJC6IEBQqSJJoyQLbZBIRbYoAKJAaSHJAjbCF541RSRISLSRkgJAKQKbY5ISJJyQDSRyQMbYxITChhHFSRhGMbY5IUCpRHHJJZITiBIVbpBHJbpJHPFhBITfI4ANIwcgI6AAV")) "AEUDmczmBD/I4xJ/AAMCkBHFAAJG8kQABJAJHFSVURAAUQRphHCkQGBJAySngJHDJRhHEJALZDAgiSBEQ0RPBIAKHAwQQI4xIEaoQFEEZpIULSRHFkDZDBwZIMEYhITa44SKSAxIDSARIDJ4IjKJCpHNEoiQGJDA2CJCQSOCYaQGJDBsCGiKQGTZIJCI4xBEJBAAEFpQAPDQoMGBQyOGIJJPGF6AALC5glCbJAQEgZCEAoowTSBypJBwKQMIQaSBAgZIJWw5ITB5RTDSBLbEAAjDOPRIVabIiQFJBCQKPYhIVCRxIEBg7WDSBpIVbJ5IQJIqQBgZIiCh7ZLJIriDbhJI3JoxIebIZITI6BIjCZ5IRI4RIPHAYAJJH4AIUAJIzHIhI/SAwzBJH6QGJH5HIHApI2HCIAJL4pITkATOJQJIMHCJeFJD8zaZCQHJCEBJCUCJCKPBJBhWGJEcia5oACJBSfHJB4QMJA6SLI4ZIKPAg3QJCUAJCbbBJETbPJAbbKbIhIBYJpIQbZ5UDbZzZFPBxIVSRIOBJA5JISAhIIF4ZIUfQpJHEwQKDJAhJHbJbBJJCIZECY4KGSQoABBIZOBSBbbIJC6IEBQqSJJoyQLbZBIRbYoAKJAaSHJAjbCF541RSRISLSRkgJAKQKbY5ISJJyQDSRyQMbYxITChhHFSRhGMbY5IUCpRHHJJZITiBIVbpBHJbpJHPFhBITfI4ANIwcgI6AAV"))
}; };
first = true;
function onCore(c) { function onCore(c) {
var core = "Core: " + c.core + c.unit; // Large or small font
var skin = "Skin: " + c.skin + c.unit; var sz = ((process.env.HWVERSION == 1) ? 3 : 2);
var px = g.getWidth() / 2;
g.setFontAlign(0, 0); g.setFontAlign(0, 0);
if (first) { g.clearRect(0, 32 + 48, g.getWidth(), 32 + 48 + 24 * 4);
g.clearRect(0, 24, g.getWidth(), g.getHeight() - 24); g.setColor(g.theme.dark ? "#CCC" : "#333"); // gray
g.drawImage(corelogo, px - 146 / 2, 30); g.setFont("6x8", sz).drawString(
first = false; "Core: " + ((c.core < 327) ? (c.core + c.unit) : 'n/a'), px, 48 + 48);
} else { g.setFont("6x8", sz).drawString("Skin: " + c.skin + c.unit, px, 48 + 48 + 24);
g.clearRect(0, 48 + 48, g.getWidth(), 48 + 48 + 24 * 2);
}
g.setColor(0xC618); // Light gray
g.setFont("6x8", 3).drawString(core, px, 48 + 48);
g.setFont("6x8", 3).drawString(skin, px, 48 + 48 + 24);
} }
Bangle.on('CoreTemp', onCore); // Background task will activate once settings are enabled.
g.clear();
Bangle.loadWidgets();
Bangle.drawWidgets();
// Background task will activate if settings are enabled.
function enableSensor() { function enableSensor() {
settings = require("Storage").readJSON("coretemp.json", 1) || {}; settings = require("Storage").readJSON("coretemp.json", 1) || {};
if (!settings.enabled) { if (!settings.enabled) {
settings.enabled = true; settings.enabled = true;
require("Storage").write("coretemp.json", settings); require("Storage").write("coretemp.json", settings);
drawBackground("Waiting for\ndata...");
}
}
function drawBackground(message) {
g.clear();
Bangle.loadWidgets(); Bangle.loadWidgets();
Bangle.drawWidgets(); Bangle.drawWidgets();
} g.reset().setFont("6x8", 2).setFontAlign(0, 0);
g.drawImage(corelogo, px - 146 / 2, 30);
g.drawString(message, g.getWidth() / 2, g.getHeight() / 2 + 16);
} }
function drawMessage() { Bangle.on('CoreTemp', onCore);
settings = require("Storage").readJSON("coretemp.json", 1) || {}; settings = require("Storage").readJSON("coretemp.json", 1) || {};
g.clearRect(0, 24, g.getWidth(), g.getHeight() - 24);
if (!settings.enabled) { if (!settings.enabled) {
g.reset().setFont("6x8", 2).setFontAlign(0, 0); drawBackground("Sensor off\nBTN" +
g.drawString("Disabled, press BTN2\nto enable.", g.getWidth() / 2, ((process.env.HWVERSION == 1) ? '2' : '1') + " to enable");
g.getHeight() / 2 - 16);
} else { } else {
g.reset().setFont("6x8", 2).setFontAlign(0, 0); drawBackground("Waiting for\ndata...");
g.drawString("Please wait...\nWaiting for data", g.getWidth() / 2,
g.getHeight() / 2 - 16);
}
} }
setWatch(() => { enableSensor(); }, BTN2, {repeat : false}); setWatch(() => { enableSensor(); }, (process.env.HWVERSION == 1) ? BTN2 : BTN1,
{repeat : false});
drawMessage();

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.8 KiB

View File

@ -1,42 +1,39 @@
// TODO Change to generic multiple sensor // TODO Change to a generic multiple sensor widget?
(() => { (() => {
var settings = {}; var settings = {};
var count = 0; var count = 0;
var core = 0;
var img0 = {
width : 24,
height : 24,
bpp : 4,
transparent : 0,
buffer :
require("heatshrink")
.decompress(atob(
"AA0IxGIBAtms0ABQOIwAKFsAWCDAkGBYQUCBwIKEBYgmBBYoHBC4oKDBAILECwRSFDQQLBsBLDBYg4CNYoKBwALGDQYLCQpALaF45jBBZBfJMIZ3GZgwkGZYibCDIMGWoILDWYbBDd4gMFWoTvFYYgAFEYYHDA=="))
};
var img1 = {
width : 24,
height : 24,
bpp : 3,
transparent : 0,
buffer :
require("heatshrink")
.decompress(atob(
"AAkCpMgAwYFBiVJkgHCAoMAyQIBwAIBAoMEyEABAUkBAkEBAdICIkBBAIdBBAcJEwo1BBAI4EAoJBEKAMAiAIEAAIvBLgosBBCYjFJQIIFKwJHFBARZFBwRrCNAKbCC4J0CpApFR4REGBAWShIxDPQSSCYogvEA="))
};
// draw your widget // draw your widget
function draw() { function draw() {
if (!settings.enabled) if (!settings.enabled)
return; return;
g.reset(); g.reset();
g.setFont("6x8", 1).setFontAlign(0, 0);
g.setFontAlign(0, 0); g.setFontAlign(0, 0);
g.clearRect(this.x, this.y, this.x + 23, this.y + 23); g.clearRect(this.x, this.y, this.x + 23, this.y + 23);
g.drawImage((count & 1) ? img1: img0, this.x, this.y);
if (count & 1) {
g.setColor("#0f0"); // green
} else {
g.setColor(g.theme.dark ? "#333" : "#CCC"); // off = grey
}
g.drawImage(
atob("DAyBAAHh0js3EuDMA8A8AWBnDj9A8A=="),
this.x+(24-12)/2,this.y+1);
g.setColor(g.theme.fg);
g.drawString(parseInt(core)+"\n."+parseInt((core*100)%100), this.x + 24 / 2, this.y + 18);
g.setColor(-1);
} }
// Set a listener to 'blink' // Set a listener to 'blink'
function onTemp(temp) { function onTemp(temp) {
count = count + 1; count = count + 1;
core = temp.core;
WIDGETS["coretemp"].draw(); WIDGETS["coretemp"].draw();
} }

View File

@ -3,3 +3,4 @@
Fix interface.html Fix interface.html
0.03: Fix theme and maps/graphing if no GPS 0.03: Fix theme and maps/graphing if no GPS
0.04: Multiple bugfixes 0.04: Multiple bugfixes
0.05: Add recording for coresensor