Commit Graph
15611 Commits
Author SHA1 Message Date
Peter KandThomas Kuehne 9b7d380257 Zepp OS: send real coordinates in v5 place response
The v5 place dataset hard-coded latitude/longitude to "0.0" and used a
constant locationKey "accu:123456", which prevented watches that were
never provisioned via the official Zepp app (Bip 6, Active 2, ...) from
accepting the response as authoritative — they treated the zero coords
as a missing-location signal and silently refused to display weather
(issue #5653).

- ZeppOsWeatherHandlerV5.createPlace: pull lat/lon from WeatherSpec
  when set, else fall back to the user-configured location pref. Format
  with Locale.ROOT and derive a stable per-location locationKey from a
  hash of the coords so the watch can dedupe responses.

- ZeppOsWeatherService.onSendWeather: same fallback chain for the
  CMD_SET_DEFAULT_LOCATION packet so the watch's default-location state
  is bootstrapped with real coordinates instead of "1.234,-5.678".

Refs #5653.

source: https://github.com/PeterXMR/Gadgetbridge

(cherry picked from commit be87ac3364fbf5725f43e3dbac87ef2e103fdd89)
2026-06-07 05:32:42 +00:00
José Rebelo ef7a297100 Merge pull request 'cherry picks from #5946' (#6237)
Reviewed-on: https://codeberg.org/Freeyourgadget/Gadgetbridge/pulls/6237
2026-06-06 21:35:50 +02:00
Ingvar StepanyanandJosé Rebelo 9229239e7e Address review comments 2026-06-06 21:26:51 +02:00
Ingvar StepanyanandJosé Rebelo 3d48db83c9 Garmin: fix transfer notification leaks and stray pre-start posts
Three lifecycle bugs in GarminSupport's transferNotification:

* addFileToDownloadList incremented totalSize unconditionally, so a directory listing arriving on connect posted a notification with the unlocalised "Unknown transfer" fallback title before any transfer started.

* The start/finish pair gated on gbDevice.isBusy(), which other paths set and clear — start could be skipped while the matching finish ran anyway, or vice versa.

* dispose() didn't finish the notification, leaving it pinned after a mid-sync disconnect.

Gate the increments and the start/finish pair on the private isBusyFetching flag, and finish + clear the flag in dispose().
2026-06-06 21:26:51 +02:00
Ingvar StepanyanandJosé Rebelo 3b9b4126ba Workout list: live-refresh on ACTION_NEW_DATA without blink
Long-running per-line fetches (e.g. ExploreSync's catalog walk) hold the device's busy task for the entire session, so the busy→idle edge WorkoutListActivity refreshes on only fires at session end. Listen for ACTION_NEW_DATA too so each newly imported activity appears as it lands.

Add a silent loadSummaries path that skips the isLoading flips, and disable the RecyclerView change animator so the dashboard row's notifyItemChanged(0) doesn't cross-fade — both would otherwise read as a distracting blink during an active sync.
2026-06-06 21:26:51 +02:00
Ingvar StepanyanandJosé Rebelo c1946573fb Garmin: ExploreSync historical activity import
Wires the new ExploreSync sub-service into ProtocolBufferHandler and GarminSupport so a paired device's historical-line catalog can be fetched independently of FIT — which Garmin Connect Mobile irreversibly archives files out of after the first sync (see issues like #5694 and #5994). Activities the FIT path can no longer see become visible again here.

Each historical line is reconstructed into an ActivityTrack, written as GPX, and persisted as a BaseActivitySummary keyed on the first-point timestamp — the same surface FIT-imported workouts use, so UI and exporters need no ExploreSync awareness. GarminCoordinator now picks the activity track provider from the summary contents (gpxTrack vs rawDetailsPath) instead of hard-coding the FIT one.
2026-06-06 21:26:51 +02:00
Ingvar StepanyanandJosé Rebelo 1cfcd0772c Garmin: extract buildExportPath helper in GarminUtils
Three call sites (FileTransferHandler, FitImporter, GarminSupport) each open-coded the same [TYPE]/[YEAR]/[TYPE]_[timestamp]_[suffix] filename shape and re-created their own SimpleDateFormat. Hoist the formatters (now thread-safe DateTimeFormatter) and the path builder into GarminUtils as buildExportPath(type, instant, suffix, ext).

FitImporter's null-type fallback now uses "NULL" consistently for both directory and filename, fixing a latent NPE.
2026-06-06 21:26:51 +02:00
Ingvar StepanyanandJosé Rebelo 5b375b2bb8 Garmin: extract sendProtobufRequest helper
Every watch-bound Smart RPC site followed the same shape: sendOutgoingMessage(taskName, protocolBufferHandler.prepareProtobufRequest(payload)). Fold it into a single sendProtobufRequest(taskName, payload) on GarminSupport. No behaviour change.
2026-06-06 21:26:51 +02:00
Ingvar StepanyanandJosé Rebelo 32a18d8d81 Garmin: deduplicate degrees ↔ semicircles math in GarminUtils
The watch encodes lat/lon as signed 32-bit semicircles (1<<31 == 180°). Move the bidirectional conversion behind named helpers backed by a single constant, and migrate toLocationData and FieldDefinitionCoordinate onto them.
2026-06-06 21:26:51 +02:00
Thomas Kuehne 25e322ea9a IntentApiReceiver: enhance device specification in Intents
- harmonise extra `address` to `device` - the old extra `address` logs a warning but is still supported
- support optional `device` extra for action nodomain.freeyourgadget.gadgetbridge.command.ACTIVITY_SYNC
- support optional `device` extra for action nodomain.freeyourgadget.gadgetbridge.command.DEBUG_SEND_NOTIFICATION
- support optional `device` extra for action nodomain.freeyourgadget.gadgetbridge.command.DEBUG_INCOMING_CALL
- support optional `device` extra for action nodomain.freeyourgadget.gadgetbridge.command.DEBUG_END_CALL
- support ComponentName extras for action nodomain.freeyourgadget.gadgetbridge.command.DEBUG_TEST_NEW_FUNCTION
- code review

See Freeyourgadget/website#247 for the documentation update.
2026-06-06 18:03:48 +00:00
José Rebelo 7f755a6887 Merge pull request 'onTestNewFunction enhancements' (#6247)
Reviewed-on: https://codeberg.org/Freeyourgadget/Gadgetbridge/pulls/6247
2026-06-06 10:00:07 +02:00
José Rebelo c186b45742 Merge pull request 'SMAQ2OSS: move SMAQ2OSSSupport to standard package' (#6242)
Reviewed-on: https://codeberg.org/Freeyourgadget/Gadgetbridge/pulls/6242
2026-06-06 09:47:56 +02:00
Thomas Kuehne bc20a1a874 onTestNewFunction enhancements
EventHandler.onTestNewFunction
- add optional `options` Bundle parameter for receiving arguments

intent nodomain.freeyourgadget.gadgetbridge.command.DEBUG_TEST_NEW_FUNCTION
- add optional String extra `address` to specify the MAC address of the target device
- add optional Bundle extra `options` to pass arguments to EventHandler.onTestNewFunction
- construct a synthetic `options` bundle if the `options` extra is missing but there are `options_...` extras

Global setting `Settings / Developer options / Intent API / Allow Debug Command` must be enabled and the device(s) connected for the following examples.

Example to trigger onTestNewFunction for all currently connected devices:
`adb shell am broadcast -p nodomain.freeyourgadget.gadgetbridge -a "nodomain.freeyourgadget.gadgetbridge.command.DEBUG_TEST_NEW_FUNCTION"`

Example to trigger onTestNewFunction for a specific device:
`adb shell am broadcast -p nodomain.freeyourgadget.gadgetbridge -a "nodomain.freeyourgadget.gadgetbridge.command.DEBUG_TEST_NEW_FUNCTION" --es address "12:34:56:78:9A:BC" `

Example to trigger onTestNewFunction for a specific device with an option Bundle containing float x=4.2 and integer array y=[1,2,3] extras:
`adb.exe shell am broadcast -p nodomain.freeyourgadget.gadgetbridge -a "nodomain.freeyourgadget.gadgetbridge.command.DEBUG_TEST_NEW_FUNCTION" --es address "31:31:43:30:40:07" --ef options_x 4.2 --eia options_y 1,2,3`

Extras for some other types can also be specified via command line. See https://developer.android.com/tools/adb#IntentSpec for details.
2026-06-06 07:28:51 +00:00
Thomas Kuehne 2407519e61 SMAQ2OSS: move SMAQ2OSSSupport to standard package 2026-06-06 00:41:59 +00:00
Gideon Zenz 8be39c99ea Health Connect: Advance sync cursor for temperature records
TemperatureSyncer is the only syncer implementing HealthConnectSyncer
directly instead of inheriting from AbstractTimeSampleSyncer or
AbstractActivitySampleSyncer, both of which populate latestRecordTimestamp
in their base sync(). Its hand-rolled sync() never set the field, so the
orchestrator had nothing to advance the persisted cursor with and the
TEMPERATURE cursor stayed pinned at its starting value. Every sync then
re-read from that frozen point to now and re-inserted the whole span; the
per-record clientRecordId dedup hid the duplicates in Health Connect, so it
was silent but re-inserted weeks of records on each run.

Return the furthest-forward edge of the inserted records (body record time,
skin record endTime) as latestRecordTimestamp on the success path. The no-op
early returns keep it null, which correctly holds the cursor, matching every
other syncer's "nothing synced" behaviour. The cursor self-heals on the next
successful sync; no reset needed.
2026-06-05 23:29:37 +02:00
José Rebelo f6fe89fcf0 Zepp OS: Limit number of weather items in V5 response 2026-06-05 21:28:33 +01:00
d3vv3andThomas Kuehne 0443798dd7 cherry pick from #5946: fix OpenTracks integration with all package names
(cherry picked from commit 0f4449cd87)
2026-06-05 15:50:44 +00:00
d3vv3andThomas Kuehne adbe6b9e1e cherry pick from #5946: support org.forkgram.messenger messenger
(cherry picked from commit 75052fc070)
2026-06-05 15:48:55 +00:00
d3vv3andThomas Kuehne e839f1a573 cherry pick from #5946: fix steps and distance device wheels become unsynced
(cherry picked from commit 5b182bf800)
2026-06-05 15:48:23 +00:00
d3vv3andThomas Kuehne 60faf96f9b cherry pick from #5946: fix REM_SLEEP / AWAKE_SLEEP mixup
(cherry picked from commit 36baca30fa)
2026-06-05 15:47:37 +00:00
Gideon Zenz 05dffc4932 Health Connect: Use sync run timestamp as clientRecordVersion for activity records
The per-minute steps, calories and distance records set clientRecordVersion
to the metric value itself. Health Connect keeps the record with the highest
clientRecordVersion on a clientRecordId collision (newVersion >= existing
overwrites), so each minute became pinned to the largest value ever sent for
it. When a device delivers activity in two phases and revises a minute's value
downward between them, the corrected record carries a lower version and is
silently ignored, leaving Health Connect above the device's own total.

Stamp clientRecordVersion with the sync run's wall-clock instead, shared by
every record in the slice. A later run always outranks the value it previously
wrote for a minute, so the freshest re-read wins regardless of whether the
value rose or fell. The clientRecordId remains the dedup key and is unchanged.
2026-06-05 14:56:03 +02:00
Gideon Zenz 829f9b7c31 Health Connect: Recover late-arriving step samples
The ACTIVITY sync cursor is a single (deviceId, dataType) timestamp shared by
the steps, active-calories and distance syncers. The cursor advances to the
latest record produced by any of them. When a device delivers calorie/distance
detail for the most recent minutes before the matching step detail, the cursor
moves past those minutes on the calorie front; the step minutes that arrive on
the next sync are then clipped by the slice start boundary and lost forever.
Resetting the HC sync state recovered them, confirming the data was present in
the database but skipped.

Give the per-minute steps, calories and distance records a deterministic
clientRecordId (gb-{type}-{manufacturer}-{model}-{endEpochSecond}) so that
re-emitting a record upserts instead of duplicating, mirroring SleepSyncer.
With records now idempotent, extend the per-syncer slice lower bound backwards
by a one-hour lookback so the trailing window is re-emitted on the next sync
and the late minutes are recovered. Heart rate is a grouped series keyed on its
start time, cannot be deduped this way, and does not extend the shared base, so
it keeps strict boundaries and never re-emits.
2026-06-05 14:56:03 +02:00
Gideon Zenz 00c0a2ba5c Xiaomi: Suppress premature activity-data-finish signal during two-phase fetch
The Xiaomi two-phase activity fetch (today + past) could fire the data-finish
signal that triggers downstream consumers before all DETAILS files had been
parsed, so a consumer reading the database in that gap saw an incomplete
picture. Hold the finish signal until both fetch phases have delivered and
all files are parsed.

Use an AtomicBoolean for the fetch-hold flag and set awaitingPastResponse
before the fetch starts to avoid signalling between the two phases.
2026-06-05 14:55:20 +02:00
Thomas Kuehne 75e25a0e90 fix: Physical Layer (PHY) mask on MIUI for gadgets other than Casio GBX100 2026-06-05 10:48:25 +00:00
Andreas Shimokawa 7d9cb26d02 Pebble: pass dev_settings=true to rebble store url, do enable pbw downloads in browser 2026-06-05 10:19:52 +02:00
Thomas Kuehne 7e6d96ae8c TransactionBuilder: rename wait/WaitAction to sleep/SleepAction
Object.wait(long) and TransactionBuilder.wait(int) have too similar signatures that may result in unintentionally calling the wrong method.
2026-06-05 03:47:59 +00:00
Thomas Kuehne 7c309e9a5d TransactionBuilder: code review 2026-06-05 02:07:36 +00:00
José Rebelo d1ec9eb25f Update "Cancel" and "Delete" string identifiers to lowercase 2026-06-04 14:02:46 +01:00
José Rebelo aecd417722 Improve steps and calories number formatting 2026-06-04 13:56:25 +01:00
FjuroandHosted Weblate c90403513e Translated using Weblate (Czech)
Currently translated at 100.0% (4817 of 4817 strings)

Translation: Freeyourgadget/Gadgetbridge
Translate-URL: https://hosted.weblate.org/projects/freeyourgadget/gadgetbridge/cs/
2026-06-04 12:36:32 +00:00
Саша ПетровићandHosted Weblate 01af9abc65 Translated using Weblate (Serbian)
Currently translated at 63.5% (3060 of 4817 strings)

Translation: Freeyourgadget/Gadgetbridge
Translate-URL: https://hosted.weblate.org/projects/freeyourgadget/gadgetbridge/sr/
2026-06-04 12:36:32 +00:00
大王叫我来巡山andHosted Weblate fe7420ea83 Translated using Weblate (Chinese (Simplified Han script))
Currently translated at 100.0% (4817 of 4817 strings)

Translation: Freeyourgadget/Gadgetbridge
Translate-URL: https://hosted.weblate.org/projects/freeyourgadget/gadgetbridge/zh_Hans/
2026-06-04 12:36:31 +00:00
summoner001andHosted Weblate 03093a0c7f Translated using Weblate (Hungarian)
Currently translated at 100.0% (4817 of 4817 strings)

Translation: Freeyourgadget/Gadgetbridge
Translate-URL: https://hosted.weblate.org/projects/freeyourgadget/gadgetbridge/hu/
2026-06-04 12:36:31 +00:00
Zbignev HarminandHosted Weblate 7710a7538c Translated using Weblate (Russian)
Currently translated at 100.0% (4817 of 4817 strings)

Translation: Freeyourgadget/Gadgetbridge
Translate-URL: https://hosted.weblate.org/projects/freeyourgadget/gadgetbridge/ru/
2026-06-04 12:36:30 +00:00
FjuroandHosted Weblate d1a89cae7d Translated using Weblate (Czech)
Currently translated at 100.0% (4816 of 4816 strings)

Translation: Freeyourgadget/Gadgetbridge
Translate-URL: https://hosted.weblate.org/projects/freeyourgadget/gadgetbridge/cs/
2026-06-04 12:36:30 +00:00
summoner001andHosted Weblate b5167ca1be Translated using Weblate (Hungarian)
Currently translated at 100.0% (4816 of 4816 strings)

Translation: Freeyourgadget/Gadgetbridge
Translate-URL: https://hosted.weblate.org/projects/freeyourgadget/gadgetbridge/hu/
2026-06-04 12:36:29 +00:00
大王叫我来巡山andHosted Weblate 2e25be1dbe Translated using Weblate (Chinese (Simplified Han script))
Currently translated at 100.0% (4816 of 4816 strings)

Translation: Freeyourgadget/Gadgetbridge
Translate-URL: https://hosted.weblate.org/projects/freeyourgadget/gadgetbridge/zh_Hans/
2026-06-04 12:36:28 +00:00
apemayandHosted Weblate 403577f25e Translated using Weblate (Spanish)
Currently translated at 100.0% (4812 of 4812 strings)

Translation: Freeyourgadget/Gadgetbridge
Translate-URL: https://hosted.weblate.org/projects/freeyourgadget/gadgetbridge/es/
2026-06-04 12:36:28 +00:00
Саша ПетровићandHosted Weblate 0d835de663 Translated using Weblate (Serbian)
Currently translated at 63.4% (3054 of 4812 strings)

Translation: Freeyourgadget/Gadgetbridge
Translate-URL: https://hosted.weblate.org/projects/freeyourgadget/gadgetbridge/sr/
2026-06-04 12:36:27 +00:00
summoner001andHosted Weblate db2d9e61bf Translated using Weblate (Hungarian)
Currently translated at 100.0% (4812 of 4812 strings)

Translation: Freeyourgadget/Gadgetbridge
Translate-URL: https://hosted.weblate.org/projects/freeyourgadget/gadgetbridge/hu/
2026-06-04 12:36:27 +00:00
大王叫我来巡山andHosted Weblate 47a1d231c3 Translated using Weblate (Chinese (Simplified Han script))
Currently translated at 100.0% (4812 of 4812 strings)

Translation: Freeyourgadget/Gadgetbridge
Translate-URL: https://hosted.weblate.org/projects/freeyourgadget/gadgetbridge/zh_Hans/
2026-06-04 12:36:26 +00:00
FjuroandHosted Weblate 046c97c57e Translated using Weblate (Czech)
Currently translated at 100.0% (4812 of 4812 strings)

Translation: Freeyourgadget/Gadgetbridge
Translate-URL: https://hosted.weblate.org/projects/freeyourgadget/gadgetbridge/cs/
2026-06-04 12:36:25 +00:00
Zbignev HarminandHosted Weblate 41351ee7a3 Translated using Weblate (Russian)
Currently translated at 100.0% (4810 of 4810 strings)

Translation: Freeyourgadget/Gadgetbridge
Translate-URL: https://hosted.weblate.org/projects/freeyourgadget/gadgetbridge/ru/
2026-06-04 12:36:25 +00:00
Da VitoriaandHosted Weblate 2316e35e21 Translated using Weblate (French)
Currently translated at 94.8% (4561 of 4810 strings)

Translation: Freeyourgadget/Gadgetbridge
Translate-URL: https://hosted.weblate.org/projects/freeyourgadget/gadgetbridge/fr/
2026-06-04 12:36:24 +00:00
SverlanaandHosted Weblate c21c426f21 Translated using Weblate (Russian)
Currently translated at 99.2% (4776 of 4810 strings)

Translation: Freeyourgadget/Gadgetbridge
Translate-URL: https://hosted.weblate.org/projects/freeyourgadget/gadgetbridge/ru/
2026-06-04 12:36:23 +00:00
Luca SötheandHosted Weblate 34a3026e5c Translated using Weblate (German)
Currently translated at 99.3% (4777 of 4810 strings)

Translation: Freeyourgadget/Gadgetbridge
Translate-URL: https://hosted.weblate.org/projects/freeyourgadget/gadgetbridge/de/
2026-06-04 12:36:23 +00:00
Luca SötheandHosted Weblate f339d9c8c1 Translated using Weblate (German)
Currently translated at 98.2% (4727 of 4810 strings)

Translation: Freeyourgadget/Gadgetbridge
Translate-URL: https://hosted.weblate.org/projects/freeyourgadget/gadgetbridge/de/
2026-06-04 12:36:22 +00:00
David D.andHosted Weblate 8243212bf6 Translated using Weblate (French)
Currently translated at 94.9% (4566 of 4810 strings)

Translation: Freeyourgadget/Gadgetbridge
Translate-URL: https://hosted.weblate.org/projects/freeyourgadget/gadgetbridge/fr/
2026-06-04 12:36:22 +00:00
大王叫我来巡山andHosted Weblate 43be00d8c1 Translated using Weblate (Chinese (Simplified Han script))
Currently translated at 100.0% (4810 of 4810 strings)

Translation: Freeyourgadget/Gadgetbridge
Translate-URL: https://hosted.weblate.org/projects/freeyourgadget/gadgetbridge/zh_Hans/
2026-06-04 12:36:21 +00:00
Da VitoriaandHosted Weblate c169f87584 Translated using Weblate (French)
Currently translated at 94.9% (4566 of 4810 strings)

Translation: Freeyourgadget/Gadgetbridge
Translate-URL: https://hosted.weblate.org/projects/freeyourgadget/gadgetbridge/fr/
2026-06-04 12:36:21 +00:00