-
Concept: Run smoke tests / unit tests in custom built Espruino IDE docker images with GitHub actions
Hi everyone! I was thinking about the following possible workflow in order to automatically run unit tests or smoke tests in an emulator:
- build a docker image that contains the Espruino IDE (https://espruino.com/ide) or a smaller version of it
- when a commit in a PR gets pushed, this triggers a GitHub action
- optionally the smoke tests could also be run just once a day, e.g. at midnight, to save GitHub Actions minutes
- this GitHub action uses the Espruino IDE docker image and automatically loads the newly added/changed code in the IDE
- some test cases that check basic functionality of the app run and confirm the changes don't break other code
When it comes to test cases, obviously some mocking needs to be done, however I think this is perfectly doable. For example https://www.espruino.com/ReferenceBANGLEJS2#l_E_getTemperature always returns
NaN
in the emulator, but the easiest way to mock it for the test suite would be to callE.getTemperature = function() { return 20; };
at the start of the test suite.For example, here's some pseudo code I came up with for
activityreminder
:// Suite setup // Mock some functions E.getTemperature = function() { return 27; }; // assume the user is always wearing the smart watch settings.maxInnactivityMin = 0; // immediately trigger an inactivity warning by setting max inactivity to 0 min // Test cases // wait a few seconds and assert E.showPrompt() got called (which should happen) // if not, fail the test or raise a warning // (optionally) take a screenshot and include it as an artifact
Why would this be useful?
Around 2 weeks ago there was an issue where (if I understood correctly) some firmware changes caused a new date format which brokeactivityreminder
because it still expected/used the old date format. We could detect sudden breaking changes like this one using test cases. For example, the test case above would have failed after the new date format changes, because it couldn't have read the new date format.Obviously this is a huge suggestion and is probably low priority, but I'm just sharing my ideas and I'm open for feedback! What are your thoughts about this?
- build a docker image that contains the Espruino IDE (https://espruino.com/ide) or a smaller version of it
-
-
-
You can calculate the RMSSD using the differences in ms between heartbeats like this:
function calculateRMSSD(RRIntervals) { var sumOfDifferencesSquared = 0; for (var i = 0; i < RRIntervals.length - 1; i++) { var difference = RRIntervals[i + 1] - RRIntervals[i]; sumOfDifferencesSquared += difference * difference; } var meanSquaredDifference = sumOfDifferencesSquared / (RRIntervals.length - 1); var rmssd = Math.sqrt(meanSquaredDifference); return rmssd; }
This is one of many ways to calculate the stress level. The event Bangle.HRM only gives the current heart beat calculated, however, the event doesn't get fired at exactly the time when a heartbeat was recognized.
I know there is a
.raw
property that provides raw data by the sensor, which you could use to manually replicate the algorithm that measures when individual heart beats occurred, however I believe this procedure is kind of reinventing the wheel.I'm pretty sure the data about the individual time differences between heart beats already exists somewhere because otherwise the algorithm couldn't calculate the heart beat.
So, how do I get the differences between individual heart beats? Thanks.
-
Thanks everyone!
I guess one could also make the assumption that at times with lots of app switching you probably are not doing a lot of moving around. So it probably wouldn't impact the statistics too much doing without retaining info across resets/loads.
Yes, that's probably true, so to save CPU and battery usage, I'll probably ignore App switches and not save data to storage, and assume that no significant activity was done during that time.
-
Okay thanks but what I don't understand: Doesn't the code in yourapp.boot.js also need to save data to storage every minute? Because if I understand it correctly when I switch apps or activities any running app gets terminated and thus any saved variables (to cache the step count at the end of the last minute) get cleared (like widgets) and the boot code needs to run again?
-
I checked the health boot.js code but if I understand correctly it also only listens for the "health" event and then saves the data to the database. And if I understand this commit correctly, "health" gets fired in
libs/banglejs/jswrap_bangle.c
and honestly, I was hoping for an easier approach than editing and recompiling C files for such a small feature. -
The WHO recommends to "perform at least 150 minutes of moderate intensity aerobic physical activity throughout the week or do at least 75 minutes of vigorous intensity aerobic physical activity throughout the week".
I would like to implement this into an app that records a minute as "moderate intensity" if more than 100 steps were performed or records it as a "vigorous intensity" if more than 130 steps were performed.
So far, I simply used
require("health").readAllRecordsSince()
to get all health records of the last week to filter out the records with an appropriate step count (see code snippet below). However, BangleJS only saves step counts per 10 minutes (probably to save storage). This is understandable but gives more inaccurate results here:
const activeSPM = 100; const intenseSPM = 130; const threshold = 0.7; let activity = { active: 0, intense: 0 }; const currentDate = new Date(); const durationDays = 7; const timeAgo = new Date(currentDate.getTime() - durationDays * 24 * 60 * 60 * 1000); require("health").readAllRecordsSince(timeAgo, h => { if (h.steps >= (intenseSPM * 10 * threshold)) { print("intense:", h); activity.intense += (h.steps / intenseSPM) * (1 / threshold) * (7 / durationDays); } else if (h.steps >= (activeSPM * 10 * threshold)) { //print("active:", h); activity.active += (h.steps / activeSPM) * (1 / threshold) * (7 / durationDays); } });
How can I get the exact step count of the last minute only, to avoid averaging/guessing the step count like above?
-
Hi! Thank you so so much!! I just made the order with the note and I'd be so happy to get the original blue strap one https://shop.espruino.com/image/cache/catalog/products/banglejs2/banglejs2-colors2-1000x800.jpg that you just mentioned! Thank you so much! :)
-
That's a good idea! However, I saw this picture and I really like the blue design of the display and considering that my dad's favorite color is blue I'd prefer to buy the blue one if possible. :)
-
-
-
-
I noticed that often times the Bangle.js 2 will falsely recognize something (e.g. typing on a keyboard) as tapping and thus unlock the watch (if "Wake on Tap" is enabled). I read at https://www.espruino.com/Bangle.js2#power-consumption that the power consumption is pretty high when the touchscreen is unlocked and the backlight is turned on, so it would be useful to prevent those false unlocks.
The Garmin Venu Sq 2 smartwatch has a feature where it only turns on/unlocks the screen when double tapping and ignores single taps. This would sort out many wrong unlocks and reduce the power consumption.
Any chance we could get this implemented?
P.S.: Thanks for this awesome smartwatch. I really love the Bangle.js 2! :)
Thanks for the info. If this already exists, cool, no need to build any new images then. And yes, I get the point that automatically catching and uploading errors would definitely be a problem regarding privacy.