-
-
I am developing a highly customizable watch face. The idea is to define the watchface entirely in a json file based on displaying images from a resource file. The images are converted from a folder structure into an json resources file and are then referenced from the watchface file. Watchfaces can be zipped and loaded as one file or the folder can be used directly if the browser supports that. Conversion happens in the browser, so no additional tools needed for installing/converting watchfaces. Using chromium on Arch linux works fine for me.
You can try it out at https://halemmerich.github.io/BangleAppsĀ/?id=imageclock .
There are two example watchfaces you can download from the customization page and try out. File format and features are describe in the README, but the whole thing is far from finished.The main problem at the moment is the memory use and relatively slow drawing. There is close to no performance optimizations yet. Ideas on how prevent having all images in memory at the same time would be appreciated. I would prefer not to write them all into dedicated files, as that would clutter the storage. Maybe parsing the json SAX-style is possible?
What do you think, are there features you would like to have in something like this?
-
The first image is the correct placement, or is it already lifted out of place on the picture? Is the button itself made from magnetic materials? Maybe a strong magnet could pull it back in place. I only have tiny neodymium magnets, those seem to do nothing.
I could try opening the watch to verify the problem, but my success rate getting sealed devices back to being sealed is not that great :)
The idea of drilling a hole seems a bit dangerous to me, since the position of the button board is not known, so damaging something is quite possible. If not during drilling, then presumably during poking around in the device with something solid enough to manipulate the button back into position. -
Any news on possible fixes? It seems one of my two bangle2 now has the same issue. Happened during testing performance improvements on reload so several long presses in a few minutes. Suddenly no click, only soft resistance. Wiggling the button around and slight "percussive maintenance" didn't change anything. The other one is still going strong :)
-
This one should work in the background: https://banglejs.com/apps/#hralarm
-
Yes, you're right, for most use cases the current implementation works well enough. I like your idea of changing the event handler registration to keep it confined to the app without overhead for all users. The problem I had to solve with replacing the
HRM
event was the more or less random order of code execution during boot. I think it depends on installation order. To fix that, i iterate through all apps having turned on the internal sensor and turn them off while turning BTHRM on for them. Thats not possible for event creation, since they come from the firmware, but event handler registration could work.Actually there is still a problem left. The recorder code currently runs before the BTHRM code and can't start the BTHRM because
setBTHRMPower
is not yet defined. The same would happen with the redefined event handler registration. There is probably a way to work around that like with thesetHRMPower
method, but it gets messier.Is there any way to force the order of boot0 construction? That would solve at least the hackish redefining of event handler registrations and power up states. Maybe sorting the files by name while writing boot0 and establishing a convention for "priority" files like an underscore in front to get them sorted first?
-
-
I like it!
My Amazfit Bip S does a little trickery to fake smoother interaction than it is probably actually capable of. It always "scrolls" the same amount of menu options (one page), triggered by swiping, but independent of swiping speed. So the rendering is not directly dependent on touch interaction. The scrolling animation is short to hide that you can not "stop" scrolling, but it is a very convincing effect if you do not try to scroll very slow or extremely fast in different directions. -
The bangles screen goes green when it actually starts sending data over. For that to happen all recorded event types must have been seen at least one time. I didn't implement showing data on screen to keep the CPU as free as possible for sending BLE data. It's probably possible to show something on screen, without loosing performance on the sending part. Maybe just printing the send lines to the display would be cheap enough. Record count is currently unknown in the app, just the browser counts the incoming lines. Storing that in RAM and printing it should be no problem.
-
Actually I didn't do anything more than just plot it using gnuplot. I have attached the files I used for plotting if you want to try it out.
The hrmaccevents app just stores a line per event, so filtering per event type could be done by throwing away all lines that do not have content in the other columns, no label needed.
-
The events send by the firmware are currently send directly and can not be wrapped or redefined in an easy way. The BTHRM app does something like redefining an event by changing the
setHRMPower
-method. It replaces those calls depending on settings and can prevent the originalHRM
event from happening by preventing the HRM sensor to be powered up. This is ok for some use cases, but things like comparing the internal with an external sensor it is more like a workaround.Would it be useful to have a generic mechanism to modify events sent by the firmware?
One easy way would be changing the
HRM
event into aHRM_int
event and defining some boot code, that transforms it to theHRM
-event. That way all apps could stay the same and work the same. But apps like BTHRM, when replacing or multiplexing events from multiple sensors could have fine control over what gets used by others apps.Something like this in boot0:
function handleHRMint(e){ Bangle.emit("HRM",e) }; Bangle.on("HRM_int", (e)=>{handleHRMint(e)})
That would mean be a bit of overhead over directly emitting the events, but presents a lot of possibilities to filter and wrap events coming from firmware.
Maybe there is a more direct way to change the event emitting?
-
-
If the ECG data can be obtained as a BT characteristic, it is probably enough to change the
supportedCharacteristics
andsupportedServices
objects to add support to BTHRM. The handler function in the characteristic needs to parse the BT data and emit an event. Alternatively you can just store data in a variable and piggyback onto the BTHRM to send it. I do that with battery and location data which are from different characteristics and cached inlastReceivedData
. -
The event recorder takes every event it gets and write one line in the .csv for it. I tried writing to a local file, but 1 minute of recording was about 200k, so tethering to the browser on PC/Phone is probably better. The code is still in there to write into a file, you could try it out by changing line 18 in custom.html to
var method=2;
. -
HRV is calculated from RR intervals, so it should work. The BTHRV app waits for the first RR interval to be received and then buzzes ands starts keeping measurements in memory. For my belt (Wahoo TICKR X2) it takes 10-15s before anything happens, the first RR intervals get send a decent bit after the first pulse measurements. Currently the data is only written at once when the 300s measurement is complete. Maybe not a bad idea to write as the data becomes available. If you see RR values in BTHRM app, it should definitely work.
As for the behaviour with the different settings: It got a bit complex now :) I think about defining modes that encapsulate all settings in fitting combinations.
HRV app uses BT event and should work with every setting combination as long
Use BT HRM
is on. BTHRM app shows internal and external sensor whenReplace HRM
is off. If it is on, then both event types (HRM and BTHRM) normally contain the same data (both from BT sensor).Fallback to HRM
decides if with the internal sensor will be enabled on disconnect. In that case, the values of HRM and BTHRM can differ, BTHRM will not be shown on disconnect, HRM enabled, then after some time BTHRM will reconnect and reappear again. Internal sensor and BT values can then mix for theFallback timeout
time as both events are emitted as HRM events. -
-
Bug is found and pull request is open ;)
You can try here: https://halemmerich.github.io/BangleAppsĀ/#bthrm
-
-
X_STEPS = 6, RAW_THRESHOLD = 7 File, Expected, Simulated, Diff, %, (Original) HughB-walk-a10021-b10248.csv, 10021, 12672, 2651, 126.45 %, (12222)
So that creates too many step counts with this low threshold.
I will try to get a longer dataset. Is there a possibility that one threshold will not cut it for all the bangles because of sensor/electronics variation? -
I have had both bangles on 2v11.53 for a few hours now (mostly sitting at desk) and the step counters are still different.
b77 has counted 167 steps, while b87 counted 667. So a bit closer together than before.jeffmers test harness and stepcount.c yielded:
X_STEPS = 6, RAW_THRESHOLD = 15 File, Expected, Simulated, Diff, %, (Original) halemmerich-walking-2-b77-2v11.csv, 150, 79, -71, 52.67 %, (156) halemmerich-walking-2-b87-2v11.csv, 150, 89, -61, 59.33 %, (151) halemmerich-stationary-1-b77-2v11.csv, 0, 0, 0, 0.00 %, (1) halemmerich-stationary-1-b87-2v11.csv, 0, 0, 0, 0.00 %, (10)
I have had play with the RAW_THRESHOLD and got down to 7 before the results were reasonable.
X_STEPS = 6, RAW_THRESHOLD = 7 File, Expected, Simulated, Diff, %, (Original) halemmerich-walking-2-b77-2v11.csv, 150, 150, 0, 100.00 %, (156) halemmerich-walking-2-b87-2v11.csv, 150, 143, -7, 95.33 %, (151) halemmerich-stationary-1-b77-2v11.csv, 0, 0, 0, 0.00 %, (1) halemmerich-stationary-1-b87-2v11.csv, 0, 12, 12, 0.00 %, (10)
I also tried walking 150 steps. b77 counted 80 steps and b87 counted 103.
-
Two bangles, both on 2v11, so I assume old threshold.
Will try the same with 2v11.53 on both this evening and run jeffmers harness. Branch to use is master?b77 was a lot better than b87, especially while both were stationary. b87 was extremely noisy between 80-180ms, 200-280ms, 450-510ms. I do not know why.
-
-
Today I have tried wearing both my bangles (2v11) on the same arm to compare the step counters. The results were as follows:
2h sitting at my desk: 0(b77) vs. 866(b87)
Lunch and rest of day sitting at my desk: 621(b77) vs. 5221(b87)b77 seems reasonable, albeit probably some percentage points on the low side.
Surprised by the massive difference I have recorded some accelerometer data and run it through the test program:
X_STEPS = 6, RAW_THRESHOLD = 17 File, Expected, Simulated, Diff, %, (Original) halemmerich-walking-2-b77.csv, 150, 77, -73, 51.33 %, (156) halemmerich-walking-2-b87.csv, 150, 78, -72, 52.00 %, (151) halemmerich-stationary-1-b77.csv, 0, 0, 0, 0.00 %, (1) halemmerich-stationary-1-b87.csv, 0, 7, 7, 0.00 %, (10)
I have walked a counted 150 steps for the first files. The plots while walking seem ok, but the stationary b87 has a lot of "movement" for being very still and having both watches on the same arm.
I don't know if it is related, but the internal HRM also seems to be a lot better on b77 than on b87. I have not recorded data for this, but during testing the difference was often > 20bpm. Maybe some hardware issue interfering with both sensors (missing filter cap, bad solder joint somewhere)?
Can I collect some other or additional data?
@HughB
Yes, a tutorial would be useful. Since the file formats are probably going to change, I would hold off on that a bit though.
@Gordon
I pushed some commits, which do help on "perceived" performance. There were some bugs on setting intervals and timers and the watchfaces have been drawn very often. The conversion of compressed or b64 image strings to buffers for drawing is now cached, which saves some expensive operations on every refresh. There is still lots of room for improvements. At least figuring out what actually has to be redrawn would help.
The digitalretro watchface needs about half of the available RAM on bangle2, so my focus for now is drawing speed. More because of saved energy due to less calculations, watchfaces are not that dynamic when drawn every minute or even second.
Would creating the script in the browser help with memory? The reading of the resources file and getting it into an object is fast enough, on the order of 80ms. Is the script code accessed directly from flash, or does it get loaded into memory before it is executed? Can I actually avoid getting the image data into RAM until it is needed there for drawing?
The idea comes from the format that is created by the unofficial de/compiler for Amazfit BIP watchfaces. I have a watch face I like for my BIP S that is now easy to port. Since there seem to be thousands of these unofficial watchfaces for BIP S, maybe there are some that are worth porting over to a similar format, but not worth creating a dedicated app for every single one. Porting would be for the most part slight structural changes to the decompiled json. Probably most of that can be automated.