diff --git a/BatteryReporting.md b/BatteryReporting.md index 37a2595..5a9fbb5 100644 --- a/BatteryReporting.md +++ b/BatteryReporting.md @@ -2,91 +2,27 @@ From version 2.1 the application includes a background service to report the current device battery level and charging status back to Home Assistant. This is a feature that Garmin omitted to include with the Bluetooth connection. -We've had [a report](https://github.com/house-of-abbey/GarminHomeAssistant/issues/39) that this feature does not work without **administrator priviledges**. We've reviewed possible fixes and come up short. We are unable to fix this at present but invite those skilled in the art of Home Assistant to suggest a solution to us! - ## Start Reporting The main drawback of this solution is that the Garmin application must be run once with the feature enabled in the settings before reporting will start. Reporting continues after you have exited the application. This is a limit we cannot code around. +It should be as simple as that, there should be a new device in the mobile app integration called `Garmin Watch` with the battery level and charging status. + +[![Open your Home Assistant instance and show an integration.](https://my.home-assistant.io/badges/integration.svg)](https://my.home-assistant.io/redirect/integration/?domain=mobile_app) + +If this is not the case, head over to the [troubleshooting page](Troubleshooting.md#watch-battery-level-reporting). + ## Stop Reporting To stop the reporting, the option must be turned off in the settings and then the application run once. Running the application then removes the background service. In both cases, the enable and repeat time settings can be changed whilst the application is running (i.e. live) and the background service will be amended. -## Listening for the `device_id` - -Open the event viewer in Home Assistant and add `garmin.battery_level` as the event to listen to as shown below. - -[![Open your Home Assistant instance and show your event developer tools.](https://my.home-assistant.io/badges/developer_events.svg)](https://my.home-assistant.io/redirect/developer_events/) - - - -```yaml -event_type: garmin.battery_level -data: - level: 45.072266 - device_id: e1004acb747607bc205a6ff7bd05a4c12faf3d6d - is_charging: false -origin: REMOTE -time_fired: "2024-01-01T18:15:35.900991+00:00" -context: - id: 01HK33T06WW4D9NEXJ9F6SRYNY - parent_id: null - user_id: 35e0e5a7e4bc49e9a328743697c58b90 -``` - -The `device_id` is consistent for our purposes. It does change between devices and also between the 'application' and 'widget' installations. Different device model simulators also vary the `device_id`. Here we want to extract `e1004acb747607bc205a6ff7bd05a4c12faf3d6d` for use in the sample YAML `trigger` above. - -## Setting up the trigger to update the entity - -The watch will send HTTP requests to HomeAssistant every 5+ minutes in a background service. The events produced by the HTTP requests can be listened for with a template entity. In this case we have two (battery level and is charging). - -```yaml - - trigger: - - platform: "event" - event_type: "garmin.battery_level" - event_data: - device_id: "" - sensor: - - name: " Battery Level" - unique_id: "" - device_class: "battery" - unit_of_measurement: "%" - state_class: "measurement" - state: "{{ trigger.event['data']['level'] }}" - icon: mdi:battery{% if trigger.event['data']['is_charging'] %}-charging{% endif %}{% if 0 < (trigger.event['data']['level'] | float / 10 ) | round(0) * 10 < 100 %}-{{ (trigger.event['data']['level'] | float / 10 ) | round(0) * 10 }}{% else %}{% if (trigger.event['data']['level'] | float / 10 ) | round(0) * 10 == 0 %}-outline{% else %}{% if trigger.event['data']['is_charging'] %}-100{% endif %}{% endif %}{% endif %} - attributes: - device_id: "" - - trigger: - - platform: "event" - event_type: "garmin.battery_level" - event_data: - device_id: "" - binary_sensor: - - name: " is Charging" - unique_id: "" - device_class: "battery_charging" - state: "{{ trigger.event['data']['is_charging'] }}" - attributes: - device_id: "" -``` - -1. Copy this yaml to your `configuration.yaml`. -2. Swap `` for the name of your device (This can be anything and is purely for the UI). Swap `` and `` for two different unique identifiers (in the Studio Code Server these can be generated from the right click menu). -3. Open the event dashboard and start listening for `garmin.battery_level` events and when your recieve one copy the device id and replace `` with it (to speed up this process you can close and reopen the GarminHomeAssistant app). - -[![Open your Home Assistant instance and show your event developer tools.](https://my.home-assistant.io/badges/developer_events.svg)](https://my.home-assistant.io/redirect/developer_events/) - -4. Restart HomeAssistant or reload the YAML. - -[![Open your Home Assistant instance and show your server controls.](https://my.home-assistant.io/badges/server_controls.svg)](https://my.home-assistant.io/redirect/server_controls/) - ## Adding a sample Home Assistant UI widget -A gauge for battery level with a chargin icon making use of [mushroom cards](https://github.com/piitaya/lovelace-mushroom), [card_mod](https://github.com/thomasloven/lovelace-card-mod) and [stack-in-card](https://github.com/custom-cards/stack-in-card): +A gauge for battery level with a charging icon making use of [mushroom cards](https://github.com/piitaya/lovelace-mushroom), [card_mod](https://github.com/thomasloven/lovelace-card-mod) and [stack-in-card](https://github.com/custom-cards/stack-in-card): - + ```yaml type: custom:stack-in-card @@ -103,7 +39,7 @@ cards: conditions: - condition: state entity: binary_sensor._is_charging - state: 'on' + state: "on" chip: type: entity icon_color: yellow @@ -119,7 +55,7 @@ cards: conditions: - condition: state entity: binary_sensor._is_charging - state: 'off' + state: "off" chip: type: entity entity: sensor._battery_level @@ -132,7 +68,7 @@ cards: } - type: gauge entity: sensor._battery_level - unit: '%' + unit: "%" name: Watch needle: false severity: diff --git a/Troubleshooting.md b/Troubleshooting.md index 2e6f6c1..1d2e0cd 100644 --- a/Troubleshooting.md +++ b/Troubleshooting.md @@ -10,8 +10,8 @@ You can purchase cloud-based access to your Home Assistant from [Nabu Casa](http ![Nabu Casa Setup](images/nabu_casa_setup.png) -* Your API URL would be of the format `https://.ui.nabu.casa/api` -* Your Garmin Watch Menu would be of the format Menu: `https://.ui.nabu.casa/local/garmin/menu.json` +- Your API URL would be of the format `https://.ui.nabu.casa/api` +- Your Garmin Watch Menu would be of the format Menu: `https://.ui.nabu.casa/local/garmin/menu.json` Where `` is your personal Nabu Casa account ID. @@ -23,21 +23,21 @@ Before Nabu Casa, or if you wanted to manage your own infrastructure, you might Now you have to manage: -* Dynamic DNS -* Public access via router port forwarding -* Security via HTTPS and URL forwarding -* Certificates for HTTPS via say [Let's Encrypt](https://letsencrypt.org/) (Nginx web server helps here) -* Proxy allow list in `configuration.yaml` as follows: +- Dynamic DNS +- Public access via router port forwarding +- Security via HTTPS and URL forwarding +- Certificates for HTTPS via say [Let's Encrypt](https://letsencrypt.org/) (Nginx web server helps here) +- Proxy allow list in `configuration.yaml` as follows: ```yaml http: use_x_forwarded_for: true trusted_proxies: - 127.0.0.1 - - 192.168.xx.xx # Server IP - AMEND THIS + - 192.168.xx.xx # Server IP - AMEND THIS - 172.30.32.0/23 # Docker IPs for NGINX - 172.30.33.0/24 # SSL proxy server - - 172.16.0.0/12 # + - 172.16.0.0/12 # ``` ### Menu Configuration URL @@ -57,7 +57,7 @@ The menu configuration can be hosted anywhere, it does not have to be on the Hom This is slightly trickier owning to the need to supply the API key. Here are three ways you can test your API URL is correctly configured. If successful, each of these should produce a JSON string output looking like: ```json -{"message":"API running."} +{ "message": "API running." } ``` #### API: Linux, MacOS, UNIX, Cygwin etc @@ -110,7 +110,7 @@ There's an online way of testing the API URL too, thanks to [REQBIN](https://req ## Watch Battery Level Reporting -For this you will need to have already got the main application or widget working with a menu in order to prove that the API calls are successful. We have proven this works with both our home brew infrastructure as well as Nabu Casa. Now with a script similar to one of the following two, you should be able to fake the watch API call and verify receipt by Home Assistant in the Event logging as shown in '[Listening for the `device_id`](BatteryReporting.md#listening-for-the-device_id)'. +For this you will need to have already got the main application or widget working with a menu in order to prove that the API calls are successful. We have proven this works with both our home brew infrastructure as well as Nabu Casa. Now with a script similar to one of the following two, you should be able to fake the watch API call and verify receipt by Home Assistant. #### Battery: Linux, MacOS, UNIX, Cygwin etc @@ -123,7 +123,7 @@ Assume a file called: `send_battery.bash` # ./send_battery.bash 19 0 # -API_KEY="" +WEBHOOK_ID="" URL="https:///api" level=${1:-50} @@ -138,10 +138,9 @@ echo "Battery Charging? = ${is_charging}" echo "" curl -s -X POST \ - -H "Authorization: Bearer ${API_KEY}" \ -H "Content-Type: application/json" \ - -d '{"level": '${level}', "is_charging": '${is_charging}', "device_id": "Bash Script"}' \ - ${URL}/events/garmin.battery_level + -d '{ "type": "update_sensor_states", "data": [ {"state": ${level},"type": "sensor","unique_id": "battery_level"}, {"state": ${is_charging},"type": "binary_sensor","unique_id": "battery_is_charging"} ] }' \ + ${URL}/webhook/${WEBHOOK_ID} ``` Execute: @@ -156,7 +155,15 @@ The output looks like this: Battery Level = 45 Battery Charging? = true -{"message":"Event garmin.battery_level fired."} +{ + "battery_level": { + "success": true + }, + "battery_is_charging": { + "success": true + } +} + ``` NB. The device ID can be any string for the purposes of this testing. Your Garmin device will choose this ID for you when it submits the readings. @@ -171,7 +178,7 @@ rem battery% charging {0|1} rem ./home_assistant_battery_level 19 0 rem -set API_KEY=FEt_fGzW_lV0xitvJPkaQHSLhGm90ADovgMbJxdHH2I +set WEBHOOK_ID= set URL=https:///api if [%1] == [] ( @@ -195,10 +202,9 @@ echo "Battery Charging? = %is_charging%" echo. curl -s -X POST ^ - -H "Authorization: Bearer %API_KEY%" ^ -H "Content-Type: application/json" ^ - -d "{\"level\": %level%, \"is_charging\": %is_charging%, \"device_id\": \"Batch File\"}" ^ - %URL%/events/garmin.battery_level + -d "{ \"type\": \"update_sensor_states\", \"data\": [ {\"state\": %level%,\"type\": \"sensor\",\"unique_id\": \"battery_level\"}, {\"state\": %is_charging%,\"type\": \"binary_sensor\",\"unique_id\": \"battery_is_charging\"} ] }" ^ + %URL%/webhook/%WEBHOOK_ID% echo. pause @@ -216,7 +222,15 @@ The output looks like this: "Battery Level = 41" "Battery Charging? = true" -{"message":"Event garmin.battery_level fired."} +{ + "battery_level": { + "success": true + }, + "battery_is_charging": { + "success": true + } +} + Press any key to continue . . . ``` @@ -237,7 +251,21 @@ https:///api/events/garmin.battery_level JSON for copy & paste: ```json -{"level": 19, "is_charging": true, "device_id": "REQBIN"} +{ + "type": "update_sensor_states", + "data": [ + { + "state": 19, + "type": "sensor", + "unique_id": "battery_level" + }, + { + "state": true, + "type": "binary_sensor", + "unique_id": "battery_is_charging" + } + ] +} ``` ![API Test REQBIN](images/api_test_online_battery2.png) diff --git a/compile_sim.cmd b/compile_sim.cmd index a3f3159..34e75b7 100644 --- a/compile_sim.cmd +++ b/compile_sim.cmd @@ -28,7 +28,8 @@ set SDK_PATH=%SDK_PATH:~0,-1%\bin rem Assume we can create and use this directory set DEST=export rem Device for simulation -set DEVICE=venu2 +rem set DEVICE=venu2 +set DEVICE=vivoactive3 rem C:\>java -jar %SDK_PATH%\monkeybrains.jar -h rem usage: monkeyc [-a ] [-b ] [--build-stats ] [-c ] [-d ] @@ -100,7 +101,8 @@ rem Compile PRG for a single device for side loading --jungles %SRC%\monkey.jungle ^ --private-key %SRC%\..\developer_key ^ --device %DEVICE%_sim ^ - --warn + --warn ^ + --release if %ERRORLEVEL% equ 0 ( %SDK_PATH%\monkeydo.bat %SRC%\bin\HomeAssistant.prg %DEVICE% diff --git a/images/Battery_Event_Screenshot.png b/images/Battery_Event_Screenshot.png deleted file mode 100644 index 60a1574..0000000 Binary files a/images/Battery_Event_Screenshot.png and /dev/null differ diff --git a/resources-ara/strings/strings.xml b/resources-ara/strings/strings.xml index 103989b..1905f18 100644 --- a/resources-ara/strings/strings.xml +++ b/resources-ara/strings/strings.xml @@ -38,10 +38,11 @@ لم يتم إرجاع JSON من طلب HTTP. قام طلب HTTP بإرجاع رمز الخطأ = يجب ألا يحتوي عنوان URL لواجهة برمجة التطبيقات على شرطة مائلة لاحقة '/' + فشل تسجيل Webhook متاح تدقيق... غير متوفره - غير مهيأ + غير مكون مخبأة قائمة طعام @@ -63,4 +64,4 @@ (القطعة فقط) قم بتشغيل التطبيق تلقائيًا من الأداة دون انتظار نقرة واحدة. قم بتمكين خدمة الخلفية لإرسال مستوى بطارية الساعة إلى Home Assistant. معدل التحديث (بالدقائق) الذي يجب أن تكرر عنده خدمة الخلفية إرسال مستوى البطارية. - \ No newline at end of file + diff --git a/resources-bul/strings/strings.xml b/resources-bul/strings/strings.xml index 0b7369e..8beed3c 100644 --- a/resources-bul/strings/strings.xml +++ b/resources-bul/strings/strings.xml @@ -38,6 +38,7 @@ Няма върнат JSON от HTTP заявка. HTTP заявката върна код на грешка = URL адресът на API не трябва да има наклонена черта '/' в края + Неуспешно регистриране на Webhook На разположение Проверка... Недостъпен @@ -53,7 +54,7 @@ Трябва ли приложението да кешира конфигурацията на менюто? Трябва ли приложението да изчисти съществуващия кеш при следващото стартиране? Изчакване в секунди. Излезте от приложението след този период на неактивност, за да запазите батерията на устройството. - След това време (в секунди) диалоговият прозорец за потвърждение за действие се затваря автоматично и действието се отменя. Задайте 0, за да деактивирате изчакването. + След това време (в секунди) диалоговият прозорец за потвърждение на действие се затваря автоматично и действието се отменя. Задайте 0, за да деактивирате изчакването. Стил на елемент от менюто. Икони Допълнителен текст @@ -63,4 +64,4 @@ (Само за джаджа) Автоматично стартирайте приложението от джаджата, без да чакате докосване. Активирайте фоновата услуга, за да изпратите нивото на батерията на часовника до Home Assistant. Честотата на опресняване (в минути), с която фоновата услуга трябва да повтори изпращането на нивото на батерията. - \ No newline at end of file + diff --git a/resources-ces/strings/strings.xml b/resources-ces/strings/strings.xml index 884b67d..486821c 100644 --- a/resources-ces/strings/strings.xml +++ b/resources-ces/strings/strings.xml @@ -38,6 +38,7 @@ Z požadavku HTTP se nevrátil žádný JSON. Požadavek HTTP vrátil kód chyby = Adresa URL rozhraní API nesmí mít koncové lomítko „/“ + Registrace Webhooku se nezdařila Dostupný Kontrola... Není k dispozici @@ -63,4 +64,4 @@ (Pouze widget) Automaticky spusťte aplikaci z widgetu bez čekání na klepnutí. Povolte službu na pozadí, aby odeslala stav baterie hodin do Home Assistant. Obnovovací frekvence (v minutách), při které by služba na pozadí měla opakovat odesílání úrovně baterie. - \ No newline at end of file + diff --git a/resources-dan/strings/strings.xml b/resources-dan/strings/strings.xml index bd76f84..609826e 100644 --- a/resources-dan/strings/strings.xml +++ b/resources-dan/strings/strings.xml @@ -38,6 +38,7 @@ Ingen JSON returneret fra HTTP-anmodning. HTTP-anmodning returnerede fejlkode = API URL må ikke have en efterfølgende skråstreg '/' + Kunne ikke registrere Webhook Ledig Tjekker... Ikke tilgængelig @@ -57,10 +58,10 @@ Menupunkt stil. Ikoner Yderligere tekst - Venstre (fra) eller Højre (til) menujustering. + Venstre (fra) eller højre (til) menujustering. Venstre til højre Højre til venstre (Kun widget) Start automatisk applikationen fra widgetten uden at vente på et tryk. Aktiver baggrundstjenesten for at sende urets batteriniveau til Home Assistant. Opdateringshastigheden (i minutter), hvormed baggrundstjenesten skal gentage afsendelsen af ​​batteriniveauet. - \ No newline at end of file + diff --git a/resources-deu/strings/strings.xml b/resources-deu/strings/strings.xml index 416987d..d2ba9cc 100644 --- a/resources-deu/strings/strings.xml +++ b/resources-deu/strings/strings.xml @@ -38,6 +38,7 @@ Von der HTTP-Anfrage wurde kein JSON zurückgegeben. Die HTTP-Anfrage gab folgenden Fehlercode zurück = Die API-URL darf keinen abschließenden Schrägstrich „/“ enthalten. + Webhook konnte nicht registriert werden Verfügbar Überprüfung... Nicht verfügbar @@ -63,4 +64,4 @@ (Nur Widget) Starten Sie die Anwendung automatisch über das Widget, ohne auf einen Tipp warten zu müssen. Aktivieren Sie den Hintergrunddienst, um den Batteriestand der Uhr an Home Assistant zu senden. Die Aktualisierungsrate (in Minuten), mit der der Hintergrunddienst das Senden des Akkustands wiederholen soll. - \ No newline at end of file + diff --git a/resources-dut/strings/strings.xml b/resources-dut/strings/strings.xml index d060776..536e6cb 100644 --- a/resources-dut/strings/strings.xml +++ b/resources-dut/strings/strings.xml @@ -38,17 +38,18 @@ Er is geen JSON geretourneerd door een HTTP-verzoek. HTTP-verzoek retourneerde foutcode = API-URL mag geen afsluitende slash '/' bevatten + Registreren van Webhook is mislukt Beschikbaar Controleren... Niet beschikbaar Niet geconfigureerd In cache opgeslagen Menu - + Selecteer... API-sleutel voor HomeAssistant. Toegangstoken met lange levensduur. - URL voor HomeAssistant API. + URL voor HomeAssistant-API. URL voor menuconfiguratie (JSON). Moet de applicatie de menuconfiguratie in de cache opslaan? Moet de applicatie de volgende keer dat deze wordt gestart de bestaande cache wissen? @@ -63,4 +64,4 @@ (Alleen Widget) Start de applicatie automatisch vanuit de widget zonder te wachten op een tik. Schakel de achtergrondservice in om het batterijniveau van de klok naar Home Assistant te sturen. De vernieuwingsfrequentie (in minuten) waarmee de achtergrondservice het batterijniveau opnieuw moet verzenden. - \ No newline at end of file + diff --git a/resources-est/strings/strings.xml b/resources-est/strings/strings.xml index c21f25e..c671361 100644 --- a/resources-est/strings/strings.xml +++ b/resources-est/strings/strings.xml @@ -35,9 +35,10 @@ API-kutsed liiga kiired. Palun aeglustage oma taotlusi. URL-i ei leitud. Võimalik API URL-i viga seadetes. URL-i ei leitud. Võimalik konfiguratsiooni URL-i viga seadetes. - HTTP-päringust ei tagastatud ühtegi JSON-i. + HTTP päringust ei tagastatud ühtegi JSON-i. HTTP päring tagastas veakoodi = API URL-i lõpus ei tohi olla kaldkriipsu „/” + Webhaoki registreerimine ebaõnnestus Saadaval Kontrollimine... Pole saadaval @@ -61,6 +62,6 @@ Vasakult paremale Paremalt vasakule (Ainult vidin) Käivitage rakendus automaatselt vidinast ilma puudutust ootamata. - Lubage taustteenus, et saata Home Assistantile kella aku tase. + Lubage taustateenus, et saata Home Assistantile kella aku tase. Värskendussagedus (minutites), mille juures taustateenus peaks aku taseme saatmist kordama. - \ No newline at end of file + diff --git a/resources-fin/strings/strings.xml b/resources-fin/strings/strings.xml index d7980dd..5db2458 100644 --- a/resources-fin/strings/strings.xml +++ b/resources-fin/strings/strings.xml @@ -38,6 +38,7 @@ HTTP-pyynnöstä ei palautettu JSON-tiedostoja. HTTP-pyyntö palautti virhekoodin = API-URL-osoitteessa ei saa olla perässä olevaa kauttaviivaa '/' + Webhookin rekisteröinti epäonnistui Saatavilla Tarkistetaan... Ei saatavilla @@ -53,7 +54,7 @@ Pitäisikö sovelluksen tallentaa valikon asetukset välimuistiin? Pitäisikö sovelluksen tyhjentää olemassa oleva välimuisti, kun se käynnistetään seuraavan kerran? Aikakatkaisu sekunneissa. Poistu sovelluksesta tämän käyttämättömyyden jälkeen säästääksesi laitteen akkua. - Tämän ajan kuluttua (sekunneissa) toiminnon vahvistusikkuna suljetaan automaattisesti ja toiminto peruutetaan. Aseta arvoksi 0, jos haluat poistaa aikakatkaisun käytöstä. + Tämän ajan kuluttua (sekunneissa) toiminnon vahvistusikkuna suljetaan automaattisesti ja toiminto peruutetaan. Aseta arvoksi 0 poistaaksesi aikakatkaisun käytöstä. Valikkokohdan tyyli. Kuvakkeet Lisäteksti @@ -63,4 +64,4 @@ (Vain widget) Käynnistä sovellus automaattisesti widgetistä odottamatta napautusta. Ota taustapalvelu käyttöön lähettääksesi kellon akun varaustason Home Assistantille. Virkistystaajuus (minuutteina), jolla taustapalvelun pitäisi toistaa akun varaustason lähettämistä. - \ No newline at end of file + diff --git a/resources-fre/strings/strings.xml b/resources-fre/strings/strings.xml index 244a601..15b468d 100644 --- a/resources-fre/strings/strings.xml +++ b/resources-fre/strings/strings.xml @@ -38,6 +38,7 @@ Aucun JSON renvoyé par la requête HTTP. La requête HTTP a renvoyé un code d'erreur = L'URL de l'API ne doit pas comporter de barre oblique finale '/' + Échec de l'enregistrement du Webhook Disponible Vérification... Indisponible @@ -52,7 +53,7 @@ URL de configuration des menus (JSON). L'application doit-elle mettre en cache la configuration du menu ? L'application doit-elle vider le cache existant au prochain démarrage ? - Délai d'expiration en secondes. Quittez l'application après cette période d'inactivité pour économiser la batterie de l'appareil. + Délai d'attente en secondes. Quittez l'application après cette période d'inactivité pour économiser la batterie de l'appareil. Passé ce délai (en secondes), une boîte de dialogue de confirmation d'une action se ferme automatiquement et l'action est annulée. Réglez sur 0 pour désactiver le délai d'attente. Style des éléments de menu. Icônes @@ -63,4 +64,4 @@ (Widget uniquement) Démarrez automatiquement l'application à partir du widget sans attendre un clic. Activez le service d'arrière-plan pour envoyer le niveau de batterie de l'horloge à Home Assistant. Fréquence de rafraîchissement (en minutes) à laquelle le service en arrière-plan doit répéter l'envoi du niveau de la batterie. - \ No newline at end of file + diff --git a/resources-gre/strings/strings.xml b/resources-gre/strings/strings.xml index d44c1f5..c0616c6 100644 --- a/resources-gre/strings/strings.xml +++ b/resources-gre/strings/strings.xml @@ -30,14 +30,15 @@ Δεν υπάρχει σύνδεση στο διαδίκτυο Καμία απάντηση, ελέγξτε τη σύνδεση στο Διαδίκτυο Δεν υπάρχει κλειδί API στις ρυθμίσεις της εφαρμογής - Δεν υπάρχει URL API στις ρυθμίσεις της εφαρμογής + Δεν υπάρχει διεύθυνση URL API στις ρυθμίσεις της εφαρμογής Δεν υπάρχει διεύθυνση URL διαμόρφωσης στις ρυθμίσεις της εφαρμογής Κλήσεις API πολύ γρήγορες. Παρακαλώ επιβραδύνετε τα αιτήματά σας. Η διεύθυνση URL δεν βρέθηκε. Πιθανό σφάλμα διεύθυνσης URL API στις ρυθμίσεις. Η διεύθυνση URL δεν βρέθηκε. Πιθανό σφάλμα διαμόρφωσης URL στις ρυθμίσεις. Δεν επιστράφηκε JSON από αίτημα HTTP. Το αίτημα HTTP επέστρεψε κωδικό σφάλματος = - Η διεύθυνση URL του API δεν πρέπει να έχει τελική κάθετο "/" + Η διεύθυνση URL του API δεν πρέπει να έχει κάθετο "/" + Η εγγραφή του Webhook απέτυχε Διαθέσιμος Ελεγχος... Μη διαθέσιμο @@ -53,7 +54,7 @@ Πρέπει η εφαρμογή να αποθηκεύσει προσωρινά τη διαμόρφωση του μενού; Πρέπει η εφαρμογή να διαγράψει την υπάρχουσα προσωρινή μνήμη την επόμενη φορά που θα ξεκινήσει; Timeout σε δευτερόλεπτα. Κλείστε την εφαρμογή μετά από αυτήν την περίοδο αδράνειας για να εξοικονομήσετε την μπαταρία της συσκευής. - Μετά από αυτό το χρονικό διάστημα (σε δευτερόλεπτα), ένα παράθυρο διαλόγου επιβεβαίωσης για μια ενέργεια κλείνει αυτόματα και η ενέργεια ακυρώνεται. Ορίστε στο 0 για να απενεργοποιήσετε το χρονικό όριο. + Μετά από αυτό το διάστημα (σε δευτερόλεπτα), ένα παράθυρο διαλόγου επιβεβαίωσης για μια ενέργεια κλείνει αυτόματα και η ενέργεια ακυρώνεται. Ορίστε στο 0 για να απενεργοποιήσετε το χρονικό όριο. Στυλ στοιχείου μενού. εικονίδια Πρόσθετο Κείμενο @@ -63,4 +64,4 @@ (Μόνο widget) Αυτόματη εκκίνηση της εφαρμογής από το widget χωρίς να περιμένετε ένα πάτημα. Ενεργοποιήστε την υπηρεσία παρασκηνίου για αποστολή της στάθμης της μπαταρίας του ρολογιού στο Home Assistant. Ο ρυθμός ανανέωσης (σε λεπτά) με τον οποίο η υπηρεσία παρασκηνίου θα πρέπει να επαναλάβει στέλνοντας το επίπεδο της μπαταρίας. - \ No newline at end of file + diff --git a/resources-heb/strings/strings.xml b/resources-heb/strings/strings.xml index 9c7a91c..305d99a 100644 --- a/resources-heb/strings/strings.xml +++ b/resources-heb/strings/strings.xml @@ -28,7 +28,7 @@ מְאוּשָׁר אין חיבור לטלפון אין חיבור אינטרנט - אין תגובה, בדוק חיבור לאינטרנט + אין תגובה, בדוק את חיבור האינטרנט אין מפתח API בהגדרות האפליקציה אין כתובת API בהגדרות האפליקציה אין כתובת URL לתצורה בהגדרות האפליקציה @@ -38,6 +38,7 @@ לא הוחזר JSON מבקשת HTTP. בקשת HTTP החזירה קוד שגיאה = כתובת ה-API לא חייבת לכלול לוכסן אחורי '/' + רישום Webhook נכשל זמין בודק... אינו זמין @@ -63,4 +64,4 @@ (יישומון בלבד) הפעל אוטומטית את האפליקציה מהווידג'ט מבלי לחכות להקשה. אפשר את שירות הרקע כדי לשלוח את רמת הסוללה של השעון אל Home Assistant. קצב הרענון (בדקות) שבו שירות הרקע אמור לחזור על שליחת רמת הסוללה. - \ No newline at end of file + diff --git a/resources-hrv/strings/strings.xml b/resources-hrv/strings/strings.xml index 9749c11..a8293a8 100644 --- a/resources-hrv/strings/strings.xml +++ b/resources-hrv/strings/strings.xml @@ -38,6 +38,7 @@ HTTP zahtjev nije vratio JSON. HTTP zahtjev vratio je kod greške = API URL ne smije imati kosu crtu na kraju '/' + Registracija Webhooka nije uspjela Dostupno Provjera... Nedostupan @@ -63,4 +64,4 @@ (Samo widget) Automatski pokrenite aplikaciju iz widgeta bez čekanja na dodir. Omogućite pozadinsku uslugu za slanje razine baterije sata kućnom pomoćniku. Brzina osvježavanja (u minutama) pri kojoj bi pozadinska usluga trebala ponavljati slanje razine baterije. - \ No newline at end of file + diff --git a/resources-hun/strings/strings.xml b/resources-hun/strings/strings.xml index 3fc7392..7308c8d 100644 --- a/resources-hun/strings/strings.xml +++ b/resources-hun/strings/strings.xml @@ -38,6 +38,7 @@ A HTTP-kérésből nem érkezett vissza JSON. A HTTP-kérés = hibakódot adott vissza Az API URL-ben nem lehet perjel a „/” + Nem sikerült regisztrálni a Webhook-ot Elérhető Ellenőrzés... Nem érhető el @@ -50,17 +51,17 @@ Hosszú életű hozzáférési token. A HomeAssistant API URL-je. URL a menükonfigurációhoz (JSON). - Az alkalmazásnak gyorsítótárba kell helyeznie a menü konfigurációját? + Az alkalmazásnak gyorsítótárba kell helyeznie a menükonfigurációt? Törölje az alkalmazásnak a meglévő gyorsítótárat a következő indításakor? Időtúllépés másodpercben. Az eszköz akkumulátorának kímélése érdekében lépjen ki az alkalmazásból ezen inaktivitási időszak után. - Ezen idő elteltével (másodpercben) egy művelet megerősítő párbeszédpanele automatikusan bezárul, és a művelet megszakad. Állítsa 0-ra az időtúllépés letiltásához. + Ezen idő letelte után (másodpercben) a művelet megerősítő párbeszédablakja automatikusan bezárul, és a művelet megszakad. Állítsa 0-ra az időtúllépés letiltásához. Menüelem stílusa. Ikonok Kiegészítő szöveg Balra (ki) vagy Jobbra (be) Menüigazítás. Balról jobbra Jobbról balra - (Csak Widget) Az alkalmazás automatikus indítása a widgetről anélkül, hogy egy érintésre várna. + (Csak widget) Az alkalmazás automatikus indítása a widgetről anélkül, hogy egy érintésre várna. Engedélyezze a háttérszolgáltatást, hogy elküldje az óra töltöttségi szintjét a Home Assistantnek. Az a frissítési gyakoriság (percben), amelynél a háttérszolgáltatásnak meg kell ismételnie az akkumulátor töltöttségi szintjének küldését. - \ No newline at end of file + diff --git a/resources-ind/strings/strings.xml b/resources-ind/strings/strings.xml index 099675c..a463892 100644 --- a/resources-ind/strings/strings.xml +++ b/resources-ind/strings/strings.xml @@ -31,13 +31,14 @@ Tidak Ada Respon, periksa koneksi Internet Tidak ada kunci API di pengaturan aplikasi Tidak ada URL API di pengaturan aplikasi - Tidak ada URL konfigurasi dalam pengaturan aplikasi + Tidak ada URL konfigurasi di pengaturan aplikasi Panggilan API terlalu cepat. Harap memperlambat permintaan Anda. URL tidak ditemukan. Potensi kesalahan URL API dalam pengaturan. URL tidak ditemukan. Potensi kesalahan URL Konfigurasi dalam pengaturan. Tidak ada JSON yang dikembalikan dari permintaan HTTP. Permintaan HTTP mengembalikan kode kesalahan = URL API tidak boleh memiliki garis miring '/' + Gagal mendaftarkan Webhook Tersedia Memeriksa... Tidak tersedia @@ -63,4 +64,4 @@ (Khusus widget) Secara otomatis memulai aplikasi dari widget tanpa menunggu ketukan. Aktifkan layanan latar belakang untuk mengirim level baterai jam ke Home Assistant. Kecepatan refresh (dalam menit) saat layanan latar belakang harus mengulangi pengiriman level baterai. - \ No newline at end of file + diff --git a/resources-ita/strings/strings.xml b/resources-ita/strings/strings.xml index bd1e5f3..a13bff1 100644 --- a/resources-ita/strings/strings.xml +++ b/resources-ita/strings/strings.xml @@ -38,6 +38,7 @@ Nessun JSON restituito dalla richiesta HTTP. La richiesta HTTP ha restituito il codice di errore = L'URL dell'API non deve avere una barra finale "/" + Impossibile registrare il Webhook Disponibile Controllo... Non disponibile @@ -63,4 +64,4 @@ (Solo widget) Avvia automaticamente l'applicazione dal widget senza attendere un tocco. Abilita il servizio in background per inviare il livello della batteria dell'orologio a Home Assistant. La frequenza di aggiornamento (in minuti) alla quale il servizio in background deve ripetere l'invio del livello della batteria. - \ No newline at end of file + diff --git a/resources-jpn/strings/strings.xml b/resources-jpn/strings/strings.xml index b8c7159..1ea0543 100644 --- a/resources-jpn/strings/strings.xml +++ b/resources-jpn/strings/strings.xml @@ -38,6 +38,7 @@ HTTP リクエストから JSON が返されませんでした。 HTTP リクエストがエラー コードを返しました = API URL の末尾にスラッシュ「/」を含めることはできません + Webhookの登録に失敗しました 利用可能 チェック中... 利用不可 @@ -63,4 +64,4 @@ (ウィジェットのみ)タップを待たずにウィジェットからアプリを自動起動します。 バックグラウンド サービスを有効にして、時計のバッテリー レベルをホーム アシスタントに送信します。 バックグラウンド サービスがバッテリー レベルの送信を繰り返すリフレッシュ レート (分単位)。 - \ No newline at end of file + diff --git a/resources-kor/strings/strings.xml b/resources-kor/strings/strings.xml index 38f7ca3..f3686f6 100644 --- a/resources-kor/strings/strings.xml +++ b/resources-kor/strings/strings.xml @@ -37,7 +37,8 @@ URL을 찾을 수 없습니다. 설정에 잠재적인 구성 URL 오류가 있습니다. HTTP 요청에서 JSON이 반환되지 않았습니다. HTTP 요청이 오류 코드를 반환했습니다 = - API URL에는 후행 슬래시 '/'가 있어서는 안 됩니다. + API URL에는 후행 슬래시 '/'가 없어야 합니다. + 웹훅 등록 실패 사용 가능 확인 중... 없는 @@ -63,4 +64,4 @@ (위젯만 해당) 탭을 기다리지 않고 위젯에서 애플리케이션을 자동으로 시작합니다. 시계 배터리 수준을 홈어시스턴트로 보내려면 백그라운드 서비스를 활성화하세요. 백그라운드 서비스가 배터리 수준 전송을 반복해야 하는 새로 고침 빈도(분)입니다. - \ No newline at end of file + diff --git a/resources-lav/strings/strings.xml b/resources-lav/strings/strings.xml index fece81d..f8a3a0b 100644 --- a/resources-lav/strings/strings.xml +++ b/resources-lav/strings/strings.xml @@ -38,6 +38,7 @@ No HTTP pieprasījuma netika atgriezts neviens JSON fails. HTTP pieprasījums atgrieza kļūdas kodu = API URL beigās nedrīkst būt slīpsvītra “/” + Neizdevās reģistrēt Web aizķeri Pieejams Notiek pārbaude... Nav pieejams @@ -57,10 +58,10 @@ Izvēlnes vienuma stils. Ikonas Papildu teksts - Kreisā (izslēgta) vai labā (ieslēgta) izvēlnes izlīdzināšana. + Kreisā (izslēgta) vai labā (ieslēgta) izvēlnes līdzināšana. No kreisās uz labo No labās uz kreiso (tikai logrīkam) Automātiski startējiet lietojumprogrammu no logrīka, negaidot pieskārienu. Iespējojiet fona pakalpojumu, lai uz Home Assistant nosūtītu pulksteņa akumulatora uzlādes līmeni. Atsvaidzes intensitāte (minūtēs), ar kādu fona pakalpojumam ir jāatkārto akumulatora līmeņa nosūtīšana. - \ No newline at end of file + diff --git a/resources-lit/strings/strings.xml b/resources-lit/strings/strings.xml index 141db93..c0079d9 100644 --- a/resources-lit/strings/strings.xml +++ b/resources-lit/strings/strings.xml @@ -38,6 +38,7 @@ Joks JSON negrąžintas iš HTTP užklausos. HTTP užklausa grąžino klaidos kodą = API URL pabaigoje negali būti pasvirojo brūkšnio „/“ + Nepavyko užregistruoti Webhook Yra Tikrinama... Nepasiekiamas @@ -46,11 +47,11 @@ Meniu Pasirinkite... - API raktas, skirtas „HomeAssistant“. + API raktas, skirtas HomeAssistant. Ilgalaikis prieigos raktas. „HomeAssistant“ API URL. Meniu konfigūravimo URL (JSON). - Ar programa turėtų talpykloje išsaugoti meniu konfigūraciją? + Ar programa turėtų išsaugoti meniu konfigūraciją talpykloje? Ar programa turėtų išvalyti esamą talpyklą kitą kartą paleidus? Skirtasis laikas sekundėmis. Po šio neveiklumo laikotarpio išeikite iš programos, kad taupytumėte įrenginio akumuliatorių. Praėjus šiam laikui (sekundėmis), veiksmo patvirtinimo dialogo langas automatiškai uždaromas ir veiksmas atšaukiamas. Nustatykite 0, kad išjungtumėte skirtąjį laiką. @@ -63,4 +64,4 @@ (Tik valdikliui) Automatiškai paleiskite programą iš valdiklio, nelaukdami, kol bus palietus. Įgalinkite foninę paslaugą, kad į „Home Assistant“ būtų išsiųstas laikrodžio akumuliatoriaus lygis. Atnaujinimo dažnis (minutėmis), kuriuo foninė paslauga turėtų pakartoti baterijos lygio siuntimą. - \ No newline at end of file + diff --git a/resources-nob/strings/strings.xml b/resources-nob/strings/strings.xml index 23836c8..5dd8d64 100644 --- a/resources-nob/strings/strings.xml +++ b/resources-nob/strings/strings.xml @@ -38,6 +38,7 @@ Ingen JSON returnert fra HTTP-forespørsel. HTTP-forespørsel returnerte feilkode = API URL må ikke ha en etterfølgende skråstrek '/' + Kunne ikke registrere Webhook Tilgjengelig Sjekker... Utilgjengelig @@ -63,4 +64,4 @@ (Kun widget) Start applikasjonen automatisk fra widgeten uten å vente på et trykk. Aktiver bakgrunnstjenesten for å sende klokkens batterinivå til Home Assistant. Oppdateringshastigheten (i minutter) som bakgrunnstjenesten skal gjenta sendingen av batterinivået med. - \ No newline at end of file + diff --git a/resources-pol/strings/strings.xml b/resources-pol/strings/strings.xml index d20db34..04ff1fa 100644 --- a/resources-pol/strings/strings.xml +++ b/resources-pol/strings/strings.xml @@ -38,6 +38,7 @@ Z żądania HTTP nie zwrócono żadnego kodu JSON. Żądanie HTTP zwróciło kod błędu = Adres URL interfejsu API nie może zawierać końcowego ukośnika „/” + Nie udało się zarejestrować webhooka Dostępny Kontrola... Niedostępne @@ -63,4 +64,4 @@ (Tylko widget) Automatycznie uruchamiaj aplikację z widgetu, bez czekania na dotknięcie. Włącz usługę działającą w tle, aby wysyłać poziom naładowania baterii zegara do Home Assistant. Częstotliwość odświeżania (w minutach), z jaką usługa działająca w tle powinna powtarzać wysyłanie informacji o poziomie baterii. - \ No newline at end of file + diff --git a/resources-por/strings/strings.xml b/resources-por/strings/strings.xml index d2c22ed..aae5cb1 100644 --- a/resources-por/strings/strings.xml +++ b/resources-por/strings/strings.xml @@ -38,6 +38,7 @@ Nenhum JSON foi retornado da solicitação HTTP. Solicitação HTTP retornou código de erro = O URL da API não deve ter uma barra final '/' + Falha ao registrar o Webhook Disponível Verificando... Indisponível @@ -63,4 +64,4 @@ (Somente widget) Inicie automaticamente o aplicativo a partir do widget sem esperar por um toque. Ative o serviço em segundo plano para enviar o nível da bateria do relógio ao Home Assistant. A taxa de atualização (em minutos) na qual o serviço em segundo plano deve repetir o envio do nível da bateria. - \ No newline at end of file + diff --git a/resources-ron/strings/strings.xml b/resources-ron/strings/strings.xml index cd327a3..72a9beb 100644 --- a/resources-ron/strings/strings.xml +++ b/resources-ron/strings/strings.xml @@ -38,6 +38,7 @@ Niciun JSON nu a fost returnat de la solicitarea HTTP. Solicitarea HTTP a returnat codul de eroare = Adresa URL API nu trebuie să aibă o bară oblică „/” + Nu s-a putut înregistra Webhook Disponibil Control... Indisponibil @@ -63,4 +64,4 @@ (Numai widget) Porniți automat aplicația din widget fără a aștepta o atingere. Activați serviciul de fundal pentru a trimite nivelul bateriei ceasului către Home Assistant. Rata de reîmprospătare (în minute) la care serviciul de fundal ar trebui să repete trimiterea nivelului bateriei. - \ No newline at end of file + diff --git a/resources-slo/strings/strings.xml b/resources-slo/strings/strings.xml index 57e893a..ecfa679 100644 --- a/resources-slo/strings/strings.xml +++ b/resources-slo/strings/strings.xml @@ -38,6 +38,7 @@ Z požiadavky HTTP sa nevrátil žiadny JSON. Požiadavka HTTP vrátila kód chyby = Adresa URL rozhrania API nesmie obsahovať koncovú lomku „/“ + Registrácia Webhooku zlyhala Dostupné Prebieha kontrola... nedostupné @@ -63,4 +64,4 @@ (Len miniaplikácia) Automaticky spustite aplikáciu z miniaplikácie bez čakania na klepnutie. Povoľte službu na pozadí na odosielanie úrovne batérie hodín do domáceho asistenta. Obnovovacia frekvencia (v minútach), pri ktorej by služba na pozadí mala opakovať odosielanie úrovne batérie. - \ No newline at end of file + diff --git a/resources-slv/strings/strings.xml b/resources-slv/strings/strings.xml index 0fde095..37c077f 100644 --- a/resources-slv/strings/strings.xml +++ b/resources-slv/strings/strings.xml @@ -38,6 +38,7 @@ Zahteva HTTP ni vrnila JSON. Zahteva HTTP je vrnila kodo napake = URL API-ja ne sme imeti končne poševnice '/' + Webhooka ni bilo mogoče registrirati Na voljo Preverjanje ... Ni na voljo @@ -48,7 +49,7 @@ Izberite ... API ključ za HomeAssistant. Dolgoživ dostopni žeton. - URL za API HomeAssistant. + URL za HomeAssistant API. URL za konfiguracijo menija (JSON). Ali naj aplikacija predpomni konfiguracijo menija? Ali naj aplikacija ob naslednjem zagonu počisti obstoječi predpomnilnik? @@ -63,4 +64,4 @@ (Samo pripomoček) Samodejno zaženite aplikacijo iz pripomočka, ne da bi čakali na dotik. Omogočite storitev v ozadju za pošiljanje ravni baterije ure domačemu pomočniku. Hitrost osveževanja (v minutah), pri kateri naj storitev v ozadju ponavlja pošiljanje stanja baterije. - \ No newline at end of file + diff --git a/resources-spa/strings/strings.xml b/resources-spa/strings/strings.xml index d291db9..8a0637c 100644 --- a/resources-spa/strings/strings.xml +++ b/resources-spa/strings/strings.xml @@ -38,6 +38,7 @@ No se devolvió ningún JSON de la solicitud HTTP. La solicitud HTTP devolvió el código de error = La URL de API no debe tener una barra diagonal '/' + No se pudo registrar el webhook Disponible Comprobación... Indisponible @@ -63,4 +64,4 @@ (Solo widget) Inicia automáticamente la aplicación desde el widget sin esperar un toque. Habilite el servicio en segundo plano para enviar el nivel de batería del reloj a Home Assistant. La frecuencia de actualización (en minutos) a la que el servicio en segundo plano debe repetir el envío del nivel de la batería. - \ No newline at end of file + diff --git a/resources-swe/strings/strings.xml b/resources-swe/strings/strings.xml index b09d4c8..50bd5d9 100644 --- a/resources-swe/strings/strings.xml +++ b/resources-swe/strings/strings.xml @@ -15,7 +15,7 @@ @@ -35,9 +35,10 @@ API-anrop för snabba. Vänligen sakta ner dina förfrågningar. Webbadressen hittades inte. Potentiellt API-URL-fel i inställningarna. Webbadressen hittades inte. Potentiellt konfigurations-URL-fel i inställningarna. - Ingen JSON returnerades från HTTP-begäran. + Ingen JSON returnerades från HTTP-förfrågan. HTTP-begäran returnerade felkod = API-URL får inte ha ett snedstreck '/' + Det gick inte att registrera Webhook Tillgängliga Kontroll... Inte tillgänglig @@ -52,7 +53,7 @@ URL för menykonfiguration (JSON). Ska programmet cachelagra menykonfigurationen? Ska programmet rensa den befintliga cachen nästa gång den startas? - Timeout på sekunder. Avsluta programmet efter denna period av inaktivitet för att spara enhetens batteri. + Timeout i sekunder. Avsluta programmet efter denna period av inaktivitet för att spara enhetens batteri. Efter denna tid (i sekunder) stängs en bekräftelsedialog för en åtgärd automatiskt och åtgärden avbryts. Ställ in på 0 för att inaktivera timeout. Menyalternativ stil. Ikoner @@ -63,4 +64,4 @@ (Endast widget) Starta programmet automatiskt från widgeten utan att vänta på ett tryck. Aktivera bakgrundstjänsten för att skicka klockans batterinivå till Home Assistant. Uppdateringshastigheten (i minuter) med vilken bakgrundstjänsten ska upprepa sändningen av batterinivån. - \ No newline at end of file + diff --git a/resources-tha/strings/strings.xml b/resources-tha/strings/strings.xml index 5907bcf..678a2a5 100644 --- a/resources-tha/strings/strings.xml +++ b/resources-tha/strings/strings.xml @@ -38,6 +38,7 @@ ไม่มี JSON ที่ส่งคืนจากคำขอ HTTP คำขอ HTTP ส่งคืนรหัสข้อผิดพลาด = URL ของ API ต้องไม่มีเครื่องหมายทับต่อท้าย '/' + ลงทะเบียน Webhook.dll ไม่สำเร็จ มีอยู่ กำลังตรวจสอบ... ไม่พร้อมใช้งาน @@ -63,4 +64,4 @@ (วิดเจ็ตเท่านั้น) เริ่มแอปพลิเคชันโดยอัตโนมัติจากวิดเจ็ตโดยไม่ต้องรอการแตะ เปิดใช้บริการพื้นหลังเพื่อส่งระดับแบตเตอรี่นาฬิกาไปยัง Home Assistant อัตรารีเฟรช (เป็นนาที) ที่บริการพื้นหลังควรส่งระดับแบตเตอรี่ซ้ำ - \ No newline at end of file + diff --git a/resources-tur/strings/strings.xml b/resources-tur/strings/strings.xml index 4ac548e..f245f8f 100644 --- a/resources-tur/strings/strings.xml +++ b/resources-tur/strings/strings.xml @@ -37,7 +37,8 @@ URL bulunamadı. Ayarlarda Olası Yapılandırma URL'si hatası. HTTP isteğinden JSON döndürülmedi. HTTP isteği hata kodunu döndürdü = - API URL'sinin sonunda '/' eğik çizgi olmamalıdır + API URL'sinin sonunda eğik çizgi '/' olmamalıdır + Webhook kaydedilemedi Mevcut Kontrol etme... Kullanım dışı @@ -63,4 +64,4 @@ (Yalnızca Widget) Dokunmayı beklemeden uygulamayı widget'tan otomatik olarak başlatın. Saatin pil seviyesini Ev Asistanına göndermek için arka plan hizmetini etkinleştirin. Arka plan hizmetinin pil seviyesini göndermeyi tekrarlaması gereken yenileme hızı (dakika olarak). - \ No newline at end of file + diff --git a/resources-ukr/strings/strings.xml b/resources-ukr/strings/strings.xml index 75c748e..0a6b2c1 100644 --- a/resources-ukr/strings/strings.xml +++ b/resources-ukr/strings/strings.xml @@ -15,7 +15,7 @@ @@ -38,6 +38,7 @@ Запит HTTP не повертає JSON. Запит HTTP повернув код помилки = URL-адреса API не повинна містити косу риску '/' + Не вдалося зареєструвати Webhook в наявності Перевірка... Недоступний @@ -49,7 +50,7 @@ Ключ API для HomeAssistant. Довговічний маркер доступу. URL для HomeAssistant API. - URL для налаштування меню (JSON). + URL-адреса для налаштування меню (JSON). Чи має програма кешувати конфігурацію меню? Чи слід програмі очистити наявний кеш під час наступного запуску? Час очікування в секундах. Вийдіть із програми після цього періоду бездіяльності, щоб заощадити батарею пристрою. @@ -63,4 +64,4 @@ (Лише віджет) Автоматично запускайте програму з віджета, не чекаючи дотику. Увімкніть фонову службу, щоб надсилати інформацію про рівень заряду акумулятора годинника до Home Assistant. Частота оновлення (у хвилинах), з якою фонова служба має повторно надсилати рівень заряду акумулятора. - \ No newline at end of file + diff --git a/resources-vie/strings/strings.xml b/resources-vie/strings/strings.xml index 63cad2e..acc200c 100644 --- a/resources-vie/strings/strings.xml +++ b/resources-vie/strings/strings.xml @@ -38,6 +38,7 @@ Không có JSON nào được trả về từ yêu cầu HTTP. Yêu cầu HTTP trả về mã lỗi = URL API không được có dấu gạch chéo ở cuối '/' + Không đăng ký được Webhook Có sẵn Đang kiểm tra... Không có sẵn @@ -63,4 +64,4 @@ (Chỉ tiện ích) Tự động khởi động ứng dụng từ tiện ích mà không cần chờ nhấn. Kích hoạt dịch vụ nền để gửi mức pin đồng hồ đến Home Assistant. Tốc độ làm mới (tính bằng phút) mà dịch vụ nền sẽ lặp lại việc gửi mức pin. - \ No newline at end of file + diff --git a/resources-zhs/strings/strings.xml b/resources-zhs/strings/strings.xml index d17a4cb..f478f28 100644 --- a/resources-zhs/strings/strings.xml +++ b/resources-zhs/strings/strings.xml @@ -38,6 +38,7 @@ HTTP 请求未返回 JSON。 HTTP请求返回错误码= API URL 不得有尾部斜杠“/” + 注册Webhook失败 可用的 检查... 不可用 @@ -63,4 +64,4 @@ (仅限小部件)从小部件自动启动应用程序,无需等待点击。 启用后台服务将时钟电池电量发送到 Home Assistant。 后台服务应重复发送电池电量的刷新率(以分钟为单位)。 - \ No newline at end of file + diff --git a/resources-zht/strings/strings.xml b/resources-zht/strings/strings.xml index e680558..6068388 100644 --- a/resources-zht/strings/strings.xml +++ b/resources-zht/strings/strings.xml @@ -38,6 +38,7 @@ HTTP 請求未傳回 JSON。 HTTP請求回傳錯誤碼= API URL 不得有尾部斜線“/” + 註冊Webhook失敗 可用的 檢查... 不可用 @@ -63,4 +64,4 @@ (僅限小部件)從小部件自動啟動應用程序,無需等待點擊。 啟用後台服務將時鐘電池電量傳送到 Home Assistant。 後台服務應重複發送電池電量的更新率(以分鐘為單位)。 - \ No newline at end of file + diff --git a/resources-zsm/strings/strings.xml b/resources-zsm/strings/strings.xml index 6c4aec1..9afed9c 100644 --- a/resources-zsm/strings/strings.xml +++ b/resources-zsm/strings/strings.xml @@ -38,6 +38,7 @@ Tiada JSON dikembalikan daripada permintaan HTTP. Permintaan HTTP mengembalikan kod ralat = URL API tidak boleh mempunyai garis miring '/' + Gagal mendaftar Webhook Tersedia Menyemak... Tidak ada @@ -63,4 +64,4 @@ (Widget sahaja) Mulakan aplikasi secara automatik daripada widget tanpa menunggu satu ketikan. Dayakan perkhidmatan latar belakang untuk menghantar paras bateri jam kepada Home Assistant. Kadar penyegaran semula (dalam minit) di mana perkhidmatan latar belakang harus mengulangi penghantaran tahap bateri. - \ No newline at end of file + diff --git a/resources/settings/properties.xml b/resources/settings/properties.xml index 7d88dff..d01f756 100644 --- a/resources/settings/properties.xml +++ b/resources/settings/properties.xml @@ -13,32 +13,50 @@ --> - + + + + - + - + false - + false 0 3 @@ -55,8 +73,8 @@ false @@ -66,8 +84,8 @@ false 15 diff --git a/resources/settings/settings.xml b/resources/settings/settings.xml index 66912fc..4cc33f9 100644 --- a/resources/settings/settings.xml +++ b/resources/settings/settings.xml @@ -107,4 +107,10 @@ + + + diff --git a/resources/strings/strings.xml b/resources/strings/strings.xml index 097dcca..379821c 100644 --- a/resources/strings/strings.xml +++ b/resources/strings/strings.xml @@ -32,6 +32,7 @@ No JSON returned from HTTP request. HTTP request returned error code = API URL must not have a trailing slash '/' + Failed to register Webhook Available Checking... Unavailable diff --git a/source/BackgroundServiceDelegate.mc b/source/BackgroundServiceDelegate.mc index e398065..d40bb42 100644 --- a/source/BackgroundServiceDelegate.mc +++ b/source/BackgroundServiceDelegate.mc @@ -51,17 +51,26 @@ class BackgroundServiceDelegate extends System.ServiceDelegate { } else { // Don't use Settings.* here as the object lasts < 30 secs and is recreated each time the background service is run Communications.makeWebRequest( - (Properties.getValue("api_url") as Lang.String) + "/events/garmin.battery_level", + (Properties.getValue("api_url") as Lang.String) + "/webhook/" + (Properties.getValue("webhook_id") as Lang.String), { - "level" => System.getSystemStats().battery, - "is_charging" => System.getSystemStats().charging, - "device_id" => System.getDeviceSettings().uniqueIdentifier + "type" => "update_sensor_states", + "data" => [ + { + "state" => System.getSystemStats().battery, + "type" => "sensor", + "unique_id" => "battery_level" + }, + { + "state" => System.getSystemStats().charging, + "type" => "binary_sensor", + "unique_id" => "battery_is_charging" + } + ] }, { :method => Communications.HTTP_REQUEST_METHOD_POST, :headers => { - "Content-Type" => Communications.REQUEST_CONTENT_TYPE_JSON, - "Authorization" => "Bearer " + (Properties.getValue("api_key") as Lang.String) + "Content-Type" => Communications.REQUEST_CONTENT_TYPE_JSON }, :responseType => Communications.HTTP_RESPONSE_CONTENT_TYPE_JSON }, diff --git a/source/RezStrings.mc b/source/RezStrings.mc index 7c0bda4..2344bbd 100644 --- a/source/RezStrings.mc +++ b/source/RezStrings.mc @@ -47,6 +47,7 @@ class RezStrings { private static var strNoJson as Lang.String or Null; private static var strUnhandledHttpErr as Lang.String or Null; private static var strTrailingSlashErr as Lang.String or Null; + private static var strWebhookFailed as Lang.String or Null; (:glance) private static var strAvailable as Lang.String or Null; (:glance) @@ -98,6 +99,7 @@ class RezStrings { strNoJson = WatchUi.loadResource($.Rez.Strings.NoJson); strUnhandledHttpErr = WatchUi.loadResource($.Rez.Strings.UnhandledHttpErr); strTrailingSlashErr = WatchUi.loadResource($.Rez.Strings.TrailingSlashErr); + strWebhookFailed = WatchUi.loadResource($.Rez.Strings.WebhookFailed); strAvailable = WatchUi.loadResource($.Rez.Strings.Available); strChecking = WatchUi.loadResource($.Rez.Strings.Checking); strUnavailable = WatchUi.loadResource($.Rez.Strings.Unavailable); @@ -178,6 +180,10 @@ class RezStrings { return strTrailingSlashErr; } + static function getWebhookFailed() as Lang.String { + return strWebhookFailed; + } + static function getAvailable() as Lang.String { return strAvailable; } diff --git a/source/Settings.mc b/source/Settings.mc index 407145f..23e6aba 100644 --- a/source/Settings.mc +++ b/source/Settings.mc @@ -32,6 +32,7 @@ class Settings { public static const MENU_STYLE_TEXT = 1; private static var mApiKey as Lang.String = ""; + private static var mWebhookId as Lang.String = ""; private static var mApiUrl as Lang.String = ""; private static var mConfigUrl as Lang.String = ""; private static var mCacheConfig as Lang.Boolean = false; @@ -45,10 +46,14 @@ class Settings { private static var mBatteryRefreshRate as Lang.Number = 15; // minutes private static var mIsApp as Lang.Boolean = false; + // Must keep the object so it doesn't get garbage collected. + private static var mWebhookManager as WebhookManager or Null; + // Called on application start and then whenever the settings are changed. static function update() { mIsApp = getApp().getIsApp(); mApiKey = Properties.getValue("api_key"); + mWebhookId = Properties.getValue("webhook_id"); mApiUrl = Properties.getValue("api_url"); mConfigUrl = Properties.getValue("config_url"); mCacheConfig = Properties.getValue("cache_config"); @@ -64,7 +69,12 @@ class Settings { // Manage this inside the application or widget only (not a glance or background service process) if (mIsApp) { if (mIsBatteryLevelEnabled) { - if ((System has :ServiceDelegate) and + if (getWebhookId().equals("")) { + mWebhookManager = new WebhookManager(); + mWebhookManager.requestWebhookId(); + } + if (!getWebhookId().equals("") and + (System has :ServiceDelegate) and ((Background.getTemporalEventRegisteredTime() == null) or (Background.getTemporalEventRegisteredTime() != (mBatteryRefreshRate * 60)))) { Background.registerForTemporalEvent(new Time.Duration(mBatteryRefreshRate * 60)); // Convert to seconds @@ -90,6 +100,20 @@ class Settings { return mApiKey; } + static function getWebhookId() as Lang.String { + return mWebhookId; + } + + static function setWebhookId(webhookId as Lang.String) { + mWebhookId = webhookId; + Properties.setValue("webhook_id", mWebhookId); + } + + static function removeWebhookId() { + mWebhookId = ""; + Properties.setValue("webhook_id", mWebhookId); + } + static function getApiUrl() as Lang.String { return mApiUrl; } @@ -131,4 +155,11 @@ class Settings { return mIsWidgetStartNoTap; } + static function disableBatteryLevel() { + mIsBatteryLevelEnabled = false; + Properties.setValue("enable_battery_level", mIsBatteryLevelEnabled); + if ((System has :ServiceDelegate) and (Background.getTemporalEventRegisteredTime() != null)) { + Background.deleteTemporalEvent(); + } + } } diff --git a/source/WebhookManager.mc b/source/WebhookManager.mc new file mode 100644 index 0000000..197d383 --- /dev/null +++ b/source/WebhookManager.mc @@ -0,0 +1,223 @@ +using Toybox.Lang; +using Toybox.Communications; +using Toybox.System; + +// Can use push view so must never be run in a glance context +class WebhookManager { + function onReturnRequestWebhookId(responseCode as Lang.Number, data as Null or Lang.Dictionary or Lang.String) as Void { + switch (responseCode) { + case Communications.BLE_HOST_TIMEOUT: + case Communications.BLE_CONNECTION_UNAVAILABLE: + if (Globals.scDebug) { + System.println("WebhookManager onReturnRequestWebhookId() Response Code: BLE_HOST_TIMEOUT or BLE_CONNECTION_UNAVAILABLE, Bluetooth connection severed."); + } + ErrorView.show(RezStrings.getWebhookFailed() + "\n" + RezStrings.getNoPhone() + "."); + break; + + case Communications.BLE_QUEUE_FULL: + if (Globals.scDebug) { + System.println("WebhookManager onReturnRequestWebhookId() Response Code: BLE_QUEUE_FULL, API calls too rapid."); + } + ErrorView.show(RezStrings.getWebhookFailed() + "\n" + RezStrings.getApiFlood()); + break; + + case Communications.NETWORK_REQUEST_TIMED_OUT: + if (Globals.scDebug) { + System.println("WebhookManager onReturnRequestWebhookId() Response Code: NETWORK_REQUEST_TIMED_OUT, check Internet connection."); + } + ErrorView.show(RezStrings.getWebhookFailed() + "\n" + RezStrings.getNoResponse()); + break; + + case Communications.NETWORK_RESPONSE_OUT_OF_MEMORY: + if (Globals.scDebug) { + System.println("WebhookManager onReturnRequestWebhookId() Response Code: NETWORK_RESPONSE_OUT_OF_MEMORY, are we going too fast?"); + } + // Ignore and see if we can carry on + break; + case Communications.INVALID_HTTP_BODY_IN_NETWORK_RESPONSE: + if (Globals.scDebug) { + System.println("WebhookManager onReturnRequestWebhookId() Response Code: INVALID_HTTP_BODY_IN_NETWORK_RESPONSE, check JSON is returned."); + } + Settings.disableBatteryLevel(); + ErrorView.show(RezStrings.getWebhookFailed() + "\n" + RezStrings.getNoJson()); + break; + + case 404: + if (Globals.scDebug) { + System.println("WebhookManager onReturnRequestWebhookId() Response Code: 404, page not found. Check API URL setting."); + } + Settings.disableBatteryLevel(); + ErrorView.show(RezStrings.getWebhookFailed() + "\n" + RezStrings.getApiUrlNotFound()); + break; + + case 201: + var id = data.get("webhook_id") as Lang.String or Null; + if (id != null) { + Settings.setWebhookId(id); + registerWebhookSensor({ + "device_class" => "battery", + "name" => "Battery Level", + "state" => System.getSystemStats().battery, + "type" => "sensor", + "unique_id" => "battery_level", + "unit_of_measurement" => "%", + "state_class" => "measurement", + "entity_category" => "diagnostic", + "disabled" => false + }); + registerWebhookSensor({ + "device_class" => "battery_charging", + "name" => "Battery is Charging", + "state" => System.getSystemStats().charging, + "type" => "binary_sensor", + "unique_id" => "battery_is_charging", + "entity_category" => "diagnostic", + "disabled" => false + }); + } else { + if (Globals.scDebug) { + System.println("WebhookManager onReturnRequestWebhookId(): No webhook id in response data."); + } + Settings.disableBatteryLevel(); + ErrorView.show(RezStrings.getWebhookFailed()); + } + break; + + default: + if (Globals.scDebug) { + System.println("WebhookManager onReturnRequestWebhookId(): Unhandled HTTP response code = " + responseCode); + } + Settings.disableBatteryLevel(); + ErrorView.show(RezStrings.getWebhookFailed() + "\n" + RezStrings.getUnhandledHttpErr() + responseCode); + } + } + + function requestWebhookId() { + if (Globals.scDebug) { + System.println("WebhookManager requestWebhookId(): Requesting webhook id"); + } + Communications.makeWebRequest( + Settings.getApiUrl() + "/mobile_app/registrations", + { + "device_id" => System.getDeviceSettings().uniqueIdentifier, + "app_id" => "garmin_home_assistant", + "app_name" => RezStrings.getAppName(), + "app_version" => "", + "device_name" => "Garmin Watch", + "manufacturer" => "Garmin", + "model" => "", + "os_name" => "", + "os_version" => Lang.format("$1$.$2$", System.getDeviceSettings().firmwareVersion), + "supports_encryption" => false, + "app_data" => {} + }, + { + :method => Communications.HTTP_REQUEST_METHOD_POST, + :headers => { + "Content-Type" => Communications.REQUEST_CONTENT_TYPE_JSON, + "Authorization" => "Bearer " + Settings.getApiKey() + }, + :responseType => Communications.HTTP_RESPONSE_CONTENT_TYPE_JSON + }, + method(:onReturnRequestWebhookId) + ); + } + + function onReturnRegisterWebhookSensor(responseCode as Lang.Number, data as Null or Lang.Dictionary or Lang.String) as Void { + switch (responseCode) { + case Communications.BLE_HOST_TIMEOUT: + case Communications.BLE_CONNECTION_UNAVAILABLE: + if (Globals.scDebug) { + System.println("WebhookManager onReturnRegisterWebhookSensor() Response Code: BLE_HOST_TIMEOUT or BLE_CONNECTION_UNAVAILABLE, Bluetooth connection severed."); + } + Settings.removeWebhookId(); + ErrorView.show(RezStrings.getWebhookFailed() + "\n" + RezStrings.getNoPhone() + "."); + break; + + case Communications.BLE_QUEUE_FULL: + if (Globals.scDebug) { + System.println("WebhookManager onReturnRegisterWebhookSensor() Response Code: BLE_QUEUE_FULL, API calls too rapid."); + } + Settings.removeWebhookId(); + ErrorView.show(RezStrings.getWebhookFailed() + "\n" + RezStrings.getApiFlood()); + break; + + case Communications.NETWORK_REQUEST_TIMED_OUT: + if (Globals.scDebug) { + System.println("WebhookManager onReturnRegisterWebhookSensor() Response Code: NETWORK_REQUEST_TIMED_OUT, check Internet connection."); + } + Settings.removeWebhookId(); + ErrorView.show(RezStrings.getWebhookFailed() + "\n" + RezStrings.getNoResponse()); + break; + + case Communications.NETWORK_RESPONSE_OUT_OF_MEMORY: + if (Globals.scDebug) { + System.println("WebhookManager onReturnRegisterWebhookSensor() Response Code: NETWORK_RESPONSE_OUT_OF_MEMORY, are we going too fast?"); + } + Settings.removeWebhookId(); + // Ignore and see if we can carry on + break; + case Communications.INVALID_HTTP_BODY_IN_NETWORK_RESPONSE: + if (Globals.scDebug) { + System.println("WebhookManager onReturnRegisterWebhookSensor() Response Code: INVALID_HTTP_BODY_IN_NETWORK_RESPONSE, check JSON is returned."); + } + Settings.removeWebhookId(); + Settings.disableBatteryLevel(); + ErrorView.show(RezStrings.getWebhookFailed() + "\n" + RezStrings.getNoJson()); + break; + + case 404: + if (Globals.scDebug) { + System.println("WebhookManager onReturnRequestWebhookId() Response Code: 404, page not found. Check API URL setting."); + } + Settings.removeWebhookId(); + Settings.disableBatteryLevel(); + ErrorView.show(RezStrings.getWebhookFailed() + "\n" + RezStrings.getApiUrlNotFound()); + break; + + case 201: + if ((data.get("success") as Lang.Boolean or Null) == true) { + if (Globals.scDebug) { + System.println("WebhookManager onReturnRegisterWebhookSensor(): Success"); + } + } else { + if (Globals.scDebug) { + System.println("WebhookManager onReturnRegisterWebhookSensor(): Failure"); + } + Settings.removeWebhookId(); + Settings.disableBatteryLevel(); + ErrorView.show(RezStrings.getWebhookFailed()); + } + break; + + default: + if (Globals.scDebug) { + System.println("WebhookManager onReturnRequestWebhookId(): Unhandled HTTP response code = " + responseCode); + } + Settings.removeWebhookId(); + Settings.disableBatteryLevel(); + ErrorView.show(RezStrings.getWebhookFailed() + "\n" + RezStrings.getUnhandledHttpErr() + responseCode); + } + } + + function registerWebhookSensor(sensor as Lang.Object) { + if (Globals.scDebug) { + System.println("WebhookManager registerWebhookSensor(): Registering webhook sensor: " + sensor.toString()); + } + Communications.makeWebRequest( + Settings.getApiUrl() + "/webhook/" + Settings.getWebhookId(), + { + "type" => "register_sensor", + "data" => sensor + }, + { + :method => Communications.HTTP_REQUEST_METHOD_POST, + :headers => { + "Content-Type" => Communications.REQUEST_CONTENT_TYPE_JSON + }, + :responseType => Communications.HTTP_RESPONSE_CONTENT_TYPE_JSON + }, + method(:onReturnRegisterWebhookSensor) + ); + } +}