-
Just to check, did you enable "Heart rate monitoring" in the Wearables section of Sleep as Android, too?
I think that's the only extra step I took beyond what was mentioned before. I don't know why that's off by default; I almost overlooked it. It does look like it took maybe 20-50 minutes before the first reading in Sleep as Android; maybe there's a delay.
-
Setting the "DIY" smartwatch option was the only thing I missed; I mistakenly assumed the "Bangle.js" choice would've worked. No need to disable automatic nighttime DND, no need to reset Sleep as Android to defaults (thankfully due to over 2 years of sleep data gathered via phone). Heart rate monitoring works, too.
For my first night, the actigraph data does look.. different than just having my phone next to my pillow (notably, a lot less deep sleep time), but I'll need to try this for longer to get a feel for which might be more accurate.
Thanks again!
-
In case anyone missed this, Sleep as Android support will be available soon, courtesy of AnotherStranger (thank you!)…
- https://codeberg.org/Freeyourgadget/Gadgetbridge/pulls/3785 has been merged (not yet in a stable release)
- https://github.com/espruino/BangleApps/pull/3422 is available on the Bangle.js app site
- https://codeberg.org/Freeyourgadget/Gadgetbridge/pulls/3785 has been merged (not yet in a stable release)
-
Someone has stepped up to work on Sleep as Android support in Gadgetbridge!
https://codeberg.org/Freeyourgadget/Gadgetbridge/pulls/3188
It looks like they are focusing on the Mi Band (based on the PR branch name), but this could potentially be used as the foundation for Bangle.js 2 support, too.
-
AntennaPod does support notification channels, but I don't see a way to hide a specific notification channels in Gadgetbridge.
However, I now see that there is a way to filter on specific words in the notification, which I had not noticed and likely can work around this issue. (Ideally, Gadgetbridge itself would be fixed, but if that's too complicated I'd understand.)
-
Noted! I didn't realize the watch could update Gadgetbridge's settings, that's rather handy. (I initially avoided this as I didn't want to have two separate collections of notification ignoring settings.)
And sure thing! I understand this is a high risk area to mess with, and I'll keep an eye out for any other apps that trigger this issue.
(I am surprised that the LineageOS system updater does not cause this given it frequently posts notification updates on download/installation progress. A quick glance at the source code doesn't find any
setLocalOnly()
calls.) -
Sure thing! Your musings make sense. I haven't looked into Gadgetbridge's handling yet, but if I notice anything in potential future code-spelunkings, I'll let you know.
And, nah, I don't need AntennaPod notifications. It'd merely be nice to have, and I figured this might impact other folks too so I should report an issue. I had considered toggling the app off in Gadgetbridge then changing it to handle media notifications before the app blocklist; I'm glad to know the watch option handles similarly.
-
Yeah, that's actually what I suggested to the AntennaPod devs on GitHub - specifying "setLocalOnly(true)" on the download and service notifications.
The counterpoint I was given is that folks may want to see download progress on other devices. And with
setAlertOnlyOnce(true)
as documented on the page you linked to, presumably Gadgetbridge and/or Bangle.js should not be repeatedly showing the notification, only updating it.From what I can tell, AntennaPod does reuse the notification ID to update the notification (rather than deleting and recreating)…
There is
updateNotifications()
, which is called byNotificationUpdater
which specifies a fixed notification ID:private class NotificationUpdater implements Runnable { public void run() { Notification n = notificationManager.updateNotifications(downloads); if (n != null) { NotificationManager nm = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE); nm.notify(R.id.notification_downloading, n); } } }
(This notification ID and others are defined in the resources.)
Based on code elsewhere in the same file, this notification is updated once a second:
/** * Schedules the notification updater task if it hasn't been scheduled yet. */ private void setupNotificationUpdaterIfNecessary() { if (notificationUpdater == null) { Log.d(TAG, "Setting up notification updater"); notificationUpdater = new NotificationUpdater(); notificationUpdaterFuture = notificationUpdateExecutor .scheduleAtFixedRate(notificationUpdater, 1, 1, TimeUnit.SECONDS); } }
-
I've run into two possibly-related issues with the handling of notifications for AntennaPod:
Playing any episode, pausing, then resuming after a minute or so results in a
Loading. If this does not go away, play any episode and contact us.
notification showing on Bangle.js, however my phone never shows this notification- That notification does not go away without me actually deleting the message from the Message GUI
- That notification does not go away without me actually deleting the message from the Message GUI
Refreshing podcasts and downloading episodes result in the watch buzzing for every percentage change despite AntennaPod specifying
setOnlyAlertOnce()
- In the process, my Bangle.js 2 bogs down with processing and can take 15-30 seconds to stop vibrating once AntennaPod has finished and the notification is gone from my phone
- Android 12+ hides the download/refresh notification for 10 seconds - when testing, make sure the download/refresh takes longer
- In the process, my Bangle.js 2 bogs down with processing and can take 15-30 seconds to stop vibrating once AntennaPod has finished and the notification is gone from my phone
I tried filing an issue on AntennaPod's repository, suggesting that download notifications should not be forwarded to wearables, but the developer responded saying some folks may expect download notifications, which I s'pose makes sense - e.g. if you have a slow download, you could monitor it from your watch/computer via KDE Connect/etc.
I'm not sure if this is a Gadgetbridge problem, a Bangle.js problem, or something else…?
Device details
- Pixel 4 XL (LineageOS 20 + GApps, Gadgetbridge 0.74.0-banglejs)
- Bangle.js 2 (firmware 2v18)
Apps:
antonclk (0.11), gpsautotime (0.04), locale (0.17), launch (0.20), about (0.14), clkinfosunrise (0.03), widlock (0.08), agpsdata (0.06), circlesclock (0.25), info (0.03), qcenter (0.04), messageicons (0.05), widbat (0.11), weather (0.25), sched (0.22), widminbt (0.01), alarm (0.41), health (0.23), widmessages (0.05), widalarmeta (0.10), owmweather (0.03), loadingscreen (0.01), kbswipe (0.08), notify (0.13), boot (0.58), setting (0.61), messages (0.60), mylocation (0.10), clock_info (0.06), android (0.29), rescalc (0.03), messagegui (0.73), multitimer (0.04), agenda (0.14), quicklaunch (0.15)
-
UPDATE: fetching Gadgetbridge debug logs, I see… nothing from Sleep as Android in Gadgetbridge's logs.
I have my custom code snippet from Tasker successfully shown and parsed, though.
Perhaps there's something between Bangle.js Gadgetbridge and Sleep as Android that needs fixed?
I do frequently see the following, but I suspect it's unrelated:
[JCould not load clock info "sched.clkinfo.js"
Looking at
adb logcat
, it seems like Sleep as Android is listening for acom.urbandroid.sleep.watch.CONFIRM_CONNECTED
broadcast:03-22 16:23:56.110 20919 20919 I SleepAsAndroid: [22Mar 16:23:56.110, main]: Theme: setting last SmartWatchActivity 16 03-22 16:23:56.110 20919 20919 I SleepAsAndroid: [22Mar 16:23:56.110, main]: SmartWatchActivity:onCreate() {EX:null} [I: {EX:test_sensors (true) }] 03-22 16:23:56.122 20919 20919 I SleepAsAndroid: [22Mar 16:23:56.122, main]: onCreate SmartWatchActivity wearable Bangle.js 03-22 16:23:56.123 20919 20919 I SleepAsAndroid: [22Mar 16:23:56.123, main]: SmartWatchActivity:Async connecting smart watch 03-22 16:23:56.123 20919 20919 I SleepAsAndroid: [22Mar 16:23:56.123, main]: SmartWatch: Async smart watch connect called 03-22 16:23:56.123 20919 20919 I SleepAsAndroid: [22Mar 16:23:56.123, main]: SleepPhaser: GET address null 03-22 16:23:56.123 20919 20919 I SleepAsAndroid: [22Mar 16:23:56.123, main]: SleepMaskBt: GET address null 03-22 16:23:56.124 20919 20919 I SleepAsAndroid: [22Mar 16:23:56.124, main]: Using watch accel: BaseWatchAccelManager 03-22 16:23:56.124 20919 20919 I SleepAsAndroid: [22Mar 16:23:56.124, main]: SmartWatch: ConnectivityChecker registering receiver for com.urbandroid.sleep.watch.CONFIRM_CONNECTED watch com.urbandroid.sleep.smartwatch.generic.GenericWatch@6946671 […] 03-22 16:23:56.131 20919 20919 D SleepAsAndroid: [22Mar 16:23:56.131, main]: SmartWatchActivity:onStart() 03-22 16:23:56.132 20919 20919 D SleepAsAndroid: [22Mar 16:23:56.132, main]: SmartWatchActivity:onResume() 03-22 16:23:56.133 20919 20919 I SleepAsAndroid: [22Mar 16:23:56.133, main]: Theme: onPostResume() SmartWatchActivity 03-22 16:23:56.138 1810 4994 D CoreBackPreview: Window{d471394 u0 com.urbandroid.sleep/com.urbandroid.sleep.SmartWatchActivity}: Setting back callback OnBackInvokedCallbackInfo{mCallback=android.window.IOnBackInvokedCallback$Stub$Proxy@3722632, mPriority=0} 03-22 16:23:56.145 20919 29298 E OpenGLRenderer: Unable to match the desired swap behavior. 03-22 16:23:56.152 20919 29298 W Parcel : Expecting binder but got null! 03-22 16:23:56.167 1810 1933 I ActivityTaskManager: Displayed com.urbandroid.sleep/.SmartWatchActivity: +81ms 03-22 16:23:56.234 20919 20919 I SleepAsAndroid: [22Mar 16:23:56.233, main]: Theme: onPostResumeAfterRecreate() […] 03-22 16:23:56.747 20919 20919 D SleepAsAndroid: [22Mar 16:23:56.747, main]: AlarmClock:onStop() 03-22 16:23:56.752 20919 20919 D SleepAsAndroid: [22Mar 16:23:56.752, main]: SimpleSettingsActivity:onStop() 03-22 16:23:56.753 20919 20919 D SleepAsAndroid: [22Mar 16:23:56.753, main]: TrackSettingsActivity:onStop() 03-22 16:23:56.754 20919 20919 D SleepAsAndroid: [22Mar 16:23:56.754, main]: SmartwatchSettingsActivity:onStop()
This matches up with the Sleep as Android Wearable integration API documentation:
https://docs.sleep.urbandroid.org/devs/wearable_api.html#initiating-connection-to-phoneI git-clone'd the Gadgetbridge source code and searched recursively for
CONFIRM_CONNECTED
, but didn't find it anywhere. -
I'm glad to know it's not just me :)
My guess is the Sleep as Android app is sending JS code to the Bangle.js 2 watch via the Bangle.js Gadgetbridge app, and expecting some sort of reply (perhaps via Android Intents?) that it doesn't receive.
I'll try to look into the Gadgetbridge debugging advice soon. You might be able to find something with it, too?
https://www.espruino.com/Gadgetbridge#debugging -
Has anyone used the Sleep as Android app with their Bangle.js 2 (not v1)?
In Sleep as Android's
Settings
→Sleep tracking
→Wearables
→Use wearable
section, there's an option forBangle.js
. If you don't have the Bangle.js Gadgetbridge installed, it'll direct you to the Play Store to get it. Otherwise, when testing, it waits to connect to my Bangle.js 2… and does nothing. I have all the Gadgetbridge and Bangle programming/intents/etc features enabled, and I've confirmed that I can send JavaScript code via Tasker (to auto-toggle Quiet mode).I'm guessing Sleep as Android's integration was written for the Bangle.js v1 since it doesn't mention heart-rate monitoring, and the v2 hardware/firmware may be different enough to break it.
I did reach out to Sleep as Android's support, and apparently it's a third party integration:
I did implement the PineTime integration myself.. but for the Bangle.js I'm sorry this is third party and I do not know anything about it :( I did not yet test this and do not have the device.. although I may get to Bangle.js in the future and hopefully integrate it.
I'd be happy to try debugging this, but I figured I'd get an idea of what others know first.
Aside, I know Bangle.js 2 has a self-contained sleep phase alarm/tracking app. However, I have over 2 years of sleep data in Sleep as Android and I've integrated it into my routine (controls bedroom lights/music, activates different modes on my phone, etc). Installing the sleep phase alarm app didn't seem to make this work, either.
-
Over a period of 1h:11m:46s, starting from around 36% charge and an (almost certainly inaccurate) calculated battery voltage of 3.8126v, using that 67 mA-ish cut-off…
0.113 Ah (or 0.57442 Wh)
The USB power meter offers a way to calculate capacity, so by setting voltage to 3.8v and estimated charging efficiency to 90%, it results in an inaccurate estimated 0.1364 Ah battery capacity (real capacity is 350 mAh).
I attempted to calculate the voltage with the following (using the
pc
calculation to compare with the Bangle's own estimate):let batteryFullVoltage = 0.3144; let v = analogRead(D3); let v = 4.2 * v / batteryFullVoltage; if (v>=3.95) { let pc = 80 + (v-3.95)*20/(4.2-3.95); // 80%+ } else if (v>=3.7) { let pc = 10 + (v-3.7)*70/(3.95-3.7); // 10%+ is linear } else { let pc = (v-3.3)*10/(3.7-3.3); // 0%+ } Terminal.write("Batt voltage:" + (v).toFixed(4).toString() + "\n");
As it turns out, your estimate was pretty close! If I had drained the battery further, I'd probably have hit your target (I try to not let the battery dip too low, either).
-
A brief follow-up - my Bangle.js 2 seems to charge at around 98 mA for the majority of time, then by the time it reaches "100%", it has tapered off to 67 mA, where my powerbank then cuts off power. This is before Charge Gently (chargent) even activates. My USB power meter was powered separately for the tests, so it did not impact the powerbank cutoff.
Taking it off the charger, letting the voltage settle, that put my Bangle 2 at around "96%" (and a few hours later, "94%").
This is an excellent solution that turns an aggravation with my powerbank's cut-off into a free hardware charge limiter for my watch, thank you @halemmerich for the idea!
-
The Chargie seems very cool. Thanks for dropping that name […]
Sure thing! I'm glad mentioning this was helpful.
As for the Bangle, a workaround would be charging from a powerbank. Many of those cut off the charging when the current is low. […]
My pre-2013 powerbank does this and it has bugged me so much. Now I see that this is a feature! I've got a USB power meter that can be independently powered (so it won't increase the power bank's load) - next time I need to charge my Bangle 2, I'll see how it goes.
I'd be really surprised if someone hasn't made an inline USB gadget that does that already - but if not you should totally make one!
Ah, that's actually why I mentioned Chargie - see "Is there any way Chargie can work without the app?" on the FAQ page.
Chargie was originally intended for managing phones via iOS and Android, but it also supports a hardware cut-off that's committed to memory. Granted, there are probably ways to make a cheaper circuit if you don't support Bluetooth control and all that.
-
-
I've seen two separate apps that provide a way to alert on approaching full battery charge,
chargent
andpowermanager
.Rather than simply alerting, does the Bangle.js 2 hardware provide a way to actually reduce the maximum charging voltage limit?
It looks like the charge controller isn't programmable, but I thought I should double-check. I see mentions of
pin_charging
andpin_voltage
, but those seem to be input-only, and the battery percentage code appears to simply convert an analog voltage value.(As context, I've been working on implementing battery charge voltage limiting for the Flipper Zero multi-tool, which is using a Texas Instruments
bq25896
controlled over I²C.) -
-
Yes, that was intended, but time to sunrise sounds good - just changed
Thank you!
I'm not sure I understand - do you have a picture? I just checked and the icons appear to be stored and rendered ok for me...
The small icons are all rendered correctly for me. It's only when I toggle "show big weather" on that I have an issue. I've attached a photo - the icon should be shown in the blank gap at the top right, above the "49°F".
It shows correctly in light theme; it's only in dark theme that it's invisible.
Hazarding a guess, the following code might need a call to
g.setColor(g.theme.fg)
first? -
Wow, that was really fast - thank you! It's also nice to have suncalc stored on the watch directly, no need to HTTP fetch it, and the faster circle rendering (and fast loading to other apps) is appreciably improved and more usable.
There's no obligation at all to change things further, but if you are open to suggestions:
Right now, the "Time" sunrise/sunset clock info shows the current time of day, which is redundant on clock faces that include a larger time of day display.
If intended, that's okay!
However, it might make more sense to either show what time of day the upcoming sunrise/sunset will be (using
sunrise.getTime()
orsunset.getTime()
, whichever comes next), or providing a textual representation of the relative time remaining (e.g. convertingv
into "3h", "52m", etc), ascirclesclock
previously did. I slightly lean towards a relative number, but I can see reasons for absolute times to be preferred and I'd be happy with either. -
Hi - I'm here to complain ;)
Actually, no, I'm really happy with the updates to circlesclock - the swipe UI to switch what's shown is really convenient for previewing what I'm actually going to see. It does interfere with Quick Launcher's swipe to launch stuff, but I can work around that.
Thank you!
The only thing I do miss is Sunrise Clockinfo does not provide a "next sunrise/sunset" mode. I can see when the next sunset happens, or when the next sunrise happens, but I don't see a way to have it automatically switch to whichever is closest (sunrise/sunset), and the circle ring appears to always be filled.
(Since I haven't yet filed a bug report, the big weather icons appear to not be colored with the FG color, as they disappear on black theme. But it's not a big deal.)
-
-
That makes sense - in rough Android parlance, the Bangle back button mimics the Android Back button (even down to the inconsistency with which Android apps handle "back" events), and
widclose
/widcloselaunch
act like the Home button/"open launcher" keyboard shortcut, respectively.I feel like it'd be reasonable to have a default implementation that's either a boolean to enable or made opt-out, similar to how the widget bar can be shown/hidden. However, I'm not sure how practical this would be in reality.
And noted on the weather app! Whenever I have the time/energy, I'll look into making this change.
-
Overall, this is awesome! The Alarm ETA widget on Bangle.js is a nice way to see how much time I have left to sleep if I wake up early, too.
However, after some more nights to test, the Bangle.js actigraph data feels like it's less meaningful vs. my phone next to my pillow. So far, Sleep as Android has not detected deep sleep, always triggering the smart wake up alarm at the earliest start time.
My phone next to my pillow (2024-7-2):
Wearing Bangle.js 2 (2024-7-9):
I wonder if there's a difference in how Bangle.js 2 reports accelerometer data..?
At a glance, the
accelsender
code looks correct, as does the Gadgetbridge handling. If I understand correctly, Bangle.js 2 finds the maximum acceleration over a 1000 ms period (o.put("interval", 1000);
), sends that to Gadgetbridge, which then finds the maximum acceleration over a 9999 ms period, sending it to Sleep as Android once it hits batch size.