-
Great, thanks for the fix. The current bleeding edge firmware seems to now work fine with my HRM belt.
When looking at the absolute time calculated with the nominal frequencies there seems to be a factor of 16 between systick and RTC. No idea where that's coming from but I think it is not really relevant as it is now working. -
Concept: Run smoke tests / unit tests in custom built Espruino IDE docker images with GitHub actions
I have found a way to implement a command for opening an interactive console. It "works" with the current state of the pull request alone with three major gotchas:
- The pressed keys are not mirrored to the console
- History etc. does not work
- The debugger does not work
1 and 2 work with these two changes:
https://github.com/espruino/EspruinoWebIDE/compare/master...halemmerich:EspruinoWebIDE:emulator
https://github.com/espruino/EspruinoAppLoaderCore/compare/master...halemmerich:EspruinoAppLoaderCore:emulatorDo you think the changes in core and IDE would have unwanted side effects elsewhere?
There seems to be a race condition somewhere that causes the result of the call (
=undefined
) and what is printed by the call to switch position. That causes occasional test failures. Do you have an idea how to get to the bottom of that problem?
The demo app/test hassaveMemoryUsage
twice since more often than not the first one producesNaN
because of this issue. Second one seems to always work somehow.
The race seems to happening independently of the changes in core/IDE. - The pressed keys are not mirrored to the console
-
setInterval(()=>{ const systickMax = peek32(0xE000E014); const rtcMax = (0xFFFFFF); let systickLater,rtcLater; let systickNow = peek32(0xE000E018); let rtcNow = peek32(0x4000B504); for (let i = 0; i < 10000; i++){} systickLater = peek32(0xE000E018); rtcLater = peek32(0x4000B504); let systickDiff = systickLater-systickNow; if (systickDiff < 0) systickDiff += systickMax; let rtcDiff = rtcLater-rtcNow; if (rtcDiff < 0) rtcDiff += rtcMax; print("Systicks:", systickDiff ); print("RTC:", rtcDiff); print("Sys/RTC:", systickDiff/rtcDiff); },1000);
This gives me values from 92-95 for Sys/RTC when the watch is on my arm and 152-156 when it has been stationary for a little while. I would have expected values on the order of 2000, so I do not have an idea how to interpret this. Or
0x4000B504
is the wrong address :-D
I got it from https://infocenter.nordicsemi.com/index.jsp?topic=%2Fps_nrf52840%2Frtc.html. -
Over 32h the drift was about 3 seconds, so just on the order of 26 ppm. I do not think that should be problematic in any way since the firmware uses 50ppm by default?
What surprised me was that I seemingly had to change the accuracy in two places to actually make a difference: https://github.com/espruino/Espruino/commit/2c2ba5894a9a1450d20100e8370eb622acd64a4a while your 50ppm commit only changedbluetooth.c
.I will have to try your suggestion comparing RTC and systick.
So systick is expected to go up with 64MHz while RTC goes up at the 32kHz of the external crystal? -
StorageFiles are not well suited for writing binary data,
\xFF
is used to detect the end of those and can not be used inside them.Flash
is dangerous to use and you could easily overwrite your bootloader or destroy the file system created by theStorage
module.I think you would be best off with using
Storage.write
/read
with allocating a whole day/week at once and use offsets for writing data points. For reading you can either useStorage.read
which returns memory-mapped strings which is light in RAM use or if your data is actually binary encoded and not easily parsed as string useStorage.readArrayBuffer
which can be wrapped into one of the array types and used for easier parsing. -
I think you are correct in regard to the DK08 probably having the same display as the BIP S, the display differences are very close to what your pictures show. I had remembered the display to be better since it is the one point I liked better on the BIP S as I got my Bangle. But in hindsight the tradeoff between less colors vs. more contrast might actually be in favor of the Bangle display for me overall. The moment the backlight comes into play its hands down the 64 color display of the BIP S.
-
Amazfit BIP S has a very similar transflective display with the same resolution but 64 colors instead of 8. That would remove the need to dither and is lots more readable for text in colors the bangle would have to dither. Needs a bit more bandwidth and RAM but probably makes up for that in saved CPU cycles for the dithering.
-
I have switched my daily driver bangle to my second one and had massive problems with the Bluetooth stability to my HRM belt, connection loss about once every 2 minutes. After finding this I set the expected accuracy in the firmware all the way up to 500ppm and it seems much better. Comparable to the older Bangle. Both had the same firmware and exact same software (brought over via backup/import).
Is this possibly this timer accuracy thing? How can I prove this theory, is comparing clock drift between the two Bangles over 24 hours good enough for this? -
Concept: Run smoke tests / unit tests in custom built Espruino IDE docker images with GitHub actions
I have done a draft at https://github.com/espruino/BangleApps/pull/3399.
It is far from done, but it seems to correctly execute the first test ported from theandroid
appstest.js
.Output currently looks like the attached image.
-
Huh, with that hint I can simplify my script down to running jekyll in the parent directory of all my checked out repos and just point the IDE to
http://localhost:4001/BangleApps/modules|http://localhost:4001/EspruinoDocs/modules
as module sources. So no more file system linking of BangleApps and EspruinoDocs into the web IDE directory.Web Bluetooth works fine for me when hosting with jekyll as http server as well but it does not work when starting with
npm start
. Not that it really matters, jekyll is just fine for my purposes. -
What is the correct way to use locally hosted web IDE with locally hosted modules without CORS getting in the way? Linking the folders and using jekyll to host the IDE works fine but it feels a bit convoluted. Running with NPM does not have working bluetooth on my system:
Chrome on Linux requires chrome://flags/#enable-experimental-web-platform-features to be enabled.
Can I somehow install a complete app to the emulator without installing all files by hand? Maybe running an emulator externally and sharing it between IDE and appstore?
-
Thanks for the compliments ;)
My first developments were either directly using hardware (GPS/BT) or depended on boot code so the emulator wasn't great for developing those which prompted me to just use the real thing. I got a spare Bangle for this so my daily driver can stay connected to GadgetBridge all the time.
I guess for most development an emulator-based workflow would be more than sufficient and probably allow for faster iterations. That is definitely something for me to explore.The IDE has some really nice features like getting the value of variables by hovering over them in the source while using the debugger and autocompletion for most of the Bangle/Espruino-specific APIs. I don't know if that could easily be replicated otherwise.
Opening and marking the code files of an app in the IDE (usually app.js,lib.js, maybe a module) for automatic upload to the Bangle is a relatively low overhead for me. Everything is just open all the time on a dedicated virtual desktop in the background even if I don't use it. I let it upload libs/modules to storage and apps usually to RAM. That way every save in the editor directly uploads to hardware. I think that could simplify your workflow too since you would not need to rely on the copy-paste script anymore. -
I'm interested in the communities workflows for development, especially on the Bangle.
Mine is as follows on Arch Linux:
- Starting a local environment with the start script.
- Checkout a branch
- Open tabs for
localhost:4000
andlocalhost:4001
in chromium. - Install app from local apploader on Bangle
- Files to be modified are loaded into the web IDE and edited there or in VSCodium depending on anticipated amount of changes
- Upload and debugging in web IDE
Gotchas:
- I link
BangleApps/modules
andEspruinoDocs/modules
toEspruinoWebIDE/[b|e]mod
dirs and sethttp://localhost:4001/bmod|http://localhost:4001/emod
as module dirs in the web IDE. Otherwise CORS prevents me from loading modules.
I have played around with using the CLI tools for upload with the options for watching files which works fine but I always come back to the browser based method since it it a bit more finicky on the command line.
What are your top tips on developing offline?
Script for starting the environment:
export PATH="$(gem env | grep USER | tr -s ' ' | rev | cut -d ' ' -f 1 | rev)/bin:$PATH" gem install jekyll jekyll-theme-slate cd BangleApps jekyll serve --port 4000 & cd .. cd EspruinoWebIDE jekyll serve --port 4001 &
- Starting a local environment with the start script.
-
There is for example https://ifan-display.com/product/1-2-inch-round-transflective-tft-lcd/ which is a round 240 by 240 pixel display with relatively small borders. At 1.2" it is a bit small but generally square 176x176 pixel Bangle 2 apps would fit in this with only a few pixels cut off at the corners. So there would be a way to use the "legacy" apps without changes on a round display.
Personally I like square better just for ease of app development. -
Concept: Run smoke tests / unit tests in custom built Espruino IDE docker images with GitHub actions
If you let people write JS they'll try to be clever and it'll no longer be a set of 'do this check that' but something far more complicated
I think this speaks most to me personally :D
I will try to keep it as simple as possible and in json. I guess if we need more complexity we could just run/eval a js file as a step from the json test definition. -
Concept: Run smoke tests / unit tests in custom built Espruino IDE docker images with GitHub actions
I've had a play around porting the first of the test cases to json:
https://gist.github.com/halemmerich/3d0f1d41d8eebe76eedc8553530e5dd5
I think this should be all the asserts/features I need. I have a rough implementation for those but it is not yet working correctly.
Why did you decide on the json based format for test cases? Wouldn't javascript files be better for editing/linting/syntax highlighting?
Maybe a library that provides asserts and an easy way to setup the emulator for running testcases for a single app? Or the other way round, the test code is a module andapptests.js
iterates over the exports which are test functions and handles the environment like now. -
-
-
-
Concept: Run smoke tests / unit tests in custom built Espruino IDE docker images with GitHub actions
I had done this a while ago: https://github.com/espruino/BangleApps/blob/master/apps/android/test.js
Every step in that would probably map nicely to a test object in the json. I think I could refactor that.
Maybe some of the asserts would be useful as a teststep in the apptests? I could try to integrate those.
How does the emulator handle "hardware" like GPS? If it does not I probably need to find a new way to track the state of the "internal" GPS instead of checking the PIN mode like it does currently.
-
I think you hit a case nobody thought about before. At least I did not. "removable" apps are expected to cleanup all changes they did to global state while they are unloaded. In my opinion that includes the loading of fonts.
Widgets are the one notable exception to this general rule, just because it is not easy to completely get rid of widgets. In your case the app removes the font as it should but the widget still exists and expects it to be there. I suspect the loading of the font only takes place once in the widget and one of the following draws then fails.- Clock loaded, widgets loaded, font available globally
- Switch from clock to launcher, widgets still loaded, font removed by clock
- Something calls draw of widget, fails because of missing font.
There are a few possible solutions:
- Checking for the font in the widgets draw and reloading it if needed
- Not unloading fonts at all, probably problematic on Bangle 1 because of memory constraints
- Make the loading of fonts more local to app/widget instead of the global graphics object
- Attach a counter to a font on load and only really unload it if there is no user left
There probably are more ways to get this done but some discussion on this will be needed since will affect global behaviour.
- Clock loaded, widgets loaded, font available globally
-
One thing that I wasn't 100% clear on was whether OWMweather replaces Weather or if it simply provides it with info necessary to pull weather.
It is neither. OWMWeather pulls weather and writes the same file that Weather uses. You can use it without Weather installed. OWMWeather writes the file and other apps that use weather as written by the Weather app can use it. Weather does use it too and the apps should not conflict.
-
Interesting, OWMWeather checks if the location data file exists, but not if the location data itself is valid. So the question is, where does the broken
mylocation.json
come from? At a glance there is no way that could happen in themylocation
app code. To me it seems as if it always either sets both lat and long or nothing. Maybe the web interface needs additional checks before writing the file.
Ah, that explains why everything halts on entering
debugger
into the interactive console.As for the example:
The first time there is an
=undefined
ending up in the last stored line and that is then parsed instead of the 158 the line before. The code sent to the emulator is identical in both cases as theDEBUG:
lines show.The emulator in the web IDE does this too and always so it probably isn't a race but something funky with storing the last line? Maybe a stray
\r
or something like that...