From bcfb9167bd6cad6660ba9163fd82e4da32fffae5 Mon Sep 17 00:00:00 2001 From: Marc Englund Date: Tue, 25 Jan 2022 22:19:34 +0200 Subject: [PATCH] New version, redesigned and refactored A bit of re-design and refactor before making things configurable. Removed flicker. --- apps/ruuviwatch/ChangeLog | 1 + apps/ruuviwatch/README.md | 37 +-- apps/ruuviwatch/metadata.json | 4 +- apps/ruuviwatch/ruuviwatch-in-action.jpg | Bin 0 -> 80687 bytes apps/ruuviwatch/ruuviwatch.app.js | 371 ++++++++++++++--------- 5 files changed, 258 insertions(+), 155 deletions(-) create mode 100644 apps/ruuviwatch/ruuviwatch-in-action.jpg diff --git a/apps/ruuviwatch/ChangeLog b/apps/ruuviwatch/ChangeLog index 7953548cb..15ff601f0 100644 --- a/apps/ruuviwatch/ChangeLog +++ b/apps/ruuviwatch/ChangeLog @@ -1,2 +1,3 @@ 0.01: Hello Ruuvi Watch! 0.02: Clear gfx on startup. +0.03: Improve design and code, reduce flicker. diff --git a/apps/ruuviwatch/README.md b/apps/ruuviwatch/README.md index bf4358267..c96e032d7 100644 --- a/apps/ruuviwatch/README.md +++ b/apps/ruuviwatch/README.md @@ -1,25 +1,26 @@ -# Ruuvi Watch +# Ruuvi Watch -Watch the status of [RuuviTags](https://ruuvi.com) in range. +Watch the status of [RuuviTags](https://ruuvi.com) in range. - - Id - - Temperature (°C) - - Humidity (%) - - Pressure (hPa) - - Battery voltage +![Ruuvi Watch in action](/BangleApps/apps/ruuviwatch/ruuviwatch-in-action.jpg) - Also shows how "fresh" the data is (age of reading). +- Id +- Temperature (°C) +- Humidity (%) +- Pressure (hPa) +- Battery voltage - ## Usage - - - Scans for devices when launched and every N seconds. - - Page trough devices with BTN1/BTN3. - - Trigger scan with BTN2. +Also shows how "fresh" the data is (age of reading). + +## Usage + +- Scans for devices when launched and every N seconds. +- Page trough devices with BTN1/BTN3. +- Trigger scan with BTN2. ## Todo / ideas - - Allow to "name" known devices - - Prevent flicker when updating - - Include more data - - Support older Ruuvi protocols - +- Settings for scan frequency, units +- Allow to "name" known devices +- Include more data +- Support older Ruuvi protocols diff --git a/apps/ruuviwatch/metadata.json b/apps/ruuviwatch/metadata.json index 12f9ff4a0..413d96153 100644 --- a/apps/ruuviwatch/metadata.json +++ b/apps/ruuviwatch/metadata.json @@ -2,8 +2,8 @@ "name": "Ruuvi Watch", "shortName":"Ruuvi Watch", "icon": "ruuviwatch.png", - "version":"0.02", - "description": "Keep an eye on RuuviTag devices (https://ruuvi.com). Only shows RuuviTags using the v5 format.", + "version":"0.03", + "description": "Keep an eye on RuuviTag devices (https://ruuvi.com). For RuuviTags using the v5 format.", "readme":"README.md", "tags": "bluetooth", "supports": ["BANGLEJS"], diff --git a/apps/ruuviwatch/ruuviwatch-in-action.jpg b/apps/ruuviwatch/ruuviwatch-in-action.jpg new file mode 100644 index 0000000000000000000000000000000000000000..08b391e8413dc1fea01a685ee60f4b93ab092fd5 GIT binary patch literal 80687 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 literal 0 HcmV?d00001 diff --git a/apps/ruuviwatch/ruuviwatch.app.js b/apps/ruuviwatch/ruuviwatch.app.js index 46218a323..674319dd8 100644 --- a/apps/ruuviwatch/ruuviwatch.app.js +++ b/apps/ruuviwatch/ruuviwatch.app.js @@ -1,151 +1,252 @@ -require("Storage").write("ruuviwatch.info",{ - "id":"ruuviwatch", - "name":"Ruuvi Watch", - "src":"ruuviwatch.app.js", - "icon":"ruuviwatch.img" - }); - - const lookup = {}; - const ruuvis = []; - let current = 0; - - function int2Hex (str) { - return ('0' + str.toString(16).toUpperCase()).slice(-2); +require("Storage").write("ruuviwatch.info", { + id: "ruuviwatch", + name: "Ruuvi Watch", + src: "ruuviwatch.app.js", + icon: "ruuviwatch.img", +}); + +const lookup = {}; +const ruuvis = []; +let current = 0; +let scanning = false; + +const SCAN_FREQ = 1000 * 30; + +// Fonts +const FONT_L = "Vector:60"; +const FONT_M = "Vector:20"; +const FONT_S = "Vector:16"; + +// "layout" +const CENTER = g.getWidth() / 2; +const MIDDLE = g.getHeight() / 2; + +const PAGING_Y = 25; +const NAME_Y = PAGING_Y + 25; + +const TEMP_Y = MIDDLE; +const HUMID_PRESSURE_Y = MIDDLE + 50; + +const VOLT_Y = g.getHeight() - 15; +const SCANNING_Y = VOLT_Y - 25; + +function int2Hex(str) { + return ("0" + str.toString(16).toUpperCase()).slice(-2); +} + +function p(data) { + const OFFSET = 7; // 0-4 header, 5-6 Ruuvi id + const robject = {}; + robject.version = data[OFFSET]; + + let temperature = (data[OFFSET + 1] << 8) | (data[OFFSET + 2] & 0xff); + if (temperature > 32767) { + temperature -= 65534; } - - function p(data) { - const OFFSET = 7; // 0-4 header, 5-6 Ruuvi id - const robject = {}; - robject.version = data[OFFSET]; - - let temperature = (data[OFFSET+1] << 8) | (data[OFFSET+2] & 0xff); - if (temperature > 32767) { - temperature -= 65534; - } - robject.temperature = temperature / 200.0; - - robject.humidity = (((data[OFFSET+3] & 0xff) << 8) | (data[OFFSET+4] & 0xff)) / 400.0; - robject.pressure = ((((data[OFFSET+5] & 0xff) << 8) | (data[OFFSET+6] & 0xff)) + 50000) / 100.0; - - let accelerationX = (data[OFFSET+7] << 8) | (data[OFFSET+8] & 0xff); - if (accelerationX > 32767) accelerationX -= 65536; // two's complement - robject.accelerationX = accelerationX / 1000.0; - - let accelerationY = (data[OFFSET+9] << 8) | (data[OFFSET+10] & 0xff); - if (accelerationY > 32767) accelerationY -= 65536; // two's complement - robject.accelerationY = accelerationY / 1000.0; - - let accelerationZ = (data[OFFSET+11] << 8) | (data[OFFSET+12] & 0xff); - if (accelerationZ > 32767) accelerationZ -= 65536; // two's complement - robject.accelerationZ = accelerationZ / 1000.0; - - const powerInfo = ((data[OFFSET+13] & 0xff) << 8) | (data[OFFSET+14] & 0xff); - robject.battery = ((powerInfo >>> 5) + 1600) / 1000.0; - robject.txPower = (powerInfo & 0b11111) * 2 - 40; - robject.movementCounter = data[OFFSET+15] & 0xff; - robject.measurementSequenceNumber = ((data[OFFSET+16] & 0xff) << 8) | (data[OFFSET+17] & 0xff); - - robject.mac = [ - int2Hex(data[OFFSET+18]), - int2Hex(data[OFFSET+19]), - int2Hex(data[OFFSET+20]), - int2Hex(data[OFFSET+21]), - int2Hex(data[OFFSET+22]), - int2Hex(data[OFFSET+23]) - ].join(':'); - - robject.name = "Ruuvi " + int2Hex(data[OFFSET+22]) + int2Hex(data[OFFSET+23]); - return robject; - } - - function getAge(created) { - const now = new Date().getTime(); - const ago = ((now - created) / 1000).toFixed(0); - return ago > 0 ? ago + "s ago" : "now"; - } - - function redraw() { - if (ruuvis.length > 0 && ruuvis[current]) { - const ruuvi = ruuvis[current]; - g.clear(); - g.setFontAlign(0,0); - g.setFont("Vector",12); - g.drawString(" (" + (current+1) + "/" + ruuvis.length + ")", g.getWidth()/2, 10); - g.setFont("Vector",20); - g.drawString(ruuvi.name, g.getWidth()/2, 30); - g.setFont("Vector",12); - const age = getAge(ruuvi.time); - if(age > (5*60)) { - g.setColor("#ff0000"); - } else if (age > 60) { - g.setColor("#f39c12"); - } else { - g.setColor("#2ecc71"); - } - g.drawString(age, g.getWidth()/2, 50); - g.setColor("#ffffff"); - g.setFont("Vector",60); - g.drawString(ruuvi.temperature.toFixed(2) + "°c", g.getWidth()/2, g.getHeight()/2); - g.setFontAlign(0,1); - g.setFont("Vector",20); - g.drawString(ruuvi.humidity + "% " + ruuvi.pressure + "hPa ", g.getWidth()/2, g.getHeight()-30); - g.setFont("Vector",12); - g.drawString(ruuvi.battery + "v", g.getWidth()/2, g.getHeight()-10); + robject.temperature = temperature / 200.0; + + robject.humidity = + (((data[OFFSET + 3] & 0xff) << 8) | (data[OFFSET + 4] & 0xff)) / 400.0; + robject.pressure = + ((((data[OFFSET + 5] & 0xff) << 8) | (data[OFFSET + 6] & 0xff)) + 50000) / + 100.0; + + let accelerationX = (data[OFFSET + 7] << 8) | (data[OFFSET + 8] & 0xff); + if (accelerationX > 32767) accelerationX -= 65536; // two's complement + robject.accelerationX = accelerationX / 1000.0; + + let accelerationY = (data[OFFSET + 9] << 8) | (data[OFFSET + 10] & 0xff); + if (accelerationY > 32767) accelerationY -= 65536; // two's complement + robject.accelerationY = accelerationY / 1000.0; + + let accelerationZ = (data[OFFSET + 11] << 8) | (data[OFFSET + 12] & 0xff); + if (accelerationZ > 32767) accelerationZ -= 65536; // two's complement + robject.accelerationZ = accelerationZ / 1000.0; + + const powerInfo = + ((data[OFFSET + 13] & 0xff) << 8) | (data[OFFSET + 14] & 0xff); + robject.battery = ((powerInfo >>> 5) + 1600) / 1000.0; + robject.txPower = (powerInfo & 0b11111) * 2 - 40; + robject.movementCounter = data[OFFSET + 15] & 0xff; + robject.measurementSequenceNumber = + ((data[OFFSET + 16] & 0xff) << 8) | (data[OFFSET + 17] & 0xff); + + robject.mac = [ + int2Hex(data[OFFSET + 18]), + int2Hex(data[OFFSET + 19]), + int2Hex(data[OFFSET + 20]), + int2Hex(data[OFFSET + 21]), + int2Hex(data[OFFSET + 22]), + int2Hex(data[OFFSET + 23]), + ].join(":"); + + robject.name = + "Ruuvi " + int2Hex(data[OFFSET + 22]) + int2Hex(data[OFFSET + 23]); + return robject; +} + +function drawAge() { + const ruuvi = ruuvis[current]; + const created = ruuvi.time; + const now = new Date().getTime(); + const agoMs = now - created; + let age = ""; + if (agoMs > SCAN_FREQ) { + const agoS = agoMs / 1000; + // not seen since last scan; indicate age + if (agoS < 60) { + // seconds + age = agoS.toFixed(0) + "s ago"; + } else if (agoS < 60 * 60) { + // minutes + age = (agoS / 60).toFixed(0) + "m ago"; } else { - g.clear(); - g.drawImage(require("Storage").read("ruuviwatch.img"), g.getWidth()/2-24, g.getHeight()/2-24); - g.setFontAlign(0,0); - g.setFont("Vector",16); - g.drawString("Looking for Ruuvi...", g.getWidth()/2, g.getHeight()/2 + 50); + // hours + age = (agoS / 60 / 60).toFixed(0) + "h ago"; } } - - function scan() { - NRF.findDevices(function(devices) { - let foundNew = false; - devices.forEach(device => { - const data = p(device.data); - data.time = new Date().getTime(); - const idx = lookup[data.name]; - if (idx !== undefined) { - ruuvis[idx] = data; - } else { - lookup[data.name] = ruuvis.push(data)-1; - foundNew = true; - } - }); - redraw(); - if (foundNew) { - Bangle.buzz(); - g.flip(); - } - - }, {timeout : 2000, filters : [{ manufacturerData:{0x0499:{}} }] }); + if (agoMs > 5 * SCAN_FREQ) { + // old + g.setColor("#ff0000"); } - + g.setFont(FONT_S); + g.drawString(age, CENTER, SCANNING_Y); +} + +function redrawAge() { + const originalColor = g.getColor(); + g.clearRect(0, SCANNING_Y - 10, g.getWidth(), SCANNING_Y + 10); + g.setFont(FONT_S); + g.setColor("#666666"); + if (scanning) { + g.drawString("Scanning...", CENTER, SCANNING_Y); + } else if (ruuvis.length > 0 && ruuvis[current]) { + drawAge(); + } else { + g.drawString("No tags in sight", CENTER, SCANNING_Y); + } + g.setColor(originalColor); +} + +function redraw() { g.clear(); - g.drawImage(require("Storage").read("ruuviwatch.img"), g.getWidth()/2-24, g.getHeight()/2-24); - - var drawInterval = setInterval(redraw, 1000); - var scanInterval = setInterval(scan, 10000); - setWatch(() => { + g.setColor("#ffffff"); + + if (ruuvis.length > 0 && ruuvis[current]) { + const ruuvi = ruuvis[current]; + + // page + g.setFont(FONT_S); + g.drawString( + " (" + (current + 1) + "/" + ruuvis.length + ")", + CENTER, + PAGING_Y + ); + + // name + g.setFont(FONT_M); + g.drawString(ruuvi.name, CENTER, NAME_Y); + + // age + redrawAge(); + + // temp + g.setFont(FONT_L); + g.drawString(ruuvi.temperature.toFixed(2) + "°c", CENTER, TEMP_Y); + + // humid & pressure + g.setFont(FONT_M); + g.drawString( + ruuvi.humidity.toFixed(2) + "% " + ruuvi.pressure.toFixed(2) + "hPa ", + CENTER, + HUMID_PRESSURE_Y + ); + + // battery + g.setFont(FONT_S); + g.drawString(ruuvi.battery + "v", CENTER, VOLT_Y); + } else { + // no ruuvis + g.drawImage( + require("Storage").read("ruuviwatch.img"), + CENTER - 24, + MIDDLE - 24 + ); + } +} + +function scan() { + if (scanning) return; + scanning = true; + NRF.findDevices( + function (devices) { + let foundNew = false; + devices.forEach((device) => { + const data = p(device.data); + data.time = new Date().getTime(); + const idx = lookup[data.name]; + if (idx !== undefined) { + ruuvis[idx] = data; + } else { + lookup[data.name] = ruuvis.push(data) - 1; + foundNew = true; + } + }); + scanning = false; + redraw(); + if (foundNew) { + Bangle.buzz(); + } + }, + { timeout: 2000, filters: [{ manufacturerData: { 0x0499: {} } }] } + ); +} + +// START +// Button 1 pages up +setWatch( + () => { current--; if (current < 0) { - current = ruuvis.length-1; + current = ruuvis.length - 1; } redraw(); - }, BTN1, {repeat:true}); - - setWatch(() => { + }, + BTN1, + { repeat: true } +); +// button triggers scan +setWatch( + () => { scan(); - }, BTN2, {repeat:true}); - - setWatch(() => { + }, + BTN2, + { repeat: true } +); +// button 3 pages down +setWatch( + () => { current++; if (current >= ruuvis.length) { current = 0; } redraw(); - }, BTN3, {repeat:true}); - - scan(); \ No newline at end of file + }, + BTN3, + { repeat: true } +); + +g.setFontAlign(0, 0); +g.clear(); +g.drawImage( + require("Storage").read("ruuviwatch.img"), + CENTER - 24, + MIDDLE - 24 +); + +g.setFont(FONT_M); +g.drawString("Ruuvi Watch", CENTER, HUMID_PRESSURE_Y); + +var ageInterval = setInterval(redrawAge, 1000); +var scanInterval = setInterval(scan, SCAN_FREQ); +scan();