1
0
mirror of https://codeberg.org/Freeyourgadget/Gadgetbridge synced 2024-06-07 05:38:13 +02:00

Compare commits

...

52 Commits

Author SHA1 Message Date
Vitaliy Tomin
c3e527549e Huawei: Set user info to device
* height
* weight
* age
* year of birth
* gender
2024-05-08 15:02:58 +08:00
ahormann
ac8d1ed6a0 New Device Soundcore Liberty 3 Pro (#3753)
Reviewed-on: https://codeberg.org/Freeyourgadget/Gadgetbridge/pulls/3753
Co-authored-by: ahormann <ahormann@gmx.net>
Co-committed-by: ahormann <ahormann@gmx.net>
2024-05-07 22:39:13 +00:00
MrYoranimo
508a86b8ed Xiaomi: fix determining fall asleep time
Because the previous implementation of determining the time the user
falls asleep in a given time range would take the 24 hours in advance
into account, graphs displaying sleep data would erroneously indicate
that the user has been asleep since the start of the timeframe if
the user was asleep during the rollover of the time frame 24 hours
before.

This commit change the algorithm to only fetch the last sleep stage
sample and sleep range sample from the database that occurred before
the given time range. This saves having to process 24 hours worth of
samples before the time range in both cases, and prevents taking into
account irrelevant sleep ranges.
2024-05-07 13:33:52 +02:00
MrYoranimo
f581d57c01 Xiaomi: fix sleep stages not getting parsed from sleep details files
Not all packets use the payload length byte/short for the payload
length. Instead, some packets do not carry a payload, in which case
the payload length bytes are assumed to represent some state or flag.
Therefore, for packets with a type known not to carry a payload, the
payload extraction is skipped, allowing other packets to get
successfully parsed again.
2024-05-07 13:17:10 +02:00
José Rebelo
bed67ef1fb Xiaomi: Allow transliteration 2024-05-05 12:36:23 +01:00
José Rebelo
04237b7727 Prevent query for devices that have activity card disabled
Even if the activity card was disabled, all devices would be queried for
data. This slows down the UI when there are a lot of devices, especially
if multiple of them have data and only a few have the card enabled.
2024-05-04 23:51:19 +01:00
Alik Aslanyan
dc1ffdafcd Rework Armenian transliteration to handle more edge cases around mixed letters 2024-05-04 20:45:35 +04:00
José Rebelo
eaf7c03f61 Galaxy Buds 2: Fix recognition of some versions 2024-05-04 11:06:07 +01:00
José Rebelo
7892afa304 Xiaomi: Fix barometer
Thanks to MrYoranimo for the fix.
2024-05-03 22:27:57 +01:00
Martin.JM
4c93647aaf [Huawei] Add TruSleep warning 2024-05-02 20:59:08 +02:00
José Rebelo
881e8e36e8 Update changelog 2024-05-01 23:35:04 +01:00
José Rebelo
0ff8774fce DebugActivity: Omit manufacturer for test devices if name contains it 2024-05-01 23:34:14 +01:00
rymut
7a50df61b8 [Huawei] refactor: removed isExperimental override 2024-05-01 22:35:12 +02:00
rymut
8860b4b678 [Huawei] fix: use correct coordinator for watch fit 2 2024-05-01 22:24:36 +02:00
Nyatsuki
b8852379f9
Translated using Weblate (Japanese)
Currently translated at 54.7% (1500 of 2739 strings)

Co-authored-by: Nyatsuki <Odamaki@yandex.ru>
Translate-URL: https://hosted.weblate.org/projects/freeyourgadget/gadgetbridge/ja/
Translation: Freeyourgadget/Gadgetbridge
2024-05-01 18:34:03 +02:00
Baka Gaijin
07a11addb9
Translated using Weblate (Japanese)
Currently translated at 54.6% (1494 of 2735 strings)

Co-authored-by: Baka Gaijin <lewdwarrior@waifu.club>
Translate-URL: https://hosted.weblate.org/projects/freeyourgadget/gadgetbridge/ja/
Translation: Freeyourgadget/Gadgetbridge
2024-05-01 18:34:02 +02:00
あぽろあぽろ
4dde33c342
Translated using Weblate (Japanese)
Currently translated at 54.6% (1494 of 2735 strings)

Co-authored-by: あぽろあぽろ <aporotilyoko0000@gmail.com>
Translate-URL: https://hosted.weblate.org/projects/freeyourgadget/gadgetbridge/ja/
Translation: Freeyourgadget/Gadgetbridge
2024-05-01 18:34:00 +02:00
Deleted User
294adf6da5
Translated using Weblate (Portuguese (Brazil))
Currently translated at 52.3% (1432 of 2735 strings)

Co-authored-by: Deleted User <Resume7202@users.noreply.hosted.weblate.org>
Translate-URL: https://hosted.weblate.org/projects/freeyourgadget/gadgetbridge/pt_BR/
Translation: Freeyourgadget/Gadgetbridge
2024-05-01 18:33:59 +02:00
José Rebelo
5c7ea9131e
Translated using Weblate (Russian)
Currently translated at 94.8% (2589 of 2731 strings)

Co-authored-by: José Rebelo <joserebelo@outlook.com>
Translate-URL: https://hosted.weblate.org/projects/freeyourgadget/gadgetbridge/ru/
Translation: Freeyourgadget/Gadgetbridge
2024-05-01 18:33:57 +02:00
0que
27fa1a94fe
Translated using Weblate (Russian)
Currently translated at 94.8% (2592 of 2734 strings)

Translated using Weblate (Russian)

Currently translated at 94.8% (2589 of 2731 strings)

Co-authored-by: 0que <0que@users.noreply.hosted.weblate.org>
Translate-URL: https://hosted.weblate.org/projects/freeyourgadget/gadgetbridge/ru/
Translation: Freeyourgadget/Gadgetbridge
2024-05-01 18:33:56 +02:00
summoner001
80857758b4
Translated using Weblate (Hungarian)
Currently translated at 84.2% (2287 of 2716 strings)

Co-authored-by: summoner001 <summoner@vivaldi.net>
Translate-URL: https://hosted.weblate.org/projects/freeyourgadget/gadgetbridge/hu/
Translation: Freeyourgadget/Gadgetbridge
2024-05-01 18:33:54 +02:00
Balage
153199b3b4
Translated using Weblate (Hungarian)
Currently translated at 83.1% (2258 of 2714 strings)

Co-authored-by: Balage <222855@buas.nl>
Translate-URL: https://hosted.weblate.org/projects/freeyourgadget/gadgetbridge/hu/
Translation: Freeyourgadget/Gadgetbridge
2024-05-01 18:33:52 +02:00
Sergey Ponomarev
c7a29e4499
Translated using Weblate (Russian)
Currently translated at 95.1% (2580 of 2711 strings)

Co-authored-by: Sergey Ponomarev <stokito@gmail.com>
Translate-URL: https://hosted.weblate.org/projects/freeyourgadget/gadgetbridge/ru/
Translation: Freeyourgadget/Gadgetbridge
2024-05-01 18:33:51 +02:00
Nyatsuki
7b05853b7d
Translated using Weblate (Japanese)
Currently translated at 54.6% (1494 of 2735 strings)

Translated using Weblate (Japanese)

Currently translated at 45.8% (1255 of 2735 strings)

Translated using Weblate (Japanese)

Currently translated at 44.3% (1213 of 2735 strings)

Translated using Weblate (Japanese)

Currently translated at 42.3% (1157 of 2734 strings)

Translated using Weblate (Japanese)

Currently translated at 41.5% (1136 of 2734 strings)

Translated using Weblate (Japanese)

Currently translated at 41.5% (1135 of 2734 strings)

Translated using Weblate (Japanese)

Currently translated at 41.5% (1134 of 2731 strings)

Translated using Weblate (Japanese)

Currently translated at 41.4% (1131 of 2731 strings)

Translated using Weblate (Japanese)

Currently translated at 41.1% (1124 of 2731 strings)

Translated using Weblate (Japanese)

Currently translated at 39.3% (1069 of 2716 strings)

Translated using Weblate (Japanese)

Currently translated at 38.3% (1042 of 2714 strings)

Translated using Weblate (Japanese)

Currently translated at 36.8% (1000 of 2711 strings)

Co-authored-by: Nyatsuki <Odamaki@yandex.ru>
Translate-URL: https://hosted.weblate.org/projects/freeyourgadget/gadgetbridge/ja/
Translation: Freeyourgadget/Gadgetbridge
2024-05-01 18:33:49 +02:00
summoner001
d543dcdd80
Translated using Weblate (Hungarian)
Currently translated at 81.0% (2198 of 2711 strings)

Co-authored-by: summoner001 <summoner@vivaldi.net>
Translate-URL: https://hosted.weblate.org/projects/freeyourgadget/gadgetbridge/hu/
Translation: Freeyourgadget/Gadgetbridge
2024-05-01 18:33:47 +02:00
0que
58c4242ba5
Translated using Weblate (Russian)
Currently translated at 95.0% (2578 of 2711 strings)

Co-authored-by: 0que <0que@users.noreply.hosted.weblate.org>
Translate-URL: https://hosted.weblate.org/projects/freeyourgadget/gadgetbridge/ru/
Translation: Freeyourgadget/Gadgetbridge
2024-05-01 18:33:44 +02:00
Hikaru
1d53259988
Translated using Weblate (Japanese)
Currently translated at 30.4% (826 of 2711 strings)

Co-authored-by: Hikaru <Hikali-47041@users.noreply.hosted.weblate.org>
Translate-URL: https://hosted.weblate.org/projects/freeyourgadget/gadgetbridge/ja/
Translation: Freeyourgadget/Gadgetbridge
2024-05-01 18:33:41 +02:00
Nyatsuki
f596c3b83c
Translated using Weblate (Japanese)
Currently translated at 30.4% (826 of 2711 strings)

Co-authored-by: Nyatsuki <Odamaki@yandex.ru>
Translate-URL: https://hosted.weblate.org/projects/freeyourgadget/gadgetbridge/ja/
Translation: Freeyourgadget/Gadgetbridge
2024-05-01 18:33:40 +02:00
ritchierope
2ed0be0bcd
Translated using Weblate (Hungarian)
Currently translated at 80.2% (2175 of 2711 strings)

Co-authored-by: ritchierope <zdg.acc@mailbox.org>
Translate-URL: https://hosted.weblate.org/projects/freeyourgadget/gadgetbridge/hu/
Translation: Freeyourgadget/Gadgetbridge
2024-05-01 18:33:37 +02:00
summoner001
a94e1eb573
Translated using Weblate (Hungarian)
Currently translated at 80.2% (2175 of 2711 strings)

Co-authored-by: summoner001 <summoner@vivaldi.net>
Translate-URL: https://hosted.weblate.org/projects/freeyourgadget/gadgetbridge/hu/
Translation: Freeyourgadget/Gadgetbridge
2024-05-01 18:33:35 +02:00
Stepan
6fd9414d37
Translated using Weblate (Russian)
Currently translated at 95.2% (2572 of 2700 strings)

Co-authored-by: Stepan <stepan.miroshnikov@gmail.com>
Translate-URL: https://hosted.weblate.org/projects/freeyourgadget/gadgetbridge/ru/
Translation: Freeyourgadget/Gadgetbridge
2024-05-01 18:33:33 +02:00
glemco
05ffd79815
Translated using Weblate (Italian)
Currently translated at 90.8% (2482 of 2731 strings)

Translated using Weblate (Italian)

Currently translated at 89.1% (2435 of 2731 strings)

Translated using Weblate (Italian)

Currently translated at 85.3% (2299 of 2694 strings)

Co-authored-by: glemco <glemco@posteo.net>
Translate-URL: https://hosted.weblate.org/projects/freeyourgadget/gadgetbridge/it/
Translation: Freeyourgadget/Gadgetbridge
2024-05-01 18:33:31 +02:00
Yaron Shahrabani
82dfbce231
Translated using Weblate (Hebrew)
Currently translated at 98.1% (2681 of 2731 strings)

Translated using Weblate (Hebrew)

Currently translated at 98.5% (2673 of 2711 strings)

Translated using Weblate (Hebrew)

Currently translated at 97.4% (2642 of 2711 strings)

Translated using Weblate (Hebrew)

Currently translated at 95.5% (2590 of 2711 strings)

Translated using Weblate (Hebrew)

Currently translated at 95.7% (2587 of 2702 strings)

Translated using Weblate (Hebrew)

Currently translated at 95.5% (2581 of 2700 strings)

Translated using Weblate (Hebrew)

Currently translated at 95.3% (2575 of 2700 strings)

Translated using Weblate (Hebrew)

Currently translated at 95.4% (2574 of 2698 strings)

Translated using Weblate (Hebrew)

Currently translated at 96.2% (2569 of 2668 strings)

Co-authored-by: Yaron Shahrabani <sh.yaron@gmail.com>
Translate-URL: https://hosted.weblate.org/projects/freeyourgadget/gadgetbridge/he/
Translation: Freeyourgadget/Gadgetbridge
2024-05-01 18:33:29 +02:00
0que
3d35e322e9
Translated using Weblate (Russian)
Currently translated at 95.1% (2568 of 2698 strings)

Translated using Weblate (Russian)

Currently translated at 95.1% (2563 of 2694 strings)

Translated using Weblate (Russian)

Currently translated at 96.0% (2562 of 2668 strings)

Co-authored-by: 0que <0que@users.noreply.hosted.weblate.org>
Translate-URL: https://hosted.weblate.org/projects/freeyourgadget/gadgetbridge/ru/
Translation: Freeyourgadget/Gadgetbridge
2024-05-01 18:33:28 +02:00
bowornsin
f2002fc9a9
Translated using Weblate (Thai)
Currently translated at 4.0% (110 of 2710 strings)

Translated using Weblate (Thai)

Currently translated at 3.2% (89 of 2702 strings)

Translated using Weblate (Thai)

Currently translated at 3.0% (82 of 2702 strings)

Translated using Weblate (Thai)

Currently translated at 3.3% (90 of 2664 strings)

Co-authored-by: bowornsin <bowornsin@gmail.com>
Translate-URL: https://hosted.weblate.org/projects/freeyourgadget/gadgetbridge/th/
Translation: Freeyourgadget/Gadgetbridge
2024-05-01 18:33:25 +02:00
Linerly
9caf07657d
Translated using Weblate (Indonesian)
Currently translated at 100.0% (2735 of 2735 strings)

Translated using Weblate (Indonesian)

Currently translated at 100.0% (2734 of 2734 strings)

Translated using Weblate (Indonesian)

Currently translated at 99.3% (2712 of 2731 strings)

Translated using Weblate (Indonesian)

Currently translated at 100.0% (2711 of 2711 strings)

Translated using Weblate (Indonesian)

Currently translated at 100.0% (2710 of 2710 strings)

Translated using Weblate (Indonesian)

Currently translated at 100.0% (2702 of 2702 strings)

Translated using Weblate (Indonesian)

Currently translated at 100.0% (2700 of 2700 strings)

Translated using Weblate (Indonesian)

Currently translated at 100.0% (2698 of 2698 strings)

Translated using Weblate (Indonesian)

Currently translated at 100.0% (2694 of 2694 strings)

Translated using Weblate (Indonesian)

Currently translated at 100.0% (2668 of 2668 strings)

Translated using Weblate (Indonesian)

Currently translated at 100.0% (2664 of 2664 strings)

Translated using Weblate (Indonesian)

Currently translated at 100.0% (2639 of 2639 strings)

Translated using Weblate (Indonesian)

Currently translated at 100.0% (2631 of 2631 strings)

Co-authored-by: Linerly <linerly@proton.me>
Translate-URL: https://hosted.weblate.org/projects/freeyourgadget/gadgetbridge/id/
Translation: Freeyourgadget/Gadgetbridge
2024-05-01 18:33:23 +02:00
Rex_sa
1c7c7ff4d6
Translated using Weblate (Arabic)
Currently translated at 100.0% (2738 of 2738 strings)

Translated using Weblate (Arabic)

Currently translated at 100.0% (2735 of 2735 strings)

Translated using Weblate (Arabic)

Currently translated at 100.0% (2734 of 2734 strings)

Translated using Weblate (Arabic)

Currently translated at 100.0% (2731 of 2731 strings)

Translated using Weblate (Arabic)

Currently translated at 100.0% (2716 of 2716 strings)

Translated using Weblate (Arabic)

Currently translated at 100.0% (2711 of 2711 strings)

Translated using Weblate (Arabic)

Currently translated at 100.0% (2710 of 2710 strings)

Translated using Weblate (Arabic)

Currently translated at 100.0% (2709 of 2709 strings)

Translated using Weblate (Arabic)

Currently translated at 100.0% (2702 of 2702 strings)

Translated using Weblate (Arabic)

Currently translated at 100.0% (2700 of 2700 strings)

Translated using Weblate (Arabic)

Currently translated at 99.7% (2691 of 2698 strings)

Translated using Weblate (Arabic)

Currently translated at 99.0% (2672 of 2698 strings)

Translated using Weblate (Arabic)

Currently translated at 100.0% (2668 of 2668 strings)

Translated using Weblate (Arabic)

Currently translated at 100.0% (2664 of 2664 strings)

Translated using Weblate (Arabic)

Currently translated at 99.3% (2646 of 2664 strings)

Translated using Weblate (Arabic)

Currently translated at 100.0% (2639 of 2639 strings)

Translated using Weblate (Arabic)

Currently translated at 100.0% (2631 of 2631 strings)

Co-authored-by: Rex_sa <rex.sa@pm.me>
Translate-URL: https://hosted.weblate.org/projects/freeyourgadget/gadgetbridge/ar/
Translation: Freeyourgadget/Gadgetbridge
2024-05-01 18:33:21 +02:00
陈少举
a8dbb30139
Translated using Weblate (Chinese (Simplified))
Currently translated at 100.0% (2739 of 2739 strings)

Translated using Weblate (Chinese (Simplified))

Currently translated at 100.0% (2738 of 2738 strings)

Translated using Weblate (Chinese (Simplified))

Currently translated at 100.0% (2735 of 2735 strings)

Translated using Weblate (Chinese (Simplified))

Currently translated at 100.0% (2734 of 2734 strings)

Translated using Weblate (Chinese (Simplified))

Currently translated at 99.9% (2730 of 2731 strings)

Translated using Weblate (Chinese (Simplified))

Currently translated at 100.0% (2716 of 2716 strings)

Translated using Weblate (Chinese (Simplified))

Currently translated at 100.0% (2714 of 2714 strings)

Translated using Weblate (Chinese (Simplified))

Currently translated at 100.0% (2710 of 2710 strings)

Translated using Weblate (Chinese (Simplified))

Currently translated at 99.8% (2706 of 2709 strings)

Translated using Weblate (Chinese (Simplified))

Currently translated at 100.0% (2702 of 2702 strings)

Translated using Weblate (Chinese (Simplified))

Currently translated at 100.0% (2700 of 2700 strings)

Translated using Weblate (Chinese (Simplified))

Currently translated at 100.0% (2698 of 2698 strings)

Translated using Weblate (Chinese (Simplified))

Currently translated at 100.0% (2694 of 2694 strings)

Translated using Weblate (Chinese (Simplified))

Currently translated at 100.0% (2668 of 2668 strings)

Translated using Weblate (Chinese (Simplified))

Currently translated at 100.0% (2664 of 2664 strings)

Translated using Weblate (Chinese (Simplified))

Currently translated at 100.0% (2639 of 2639 strings)

Translated using Weblate (Chinese (Simplified))

Currently translated at 100.0% (2631 of 2631 strings)

Co-authored-by: 陈少举 <oshirisu.red@gmail.com>
Translate-URL: https://hosted.weblate.org/projects/freeyourgadget/gadgetbridge/zh_Hans/
Translation: Freeyourgadget/Gadgetbridge
2024-05-01 18:33:19 +02:00
arjan-s
59e9d01605
Translated using Weblate (Dutch)
Currently translated at 100.0% (2735 of 2735 strings)

Translated using Weblate (Dutch)

Currently translated at 100.0% (2734 of 2734 strings)

Translated using Weblate (Dutch)

Currently translated at 100.0% (2731 of 2731 strings)

Translated using Weblate (Dutch)

Currently translated at 100.0% (2710 of 2710 strings)

Translated using Weblate (Dutch)

Currently translated at 100.0% (2698 of 2698 strings)

Translated using Weblate (Dutch)

Currently translated at 100.0% (2639 of 2639 strings)

Translated using Weblate (Dutch)

Currently translated at 100.0% (2631 of 2631 strings)

Co-authored-by: arjan-s <a_gitlab@anymore.nl>
Translate-URL: https://hosted.weblate.org/projects/freeyourgadget/gadgetbridge/nl/
Translation: Freeyourgadget/Gadgetbridge
2024-05-01 18:33:17 +02:00
Mikachu
e99a7654af
Translated using Weblate (Dutch)
Currently translated at 100.0% (2631 of 2631 strings)

Co-authored-by: Mikachu <micah.sh@proton.me>
Translate-URL: https://hosted.weblate.org/projects/freeyourgadget/gadgetbridge/nl/
Translation: Freeyourgadget/Gadgetbridge
2024-05-01 18:33:16 +02:00
Oğuz Ersen
30de0cda70
Translated using Weblate (Turkish)
Currently translated at 100.0% (2739 of 2739 strings)

Translated using Weblate (Turkish)

Currently translated at 100.0% (2738 of 2738 strings)

Translated using Weblate (Turkish)

Currently translated at 100.0% (2735 of 2735 strings)

Translated using Weblate (Turkish)

Currently translated at 100.0% (2734 of 2734 strings)

Translated using Weblate (Turkish)

Currently translated at 100.0% (2733 of 2733 strings)

Translated using Weblate (Turkish)

Currently translated at 100.0% (2731 of 2731 strings)

Translated using Weblate (Turkish)

Currently translated at 100.0% (2716 of 2716 strings)

Translated using Weblate (Turkish)

Currently translated at 100.0% (2714 of 2714 strings)

Translated using Weblate (Turkish)

Currently translated at 100.0% (2711 of 2711 strings)

Translated using Weblate (Turkish)

Currently translated at 100.0% (2710 of 2710 strings)

Translated using Weblate (Turkish)

Currently translated at 100.0% (2709 of 2709 strings)

Translated using Weblate (Turkish)

Currently translated at 100.0% (2704 of 2704 strings)

Translated using Weblate (Turkish)

Currently translated at 100.0% (2702 of 2702 strings)

Translated using Weblate (Turkish)

Currently translated at 100.0% (2700 of 2700 strings)

Translated using Weblate (Turkish)

Currently translated at 100.0% (2698 of 2698 strings)

Translated using Weblate (Turkish)

Currently translated at 100.0% (2694 of 2694 strings)

Translated using Weblate (Turkish)

Currently translated at 100.0% (2668 of 2668 strings)

Translated using Weblate (Turkish)

Currently translated at 100.0% (2664 of 2664 strings)

Translated using Weblate (Turkish)

Currently translated at 100.0% (2639 of 2639 strings)

Translated using Weblate (Turkish)

Currently translated at 100.0% (2631 of 2631 strings)

Co-authored-by: Oğuz Ersen <oguz@ersen.moe>
Translate-URL: https://hosted.weblate.org/projects/freeyourgadget/gadgetbridge/tr/
Translation: Freeyourgadget/Gadgetbridge
2024-05-01 18:33:14 +02:00
gallegonovato
ccbfeb11d0
Translated using Weblate (Spanish)
Currently translated at 100.0% (2739 of 2739 strings)

Translated using Weblate (Spanish)

Currently translated at 100.0% (2735 of 2735 strings)

Translated using Weblate (Spanish)

Currently translated at 100.0% (2734 of 2734 strings)

Translated using Weblate (Spanish)

Currently translated at 100.0% (2733 of 2733 strings)

Translated using Weblate (Spanish)

Currently translated at 100.0% (2731 of 2731 strings)

Translated using Weblate (Spanish)

Currently translated at 100.0% (2714 of 2714 strings)

Translated using Weblate (Spanish)

Currently translated at 100.0% (2702 of 2702 strings)

Translated using Weblate (Spanish)

Currently translated at 100.0% (2700 of 2700 strings)

Translated using Weblate (Spanish)

Currently translated at 100.0% (2698 of 2698 strings)

Translated using Weblate (Spanish)

Currently translated at 100.0% (2668 of 2668 strings)

Translated using Weblate (Spanish)

Currently translated at 100.0% (2664 of 2664 strings)

Translated using Weblate (Spanish)

Currently translated at 100.0% (2639 of 2639 strings)

Translated using Weblate (Spanish)

Currently translated at 100.0% (2631 of 2631 strings)

Co-authored-by: gallegonovato <fran-carro@hotmail.es>
Translate-URL: https://hosted.weblate.org/projects/freeyourgadget/gadgetbridge/es/
Translation: Freeyourgadget/Gadgetbridge
2024-05-01 18:33:12 +02:00
skdubg
e6e87f9ff7
Translated using Weblate (German)
Currently translated at 100.0% (2739 of 2739 strings)

Translated using Weblate (German)

Currently translated at 100.0% (2738 of 2738 strings)

Translated using Weblate (German)

Currently translated at 100.0% (2735 of 2735 strings)

Translated using Weblate (German)

Currently translated at 100.0% (2734 of 2734 strings)

Translated using Weblate (German)

Currently translated at 100.0% (2733 of 2733 strings)

Translated using Weblate (German)

Currently translated at 100.0% (2731 of 2731 strings)

Translated using Weblate (German)

Currently translated at 100.0% (2716 of 2716 strings)

Translated using Weblate (German)

Currently translated at 100.0% (2714 of 2714 strings)

Translated using Weblate (German)

Currently translated at 100.0% (2711 of 2711 strings)

Translated using Weblate (German)

Currently translated at 100.0% (2702 of 2702 strings)

Translated using Weblate (German)

Currently translated at 99.8% (2695 of 2700 strings)

Translated using Weblate (German)

Currently translated at 99.8% (2693 of 2698 strings)

Translated using Weblate (German)

Currently translated at 99.7% (2691 of 2698 strings)

Translated using Weblate (German)

Currently translated at 99.7% (2687 of 2694 strings)

Translated using Weblate (German)

Currently translated at 99.7% (2661 of 2668 strings)

Translated using Weblate (German)

Currently translated at 99.7% (2657 of 2664 strings)

Translated using Weblate (German)

Currently translated at 99.5% (2652 of 2664 strings)

Translated using Weblate (German)

Currently translated at 100.0% (2639 of 2639 strings)

Translated using Weblate (German)

Currently translated at 100.0% (2631 of 2631 strings)

Co-authored-by: skdubg <skdubg@autistici.org>
Translate-URL: https://hosted.weblate.org/projects/freeyourgadget/gadgetbridge/de/
Translation: Freeyourgadget/Gadgetbridge
2024-05-01 18:33:10 +02:00
Martin.JM
83fd09939f [Huawei] Fix PR #3742, add workout frequency and altitude 2024-05-01 16:32:27 +00:00
Damien 'Psolyca' Gaignon
2d32822ff8
[Huawei] Add Huawei Watch Fit 2 gadget 2024-05-01 12:03:59 +02:00
José Rebelo
772ec05049 Update changelog 2024-04-30 20:57:40 +01:00
José Rebelo
18e08d13da Fix tests and linter 2024-04-30 20:43:23 +01:00
Martin.JM
1c2c1f710e [Huawei] Add support for workout calories and cycling power 2024-04-30 21:08:23 +02:00
José Rebelo
013ffe5559 Format pace as mm:ss 2024-04-29 19:50:57 +01:00
Martin.JM
bcd35b02da [Huawei] Add HR and SpO support for two watches
- Huawei Watch GT4
- Huawei Watch Ultimate
2024-04-29 10:58:24 +02:00
Gonk
b7d2808392 Added debug end call to the API 2024-04-28 23:19:24 +02:00
José Rebelo
9bef90a151 HPlus: Migrate global preferences to device-specific 2024-04-28 19:02:20 +01:00
70 changed files with 4814 additions and 881 deletions

View File

@ -2,21 +2,61 @@
#### Next release (WIP)
* Experimental support for Redmi Watch 4
* Initial support for Huawei Watch Fit 2
* Introduce new Dashboard view
* AsteroidOS: Added icons to the notifications
* Bangle.js: Add screenshot support
* Bangle.js: Add setting to disable notifications
* Bangle.js: Allow wake phone when opening notification response from watch
* Bangle.js: Fix activity intensity normalization
* Bangle.js: Fix message reply
* Fossil/Skagen Hybrids: Update device settings to new structure
* Galaxy Buds Live: Update device settings to new structure
* HPlus: Migrate global preferences to device-specific
* Huawei: Add cycling workout type
* Huawei: Add enable HeartRate and SpO2 force option
* Huawei: Add huawei account support (pair without resetting watch)
* Huawei: Add support for workout calories and cycling power
* Huawei: Ask pincode only on first connection
* Huawei: Enable sleep detection
* Huawei: File upload and watchface management
* Huawei: Fix force DND support
* Huawei: Fix long notification
* Huawei: Fix TimeZone offset calculation
* Huawei: Improve connection and reconnection
* Huawei: Improve notification icons
* Huawei: Improve workout parsing
* Huawei: Rework settings menu with sub-screens
* Huawei: Support sending GPS to band
* Huawei Watch GT4: Add HR and SpO support
* Huawei Watch Ultimate: Add HR and SpO support
* Intent API: Added debug end call
* Mi Band 6: Add menu items for NFC shortcuts
* Nothing CMF Watch Pro: Add weather support
* Nothing Earbuds: Add adjustable delay for auto-pick-up of calls
* Nothing Earbuds: Add option to auto-reply to incoming phone calls
* Nothing Earbuds: Add option to read aloud incoming notifications
* Xiaomi Smart Band 8 Active: Fix discovery
* Xiaomi: Fix some crashes
* Xiaomi: Improve reconnection
* Xiaomi: Improve weather support, add multiple locations
* Set navbar color to match theme
* Xiaomi: Sync calendar event reminders
* Zepp OS: Add support for Sleep as Android
* Zepp OS: Sync calendar event reminders
* Add Armenian and Serbian transliterators
* Add GENERIC_PHONE and GENERIC_CALENDAR NotificationType handling
* Add support for scannable-only devices
* Fix crash when connecting on some phones
* Fix crash when enabling bluetooth
* Fix receiving shared gpx files
* Format pace as mm:ss
* Set navbar color to match theme
* Simplify pairing of bonded and companion devices
* Prevent text cutoff on all checkbox preferences
* Recognize "Delta Chat" as generic chat
* Remove deprecated general auto-reconnect preference
* Refactor location service
* Fix text cutoff on all checkbox preferences
#### 0.80.0
* Initial support for Amazfit Bip 3

View File

@ -45,7 +45,7 @@ public class GBDaoGenerator {
public static void main(String[] args) throws Exception {
final Schema schema = new Schema(71, MAIN_PACKAGE + ".entities");
final Schema schema = new Schema(73, MAIN_PACKAGE + ".entities");
Entity userAttributes = addUserAttributes(schema);
Entity user = addUserInfo(schema, userAttributes);
@ -1167,6 +1167,12 @@ public class GBDaoGenerator {
workoutDataSample.addByteArrayProperty("dataErrorHex");
workoutDataSample.addShortProperty("calories").notNull();
workoutDataSample.addShortProperty("cyclingPower").notNull();
workoutDataSample.addShortProperty("frequency").notNull();
workoutDataSample.addIntProperty("altitude");
return workoutDataSample;
}

View File

@ -178,10 +178,6 @@
android:name=".devices.pebble.PebbleSettingsActivity"
android:label="@string/pref_title_pebble_settings"
android:parentActivityName=".activities.SettingsActivity" />
<activity
android:name=".devices.hplus.HPlusSettingsActivity"
android:label="@string/preferences_hplus_settings"
android:parentActivityName=".activities.SettingsActivity" />
<activity
android:name=".devices.zetime.ZeTimePreferenceActivity"
android:label="@string/zetime_title_settings"

View File

@ -124,7 +124,7 @@ public class GBApplication extends Application {
private static SharedPreferences sharedPrefs;
private static final String PREFS_VERSION = "shared_preferences_version";
//if preferences have to be migrated, increment the following and add the migration logic in migratePrefs below; see http://stackoverflow.com/questions/16397848/how-can-i-migrate-android-preferences-with-a-new-version
private static final int CURRENT_PREFS_VERSION = 28;
private static final int CURRENT_PREFS_VERSION = 29;
private static final LimitedQueue<Integer, String> mIDSenderLookup = new LimitedQueue<>(16);
private static Prefs prefs;
@ -1446,6 +1446,28 @@ public class GBApplication extends Application {
}
}
if (oldVersion < 29) {
// Migrate HPlus preferences to device-specific
try (DBHandler db = acquireDB()) {
final DaoSession daoSession = db.getDaoSession();
final List<Device> activeDevices = DBHelper.getActiveDevices(daoSession);
for (Device dbDevice : activeDevices) {
final DeviceType deviceType = DeviceType.fromName(dbDevice.getTypeName());
if (deviceType == DeviceType.HPLUS) {
final SharedPreferences deviceSharedPrefs = GBApplication.getDeviceSpecificSharedPrefs(dbDevice.getIdentifier());
final SharedPreferences.Editor deviceSharedPrefsEdit = deviceSharedPrefs.edit();
deviceSharedPrefsEdit.putString("hplus_screentime", sharedPrefs.getString("hplus_screentime", "5"));
deviceSharedPrefsEdit.putBoolean("hplus_alldayhr", sharedPrefs.getBoolean("hplus_alldayhr", true));
deviceSharedPrefsEdit.apply();
}
}
} catch (Exception e) {
Log.w(TAG, "error acquiring DB lock");
}
}
editor.putString(PREFS_VERSION, Integer.toString(CURRENT_PREFS_VERSION));
editor.apply();
}
@ -1457,6 +1479,10 @@ public class GBApplication extends Application {
return context.getSharedPreferences("devicesettings_" + deviceIdentifier, Context.MODE_PRIVATE);
}
public static Prefs getDevicePrefs(final String deviceIdentifier) {
return new Prefs(getDeviceSpecificSharedPrefs(deviceIdentifier));
}
public static void deleteDeviceSpecificSharedPrefs(String deviceIdentifier) {
if (deviceIdentifier == null || deviceIdentifier.isEmpty()) {
return;

View File

@ -71,6 +71,7 @@ import java.util.Comparator;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;
import java.util.concurrent.TimeUnit;
import nodomain.freeyourgadget.gadgetbridge.GBApplication;
@ -518,6 +519,14 @@ public class ActivitySummaryDetail extends AbstractGBActivity {
if (unit.equals("seconds") && !show_raw_data) { //rather then plain seconds, show formatted duration
value_field.setText(DateTimeUtils.formatDurationHoursMinutes((long) value, TimeUnit.SECONDS));
} else if (unit.equals("minutes_km") || unit.equals("minutes_mi")) {
// Format pace
value_field.setText(String.format(
Locale.getDefault(),
"%d:%02d %s",
(int) Math.floor(value), (int) Math.round(60 * (value - (int) Math.floor(value))),
getStringResourceByName(unit)
));
} else {
value_field.setText(String.format("%s %s", df.format(value), getStringResourceByName(unit)));
}

View File

@ -1184,7 +1184,10 @@ public class DebugActivity extends AbstractGBActivity {
for (DeviceType deviceType : DeviceType.values()) {
DeviceCoordinator coordinator = deviceType.getDeviceCoordinator();
int icon = coordinator.getDefaultIconResource();
String name = app.getString(coordinator.getDeviceNameResource()) + " (" + coordinator.getManufacturer() + ")";
String name = app.getString(coordinator.getDeviceNameResource());
if (!name.startsWith(coordinator.getManufacturer())) {
name += " (" + coordinator.getManufacturer() + ")";
}
long deviceId = deviceType.ordinal();
newMap.put(name, new Pair(deviceId, icon));
}

View File

@ -46,6 +46,7 @@ import java.util.Objects;
import nodomain.freeyourgadget.gadgetbridge.GBApplication;
import nodomain.freeyourgadget.gadgetbridge.R;
import nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSettingsPreferenceConst;
import nodomain.freeyourgadget.gadgetbridge.activities.discovery.DiscoveryActivityV2;
import nodomain.freeyourgadget.gadgetbridge.adapter.GBDeviceAdapterv2;
import nodomain.freeyourgadget.gadgetbridge.database.DBAccess;
@ -233,7 +234,8 @@ public class DevicesFragment extends Fragment {
protected void doInBackground(DBHandler db) {
for (GBDevice gbDevice : deviceList) {
final DeviceCoordinator coordinator = gbDevice.getDeviceCoordinator();
if (coordinator.supportsActivityTracking()) {
boolean showActivityCard = GBApplication.getDevicePrefs(gbDevice.getAddress()).getBoolean(DeviceSettingsPreferenceConst.PREFS_ACTIVITY_IN_DEVICE_CARD, true);
if (coordinator.supportsActivityTracking() && showActivityCard) {
long[] stepsAndSleepData = getSteps(gbDevice, db);
deviceActivityHashMap.put(gbDevice.getAddress(), stepsAndSleepData);
}

View File

@ -66,7 +66,6 @@ import nodomain.freeyourgadget.gadgetbridge.R;
import nodomain.freeyourgadget.gadgetbridge.activities.charts.ChartsPreferencesActivity;
import nodomain.freeyourgadget.gadgetbridge.activities.discovery.DiscoveryPairingPreferenceActivity;
import nodomain.freeyourgadget.gadgetbridge.database.PeriodicExporter;
import nodomain.freeyourgadget.gadgetbridge.devices.hplus.HPlusSettingsActivity;
import nodomain.freeyourgadget.gadgetbridge.devices.miband.MiBandPreferencesActivity;
import nodomain.freeyourgadget.gadgetbridge.devices.pebble.PebbleSettingsActivity;
import nodomain.freeyourgadget.gadgetbridge.devices.qhybrid.ConfigActivity;
@ -156,15 +155,6 @@ public class SettingsActivity extends AbstractSettingsActivityV2 {
});
}
pref = findPreference("pref_key_hplus");
if (pref != null) {
pref.setOnPreferenceClickListener(preference -> {
Intent enableIntent = new Intent(requireContext(), HPlusSettingsActivity.class);
startActivity(enableIntent);
return true;
});
}
pref = findPreference("pref_key_zetime");
if (pref != null) {
pref.setOnPreferenceClickListener(preference -> {

View File

@ -395,7 +395,7 @@ public class DashboardTodayWidget extends AbstractDashboardWidget {
if (firstTimestamp == 0) firstTimestamp = sample.getTimestamp();
if (lastTimestamp == 0) lastTimestamp = sample.getTimestamp();
if ((sample.getHeartRate() < 10 || sample.getTimestamp() > lastTimestamp + dashboardData.hrIntervalSecs) && firstTimestamp != lastTimestamp) {
LOG.info("Registered worn session from " + firstTimestamp + " to " + lastTimestamp);
LOG.debug("Registered worn session from {} to {}", firstTimestamp, lastTimestamp);
addActivity(firstTimestamp, lastTimestamp, ActivityKind.TYPE_NOT_MEASURED);
if (sample.getHeartRate() < 10) {
firstTimestamp = 0;
@ -409,7 +409,7 @@ public class DashboardTodayWidget extends AbstractDashboardWidget {
lastTimestamp = sample.getTimestamp();
}
if (firstTimestamp != lastTimestamp) {
LOG.info("Registered worn session from " + firstTimestamp + " to " + lastTimestamp);
LOG.debug("Registered worn session from {} to {}", firstTimestamp, lastTimestamp);
addActivity(firstTimestamp, lastTimestamp, ActivityKind.TYPE_NOT_MEASURED);
}
}

View File

@ -343,6 +343,25 @@ public class DeviceSettingsPreferenceConst {
public static final String PREF_SONY_PROTOCOL_VERSION = "pref_protocol_version";
public static final String PREF_SONY_ACTUAL_PROTOCOL_VERSION = "pref_actual_protocol_version";
public static final String PREF_SONY_AMBIENT_SOUND_CONTROL = "pref_sony_ambient_sound_control";
public static final String PREF_SOUNDCORE_AMBIENT_SOUND_CONTROL = "pref_soundcore_ambient_sound_control";
public static final String PREF_SOUNDCORE_ADAPTIVE_NOISE_CANCELLING = "pref_adaptive_noise_cancelling";
public static final String PREF_SOUNDCORE_WIND_NOISE_REDUCTION= "pref_soundcore_wind_noise_reduction";
public static final String PREF_SOUNDCORE_TRANSPARENCY_VOCAL_MODE = "pref_soundcore_transparency_vocal_mode";
public static final String PREF_SOUNDCORE_WEARING_DETECTION = "pref_soundcore_wearing_detection";
public static final String PREF_SOUNDCORE_WEARING_TONE = "pref_soundcore_wearing_tone";
public static final String PREF_SOUNDCORE_TOUCH_TONE = "pref_soundcore_touch_tone";
public static final String PREF_SOUNDCORE_CONTROL_SINGLE_TAP_DISABLED = "pref_soundcore_control_single_tap_disabled";
public static final String PREF_SOUNDCORE_CONTROL_DOUBLE_TAP_DISABLED = "pref_soundcore_control_double_tap_disabled";
public static final String PREF_SOUNDCORE_CONTROL_TRIPLE_TAP_DISABLED = "pref_soundcore_control_triple_tap_disabled";
public static final String PREF_SOUNDCORE_CONTROL_LONG_PRESS_DISABLED = "pref_soundcore_control_long_press_disabled";
public static final String PREF_SOUNDCORE_CONTROL_SINGLE_TAP_ACTION_LEFT = "pref_soundcore_control_single_tap_action_left";
public static final String PREF_SOUNDCORE_CONTROL_DOUBLE_TAP_ACTION_LEFT = "pref_soundcore_control_double_tap_action_left";
public static final String PREF_SOUNDCORE_CONTROL_TRIPLE_TAP_ACTION_LEFT = "pref_soundcore_control_triple_tap_action_left";
public static final String PREF_SOUNDCORE_CONTROL_LONG_PRESS_ACTION_LEFT = "pref_soundcore_control_long_press_action_left";
public static final String PREF_SOUNDCORE_CONTROL_SINGLE_TAP_ACTION_RIGHT = "pref_soundcore_control_single_tap_action_right";
public static final String PREF_SOUNDCORE_CONTROL_DOUBLE_TAP_ACTION_RIGHT = "pref_soundcore_control_double_tap_action_right";
public static final String PREF_SOUNDCORE_CONTROL_TRIPLE_TAP_ACTION_RIGHT = "pref_soundcore_control_triple_tap_action_right";
public static final String PREF_SOUNDCORE_CONTROL_LONG_PRESS_ACTION_RIGHT = "pref_soundcore_control_long_press_action_right";
public static final String PREF_SONY_AMBIENT_SOUND_CONTROL_BUTTON_MODE = "pref_sony_ambient_sound_control_button_mode";
public static final String PREF_SONY_FOCUS_VOICE = "pref_sony_focus_voice";
public static final String PREF_SONY_AMBIENT_SOUND_LEVEL = "pref_sony_ambient_sound_level";

View File

@ -563,6 +563,27 @@ public class DeviceSpecificSettingsFragment extends AbstractPreferenceFragment i
addPreferenceHandlerFor(PREF_SONY_CONNECT_TWO_DEVICES);
addPreferenceHandlerFor(PREF_SONY_ADAPTIVE_VOLUME_CONTROL);
addPreferenceHandlerFor(PREF_SONY_WIDE_AREA_TAP);
addPreferenceHandlerFor(PREF_SOUNDCORE_AMBIENT_SOUND_CONTROL);
addPreferenceHandlerFor(PREF_SOUNDCORE_WIND_NOISE_REDUCTION);
addPreferenceHandlerFor(PREF_SOUNDCORE_TRANSPARENCY_VOCAL_MODE);
addPreferenceHandlerFor(PREF_SOUNDCORE_ADAPTIVE_NOISE_CANCELLING);
addPreferenceHandlerFor(PREF_SOUNDCORE_TOUCH_TONE);
addPreferenceHandlerFor(PREF_SOUNDCORE_WEARING_TONE);
addPreferenceHandlerFor(PREF_SOUNDCORE_WEARING_DETECTION);
addPreferenceHandlerFor(PREF_SOUNDCORE_CONTROL_SINGLE_TAP_DISABLED);
addPreferenceHandlerFor(PREF_SOUNDCORE_CONTROL_DOUBLE_TAP_DISABLED);
addPreferenceHandlerFor(PREF_SOUNDCORE_CONTROL_TRIPLE_TAP_DISABLED);
addPreferenceHandlerFor(PREF_SOUNDCORE_CONTROL_LONG_PRESS_DISABLED);
addPreferenceHandlerFor(PREF_SOUNDCORE_CONTROL_SINGLE_TAP_ACTION_LEFT);
addPreferenceHandlerFor(PREF_SOUNDCORE_CONTROL_SINGLE_TAP_ACTION_RIGHT);
addPreferenceHandlerFor(PREF_SOUNDCORE_CONTROL_DOUBLE_TAP_ACTION_LEFT);
addPreferenceHandlerFor(PREF_SOUNDCORE_CONTROL_DOUBLE_TAP_ACTION_RIGHT);
addPreferenceHandlerFor(PREF_SOUNDCORE_CONTROL_TRIPLE_TAP_ACTION_LEFT);
addPreferenceHandlerFor(PREF_SOUNDCORE_CONTROL_TRIPLE_TAP_ACTION_RIGHT);
addPreferenceHandlerFor(PREF_SOUNDCORE_CONTROL_LONG_PRESS_ACTION_LEFT);
addPreferenceHandlerFor(PREF_SOUNDCORE_CONTROL_LONG_PRESS_ACTION_RIGHT);
addPreferenceHandlerFor(PREF_FEMOMETER_MEASUREMENT_MODE);
addPreferenceHandlerFor(PREF_QC35_NOISE_CANCELLING_LEVEL);
@ -922,6 +943,7 @@ public class DeviceSpecificSettingsFragment extends AbstractPreferenceFragment i
setInputTypeFor(DeviceSettingsPreferenceConst.PREF_DEVICE_GPS_UPDATE_INTERVAL, InputType.TYPE_CLASS_NUMBER);
setInputTypeFor(DeviceSettingsPreferenceConst.PREF_BANGLEJS_TEXT_BITMAP_SIZE, InputType.TYPE_CLASS_NUMBER);
setInputTypeFor(DeviceSettingsPreferenceConst.PREF_AUTO_REPLY_INCOMING_CALL_DELAY, InputType.TYPE_CLASS_NUMBER);
setInputTypeFor("hplus_screentime", InputType.TYPE_CLASS_NUMBER);
new PasswordCapabilityImpl().registerPreferences(getContext(), coordinator.getPasswordCapability(), this);
new HeartRateCapability().registerPreferences(getContext(), coordinator.getHeartRateMeasurementIntervals(), this);

View File

@ -34,6 +34,7 @@ public enum DeviceSpecificSettingsScreen {
DATE_TIME("pref_screen_date_time", R.xml.devicesettings_root_date_time),
WORKOUT("pref_screen_workout", R.xml.devicesettings_root_workout),
HEALTH("pref_screen_health", R.xml.devicesettings_root_health),
TOUCH_OPTIONS("pref_screen_touch_options", R.xml.devicesettings_root_touch_options),
;
private final String key;

View File

@ -1316,6 +1316,13 @@ public class GBDeviceAdapterv2 extends ListAdapter<GBDevice, GBDeviceAdapterv2.V
}
private void setActivityCard(ViewHolder holder, final GBDevice device, long[] dailyTotals) {
boolean showActivityCard = GBApplication.getDeviceSpecificSharedPrefs(device.getAddress()).getBoolean(DeviceSettingsPreferenceConst.PREFS_ACTIVITY_IN_DEVICE_CARD, true);
holder.cardViewActivityCardLayout.setVisibility(showActivityCard ? View.VISIBLE : View.GONE);
if (!showActivityCard) {
return;
}
int steps = (int) dailyTotals[0];
int sleep = (int) dailyTotals[1];
ActivityUser activityUser = new ActivityUser();
@ -1336,8 +1343,6 @@ public class GBDeviceAdapterv2 extends ListAdapter<GBDevice, GBDeviceAdapterv2.V
setUpChart(holder.SleepTimeChart);
setChartsData(holder.SleepTimeChart, sleep, sleepGoalMinutes, context.getString(R.string.prefs_activity_in_device_card_sleep_title), String.format("%1s", getHM(sleep)), context);
boolean showActivityCard = GBApplication.getDeviceSpecificSharedPrefs(device.getAddress()).getBoolean(DeviceSettingsPreferenceConst.PREFS_ACTIVITY_IN_DEVICE_CARD, true);
holder.cardViewActivityCardLayout.setVisibility(showActivityCard ? View.VISIBLE : View.GONE);
boolean showActivitySteps = GBApplication.getDeviceSpecificSharedPrefs(device.getAddress()).getBoolean(DeviceSettingsPreferenceConst.PREFS_ACTIVITY_IN_DEVICE_CARD_STEPS, true);
boolean showActivitySleep = GBApplication.getDeviceSpecificSharedPrefs(device.getAddress()).getBoolean(DeviceSettingsPreferenceConst.PREFS_ACTIVITY_IN_DEVICE_CARD_SLEEP, true);

View File

@ -0,0 +1,43 @@
/* Copyright (C) 2024 Martin.JM
This file is part of Gadgetbridge.
Gadgetbridge is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published
by the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Gadgetbridge is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>. */
package nodomain.freeyourgadget.gadgetbridge.database.schema;
import android.database.sqlite.SQLiteDatabase;
import nodomain.freeyourgadget.gadgetbridge.database.DBHelper;
import nodomain.freeyourgadget.gadgetbridge.database.DBUpdateScript;
import nodomain.freeyourgadget.gadgetbridge.entities.HuaweiWorkoutDataSampleDao;
public class GadgetbridgeUpdate_72 implements DBUpdateScript {
@Override
public void upgradeSchema(final SQLiteDatabase db) {
if (!DBHelper.existsColumn(HuaweiWorkoutDataSampleDao.TABLENAME, HuaweiWorkoutDataSampleDao.Properties.Calories.columnName, db)) {
final String statement = "ALTER TABLE " + HuaweiWorkoutDataSampleDao.TABLENAME + " ADD COLUMN \""
+ HuaweiWorkoutDataSampleDao.Properties.Calories.columnName + "\" INTEGER NOT NULL DEFAULT -1";
db.execSQL(statement);
}
if (!DBHelper.existsColumn(HuaweiWorkoutDataSampleDao.TABLENAME, HuaweiWorkoutDataSampleDao.Properties.CyclingPower.columnName, db)) {
final String statement = "ALTER TABLE " + HuaweiWorkoutDataSampleDao.TABLENAME + " ADD COLUMN \""
+ HuaweiWorkoutDataSampleDao.Properties.CyclingPower.columnName + "\" INTEGER NOT NULL DEFAULT -1";
db.execSQL(statement);
}
}
@Override
public void downgradeSchema(final SQLiteDatabase db) {
}
}

View File

@ -0,0 +1,43 @@
/* Copyright (C) 2024 Martin.JM
This file is part of Gadgetbridge.
Gadgetbridge is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published
by the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Gadgetbridge is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>. */
package nodomain.freeyourgadget.gadgetbridge.database.schema;
import android.database.sqlite.SQLiteDatabase;
import nodomain.freeyourgadget.gadgetbridge.database.DBHelper;
import nodomain.freeyourgadget.gadgetbridge.database.DBUpdateScript;
import nodomain.freeyourgadget.gadgetbridge.entities.HuaweiWorkoutDataSampleDao;
public class GadgetbridgeUpdate_73 implements DBUpdateScript {
@Override
public void upgradeSchema(final SQLiteDatabase db) {
if (!DBHelper.existsColumn(HuaweiWorkoutDataSampleDao.TABLENAME, HuaweiWorkoutDataSampleDao.Properties.Frequency.columnName, db)) {
final String statement = "ALTER TABLE " + HuaweiWorkoutDataSampleDao.TABLENAME + " ADD COLUMN \""
+ HuaweiWorkoutDataSampleDao.Properties.Frequency.columnName + "\" INTEGER NOT NULL DEFAULT -1";
db.execSQL(statement);
}
if (!DBHelper.existsColumn(HuaweiWorkoutDataSampleDao.TABLENAME, HuaweiWorkoutDataSampleDao.Properties.Altitude.columnName, db)) {
final String statement = "ALTER TABLE " + HuaweiWorkoutDataSampleDao.TABLENAME + " ADD COLUMN \""
+ HuaweiWorkoutDataSampleDao.Properties.Altitude.columnName + "\" INTEGER DEFAULT NULL";
db.execSQL(statement);
}
}
@Override
public void downgradeSchema(final SQLiteDatabase db) {
}
}

View File

@ -100,6 +100,25 @@ public abstract class AbstractTimeSampleProvider<T extends AbstractTimeSample> i
return samples.get(0);
}
public T getLastSampleBefore(final long timestampTo) {
final Device dbDevice = DBHelper.findDevice(getDevice(), getSession());
if (dbDevice == null) {
// no device, no sample
return null;
}
final Property deviceIdSampleProp = getDeviceIdentifierSampleProperty();
final Property timestampSampleProp = getTimestampSampleProperty();
final List<T> samples = getSampleDao().queryBuilder()
.where(deviceIdSampleProp.eq(dbDevice.getId()),
timestampSampleProp.le(timestampTo))
.orderDesc(getTimestampSampleProperty())
.limit(1)
.list();
return !samples.isEmpty() ? samples.get(0) : null;
}
@Nullable
@Override
public T getFirstSample() {

View File

@ -23,14 +23,13 @@ import java.util.regex.Pattern;
import nodomain.freeyourgadget.gadgetbridge.R;
import nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSpecificSettingsCustomizer;
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
import nodomain.freeyourgadget.gadgetbridge.impl.GBDeviceCandidate;
import nodomain.freeyourgadget.gadgetbridge.model.BatteryConfig;
import nodomain.freeyourgadget.gadgetbridge.model.DeviceType;
public class GalaxyBuds2DeviceCoordinator extends GalaxyBudsGenericCoordinator {
@Override
protected Pattern getSupportedDeviceName() {
return Pattern.compile("Galaxy Buds2 \\(.*");
// Some devices are just called "Buds2", others "Galaxy Buds2 (..."
return Pattern.compile("(Galaxy )?Buds2( \\(.*)?");
}
@Override

View File

@ -18,11 +18,8 @@
along with this program. If not, see <https://www.gnu.org/licenses/>. */
package nodomain.freeyourgadget.gadgetbridge.devices.hplus;
import android.app.Activity;
import android.bluetooth.le.ScanFilter;
import android.content.Context;
import android.content.SharedPreferences;
import android.net.Uri;
import android.os.ParcelUuid;
import org.slf4j.Logger;
@ -42,16 +39,13 @@ import nodomain.freeyourgadget.gadgetbridge.R;
import nodomain.freeyourgadget.gadgetbridge.activities.SettingsActivity;
import nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSettingsPreferenceConst;
import nodomain.freeyourgadget.gadgetbridge.devices.AbstractBLEDeviceCoordinator;
import nodomain.freeyourgadget.gadgetbridge.devices.InstallHandler;
import nodomain.freeyourgadget.gadgetbridge.devices.SampleProvider;
import nodomain.freeyourgadget.gadgetbridge.entities.DaoSession;
import nodomain.freeyourgadget.gadgetbridge.entities.Device;
import nodomain.freeyourgadget.gadgetbridge.entities.HPlusHealthActivitySampleDao;
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
import nodomain.freeyourgadget.gadgetbridge.impl.GBDeviceCandidate;
import nodomain.freeyourgadget.gadgetbridge.model.ActivitySample;
import nodomain.freeyourgadget.gadgetbridge.model.ActivityUser;
import nodomain.freeyourgadget.gadgetbridge.model.DeviceType;
import nodomain.freeyourgadget.gadgetbridge.service.DeviceSupport;
import nodomain.freeyourgadget.gadgetbridge.service.devices.hplus.HPlusSupport;
import nodomain.freeyourgadget.gadgetbridge.util.GBPrefs;
@ -81,36 +75,16 @@ public class HPlusCoordinator extends AbstractBLEDeviceCoordinator {
return BONDING_STYLE_NONE;
}
@Override
public boolean supportsCalendarEvents() {
return false;
}
@Override
public boolean supportsRealtimeData() {
return true;
}
@Override
public boolean supportsWeather() {
return false;
}
@Override
public boolean supportsFindDevice() {
return true;
}
@Override
public Class<? extends Activity> getPairingActivity() {
return null;
}
@Override
public InstallHandler findInstallHandler(Uri uri, Context context) {
return null;
}
@Override
public boolean supportsActivityDataFetching() {
return true;
@ -126,11 +100,6 @@ public class HPlusCoordinator extends AbstractBLEDeviceCoordinator {
return new HPlusHealthSampleProvider(device, session);
}
@Override
public boolean supportsScreenshots(final GBDevice device) {
return false;
}
@Override
public int getAlarmSlotCount(GBDevice device) {
return 3; // FIXME - check the real value
@ -146,16 +115,6 @@ public class HPlusCoordinator extends AbstractBLEDeviceCoordinator {
return "Zeblaze";
}
@Override
public boolean supportsAppsManagement(final GBDevice device) {
return false;
}
@Override
public Class<? extends Activity> getAppsManagementActivity() {
return null;
}
@Override
protected void deleteDevice(@NonNull GBDevice gbDevice, @NonNull Device device, @NonNull DaoSession session) throws GBException {
Long deviceId = device.getId();
@ -236,11 +195,11 @@ public class HPlusCoordinator extends AbstractBLEDeviceCoordinator {
}
public static byte getScreenTime(String address) {
return (byte) (prefs.getInt(HPlusConstants.PREF_HPLUS_SCREENTIME, 5) & 0xFF);
return (byte) (GBApplication.getDevicePrefs(address).getInt(HPlusConstants.PREF_HPLUS_SCREENTIME, 5) & 0xFF);
}
public static byte getAllDayHR(String address) {
boolean value = (prefs.getBoolean(HPlusConstants.PREF_HPLUS_ALLDAYHR, true));
boolean value = (GBApplication.getDevicePrefs(address).getBoolean(HPlusConstants.PREF_HPLUS_ALLDAYHR, true));
if (value) {
return HPlusConstants.ARG_HEARTRATE_ALLDAY_ON;
@ -310,6 +269,7 @@ public class HPlusCoordinator extends AbstractBLEDeviceCoordinator {
return new int[]{
//R.xml.devicesettings_wearlocation, // disabled, since it is never used in code
R.xml.devicesettings_timeformat,
R.xml.devicesettings_hplus,
R.xml.devicesettings_transliteration
};
}

View File

@ -1,49 +0,0 @@
/* Copyright (C) 2023-2024 José Rebelo
This file is part of Gadgetbridge.
Gadgetbridge is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published
by the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Gadgetbridge is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>. */
package nodomain.freeyourgadget.gadgetbridge.devices.hplus;
import android.os.Bundle;
import android.text.InputType;
import androidx.preference.PreferenceFragmentCompat;
import nodomain.freeyourgadget.gadgetbridge.R;
import nodomain.freeyourgadget.gadgetbridge.activities.AbstractPreferenceFragment;
import nodomain.freeyourgadget.gadgetbridge.activities.AbstractSettingsActivityV2;
public class HPlusSettingsActivity extends AbstractSettingsActivityV2 {
@Override
protected String fragmentTag() {
return HPlusSettingsFragment.FRAGMENT_TAG;
}
@Override
protected PreferenceFragmentCompat newFragment() {
return new HPlusSettingsFragment();
}
public static class HPlusSettingsFragment extends AbstractPreferenceFragment {
static final String FRAGMENT_TAG = "HPLUS_SETTINGS_FRAGMENT";
@Override
public void onCreatePreferences(final Bundle savedInstanceState, final String rootKey) {
setPreferencesFromResource(R.xml.hplus_preferences, rootKey);
setInputTypeFor("hplus_screentime", InputType.TYPE_CLASS_NUMBER);
}
}
}

View File

@ -66,6 +66,7 @@ public final class HuaweiConstants {
public static final String HU_WATCHGT3PRO_NAME = "huawei watch gt 3 pro-";
public static final String HU_WATCHGT4_NAME = "huawei watch gt 4-";
public static final String HU_WATCHFIT_NAME = "huawei watch fit-";
public static final String HU_WATCHFIT2_NAME = "huawei watch fit 2-";
public static final String HU_WATCHULTIMATE_NAME = "huawei watch ultimate-";
public static final String PREF_HUAWEI_ADDRESS = "huawei_address";

View File

@ -317,6 +317,10 @@ public class HuaweiCoordinator {
public boolean supportsMotionGoal() {
return supportsCommandForService(0x07, 0x01);
}
public boolean supportsUserInfo() {
return supportsCommandForService(0x07, 0x02);
}
public boolean supportsInactivityWarnings() {
return supportsCommandForService(0x07, 0x06);

View File

@ -0,0 +1,51 @@
/* Copyright (C) 2024 Damien Gaignon
This file is part of Gadgetbridge.
Gadgetbridge is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published
by the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Gadgetbridge is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>. */
package nodomain.freeyourgadget.gadgetbridge.devices.huawei.huaweiwatchfit2;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.regex.Pattern;
import nodomain.freeyourgadget.gadgetbridge.R;
import nodomain.freeyourgadget.gadgetbridge.devices.huawei.HuaweiBRCoordinator;
import nodomain.freeyourgadget.gadgetbridge.devices.huawei.HuaweiConstants;
import nodomain.freeyourgadget.gadgetbridge.model.DeviceType;
public class HuaweiWatchFit2Coordinator extends HuaweiBRCoordinator {
private static final Logger LOG = LoggerFactory.getLogger(HuaweiWatchFit2Coordinator.class);
public HuaweiWatchFit2Coordinator() {
super();
getHuaweiCoordinator().setTransactionCrypted(true);
}
@Override
public DeviceType getDeviceType() {
return DeviceType.HUAWEIWATCHFIT2;
}
@Override
protected Pattern getSupportedDeviceName() {
return Pattern.compile("(" + HuaweiConstants.HU_WATCHFIT2_NAME + ").*", Pattern.CASE_INSENSITIVE);
}
@Override
public int getDeviceNameResource() {
return R.string.devicetype_huawei_watchfit2;
}
}

View File

@ -22,11 +22,15 @@ import org.slf4j.LoggerFactory;
import java.util.regex.Pattern;
import nodomain.freeyourgadget.gadgetbridge.R;
import nodomain.freeyourgadget.gadgetbridge.devices.TimeSampleProvider;
import nodomain.freeyourgadget.gadgetbridge.devices.huawei.HuaweiBRCoordinator;
import nodomain.freeyourgadget.gadgetbridge.devices.huawei.HuaweiConstants;
import nodomain.freeyourgadget.gadgetbridge.devices.huawei.HuaweiSpo2SampleProvider;
import nodomain.freeyourgadget.gadgetbridge.entities.DaoSession;
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
import nodomain.freeyourgadget.gadgetbridge.impl.GBDeviceCandidate;
import nodomain.freeyourgadget.gadgetbridge.model.DeviceType;
import nodomain.freeyourgadget.gadgetbridge.model.Spo2Sample;
public class HuaweiWatchGT4Coordinator extends HuaweiBRCoordinator {
private static final Logger LOG = LoggerFactory.getLogger(HuaweiWatchGT4Coordinator.class);
@ -46,6 +50,21 @@ public class HuaweiWatchGT4Coordinator extends HuaweiBRCoordinator {
return Pattern.compile("(" + HuaweiConstants.HU_WATCHGT4_NAME + ").*", Pattern.CASE_INSENSITIVE);
}
@Override
public boolean supportsHeartRateMeasurement(GBDevice device) {
return true;
}
@Override
public boolean supportsSpo2() {
return true;
}
@Override
public TimeSampleProvider<? extends Spo2Sample> getSpo2SampleProvider(GBDevice device, DaoSession session) {
return new HuaweiSpo2SampleProvider(device, session);
}
@Override
public int getDeviceNameResource() {
return R.string.devicetype_huawei_watchgt4;

View File

@ -22,10 +22,14 @@ import org.slf4j.LoggerFactory;
import java.util.regex.Pattern;
import nodomain.freeyourgadget.gadgetbridge.R;
import nodomain.freeyourgadget.gadgetbridge.devices.TimeSampleProvider;
import nodomain.freeyourgadget.gadgetbridge.devices.huawei.HuaweiBRCoordinator;
import nodomain.freeyourgadget.gadgetbridge.devices.huawei.HuaweiConstants;
import nodomain.freeyourgadget.gadgetbridge.devices.huawei.HuaweiSpo2SampleProvider;
import nodomain.freeyourgadget.gadgetbridge.entities.DaoSession;
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
import nodomain.freeyourgadget.gadgetbridge.model.DeviceType;
import nodomain.freeyourgadget.gadgetbridge.model.Spo2Sample;
public class HuaweiWatchUltimateCoordinator extends HuaweiBRCoordinator {
private static final Logger LOG = LoggerFactory.getLogger(HuaweiWatchUltimateCoordinator.class);
@ -45,6 +49,21 @@ public class HuaweiWatchUltimateCoordinator extends HuaweiBRCoordinator {
return Pattern.compile("(" + HuaweiConstants.HU_WATCHULTIMATE_NAME + ").*", Pattern.CASE_INSENSITIVE);
}
@Override
public boolean supportsHeartRateMeasurement(GBDevice device) {
return true;
}
@Override
public boolean supportsSpo2() {
return true;
}
@Override
public TimeSampleProvider<? extends Spo2Sample> getSpo2SampleProvider(GBDevice device, DaoSession session) {
return new HuaweiSpo2SampleProvider(device, session);
}
@Override
public int getDeviceNameResource() {
return R.string.devicetype_huawei_watchultimate;

View File

@ -1,4 +1,4 @@
/* Copyright (C) 2024 Damien Gaignon, Martin.JM
/* Copyright (C) 2024 Damien Gaignon, Martin.JM, Vitalii Tomin
This file is part of Gadgetbridge.
@ -71,6 +71,34 @@ public class FitnessData {
}
}
}
public static class UserInfo {
public static final byte id = 0x02;
public static class Request extends HuaweiPacket {
public Request(ParamsProvider paramsProvider,
int height,
int weight,
int age,
int birthdayEncoded,
byte gender) {
super(paramsProvider);
this.serviceId = FitnessData.id;
this.commandId = id;
byte bmi1 = (byte)Math.round(0.42f * height);
byte bmi2 = (byte)Math.round(0.83f * height);
this.tlv = new HuaweiTLV()
.put(0x01, (byte)height)
.put(0x02, (byte)weight)
.put(0x03, (byte)age)
.put(0x04, birthdayEncoded)
.put(0x05, gender)
.put(0x06, bmi1)
.put(0x07, bmi2);
}
}
}
public static class MessageCount {
public static final byte sleepId = 0x0C;
public static final byte stepId = 0x0A;

View File

@ -239,12 +239,17 @@ public class Workout {
public byte swolf = -1;
public short strokeRate = -1;
public short calories = -1;
public short cyclingPower = -1;
public short frequency = -1;
public Integer altitude = null;
public int timestamp = -1; // Calculated timestamp for this data point
@Override
public String toString() {
return "Data{" +
"unknownData=" + unknownData +
"unknownData=" + Arrays.toString(unknownData) +
", heartRate=" + heartRate +
", speed=" + speed +
", stepRate=" + stepRate +
@ -259,13 +264,17 @@ public class Workout {
", eversionAngle=" + eversionAngle +
", swolf=" + swolf +
", strokeRate=" + strokeRate +
", calories=" + calories +
", cyclingPower=" + cyclingPower +
", frequency=" + frequency +
", altitude=" + altitude +
", timestamp=" + timestamp +
'}';
}
}
// I'm not sure about the lengths, but we haven't gotten any complaints so they probably are fine
private final byte[] bitmapLengths = {1, 2, 1, 2, 2, 4, -1, 2, 2, 1, 1, 1, 1, 1, 1, 1};
private final byte[] bitmapLengths = {1, 2, 1, 2, 2, 4, -1, 2, 2, 2, 1, 1, 1, 1, 1, 1};
private final byte[] innerBitmapLengths = {2, 2, 2, 1, 2, 1, 1, 1, 1, 2, 2, 1, 1, 1, 1, 1};
public short workoutNumber;
@ -367,6 +376,9 @@ public class Workout {
case 4:
data.strokeRate = buf.getShort();
break;
case 5:
data.altitude = buf.getInt();
break;
case 6:
// Inner data, parsing into data
// TODO: function for readability?
@ -410,6 +422,15 @@ public class Workout {
}
}
break;
case 7:
data.calories = buf.getShort();
break;
case 8:
data.frequency = buf.getShort();
break;
case 9:
data.cyclingPower = buf.getShort();
break;
default:
data.unknownData = this.tlv.serialize();
// Fix alignment

View File

@ -0,0 +1,83 @@
package nodomain.freeyourgadget.gadgetbridge.devices.soundcore;
import androidx.annotation.NonNull;
import java.util.regex.Pattern;
import nodomain.freeyourgadget.gadgetbridge.GBException;
import nodomain.freeyourgadget.gadgetbridge.R;
import nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSpecificSettings;
import nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSpecificSettingsScreen;
import nodomain.freeyourgadget.gadgetbridge.devices.AbstractDeviceCoordinator;
import nodomain.freeyourgadget.gadgetbridge.entities.DaoSession;
import nodomain.freeyourgadget.gadgetbridge.entities.Device;
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
import nodomain.freeyourgadget.gadgetbridge.model.BatteryConfig;
import nodomain.freeyourgadget.gadgetbridge.service.DeviceSupport;
import nodomain.freeyourgadget.gadgetbridge.service.devices.soundcore.SoundcoreLiberty3ProDeviceSupport;
public class SoundcoreLiberty3ProCoordinator extends AbstractDeviceCoordinator {
@Override
public int getDeviceNameResource() {
return R.string.devicetype_soundcore_liberty3_pro;
}
@Override
public int getDefaultIconResource() {
return R.drawable.ic_device_galaxy_buds;
}
@Override
public int getDisabledIconResource() {
return R.drawable.ic_device_galaxy_buds_disabled;
}
@Override
public String getManufacturer() {
return "Anker";
}
@Override
protected Pattern getSupportedDeviceName() {
return Pattern.compile("Soundcore Liberty 3 Pro");
}
@Override
public int getBondingStyle(){
return BONDING_STYLE_NONE;
}
@Override
protected void deleteDevice(@NonNull GBDevice gbDevice, @NonNull Device device, @NonNull DaoSession session) throws GBException {
}
@Override
public int getBatteryCount() {
return 3;
}
@Override
public BatteryConfig[] getBatteryConfig() {
BatteryConfig battery1 = new BatteryConfig(0, R.drawable.ic_buds_pro_case, R.string.battery_case);
BatteryConfig battery2 = new BatteryConfig(1, R.drawable.ic_nothing_ear_l, R.string.left_earbud);
BatteryConfig battery3 = new BatteryConfig(2, R.drawable.ic_nothing_ear_r, R.string.right_earbud);
return new BatteryConfig[]{battery1, battery2, battery3};
}
@Override
public DeviceSpecificSettings getDeviceSpecificSettings(final GBDevice device) {
final DeviceSpecificSettings deviceSpecificSettings = new DeviceSpecificSettings();
deviceSpecificSettings.addRootScreen(DeviceSpecificSettingsScreen.TOUCH_OPTIONS);
deviceSpecificSettings.addSubScreen(DeviceSpecificSettingsScreen.TOUCH_OPTIONS, R.xml.devicesettings_sony_headphones_ambient_sound_control_button_modes);
deviceSpecificSettings.addSubScreen(DeviceSpecificSettingsScreen.TOUCH_OPTIONS, R.xml.devicesettings_soundcore_touch_options);
deviceSpecificSettings.addRootScreen(R.xml.devicesettings_soundcore_headphones);
return deviceSpecificSettings;
}
@NonNull
@Override
public Class<? extends DeviceSupport> getDeviceSupportClass() {
return SoundcoreLiberty3ProDeviceSupport.class;
}
}

View File

@ -457,6 +457,7 @@ public abstract class XiaomiCoordinator extends AbstractBLEDeviceCoordinator {
if (getCannedRepliesSlotCount(device) > 0) {
notifications.add(R.xml.devicesettings_canned_dismisscall_16);
}
notifications.add(R.xml.devicesettings_transliteration);
//
// Calendar

View File

@ -97,60 +97,80 @@ public class XiaomiSampleProvider extends AbstractSampleProvider<XiaomiActivityS
return samples;
}
/**
* See {@link nodomain.freeyourgadget.gadgetbridge.service.devices.xiaomi.activity.impl.SleepDetailsParser}
*/
private static int getActivityKindForSample(final XiaomiSleepStageSample sample) {
switch (sample.getStage()) {
case 2:
return ActivityKind.TYPE_DEEP_SLEEP;
case 3:
return ActivityKind.TYPE_LIGHT_SLEEP;
case 4:
return ActivityKind.TYPE_REM_SLEEP;
default: // default to awake
return ActivityKind.TYPE_UNKNOWN;
}
}
/**
* Overlay sleep states on activity samples, since they are stored on a separate table.
*
* @implNote This currently needs to look back a further 24h, so that we are sure that we
* got the sleep start of a sleep session at the start of the samples, if any. This is especially
* noticeable if the charts are configured in a noon-to-noon setting. FIXME: This is not ideal,
* and we may need to rethink the way sleep samples are persisted in the database for Xiaomi devices.
* @implNote In order to determine whether a sleep session was ongoing at the start of the
* given range and what the detected sleep stage was at that time, the last sleep stage and
* sleep time sample before the given range will be queried and included in the results if
* found.
*/
public void overlaySleep(final List<XiaomiActivitySample> samples, final int timestamp_from, final int timestamp_to) {
final RangeMap<Long, Integer> stagesMap = new RangeMap<>();
final XiaomiSleepStageSampleProvider sleepStagesSampleProvider = new XiaomiSleepStageSampleProvider(getDevice(), getSession());
final List<XiaomiSleepStageSample> stageSamples = sleepStagesSampleProvider.getAllSamples(
timestamp_from * 1000L - 86400000L,
// Retrieve the last stage before this time range, as the user could have been asleep during
// the range transition
final XiaomiSleepStageSample lastSleepStageBeforeRange = sleepStagesSampleProvider.getLastSampleBefore(timestamp_from * 1000L);
if (lastSleepStageBeforeRange != null) {
LOG.debug("Last sleep stage before range: ts={}, stage={}", lastSleepStageBeforeRange.getTimestamp(), lastSleepStageBeforeRange.getStage());
stagesMap.put(lastSleepStageBeforeRange.getTimestamp(), getActivityKindForSample(lastSleepStageBeforeRange));
}
// Retrieve all sleep stage samples during the range
final List<XiaomiSleepStageSample> sleepStagesInRange = sleepStagesSampleProvider.getAllSamples(
timestamp_from * 1000L,
timestamp_to * 1000L
);
if (!stageSamples.isEmpty()) {
if (!sleepStagesInRange.isEmpty()) {
// We got actual sleep stages
LOG.debug("Found {} sleep stage samples between {} and {}", stageSamples.size(), timestamp_from, timestamp_to);
LOG.debug("Found {} sleep stage samples between {} and {}", sleepStagesInRange.size(), timestamp_from, timestamp_to);
for (final XiaomiSleepStageSample stageSample : stageSamples) {
final int activityKind;
switch (stageSample.getStage()) {
case 2: // deep
activityKind = ActivityKind.TYPE_DEEP_SLEEP;
break;
case 3: // light
activityKind = ActivityKind.TYPE_LIGHT_SLEEP;
break;
case 4: // rem
activityKind = ActivityKind.TYPE_REM_SLEEP;
break;
case 0: // final awake
case 1: // ?
case 5: // awake during the night
default:
activityKind = ActivityKind.TYPE_UNKNOWN;
break;
}
stagesMap.put(stageSample.getTimestamp(), activityKind);
for (final XiaomiSleepStageSample stageSample : sleepStagesInRange) {
stagesMap.put(stageSample.getTimestamp(), getActivityKindForSample(stageSample));
}
}
// Fetch bed and wakeup times as well.
final XiaomiSleepTimeSampleProvider sleepTimeSampleProvider = new XiaomiSleepTimeSampleProvider(getDevice(), getSession());
final List<XiaomiSleepTimeSample> sleepTimeSamples = sleepTimeSampleProvider.getAllSamples(
timestamp_from * 1000L - 86400000L,
// Find last sleep sample before the requested range, as the recorded wake up time may be
// in the current range
final XiaomiSleepTimeSample lastSleepTimesBeforeRange = sleepTimeSampleProvider.getLastSampleBefore(timestamp_from * 1000L);
if (lastSleepTimesBeforeRange != null) {
stagesMap.put(lastSleepTimesBeforeRange.getWakeupTime(), ActivityKind.TYPE_UNKNOWN);
stagesMap.put(lastSleepTimesBeforeRange.getTimestamp(), ActivityKind.TYPE_LIGHT_SLEEP);
}
// Find all wake up and sleep samples in the current time range
final List<XiaomiSleepTimeSample> sleepTimesInRange = sleepTimeSampleProvider.getAllSamples(
timestamp_from * 1000L,
timestamp_to * 1000L
);
if (!sleepTimeSamples.isEmpty()) {
LOG.debug("Found {} sleep samples between {} and {}", sleepTimeSamples.size(), timestamp_from, timestamp_to);
for (final XiaomiSleepTimeSample stageSample : sleepTimeSamples) {
if (stageSamples.isEmpty()) {
if (!sleepTimesInRange.isEmpty()) {
LOG.debug("Found {} sleep samples between {} and {}", sleepTimesInRange.size(), timestamp_from, timestamp_to);
for (final XiaomiSleepTimeSample stageSample : sleepTimesInRange) {
if (sleepStagesInRange.isEmpty()) {
// Only overlay them as light sleep if we don't have actual sleep stages
stagesMap.put(stageSample.getTimestamp(), ActivityKind.TYPE_LIGHT_SLEEP);
}

View File

@ -53,6 +53,7 @@ public class IntentApiReceiver extends BroadcastReceiver {
public static final String COMMAND_TRIGGER_EXPORT = "nodomain.freeyourgadget.gadgetbridge.command.TRIGGER_EXPORT";
public static final String COMMAND_DEBUG_SEND_NOTIFICATION = "nodomain.freeyourgadget.gadgetbridge.command.DEBUG_SEND_NOTIFICATION";
public static final String COMMAND_DEBUG_INCOMING_CALL = "nodomain.freeyourgadget.gadgetbridge.command.DEBUG_INCOMING_CALL";
public static final String COMMAND_DEBUG_END_CALL = "nodomain.freeyourgadget.gadgetbridge.command.DEBUG_END_CALL";
public static final String COMMAND_DEBUG_SET_DEVICE_ADDRESS = "nodomain.freeyourgadget.gadgetbridge.command.DEBUG_SET_DEVICE_ADDRESS";
public static final String COMMAND_DEBUG_TEST_NEW_FUNCTION = "nodomain.freeyourgadget.gadgetbridge.command.DEBUG_TEST_NEW_FUNCTION";
@ -168,6 +169,18 @@ public class IntentApiReceiver extends BroadcastReceiver {
}
GBApplication.deviceService().onSetCallState(callSpec);
break;
case COMMAND_DEBUG_END_CALL:
if (!prefs.getBoolean("intent_api_allow_debug_commands", false)) {
LOG.warn(msgDebugNotAllowed);
return;
}
LOG.info("Triggering Debug End Call");
CallSpec callSpecEnd = new CallSpec();
callSpecEnd.command = CallSpec.CALL_END;
GBApplication.deviceService().onSetCallState(callSpecEnd);
break;
case COMMAND_DEBUG_SET_DEVICE_ADDRESS:
if (!prefs.getBoolean("intent_api_allow_debug_commands", false)) {
LOG.warn(msgDebugNotAllowed);
@ -193,6 +206,7 @@ public class IntentApiReceiver extends BroadcastReceiver {
intentFilter.addAction(COMMAND_TRIGGER_EXPORT);
intentFilter.addAction(COMMAND_DEBUG_SEND_NOTIFICATION);
intentFilter.addAction(COMMAND_DEBUG_INCOMING_CALL);
intentFilter.addAction(COMMAND_DEBUG_END_CALL);
intentFilter.addAction(COMMAND_DEBUG_SET_DEVICE_ADDRESS);
intentFilter.addAction(COMMAND_DEBUG_TEST_NEW_FUNCTION);
return intentFilter;

View File

@ -106,6 +106,10 @@ public class ActivitySummaryEntries {
public static final String MAXIMUM_OXYGEN_UPTAKE = "maximumOxygenUptake";
public static final String RECOVERY_TIME = "recoveryTime";
public static final String CYCLING_POWER_AVERAGE = "cyclingPowerAverage";
public static final String CYCLING_POWER_MIN = "cyclingPowerMin";
public static final String CYCLING_POWER_MAX = "cyclingPowerMax";
public static final String UNIT_BPM = "bpm";
public static final String UNIT_CM = "cm";
public static final String UNIT_UNIX_EPOCH_SECONDS = "unix_epoch_seconds";

View File

@ -119,6 +119,7 @@ import nodomain.freeyourgadget.gadgetbridge.devices.huawei.huaweiband8.HuaweiBan
import nodomain.freeyourgadget.gadgetbridge.devices.huawei.huaweibandaw70.HuaweiBandAw70Coordinator;
import nodomain.freeyourgadget.gadgetbridge.devices.huawei.huaweitalkbandb6.HuaweiTalkBandB6Coordinator;
import nodomain.freeyourgadget.gadgetbridge.devices.huawei.huaweiwatchfit.HuaweiWatchFitCoordinator;
import nodomain.freeyourgadget.gadgetbridge.devices.huawei.huaweiwatchfit2.HuaweiWatchFit2Coordinator;
import nodomain.freeyourgadget.gadgetbridge.devices.huawei.huaweiwatchgt.HuaweiWatchGTCoordinator;
import nodomain.freeyourgadget.gadgetbridge.devices.huawei.huaweiwatchgt2.HuaweiWatchGT2Coordinator;
import nodomain.freeyourgadget.gadgetbridge.devices.huawei.huaweiwatchgt2e.HuaweiWatchGT2eCoordinator;
@ -167,6 +168,7 @@ import nodomain.freeyourgadget.gadgetbridge.devices.sony.headphones.coordinators
import nodomain.freeyourgadget.gadgetbridge.devices.sony.headphones.coordinators.SonyWH1000XM5Coordinator;
import nodomain.freeyourgadget.gadgetbridge.devices.sony.wena3.SonyWena3Coordinator;
import nodomain.freeyourgadget.gadgetbridge.devices.sonyswr12.SonySWR12DeviceCoordinator;
import nodomain.freeyourgadget.gadgetbridge.devices.soundcore.SoundcoreLiberty3ProCoordinator;
import nodomain.freeyourgadget.gadgetbridge.devices.supercars.SuperCarsCoordinator;
import nodomain.freeyourgadget.gadgetbridge.devices.test.TestDeviceCoordinator;
import nodomain.freeyourgadget.gadgetbridge.devices.tlw64.TLW64Coordinator;
@ -347,6 +349,7 @@ public enum DeviceType {
SONY_LINKBUDS_S(SonyLinkBudsSCoordinator.class),
SONY_WH_1000XM5(SonyWH1000XM5Coordinator.class),
SONY_WF_1000XM5(SonyWF1000XM5Coordinator.class),
SOUNDCORE_LIBERTY3_PRO(SoundcoreLiberty3ProCoordinator.class),
BOSE_QC35(QC35Coordinator.class),
HONORBAND3(HonorBand3Coordinator.class),
HONORBAND4(HonorBand4Coordinator.class),
@ -366,6 +369,7 @@ public enum DeviceType {
HUAWEIWATCHGT4(HuaweiWatchGT4Coordinator.class),
HUAWEIBAND8(HuaweiBand8Coordinator.class),
HUAWEIWATCHFIT(HuaweiWatchFitCoordinator.class),
HUAWEIWATCHFIT2(HuaweiWatchFit2Coordinator.class),
HUAWEIWATCHULTIMATE(HuaweiWatchUltimateCoordinator.class),
VESC(VescCoordinator.class),
BINARY_SENSOR(BinarySensorCoordinator.class),

View File

@ -18,6 +18,7 @@
package nodomain.freeyourgadget.gadgetbridge.service.btle;
import android.Manifest;
import android.annotation.SuppressLint;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.Service;
@ -326,8 +327,8 @@ public class BLEScanService extends Service {
unregisterReceiver(bluetoothStateChangedReceiver);
}
private boolean hasBluetoothPermission(){
if(Build.VERSION.SDK_INT <= Build.VERSION_CODES.R){
private boolean hasBluetoothPermission() {
if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.R) {
// workaround. Cannot give bluetooth permission on Android O
LOG.warn("Running on android 11, skipping bluetooth permission check");
return ActivityCompat.checkSelfPermission(getApplicationContext(), Manifest.permission.ACCESS_COARSE_LOCATION) == PackageManager.PERMISSION_GRANTED;
@ -335,6 +336,7 @@ public class BLEScanService extends Service {
return ActivityCompat.checkSelfPermission(getApplicationContext(), Manifest.permission.BLUETOOTH_SCAN) == PackageManager.PERMISSION_GRANTED;
}
@SuppressLint("MissingPermission") // linter does not recognize the usage of hasBluetoothPermission
private void restartScan(boolean applyFilters) {
if (!hasBluetoothPermission()) {
// this should never happen
@ -357,7 +359,9 @@ public class BLEScanService extends Service {
return;
}
if (currentState.isDoingAnyScan()) {
scanner.stopScan(scanCallback);
if (hasBluetoothPermission()) {
scanner.stopScan(scanCallback);
}
}
ArrayList<ScanFilter> scanFilters = null;
@ -375,7 +379,7 @@ public class BLEScanService extends Service {
}
}
if (scanFilters.size() == 0) {
if (scanFilters.isEmpty()) {
// no need to start scanning
LOG.debug("restartScan: stopping BLE scan, no devices");
currentState = ScanningState.NOT_SCANNING;

View File

@ -88,6 +88,7 @@ import nodomain.freeyourgadget.gadgetbridge.service.devices.huawei.requests.GetN
import nodomain.freeyourgadget.gadgetbridge.service.devices.huawei.requests.GetSmartAlarmList;
import nodomain.freeyourgadget.gadgetbridge.service.devices.huawei.requests.GetWatchfaceParams;
import nodomain.freeyourgadget.gadgetbridge.service.devices.huawei.requests.SendExtendedAccountRequest;
import nodomain.freeyourgadget.gadgetbridge.service.devices.huawei.requests.SendFitnessUserInfoRequest;
import nodomain.freeyourgadget.gadgetbridge.service.devices.huawei.requests.SendGpsAndTimeToDeviceRequest;
import nodomain.freeyourgadget.gadgetbridge.service.devices.huawei.requests.SendGpsDataRequest;
import nodomain.freeyourgadget.gadgetbridge.service.devices.huawei.requests.SendFileUploadInfo;
@ -505,6 +506,7 @@ public class HuaweiSupportProvider {
}
onSetTime();
getBatteryLevel();
sendUserInfo();
if (isBLE()) {
assert leBuilder != null;
leBuilder.add(new nodomain.freeyourgadget.gadgetbridge.service.btle.actions.SetDeviceStateAction(gbDevice, GBDevice.State.INITIALIZED, context));
@ -963,6 +965,12 @@ public class HuaweiSupportProvider {
case ActivityUser.PREF_USER_STEPS_GOAL:
new SendFitnessGoalRequest(this).doPerform();
break;
case ActivityUser.PREF_USER_WEIGHT_KG:
case ActivityUser.PREF_USER_HEIGHT_CM:
case ActivityUser.PREF_USER_GENDER:
case ActivityUser.PREF_USER_YEAR_OF_BIRTH:
sendUserInfo();
break;
}
} catch (IOException e) {
// TODO: Use translatable string
@ -1513,7 +1521,11 @@ public class HuaweiSupportProvider {
data.eversionAngle,
data.swolf,
data.strokeRate,
unknown
unknown,
data.calories,
data.cyclingPower,
data.frequency,
data.altitude
);
dao.insertOrReplace(dataSample);
}
@ -1566,6 +1578,17 @@ public class HuaweiSupportProvider {
}
}
public void sendUserInfo() {
try {
SendFitnessUserInfoRequest sendFitnessUserInfoRequest = new SendFitnessUserInfoRequest(this);
sendFitnessUserInfoRequest.doPerform();
} catch (IOException e) {
GB.toast(context, "Failed to set user info", Toast.LENGTH_SHORT, GB.ERROR, e);
LOG.error("Failed to set user info", e);
}
}
public void setActivateOnLift() {
try {
SetActivateOnLiftRequest setActivateOnLiftReq = new SetActivateOnLiftRequest(this);

View File

@ -106,7 +106,11 @@ public class HuaweiWorkoutGbParser {
responseData.eversionAngle,
responseData.swolf,
responseData.strokeRate,
dataErrorHex
dataErrorHex,
responseData.calories,
responseData.cyclingPower,
responseData.frequency,
responseData.altitude
);
dbHandler.getDaoSession().getHuaweiWorkoutDataSampleDao().insertOrReplace(dataSample);
@ -301,6 +305,18 @@ public class HuaweiWorkoutGbParser {
int heartRateCount = 0;
int maxHeartRate = 0;
int minHeartRate = Integer.MAX_VALUE;
int sumCalories = 0;
int minCyclingPower = Integer.MAX_VALUE;
int maxCyclingPower = 0;
int cyclingPower = 0;
int cyclingPowerCount = 0;
int avgAltitude = 0;
int altitudeCount = 0;
int minAltitude = 0;
int maxAltitude = 0;
Integer previousAlt = null;
int sumAltitudeUp = 0;
int sumAltitudeDown = 0;
for (HuaweiWorkoutDataSample dataSample : dataSamples) {
if (dataSample.getSpeed() != -1) {
speed += dataSample.getSpeed();
@ -373,6 +389,33 @@ public class HuaweiWorkoutGbParser {
if (hr < minHeartRate)
minHeartRate = hr;
}
if (dataSample.getCalories() != -1)
sumCalories += dataSample.getCalories();
if (dataSample.getCyclingPower() != -1) {
int cp = dataSample.getCyclingPower();
cyclingPower += cp;
cyclingPowerCount += 1;
if (cp > maxCyclingPower)
maxCyclingPower = cp;
if (cp < minCyclingPower)
minCyclingPower = cp;
}
if (dataSample.getAltitude() != null) {
int alt = dataSample.getAltitude();
avgAltitude += alt;
altitudeCount += 1;
if (alt > maxAltitude)
maxAltitude = alt;
if (alt < minAltitude)
minAltitude = alt;
if (previousAlt != null) {
if (alt > previousAlt)
sumAltitudeUp += alt - previousAlt;
else if (alt < previousAlt)
sumAltitudeDown += previousAlt - alt;
}
previousAlt = alt;
}
if (dataSample.getDataErrorHex() != null)
unknownData = true;
}
@ -400,6 +443,10 @@ public class HuaweiWorkoutGbParser {
strokeRate = strokeRate / strokeRateCount;
if (heartRateCount > 0)
heartRate = heartRate / heartRateCount;
if (cyclingPowerCount > 0)
cyclingPower = cyclingPower / cyclingPowerCount;
if (altitudeCount > 0)
avgAltitude = avgAltitude / altitudeCount;
if (speedCount > 0) {
JSONObject speedJson = new JSONObject();
@ -534,6 +581,57 @@ public class HuaweiWorkoutGbParser {
minHeartRateJson.put("unit", ActivitySummaryEntries.UNIT_BPM);
jsonObject.put(ActivitySummaryEntries.HR_MIN, minHeartRateJson);
}
if (sumCalories > 0) {
JSONObject caloriesSumJson = new JSONObject();
caloriesSumJson.put("value", sumCalories);
caloriesSumJson.put("unit", ActivitySummaryEntries.UNIT_KCAL);
jsonObject.put(ActivitySummaryEntries.CALORIES_BURNT, caloriesSumJson);
}
if (cyclingPowerCount > 0) {
JSONObject cyclingPowerJson = new JSONObject();
cyclingPowerJson.put("value", cyclingPower);
cyclingPowerJson.put("unit", "");
jsonObject.put(ActivitySummaryEntries.CYCLING_POWER_AVERAGE, cyclingPowerJson);
JSONObject minCyclingPowerJson = new JSONObject();
minCyclingPowerJson.put("value", minCyclingPower);
minCyclingPowerJson.put("unit", "");
jsonObject.put(ActivitySummaryEntries.CYCLING_POWER_MIN, minCyclingPowerJson);
JSONObject maxCyclingPowerJson = new JSONObject();
maxCyclingPowerJson.put("value", maxCyclingPower);
maxCyclingPowerJson.put("unit", "");
jsonObject.put(ActivitySummaryEntries.CYCLING_POWER_MAX, maxCyclingPowerJson);
}
if (altitudeCount > 0) {
JSONObject avgAltitudeJson = new JSONObject();
avgAltitudeJson.put("value", avgAltitude);
avgAltitudeJson.put("unit", "");
jsonObject.put(ActivitySummaryEntries.ALTITUDE_AVG, avgAltitudeJson);
JSONObject minAltitudeJson = new JSONObject();
minAltitudeJson.put("value", minAltitude);
minAltitudeJson.put("unit", "");
jsonObject.put(ActivitySummaryEntries.ALTITUDE_MIN, minAltitudeJson);
JSONObject maxAltitudeJson = new JSONObject();
maxAltitudeJson.put("value", maxAltitude);
maxAltitudeJson.put("unit", "");
jsonObject.put(ActivitySummaryEntries.ALTITUDE_MAX, maxAltitudeJson);
JSONObject sumUpAltitudeJson = new JSONObject();
sumUpAltitudeJson.put("value", sumAltitudeUp);
sumUpAltitudeJson.put("unit", "");
jsonObject.put(ActivitySummaryEntries.ELEVATION_GAIN, sumUpAltitudeJson);
JSONObject sumDownAltitudeJson = new JSONObject();
sumDownAltitudeJson.put("value", sumAltitudeDown);
sumDownAltitudeJson.put("unit", "");
jsonObject.put(ActivitySummaryEntries.ELEVATION_LOSS, sumDownAltitudeJson);
}
}
try (CloseableListIterator<HuaweiWorkoutPaceSample> it = qbPace.build().listIterator()) {

View File

@ -0,0 +1,76 @@
/* Copyright (C) 2024 Vitalii Tomin
This file is part of Gadgetbridge.
Gadgetbridge is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published
by the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Gadgetbridge is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>. */
package nodomain.freeyourgadget.gadgetbridge.service.devices.huawei.requests;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import nodomain.freeyourgadget.gadgetbridge.devices.huawei.HuaweiPacket;
import nodomain.freeyourgadget.gadgetbridge.devices.huawei.packets.FitnessData;
import nodomain.freeyourgadget.gadgetbridge.devices.huawei.packets.FitnessData.UserInfo;
import nodomain.freeyourgadget.gadgetbridge.model.ActivityUser;
import nodomain.freeyourgadget.gadgetbridge.service.devices.huawei.HuaweiSupportProvider;
public class SendFitnessUserInfoRequest extends Request {
private static final Logger LOG = LoggerFactory.getLogger(SendFitnessUserInfoRequest.class);
public SendFitnessUserInfoRequest(HuaweiSupportProvider support) {
super(support);
this.serviceId = FitnessData.id;
this.commandId = UserInfo.id;
}
@Override
protected List<byte[]> createRequest() throws RequestCreationException {
try {
// Hardcoded values till interface for goal
ActivityUser activityUser = new ActivityUser();
byte gender = 3;
if (activityUser.getGender() == ActivityUser.GENDER_FEMALE) {
gender = 2;
} else if (activityUser.getGender() == ActivityUser.GENDER_MALE) {
gender = 1;
}
Date birthday = activityUser.getUserBirthday();
Calendar cal = Calendar.getInstance();
cal.setTime(birthday);
int birthdayEncoded = cal.get(Calendar.YEAR) << 16;
birthdayEncoded += (cal.get(Calendar.MONTH)+1) << 8;
birthdayEncoded += cal.get(Calendar.DAY_OF_MONTH);
return new UserInfo.Request(paramsProvider,
activityUser.getHeightCm(),
activityUser.getWeightKg(),
activityUser.getAge(),
birthdayEncoded,
gender
).serialize();
} catch (HuaweiPacket.CryptoException e) {
throw new RequestCreationException(e);
}
}
@Override
protected void processResponse() {
LOG.debug("handle Send Fitness UserInfo Request");
}
}

View File

@ -0,0 +1,33 @@
package nodomain.freeyourgadget.gadgetbridge.service.devices.soundcore;
import nodomain.freeyourgadget.gadgetbridge.service.btbr.TransactionBuilder;
import nodomain.freeyourgadget.gadgetbridge.service.serial.AbstractSerialDeviceSupport;
import nodomain.freeyourgadget.gadgetbridge.service.serial.GBDeviceIoThread;
import nodomain.freeyourgadget.gadgetbridge.service.serial.GBDeviceProtocol;
public class SoundcoreLiberty3ProDeviceSupport extends AbstractSerialDeviceSupport {
@Override
public boolean connect() {
getDeviceIOThread().start();
return true;
}
@Override
public boolean useAutoConnect() {
return false;
}
@Override
protected GBDeviceProtocol createDeviceProtocol() {
return new SoundcoreLibertyProtocol(getDevice());
}
@Override
protected synchronized GBDeviceIoThread createDeviceIOThread() {
return new SoundcoreLibertyIOThread(getDevice(), getContext(),
(SoundcoreLibertyProtocol) getDeviceProtocol(),
SoundcoreLiberty3ProDeviceSupport.this, getBluetoothAdapter());
}
}

View File

@ -0,0 +1,49 @@
package nodomain.freeyourgadget.gadgetbridge.service.devices.soundcore;
import static nodomain.freeyourgadget.gadgetbridge.util.GB.hexdump;
import android.bluetooth.BluetoothAdapter;
import android.content.Context;
import android.os.ParcelUuid;
import androidx.annotation.NonNull;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.IOException;
import java.io.InputStream;
import java.util.Arrays;
import java.util.UUID;
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
import nodomain.freeyourgadget.gadgetbridge.service.btclassic.BtClassicIoThread;
public class SoundcoreLibertyIOThread extends BtClassicIoThread {
private static final Logger LOG = LoggerFactory.getLogger(SoundcoreLibertyIOThread.class);
private final SoundcoreLibertyProtocol mSoundcoreProtocol;
public SoundcoreLibertyIOThread(GBDevice gbDevice, Context context, SoundcoreLibertyProtocol deviceProtocol, SoundcoreLiberty3ProDeviceSupport deviceSupport, BluetoothAdapter btAdapter) {
super(gbDevice, context, deviceProtocol, deviceSupport, btAdapter);
mSoundcoreProtocol = deviceProtocol;
}
@Override
protected void initialize() {
write(mSoundcoreProtocol.encodeDeviceInfoRequest());
setUpdateState(GBDevice.State.INITIALIZED);
}
@NonNull
protected UUID getUuidToConnect(@NonNull ParcelUuid[] uuids) {
return mSoundcoreProtocol.UUID_DEVICE_CTRL;
}
@Override
protected byte[] parseIncoming(InputStream inStream) throws IOException {
byte[] buffer = new byte[1048576]; //HUGE read
int bytes = inStream.read(buffer);
LOG.debug("read " + bytes + " bytes. " + hexdump(buffer, 0, bytes));
return Arrays.copyOf(buffer, bytes);
}
}

View File

@ -0,0 +1,377 @@
package nodomain.freeyourgadget.gadgetbridge.service.devices.soundcore;
import static nodomain.freeyourgadget.gadgetbridge.util.GB.hexdump;
import android.content.SharedPreferences;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.UUID;
import nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSettingsPreferenceConst;
import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEvent;
import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEventBatteryInfo;
import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEventVersionInfo;
import nodomain.freeyourgadget.gadgetbridge.devices.sony.headphones.prefs.AmbientSoundControlButtonMode;
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
import nodomain.freeyourgadget.gadgetbridge.service.serial.GBDeviceProtocol;
import nodomain.freeyourgadget.gadgetbridge.util.Prefs;
public class SoundcoreLibertyProtocol extends GBDeviceProtocol {
private static final Logger LOG = LoggerFactory.getLogger(SoundcoreLibertyProtocol.class);
private static final int battery_case = 0;
private static final int battery_earphone_left = 1;
private static final int battery_earphone_right = 2;
final UUID UUID_DEVICE_CTRL = UUID.fromString("0cf12d31-fac3-4553-bd80-d6832e7b3952");
protected SoundcoreLibertyProtocol(GBDevice device) {
super(device);
}
private GBDeviceEventBatteryInfo buildBatteryInfo(int batteryIndex, int level) {
GBDeviceEventBatteryInfo info = new GBDeviceEventBatteryInfo();
info.batteryIndex = batteryIndex;
info.level = level;
return info;
}
private GBDeviceEventVersionInfo buildVersionInfo(String firmware1, String firmware2, String serialNumber) {
GBDeviceEventVersionInfo info = new GBDeviceEventVersionInfo();
info.hwVersion = serialNumber;
info.fwVersion = firmware1;
info.fwVersion2 = firmware2;
return info;
}
private String readString(byte[] data, int position, int size) {
if (position + size > data.length) throw new IllegalStateException();
return new String(data, position, size, StandardCharsets.UTF_8);
}
@Override
public GBDeviceEvent[] decodeResponse(byte[] responseData) {
// Byte 0-4: Header
// Byte 5-6: Command (Audio-Mode)
// Byte 7: Size of data
// Byte 8-(x-1): Data
// Byte x: Checksum
if (responseData.length == 0) return null;
List<GBDeviceEvent> devEvts = new ArrayList<>();
byte[] command = Arrays.copyOfRange(responseData, 5, 7);
byte[] data = Arrays.copyOfRange(responseData, 8, responseData.length-1);
if (Arrays.equals(command, new byte[]{0x01, 0x01})) {
// a lot of other data is in here, anything interesting?
String firmware1 = readString(data, 7, 5);
String firmware2 = readString(data, 12, 5);
String serialNumber = readString(data, 17, 16);
devEvts.add(buildVersionInfo(firmware1, firmware2, serialNumber));
} else if (Arrays.equals(command, new byte[]{0x01, (byte) 0x8d})) {
LOG.debug("Unknown incoming message - command: " + hexdump(command) + ", dump: " + hexdump(responseData));
} else if (Arrays.equals(command, new byte[]{0x05, (byte) 0x82})) {
LOG.debug("Unknown incoming message - command: " + hexdump(command) + ", dump: " + hexdump(responseData));
} else if (Arrays.equals(command, new byte[]{0x05, 0x01})) {
LOG.debug("Unknown incoming message - command: " + hexdump(command) + ", dump: " + hexdump(responseData));
} else if (Arrays.equals(command, new byte[]{0x06, 0x01})) { //Sound Mode Update
decodeAudioMode(data);
} else if (Arrays.equals(command, new byte[]{0x01, 0x03})) { // Battery Update
int batteryLeft = data[1] * 20;
int batteryRight = data[2] * 20;
int batteryCase = data[3] * 20;
devEvts.add(buildBatteryInfo(battery_case, batteryCase));
devEvts.add(buildBatteryInfo(battery_earphone_left, batteryLeft));
devEvts.add(buildBatteryInfo(battery_earphone_right, batteryRight));
} else {
// see https://github.com/gmallios/SoundcoreManager/blob/master/soundcore-lib/src/models/packet_kind.rs
// for a mapping for other soundcore devices (similar protocol?)
LOG.debug("Unknown incoming message - command: " + hexdump(command) + ", dump: " + hexdump(responseData));
}
return devEvts.toArray(new GBDeviceEvent[devEvts.size()]);
}
private void decodeAudioMode(byte[] payload) {
SharedPreferences prefs = getDevicePrefs().getPreferences();
SharedPreferences.Editor editor = prefs.edit();
String soundmode = "off";
int anc_strength = 0;
if (payload[1] == 0x00) {
soundmode = "noise_cancelling";
} else if (payload[1] == 0x01) {
soundmode = "ambient_sound";
} else if (payload[1] == 0x02) {
soundmode = "off";
}
if (payload[2] == 0x10) {
anc_strength = 0;
} else if (payload[2] == 0x20) {
anc_strength = 1;
} else if (payload[2] == 0x30) {
anc_strength = 2;
}
boolean vocal_mode = (payload[3] == 0x01);
boolean adaptive_anc = (payload[4] == 0x01);
boolean windnoiseReduction = (payload[5] == 0x01);
editor.putString(DeviceSettingsPreferenceConst.PREF_SOUNDCORE_AMBIENT_SOUND_CONTROL, soundmode);
editor.putInt(DeviceSettingsPreferenceConst.PREF_SONY_AMBIENT_SOUND_LEVEL, anc_strength);
editor.putBoolean(DeviceSettingsPreferenceConst.PREF_SOUNDCORE_TRANSPARENCY_VOCAL_MODE, vocal_mode);
editor.putBoolean(DeviceSettingsPreferenceConst.PREF_SOUNDCORE_ADAPTIVE_NOISE_CANCELLING, adaptive_anc);
editor.putBoolean(DeviceSettingsPreferenceConst.PREF_SOUNDCORE_WIND_NOISE_REDUCTION, windnoiseReduction);
editor.apply();
}
@Override
public byte[] encodeSendConfiguration(String config) {
Prefs prefs = getDevicePrefs();
String pref_string;
switch (config) {
// Ambient Sound Modes
case DeviceSettingsPreferenceConst.PREF_SOUNDCORE_AMBIENT_SOUND_CONTROL:
case DeviceSettingsPreferenceConst.PREF_SOUNDCORE_WIND_NOISE_REDUCTION:
case DeviceSettingsPreferenceConst.PREF_SOUNDCORE_TRANSPARENCY_VOCAL_MODE:
case DeviceSettingsPreferenceConst.PREF_SOUNDCORE_ADAPTIVE_NOISE_CANCELLING:
case DeviceSettingsPreferenceConst.PREF_SONY_AMBIENT_SOUND_LEVEL:
return encodeAudioMode();
// Control
case DeviceSettingsPreferenceConst.PREF_SOUNDCORE_CONTROL_SINGLE_TAP_DISABLED:
return encodeControlTouchLockMessage(TapAction.SINGLE_TAP, prefs.getBoolean(DeviceSettingsPreferenceConst.PREF_SOUNDCORE_CONTROL_SINGLE_TAP_DISABLED, false));
case DeviceSettingsPreferenceConst.PREF_SOUNDCORE_CONTROL_DOUBLE_TAP_DISABLED:
return encodeControlTouchLockMessage(TapAction.DOUBLE_TAP, prefs.getBoolean(DeviceSettingsPreferenceConst.PREF_SOUNDCORE_CONTROL_DOUBLE_TAP_DISABLED, false));
case DeviceSettingsPreferenceConst.PREF_SOUNDCORE_CONTROL_TRIPLE_TAP_DISABLED:
return encodeControlTouchLockMessage(TapAction.TRIPLE_TAP, prefs.getBoolean(DeviceSettingsPreferenceConst.PREF_SOUNDCORE_CONTROL_TRIPLE_TAP_DISABLED, false));
case DeviceSettingsPreferenceConst.PREF_SOUNDCORE_CONTROL_LONG_PRESS_DISABLED:
return encodeControlTouchLockMessage(TapAction.LONG_PRESS, prefs.getBoolean(DeviceSettingsPreferenceConst.PREF_SOUNDCORE_CONTROL_LONG_PRESS_DISABLED, false));
case DeviceSettingsPreferenceConst.PREF_SOUNDCORE_CONTROL_SINGLE_TAP_ACTION_LEFT:
pref_string = prefs.getString(DeviceSettingsPreferenceConst.PREF_SOUNDCORE_CONTROL_SINGLE_TAP_ACTION_LEFT, "");
return encodeControlFunctionMessage(TapAction.SINGLE_TAP, false, TapFunction.valueOf(pref_string));
case DeviceSettingsPreferenceConst.PREF_SOUNDCORE_CONTROL_SINGLE_TAP_ACTION_RIGHT:
pref_string = prefs.getString(DeviceSettingsPreferenceConst.PREF_SOUNDCORE_CONTROL_SINGLE_TAP_ACTION_RIGHT, "");
return encodeControlFunctionMessage(TapAction.SINGLE_TAP, true, TapFunction.valueOf(pref_string));
case DeviceSettingsPreferenceConst.PREF_SOUNDCORE_CONTROL_DOUBLE_TAP_ACTION_LEFT:
pref_string = prefs.getString(DeviceSettingsPreferenceConst.PREF_SOUNDCORE_CONTROL_DOUBLE_TAP_ACTION_LEFT, "");
return encodeControlFunctionMessage(TapAction.DOUBLE_TAP, false, TapFunction.valueOf(pref_string));
case DeviceSettingsPreferenceConst.PREF_SOUNDCORE_CONTROL_DOUBLE_TAP_ACTION_RIGHT:
pref_string = prefs.getString(DeviceSettingsPreferenceConst.PREF_SOUNDCORE_CONTROL_DOUBLE_TAP_ACTION_RIGHT, "");
return encodeControlFunctionMessage(TapAction.DOUBLE_TAP, true, TapFunction.valueOf(pref_string));
case DeviceSettingsPreferenceConst.PREF_SOUNDCORE_CONTROL_TRIPLE_TAP_ACTION_LEFT:
pref_string = prefs.getString(DeviceSettingsPreferenceConst.PREF_SOUNDCORE_CONTROL_TRIPLE_TAP_ACTION_LEFT, "");
return encodeControlFunctionMessage(TapAction.TRIPLE_TAP, false, TapFunction.valueOf(pref_string));
case DeviceSettingsPreferenceConst.PREF_SOUNDCORE_CONTROL_TRIPLE_TAP_ACTION_RIGHT:
pref_string = prefs.getString(DeviceSettingsPreferenceConst.PREF_SOUNDCORE_CONTROL_TRIPLE_TAP_ACTION_RIGHT, "");
return encodeControlFunctionMessage(TapAction.TRIPLE_TAP, true, TapFunction.valueOf(pref_string));
case DeviceSettingsPreferenceConst.PREF_SOUNDCORE_CONTROL_LONG_PRESS_ACTION_LEFT:
pref_string = prefs.getString(DeviceSettingsPreferenceConst.PREF_SOUNDCORE_CONTROL_LONG_PRESS_ACTION_LEFT, "");
return encodeControlFunctionMessage(TapAction.LONG_PRESS, false, TapFunction.valueOf(pref_string));
case DeviceSettingsPreferenceConst.PREF_SOUNDCORE_CONTROL_LONG_PRESS_ACTION_RIGHT:
pref_string = prefs.getString(DeviceSettingsPreferenceConst.PREF_SOUNDCORE_CONTROL_LONG_PRESS_ACTION_RIGHT, "");
return encodeControlFunctionMessage(TapAction.LONG_PRESS, true, TapFunction.valueOf(pref_string));
case DeviceSettingsPreferenceConst.PREF_SONY_AMBIENT_SOUND_CONTROL_BUTTON_MODE:
AmbientSoundControlButtonMode modes = AmbientSoundControlButtonMode.fromPreferences(prefs.getPreferences());
switch (modes) {
case NC_AS_OFF:
return encodeControlAmbientModeMessage(true, true, true);
case NC_AS:
return encodeControlAmbientModeMessage(true, true, false);
case NC_OFF:
return encodeControlAmbientModeMessage(true, false, true);
case AS_OFF:
return encodeControlAmbientModeMessage(false, true, true);
}
// Miscellaneous Settings
case DeviceSettingsPreferenceConst.PREF_SOUNDCORE_WEARING_DETECTION:
boolean wearingDetection = prefs.getBoolean(DeviceSettingsPreferenceConst.PREF_SOUNDCORE_WEARING_DETECTION, false);
return encodeMessage((byte) 0x01, (byte) 0x81, new byte[]{0x00, encodeBoolean(wearingDetection)});
case DeviceSettingsPreferenceConst.PREF_SOUNDCORE_WEARING_TONE:
boolean wearingTone = prefs.getBoolean(DeviceSettingsPreferenceConst.PREF_SOUNDCORE_WEARING_TONE, false);
return encodeMessage((byte) 0x01, (byte) 0x8c, new byte[]{0x00, encodeBoolean(wearingTone)});
case DeviceSettingsPreferenceConst.PREF_SOUNDCORE_TOUCH_TONE:
boolean touchTone = prefs.getBoolean(DeviceSettingsPreferenceConst.PREF_SOUNDCORE_TOUCH_TONE, false);
return encodeMessage((byte) 0x01, (byte) 0x83, new byte[]{0x00, encodeBoolean(touchTone)});
default:
LOG.debug("Unsupported CONFIG: " + config);
}
return super.encodeSendConfiguration(config);
}
byte[] encodeDeviceInfoRequest() {
byte[] payload = new byte[]{0x00};
return encodeMessage((byte) 0x01, (byte) 0x01, payload);
}
byte[] encodeMysteryDataRequest1() {
byte[] payload = new byte[]{0x00, 0x00};
return encodeMessage((byte) 0x01, (byte) 0x8d, payload);
}
byte[] encodeMysteryDataRequest2() {
byte[] payload = new byte[]{0x00};
return encodeMessage((byte) 0x05, (byte) 0x01, payload);
}
byte[] encodeMysteryDataRequest3() {
byte[] payload = new byte[]{0x00, 0x00};
return encodeMessage((byte) 0x05, (byte) 0x82, payload);
}
/**
* Encodes the following settings to a payload to set the audio-mode on the headphones:
* PREF_SOUNDCORE_AMBIENT_SOUND_CONTROL If ANC, Transparent or neither should be active
* PREF_SOUNDCORE_ADAPTIVE_NOISE_CANCELLING If the strenght of the ANC should be set manual or adaptively according to ambient noise
* PREF_SONY_AMBIENT_SOUND_LEVEL How strong the ANC should be in manual mode
* PREF_SOUNDCORE_TRANSPARENCY_VOCAL_MODE If the Transparency should focus on vocals or should be fully transparent
* PREF_SOUNDCORE_WIND_NOISE_REDUCTION If Transparency or ANC should reduce Wind Noise
* @return The payload
*/
private byte[] encodeAudioMode() {
Prefs prefs = getDevicePrefs();
byte anc_mode;
switch (prefs.getString(DeviceSettingsPreferenceConst.PREF_SOUNDCORE_AMBIENT_SOUND_CONTROL, "off")) {
case "noise_cancelling":
anc_mode = 0x00;
break;
case "ambient_sound":
anc_mode = 0x01;
break;
case "off":
anc_mode = 0x02;
break;
default:
LOG.error("Invalid Audio Mode selected");
return null;
}
byte anc_strength;
switch (prefs.getInt(DeviceSettingsPreferenceConst.PREF_SONY_AMBIENT_SOUND_LEVEL, 0)) {
case 0:
anc_strength = 0x10;
break;
case 1:
anc_strength = 0x20;
break;
case 2:
anc_strength = 0x30;
break;
default:
LOG.error("Invalid ANC Strength selected");
return null;
}
byte adaptive_anc = encodeBoolean(prefs.getBoolean(DeviceSettingsPreferenceConst.PREF_SOUNDCORE_ADAPTIVE_NOISE_CANCELLING, true));
byte vocal_mode = encodeBoolean(prefs.getBoolean(DeviceSettingsPreferenceConst.PREF_SOUNDCORE_TRANSPARENCY_VOCAL_MODE, false));
byte windnoise_reduction = encodeBoolean(prefs.getBoolean(DeviceSettingsPreferenceConst.PREF_SOUNDCORE_WIND_NOISE_REDUCTION, false));
byte[] payload = new byte[]{0x00, anc_mode, anc_strength, vocal_mode, adaptive_anc, windnoise_reduction, 0x01};
return encodeMessage((byte) 0x06, (byte) 0x81, payload);
}
/**
* Enables or disables a tap-action
* @param action The byte that encodes the action (single/double/triple or long tap)
* @param disabled If the action should be enabled or disabled
* @return
*/
private byte[] encodeControlTouchLockMessage(TapAction action, boolean disabled) {
boolean enabled = !disabled;
byte enabled_byte;
byte[] payload;
switch (action) {
case SINGLE_TAP:
case TRIPLE_TAP:
enabled_byte = encodeBoolean(enabled);
break;
case DOUBLE_TAP:
case LONG_PRESS:
enabled_byte = enabled?(byte) 0x11: (byte) 0x10;
break;
default:
LOG.error("Invalid Tap action");
return null;
}
payload = new byte[]{0x00, 0x00, action.getCode(), enabled_byte};
return encodeMessage((byte) 0x04, (byte) 0x83, payload);
}
/**
* Assigns a function (eg play/pause) to an action (eg single tap on right bud)
* @param action The byte that encodes the action (single/double/triple or long tap)
* @param right If the right or left earbud is meant
* @param function The byte that encodes the triggered function (eg play/pause)
* @return The encoded message
*/
private byte[] encodeControlFunctionMessage(TapAction action, boolean right, TapFunction function) {
byte function_byte;
switch (action) {
case SINGLE_TAP:
case DOUBLE_TAP:
function_byte = (byte) (16*6 + function.getCode());
break;
case TRIPLE_TAP:
function_byte = (byte) (16*4 + function.getCode());
break;
case LONG_PRESS:
function_byte = (byte) (16*5 + function.getCode());
break;
default:
LOG.error("Invalid Tap action");
return null;
}
byte[] payload = new byte[] {0x00, encodeBoolean(right), action.getCode(), function_byte};
return encodeMessage((byte) 0x04, (byte) 0x81, payload);
}
/**
* Encodes between which Audio Modes a tap should switch, if it is set to switch the Audio Mode.
* Zb ANC -> -> Transparency -> Normal -> ANC -> ....
*/
private byte[] encodeControlAmbientModeMessage(boolean anc, boolean transparency, boolean normal) {
// Original app does not allow only one true flag. Unsure if Earbuds accept this state.
byte ambientModes = (byte) (4 * (normal?1:0) + 2 * (transparency?1:0) + (anc?1:0));
return encodeMessage((byte) 0x06, (byte) 0x82, new byte[] {0x00, ambientModes});
}
private byte encodeBoolean(boolean bool) {
if (bool) return 0x01;
else return 0x00;
}
private byte[] encodeMessage(byte command1, byte command2, byte[] payload) {
int size = 8 + payload.length + 1;
ByteBuffer msgBuf = ByteBuffer.allocate(size);
msgBuf.order(ByteOrder.BIG_ENDIAN);
msgBuf.put(new byte[] {0x08, (byte) 0xee, 0x00, 0x00, 0x00}); // header
msgBuf.put(command1);
msgBuf.put(command2);
msgBuf.put((byte) size);
msgBuf.put(payload);
byte checksum = -10;
checksum += command1 + command2 + size;
for (int b : payload) {
checksum += b;
}
msgBuf.put(checksum);
return msgBuf.array();
}
}

View File

@ -0,0 +1,19 @@
package nodomain.freeyourgadget.gadgetbridge.service.devices.soundcore;
enum TapAction {
SINGLE_TAP((byte) 0x02),
DOUBLE_TAP((byte) 0x00),
TRIPLE_TAP((byte) 0x05),
LONG_PRESS((byte) 0x01)
;
private final byte code;
TapAction(final byte code) {
this.code = code;
}
public byte getCode() {
return code;
}
}

View File

@ -0,0 +1,21 @@
package nodomain.freeyourgadget.gadgetbridge.service.devices.soundcore;
enum TapFunction {
VOLUME_DOWN(1),
VOLUME_UP(0),
MEDIA_NEXT( 3),
MEDIA_PREV(2),
PLAYPAUSE(6),
VOICE_ASSISTANT(5),
AMBIENT_SOUND_CONTROL(4)
;
private final int code;
TapFunction(final int code) {
this.code = code;
}
public int getCode() {
return code;
}
}

View File

@ -81,6 +81,7 @@ public class SleepDetailsParser extends XiaomiActivityParser {
// Heart rate samples
if ((header & (1 << (5 - versionDependentFields))) != 0) {
LOG.debug("Heart rate samples from offset {}", Integer.toHexString(buf.position()));
final int unit = buf.getShort(); // Time unit (i.e sample rate)
final int count = buf.getShort();
@ -98,6 +99,7 @@ public class SleepDetailsParser extends XiaomiActivityParser {
// SpO2 samples
if ((header & (1 << (4 - versionDependentFields))) != 0) {
LOG.debug("SpO₂ samples from offset {}", Integer.toHexString(buf.position()));
final int unit = buf.getShort(); // Time unit (i.e sample rate)
final int count = buf.getShort();
@ -115,6 +117,7 @@ public class SleepDetailsParser extends XiaomiActivityParser {
// snore samples
if (fileId.getVersion() >= 3 && (header & (1 << (3 - versionDependentFields))) != 0) {
LOG.debug("Snore level samples from offset {}", Integer.toHexString(buf.position()));
final int unit = buf.getShort(); // Time unit (i.e sample rate)
final int count = buf.getShort();
@ -131,27 +134,26 @@ public class SleepDetailsParser extends XiaomiActivityParser {
}
final List<XiaomiSleepStageSample> stages = new ArrayList<>();
LOG.debug("Sleep stage packets from offset {}", Integer.toHexString(buf.position()));
// Do not crash if we face a buffer underflow, as the next parsing is not 100% fool-proof,
// and we still want to persist whatever we got so far
boolean stagesParseFailed = false;
try {
while (buf.remaining() >= 17 && buf.getInt() == 0xFFFCFAFB) {
while (buf.remaining() >= 17) {
if (!readStagePacketHeader(buf)) {
break;
}
final int headerLen = buf.get() & 0xFF; // this seems to always be 17
// This timestamp is kind of weird, is seems to sometimes be in seconds
// and other times in nanoseconds. Message types 16 and 17 are in seconds
final long ts = buf.getLong();
final int unk = buf.get() & 0xFF;
final int parity = buf.get() & 0xFF; // sum of stage bit count should be uneven
final int type = buf.get() & 0xFF;
final int dataLen = ((buf.get() & 0xFF) << 8) | (buf.get() & 0xFF);
final byte[] data = new byte[dataLen];
buf.get(data);
final ByteBuffer dataBuf = ByteBuffer.wrap(data).order(ByteOrder.BIG_ENDIAN);
// Known types:
// - acc_unk = 0,
// - ppg_unk = 1,
@ -162,6 +164,17 @@ public class SleepDetailsParser extends XiaomiActivityParser {
// - Summary = 16,
// - Stages = 17
if (type == 0x2 || type == 0x3 || type == 0x9 || type == 0xc || type == 0xd || type == 0xe || type == 0xf) {
// the bytes reserved for the data length are believed to be flags, as they
// do not actually have any data following the headers
continue;
}
final byte[] data = new byte[dataLen];
buf.get(data);
final ByteBuffer dataBuf = ByteBuffer.wrap(data).order(ByteOrder.BIG_ENDIAN);
if (type == 16) {
final int data_0 = dataBuf.get() & 0xFF;
final int sleep_index = data_0 >> 4;
@ -193,11 +206,10 @@ public class SleepDetailsParser extends XiaomiActivityParser {
sample.setAwakeDuration(wake_duration);
// FIXME: This is an array, but we end up persisting only the last sample, since
// the timestamp is the primary key
// the timestamp is the primary key
summaries.add(sample);
sample = null;
}
else if (type == 17) { // Stages
} else if (type == 17) { // Stages
long currentTime = ts * 1000;
for (int i = 0; i < dataLen / 2; i++) {
// when the change to the phase occurs
@ -250,7 +262,6 @@ public class SleepDetailsParser extends XiaomiActivityParser {
sampleProvider.addSample(summary);
}
} catch (final Exception e) {
GB.toast(support.getContext(), "Error saving sleep sample", Toast.LENGTH_LONG, GB.ERROR);
LOG.error("Error saving sleep sample", e);
@ -282,10 +293,23 @@ public class SleepDetailsParser extends XiaomiActivityParser {
}
}
return stagesParseFailed;
return !stagesParseFailed;
}
static private int decodeStage(int rawStage) {
private static boolean readStagePacketHeader(final ByteBuffer buffer) {
while (buffer.remaining() >= 17) {
if (buffer.getInt() != 0xfffcfafb) {
// rollback to second byte of header
buffer.position(buffer.position() - 3);
continue;
}
return true;
}
return false;
}
private static int decodeStage(int rawStage) {
switch (rawStage) {
case 0:
return 5; // AWAKE

View File

@ -302,7 +302,7 @@ public class XiaomiWeatherService extends AbstractXiaomiService {
"Unknown" // some string like "Moderate"
))
.setWarning(XiaomiProto.WeatherWarnings.newBuilder()) // TODO add warnings when they become available through spec
.setPressure(weatherSpec.pressure)
.setPressure(weatherSpec.pressure * 100f)
))
.build();

View File

@ -26,6 +26,7 @@ import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
@ -36,134 +37,181 @@ public class ArmenianTransliterator implements Transliterator {
// Or if it has 'ւ' symbol after it, then we should read it as 'u' (as double o in booze)
private static final Map<String, String> transliterateMap = new LinkedHashMap<String, String>() {
{
// Simple substitutions
Map<String, String> simpleSubstitions = new HashMap<String, String>() {
{
put("ա","a");
put("բ","b");
put("գ","g");
put("դ","d");
put("ե","e");
put("զ","z");
put("է","e");
put("ը","y");
put("թ","t");
put("ժ","j");
put("ի","i");
put("լ","l");
put("խ","x");
put("ծ","c");
put("կ","k");
put("հ","h");
put("ձ","dz");
put("ղ","x");
put("ճ","c");
put("մ","m");
put("յ","y");
put("ն","n");
put("շ","sh");
put("չ","ch");
put("պ","p");
put("ջ","j");
put("ռ","r");
put("ս","s");
put("վ","v");
put("տ","t");
put("ր","r");
put("ց","c");
put("փ","p");
put("ք","q");
put("օ","o");
put("և","ev");
put("ֆ","f");
}
};
// Letter + 'ու'
put("աու","au");
put("բու","bu");
put("գու","gu");
put("դու","du");
put("եու","eu");
put("զու","zu");
put("էու","eu");
put("ըու","yu");
put("թու","tu");
put("ժու","ju");
put("իու","iu");
put("լու","lu");
put("խու","xu");
put("ծու","cu");
put("կու","ku");
put("հու","hu");
put("ձու","dzu");
put("ղու","xu");
put("ճու","cu");
put("մու","mu");
put("յու","yu");
put("նու","nu");
put("շու","shu");
put("չու","chu");
put("պու","pu");
put("ջու","ju");
put("ռու","ru");
put("սու","su");
put("վու","vu");
put("տու","tu");
put("րու","ru");
put("ցու","cu");
put("փու","pu");
put("քու","qu");
put("օու","ou");
put("ևու","eu");
put("ֆու","fu");
put("ոու","vou");
char[] letterMapU = {
'ա',
'բ',
'գ',
'դ',
'ե',
'զ',
'է',
'ը',
'թ',
'ժ',
'ի',
'լ',
'խ',
'ծ',
'կ',
'հ',
'ձ',
'ղ',
'ճ',
'մ',
'յ',
'ն',
'շ',
'չ',
'պ',
'ջ',
'ռ',
'ս',
'վ',
'տ',
'ր',
'ց',
'փ',
'ք',
'օ',
'և',
'ֆ',
'ո',
};
for(char letter : letterMapU) {
char capitalLetter = Character.toUpperCase(letter);
final String transliteratedLetter = simpleSubstitions.get(Character.toString(letter));
final String transliteratedCapitalLetter = simpleSubstitions.get(Character.toString(capitalLetter));
put(Character.toString(letter) + "ու", transliteratedLetter + "u");
put(Character.toString(capitalLetter) + "ու", transliteratedCapitalLetter + "u");
put(Character.toString(letter) + "ՈՒ", transliteratedLetter + "U");
put(Character.toString(capitalLetter) + "ՈՒ", transliteratedCapitalLetter + "U");
put(Character.toString(letter) + "Ու", transliteratedLetter + "U");
put(Character.toString(capitalLetter) + "Ու", transliteratedCapitalLetter + "U");
put(Character.toString(letter) + "ոՒ", transliteratedLetter + "U");
put(Character.toString(capitalLetter) + "ոՒ", transliteratedCapitalLetter + "U");
}
put("ու","u");
put("Ու","U");
put("ոՒ","U");
put("ՈՒ","U");
// Letter + 'ո'
put("բո","bo");
put("գո","go");
put("դո","do");
put("զո","zo");
put("թո","to");
put("ժո","jo");
put("լո","lo");
put("խո","xo");
put("ծո","co");
put("կո","ko");
put("հո","ho");
put("ձո","dzo");
put("ղո","xo");
put("ճո","co");
put("մո","mo");
put("յո","yo");
put("նո","no");
put("շո","so");
put("չո","co");
put("պո","po");
put("ջո","jo");
put("ռո","ro");
put("սո","so");
put("վո","vo");
put("տո","to");
put("րո","ro");
put("ցո","co");
put("փո","po");
put("քո","qo");
put("ևո","eo");
put("ֆո","fo");
char[] letterMapVo = {
'բ',
'գ',
'դ',
'զ',
'թ',
'ժ',
'լ',
'խ',
'ծ',
'կ',
'հ',
'ձ',
'ղ',
'ճ',
'մ',
'յ',
'ն',
'շ',
'չ',
'պ',
'ջ',
'ռ',
'ս',
'վ',
'տ',
'ր',
'ց',
'փ',
'ք',
'և',
'ֆ',
};
for(char letter : letterMapVo) {
char capitalLetter = Character.toUpperCase(letter);
final String transliteratedLetter = simpleSubstitions.get(Character.toString(letter));
final String transliteratedCapitalLetter = simpleSubstitions.get(Character.toString(capitalLetter));
put(Character.toString(letter) + "ո", transliteratedLetter + "o");
put(Character.toString(capitalLetter) + "ո", transliteratedCapitalLetter + "o");
put(Character.toString(letter) + "Ո", transliteratedLetter + "Օ");
put(Character.toString(capitalLetter) + "Ո", transliteratedCapitalLetter + "Օ");
}
put("ո","vo");
put("Ո","VO");
// Two different ways to write, we support all.
put("եւ","ev");
put("եվ","ev");
// Simple substitutions
put("ա","a");
put("բ","b");
put("գ","g");
put("դ","d");
put("ե","e");
put("զ","z");
put("է","e");
put("ը","y");
put("թ","t");
put("ժ","j");
put("ի","i");
put("լ","l");
put("խ","x");
put("ծ","c");
put("կ","k");
put("հ","h");
put("ձ","dz");
put("ղ","x");
put("ճ","c");
put("մ","m");
put("յ","y");
put("ն","n");
put("շ","sh");
put("չ","ch");
put("պ","p");
put("ջ","j");
put("ռ","r");
put("ս","s");
put("վ","v");
put("տ","t");
put("ր","r");
put("ց","c");
put("փ","p");
put("ք","q");
put("օ","o");
put("և","ev");
put("ֆ","f");
put("Եւ","Ev");
put("Եվ","Ev");
put("ԵՒ","EV");
put("ԵՎ","EV");
// If this symbol wasn't used in the combination with others, then it's meaningless
put("ւ","");
put("Ւ","");
// Add support for capitilazed words
for (final Map.Entry<String,String> entry : ((Map<String, String>)this.clone()).entrySet()) {
final String capitalKey = WordUtils.capitalize(entry.getKey());
if(!capitalKey.equals(entry.getKey())) {
put(capitalKey, WordUtils.capitalize(entry.getValue()));
}
// Simple substitutions have last priority
for (final Map.Entry<String,String> entry : simpleSubstitions.entrySet()) {
put(entry.getKey(), entry.getValue());
put(entry.getKey().toUpperCase(), entry.getValue().toUpperCase());
}
}};

View File

@ -2835,4 +2835,121 @@
<string name="devicetype_huawei_watchgt4">Huawei Watch GT 4</string>
<string name="busy_task_fetch_sports_details_interrupted">تمت مقاطعة جلب التفاصيل الرياضية</string>
<string name="devicetype_huawei_watchultimate">Huawei Watch Ultimate</string>
<string name="unbind_before_pair_title">مرتبط بالفعل</string>
<string name="companion_pairing_request_description">إقران هذا الجهاز كمرافق؟.
\n
\nيوصى بهذا لبعض الوظائف مثل البحث عن الجهاز، ويوفر اتصالاً أفضل.</string>
<string name="companion_pairing_request_title">جهاز مرافق</string>
<string name="unbind_before_pair_message">هذا الجهاز مرتبط بالفعل بإعدادات Android، مما قد يؤدي إلى فشل الاقتران لبعض الأجهزة.
\n
\nإذا فشلت إضافة الجهاز، فيرجى إزالته في إعدادات Android والمحاولة مرة أخرى.</string>
<string name="devicetype_scannable">جهاز قابل للمسح الضوئي</string>
<string name="state_scanned">تم مسحها</string>
<string name="devicesetting_scannable_debounce">مهلة الارتداد القابلة للمسح (ثواني)</string>
<string name="devicesetting_scannable_rssi_summary">الحد الأدنى لعتبة RSSI للكشف</string>
<string name="devicesetting_scannable_minimum_unseen">الحد الأدنى للوقت غير المرئي (ثواني)</string>
<string name="devicesetting_scannable_debounce_summary">بعد أن يتم فحصه، سيظل الجهاز ممسوحًا ضوئيًا ويتم تجاهله لفترة زمنية محددة</string>
<string name="devicesetting_scannable_minimum_unseen_summary">بعد أن يتم فحصه، يجب أن يكون الجهاز غير مرئي لهذه الفترة من الوقت قبل أن يتم تسجيله مرة أخرى</string>
<string name="devicesetting_scannable_rssi">الحد الأدنى لعتبة RSSI</string>
<string name="stepRateSum">مجموع معدل الخطوة</string>
<string name="stepRateAvg">متوسط معدل الخطوة</string>
<string name="stepLengthAvg">متوسط طول الخطوة</string>
<string name="groundContactTimeAvg">متوسط وقت التلامس بالأرض</string>
<string name="impactAvg">متوسط الأثر</string>
<string name="impactMax">اقصى أثر</string>
<string name="swingAngleAvg">متوسط زاوية التأرجح</string>
<string name="swolfAvg">متوسط المذؤوب</string>
<string name="swolfMax">الحد الأقصى للمذؤوب</string>
<string name="swolfMin">الحد الأدنى للمذؤوبين</string>
<string name="foreFootLandings">الهبوط الأمامي</string>
<string name="midFootLandings">هبوط منتصف القدم</string>
<string name="backFootLandings">هبوط القدم الخلفية</string>
<string name="eversionAngleAvg">متوسط زاوية الانقلاب</string>
<string name="eversionAngleMax">أقصى زاوية للانقلاب</string>
<string name="fmtPaceDistance">مسافة الوتيرة %d</string>
<string name="fmtPaceType">نوع الوتيرة %d</string>
<string name="fmtPacePace">وتيرة %d الوتيرة</string>
<string name="fmtPaceCorrection">تصحيح الوتيرة %d</string>
<string name="fmtPaceTypeAverage">نوع متوسط السرعة %d</string>
<string name="unknownDataEncountered">تمت مواجهة بيانات غير معروفة</string>
<string name="milliseconds">ميلي ثانية</string>
<string name="degrees">درجة</string>
<string name="Pace">وتيره</string>
<string name="RunningForm">نموذج الجري</string>
<string name="pref_force_enable_spo2_support">دعم قوة SpO2</string>
<string name="pref_force_enable_heartrate_support">دعم قوة معدل ضربات القلب</string>
<string name="pref_force_enable_heartrate_support_summary">قوة تمكين دعم معدل ضربات القلب.
\nاستخدام على مسؤوليتك الخاصة</string>
<string name="pref_force_enable_spo2_support_summary">فرض تمكين دعم SpO2.
\nاستخدام على مسؤوليتك الخاصة</string>
<string name="dashboard_settings">إعدادات لوحة القيادة</string>
<string name="error_showing_changelog">حدث خطأ أثناء عرض سجل التغيير</string>
<string name="activity_type_worn">تم لبسها</string>
<string name="bottom_nav_devices">الأجهزة</string>
<string name="bottom_nav_dashboard">اللوحة</string>
<string name="pref_dashboard_first_title">اظهر اللوحة أولا</string>
<string name="pref_dashboard_first_summary">إظهار لوحة المعلومات عند بدء تشغيل Gadgetbridge، بدلاً من شاشة الأجهزة</string>
<string name="pref_dashboard_cards_title">عرض الأدوات على البطاقات</string>
<string name="pref_dashboard_cards_summary">ارسم بطاقات حول الأدوات على لوحة المعلومات</string>
<string name="pref_dashboard_widget_settings">إعدادات الويدجيت</string>
<string name="pref_dashboard_widget_today_title">خريطة الأنشطة</string>
<string name="pref_dashboard_widget_today_24h_title">وضع 24 ساعة</string>
<string name="pref_dashboard_widget_double_size_title">حجم مزدوج</string>
<string name="pref_dashboard_widget_show_legend_title">عرض الأسطورة</string>
<string name="pref_dashboard_widget_goals_chart_title">خريطة الأهداف</string>
<string name="pref_dashboard_all_devices_title">جميع الأجهزة</string>
<string name="pref_dashboard_select_devices_title">تحديد الأجهزة...</string>
<string name="pref_dashboard_widgets_order_summary">حدد الأدوات التي تم تمكينها وبأي ترتيب يتم عرضها على لوحة المعلومات</string>
<string name="pref_dashboard_widget_today_24h_summary">اعرض النشاط في دائرة واحدة مدتها 24 ساعة بدلاً من دائرة مزدوجة مدتها 12 ساعة</string>
<string name="pref_dashboard_widget_double_size_summary">اسمح للأداة بشغل عمودين على لوحة المعلومات</string>
<string name="pref_dashboard_all_devices_summary">قم بدمج بيانات النشاط من كافة الأجهزة المضافة للحصول على الإجماليات على لوحة المعلومات</string>
<string name="pref_dashboard_devices_to_include">الأجهزة التي تشمل</string>
<string name="pref_dashboard_widget_show_legend_summary">إظهار وسيلة إيضاح أسفل الأداة تشرح الألوان</string>
<string name="pref_dashboard_select_devices_summary">قم بدمج بيانات النشاط من أجهزة محددة للحصول على الإجماليات على لوحة المعلومات</string>
<string name="pref_dashboard_widget_today_hr_interval_title">الفاصل الزمني لمعدل ضربات القلب</string>
<string name="pref_dashboard_widget_today_hr_interval_summary">مقدار الدقائق التي يظهرها الرسم البياني \"مستهلكة\" بعد كل قياس ناجح لمعدل ضربات القلب</string>
<string name="pref_header_generic">نوعي</string>
<string name="pref_header_audio">صوت</string>
<string name="pref_auto_reply_calls_summary">سوف يقوم الهاتف تلقائيًا باستقبال المكالمات الهاتفية الواردة</string>
<string name="pref_auto_reply_calls_title">الرد على المكالمات الهاتفية تلقائيا</string>
<string name="pref_auto_reply_calls_delay_summary">عدد الثواني التي يتم بعدها الرد على المكالمة تلقائيًا</string>
<string name="pref_auto_reply_calls_delay_title">تأخير الرد التلقائي</string>
<string name="pref_title_notification_wake_on_open">التنبيه التلقائي وفتح القفل</string>
<string name="pref_summary_notification_wake_on_open">قم بتنبيه جهاز Android وإلغاء قفله عندما ترسل الأداة ردًا مفتوحًا. يجب أن تكون في حالة موثوقة.</string>
<string name="devicetype_redmi_watch_4">ساعة ريدمي ٤</string>
<string name="widget_name_colored_tile">%1$s (إطار ملون)</string>
<string name="pref_speak_notifications_aloud_summary">سيتم قراءة الإخطارات بصوت عال من خلال سماعات الرأس</string>
<string name="pref_speak_notifications_aloud_title">نطق الإخطارات بصوت عال</string>
<string name="widget_layout_top_wide_bot_large">عريضة من الأعلى، كبيرة من الأسفل</string>
<string name="widget_layout_top_large_bot_wide">كبير من الاعلى، عريضة من الاسفل</string>
<string name="widget_name_untitled">عنصر واجهة المستخدم بدون عنوان (%1$s)</string>
<string name="pref_header_calls_and_notifications">المكالمات والإخطارات</string>
<string name="armenian">اﻷرمينية</string>
<string name="pref_summary_bottom_navigation_bar_off">قم بالتبديل بين الشاشات الرئيسية فقط باستخدام السحب الأفقي</string>
<string name="pref_dashboard_widget_today_upside_down_summary">في وضع 24 ساعة، ارسم منتصف الليل في الأسفل، ومنتصف النهار في الجزء العلوي من الرسم البياني</string>
<string name="pref_dashboard_widget_today_upside_down_title">منتصف الليل في الأسفل</string>
<string name="pref_title_bottom_navigation_bar">شريط التنقل السفلي</string>
<string name="pref_summary_bottom_navigation_bar_on">قم بالتبديل بين الشاشات الرئيسية باستخدام شريط التنقل أو التمرير الأفقي</string>
<string name="sleepasandroid_settings">نم كالأندرويد</string>
<string name="pref_sleepasandroid_enable_summary">تمكين تكامل Sleep As Android</string>
<string name="alarm_slot_reset">تم ضبط فتحة التنبيه على الوضع الافتراضي</string>
<string name="pref_sleepasandroid_feat_heartrate">معدل ضربات القلب</string>
<string name="pref_sleepasandroid_device_title">جهاز المزود</string>
<string name="pref_sleepasandroid_device_summary">حدد الجهاز كمزود بيانات Sleep As Android</string>
<string name="pref_sleepasandroid_features_title">المميزات</string>
<string name="pref_sleepasandroid_features_summary">يختلف الدعم من جهاز إلى جهاز</string>
<string name="pref_sleepasandroid_feat_alarms">إنذار</string>
<string name="pref_sleepasandroid_slot_title">فتحة الإشعارات</string>
<string name="pref_sleepasandroid_slot_summary">ما هي فتحة التنبيه التي يجب استخدامها عند ضبط الإشعارات</string>
<string name="pref_sleepasandroid_feat_notifications">الإشعارات</string>
<string name="pref_sleepasandroid_feat_movement">مقياس التسارع</string>
<string name="pref_sleepasandroid_feat_oximetry">المقاييس</string>
<string name="pref_sleepasandroid_feat_spo2">SPO2</string>
<string name="pref_title_huawei_account">حساب هواوي</string>
<string name="pref_summary_huawei_account">حساب هواوي المستخدم في عملية الاقتران. يسمح إعداده بالاقتران دون إعادة ضبط المصنع.</string>
<string name="serbian">الصربية</string>
<string name="watchface_resolution_doesnt_match">دقة وجه الساعة لا تتطابق مع شاشة الجهاز. واجهة الساعة هي %1$s شاشة الجهاز هي %2$s</string>
<string name="cyclingPowerMax">أقصى قوة ركوب الدراجة</string>
<string name="cyclingPowerAverage">متوسط قوة ركوب الدراجة</string>
<string name="cyclingPowerMin">الحد الأدنى من قوة ركوب الدراجة</string>
</resources>

View File

@ -768,7 +768,7 @@
<string name="prefs_find_phone_summary">Verwende dein Band, um den Klingelton deines Telefons wiederzugeben.</string>
<string name="prefs_find_phone_duration">Klingeldauer in Sekunden</string>
<string name="maximum_duration">Dauer</string>
<string name="discovery_need_to_enter_authkey">Dieses Gerät benötigt einen geheimen Authentifikationsschlüssel, den du durch langes Drücken auf den Gerätnamen eingeben kannst. Genaueres im Wiki.</string>
<string name="discovery_need_to_enter_authkey">Dieses Gerät benötigt einen geheimen Authentifikationsschlüssel, den du durch langes Drücken auf den Gerätnamen eingeben kannst. Mehr Informationen gibt es auf der Gadgetbride-Webseite.</string>
<string name="fw_upgrade_notice_amazfitbip_lite">Du bist dabei, die Firmware %s auf deine Amazfit Bip Lite zu installieren.
\n
\nBitte stelle sicher, dass du die .fw Datei und danach die .res Datei installierst. Deine Uhr wird nach der Installation der .fw Datei neu gestartet.
@ -915,7 +915,7 @@
<string name="about_description_generic">Cloudloser freier Ersatz für proprietäre Android-Gadget-Apps der Hersteller.</string>
<string name="about_activity_title_generic">Über Gadgetbridge</string>
<string name="about_title">Über</string>
<string name="pref_title_weather_summary">Wird für den LineageOS Wetterdienst genutzt, andere Android-Versionen müssen eine Anwendung wie Weather notification nutzen. Mehr Informationen gibt es im Gadgetbride-Wiki.</string>
<string name="pref_title_weather_summary">Wird für den LineageOS Wetterdienst genutzt, andere Android-Versionen müssen eine Anwendung (wie Breezy Weather) nutzen. Mehr Informationen gibt es auf der Gadgetbride-Webseite.</string>
<string name="menuitem_worldclock">Weltzeituhr</string>
<string name="error_version_check_extreme_caution">ACHTUNG: Fehler beim Prüfen der Information zur Version! Du solltest nicht fortfahren! Versionsname \"%s\" gefunden</string>
<string name="permission_granting_mandatory">Alle Berechtigungen sind notwendig und es kann zu Problemen führen, wenn sie nicht genehmigt werden</string>
@ -1221,7 +1221,7 @@
\nHinweis: Du musst .res nicht installieren, wenn es genau die gleiche ist, wie die zuvor installierte.
\n
\nINSTALLATION AUF EIGENE GEFAHR!</string>
<string name="fossil_hr_commute_actions_explanation">Die hier konfigurierten Aktionen werden in der Commute-App auf deiner Uhr angezeigt. Lies das Wiki, um Informationen zum Umgang mit den durch diese Aktionen erzeugten Vorgaben zu erhalten.</string>
<string name="fossil_hr_commute_actions_explanation">Die hier konfigurierten Aktionen werden in der Commute-App auf deiner Uhr angezeigt. Mehr Informationen gibt es auf der Gadgetbride-Webseite.</string>
<string name="kind_agps_bundle">AGPS-Bundle</string>
<string name="qhybrid_calibration_100_steps">100 Schritte</string>
<string name="qhybrid_calibration_10_steps">10 Schritte</string>
@ -1727,7 +1727,7 @@
<string name="controlcenter_toggle_details">Details anzeigen</string>
<string name="controlcenter_connected_fraction">Verbunden: %d/%d</string>
<string name="ukranian">Ukrainisch</string>
<string name="info_no_devices_connected">keine Geräte verbunden</string>
<string name="info_no_devices_connected">Keine Geräte verbunden</string>
<string name="info_connected_count">%d Geräte verbunden</string>
<string name="estonian">Estnisch</string>
<string name="extended_ascii">Erweitertes ASCII</string>
@ -1775,7 +1775,7 @@
<string name="open_fw_installer_connect_minimum_one_device">Bitte verbinde MINDESTENS EIN Gerät, an das du die Datei senden möchtest.</string>
<string name="open_fw_installer_connect_maximum_one_device">Bitte verbinde NUR EIN Gerät, an das du die Datei senden möchtest.</string>
<string name="open_fw_installer_ensure_device_connected">Stelle sicher, dass das Gerät %s angeschlossen ist</string>
<string name="open_fw_installer_info_text">Mit dem Firmware/Watchface/App/File Installer kannst du unterstützte Dateien (Firmware, Zifferblätter, Anwendungen, GPS, Ressourcen, Schriftarten...) auf das Gerät hochladen/installieren. Weitere Informationen findest du im Wiki: https://codeberg.org/Freeyourgadget/Gadgetbridge/wiki/Firmware-Update</string>
<string name="open_fw_installer_info_text">Mit dem Firmware/Watchface/App/File Installer kannst du unterstützte Dateien (Firmware, Zifferblätter, Anwendungen, GPS, Ressourcen, Schriftarten...) auf das Gerät hochladen/installieren. Mehr Informationen gibt es auf der Gadgetbride-Webseite.</string>
<string name="open_fw_installer_getting_files_text">Da wir die Firmware-Dateien nicht verteilen dürfen, musst du dir die Dateien selbst beschaffen. Das bedeutet, dass du nach den Dateien in apk-Dateien, online, in Foren, auf Amazfitwatchfaces (für Miband/Amazfit-Geräte) und so weiter suchen musst.</string>
<string name="appmanager_item_outdated">(veraltet)</string>
<string name="pref_title_banglejs_txt_bitmap_size">Größe der Text-Bitmaps</string>
@ -2119,13 +2119,13 @@
<string name="devicetype_galaxybuds_2_pro">Galaxy Buds2 Pro</string>
<string name="devicetype_soflow_s06">SoFlow SO6</string>
<string name="pref_title_lock_unlock">Sperren</string>
<string name="pref_header_intent_api">Intent API</string>
<string name="pref_header_intent_api">Intent-API</string>
<string name="pref_agps_update_time">AGPS Aktualisierungszeit</string>
<string name="pref_agps_expire_time">AGPS Ablaufzeit</string>
<string name="intent_api_allow_activity_sync_summary">Auslösen der Aktivitätssynchronisierung über die Intent API erlauben</string>
<string name="intent_api_allow_activity_sync_summary">Auslösen der Aktivitätssynchronisierung über die Intent-API erlauben</string>
<string name="intent_api_allow_activity_sync_title">Aktivitätssynchronisierungsauslöser zulassen</string>
<string name="sony_ambient_sound_control_button_modes">Tastenmodi für die Steuerung von Umgebungsgeräuschen</string>
<string name="intent_api_allow_trigger_export_summary">Datenbankexport über die Intent API erlauben</string>
<string name="intent_api_allow_trigger_export_summary">Datenbankexport über die Intent-API erlauben</string>
<string name="intent_api_broadcast_export_summary">Einen Intent via Broadcast verschicken, wenn der Datenbankexport abgeschlossen ist</string>
<string name="pref_workout_keep_screen_on_title">Bildschirm während des Trainings eingeschaltet lassen</string>
<string name="pref_workout_keep_screen_on_summary">Der Bildschirm bleibt während des Trainings eingeschaltet und die Helligkeit wird angepasst, um die Trainingsdaten in Echtzeit anzuzeigen</string>
@ -2849,4 +2849,122 @@
<string name="devicetype_huawei_watchultimate">Huawei Watch Ultimate</string>
<string name="devicetype_huawei_watchgt4">Huawei Watch GT 4</string>
<string name="busy_task_fetch_sports_details_interrupted">Das Abrufen von Sportdaten wurde unterbrochen</string>
<string name="companion_pairing_request_title">Begleitendes Gerät</string>
<string name="unbind_before_pair_title">Bereits gebunden</string>
<string name="companion_pairing_request_description">Koppelst du dieses Gerät als Begleiter?
\n
\nDies wird für einige Funktionen empfohlen, z. B. für die Gerätesuche, und bietet eine bessere Verbindung.</string>
<string name="unbind_before_pair_message">Dieses Gerät ist bereits in den Android-Einstellungen gebunden, was dazu führen kann, dass die Kopplung bei einigen Geräten fehlschlägt.
\n
\nWenn das Hinzufügen des Geräts fehlschlägt, entferne es bitte in den Android-Einstellungen und versuche es erneut.</string>
<string name="devicetype_scannable">Scannbares Gerät</string>
<string name="state_scanned">Gescannt</string>
<string name="devicesetting_scannable_minimum_unseen">Minimale ungesehene Zeit (Sekunden)</string>
<string name="devicesetting_scannable_rssi">Minimaler RSSI-Schwellenwert</string>
<string name="devicesetting_scannable_debounce_summary">Nach dem Scannen bleibt das Gerät als gescannt und wird für die angegebene Zeitspanne ignoriert</string>
<string name="devicesetting_scannable_minimum_unseen_summary">Nach dem Scannen muss das Gerät für diese Zeitspanne unsichtbar sein, bevor es erneut registriert wird</string>
<string name="devicesetting_scannable_rssi_summary">Der minimale RSSI-Schwellenwert für die Erkennung</string>
<string name="devicesetting_scannable_debounce">Zeitüberschreitung der abtastbaren Entprellung (Sekunden)</string>
<string name="stepRateSum">Summe der Schrittgeschwindigkeit</string>
<string name="stepRateAvg">Durchschnittliche Schrittfrequenz</string>
<string name="stepLengthAvg">Durchschnittliche Schrittlänge</string>
<string name="groundContactTimeAvg">Durchschnittliche Bodenkontaktzeit</string>
<string name="impactAvg">Durchschnittliche Auswirkungen</string>
<string name="impactMax">Maximale Wirkung</string>
<string name="swingAngleAvg">Durchschnittlicher Schwenkwinkel</string>
<string name="foreFootLandings">Landungen mit dem Vorderfuß</string>
<string name="eversionAngleAvg">Durchschnittlicher Eversionswinkel</string>
<string name="eversionAngleMax">Maximaler Eversionswinkel</string>
<string name="unknownDataEncountered">Unbekannte Daten gefunden</string>
<string name="milliseconds">Millisekunden</string>
<string name="degrees">Grad</string>
<string name="swolfAvg">Mittlerer Swolf</string>
<string name="swolfMax">Maximaler Swolf</string>
<string name="swolfMin">Minimaler Swolf</string>
<string name="backFootLandings">Landungen mit dem Fußrücken</string>
<string name="midFootLandings">Landungen mit dem Mittelfuß</string>
<string name="pref_force_enable_spo2_support">SpO2-Unterstützung erzwingen</string>
<string name="pref_force_enable_heartrate_support">Unterstützung der Herzfrequenz erzwingen</string>
<string name="pref_force_enable_spo2_support_summary">Erzwinge die Aktivierung der SpO2-Unterstützung.
\nVERWENDUNG AUF EIGENE GEFAHR</string>
<string name="pref_force_enable_heartrate_support_summary">Erzwinge die Herzfrequenzunterstützung.
\nVERWENDUNG AUF EIGENE GEFAHR</string>
<string name="error_showing_changelog">Fehler bei der Anzeige des Changelogs</string>
<string name="pref_dashboard_widget_goals_chart_title">Zieltabelle</string>
<string name="pref_dashboard_all_devices_title">Alle Geräte</string>
<string name="pref_dashboard_widgets_order_summary">Wähle, welche Widgets aktiviert sind und in welcher Reihenfolge sie auf dem Dashboard angezeigt werden</string>
<string name="pref_dashboard_widget_today_24h_summary">Zeige die Aktivität in einem einzelnen 24-Stunden-Kreis anstelle eines doppelten 12-Stunden-Kreis</string>
<string name="pref_dashboard_widget_double_size_summary">Erlaube dem Widget, zwei Spalten auf dem Dashboard einzunehmen</string>
<string name="pref_dashboard_widget_show_legend_summary">Eine Legende unterhalb des Widgets anzeigen, welche die Farben erklärt</string>
<string name="pref_dashboard_widget_today_hr_interval_title">Herzfrequenz-Intervall</string>
<string name="activity_type_worn">Getragen</string>
<string name="dashboard_settings">Dashboard-Einstellungen</string>
<string name="bottom_nav_dashboard">Dashboard</string>
<string name="bottom_nav_devices">Geräte</string>
<string name="pref_dashboard_first_title">Dashboard zuerst anzeigen</string>
<string name="pref_dashboard_first_summary">Zeige beim Start von Gadgetbridge das Dashboard anstelle des Gerätebildschirms an</string>
<string name="pref_dashboard_cards_title">Widgets auf Karten anzeigen</string>
<string name="pref_dashboard_widget_today_hr_interval_summary">Die Anzahl der Minuten, die das Diagramm nach jeder erfolgreichen Herzfrequenzmessung \"Getragen\" anzeigt</string>
<string name="pref_dashboard_cards_summary">Zeichne Karten um die Widgets auf dem Dashboard</string>
<string name="pref_dashboard_widget_settings">Widget-Einstellungen</string>
<string name="pref_dashboard_widget_today_title">Tätigkeitstabelle</string>
<string name="pref_dashboard_widget_today_24h_title">24h-Modus</string>
<string name="pref_dashboard_widget_double_size_title">Doppelte Größe</string>
<string name="pref_dashboard_widget_show_legend_title">Legende anzeigen</string>
<string name="pref_dashboard_select_devices_title">Geräte auswählen...</string>
<string name="pref_dashboard_all_devices_summary">Kombiniere Aktivitätsdaten von allen hinzugefügten Geräten für die Gesamtzahlen auf dem Dashboard</string>
<string name="pref_dashboard_select_devices_summary">Kombiniere Aktivitätsdaten von bestimmten Geräten für die Gesamtzahlen auf dem Dashboard</string>
<string name="fmtPaceDistance">Tempo %d Entfernung</string>
<string name="pref_auto_reply_calls_delay_title">Automatische Antwortverzögerung</string>
<string name="pref_auto_reply_calls_delay_summary">Anzahl der Sekunden, nach denen der Anruf automatisch entgegengenommen wird</string>
<string name="pref_auto_reply_calls_title">Telefonanrufe automatisch annehmen</string>
<string name="pref_auto_reply_calls_summary">Das Telefon nimmt eingehende Telefonanrufe automatisch entgegen</string>
<string name="pref_dashboard_devices_to_include">Einzubeziehende Geräte</string>
<string name="RunningForm">Art der Durchführung</string>
<string name="pref_header_audio">Audio</string>
<string name="pref_header_generic">Allgemein</string>
<string name="pref_title_notification_wake_on_open">Automatisches Aufwachen und Entsperren</string>
<string name="pref_summary_notification_wake_on_open">Wecken und Entsperren des Android-Geräts, wenn das Gadget eine OPEN-Antwort zurücksendet. Es muss sich in einem vertrauenswürdigen Zustand befinden.</string>
<string name="fmtPaceType">Tempo %d Typ</string>
<string name="fmtPacePace">Tempo %d Tempo</string>
<string name="fmtPaceCorrection">Tempo %d Korrektur</string>
<string name="fmtPaceTypeAverage">Tempo-Typ %d Durchschnitt</string>
<string name="Pace">Tempo</string>
<string name="widget_name_colored_tile">%1$s (farbige Kachel)</string>
<string name="armenian">Armenisch</string>
<string name="widget_layout_top_wide_bot_large">Oben weit, unten groß</string>
<string name="widget_name_untitled">Unbenanntes Widget (%1$s)</string>
<string name="pref_speak_notifications_aloud_summary">Benachrichtigungen werden über die Kopfhörer vorgelesen</string>
<string name="pref_speak_notifications_aloud_title">Lautes Sprechen von Benachrichtigungen</string>
<string name="pref_header_calls_and_notifications">Anrufe und Benachrichtigungen</string>
<string name="devicetype_redmi_watch_4">Redmi Watch 4</string>
<string name="widget_layout_top_large_bot_wide">Oben groß, unten weit</string>
<string name="pref_summary_bottom_navigation_bar_off">Wechseln zwischen den Hauptbildschirmen nur durch horizontales Wischen</string>
<string name="pref_title_bottom_navigation_bar">Untere Navigationsleiste</string>
<string name="pref_summary_bottom_navigation_bar_on">Wechsle zwischen den Hauptbildschirmen mit der Navigationsleiste oder durch horizontales Wischen</string>
<string name="pref_dashboard_widget_today_upside_down_title">Mitternacht ist unten</string>
<string name="pref_dashboard_widget_today_upside_down_summary">Im 24-Stunden-Modus zeichne Mitternacht unten und Mittag oben im Diagramm</string>
<string name="pref_sleepasandroid_device_title">Auszuwählendes Gerät</string>
<string name="pref_sleepasandroid_device_summary">Gerät als Sleep as Android-Datenanbieter auswählen</string>
<string name="pref_sleepasandroid_features_summary">Die Unterstützung ist von Gerät zu Gerät unterschiedlich</string>
<string name="pref_sleepasandroid_feat_alarms">Alarme</string>
<string name="alarm_slot_reset">Der Alarm-Platz wurde auf Standard eingestellt</string>
<string name="pref_sleepasandroid_feat_notifications">Benachrichtigungen</string>
<string name="pref_sleepasandroid_feat_movement">Beschleunigungssensor</string>
<string name="pref_sleepasandroid_feat_heartrate">Herzfrequenz</string>
<string name="pref_sleepasandroid_feat_spo2">SpO2</string>
<string name="sleepasandroid_settings">Sleep as Android</string>
<string name="pref_sleepasandroid_enable_summary">Aktiviere die Integration von Sleep as Android</string>
<string name="pref_sleepasandroid_features_title">Eigenschaften</string>
<string name="pref_sleepasandroid_slot_title">Alarm-Platz</string>
<string name="pref_sleepasandroid_slot_summary">Welcher Alarm-Platz beim Einstellen von Alarmen zu verwenden ist</string>
<string name="pref_sleepasandroid_feat_oximetry">Oximetrie</string>
<string name="pref_title_huawei_account">Huawei Account</string>
<string name="pref_summary_huawei_account">Huawei-Account, welcher für den Kopplungsprozess verwendet wird. Die Einstellung ermöglicht die Kopplung ohne Werksreset.</string>
<string name="serbian">Serbisch</string>
<string name="watchface_resolution_doesnt_match">Die Auflösung des Watchface stimmt nicht mit dem Bildschirm des Geräts überein. Watchface ist %1$s Gerätebildschirm ist %2$s</string>
<string name="cyclingPowerMin">Minimale Leistung beim Radfahren</string>
<string name="cyclingPowerMax">Maximale Leistung beim Radfahren</string>
<string name="cyclingPowerAverage">Durchschnittliche Leistung beim Radfahren</string>
<string name="devicetype_huawei_watchfit2">Huawei Watch Fit 2</string>
</resources>

View File

@ -1766,7 +1766,7 @@
<string name="sony_ambient_sound_control_button_modes">Modos del botón de control de sonido ambiente</string>
<string name="sony_ambient_sound_control_button_mode_nc_as_off">Cancelación de ruido, sonido ambiente, apagado</string>
<string name="sony_ambient_sound_control_button_mode_as_off">Sonido ambiente, apagado</string>
<string name="info_no_devices_connected">no hay dispositivos conectados</string>
<string name="info_no_devices_connected">Ningún dispositivo conectado</string>
<string name="controlcenter_set_folder_title">Establecer o crear una nueva carpeta</string>
<string name="autoconnect_from_device_summary">Establecer una conexión cuando ésta es iniciada por un dispositivo, como los auriculares</string>
<string name="activity_prefs_allow_bluetooth_intent_api">API Intent de Bluetooth</string>
@ -2844,4 +2844,122 @@
<string name="devicetype_huawei_watchgt4">Huawei Watch GT 4</string>
<string name="devicetype_huawei_watchultimate">Huawei Watch Ultimate</string>
<string name="busy_task_fetch_sports_details_interrupted">Se interrumpió la búsqueda de los detalles deportivos</string>
<string name="unbind_before_pair_message">Este dispositivo ya está vinculado en los ajustes de Android, lo que puede hacer que el emparejamiento falle en algunos dispositivos.
\n
\nSi no se puede añadir el dispositivo, elimínelo de los ajustes de Android y vuelva a intentarlo.</string>
<string name="companion_pairing_request_title">Dispositivo complementario</string>
<string name="companion_pairing_request_description">¿Empareje este dispositivo como complementario?
\n
\nSe recomienda para algunas funciones, como buscar dispositivo, y proporciona una mejor conexión.</string>
<string name="unbind_before_pair_title">Ya vinculado</string>
<string name="devicesetting_scannable_rssi">Umbral mínimo de RSSI</string>
<string name="devicesetting_scannable_minimum_unseen_summary">Después de ser escaneado, el dispositivo debe permanecer oculto durante este tiempo antes de ser registrado de nuevo</string>
<string name="devicesetting_scannable_rssi_summary">El umbral RSSI mínimo para la detección</string>
<string name="devicesetting_scannable_debounce">Tiempo de espera para volver a escanear (segundos)</string>
<string name="devicetype_scannable">Dispositivo escaneable</string>
<string name="state_scanned">Escaneado</string>
<string name="devicesetting_scannable_debounce_summary">Después de ser escaneado, el dispositivo permanecerá como escaneado e ignorado durante el tiempo especificado</string>
<string name="devicesetting_scannable_minimum_unseen">Tiempo mínimo sin ser escaneado (segundos)</string>
<string name="swolfAvg">Promedio swolf</string>
<string name="swolfMax">Swolf máximo</string>
<string name="swolfMin">Swolf mínimo</string>
<string name="stepRateSum">Velocidad total de pasos</string>
<string name="stepRateAvg">Frecuencia media del paso</string>
<string name="stepLengthAvg">Longitud media de los pasos</string>
<string name="groundContactTimeAvg">Tiempo medio de la pisada</string>
<string name="impactAvg">Promedio de la pisada</string>
<string name="impactMax">Pisada máxima</string>
<string name="swingAngleAvg">Ángulo promedio de giro</string>
<string name="foreFootLandings">Pisadas con el antepié</string>
<string name="midFootLandings">Pisadas con el mediopié</string>
<string name="backFootLandings">Pisadas con el retropié</string>
<string name="eversionAngleAvg">Angulo medio de la eversión</string>
<string name="eversionAngleMax">Angulo máximo de la eversión</string>
<string name="fmtPaceDistance">Ritmo %d distancia</string>
<string name="fmtPaceType">Tipo %d ritmo</string>
<string name="fmtPacePace">Ritmo %d</string>
<string name="fmtPaceCorrection">Corrección del ritmo %d</string>
<string name="fmtPaceTypeAverage">Tipo de ritmo %d medio</string>
<string name="unknownDataEncountered">Se encontraron datos desconocidos</string>
<string name="milliseconds">milisegundos</string>
<string name="degrees">grados</string>
<string name="RunningForm">Forma de ejecución</string>
<string name="Pace">Ritmo</string>
<string name="pref_force_enable_heartrate_support">Forzar soporte de frecuencia cardíaca</string>
<string name="pref_force_enable_heartrate_support_summary">Forzar habilitar el soporte de frecuencia cardíaca.
\nÚSELO BAJO SU PROPIO RIESGO</string>
<string name="pref_force_enable_spo2_support">Forzar el soporte de SpO2</string>
<string name="pref_force_enable_spo2_support_summary">Forzar la habilitación del soporte de SpO2.
\nÚSELO BAJO SU PROPIO RIESGO</string>
<string name="error_showing_changelog">Error al mostrar el registro de cambios</string>
<string name="dashboard_settings">Ajustes del panel de control</string>
<string name="bottom_nav_dashboard">Panel de control</string>
<string name="bottom_nav_devices">Dispositivos</string>
<string name="pref_dashboard_first_title">Mostrar primero el panel de control</string>
<string name="pref_dashboard_first_summary">Mostrar el panel de control cuando se inicia Gadgetbridge, en lugar de la pantalla de dispositivos</string>
<string name="pref_dashboard_cards_title">Mostrar widgets en las tarjetas</string>
<string name="pref_dashboard_cards_summary">Dibujar tarjetas alrededor de los widgets del panel de control</string>
<string name="pref_dashboard_widget_settings">Ajustes del widget</string>
<string name="pref_dashboard_widget_today_title">Gráfico de actividad</string>
<string name="pref_dashboard_widget_today_24h_title">Modo 24h</string>
<string name="pref_dashboard_widget_double_size_title">Tamaño doble</string>
<string name="pref_dashboard_widget_show_legend_title">Mostrar leyenda</string>
<string name="pref_dashboard_widget_goals_chart_title">Gráfico de objetivos</string>
<string name="pref_dashboard_devices_to_include">Dispositivos a incluir</string>
<string name="pref_dashboard_all_devices_title">Todos los dispositivos</string>
<string name="pref_dashboard_select_devices_title">Selecciona los dispositivos...</string>
<string name="pref_dashboard_widgets_order_summary">Seleccione qué widgets están activados y en qué orden se muestran en el panel de control</string>
<string name="pref_dashboard_widget_today_24h_summary">Mostrar la actividad en un único círculo de 24h en lugar de un círculo doble de 12h</string>
<string name="pref_dashboard_widget_double_size_summary">Permitir que el widget ocupe dos columnas en el panel de control</string>
<string name="pref_dashboard_widget_show_legend_summary">Mostrar una leyenda debajo del widget explicando los colores</string>
<string name="pref_dashboard_all_devices_summary">Combinar los datos de la actividad de todos los dispositivos añadidos para los totales del panel de control</string>
<string name="pref_dashboard_select_devices_summary">Combinar los datos de actividad de dispositivos específicos para los totales del panel de control</string>
<string name="pref_dashboard_widget_today_hr_interval_title">Intervalo de frecuencia cardíaca</string>
<string name="activity_type_worn">Usada</string>
<string name="pref_dashboard_widget_today_hr_interval_summary">La cantidad de minutos que el gráfico muestra \"usado\" después de cada medición correcta de la frecuencia cardíaca</string>
<string name="pref_auto_reply_calls_summary">El teléfono descolgará automáticamente las llamadas entrantes</string>
<string name="pref_auto_reply_calls_delay_summary">Número de segundos tras los cuales se descuelga automáticamente la llamada</string>
<string name="pref_auto_reply_calls_title">Responder automáticamente a las llamadas</string>
<string name="pref_auto_reply_calls_delay_title">Retraso automático en la respuesta</string>
<string name="pref_header_audio">Audio</string>
<string name="pref_header_generic">Genérico</string>
<string name="pref_summary_notification_wake_on_open">Despierta y desbloquea el dispositivo Android cuando el gadget envía una respuesta ABIERTO de vuelta. Debe estar en un estado de confianza.</string>
<string name="pref_title_notification_wake_on_open">Despertador y desbloqueo automáticos</string>
<string name="armenian">armenio</string>
<string name="widget_layout_top_wide_bot_large">Ancho arriba, grande abajo</string>
<string name="widget_layout_top_large_bot_wide">Grande arriba, ancho abajo</string>
<string name="pref_speak_notifications_aloud_summary">Las notificaciones se leerán en voz alta a través de los auriculares</string>
<string name="pref_speak_notifications_aloud_title">Decir las notificaciones con volumen alto</string>
<string name="pref_header_calls_and_notifications">llamadas y notificaciones</string>
<string name="pref_title_bottom_navigation_bar">Barra de navegación inferior</string>
<string name="pref_summary_bottom_navigation_bar_off">Cambiar entre pantallas principales solo deslizando el dedo horizontalmente</string>
<string name="widget_name_colored_tile">%1$s (mosaico de color)</string>
<string name="widget_name_untitled">Widget sin título ( %1$s )</string>
<string name="pref_summary_bottom_navigation_bar_on">Cambiar entre pantallas principales usando la barra de navegación o deslizando el dedo horizontalmente</string>
<string name="devicetype_redmi_watch_4">Redmi Watch 4</string>
<string name="pref_dashboard_widget_today_upside_down_title">Medianoche en el fondo</string>
<string name="pref_dashboard_widget_today_upside_down_summary">En el modo 24h, dibuje la medianoche en la parte inferior y el mediodía en la parte superior del gráfico</string>
<string name="sleepasandroid_settings">Dormir como Android</string>
<string name="pref_sleepasandroid_enable_summary">Habilitar la integración de Sleep As Android</string>
<string name="pref_sleepasandroid_device_summary">Seleccione el dispositivo como proveedor de datos de Sleep As Android</string>
<string name="pref_sleepasandroid_slot_summary">¿Qué espacio para la alarma se debe utilizar al configurar las alarmas?</string>
<string name="pref_sleepasandroid_feat_oximetry">oximetria</string>
<string name="pref_sleepasandroid_device_title">Dispositivo del proveedor</string>
<string name="pref_sleepasandroid_features_title">Características</string>
<string name="pref_sleepasandroid_features_summary">La compatibilidad varía de un dispositivo a otro</string>
<string name="pref_sleepasandroid_feat_alarms">Alarmas</string>
<string name="alarm_slot_reset">El espacio de la alarma se ha ajustado por defecto</string>
<string name="pref_sleepasandroid_slot_title">Espacio de alarmas</string>
<string name="pref_sleepasandroid_feat_notifications">Notificaciones</string>
<string name="pref_sleepasandroid_feat_movement">Acelerómetro</string>
<string name="pref_sleepasandroid_feat_heartrate">Frecuencia cardíaca</string>
<string name="pref_sleepasandroid_feat_spo2">SPO2</string>
<string name="pref_title_huawei_account">Cuenta Huawei</string>
<string name="pref_summary_huawei_account">Cuenta de Huawei utilizada en el proceso de emparejamiento. Configurarlo permite el emparejamiento sin restablecimiento de fábrica.</string>
<string name="serbian">Serbio</string>
<string name="watchface_resolution_doesnt_match">La resolución de Watchface no coincide con la pantalla del dispositivo. Watchface es %1$s la pantalla del dispositivo es %2$s</string>
<string name="cyclingPowerMin">Potencia mínima del ciclo</string>
<string name="devicetype_huawei_watchfit2">Huawei Watch Fit 2</string>
<string name="cyclingPowerAverage">Potencia media de ciclo</string>
<string name="cyclingPowerMax">Potencia máxima del ciclo</string>
</resources>

View File

@ -2764,4 +2764,134 @@
<string name="pref_enable_call_accept">הפעלת קבלת שיחות</string>
<string name="pref_heartrate_automatic_enable">הפעלת מדידת דופק אוטומטית</string>
<string name="activity_type_roller_skating">החלקה על גלגיליות</string>
<string name="devicetype_nothing_cmf_watch_pro">CMF Watch Pro</string>
<string name="devicetype_nothingear2">Nothing Ear (2)</string>
<string name="pref_header_sony_sound_control">בקרת שמע</string>
<string name="pref_wide_area_tap_title">טפיחה באזור רחב</string>
<string name="devicetype_nothingearstick">Nothing Ear (Stick)</string>
<string name="prefs_active_noise_cancelling_transparency">שקיפות</string>
<string name="degrees">מעלות</string>
<string name="Pace">צעד</string>
<string name="RunningForm">צורת ריצה</string>
<string name="pref_wide_area_tap_summary">זיהוי טפיחות בין הלחיים והאוזניים</string>
<string name="pref_force_enable_heartrate_support_summary">אילוץ הפעלת תמיכה בדופק.
\nעל אחריותך בלבד</string>
<string name="pref_force_enable_spo2_support">אילוץ תמיכה במדידת חמצן</string>
<string name="unbind_before_pair_title">כבר מאוגד</string>
<string name="pref_force_enable_heartrate_support">אילוץ תמיכה בדופק</string>
<string name="pref_force_enable_spo2_support_summary">אילוץ תמיכה במדידת חמצן בדם.
\nלשימוש על אחריותך בלבד</string>
<string name="state_scanned">נסרק</string>
<string name="weeksleepchart_sleep_a_week_or_month">שינה בשבוע/חודש</string>
<string name="pref_header_audio">שמע</string>
<string name="weekstepschart_steps_a_week_or_month">צעדים לשבוע/חודש</string>
<string name="busy_task_fetch_sports_details_interrupted">משיכת פרטי הספורט נקטעה</string>
<string name="fw_upgrade_notice_amazfitbip3">פעולה זו תתקין את הקושחה %s על ה־Amazfit Bip 3 שלך.
\n
\nנא לוודא את התקנת קושחת ה־‎.fw בהתחלה, לאחר מכן את קובץ ה־‎.res השעון שלך יופעל מחדש לאחר התקנת קובץ ה־fw.
\n
\nלתשומת לבך: אין צורך בהתקנת קובץ ה־‎.res אם הוא כבר זהה לזה שהתקנת בעבר.
\n
\nהמשך התהליך הוא על אחריותך!</string>
<string name="pref_header_generic">גנרי</string>
<string name="pref_title_notification_wake_on_open">התעוררות ושחרור נעילה אוטומטיים</string>
<string name="pref_summary_notification_wake_on_open">להעיר ולשחרר את הנעילה של מכשיר ה־Android כשההתקן שולח תגובת פתיחה בחזרה. חייב להיות במצב אמין.</string>
<string name="pref_auto_reply_calls_delay_title">השהיית מענה אוטומטי</string>
<string name="pref_auto_reply_calls_delay_summary">מספר השניות שלאחריהן השיחה תתקבל אוטומטית</string>
<string name="pref_auto_reply_calls_title">לענות לשיחות טלפון אוטומטית</string>
<string name="pref_auto_reply_calls_summary">הטלפון יקבל שיחות נכנסות אוטומטית</string>
<string name="pref_dashboard_widget_today_hr_interval_title">משך דופק</string>
<string name="pref_dashboard_select_devices_summary">שילוב פעילות מהתקנים מסוימים לסיכומים של לוח הבקרה</string>
<string name="pref_dashboard_widget_today_hr_interval_summary">כמות הדקות שהתרשים מציג ‚נענד’ אחרי כל מדידת דופק מוצלחת</string>
<string name="devicetype_amazfit_active_edge">Amazfit Active Edge</string>
<string name="devicetype_amazfit_bip3">Amazfit Bip 3</string>
<string name="devicetype_huawei_watchgt4">Huawei Watch GT 4</string>
<string name="devicetype_huawei_watchultimate">Huawei Watch Ultimate</string>
<string name="sony_protocol_v2">גרסה 2</string>
<string name="sony_protocol_v1">גרסה 1</string>
<string name="companion_pairing_request_title">התקן ליווי</string>
<string name="zepp_os_watchface_the_ultima">האולטימה</string>
<string name="prefs_workmode">מצב עבודה</string>
<string name="devicetype_mijia_mho_c303">Mijia MHO-C303</string>
<string name="devicetype_sony_linkbuds">Sony LinkBuds</string>
<string name="zepp_os_watchface_lightning_flash">הבזק מהבהב</string>
<string name="zepp_os_watchface_free_combination">שילוב חופשי</string>
<string name="zepp_os_watchface_pure_white">לבן טהור</string>
<string name="devicetype_huawei_band8">Huawei Band 8</string>
<string name="zepp_os_watchface_starry_sky">ליל כוכבים</string>
<string name="devicetype_honor_band5">Honor Band 5</string>
<string name="devicetype_honor_band3">Honor Band 3</string>
<string name="devicetype_honor_band4">Honor Band 4</string>
<string name="sony_protocol_v3">גרסה 3</string>
<string name="devicetype_miband8active">Xiaomi Smart Band 8 Active</string>
<string name="devicetype_amazfit_balance">Amazfit Balance</string>
<string name="devicetype_colacao21">ColaCao 2021</string>
<string name="devicetype_colacao23">ColaCao 2023</string>
<string name="devicetype_huawei_band_aw70">Huawei Band (AW70)</string>
<string name="devicetype_huawei_band6">Huawei Band 6</string>
<string name="devicetype_huawei_band7">Huawei Band 7</string>
<string name="devicetype_redmi_watch_4">Redmi Watch 4</string>
<string name="zepp_os_watchface_vast_sky">שמיים פרוסים</string>
<string name="zepp_os_watchface_guider">מנחה</string>
<string name="flatDistance">מרחק במישור</string>
<string name="huawei_trusleep_title">HUAWEI TruSleep ™‎</string>
<string name="widget_layout_top_wide_bot_large">רחב למעלה, גדול למטה</string>
<string name="widget_layout_top_large_bot_wide">גדול למעלה, רחב למטה</string>
<string name="widget_name_colored_tile">%1$s (אריח צבעוני)</string>
<string name="widget_name_untitled">וידג׳ט ללא שם (%1$s)</string>
<string name="pref_force_connection_type_ble">בלוטות׳ LE (אנרגיה נמוכה)</string>
<string name="devicetype_honor_magicwatch2">Honor MagicWatch 2</string>
<string name="devicetype_amazfit_active">Amazfit Active</string>
<string name="devicetype_sony_wi_sp600n">Sony WI-SP600N</string>
<string name="devicetype_honor_band6">Honor Band 6</string>
<string name="devicetype_honor_band7">Honor Band 7</string>
<string name="protocol_version">גרסת פרוטוקול</string>
<string name="stepRateSum">סיכום קצב הצעדים</string>
<string name="stepRateAvg">קצב צעדים ממוצע</string>
<string name="stepLengthAvg">אורך צעד ממוצע</string>
<string name="groundContactTimeAvg">זמן מגע ממוצע עם הקרקע</string>
<string name="impactAvg">הלימה ממוצעת</string>
<string name="impactMax">הלימה מרבית</string>
<string name="swingAngleAvg">זווית הנפה ממוצעת</string>
<string name="unknownDataEncountered">התגלו נתונים לא מוכרים</string>
<string name="milliseconds">מילישניות</string>
<string name="bottom_nav_dashboard">לוח בקרה</string>
<string name="bottom_nav_devices">התקנים</string>
<string name="dashboard_settings">הגדרות לוח בקרה</string>
<string name="pref_dashboard_first_title">להציג את לוח הבקרה תחילה</string>
<string name="pref_dashboard_first_summary">להציג את לוח הבקרה עם הפעלת Gadgetbridge במקום את מסך ההתקנים</string>
<string name="pref_dashboard_widget_today_24h_title">מצב 24 שעות</string>
<string name="pref_dashboard_cards_title">הצגת וידג׳טים על הכרטיסים</string>
<string name="pref_dashboard_widget_today_title">תרשים פעילות</string>
<string name="pref_dashboard_widget_settings">הגדרות וידג׳ט</string>
<string name="pref_dashboard_cards_summary">ציור כרטיסים סביב הווידג׳טים בלוח הבקרה</string>
<string name="pref_dashboard_widget_show_legend_title">הצגת מקרא</string>
<string name="pref_dashboard_widget_double_size_title">גודל כפול</string>
<string name="pref_dashboard_devices_to_include">התקנים שיש לכלול</string>
<string name="pref_dashboard_widget_goals_chart_title">תרשים יעדים</string>
<string name="pref_dashboard_all_devices_summary">שילוב נתוני הפעילות מכל ההתקנים שנוספו לסיכומים שבלוח הבקרה</string>
<string name="pref_dashboard_widget_show_legend_summary">הצגת מקרא מתחת לווידג׳ט שמסביר את הצבעים</string>
<string name="devicesetting_scannable_minimum_unseen">זמן נתק מזערי (שניות)</string>
<string name="pref_dashboard_widget_today_24h_summary">להציג את הפעילות בעיגול אחיד של 24 שעות במקום שני עיגולים של 12 שעות</string>
<string name="activity_type_worn">נענד</string>
<string name="pref_dashboard_select_devices_title">בחירת התקנים…</string>
<string name="pref_dashboard_all_devices_title">כל ההתקנים</string>
<string name="pref_dashboard_widget_double_size_summary">לאפשר לווידג׳ט לתפוס שתי עמודות בלוח הבקרה</string>
<string name="error_showing_changelog">שגיאה בהצגת יומן השינויים</string>
<string name="devicesetting_scannable_rssi_summary">סף הקליטה המזערי לזיהוי</string>
<string name="devicesetting_scannable_rssi">סף קליטה מזערי</string>
<string name="devicesetting_scannable_minimum_unseen_summary">לאחר הסריקה, ההתקן צריך להיות בנתק למשך פרק הזמן שהוגדר לפני שיירשם שוב</string>
<string name="pref_dashboard_widgets_order_summary">נא לבחור אילו וידג׳טים יופעלו ובאיזה סדר יוצגו בלוח הבקרה</string>
<string name="pref_header_calls_and_notifications">שיחות והתראות</string>
<string name="pref_speak_notifications_aloud_title">הקראת התראות בקול רם</string>
<string name="pref_speak_notifications_aloud_summary">התראות תיקראנה בקול רם דרך האוזניות</string>
<string name="armenian">ארמנית</string>
<string name="pref_sleepasandroid_device_title">התקן ספק</string>
<string name="pref_sleepasandroid_features_summary">התמיכה משתנה מהתקן להתקן</string>
<string name="pref_sleepasandroid_feat_spo2">SpO2</string>
<string name="pref_sleepasandroid_feat_heartrate">דופק</string>
<string name="pref_sleepasandroid_feat_movement">מד תאוצה</string>
<string name="pref_sleepasandroid_feat_oximetry">מדידת חמצן</string>
<string name="pref_sleepasandroid_feat_notifications">הודעות</string>
<string name="pref_sleepasandroid_features_title">יכולות</string>
</resources>

File diff suppressed because it is too large Load Diff

View File

@ -1408,7 +1408,7 @@
<string name="sony_equalizer_preset_vocal">Vokal</string>
<string name="sony_anc_optimizer_status_wearing_condition">Mengukur kondisi pemakaian…</string>
<string name="pref_activity_recognize_running">mengenal berlari</string>
<string name="info_no_devices_connected">tidak ada perangkat terhubung</string>
<string name="info_no_devices_connected">Tidak ada perangkat yang terhubung</string>
<string name="info_connected_count">%d perangkat terhubung</string>
<string name="watchface_setting_light_up_on_notification">Nyalakan pada notifikasi baru</string>
<string name="connection_over_ble">Koneksi melalui BLE</string>
@ -2831,4 +2831,119 @@
<string name="busy_task_fetch_sports_details_interrupted">Pengambilan detail olahraga ditunda</string>
<string name="devicetype_huawei_watchgt4">Huawei Watch GT 4</string>
<string name="devicetype_huawei_watchultimate">Huawei Watch Ultimate</string>
<string name="companion_pairing_request_title">Perangkat pendamping</string>
<string name="companion_pairing_request_description">Sandingkan perangkat ini sebagai pendamping?
\n
\nIni disarankan untuk beberapa fungsi seperti cari perangkat, dan menyediakan koneksi yang lebih baik.</string>
<string name="unbind_before_pair_title">Sudah tersanding</string>
<string name="unbind_before_pair_message">Perangkat ini sudah disandingkan dalam pengaturan Android yang dapat membuat penyandingan gagal untuk beberapa perangkat.
\n
\nJika penambahan perangkat gagal, silakan hapus dari pengaturan Android dan coba lagi.</string>
<string name="devicesetting_scannable_debounce">Waktu habis penghilangan pemindaian (detik)</string>
<string name="devicesetting_scannable_rssi_summary">Ambang RSSI minimum untuk deteksi</string>
<string name="devicetype_scannable">Perangkat dapat dipindai</string>
<string name="state_scanned">Dipindai</string>
<string name="devicesetting_scannable_minimum_unseen">Waktu tidak terlihat minimum (detik)</string>
<string name="devicesetting_scannable_rssi">Ambang RSSI minimal</string>
<string name="devicesetting_scannable_debounce_summary">Setelah dipindai, perangkat akan ditetapkan sebagai dipindai dan diabaikan selama waktu yang sudah ditentukan</string>
<string name="devicesetting_scannable_minimum_unseen_summary">Setelah dipindai, perangkat harus tidak terlihat selama waktu ini sebelum didaftarkan lagi</string>
<string name="swolfAvg">Swolf rata-rata</string>
<string name="swolfMax">Swolf maksimum</string>
<string name="swolfMin">Swolf minimum</string>
<string name="stepRateSum">Jumlah laju langkah</string>
<string name="stepRateAvg">Laju langkah rata-rata</string>
<string name="stepLengthAvg">Panjang Langkah Rata-rata</string>
<string name="groundContactTimeAvg">Waktu kontak tanah rata-rata</string>
<string name="impactAvg">Dampak rata-rata</string>
<string name="impactMax">Dampak maksimum</string>
<string name="swingAngleAvg">Sudut ayunan rata-rata</string>
<string name="backFootLandings">Landasan kaki belakang</string>
<string name="eversionAngleAvg">Sudut eversi rata-rata</string>
<string name="eversionAngleMax">Sudut eversi maksimum</string>
<string name="fmtPaceDistance">Jarak laju %d</string>
<string name="fmtPaceType">Jenis laju %d</string>
<string name="fmtPacePace">Laju dalam laju %d</string>
<string name="fmtPaceCorrection">Koreksi laju %d</string>
<string name="fmtPaceTypeAverage">Rata-rata Jenis Laju %d</string>
<string name="unknownDataEncountered">Mendapatkan data tidak diketahui</string>
<string name="milliseconds">milidetik</string>
<string name="degrees">derajat</string>
<string name="Pace">Laju</string>
<string name="midFootLandings">Landasan kaki tengah</string>
<string name="foreFootLandings">Landasan kaki depan</string>
<string name="RunningForm">Bentuk Lari</string>
<string name="pref_force_enable_heartrate_support">Paksa dukungan detak jantung</string>
<string name="pref_force_enable_heartrate_support_summary">Paksa nengaktifkan dukungan detak jantung.
\n
\nGUNAKAN DENGAN RISIKO ANDA SENDIRI</string>
<string name="pref_force_enable_spo2_support">Paksa dukungan SpO2</string>
<string name="pref_force_enable_spo2_support_summary">Paksa mengaktifkan dukungan SpO2.
\nGUNAKAN DENGAN RISIKO ANDA SENDIRI</string>
<string name="activity_type_worn">Dipakai</string>
<string name="dashboard_settings">Pengaturan dasbor</string>
<string name="bottom_nav_devices">Perangkat</string>
<string name="pref_dashboard_first_title">Tampilkan dasbor terlebih dahulu</string>
<string name="pref_dashboard_first_summary">Tampilkan dasbor ketika Gadgetbridge dibuka, daripada layar perangkat</string>
<string name="pref_dashboard_cards_title">Tampilkan widget pada kartu</string>
<string name="pref_dashboard_widget_today_title">Bagan aktivitas</string>
<string name="pref_dashboard_widget_today_24h_title">Mode 24j</string>
<string name="pref_dashboard_widget_double_size_title">Ukuran ganda</string>
<string name="pref_dashboard_widget_show_legend_title">Tampilkan legenda</string>
<string name="pref_dashboard_widget_goals_chart_title">Bagan capaian</string>
<string name="pref_dashboard_devices_to_include">Perangkat untuk disertakan</string>
<string name="pref_dashboard_widget_today_24h_summary">Tampilkan aktivitas dalam lingkaran 24j daripada lingkaran 12j ganda</string>
<string name="pref_dashboard_widget_double_size_summary">Perbolehkan widget untuk memakai sampai dua kolom di dasbor</string>
<string name="pref_dashboard_widget_show_legend_summary">Tampilkan legenda di bawah widget menjelaskan warnanya</string>
<string name="pref_dashboard_all_devices_summary">Gabungkan data aktivitas dari semua perangkat yang ditambahkan untuk jumlah di dasbor</string>
<string name="pref_dashboard_widget_today_hr_interval_title">Interval detak jantung</string>
<string name="pref_dashboard_widget_today_hr_interval_summary">Jumlah menit bagan menampilkan \'dipakai\' setelah pengukuran detak jantung berhasil</string>
<string name="error_showing_changelog">Terjadi kesalahan menampilkan catatan perubahan</string>
<string name="bottom_nav_dashboard">Dasbor</string>
<string name="pref_dashboard_widget_settings">Pengaturan widget</string>
<string name="pref_dashboard_all_devices_title">Semua perangkat</string>
<string name="pref_dashboard_select_devices_title">Pilih perangkat...</string>
<string name="pref_dashboard_widgets_order_summary">Pilih widget apa saja yang diaktifkan dan dalam urutan yang ditampilkan di dasbor</string>
<string name="pref_dashboard_select_devices_summary">Gabungkan data aktivitas dari perangkat tertentu untuk jumlah di dasbor</string>
<string name="pref_dashboard_cards_summary">Gambar kartu di sekitar widget dalam dasbor</string>
<string name="pref_auto_reply_calls_summary">Ponsel akan mengangkat panggilan masuk secara otomatis</string>
<string name="pref_auto_reply_calls_title">Jawab panggilan telepon secara otomatis</string>
<string name="pref_auto_reply_calls_delay_summary">Detik setelah panggilan diambil secara otomatis</string>
<string name="pref_auto_reply_calls_delay_title">Jeda Penjawaban Otomatis</string>
<string name="pref_header_audio">Audio</string>
<string name="pref_header_generic">Generik</string>
<string name="pref_title_notification_wake_on_open">Bangun dan buka kunci otomatis</string>
<string name="pref_summary_notification_wake_on_open">Bangun dan buka kunci perangkat Android ketika perangkat mengirim respons OPEN kembali. Perlu dalam keadaan terpercaya.</string>
<string name="pref_speak_notifications_aloud_summary">Notifikasi akan dibaca melalui headphone</string>
<string name="pref_speak_notifications_aloud_title">Bacakan Notifikasi</string>
<string name="devicetype_redmi_watch_4">Redmi Watch 4</string>
<string name="widget_layout_top_large_bot_wide">Besar atas, lebar bawah</string>
<string name="widget_layout_top_wide_bot_large">Lebar atas, besar bawah</string>
<string name="widget_name_colored_tile">%1$s (ubin berwarna)</string>
<string name="widget_name_untitled">Widget tidak berjudul (%1$s)</string>
<string name="pref_header_calls_and_notifications">Panggilan dan notifikasi</string>
<string name="armenian">Armenia</string>
<string name="pref_sleepasandroid_feat_spo2">SPO2</string>
<string name="pref_title_huawei_account">Akun Huawei</string>
<string name="pref_summary_huawei_account">Akun Huawei digunakan dalam proses penyandingan. Dapat menyandingkan tanpa pengaturan ulang ke pengaturan pabrik.</string>
<string name="serbian">Serbia</string>
<string name="pref_sleepasandroid_enable_summary">Aktifkan integrasi Sleep As Android</string>
<string name="pref_sleepasandroid_device_title">Perangkat penyedia</string>
<string name="pref_sleepasandroid_features_summary">Dukungan tergantung pada perangkat</string>
<string name="pref_sleepasandroid_slot_title">Slot alarm</string>
<string name="pref_sleepasandroid_slot_summary">Slot alarm mana yang digunakan ketika mengatur alarm</string>
<string name="alarm_slot_reset">Slot alarm telah diatur menjadi bawaan</string>
<string name="pref_sleepasandroid_feat_notifications">Notifikasi</string>
<string name="pref_dashboard_widget_today_upside_down_title">Tengah malam di bawah</string>
<string name="pref_dashboard_widget_today_upside_down_summary">Dalam mode 24 jam, gambar tengah malam di bawah, tengah hari di atas bagan</string>
<string name="sleepasandroid_settings">Sleep As Android</string>
<string name="pref_sleepasandroid_device_summary">Pilih perangkat sebagai penyedia data Sleep As Amdroid</string>
<string name="pref_sleepasandroid_features_title">Fitur</string>
<string name="pref_sleepasandroid_feat_alarms">Alarm</string>
<string name="pref_sleepasandroid_feat_movement">Akselerometer</string>
<string name="pref_sleepasandroid_feat_heartrate">Detak jantung</string>
<string name="pref_sleepasandroid_feat_oximetry">Oksimetri</string>
<string name="pref_title_bottom_navigation_bar">Bilah navigasi bawah</string>
<string name="pref_summary_bottom_navigation_bar_on">Ganti antara layar utama menggunakan bilah navigasi atau pengusapan horizontal</string>
<string name="pref_summary_bottom_navigation_bar_off">Ganti antara layar utama hanya menggunakan pengusapan horizontal</string>
<string name="watchface_resolution_doesnt_match">Resolusi wajah jam tidak cocok dengan layar perangkat. Resolusi wajah jam adalah %1$s dan layar perangkat adalah %2$s</string>
</resources>

View File

@ -52,14 +52,14 @@
<!--Strings related to Settings-->
<string name="title_activity_settings">Impostazioni</string>
<string name="pref_header_general">Impostazioni generali</string>
<string name="pref_title_general_autoconnectonbluetooth">Collegati al dispositivo Gadgetbridge quando il Bluetooth viene acceso</string>
<string name="pref_title_general_autoconnectonbluetooth">Collegati al/ai dispositivo/i Gadgetbridge quando il Bluetooth viene acceso</string>
<string name="pref_title_general_autostartonboot">Avvio automatico</string>
<string name="pref_title_general_autoreconnect">Riconnessione automatica</string>
<string name="pref_title_audio_player">Riproduttore musicale preferito</string>
<string name="pref_default">Predefinito</string>
<string name="pref_header_datetime">Data e ora</string>
<string name="pref_title_datetime_syctimeonconnect">Sincronizza l\'ora</string>
<string name="pref_summary_datetime_syctimeonconnect">Sincronizza l\'orario del dispositivo al collegamento con Gadgetbridge e quando viene cambiata l\'ora o il fuso orario sul dispositivo Android</string>
<string name="pref_summary_datetime_syctimeonconnect">Sincronizza l\'orario del/i dispositivo/i al collegamento con Gadgetbridge e quando viene cambiata l\'ora o il fuso orario sul dispositivo e periodicamente</string>
<string name="pref_title_theme">Tema</string>
<string name="pref_theme_light">Chiaro</string>
<string name="pref_theme_dark">Scuro</string>
@ -1122,7 +1122,7 @@
<string name="prefs_events_forwarding_summary">Utilizza gli eventi del dispositivo per avviare azioni e broadcast di Android</string>
<string name="seconds_m">sec/m</string>
<string name="descentSeconds">Discendente</string>
<string name="swolfIndex">Indice SWOLF</string>
<string name="swolfIndex">SWOLF</string>
<string name="pref_title_lower_button_function_double">Pulsante inferiore, doppio</string>
<string name="pref_title_middle_button_function_double">Pulsante centrale, doppio</string>
<string name="pref_title_upper_button_function_double">Pulsante superiore, doppio</string>
@ -2451,4 +2451,235 @@
<string name="prefs_wena3_notification_settings_title">Impostazioni Notifiche</string>
<string name="devicetype_sony_wf_1000xm5">Sony WF-1000XM5</string>
<string name="devicetype_femometer_vinca2">Femometer Vinca II</string>
<string name="pai_chart_per_week">PAI settimanale</string>
<string name="pai_chart_per_month">PAI mensile</string>
<string name="weekstepschart_steps_a_week_or_month">Passi mensili/settimanali</string>
<string name="weeksleepchart_sleep_a_week_or_month">Sono mensile/settimanale</string>
<string name="dnd_all_day">Tutto il giorno</string>
<string name="busy_task_fetch_sports_details_interrupted">Il recupero dei dettagli sportivi è stato interrotto</string>
<string name="heartrate_bpm_165">165 bpm</string>
<string name="heartrate_bpm_175">175 bpm</string>
<string name="heartrate_bpm_185">185 bpm</string>
<string name="pref_title_casio_alert_email">Avviso per notifiche e-mail</string>
<string name="pref_summary_casio_alert_email">Avviso (vibrazione/bip) per le notifiche via e-mail</string>
<string name="pref_title_casio_alert_sms">Avviso per notifiche SMS</string>
<string name="pref_summary_casio_alert_sms">Avviso (vibrazione/bip) per le notifiche SMS (messaggi di testo)</string>
<string name="pref_title_casio_alert_other">Avviso per altre notifiche</string>
<string name="pref_summary_casio_alert_other">Avviso (vibrazione/bip) per le notifiche con altre categorie</string>
<string name="busy_task_fetch_pai_data">Recupero dati PAI</string>
<string name="manual">Manuale</string>
<string name="updatefirmwareoperation_updateproblem_low_battery">Il dispositivo è troppo scarico</string>
<string name="clap_hands_to_wakeup_device">Batti le mani per attivare lo schermo</string>
<string name="clap_hands_to_wakeup_device_summary">Battere di nuovo le mani spegnerà lo schermo</string>
<string name="pixoo_power_saving_summary">Lo schermo si spegnerà se il microfono rileva silenzio per un certo periodo</string>
<string name="prefs_wearmode">Modalità uso</string>
<string name="wearmode_pebble">Pebble (fibbia per scarpe)</string>
<string name="wearmode_necklace">Collana (laccetto collo)</string>
<string name="danish">Danese</string>
<string name="pref_title_general_reconnectonlytoconnected">Riconnetti solo ai dispositivi collegati</string>
<string name="pref_summary_general_reconnectonlytoconnected">Riconnetti solo ai dispositivi collegati, invece di riconnettersi a tutti i dispositivi</string>
<string name="pref_title_preview_message_in_title">Mostra anteprima del messaggio nel titolo</string>
<string name="pref_summary_preview_message_in_title">Mostra un\'anteprima del messaggio nel titolo di una notifica, come consentito dal dispositivo</string>
<string name="pref_title_casio_alert_call">Avviso per chiamate in arrivo</string>
<string name="heartrate_bpm_195">195 bpm</string>
<string name="wearmode_band">Cinturino (polsino)</string>
<string name="pref_title_send_app_notifications">Invia notifiche</string>
<string name="pref_summary_send_app_notifications">Inviare le notifiche delle app al dispositivo</string>
<string name="alarm_smart_wakeup_interval_default">5 minuti</string>
<string name="heartrate_bpm_155">155 bpm</string>
<string name="heartrate_bpm_205">205 bpm</string>
<string name="prefs_device_name">Nome dispositivo</string>
<string name="pref_title_goal_secondary">Obiettivo secondario</string>
<string name="pref_summary_casio_alert_call">Avviso (vibrazione/bip) per le chiamate in arrivo</string>
<string name="pref_title_casio_alert_calendar">Avviso per notifiche del calendario</string>
<string name="pref_summary_casio_alert_calendar">Avviso (vibrazione/bip) per le notifiche del calendario</string>
<string name="fw_upgrade_notice_amazfitbip3">Stai per installare il firmware %s sul tuo Amazfit Bip 3.
\n
\nAssicurati di installare prima il file .fw e dopo il file .res. L\'orologio si riavvierà al termine del caricamento del file .fw.
\n
\nNota: non è necessario installare il file .res se è uguale a quello installato in precedenza.
\n
\nPROCEDI A TUO RISCHIO E PERICOLO!</string>
<string name="pref_header_generic">Generico</string>
<string name="pref_header_audio">Suono</string>
<string name="activity_type_darts">Freccette</string>
<string name="activity_type_kite_flying">Aquilone</string>
<string name="devicetype_miband7pro">Xiaomi Smart Band 7 Pro</string>
<string name="devicetype_colacao21">ColaCao 2021</string>
<string name="hydration_dnd_summary">Disattivare avvisi di idratazione per un intervallo di tempo</string>
<string name="silent_mode_vibrate_silent">Vibrazione / Silenzioso</string>
<string name="activity_type_mountain_hike">Escursione in montagna</string>
<string name="activity_type_fitness_exercises">Esercizi fitness</string>
<string name="activity_type_cross_country_running">Corsa campestre</string>
<string name="activity_type_karate">Karate</string>
<string name="activity_type_cooldown">Raffreddamento</string>
<string name="activity_type_cross_training">Allenamento incrociato</string>
<string name="activity_type_plank">Plancia</string>
<string name="activity_type_aerobic_exercise">Esercizi aerobici</string>
<string name="activity_type_javelin">Giavellotto</string>
<string name="activity_type_long_jump">Salto in lungo</string>
<string name="activity_type_high_jump">Salto in alto</string>
<string name="activity_type_trampoline">Trampolino</string>
<string name="activity_type_dumbbell">Pesi</string>
<string name="activity_type_tai_chi">Tai chi</string>
<string name="activity_type_hula_hooping">Hula hoop</string>
<string name="activity_type_disc_sports">Lancio del disco</string>
<string name="activity_type_shuttlecock">Volano</string>
<string name="activity_type_archery">Tiro con l\'arco</string>
<string name="activity_type_softball">Softball</string>
<string name="activity_type_sailing">Vela</string>
<string name="activity_type_ice_hockey">Hockey su ghiaccio</string>
<string name="activity_type_dodgeball">Palla prigioniera</string>
<string name="activity_type_skateboarding">Skateboard</string>
<string name="activity_type_rock_climbing">Arrampicata su roccia</string>
<string name="activity_type_hunting">Caccia</string>
<string name="activity_type_trail_run">Corsa su sentiero</string>
<string name="devicetype_huawei_watchfit">Huawei Watch Fit</string>
<string name="devicetype_huawei_watchultimate">Huawei Watch Ultimate</string>
<string name="menuitem_zepp_pay">Zepp Pay</string>
<string name="zepp_os_watchface_guider">Guida</string>
<string name="menuitem_zepp_coach">Zepp Coach</string>
<string name="prefs_disconnect_notification_summary">Notifica sul dispositivo quando viene disconnesso dal BT.</string>
<string name="prefs_phone_silent_mode">Telefono in silenzioso</string>
<string name="pref_do_not_disturb_not_wear">Non disturbare quando non indossato</string>
<string name="devicetype_amazfit_bip3">Amazfit Bip 3</string>
<string name="devicetype_huawei_talk_band_b6">Huawei Talk Band B6</string>
<string name="devicetype_huawei_watchgt2e">Huawei Watch GT 2e</string>
<string name="pref_title_notification_wake_on_open">Risveglio e sblocco automatico</string>
<string name="pref_summary_notification_wake_on_open">Risveglia e sblocca il dispositivo Android quando il gadget invia una risposta OPEN. Deve essere segnato come affidabile.</string>
<string name="activity_type_crossfit">Crossfit</string>
<string name="activity_type_functional_training">Allenamento funzionale</string>
<string name="activity_type_physical_training">Allenamento fisico</string>
<string name="activity_type_taekwondo">Taekwondo</string>
<string name="activity_type_fencing">Scherma</string>
<string name="activity_type_kendo">Kendo</string>
<string name="devicetype_mijia_lywsd03">Sensore di temperatura e umidità Mijia 2</string>
<string name="devicetype_mijia_mho_c303">Mijia MHO-C303</string>
<string name="devicetype_sony_linkbuds">Sony LinkBuds</string>
<string name="devicetype_honor_band3">Honor Band 3</string>
<string name="devicetype_honor_band6">Honor Band 6</string>
<string name="devicetype_huawei_band8">Huawei Band 8</string>
<string name="devicetype_huawei_watch_gt">Huawei Watch GT</string>
<string name="devicetype_huawei_band4pro">Huawei Band 4 (Pro)</string>
<string name="devicetype_huawei_watchgt3">Huawei Watch GT 3 (Pro)</string>
<string name="devicetype_huawei_watchgt4">Huawei Watch GT 4</string>
<string name="devicetype_xiaomi_watch_lite">Xiaomi Watch Lite</string>
<string name="devicetype_redmiwatch3active">Redmi Watch 3 Active</string>
<string name="devicetype_redmiwatch3">Redmi Watch 3</string>
<string name="devicetype_redmi_smart_band_2">Redmi Smart Band 2</string>
<string name="prefs_heartrate_alert_active_high_threshold">Soglia di allarme per elevata frequenza cardiaca</string>
<string name="activity_type_flexibility">Flessibilità</string>
<string name="activity_type_track_and_field">Atletica leggera</string>
<string name="activity_type_pull_ups">Trazioni</string>
<string name="activity_type_jazz_dance">Danza jazz</string>
<string name="activity_type_latin_dance">Danza latina</string>
<string name="activity_type_kabaddi">Kabaddi</string>
<string name="activity_type_mind_and_body">Corpo e mente</string>
<string name="activity_type_karting">Go-kart</string>
<string name="activity_type_australian_football">Football australiano</string>
<string name="activity_type_lacross">Lacrosse</string>
<string name="activity_type_shot">Tiro</string>
<string name="activity_type_skating">Pattinaggio</string>
<string name="devicetype_miband8">Xiaomi Smart Band 8</string>
<string name="devicetype_miband8pro">Xiaomi Smart Band 8 Pro</string>
<string name="devicetype_honor_magicwatch2">Honor MagicWatch 2</string>
<string name="devicetype_huawei_band6">Huawei Band 6</string>
<string name="zepp_os_watchface_the_ultima">L\'ultima</string>
<string name="devicetype_honor_band4">Honor Band 4</string>
<string name="devicetype_honor_band5">Honor Band 5</string>
<string name="devicetype_honor_band7">Honor Band 7</string>
<string name="silent_mode_normal_silent">Normale / Silenzioso</string>
<string name="silent_mode_normal_vibrate">Normale / Vibrazione</string>
<string name="activity_type_wrestling">Lotta</string>
<string name="devicetype_colacao23">ColaCao 2023</string>
<string name="devicetype_miband8active">Xiaomi Smart Band 8 Active</string>
<string name="devicetype_huawei_band_aw70">Huawei Band (AW70)</string>
<string name="armenian">Armeno</string>
<string name="activity_type_indoor_running">Corsa al coperto</string>
<string name="activity_type_free_training">Allenamento libero</string>
<string name="activity_type_rower">Vogatore</string>
<string name="activity_type_stair_stepper">Stepper</string>
<string name="activity_type_horizontal_bar">Barre orizzontali</string>
<string name="activity_type_parallel_bar">Barre parallele</string>
<string name="activity_type_sit_ups">Addominali</string>
<string name="activity_type_push_ups">Flessioni</string>
<string name="activity_type_battle_rope">Tiro della fune</string>
<string name="activity_type_belly_dance">Danza del ventre</string>
<string name="activity_type_ballet">Balletto</string>
<string name="activity_type_other_dance">Altre danze</string>
<string name="activity_type_roller_skating">Pattini a rotelle</string>
<string name="activity_type_martial_arts">Arti marziali</string>
<string name="activity_type_horse_riding">Equitazione</string>
<string name="activity_type_swing">Altalena</string>
<string name="activity_type_stairs">Scale</string>
<string name="activity_type_fishing">Pesca</string>
<string name="activity_type_hand_cycling">Ciclismo manuale</string>
<string name="activity_type_billiards">Bigliardo</string>
<string name="activity_type_cross_country_skiing">Sci di fondo</string>
<string name="activity_type_snow_sports">Sport invernali</string>
<string name="activity_type_outdoor_walking">Camminata all\'estero</string>
<string name="devicetype_huawei_band7">Huawei Band 7</string>
<string name="devicetype_huawei_watchgt2">Huawei Watch GT 2 (Pro)</string>
<string name="devicetype_redmi_watch_2">Redmi Watch 2</string>
<string name="devicetype_redmi_smart_band_pro">Redmi Smart Band Pro</string>
<string name="devicetype_redmi_watch_4">Redmi Watch 4</string>
<string name="menuitem_readiness">Preparazione</string>
<string name="menuitem_body_composition">Composizione corporea</string>
<string name="menuitem_buzzer_intensity">Intensità cicalino</string>
<string name="alarm_smart_wakeup_interval">Intervallo di attivazione intelligente:</string>
<string name="standing_time">Tempo di riposo</string>
<string name="devicetype_redmi_watch_2_lite">Redmi Watch 2 Lite</string>
<string name="prefs_password_4_digits_0_to_9_summary">La password deve essere di 4 cifre, utilizzando solo numeri</string>
<string name="active_time">Tempo di attività</string>
<string name="devicetype_sony_wi_sp600n">Sony WI-SP600N</string>
<string name="swolfAvg">Swolf medio</string>
<string name="swolfMax">Swolf massimo</string>
<string name="swolfMin">Swolf minimo</string>
<string name="zepp_os_watchface_lightning_flash">Lampo di luce</string>
<string name="yard">iarda</string>
<string name="stepLengthAvg">Lunghezza media dei passi</string>
<string name="pref_header_sony_sound_control">Controllo sonoro</string>
<string name="pai_total">Totale</string>
<string name="sony_protocol_v3">Versione 3</string>
<string name="protocol_version">Versione protocollo</string>
<string name="maxStrokeRate">Frequenza Massima Corse</string>
<string name="strokes">Corse Totali</string>
<string name="pref_device_action_dnd_off">Non disturbare - Spento</string>
<string name="activity_type_curling">Curling</string>
<string name="devicetype_nothingear2">Nothing Ear (2)</string>
<string name="do_not_disturb_lift_wrist_summary">Solo se l\'attivazione del display al sollevamento è abilitata</string>
<string name="sony_protocol_v2">Versione 2</string>
<string name="activity_type_pickleball">Pickleball</string>
<string name="activity_type_jet_skiing">Moto d\'acqua</string>
<string name="activity_type_trekking">Escursionismo</string>
<string name="fmtPaceTypeAverage">Tipo di ritmo %d medio</string>
<string name="unknownDataEncountered">Dati sconosciuti riscontrati</string>
<string name="strokes_minute">serie/min</string>
<string name="devicetype_nothingearstick">Nothing Ear (Stick)</string>
<string name="devicetype_nothing_cmf_watch_pro">CMF Watch Pro</string>
<string name="pai_day">Aumento giornaliero</string>
<string name="sony_protocol_v1">Versione 1</string>
<string name="activity_type_smith_machine">Macchina Smith</string>
<string name="zepp_os_watchface_free_combination">Combinazione libera</string>
<string name="zepp_os_watchface_city_of_speed">Città di velocità</string>
<string name="avgStrokeRate">Frequenza Media Corse</string>
<string name="stepRateAvg">Velocità media dei passi</string>
<string name="eversionAngleAvg">Angolo medio di estroflessione</string>
<string name="eversionAngleMax">Angolo massimo di estroflessione</string>
<string name="fmtPaceDistance">Ritmo %d distanza</string>
<string name="fmtPaceType">Tipo %d ritmo</string>
<string name="fmtPacePace">Ritmo %d</string>
<string name="fmtPaceCorrection">Correzione ritmo %d</string>
<string name="milliseconds">millisecondi</string>
<string name="degrees">gradi</string>
<string name="pref_device_action_dnd_priority">Non disturbare - Solo priorità</string>
<string name="pref_device_action_dnd_alarms">Non disturbare - Solo sveglie</string>
<string name="pref_device_action_dnd_on">Non disturbare - Acceso</string>
<string name="huawei_trusleep_title">HUAWEI TruSleep ™</string>
<string name="prefs_workmode">Modalità lavoro</string>
<string name="flatDistance">Distanza piana</string>
<string name="prefs_active_noise_cancelling_transparency">Trasparenza</string>
<string name="laneLength">Lunghezza Corsia</string>
<string name="stepRateSum">Velocità totale dei passi</string>
<string name="Pace">Ritmo</string>
</resources>

File diff suppressed because it is too large Load Diff

View File

@ -1728,7 +1728,7 @@
<string name="prefs_password_summary">Vergrendel de band met een wachtwoord wanneer deze van de pols wordt verwijderd</string>
<string name="prefs_password_enabled">Wachtwoord ingeschakeld</string>
<string name="prefs_password_4_digits_1_to_4_summary">Het wachtwoord moet 4 cijfers hebben, met de nummers 1 tot en met 4</string>
<string name="info_no_devices_connected">geen apparaten aangesloten</string>
<string name="info_no_devices_connected">Geen apparaten aangesloten</string>
<string name="pref_blacklist_calendars_summary">Agenda\'s op de zwarte lijst worden niet gesynchroniseerd met het apparaat</string>
<string name="bengali">Bengaals</string>
<string name="czech">Tsjechisch</string>
@ -2832,13 +2832,127 @@
<string name="pref_adaptive_volume_control_summary">Verhoog volume automatisch bij veel omgevingsgeluid</string>
<string name="pref_header_sony_sound_control">Geluidsinstellingen</string>
<string name="error_scan_failed">Scan mislukt: %d</string>
<string name="scan_scanning_all_devices">Scannen voor alle apparaten</string>
<string name="scan_scanning_all_devices">Scannen naar alle apparaten</string>
<string name="scan_not_scanning">Niet aan het scannen</string>
<string name="scan_scanning_single_device">Scannen voor 1 apparaat</string>
<string name="scan_scanning_multiple_devices">Scannen voor %d apparaten</string>
<string name="scan_scanning_single_device">Scannen naar 1 apparaat</string>
<string name="scan_scanning_multiple_devices">Scannen naar %d apparaten</string>
<string name="notification_channel_scan_service_name">Scan-service</string>
<string name="device_state_waiting_scan">Wachten op apparaatscan</string>
<string name="devicetype_miband8active">Xiaomi Smart Band 8 Active</string>
<string name="alarm_smart_wakeup_interval_default">5 minuten</string>
<string name="alarm_smart_wakeup_interval">Interval slim wekken:</string>
<string name="companion_pairing_request_title">Bijbehorend apparaat</string>
<string name="unbind_before_pair_title">Al gekoppeld</string>
<string name="unbind_before_pair_message">Dit apparaat is al gekoppeld aan de Android-instellingen, waardoor het koppelen op sommige apparaten kan mislukken.
\n
\nAls het toevoegen van het apparaat mislukt, verwijder het dan in de Android-instellingen en probeer het opnieuw.</string>
<string name="companion_pairing_request_description">Koppel je dit apparaat als begeleider?
\n
\nDit wordt aanbevolen voor sommige functies zoals zoeken naar apparaten en biedt een betere verbinding.</string>
<string name="devicesetting_scannable_minimum_unseen_summary">Na te zijn gevonden, moet het apparaat deze tijd buiten bereik zijn om opnieuw gevonden te kunnen worden</string>
<string name="devicetype_scannable">Scanbaar apparaat</string>
<string name="state_scanned">Gescand</string>
<string name="devicesetting_scannable_debounce">Seconden zichtbaar na gescand</string>
<string name="devicesetting_scannable_minimum_unseen">Seconden afwezig na niet gescand</string>
<string name="devicesetting_scannable_rssi">Minimaal RSSI-niveau</string>
<string name="devicesetting_scannable_debounce_summary">Na te zijn gevonden, blijft het apparaat deze tijd actief als gescand en wordt verder genegeerd</string>
<string name="devicesetting_scannable_rssi_summary">Het minimale RSSI-niveau om gevonden te kunnen worden</string>
<string name="pref_force_enable_heartrate_support">Forceer hartslagmeting</string>
<string name="pref_force_enable_heartrate_support_summary">Forceer ondersteuning van hartslagmeting
\nGEBRUIK OP EIGEN RISICO</string>
<string name="pref_force_enable_spo2_support">Forceer SpO2-ondersteuning</string>
<string name="pref_force_enable_spo2_support_summary">Forceer ondersteuning van bloedzuurstofmetingen
\nGEBRUIK OP EIGEN RISICO</string>
<string name="error_showing_changelog">Fout bij tonen wijzigingenlijst</string>
<string name="activity_type_worn">Gedragen</string>
<string name="bottom_nav_dashboard">Dashboard</string>
<string name="pref_dashboard_first_title">Toon dashboard eerst</string>
<string name="pref_dashboard_first_summary">Toon het dashboard wanneer Gadgetbridge opstart, in plaats van het apparatenscherm</string>
<string name="pref_dashboard_cards_title">Widgets op kaarten</string>
<string name="pref_dashboard_widget_settings">Widget-instellingen</string>
<string name="pref_dashboard_widget_double_size_title">Dubbele grootte</string>
<string name="pref_dashboard_widget_show_legend_title">Toon legenda</string>
<string name="pref_dashboard_widget_goals_chart_title">Doelen-diagram</string>
<string name="pref_dashboard_devices_to_include">Apparaten</string>
<string name="pref_dashboard_all_devices_title">Alle apparaten</string>
<string name="pref_dashboard_select_devices_title">Selecteer apparaten...</string>
<string name="pref_dashboard_widgets_order_summary">Selecteer welke widgets op het dashboard getoond worden en in welke volgorde</string>
<string name="pref_dashboard_all_devices_summary">Combineer activiteitsgegevens van alle toegevoegde apparaten voor het dashboard</string>
<string name="pref_dashboard_widget_today_24h_summary">Toon de activiteit in een enkele 24-uurscirkel in plaats van een dubbele 12-uurscirkel</string>
<string name="pref_dashboard_widget_show_legend_summary">Toon een legenda onder de widget om de kleuren uit te leggen</string>
<string name="pref_dashboard_select_devices_summary">Combineer activiteitsgegevens van specifieke apparaten voor het dashboard</string>
<string name="pref_dashboard_widget_today_hr_interval_title">Interval hartslagmeting</string>
<string name="pref_dashboard_widget_today_hr_interval_summary">Het aantal minuten dat het diagram \'gedragen\' toont na elke succesvolle hartslagmeting</string>
<string name="pref_auto_reply_calls_summary">De telefoon neemt binnenkomende telefoongesprekken automatisch op</string>
<string name="pref_auto_reply_calls_title">Binnenkomende gesprekken automatisch opnemen</string>
<string name="dashboard_settings">Dashboard-instellingen</string>
<string name="bottom_nav_devices">Apparaten</string>
<string name="pref_dashboard_cards_summary">Toon de widgets op kaarten op het dashboard</string>
<string name="pref_dashboard_widget_today_title">Activiteit-diagram</string>
<string name="pref_dashboard_widget_today_24h_title">24-uursmodus</string>
<string name="pref_dashboard_widget_double_size_summary">Sta de widget toe om twee kolommen van het dashboard te gebruiken</string>
<string name="pref_auto_reply_calls_delay_summary">Aantal seconden waarna een binnenkomend telefoongesprek automatisch opgenomen wordt</string>
<string name="pref_auto_reply_calls_delay_title">Vertraging automatisch opnemen</string>
<string name="swolfAvg">Gemiddelde SWOLF</string>
<string name="swolfMax">Maximale SWOLF</string>
<string name="swolfMin">Minimale SWOLF</string>
<string name="stepRateSum">Opgetelde stapsnelheid</string>
<string name="stepRateAvg">Gemiddelde stapsnelheid</string>
<string name="stepLengthAvg">Gemiddelde staplengte</string>
<string name="groundContactTimeAvg">Gemiddelde contacttijd met grond</string>
<string name="impactAvg">Gemiddelde impact</string>
<string name="impactMax">Maximale impact</string>
<string name="swingAngleAvg">Gemiddelde zwaaihoek</string>
<string name="foreFootLandings">Voorvoetlandingen</string>
<string name="midFootLandings">Midvoetlandingen</string>
<string name="backFootLandings">Hiellandingen</string>
<string name="eversionAngleAvg">Gemiddelde eversiehoek</string>
<string name="eversionAngleMax">Maximale eversiehoek</string>
<string name="fmtPaceDistance">Tempo %d afstand</string>
<string name="fmtPaceType">Tempo %d type</string>
<string name="fmtPacePace">Tempo %d tempo</string>
<string name="fmtPaceCorrection">Tempo %d correctie</string>
<string name="fmtPaceTypeAverage">Tempotype %d gemiddelde</string>
<string name="unknownDataEncountered">Niet-herkende gegevens aangetroffen</string>
<string name="milliseconds">milliseconden</string>
<string name="degrees">graden</string>
<string name="Pace">Tempo</string>
<string name="RunningForm">Hardloopkwaliteit</string>
<string name="pref_header_audio">Audio</string>
<string name="pref_header_generic">Algemeen</string>
<string name="pref_title_notification_wake_on_open">Automatisch ontgrendelen</string>
<string name="pref_summary_notification_wake_on_open">Ontgrendel het scherm van het Android-apparaat wanneer de gadget een OPEN-commando stuurt. Werkt alleen wanneer vertrouwde ontgrendeling actief is.</string>
<string name="pref_speak_notifications_aloud_summary">Meldingen zullen opgelezen worden via de koptelefoon</string>
<string name="pref_speak_notifications_aloud_title">Meldingen oplezen</string>
<string name="devicetype_redmi_watch_4">Redmi Watch 4</string>
<string name="widget_name_untitled">Widget zonder titel (%1$s)</string>
<string name="pref_header_calls_and_notifications">Gesprekken en meldingen</string>
<string name="widget_layout_top_wide_bot_large">Breed boven, groot onder</string>
<string name="widget_layout_top_large_bot_wide">Groot boven, breed onder</string>
<string name="widget_name_colored_tile">%1$s (gekleurde titel)</string>
<string name="pref_dashboard_widget_today_upside_down_summary">Toon in 24-uursmodus middernacht onderaan en 12 uur bovenaan de cirkel</string>
<string name="sleepasandroid_settings">Sleep As Android</string>
<string name="pref_summary_bottom_navigation_bar_off">Wissel tussen de hoofdschermen alleen met horizontaal vegen</string>
<string name="pref_dashboard_widget_today_upside_down_title">Middernacht onderaan</string>
<string name="pref_sleepasandroid_device_title">Gekoppeld apparaat</string>
<string name="pref_sleepasandroid_device_summary">Selecteer apparaat als databron voor Sleep As Android</string>
<string name="pref_sleepasandroid_features_title">Functies</string>
<string name="pref_sleepasandroid_features_summary">Ondersteuning verschilt per apparaat</string>
<string name="pref_sleepasandroid_feat_alarms">Wekkers</string>
<string name="pref_sleepasandroid_slot_summary">Welk wekkerslot wordt gebruikt voor het instellen van wekkers</string>
<string name="pref_sleepasandroid_slot_title">Wekkerslot</string>
<string name="pref_sleepasandroid_feat_movement">Bewegingssensor</string>
<string name="pref_sleepasandroid_feat_heartrate">Hartslag</string>
<string name="pref_sleepasandroid_feat_spo2">SpO2</string>
<string name="pref_sleepasandroid_enable_summary">Integratie met Sleep As Android inschakelen</string>
<string name="alarm_slot_reset">Wekkerslot is teruggezet naar standaard</string>
<string name="pref_sleepasandroid_feat_notifications">Meldingen</string>
<string name="pref_sleepasandroid_feat_oximetry">Bloedzuurstof</string>
<string name="armenian">Armeens</string>
<string name="pref_title_bottom_navigation_bar">Navigatiebalk onderaan</string>
<string name="pref_summary_bottom_navigation_bar_on">Wissel tussen de hoofdschermen met de navigatiebalk of horizontaal vegen</string>
<string name="pref_title_huawei_account">Huawei-account</string>
<string name="serbian">Servisch</string>
<string name="pref_summary_huawei_account">Huawei-account dat gebruikt is tijdens het bindingsproces. Het hier instellen staat toe dat het apparaat gebonden kan worden zonder reset naar fabrieksinstellingen.</string>
<string name="watchface_resolution_doesnt_match">Resolutie van wijzerplaat komt niet overeen met het scherm van het apparaat. Wijzerplaat is %1$s en scherm is %2$s</string>
</resources>

View File

@ -766,7 +766,7 @@
<string name="prefs_find_phone_duration">Duração do toque sonoro em segundos</string>
<string name="maximum_duration">Duração</string>
<string name="discovery_need_to_enter_authkey">Esse dispositivo precisa de sua chave de autenticação secreta, realize pressionamento longo no dispositivo para inseri-lo. Leia o wiki.</string>
<string name="fw_upgrade_notice_amazfitbip_lite">Você está prestes a instalar o firmware %s no seu Amazit Bip Lite.
<string name="fw_upgrade_notice_amazfitbip_lite">Você está prestes a instalar o firmware %s no seu Amazfit Bip Lite.
\n
\nCertifique-se de instalar o arquivo .fw, e depois o arquivo .res. Seu relógio será reiniciado após a instalação do arquivo .fw.
\n
@ -1510,7 +1510,7 @@
<string name="about_description_banglejs_nightly">Aplicativo companheiro Android para Bangle.js construído em cima do projeto Gadgetbridge, com acesso adicional à Internet.
\n
\nDevido às políticas Google Play Store, não somos permitidos ter um link de doação no próprio aplicativo, mas se você gosta deste aplicativo, por favor, considere doar através da página inicial do Gadgetbridge abaixo.</string>
<string name="single_band">Banda única</string>
<string name="single_band">Single Band</string>
<string name="about_activity_title_banglejs_nightly">Sobre o Bangle.js Gadgetbridge (Nightly)</string>
<string name="power_saving">Economia de energia</string>
<string name="gadgetbridge_running_banglejs_nightly">Nightly Bangle.js em execução</string>
@ -1519,4 +1519,92 @@
<string name="action_changelog">Registro de mudanças</string>
<string name="custom">Personalizado</string>
<string name="application_name_banglejs_nightly">Bangle.js Gadgetbridge (Nightly)</string>
<string name="pref_header_health">Saúde</string>
<string name="error_showing_changelog">Erro ao exibir o registro de alterações</string>
<string name="appmanager_watchface_activate">Ativar</string>
<string name="pref_header_audio">Áudio</string>
<string name="pref_header_generic">Genérico</string>
<string name="pref_title_mb_intents">Transmitir diretamente as intenções dos botões de mídia</string>
<string name="pref_summary_mb_intents">Ative se o controle de mídia do dispositivo não estiver funcionando para determinados aplicativos</string>
<string name="pref_theme_dynamic">Cores dinâmicas</string>
<string name="pref_show_changelog_summary">Exibir o registro de alterações desde a última versão após a atualização do Gadgetbridge</string>
<string name="accuracy_first">Precisão primeiro</string>
<string name="speed_first">Velocidade primeiro</string>
<string name="pref_show_changelog">Mostrar registro de alterações na inicialização</string>
<string name="steps_streaks">Sequência de passos</string>
<string name="step_streak_total">Total</string>
<string name="steps_streaks_average_steps">Média de
\npassos</string>
<string name="steps_streaks_achievement_rate">Taxa de
\nconquista</string>
<string name="steps_streaks_total_steps_hint_totals">Número total de passos já registrados</string>
<string name="step_streaks_achievements_sharing_title">Conquistas de passos</string>
<string name="changelog_show_full">Mais…</string>
<string name="uploadwatchfaceoperation_in_progress">Carregando o watchface</string>
<string name="steps_streaks_total_steps_hint">Número total de passos em toda a sequência</string>
<string name="steps_streaks_total_steps_average_hint">Média total de %d passos por dia</string>
<string name="step_streak_days_hint">Número de dias consecutivos em que a meta de passos foi atingida</string>
<string name="steps_streaks_hint">Sequência de dias consecutivos sem interrupção com metas de passos sendo alcançadas</string>
<string name="uploading_watchface">Carregando o watchface…</string>
<string name="step_streak_longest">Mais longo</string>
<string name="appmanager_app_share">Compartilhar</string>
<string name="debugactivity_confirm_remove_device_preferences_title">Remover as preferências do dispositivo?</string>
<string name="debugactivity_confirm_remove_device_preferences">Isso redefinirá as preferências do dispositivo para todos os dispositivos conectados. Tem certeza?</string>
<string name="pref_header_calendar">Calendário</string>
<string name="pref_title_general_reconnectonlytoconnected">Reconectar somente a dispositivos conectados</string>
<string name="pref_summary_general_reconnectonlytoconnected">Reconectar somente a dispositivos conectados, em vez de reconectar a todos os dispositivos</string>
<string name="steps_streaks_total_steps">Passos
\ntotais</string>
<string name="steps_streaks_streak_days">Dias
\nseguidos</string>
<string name="fw_upgrade_notice_amazfitbip3pro">Você está prestes a instalar o firmware %s no seu Amazfit Bip 3 Pro.
\n
\nCertifique-se de instalar o arquivo .fw, e depois o arquivo .res. Seu relógio será reiniciado após a instalação do arquivo .fw.
\n
\nNota: você não precisa instalar .res se esse arquivo for exatamente o mesmo que os instalados anteriormente.
\n
\nPROSSIGA POR SUA CONTA E RISCO!</string>
<string name="open_fw_installer_select_file">Selecione um arquivo que deseja enviar para o dispositivo: %s</string>
<string name="pref_header_display">Exibir</string>
<string name="step_streak_average_steps_hint">Média de passos por dia da sequência</string>
<string name="appmanager_app_start">Iniciar</string>
<string name="appmanager_app_download">Download para o cache</string>
<string name="appmanager_item_outdated">(desatualizado)</string>
<string name="appmanager_download_started">Download do aplicativo iniciado</string>
<string name="pref_header_connection">Conexão</string>
<string name="step_streak_ongoing">Em andamento</string>
<string name="pref_title_navigation_prefs">Preferências de navegação</string>
<string name="pref_sleepasandroid_features_title">Recursos</string>
<string name="pref_sleepasandroid_feat_heartrate">Frequência cardíaca</string>
<string name="pref_summary_huawei_account">Conta da Huawei usada no processo de emparelhamento. Sua configuração permite emparelhar sem redefinição de fábrica.</string>
<string name="pref_header_time">Hora</string>
<string name="steps_streaks_total_days_hint_totals">Porcentagem de dias com meta atingida em relação a todos os dias com passos</string>
<string name="pref_cache_weather">Informações sobre o clima em cache</string>
<string name="pref_cache_weather_summary">As informações do clima serão armazenadas em cache durante as reinicializações do aplicativo.</string>
<string name="dual_band">Dual Band</string>
<string name="steps_streaks_since_date">Desde %s</string>
<string name="step_streaks_achievements_sharing_message">Minhas conquistas diárias de passos!</string>
<string name="watchface_resolution_doesnt_match">A resolução do watchface não corresponde à tela do dispositivo. Watchface é %1$s a tela do dispositivo é %2$s</string>
<string name="pref_title_huawei_account">Conta da Huawei</string>
<string name="appmanager_downloaded_to_cache">Download de %s para o cache</string>
<string name="appmanager_download_app_error">Erro no download do aplicativo</string>
<string name="open_fw_installer_connect_minimum_one_device">Conecte pelo menos um dispositivo para o qual você deseja enviar o arquivo.</string>
<string name="pref_header_sound_vibration">Som e vibração</string>
<string name="open_fw_installer_connect_maximum_one_device">Conecte APENAS UM dispositivo para o qual você deseja enviar o arquivo.</string>
<string name="pref_header_offline_voice">Voz offline</string>
<string name="open_fw_installer_ensure_device_connected">Certifique-se de que o dispositivo %s esteja conectado</string>
<string name="fw_upgrade_notice_amazfitbip3">Você está prestes a instalar o firmware %s no seu Amazfit Bip 3.
\n
\nCertifique-se de instalar o arquivo .fw, e depois o arquivo .res. Seu relógio será reiniciado após a instalação do arquivo .fw.
\n
\nNota: você não precisa instalar .res se esse arquivo for exatamente o mesmo que os instalados anteriormente.
\n
\nPROSSIGA POR SUA CONTA E RISCO!</string>
<string name="fw_upgrade_notice_miband7">Você está prestes a instalar o firmware %s no seu Xiaomi Smart Band 7.
\n
\nCertifique-se de instalar o arquivo .fw, e depois o arquivo .res. Seu relógio será reiniciado após a instalação do arquivo .fw.
\n
\nPROSSIGA POR SUA CONTA E RISCO!</string>
<string name="uploadwatchfaceoperation_complete">Instalação do Watchface concluída</string>
<string name="uploadwatchfaceoperation_failed">Falha na instalação do Watchface</string>
</resources>

View File

@ -1118,7 +1118,7 @@
<string name="movement_intensity">Интенсивность движения</string>
<string name="devicestatus_upload_started">Загрузка началась</string>
<string name="activity_list_summary_activities">Активности</string>
<string name="menuitem_sleep">Шаги</string>
<string name="menuitem_sleep">Сон</string>
<string name="devicetype_amazfit_bipu">Amazfit Bip U</string>
<string name="pref_title_upper_button_function_double">Двойное нажатие на верхнюю кнопку</string>
<string name="pref_title_lower_button_function_double">Двойное нажатие на нижнюю кнопку</string>
@ -1855,7 +1855,7 @@
<string name="error_setting_parent_folder">Ошибка задания родительской папки: %s</string>
<string name="autoconnect_from_device_summary">Подключаться в случае когда соединение инициировано устройством, например, наушниками</string>
<string name="devicetype_sony_wh_1000xm2">Sony WH-1000XM2</string>
<string name="info_no_devices_connected">нет подключенных устройств</string>
<string name="info_no_devices_connected">Нет подключенных устройств</string>
<string name="controlcenter_set_parent_folder">Задать родительскую папку</string>
<string name="controlcenter_set_folder_title">Укажите папку или создайте новую</string>
<string name="autoconnect_from_device_title">Подключаться при подключении с устройства</string>
@ -2665,13 +2665,13 @@
<string name="pref_heartrate_automatic_enable">Автоизмерение сердцебиения</string>
<string name="pref_spo_automatic_enable">Автоизмерение кислорода в крови</string>
<string name="pref_force_options">Форсирование опций</string>
<string name="pref_force_smart_alarm">Форсировать умный будильник</string>
<string name="pref_force_smart_alarm">Поддержка умного будильника</string>
<string name="pref_force_smart_alarm_summary">Форсировать поддержку умных будильников.
\nИСПОЛЬЗУЙТЕ НА СВОЙ РИСК</string>
<string name="pref_force_wear_location">Форсировать место ношения</string>
<string name="pref_force_wear_location">Поддержка места ношения</string>
<string name="pref_force_wear_location_summary">Форсировать поддержку расположения ношения устройства.
\nИСПОЛЬЗУЙТЕ НА СВОЙ РИСК</string>
<string name="pref_force_dnd_support">Форсировать поддержку \"не беспокоить\"</string>
<string name="pref_force_dnd_support">Поддержка \"не беспокоить\"</string>
<string name="huawei_ignore_wakeup_status_start">Игнорировать статус начала вставания</string>
<string name="huawei_ignore_wakeup_status_start_description">Может помочь исправить распознание сна. Сразу видимо в обзоре дневных активностей.</string>
<string name="huawei_ignore_wakeup_status_end">Игнорировать статус окончания вставания</string>
@ -2787,4 +2787,43 @@
<string name="devicetype_huawei_watchgt4">Huawei Watch GT 4</string>
<string name="devicetype_huawei_watchultimate">Huawei Watch Ultimate</string>
<string name="busy_task_fetch_sports_details_interrupted">Получение подробностей о спорте было прервано</string>
<string name="pref_force_enable_heartrate_support">Поддержка измерения пульса</string>
<string name="pref_force_enable_spo2_support_summary">Форсировать поддержку измерения уровня кислорода в крови.
\nИСПОЛЬЗУЙТЕ НА СВОЙ РИСК</string>
<string name="pref_force_enable_heartrate_support_summary">Форсировать поддержку измерения пульса.
\nИСПОЛЬЗУЙТЕ НА СВОЙ РИСК</string>
<string name="pref_force_enable_spo2_support">Поддержка измерения SpO2</string>
<string name="pref_dashboard_widget_double_size_summary">Позволить виджету занять две колонки на обзорной панели</string>
<string name="pref_dashboard_widget_show_legend_summary">Показывать значения цветов под виджетом</string>
<string name="pref_dashboard_select_devices_title">Выбрать устройства...</string>
<string name="pref_dashboard_widgets_order_summary">Выберите виджеты и порядок их отображения на главном экране</string>
<string name="pref_dashboard_widget_today_24h_summary">Показывать активность в одном 24-часовом кружке вместо двойного 12ч</string>
<string name="pref_auto_reply_calls_title">Принимать звонки автоматически</string>
<string name="pref_auto_reply_calls_delay_title">Задержка перед автоприёмом</string>
<string name="pref_auto_reply_calls_summary">Телефон будет автоматически принимать входящие звонки</string>
<string name="pref_auto_reply_calls_delay_summary">Время в секундах до того, как звонок будет автоматически принят</string>
<string name="pref_header_generic">Общий</string>
<string name="pref_header_audio">Звук</string>
<string name="activity_type_free_training">Свободная тренировка</string>
<string name="activity_type_dynamic_cycle">Динамический цикл</string>
<string name="pref_dashboard_widget_today_hr_interval_title">Интервал измерений пульса</string>
<string name="pref_speak_notifications_aloud_title">Произносить уведомления вслух</string>
<string name="pref_header_calls_and_notifications">Вызовы и уведомления</string>
<string name="pref_dashboard_widget_show_legend_title">Показывать обозначения</string>
<string name="armenian">Армянский</string>
<string name="devicetype_redmi_watch_4">Redmi Watch 4</string>
<string name="pref_title_notification_wake_on_open">Автопробуждение и разблокировка</string>
<string name="pref_summary_notification_wake_on_open">Пробуждать и разблокировать Android-устройство когда носимое устройство отвечает с OPEN. Нужно быть в доверенном состоянии.</string>
<string name="pref_sleepasandroid_features_title">Функции</string>
<string name="pref_sleepasandroid_features_summary">Поддержка варьируется в зависимости от устройства</string>
<string name="pref_sleepasandroid_feat_movement">Акселерометр</string>
<string name="pref_sleepasandroid_feat_heartrate">Пульс</string>
<string name="pref_sleepasandroid_feat_spo2">SpO2</string>
<string name="pref_title_bottom_navigation_bar">Нижняя панель навигации</string>
<string name="pref_summary_bottom_navigation_bar_on">Переключаться между основными экранами через панель навигации или жестами</string>
<string name="pref_sleepasandroid_feat_notifications">Уведомления</string>
<string name="pref_summary_bottom_navigation_bar_off">Переключаться между основными экранами только по жестам</string>
<string name="serbian">Сербский</string>
<string name="pref_title_huawei_account">Учётная запись Huawei</string>
<string name="pref_summary_huawei_account">Используется для сопряжения без сброса устройства.</string>
</resources>

View File

@ -1,21 +1,21 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="about_activity_title_generic">เกี่ยวกับ Gadgetbridge</string>
<string name="application_name_generic"></string>
<string name="application_name_generic">Gadgetbridge</string>
<string name="gadgetbridge_running_generic">Gadgetbridge กำลังทำงาน</string>
<string name="about_description_generic">แอปเสรีไม่สงวนลิขสิทธิ์ ไม่พึ่งระบบคลาวด์ สำหรับใช้ทดแทนแอปจากผู้ผลิตที่ไม่เปิดเผยโค้ดอิสระ</string>
<string name="title_activity_controlcenter_generic"></string>
<string name="title_activity_controlcenter_generic">Gadgetbridge</string>
<string name="about_activity_title_banglejs_main">เกี่ยวกับ Bangle.js Gadgetbridge</string>
<string name="gadgetbridge_running_banglejs_main">Bangle.js กำลังทำงานอยู่</string>
<string name="application_name_banglejs_nightly"></string>
<string name="title_activity_controlcenter_banglejs_nightly"></string>
<string name="application_name_banglejs_nightly">Bangle.js Gadgetbridge (Nightly)</string>
<string name="title_activity_controlcenter_banglejs_nightly">Bangle.js Gadgetbridge (Nightly)</string>
<string name="gadgetbridge_running_banglejs_nightly">Nightly Bangle.js กำลังทำงานอยู่</string>
<string name="about_activity_title_main_nightly">เกี่ยวกับ Gadgetbridge Nightly</string>
<string name="title_activity_controlcenter_main_nightly"></string>
<string name="about_activity_title_main_nightly">เกี่ยวกับ Gadgetbridge รุ่นทดสอบ</string>
<string name="title_activity_controlcenter_main_nightly">Gadgetbridge Nightly</string>
<string name="gadgetbridge_running_main_nightly">Nightly GB กำลังทำงานอยู่</string>
<string name="application_name_main_nopebble">Gadgetbridge (Nightly โดยไม่มี Pebble provider)</string>
<string name="title_activity_controlcenter_main_nopebble">Gadgetbridge Nightly แบบไม่มี Pebbleล</string>
<string name="about_activity_title_main_nopebble">เกี่ยวกับ Gadgetbridge Nightly แบบไม่มี Pebbleล</string>
<string name="about_activity_title_main_nopebble">About Gadgetbridge Nightly No Pebble</string>
<string name="action_settings">การตั้งค่า</string>
<string name="action_debug">ดีบั้ก</string>
<string name="action_quit">ออก</string>
@ -67,8 +67,8 @@
<string name="title_activity_debug">ดีบั้ก</string>
<string name="debugactivity_really_factoryreset_title">คืนค่าเรื่มต้นจากโรงงาน?</string>
<string name="debugactivity_confirm_remove_device_preferences_title">ลบการตั้งค่าของอุปกรณ์?</string>
<string name="about_activity_title_banglejs_nightly">เกี่ยวกับ Bangle.js Gadgetbridge (Nightly)</string>
<string name="about_description_main_nightly">แอปเสรีไม่สงวนลิขสิทธิ์ ไม่พึ่งระบบคลาวด์ สำหรับใช้ทดแทนแอปแก็ดเจ็ตต่างๆจากผู้ผลิตที่ไม่เปิดเผยโค้ดอิสระ เวอร์ชั่น Nightly ของ Gadgetbridge ไม่สามารถติดตั้งซ้อนได้หากคุณมีแอป Gadgetbridge หรือ Pebble ติดตั้งอยู่แล้ว เนื่องจากการขัดแย้งกันของ Pebble provider</string>
<string name="about_activity_title_banglejs_nightly">เกี่ยวกับ Bangle.js Gadgetbridge (รุ่นทดสอบ)</string>
<string name="about_description_main_nightly">แอปเสรีไม่สงวนลิขสิทธิ์ ไม่พึ่งระบบคลาวด์ สำหรับใช้ทดแทนแอปแก็ดเจ็ตต่างๆจากผู้ผลิตที่ไม่เปิดเผยโค้ดอิสระ เวอร์ชั่นทดสอบของ Gadgetbridge ไม่สามารถติดตั้งคู่กันได้หากคุณมีแอป Gadgetbridge หรือ Pebble ติดตั้งอยู่แล้ว เนื่องจากการขัดแย้งกันของ Pebble provider</string>
<string name="controlcenter_delete_device">ลบอุปกรณ์</string>
<string name="prefs_activity_in_device_card_title">แสดงข้อมูลกิจกรรมบนการ์ดของอุปกรณ์</string>
<string name="prefs_activity_in_device_card_title_summary">แสดงจำนวนก้าวเดินปัจจุบัน ระยะทางหรือการนอนหลับบนการ์ดของอุปกรณ์</string>
@ -81,4 +81,40 @@
\n
\nเนื่องจากนโยบายของ Google Play เราจึงไม่สามารถเพื่มช่องการบริจาคในแอปได้โดยตรง แต่ถ้าคุณชอบแอปนี้โปรดพิจารณาบริจาคผ่านหน้าหลักของ Gadgetbridge ด้านล่างนี้</string>
<string name="debugactivity_really_factoryreset">การคืนค่าโรงงานจะลบข้อมูลทุกอย่างของอุปกรณ์ Xiaomi/Huami (ที่รองรับ) และยังเปลี่ยนที่อยู่ Bluetooth MAC address ฉะนั้น Gadgetbridge จะมองเห็นเป็นอุปกรณ์ใหม่</string>
<string name="application_name_banglejs_main">Bangle.js Gadgetbridge</string>
<string name="title_activity_controlcenter_banglejs_main">Bangle.js Gadgetbridge</string>
<string name="application_name_main_nightly">Gadgetbridge (รุ่นทดสอบ)</string>
<string name="about_links">ลิงก์</string>
<string name="single_band">ช่องความถี่เดี่ยว</string>
<string name="dual_band">ช่องความถี่คู่</string>
<string name="debugactivity_confirm_remove_device_preferences">นี่จะเป็นการรีเซ็ตการตั้งค่าของทุกอุปกรณ์ที่เชื่อมต่ออยู่ แน่ใจหรือ?</string>
<string name="about_description_main_nopebble">แอปเสรีไม่สงวนลิขสิทธิ์ ไม่พึ่งระบบคลาวด์ สำหรับใช้ทดแทนแอปแก็ดเจ็ตต่างๆจากผู้ผลิตที่ไม่เปิดเผยโค้ดอิสระ เวอร์ชั่นทดสอบของ Gadgetbridge มี Pebble provider ที่ถูกเปลี่ยนชื่อเพื่อป้องกันการขัดแย้งกัน ฉะนั้นการทำงานร่วมกับฟีเจอร์บางอย่างของ Pebble อาจใช้ไม่ได้ แต่สามารถติดตั้งแอปนี้คู่กับแอป Gadgetbridge ที่มีอยู่แล้วได้</string>
<string name="appmanager_installed_watchapps">แอปที่ติดตั้งแล้ว</string>
<string name="appmanager_installed_watchfaces">หน้าปัดนาฬิกาที่ติดตั้งแล้ว</string>
<string name="about_core_team_title">ผู้ร่วมพัฒนาหลักๆ(ตั้งแต่เรื่มพัฒนาแรกๆ)</string>
<string name="gadgetbridge_running_main_nopebble">Nightly NoPebble GB กำลังทำงาน</string>
<string name="appmanager_app_share">แชร์</string>
<string name="title_activity_notification_management">การตั้งค่าการแจ้งเตือน</string>
<string name="pref_title_notifications_call">เมื่อมีสายเข้า</string>
<string name="pref_title_notifications_ignore_low_priority">ไม่สนใจการแจ้งเตือนความสำคัญต่ำ</string>
<string name="pref_title_notifications_generic_settings">การตั้งค่าการแจ้งเตือนของ Android</string>
<string name="pref_title_notifications_generic">การรองรับการแจ้งเตือนทั่วไป</string>
<string name="pref_title_whenscreenon">...และเมื่อหน้าจอเปิดอยู่</string>
<string name="pref_summary_notifications_ignore_low_priority">ไม่ต้องส่งการแจ้งเตือนที่มีความสำคัญต่ำต่างๆไปยังอุปกรณ์</string>
<string name="pref_title_support_voip_calls">การโทรจากระบบ VoIP</string>
<string name="pref_summary_notification_prefer_long_text">หากเป็นไปได้ ให้ส่งการแจ้งเตือนที่มีข้อความยาวๆ ไปยังอุปกรณ์</string>
<string name="pref_summary_notifications_ignore_work_profile">ไม่ต้องส่งการแจ้งเตือนจากแอปที่อยู่ในโปรไฟล์งานไปยังอุปกรณ์</string>
<string name="pref_title_notification_cache_while_disconnected">แคชการแจังเตือนไว้</string>
<string name="pref_summary_notification_cache_while_disconnected">ส่งการแจ้งเตือนที่พลาดไป เมื่ออุปกรณ์กลับมาเชื่อมต่ออีกครั้งหลังจากไม่อยู่ในระยะการเชื่อมต่อ</string>
<string name="pref_title_notification_prefer_long_text">ส่งการแจ้งเตือนข้อความยาวๆ</string>
<string name="never">ไม่เลย</string>
<string name="always">ตลอดเวลา</string>
<string name="pref_title_notifications_ignore_work_profile">ไม่สนใจการแจ้งเตือนจากโปรไฟล์งาน</string>
<string name="pref_title_ping_tone">เสียงตอนปิงอุปกรณ์</string>
<string name="pref_title_notification_delay_calls">หน่วงการแจ้งเตือนการโทร</string>
<string name="pref_summary_notification_delay_calls">หน่วงไว้ก่อนจะส่งการไปแจ้งเตือนไปยังอุปกรณ์ หน่วยเป็นวินาที</string>
<string name="about_contributors">ผู้ร่วมพัฒนา</string>
<string name="about_additional_device_support">ผู้สนับสนุนการรองรับอุปกรณ์เพื่มเติม</string>
<string name="about_additional_contributions">ขอขอบคุณผู่ร่วมพัฒนาทุกท่านที่ช่วยกันแก้ไขโค้ด, แปลภาษา, ช่วยเหลือ, ออกไอเดีย, ให้กำลังใจ, แจ้งบั้ก, และบริจาคเงิน... ✊</string>
<string name="action_discover">เชื่อมต่ออุปกรณ์ใหม่</string>
</resources>

View File

@ -1734,7 +1734,7 @@
<string name="permission_location">%1$s ekranınız kapalıyken bile saatinize bağlı kalmasını sağlamak için arka planda konumunuza erişmeye ihtiyaç duyuyor.
\n
\nKabul etmek için lütfen \'%2$s\' düğmesine dokunun.</string>
<string name="info_no_devices_connected">bağlı aygıt yok</string>
<string name="info_no_devices_connected">Bağlı aygıt yok</string>
<string name="info_connected_count">%d aygıt bağlı</string>
<string name="estonian">Estonca</string>
<string name="lithuanian">Litvanyaca</string>
@ -2854,4 +2854,122 @@
<string name="devicetype_huawei_watchgt4">Huawei Watch GT 4</string>
<string name="busy_task_fetch_sports_details_interrupted">Spor bilgilerinin getirilmesi yarıda kesildi</string>
<string name="devicetype_huawei_watchultimate">Huawei Watch Ultimate</string>
<string name="companion_pairing_request_title">Yardımcı aygıt</string>
<string name="companion_pairing_request_description">Bu aygıt yardımcı olarak eşleştirilsin mi?
\n
\nBu, aygıt bulma gibi bazı işlevler için tavsiye edilir ve daha iyi bir bağlantı sağlar.</string>
<string name="unbind_before_pair_title">Zaten bağlı</string>
<string name="unbind_before_pair_message">Bu aygıt Android ayarlarında zaten bağlı, bu da bazı aygıtlar için eşleştirmenin başarısız olmasına neden olabilir.
\n
\nAygıtı eklemek başarısız olursa, lütfen Android ayarlarından kaldırın ve tekrar deneyin.</string>
<string name="devicesetting_scannable_debounce">Taranabilir hata giderme zaman aşımı (saniye)</string>
<string name="devicesetting_scannable_rssi">En düşük RSSI eşiği</string>
<string name="devicesetting_scannable_debounce_summary">Tarandıktan sonra aygıt tarandı olarak kalır ve belirtilen süre boyunca yok sayılır</string>
<string name="devicetype_scannable">Taranabilir aygıt</string>
<string name="state_scanned">Tarandı</string>
<string name="devicesetting_scannable_minimum_unseen">En kısa görülmeme süresi (saniye)</string>
<string name="devicesetting_scannable_minimum_unseen_summary">Tarandıktan sonra, aygıtın tekrar kaydedilmeden önce bu süre boyunca görülmemesi gerekir</string>
<string name="devicesetting_scannable_rssi_summary">Algılama için en düşük RSSI eşiği</string>
<string name="swolfAvg">Ortalama swolf</string>
<string name="swolfMax">En yüksek swolf</string>
<string name="swolfMin">En düşük swolf</string>
<string name="stepRateSum">Adım hızı toplamı</string>
<string name="stepRateAvg">Ortalama adım hızı</string>
<string name="stepLengthAvg">Ortalama Adım Uzunluğu</string>
<string name="groundContactTimeAvg">Ortalama yerle temas süresi</string>
<string name="impactAvg">Ortalama etki</string>
<string name="impactMax">En yüksek etki</string>
<string name="swingAngleAvg">Ortalama salınım açısı</string>
<string name="foreFootLandings">Ön ayak inişi</string>
<string name="midFootLandings">Orta ayak inişi</string>
<string name="backFootLandings">Arka ayak inişi</string>
<string name="eversionAngleAvg">Ortalama ters dönme açısı</string>
<string name="eversionAngleMax">En yüksek ters dönme açısı</string>
<string name="fmtPaceDistance">Hız %d mesafe</string>
<string name="fmtPaceType">Hız %d tür</string>
<string name="fmtPacePace">Hız %d hız</string>
<string name="fmtPaceCorrection">Hız %d düzeltme</string>
<string name="fmtPaceTypeAverage">Hız Türü %d ortalama</string>
<string name="unknownDataEncountered">Bilinmeyen veriyle karşılaşıldı</string>
<string name="milliseconds">milisaniye</string>
<string name="degrees">derece</string>
<string name="Pace">Hız</string>
<string name="RunningForm">Koşu Biçimi</string>
<string name="pref_force_enable_heartrate_support">Kalp ritmi desteğini zorla</string>
<string name="pref_force_enable_heartrate_support_summary">Kalp ritmi desteğini etkinleştirmeye zorla.
\nKULLANMANIZ DURUMUNDA RİSK SİZE AİTTİR</string>
<string name="pref_force_enable_spo2_support">SpO2 desteğini zorla</string>
<string name="pref_force_enable_spo2_support_summary">SpO2 desteğini etkinleştirmeye zorla.
\nKULLANMANIZ DURUMUNDA RİSK SİZE AİTTİR</string>
<string name="activity_type_worn">Yorgun</string>
<string name="pref_dashboard_cards_title">Kartlarda widget\'ları göster</string>
<string name="error_showing_changelog">Değişiklik günlüğü gösterilirken hata oluştu</string>
<string name="dashboard_settings">Gösterge tablosu ayarları</string>
<string name="pref_dashboard_cards_summary">Gösterge tablosunda widget\'ların etrafına kartlar çiz</string>
<string name="pref_dashboard_first_title">Önce gösterge tablosunu göster</string>
<string name="pref_dashboard_first_summary">Gadgetbridge başladığında aygıtlar ekranı yerine gösterge tablosunu göster</string>
<string name="pref_dashboard_widget_settings">Widget ayarları</string>
<string name="pref_dashboard_widget_today_title">Etkinlik çizelgesi</string>
<string name="pref_dashboard_all_devices_title">Tüm aygıtlar</string>
<string name="pref_dashboard_widget_today_hr_interval_title">Kalp ritmi aralığı</string>
<string name="pref_dashboard_widget_double_size_summary">Widget\'ın gösterge tablosunda iki sütun kaplamasına izin ver</string>
<string name="pref_dashboard_widget_show_legend_summary">Widget\'ın altında renkleri açıklayan bir açıklama göster</string>
<string name="pref_dashboard_all_devices_summary">Gösterge tablosundaki toplamlar için eklenen tüm aygıtlardan gelen etkinlik verilerini birleştir</string>
<string name="bottom_nav_dashboard">Gösterge tablosu</string>
<string name="bottom_nav_devices">Aygıtlar</string>
<string name="pref_dashboard_widget_today_24h_title">24 saat modu</string>
<string name="pref_dashboard_widget_double_size_title">İki katı boyut</string>
<string name="pref_dashboard_widget_goals_chart_title">Hedefler çizelgesi</string>
<string name="pref_dashboard_devices_to_include">Dahil edilecek aygıtlar</string>
<string name="pref_dashboard_select_devices_title">Aygıtları seç...</string>
<string name="pref_dashboard_widgets_order_summary">Hangi widget\'ların etkinleştirileceğini ve gösterge tablosunda hangi sırada görüntüleneceğini seçin</string>
<string name="pref_dashboard_widget_today_24h_summary">Etkinliği iki tane 12 saatlik daire yerine bir tane 24 saatlik daire içinde göster</string>
<string name="pref_dashboard_select_devices_summary">Gösterge tablosundaki toplamlar için belirli aygıtlardan gelen etkinlik verilerini birleştir</string>
<string name="pref_dashboard_widget_today_hr_interval_summary">Her başarılı kalp ritmi ölçümünden sonra grafiğin \'yorgun\' olarak gösterdiği dakika miktarı</string>
<string name="pref_dashboard_widget_show_legend_title">ıklamaları göster</string>
<string name="pref_auto_reply_calls_summary">Telefon gelen aramaları otomatik olarak yanıtlayacaktır</string>
<string name="pref_auto_reply_calls_delay_summary">Aramanın otomatik olarak yanıtlanacağı saniye sayısı</string>
<string name="pref_auto_reply_calls_title">Telefon aramalarını otomatik yanıtla</string>
<string name="pref_auto_reply_calls_delay_title">Otomatik Yanıt Gecikmesi</string>
<string name="pref_header_audio">Ses</string>
<string name="pref_header_generic">Genel</string>
<string name="pref_title_notification_wake_on_open">Otomatik uyandır ve kilidi aç</string>
<string name="pref_summary_notification_wake_on_open">Aygıt bir OPEN (AÇ) yanıtı gönderdiğinde Android aygıtını uyandırın ve kilidini açın. Güvenilir bir durumda olması gerekir.</string>
<string name="pref_speak_notifications_aloud_summary">Bildirimler kulaklıklardan yüksek sesle okunacaktır</string>
<string name="pref_speak_notifications_aloud_title">Bildirimleri Sesli Oku</string>
<string name="devicetype_redmi_watch_4">Redmi Watch 4</string>
<string name="widget_layout_top_wide_bot_large">Yukarıda geniş, aşağıda büyük</string>
<string name="widget_layout_top_large_bot_wide">Yukarıda büyük, aşağıda geniş</string>
<string name="widget_name_colored_tile">%1$s (renkli döşeme)</string>
<string name="widget_name_untitled">Başlıksız widget (%1$s)</string>
<string name="pref_header_calls_and_notifications">Çağrılar ve bildirimler</string>
<string name="armenian">Ermenice</string>
<string name="pref_summary_bottom_navigation_bar_off">Yalnızca yatay kaydırma kullanarak ana ekranlar arasında geçiş yapın</string>
<string name="pref_summary_bottom_navigation_bar_on">Gezinme çubuğunu veya yatay kaydırmayı kullanarak ana ekranlar arasında geçiş yapın</string>
<string name="pref_title_bottom_navigation_bar">Alt gezinme çubuğu</string>
<string name="pref_dashboard_widget_today_upside_down_title">Gece yarısı altta</string>
<string name="pref_dashboard_widget_today_upside_down_summary">24 saat modunda, gece yarısını grafiğin alt kısmına, gün ortasını ise grafiğin üst kısmına çiz</string>
<string name="pref_sleepasandroid_features_summary">Destek aygıttan aygıta farklılık gösterir</string>
<string name="pref_sleepasandroid_feat_alarms">Alarmlar</string>
<string name="pref_sleepasandroid_slot_title">Alarm yuvası</string>
<string name="alarm_slot_reset">Alarm yuvası öntanımlı olarak ayarlandı</string>
<string name="pref_sleepasandroid_feat_heartrate">Kalp ritmi</string>
<string name="pref_sleepasandroid_feat_oximetry">Oksimetri</string>
<string name="pref_sleepasandroid_feat_spo2">SPO2</string>
<string name="sleepasandroid_settings">Sleep As Android</string>
<string name="pref_sleepasandroid_slot_summary">Alarmları ayarlarken hangi alarm yuvasının kullanılacağı</string>
<string name="pref_sleepasandroid_feat_notifications">Bildirimler</string>
<string name="pref_sleepasandroid_feat_movement">İvmeölçer</string>
<string name="pref_sleepasandroid_enable_summary">Sleep As Android bütünleşmesini etkinleştir</string>
<string name="pref_sleepasandroid_device_title">Sağlayıcı aygıt</string>
<string name="pref_sleepasandroid_device_summary">Sleep As Android veri sağlayıcısı olarak aygıtı seçin</string>
<string name="pref_sleepasandroid_features_title">Özellikler</string>
<string name="pref_summary_huawei_account">Eşleştirme işleminde kullanılan Huawei hesabı. Ayarlanması, fabrika ayarlarına sıfırlamadan eşleştirmeyi sağlar.</string>
<string name="pref_title_huawei_account">Huawei Hesabı</string>
<string name="serbian">Sırpça</string>
<string name="watchface_resolution_doesnt_match">Saat arayüzü çözünürlüğü aygıt ekranıyla eşleşmiyor. Saat arayüzü %1$s, aygıt ekranı %2$s</string>
<string name="cyclingPowerMin">En düşük bisiklet gücü</string>
<string name="cyclingPowerAverage">Ortalama bisiklet gücü</string>
<string name="cyclingPowerMax">En yüksek bisiklet gücü</string>
<string name="devicetype_huawei_watchfit2">Huawei Watch Fit 2</string>
</resources>

View File

@ -553,7 +553,7 @@
<string name="activity_type_activity">活动</string>
<string name="activity_type_light_sleep">浅睡眠</string>
<string name="activity_type_deep_sleep">深睡眠</string>
<string name="activity_type_not_worn">设备没有磨损</string>
<string name="activity_type_not_worn">设备没有佩戴</string>
<string name="activity_type_running">跑步</string>
<string name="activity_type_walking">走路</string>
<string name="activity_type_swimming">游泳</string>
@ -2842,4 +2842,122 @@
<string name="devicetype_huawei_watchgt4">华为手表 GT 4</string>
<string name="busy_task_fetch_sports_details_interrupted">获取运动详情时被中断</string>
<string name="devicetype_huawei_watchultimate">华为手表 Ultimate</string>
<string name="unbind_before_pair_title">已绑定</string>
<string name="companion_pairing_request_title">陪伴设备</string>
<string name="companion_pairing_request_description">将此设备配对为陪伴设备?
\n
\n建议将此功能用于某些功能例如查找设备并提供更好的连接。</string>
<string name="unbind_before_pair_message">该设备已在 Android 设置中绑定,这可能会导致某些设备配对失败。
\n
\n如果添加设备失败请在 Android 设置中将其删除,然后重试。</string>
<string name="devicetype_scannable">可扫描的设备</string>
<string name="state_scanned">已扫描</string>
<string name="devicesetting_scannable_rssi">最小 RSSI 阈值</string>
<string name="devicesetting_scannable_rssi_summary">检测的最小 RSSI 阈值</string>
<string name="devicesetting_scannable_debounce">可扫描的去抖动超时(秒)</string>
<string name="devicesetting_scannable_minimum_unseen">最短未发现时间(秒)</string>
<string name="devicesetting_scannable_debounce_summary">扫描后,设备将保持扫描状态并在指定时间内被忽略</string>
<string name="devicesetting_scannable_minimum_unseen_summary">扫描后,设备必须在这段时间内不可见,然后才能再次注册</string>
<string name="swolfAvg">平均 Swolf</string>
<string name="swolfMax">最大 Swolf</string>
<string name="swolfMin">最小 Swolf</string>
<string name="stepRateSum">步速总和</string>
<string name="stepRateAvg">平均步速</string>
<string name="stepLengthAvg">平均步长</string>
<string name="groundContactTimeAvg">平均触地时间</string>
<string name="impactAvg">平均影响</string>
<string name="impactMax">最大影响</string>
<string name="swingAngleAvg">平均摆角</string>
<string name="foreFootLandings">前脚落地</string>
<string name="midFootLandings">中足落地</string>
<string name="backFootLandings">后脚落地</string>
<string name="eversionAngleAvg">平均外翻角度</string>
<string name="eversionAngleMax">最大外翻角度</string>
<string name="fmtPaceDistance">步速 %d 距离</string>
<string name="fmtPaceType">步速 %d 类型</string>
<string name="fmtPacePace">步速 %d 步速</string>
<string name="degrees"></string>
<string name="fmtPaceCorrection">步速 %d 修正</string>
<string name="fmtPaceTypeAverage">配速类型 %d 平均值</string>
<string name="unknownDataEncountered">遇到未知数据</string>
<string name="milliseconds">毫秒</string>
<string name="Pace">步伐</string>
<string name="RunningForm">跑步形式</string>
<string name="pref_force_enable_heartrate_support">强制支持心率</string>
<string name="pref_force_enable_spo2_support">强制支持血氧</string>
<string name="pref_force_enable_heartrate_support_summary">强制启用心率支持。
\n风险自担</string>
<string name="pref_force_enable_spo2_support_summary">强制启用血氧支持。
\n风险自担</string>
<string name="pref_dashboard_devices_to_include">要包括的设备</string>
<string name="pref_dashboard_all_devices_title">所有设备</string>
<string name="pref_dashboard_select_devices_title">选择设备...</string>
<string name="pref_dashboard_widgets_order_summary">选择启用哪些小部件以及它们在仪表板上的显示顺序</string>
<string name="pref_dashboard_widget_today_24h_summary">以单个 24 小时圆圈而不是双 12 小时圆圈显示活动</string>
<string name="pref_dashboard_widget_show_legend_summary">在小部件下方显示说明颜色的图例</string>
<string name="pref_dashboard_select_devices_summary">将来自特定设备的活动数据合并到仪表板上的总计中</string>
<string name="activity_type_worn">佩戴</string>
<string name="bottom_nav_dashboard">仪表板</string>
<string name="error_showing_changelog">显示变更日志时出错</string>
<string name="dashboard_settings">仪表板设置</string>
<string name="bottom_nav_devices">设备</string>
<string name="pref_dashboard_first_title">首先显示仪表板</string>
<string name="pref_dashboard_first_summary">Gadgetbridge 启动时显示仪表板,而不是设备屏幕</string>
<string name="pref_dashboard_cards_title">在卡片上显示小部件</string>
<string name="pref_dashboard_cards_summary">在仪表板上的小部件周围绘制卡片</string>
<string name="pref_dashboard_widget_settings">小部件设置</string>
<string name="pref_dashboard_widget_today_title">活动图表</string>
<string name="pref_dashboard_widget_today_24h_title">24小时模式</string>
<string name="pref_dashboard_widget_double_size_title">双倍尺寸</string>
<string name="pref_dashboard_widget_goals_chart_title">目标图表</string>
<string name="pref_dashboard_widget_show_legend_title">显示图例</string>
<string name="pref_dashboard_widget_double_size_summary">允许小部件占据仪表板上的两列</string>
<string name="pref_dashboard_all_devices_summary">将所有添加设备的活动数据合并到仪表板上的总计中</string>
<string name="pref_dashboard_widget_today_hr_interval_title">心率区间</string>
<string name="pref_dashboard_widget_today_hr_interval_summary">每次成功测量心率后图表显示“佩戴”的分钟数</string>
<string name="pref_auto_reply_calls_summary">手机将自动接听来电</string>
<string name="pref_auto_reply_calls_title">自动接听电话</string>
<string name="pref_auto_reply_calls_delay_summary">自动接听电话之前的秒数</string>
<string name="pref_auto_reply_calls_delay_title">自动应答延迟</string>
<string name="pref_header_audio">音频</string>
<string name="pref_header_generic">普通</string>
<string name="pref_title_notification_wake_on_open">自动唤醒并解锁</string>
<string name="pref_summary_notification_wake_on_open">当小工具发回 OPEN 响应时,唤醒并解锁 Android 设备。需要处于可信状态。</string>
<string name="widget_layout_top_wide_bot_large">上面宽,下面大</string>
<string name="widget_layout_top_large_bot_wide">上面大,下面宽</string>
<string name="widget_name_colored_tile">%1$s (彩色磁贴)</string>
<string name="devicetype_redmi_watch_4">红米手表 4</string>
<string name="pref_speak_notifications_aloud_summary">通知将通过耳机大声朗读</string>
<string name="pref_speak_notifications_aloud_title">大声说出通知</string>
<string name="widget_name_untitled">无标题小部件(%1$s</string>
<string name="pref_header_calls_and_notifications">来电和通知</string>
<string name="armenian">亚美尼亚语</string>
<string name="pref_title_bottom_navigation_bar">底部导航栏</string>
<string name="pref_summary_bottom_navigation_bar_off">仅使用水平滑动在主屏幕之间切换</string>
<string name="pref_summary_bottom_navigation_bar_on">使用导航栏或横向滑动在主屏幕之间切换</string>
<string name="pref_dashboard_widget_today_upside_down_summary">在 24 小时模式下,在图表底部绘制午夜,在图表顶部绘制中午</string>
<string name="pref_dashboard_widget_today_upside_down_title">午夜在底部</string>
<string name="pref_sleepasandroid_device_summary">选择 Sleep As Android 作为设备数据提供者</string>
<string name="pref_sleepasandroid_device_title">设备提供者</string>
<string name="pref_sleepasandroid_features_title">特点</string>
<string name="pref_sleepasandroid_features_summary">支持因设备而异</string>
<string name="pref_sleepasandroid_feat_movement">加速计</string>
<string name="pref_sleepasandroid_feat_heartrate">心率</string>
<string name="pref_sleepasandroid_feat_oximetry">血氧饱和度</string>
<string name="pref_sleepasandroid_feat_spo2">SPO2</string>
<string name="pref_sleepasandroid_feat_alarms">闹钟</string>
<string name="pref_sleepasandroid_slot_summary">设置闹钟时使用哪个闹钟槽</string>
<string name="pref_sleepasandroid_slot_title">闹钟槽</string>
<string name="alarm_slot_reset">闹钟槽已设置为默认值</string>
<string name="pref_sleepasandroid_feat_notifications">通知</string>
<string name="sleepasandroid_settings">Sleep As Android</string>
<string name="pref_summary_huawei_account">配对过程中使用的华为帐号。 设置它以允许在不恢复出厂设置的情况下进行配对。</string>
<string name="pref_title_huawei_account">华为账号</string>
<string name="serbian">塞尔维亚语</string>
<string name="pref_sleepasandroid_enable_summary">启用 Sleep As Android 集成</string>
<string name="watchface_resolution_doesnt_match">表盘分辨率与设备屏幕不匹配。表盘为 %1$s 设备屏幕为 %2$s</string>
<string name="cyclingPowerMin">最小骑行功率</string>
<string name="cyclingPowerAverage">平均骑行功率</string>
<string name="cyclingPowerMax">最大骑行功率</string>
<string name="devicetype_huawei_watchfit2">华为 Watch Fit 2</string>
</resources>

View File

@ -3441,6 +3441,27 @@
<item>as_off</item>
</string-array>
<string-array name="soundcore_button_function_names">
<item>@string/pref_media_volumedown</item>
<item>@string/pref_media_volumeup</item>
<item>@string/pref_media_next</item>
<item>@string/pref_media_previous</item>
<item>@string/pref_media_playpause</item>
<item>@string/pref_title_touch_voice_assistant</item>
<item>@string/sony_button_mode_ambient_sound_control</item>
</string-array>
<string-array name="soundcore_button_function_values">
<item>VOLUME_DOWN</item>
<item>VOLUME_UP</item>
<item>MEDIA_NEXT</item>
<item>MEDIA_PREV</item>
<item>PLAYPAUSE</item>
<item>VOICE_ASSISTANT</item>
<item>AMBIENT_SOUND_CONTROL</item>
</string-array>
<string-array name="fitness_tracking_apps_package_names">
<item>de.dennisguse.opentracks</item>
<item>de.dennisguse.opentracks.playStore</item>

View File

@ -520,6 +520,10 @@
<string name="pref_gps_satellite_search">Satellite Search</string>
<string name="pref_crown_vibration">Crown Vibration</string>
<string name="pref_alert_tone">Alert Tone</string>
<string name="pref_touch_tone">Touch Tone</string>
<string name="pref_touch_tone_summary">Plays a tone when the earbud is touched</string>
<string name="pref_wearing_tone">Wearing Tone</string>
<string name="pref_wearing_tone_summary">Plays a tone when the earbud is inserted</string>
<string name="pref_cover_to_mute">Cover to Mute</string>
<string name="pref_vibrate_for_alert">Vibrate for Alert</string>
<string name="pref_text_to_speech">Text to Speech</string>
@ -1533,6 +1537,7 @@
<string name="devicetype_sony_wi_sp600n">Sony WI-SP600N</string>
<string name="devicetype_sony_linkbuds">Sony LinkBuds</string>
<string name="devicetype_sony_linkbuds_s">Sony LinkBuds S</string>
<string name="devicetype_soundcore_liberty3_pro">Soundcore Liberty 3 Pro</string>
<string name="devicetype_binary_sensor">Binary sensor</string>
<string name="devicetype_honor_band3">Honor Band 3</string>
<string name="devicetype_honor_band4">Honor Band 4</string>
@ -1552,6 +1557,7 @@
<string name="devicetype_huawei_watchgt3">Huawei Watch GT 3 (Pro)</string>
<string name="devicetype_huawei_watchgt4">Huawei Watch GT 4</string>
<string name="devicetype_huawei_watchfit">Huawei Watch Fit</string>
<string name="devicetype_huawei_watchfit2">Huawei Watch Fit 2</string>
<string name="devicetype_huawei_watchultimate">Huawei Watch Ultimate</string>
<string name="devicetype_femometer_vinca2">Femometer Vinca II</string>
<string name="devicetype_xiaomi_watch_lite">Xiaomi Watch Lite</string>
@ -1907,6 +1913,9 @@
<string name="fmtPaceCorrection">Pace %d correction</string>
<string name="fmtPaceTypeAverage">Pace Type %d average</string>
<string name="unknownDataEncountered">Unknown data encountered</string>
<string name="cyclingPowerAverage">Average cycling power</string>
<string name="cyclingPowerMin">Min cycling power</string>
<string name="cyclingPowerMax">Max cycling power</string>
<!-- activity summary units-->
<string name="meters">m</string>
<string name="cm">cm</string>
@ -2280,6 +2289,8 @@
<string name="pref_wide_area_tap_title">Wide area tap</string>
<string name="pref_adaptive_volume_control_summary">Increase volume automatically when ambient sound is loud</string>
<string name="pref_adaptive_volume_control_title">Adaptive volume control</string>
<string name="pref_adaptive_noise_cancelling_title">Adaptive ANC</string>
<string name="pref_adaptive_noise_cancelling_summary">Set the strength of the ANC automatically depending on the ambient sound level</string>
<string name="sony_speak_to_chat">Speak-to-chat</string>
<string name="sony_speak_to_chat_summary">Turn off noise cancelling automatically when you start talking.</string>
<string name="sony_speak_to_chat_sensitivity">Voice Detection Sensitivity</string>
@ -2377,6 +2388,7 @@
<string name="huawei_trusleep_title">HUAWEI TruSleep &#8482;</string>
<string name="huawei_trusleep_summary">Monitor your sleep quality and breathing pattern in real time.\nAnalyze your sleep patterns and accurately diagnose 6 types of sleeping problems.</string>
<string name="huawei_trusleep_summary_light">Improved sleep monitoring</string>
<string name="huawei_trusleep_warning">Warning: enabling this will stop sleep from showing up in Gadgetbridge! Click here if you accept this.</string>
<string name="prefs_activity_recognition">Activity recognition settings</string>
<string name="pref_activity_recognize_running">recognize running</string>
<string name="pref_activity_recognize_biking">recognize biking</string>

View File

@ -0,0 +1,18 @@
<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<EditTextPreference
android:defaultValue="5"
android:icon="@drawable/ic_always_on_display"
android:key="hplus_screentime"
android:title="@string/pref_title_screentime"
app:useSimpleSummaryProvider="true" />
<SwitchPreferenceCompat
android:defaultValue="true"
android:icon="@drawable/ic_heart"
android:key="hplus_alldayhr"
android:layout="@layout/preference_checkbox"
android:title="@string/prefs_title_all_day_heart_rate" />
</PreferenceScreen>

View File

@ -0,0 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.preference.PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
<PreferenceScreen
android:icon="@drawable/ic_touch"
android:key="pref_screen_touch_options"
android:persistent="false"
android:title="@string/prefs_galaxy_touch_options">
</PreferenceScreen>
</androidx.preference.PreferenceScreen>

View File

@ -0,0 +1,76 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.preference.PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
<PreferenceCategory
android:key="pref_key_header_soundcore_ambient_sound_control"
android:title="@string/pref_header_sony_ambient_sound_control">
<ListPreference
android:defaultValue="noise_cancelling"
android:entries="@array/sony_ambient_sound_control_names"
android:entryValues="@array/sony_ambient_sound_control_values"
android:icon="@drawable/ic_hearing"
android:key="pref_soundcore_ambient_sound_control"
android:summary="%s"
android:title="@string/sony_ambient_sound" />
<SwitchPreferenceCompat
android:defaultValue="true"
android:disableDependentsState="true"
android:icon="@drawable/ic_hearing"
android:key="pref_adaptive_noise_cancelling"
android:layout="@layout/preference_checkbox"
android:summary="@string/pref_adaptive_noise_cancelling_summary"
android:title="@string/pref_adaptive_noise_cancelling_title" />
<!-- [0, 2], low moderate and high -->
<SeekBarPreference
android:dependency="pref_adaptive_noise_cancelling"
android:defaultValue="0"
android:icon="@drawable/ic_hearing"
android:key="pref_sony_ambient_sound_level"
android:max="2"
android:title="@string/prefs_active_noise_cancelling_level" />
<SwitchPreferenceCompat
android:defaultValue="false"
android:icon="@drawable/ic_block"
android:key="pref_soundcore_wind_noise_reduction"
android:layout="@layout/preference_checkbox"
android:title="@string/sony_ambient_sound_wind_noise_reduction" />
<SwitchPreferenceCompat
android:defaultValue="false"
android:icon="@drawable/ic_voice"
android:key="pref_soundcore_transparency_vocal_mode"
android:layout="@layout/preference_checkbox"
android:title="@string/sony_ambient_sound_focus_voice" />
</PreferenceCategory>
<PreferenceCategory
android:key="pref_key_header_soundcore_other"
android:title="@string/pref_header_other">
<SwitchPreferenceCompat
android:defaultValue="false"
android:layout="@layout/preference_checkbox"
android:summary="@string/nothing_prefs_inear_summary"
android:title="@string/nothing_prefs_inear_title"/>
<SwitchPreferenceCompat
android:defaultValue="false"
android:key="pref_soundcore_wearing_tone"
android:layout="@layout/preference_checkbox"
android:summary="@string/pref_wearing_tone_summary"
android:title="@string/pref_wearing_tone"/>
<SwitchPreferenceCompat
android:defaultValue="false"
android:key="pref_soundcore_touch_tone"
android:layout="@layout/preference_checkbox"
android:summary="@string/pref_touch_tone_summary"
android:title="@string/pref_touch_tone"/>
</PreferenceCategory>
</androidx.preference.PreferenceScreen>

View File

@ -0,0 +1,107 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.preference.PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
<PreferenceCategory android:title="@string/single_tap">
<SwitchPreferenceCompat
android:defaultValue="false"
android:disableDependentsState="true"
android:icon="@drawable/ic_lock_open"
android:key="pref_soundcore_control_single_tap_disabled"
android:layout="@layout/preference_checkbox"
android:summary="@string/prefs_touch_lock_summary"
android:title="@string/prefs_touch_lock" />
<ListPreference
android:dependency="pref_soundcore_control_single_tap_disabled"
android:entries="@array/soundcore_button_function_names"
android:entryValues="@array/soundcore_button_function_values"
android:icon="@drawable/ic_touch"
android:key="pref_soundcore_control_single_tap_action_left"
android:summary="%s"
android:title="@string/prefs_left" />
<ListPreference
android:dependency="pref_soundcore_control_single_tap_disabled"
android:entries="@array/soundcore_button_function_names"
android:entryValues="@array/soundcore_button_function_values"
android:icon="@drawable/ic_touch"
android:key="pref_soundcore_control_single_tap_action_right"
android:summary="%s"
android:title="@string/prefs_right" />
</PreferenceCategory>
<PreferenceCategory android:title="@string/double_tap">
<SwitchPreferenceCompat
android:defaultValue="false"
android:disableDependentsState="true"
android:icon="@drawable/ic_lock_open"
android:key="pref_soundcore_control_double_tap_disabled"
android:layout="@layout/preference_checkbox"
android:summary="@string/prefs_touch_lock_summary"
android:title="@string/prefs_touch_lock" />
<ListPreference
android:dependency="pref_soundcore_control_double_tap_disabled"
android:entries="@array/soundcore_button_function_names"
android:entryValues="@array/soundcore_button_function_values"
android:icon="@drawable/ic_touch"
android:key="pref_soundcore_control_double_tap_action_left"
android:summary="%s"
android:title="@string/prefs_left" />
<ListPreference
android:dependency="pref_soundcore_control_double_tap_disabled"
android:entries="@array/soundcore_button_function_names"
android:entryValues="@array/soundcore_button_function_values"
android:icon="@drawable/ic_touch"
android:key="pref_soundcore_control_double_tap_action_right"
android:summary="%s"
android:title="@string/prefs_right" />
</PreferenceCategory>
<PreferenceCategory android:title="@string/triple_tap">
<SwitchPreferenceCompat
android:defaultValue="false"
android:disableDependentsState="true"
android:icon="@drawable/ic_lock_open"
android:key="pref_soundcore_control_triple_tap_disabled"
android:layout="@layout/preference_checkbox"
android:summary="@string/prefs_touch_lock_summary"
android:title="@string/prefs_touch_lock" />
<ListPreference
android:dependency="pref_soundcore_control_triple_tap_disabled"
android:entries="@array/soundcore_button_function_names"
android:entryValues="@array/soundcore_button_function_values"
android:icon="@drawable/ic_touch"
android:key="pref_soundcore_control_triple_tap_action_left"
android:summary="%s"
android:title="@string/prefs_left" />
<ListPreference
android:dependency="pref_soundcore_control_triple_tap_disabled"
android:entries="@array/soundcore_button_function_names"
android:entryValues="@array/soundcore_button_function_values"
android:icon="@drawable/ic_touch"
android:key="pref_soundcore_control_triple_tap_action_right"
android:summary="%s"
android:title="@string/prefs_right" />
</PreferenceCategory>
<PreferenceCategory android:title="@string/long_press">
<SwitchPreferenceCompat
android:defaultValue="false"
android:disableDependentsState="true"
android:icon="@drawable/ic_lock_open"
android:key="pref_soundcore_control_long_press_disabled"
android:layout="@layout/preference_checkbox"
android:summary="@string/prefs_touch_lock_summary"
android:title="@string/prefs_touch_lock" />
<ListPreference
android:dependency="pref_soundcore_control_long_press_disabled"
android:entries="@array/soundcore_button_function_names"
android:entryValues="@array/soundcore_button_function_values"
android:icon="@drawable/ic_touch"
android:key="pref_soundcore_control_long_press_action_left"
android:summary="%s"
android:title="@string/prefs_left" />
<ListPreference
android:dependency="pref_soundcore_control_long_press_disabled"
android:entries="@array/soundcore_button_function_names"
android:entryValues="@array/soundcore_button_function_values"
android:icon="@drawable/ic_touch"
android:key="pref_soundcore_control_long_press_action_right"
android:summary="%s"
android:title="@string/prefs_right" />
</PreferenceCategory>
</androidx.preference.PreferenceScreen>

View File

@ -1,19 +1,26 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.preference.PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
<PreferenceScreen
android:icon="@drawable/ic_access_time"
android:icon="@drawable/ic_activity_sleep"
android:key="screen_trusleep"
android:persistent="false"
android:title="@string/huawei_trusleep_title"
android:summary="@string/huawei_trusleep_summary_light">
<SwitchPreferenceCompat
android:icon="@drawable/ic_access_time"
android:defaultValue="false"
android:key="trusleep"
android:layout="@layout/preference_checkbox"
<PreferenceScreen
android:icon="@drawable/ic_activity_sleep"
android:key="screen_trusleep_warning"
android:title="@string/huawei_trusleep_title"
android:summary="@string/huawei_trusleep_summary"/>
android:summary="@string/huawei_trusleep_warning">
<SwitchPreferenceCompat
android:icon="@drawable/ic_activity_sleep"
android:defaultValue="false"
android:key="trusleep"
android:layout="@layout/preference_checkbox"
android:title="@string/huawei_trusleep_title"
android:summary="@string/huawei_trusleep_summary"/>
</PreferenceScreen>
</PreferenceScreen>
</androidx.preference.PreferenceScreen>

View File

@ -1,23 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<PreferenceCategory
android:key="pref_category_hplus_general"
android:title="@string/pref_header_general"
app:iconSpaceReserved="false">
<EditTextPreference
android:defaultValue="5"
android:key="hplus_screentime"
android:title="@string/pref_title_screentime"
app:iconSpaceReserved="false"
app:useSimpleSummaryProvider="true"/>
<SwitchPreferenceCompat
android:defaultValue="true"
android:key="hplus_alldayhr"
android:layout="@layout/preference_checkbox"
android:title="@string/prefs_title_all_day_heart_rate"
app:iconSpaceReserved="false" />
</PreferenceCategory>
</PreferenceScreen>

View File

@ -285,11 +285,6 @@
android:key="pref_key_pebble"
android:title="@string/pref_title_pebble_settings">
</Preference>
<Preference
android:icon="@drawable/ic_device_hplus"
android:key="pref_key_hplus"
android:title="@string/preferences_hplus_settings">
</Preference>
<Preference
android:icon="@drawable/ic_device_zetime"
android:key="pref_key_zetime"

View File

@ -259,6 +259,14 @@ public class TestWorkout {
byte backFootLanding2 = 0x26;
byte eversionAngle2 = 0x27;
// TODO: Add:
// - swolf
// - stoke rate
// - calories
// - cycling power
// - frequency
// - altitude
ByteBuffer headerBuf = ByteBuffer.allocate(14);
headerBuf.putShort(workoutNumber);
headerBuf.putShort(dataNumber);

View File

@ -33,6 +33,19 @@ public class ArmenianTransliteratorTest extends TestCase {
new ArmenianTransliterator().transliterate("որը jet iridescent կառուցում են sheen Վիքիպեդիա կայքից օգտվողները and a distinctive ազատ խմբագրման ձևաչափով"));
}
@Test
public void testMixedCaseWords() {
Assert.assertEquals(
"Inchpes", new ArmenianTransliterator().transliterate("Ինչպես")
);
Assert.assertEquals(
"VOrՕSHEL", new ArmenianTransliterator().transliterate("ՈրՈՇԵԼ")
);
Assert.assertEquals(
"Ushadir", new ArmenianTransliterator().transliterate("Ուշադիր")
);
}
@Test
public void testTop100Words() {

View File

@ -53,7 +53,7 @@ public class LanguageUtilsTest extends TestBase {
final Map<String, String> tests = new LinkedHashMap<String, String>() {{
put("Тхе qицк брон фоx јумпед овер тхе лаз* дог", "The qick bron fox jumped over the laz* dog");
put("Српска ћирилица", "Srpska cirilica");
put("Novak Đoković", "Novak Dokovic");
put("Novak Đoković", "Novak Djokovic");
put("Џ, Њ and Љ", "Dz, Nj and Lj");
put("Љуљачка", "Ljuljacka");
put("Наковањ", "Nakovanj");
@ -63,7 +63,7 @@ public class LanguageUtilsTest extends TestBase {
put("Ћ, ћ", "C, c");
put("Ж, ж", "Z, z");
put("Ш, ш", "S, s");
put("Ђ, ђ", "D, d");
put("Ђ, ђ", "Dj, dj");
put("Џ, џ", "Dz, dz");
put("Њ, њ", "Nj, nj");
put("Љ, љ", "Lj, lj");