mirror of
https://github.com/house-of-abbey/GarminHomeAssistant.git
synced 2025-06-16 03:18:35 +00:00
Merge branch 'main' into patch-1
This commit is contained in:
31
.github/workflows/translate.yml
vendored
Normal file
31
.github/workflows/translate.yml
vendored
Normal file
@ -0,0 +1,31 @@
|
||||
name: Translate
|
||||
on:
|
||||
push:
|
||||
paths:
|
||||
- "resources/strings/strings.xml"
|
||||
- "resources-*/strings/corrections.xml"
|
||||
|
||||
jobs:
|
||||
translate:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
permissions:
|
||||
# Give the default GITHUB_TOKEN write permission to commit and push the
|
||||
# added or changed files to the repository.
|
||||
contents: write
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Setup Python
|
||||
uses: actions/setup-python@v4.7.1
|
||||
|
||||
- run: |
|
||||
pip install beautifulsoup4
|
||||
pip install deep-translate
|
||||
pip install xml
|
||||
|
||||
- run: python translate.py
|
||||
|
||||
# Commit all changed files back to the repository
|
||||
- uses: stefanzweifel/git-auto-commit-action@v5
|
6
.vscode/settings.json
vendored
Normal file
6
.vscode/settings.json
vendored
Normal file
@ -0,0 +1,6 @@
|
||||
{
|
||||
"cSpell.words": [
|
||||
"usbs",
|
||||
"Venu"
|
||||
]
|
||||
}
|
@ -2,10 +2,6 @@
|
||||
"folders": [
|
||||
{
|
||||
"path": "."
|
||||
},
|
||||
{
|
||||
"name": "abc",
|
||||
"path": "../blah/abc"
|
||||
}
|
||||
],
|
||||
"settings": {}
|
||||
|
66
README.md
66
README.md
@ -4,10 +4,9 @@
|
||||
|
||||
A Garmin application to provide a "dashboard" to control your devices via [Home Assistant](https://www.home-assistant.io/). The application will never be as fully fledged as a Home Assistant dashboard, so it is designed to be good enough for the simple and essential things. Those things that can be activated via an on/off toggle or a tap. That should cover lights, switches, and anything requiring a single press such as an automation. For anything more complicated, e.g. thermostat, it would always be quicker and simpler to reach for your phone or tablet... or the device's own remote control!
|
||||
|
||||
The application is designed around a simple scrollable menu where menu items have been extended to interface with the [Home Assistant API](https://developers.home-assistant.io/docs/api/rest/), e.g. to get the status of switches or lights for display on the toggle menu item. It is possible to nest menus, so there is a menu item to open a sub-menu. This can be
|
||||
arbitrarily deep and nested in the format of a tree of items, although you need to consider if reaching for your phone becomes quicker to select the device what you want to control.
|
||||
The application is designed around a simple scrollable menu where menu items have been extended to interface with the [Home Assistant API](https://developers.home-assistant.io/docs/api/rest/), e.g. to get the status of switches or lights for display on the toggle menu item. It is possible to nest menus, so there is a menu item to open a sub-menu. This can be arbitrarily deep and nested in the format of a tree of items, although you need to consider if reaching for your phone becomes quicker to select the device what you want to control.
|
||||
|
||||
It is important to note that your homeassistant instance will need to be accessible via HTTPS with public SSL or all requests from the Garmin will not work. This cannot be a self-signed certificate, it must be a public certificate (You can get one for free from Let's Encrypt or you can pay for homeassistant cloud).
|
||||
It is important to note that your Home Assistant instance will need to be accessible via HTTPS with public SSL or all requests from the Garmin will not work. This cannot be a self-signed certificate, it must be a public certificate (You can get one for free from [Let's Encrypt](https://letsencrypt.org/) or you can pay for [Home Assistant cloud](https://www.nabucasa.com/)).
|
||||
|
||||
## Application Installation
|
||||
|
||||
@ -15,7 +14,7 @@ Head over to the [GarminHomeAssistant](https://apps.garmin.com/en-US/apps/61c91d
|
||||
|
||||
## Dashboard Definition
|
||||
|
||||
Setup for this menu is more complicated than the Connect IQ settings menu really allows you to specify. In order to make the dashboard easily configurable and easy to change, we have provided an external mechanism for specifying the menu layout, a JSON file you write, retrieved from a URL you specify. JSON was chosen over YAML because Garmin can parse JSON HTTP GET responses into its own internal dictionary, it cannot parse YAML, hence a choice of one really. We recommend you take advantage of [Home Assistant's own web server](https://www.home-assistant.io/integrations/http/#hosting-files) to provide the JSON definition. The advantage here are:
|
||||
Setup for this menu is more complicated than the Connect IQ settings menu really allows you to specify. In order to make the dashboard easily configurable and easy to change, we have provided an external mechanism for specifying the menu layout, a JSON file you write, retrieved from a URL you specify. JSON was chosen over YAML because Garmin can parse JSON HTTP GET responses into its own internal dictionary, it cannot parse YAML, hence a choice of one really. Note that JSON and YAML are essentially a 1:1 format mapping except JSON does not have comments. We recommend you take advantage of [Home Assistant's own web server](https://www.home-assistant.io/integrations/http/#hosting-files) to provide the JSON definition. The advantage here are:
|
||||
|
||||
1. the file is as public as you make your Home Assistant,
|
||||
2. the file is editable within Home Assistant via "Studio Code Server", and
|
||||
@ -35,7 +34,8 @@ Example schema as shown in the images:
|
||||
{
|
||||
"entity": "script.food_on_table",
|
||||
"name": "Food is Ready!",
|
||||
"type": "tap"
|
||||
"type": "tap",
|
||||
"service" : "script.turn_on"
|
||||
},
|
||||
{
|
||||
"entity": "light.bedside_light_switch",
|
||||
@ -76,9 +76,21 @@ Example schema as shown in the images:
|
||||
"type": "toggle"
|
||||
},
|
||||
{
|
||||
"entity": "switch.crnr_tbl_usbs",
|
||||
"name": "Corner Table USBs",
|
||||
"entity": "automation.garage_door_check",
|
||||
"name": "Garage Door Check",
|
||||
"type": "toggle"
|
||||
},
|
||||
{
|
||||
"entity": "automation.turn_off_usb_chargers",
|
||||
"name": "Turn off USBs",
|
||||
"type": "tap",
|
||||
"service" : "automation.trigger"
|
||||
},
|
||||
{
|
||||
"entity": "scene.tv_light",
|
||||
"name": "TV Lights Scene",
|
||||
"type": "tap",
|
||||
"service": "scene.turn_on"
|
||||
}
|
||||
]
|
||||
}
|
||||
@ -86,6 +98,28 @@ Example schema as shown in the images:
|
||||
|
||||
NB. Entity names are not real in case anyone's a hacker.
|
||||
|
||||
The example above illustrates how to configure:
|
||||
|
||||
* Light or switch toggles
|
||||
* Automation enable toggles
|
||||
* Script invocation (tap)
|
||||
* Service invocation, e.g. Scene setting, (tap)
|
||||
* A sub-menu to open (tap)
|
||||
|
||||
The example JSON shows an example usage of each of these Home Assistance entity types. Presently, an automation is the only one that can be either a 'tap' or a 'toggle'.
|
||||
|
||||
| HA Type | Tap | Toggle |
|
||||
|------------|:---:|:------:|
|
||||
| Switch | N | Y |
|
||||
| Light | N | Y |
|
||||
| Automation | Y | Y |
|
||||
| Script | Y | N |
|
||||
| Scene | Y | N |
|
||||
|
||||
NB. All 'tap' items must specify a 'service' tag.
|
||||
|
||||
Possible future extensions might include specifying the alternative texts to use instead of "On" and "Off", e.g. "Locked" and "Unlocked" (but wouldn't having locks operated from your watch be a security concern ;-))
|
||||
|
||||
The [schema](https://raw.githubusercontent.com/house-of-abbey/GarminHomeAssistant/main/config.schema.json) is checked by using a URL directly back to this GitHub source repository, so you do not need to install that file. You can just copy & paste your entity names from the YAML configuration files used to configure Home Assistant. With a submenu, there's a difference between "title" and "name". The "name" goes on the menu item, and the "title" at the head of the submenu. If your dashboard definition fails to meet the schema, the application will simply drop items with the wrong field names without warning.
|
||||
|
||||
## API Key Creation
|
||||
@ -101,7 +135,7 @@ Having created that token, before you dismiss the dialogue box with the value yo
|
||||
<img src="images/GarminHomeAssistantSettings.png" width="400" title="Application Settings"/>
|
||||
|
||||
1. Paste your API key you've just created into the top field.
|
||||
2. Add the URL for your Home Assistant API, e.g. `https://<homeassistant>/api/`.
|
||||
2. Add the URL for your Home Assistant API, e.g. `https://<homeassistant>/api`. (No trailing slash `/`` character as one gets appended when creating the URL and you do not want two.)
|
||||
3. Add the URL of your JSON file, e.g. `https://<homeassistant>/local/garmin/<something>.json`.
|
||||
|
||||
You should now have a working application on your watch and be able to operate your Home Assistant devices for as long as your watch is within Bluetooth range of your phone.
|
||||
@ -116,8 +150,22 @@ The application will display a 'toast' showing Home Assistant's friendly name of
|
||||
|
||||
## External Device Changes
|
||||
|
||||
Home Assistant will inevitably change the state of devices you are also controlling via your Garmin. The Garmin application does not maintain a web socket to listen for changes. Instead it must poll the Home Assistant API with your key. Therefore the application is not responsive to changes, instead there will be a delay of about 5 seconds to pick up state changes. The thinking here is that the watch application will only ever be open briefly not persistently, so the delay in picking up state changes won't be observed often for any race condition between two controllers.
|
||||
Home Assistant will inevitably change the state of devices you are also controlling via your Garmin. The Garmin application does not maintain a web socket to listen for changes. Instead it must poll the Home Assistant API with your key. Therefore the application is not that responsive to changes. Instead there will be a delay of multiples of 100 ms per item whose status needs to be checked and amended.
|
||||
|
||||
The per toggle item delay is caused by a queue of responses to web requests filling up a queue and giving a [Communications](https://developer.garmin.com/connect-iq/api-docs/Toybox/Communications.html).`BLE_QUEUE_FULL` response code. For a Venu 2 Garmin watch an API call delay of 600 ms was found to be sustainable (500 ms was still too fast). The code now chains a sequence of updates, so as one finishes it invokes the next item's update. The more items requiring a status update that you pack into your dashboard, the slower each individual item will be updated!
|
||||
|
||||
The thinking here is that the watch application will only ever be open briefly not persistently, so the delay in picking up state changes won't be observed often for any race condition between two controllers.
|
||||
|
||||
As a consequence of this update mechanism, if you request changes too quickly you will be notified that your device cannot keep up with the rate of API responses and you will have to dismiss the error in order to continue. The is a _feature not a bug_!
|
||||
|
||||
## Changes to the (JSON) Dashboard Definition
|
||||
|
||||
When you change the JSON file defining your dashboard, you must exit the application and the reopen it. It only takes a matter of a few seconds to pick up the new definition, but it is not automatic.
|
||||
|
||||
## Version History
|
||||
|
||||
| Version | Comment |
|
||||
|:-------:|---------|
|
||||
| 1.0 | Initial release for 26 devices. |
|
||||
| 1.1 | Updated for 54 more devices, 80 in total. Scene support. Added vibrate acknowledgement for tap-based menu items. Falls back to a custom visual confirmation in the absence of 'toast' and vibrate support. Bug fix for large menus needing status updates. |
|
||||
| 1.2 | Do not crash on zero items to update. Report unreachable URLs. Verify API URL does not have a trailing slash '/'. Increased HTTP response diagnosis. Reduced minimum API Level required from 3.3.0 to 3.1.0 to allow more device "part numbers" to be satisfied. |
|
||||
|
@ -26,7 +26,7 @@
|
||||
"type": { "const": "tap" },
|
||||
"service": { "$ref": "#/$defs/entity" }
|
||||
},
|
||||
"required": ["entity", "name", "type"],
|
||||
"required": ["entity", "name", "type", "service"],
|
||||
"additionalProperties": false
|
||||
},
|
||||
"menu": {
|
||||
|
@ -21,7 +21,7 @@
|
||||
Use "Monkey C: Edit Application" from the Visual Studio Code command palette
|
||||
to update the application attributes.
|
||||
-->
|
||||
<iq:application id="98c36259-498a-4458-9cef-74a273ad2bc3" type="watch-app" name="@Strings.AppName" entry="HomeAssistantApp" launcherIcon="@Drawables.LauncherIcon" minApiLevel="3.3.0">
|
||||
<iq:application id="40131e87-31ff-454b-a8e2-92276ee399d6" type="watch-app" name="@Strings.AppName" entry="HomeAssistantApp" launcherIcon="@Drawables.LauncherIcon" minApiLevel="3.1.0">
|
||||
<!--
|
||||
Use the following from the Visual Studio Code comand palette to edit
|
||||
the build targets:
|
||||
@ -33,7 +33,7 @@
|
||||
<!--
|
||||
Device Information & References:
|
||||
* https://developer.garmin.com/connect-iq/compatible-devices/
|
||||
* https://developer.garmin.com/connect-iq/reference-guides/devices-reference/#epix%E2%84%A2progen251mmtactix%C2%AE7%E2%80%93amolededition
|
||||
* https://developer.garmin.com/connect-iq/reference-guides/devices-reference/
|
||||
-->
|
||||
|
||||
<!-- Screen Size 390x390 launcher icon size 70x70 -->
|
||||
@ -124,6 +124,7 @@
|
||||
<iq:product id="instinct2s"/>
|
||||
<!-- Screen Size 176x176 launcher icon size 62x62 -->
|
||||
<iq:product id="instinct2x"/>
|
||||
<!-- Screen Size 176x176 launcher icon size 26x26 -->
|
||||
<iq:product id="instinctcrossover"/>
|
||||
<!-- Screen Size 218x218 launcher icon size 30x30 -->
|
||||
<iq:product id="legacyherocaptainmarvel"/>
|
||||
|
@ -18,8 +18,9 @@
|
||||
|
||||
project.manifest = manifest.xml
|
||||
|
||||
# Device Reference
|
||||
# https://developer.garmin.com/connect-iq/reference-guides/devices-reference/
|
||||
# Device References
|
||||
# * https://developer.garmin.com/connect-iq/compatible-devices/
|
||||
# * https://developer.garmin.com/connect-iq/reference-guides/devices-reference/
|
||||
#
|
||||
# Widget launcher icon, multiple resolutions
|
||||
# https://forums.garmin.com/developer/connect-iq/f/discussion/255433/widget-launcher-icon-multiple-resolutions/1563305
|
||||
@ -121,7 +122,8 @@ instinct2.resourcePath = $(instinct2.resourcePath);resources-launcher-62-62;reso
|
||||
instinct2s.resourcePath = $(instinct2s.resourcePath);resources-launcher-54-54;resources-icons-18
|
||||
# Screen Size 176x176 launcher icon size 62x62
|
||||
instinct2x.resourcePath = $(instinct2x.resourcePath);resources-launcher-62-62;resources-icons-21
|
||||
instinctcrossover.resourcePath = $(instinctcrossover.resourcePath);resources-launcher-62-62;resources-icons-21
|
||||
# Screen Size 176x176 launcher icon size 26x26
|
||||
instinctcrossover.resourcePath = $(instinctcrossover.resourcePath);resources-launcher-26-26;resources-icons-21
|
||||
# Screen Size 218x218 launcher icon size 30x30
|
||||
legacyherocaptainmarvel.resourcePath = $(legacyherocaptainmarvel.resourcePath);resources-launcher-30-30;resources-icons-26
|
||||
# Screen Size 260x260 launcher icon size 35x35
|
||||
|
@ -29,5 +29,9 @@
|
||||
<string id="NoAPIKey">لا يوجد مفتاح API في إعدادات التطبيق</string>
|
||||
<string id="NoApiUrl">لا يوجد عنوان URL لواجهة برمجة التطبيقات في إعدادات التطبيق</string>
|
||||
<string id="NoConfigUrl">لا يوجد عنوان URL للتكوين في إعدادات التطبيق</string>
|
||||
<string id="ApiFlood">مكالمات API سريعة جدًا. يرجى الإبلاغ عن هذا الخطأ مع تفاصيل الجهاز.</string>
|
||||
<string id="ApiFlood">مكالمات API سريعة جدًا. يرجى إبطاء طلباتك.</string>
|
||||
<string id="ApiUrlNotFound">لم يتم العثور على عنوان URL. خطأ محتمل في عنوان URL لواجهة برمجة التطبيقات في الإعدادات.</string>
|
||||
<string id="ConfigUrlNotFound">لم يتم العثور على عنوان URL. خطأ محتمل في عنوان URL للتكوين في الإعدادات.</string>
|
||||
<string id="UnhandledHttpErr">قام طلب HTTP بإرجاع رمز الخطأ =</string>
|
||||
<string id="TrailingSlashErr">يجب ألا يحتوي عنوان URL لواجهة برمجة التطبيقات على شرطة مائلة لاحقة '/'</string>
|
||||
</strings>
|
@ -29,5 +29,9 @@
|
||||
<string id="NoAPIKey">Няма API ключ в настройките на приложението</string>
|
||||
<string id="NoApiUrl">Няма URL адрес на API в настройките на приложението</string>
|
||||
<string id="NoConfigUrl">Няма конфигурационен URL адрес в настройките на приложението</string>
|
||||
<string id="ApiFlood">Извикванията на API са твърде бързи. Моля, докладвайте тази грешка с подробности за устройството.</string>
|
||||
<string id="ApiFlood">Извикванията на API са твърде бързи. Моля, забавете вашите заявки.</string>
|
||||
<string id="ApiUrlNotFound">URL не е намерен. Потенциална грешка в URL адреса на API в настройките.</string>
|
||||
<string id="ConfigUrlNotFound">URL не е намерен. Потенциална грешка в URL адреса на конфигурацията в настройките.</string>
|
||||
<string id="UnhandledHttpErr">HTTP заявката върна код на грешка =</string>
|
||||
<string id="TrailingSlashErr">URL адресът на API не трябва да има наклонена черта '/' в края</string>
|
||||
</strings>
|
@ -29,5 +29,9 @@
|
||||
<string id="NoAPIKey">V nastavení aplikace není žádný klíč API</string>
|
||||
<string id="NoApiUrl">V nastavení aplikace není žádná adresa URL API</string>
|
||||
<string id="NoConfigUrl">V nastavení aplikace není žádná konfigurační URL</string>
|
||||
<string id="ApiFlood">Příliš rychlá volání API. Nahlaste tuto chybu s podrobnostmi o zařízení.</string>
|
||||
<string id="ApiFlood">Příliš rychlá volání API. Zpomalte prosím své požadavky.</string>
|
||||
<string id="ApiUrlNotFound">Adresa URL nenalezena. Potenciální chyba adresy URL rozhraní API v nastavení.</string>
|
||||
<string id="ConfigUrlNotFound">Adresa URL nenalezena. Potenciální chyba konfigurační adresy URL v nastavení.</string>
|
||||
<string id="UnhandledHttpErr">Požadavek HTTP vrátil kód chyby =</string>
|
||||
<string id="TrailingSlashErr">Adresa URL rozhraní API nesmí mít koncové lomítko „/“</string>
|
||||
</strings>
|
@ -25,9 +25,13 @@
|
||||
<string id="MenuItemTap">Tryk på</string>
|
||||
<string id="MenuItemMenu">Menu</string>
|
||||
<string id="NoInternet">Ingen internetforbindelse</string>
|
||||
<string id="NoMenu">Fejl ved menuhentning</string>
|
||||
<string id="NoMenu">Menuhentningsfejl</string>
|
||||
<string id="NoAPIKey">Ingen API-nøgle i applikationsindstillingerne</string>
|
||||
<string id="NoApiUrl">Ingen API-URL i applikationsindstillingerne</string>
|
||||
<string id="NoConfigUrl">Ingen konfigurations-URL i applikationsindstillingerne</string>
|
||||
<string id="ApiFlood">API-kald for hurtigt. Rapportér venligst denne fejl med enhedsoplysninger.</string>
|
||||
<string id="ApiFlood">API-kald for hurtigt. Sænk venligst dine anmodninger.</string>
|
||||
<string id="ApiUrlNotFound">URL ikke fundet. Potentiel API URL-fejl i indstillinger.</string>
|
||||
<string id="ConfigUrlNotFound">URL ikke fundet. Potentiel konfigurations-URL-fejl i indstillinger.</string>
|
||||
<string id="UnhandledHttpErr">HTTP-anmodning returnerede fejlkode =</string>
|
||||
<string id="TrailingSlashErr">API URL må ikke have en efterfølgende skråstreg '/'</string>
|
||||
</strings>
|
@ -29,5 +29,9 @@
|
||||
<string id="NoAPIKey">Kein API-Schlüssel in den Anwendungseinstellungen</string>
|
||||
<string id="NoApiUrl">Keine API-URL in den Anwendungseinstellungen</string>
|
||||
<string id="NoConfigUrl">Keine Konfigurations-URL in den Anwendungseinstellungen</string>
|
||||
<string id="ApiFlood">API-Aufrufe zu schnell. Bitte melden Sie diesen Fehler mit Gerätedetails.</string>
|
||||
<string id="ApiFlood">API-Aufrufe zu schnell. Bitte verlangsamen Sie Ihre Anfragen.</string>
|
||||
<string id="ApiUrlNotFound">URL nicht gefunden. Möglicher API-URL-Fehler in den Einstellungen.</string>
|
||||
<string id="ConfigUrlNotFound">URL nicht gefunden. Möglicher Konfigurations-URL-Fehler in den Einstellungen.</string>
|
||||
<string id="UnhandledHttpErr">Die HTTP-Anfrage hat den Fehlercode = zurückgegeben</string>
|
||||
<string id="TrailingSlashErr">Die API-URL darf keinen abschließenden Schrägstrich „/“ enthalten.</string>
|
||||
</strings>
|
@ -29,5 +29,9 @@
|
||||
<string id="NoAPIKey">Geen API-sleutel in de applicatie-instellingen</string>
|
||||
<string id="NoApiUrl">Geen API-URL in de applicatie-instellingen</string>
|
||||
<string id="NoConfigUrl">Geen configuratie-URL in de applicatie-instellingen</string>
|
||||
<string id="ApiFlood">API-aanroepen te snel. Rapporteer deze fout met apparaatgegevens.</string>
|
||||
<string id="ApiFlood">API-aanroepen te snel. Vertraag uw verzoeken.</string>
|
||||
<string id="ApiUrlNotFound">URL niet gevonden. Mogelijke API-URL-fout in instellingen.</string>
|
||||
<string id="ConfigUrlNotFound">URL niet gevonden. Mogelijke configuratie-URL-fout in de instellingen.</string>
|
||||
<string id="UnhandledHttpErr">HTTP-verzoek retourneerde foutcode =</string>
|
||||
<string id="TrailingSlashErr">API-URL mag geen afsluitende slash '/' bevatten</string>
|
||||
</strings>
|
@ -29,5 +29,9 @@
|
||||
<string id="NoAPIKey">Rakenduse seadetes pole API-võtit</string>
|
||||
<string id="NoApiUrl">Rakenduse seadetes pole API URL-i</string>
|
||||
<string id="NoConfigUrl">Rakenduse seadetes pole konfiguratsiooni URL-i</string>
|
||||
<string id="ApiFlood">API-kutsed liiga kiired. Teatage sellest veast koos seadme üksikasjadega.</string>
|
||||
<string id="ApiFlood">API-kutsed liiga kiired. Palun aeglustage taotluste esitamist.</string>
|
||||
<string id="ApiUrlNotFound">URL-i ei leitud. Võimalik API URL-i viga seadetes.</string>
|
||||
<string id="ConfigUrlNotFound">URL-i ei leitud. Võimalik konfiguratsiooni URL-i viga seadetes.</string>
|
||||
<string id="UnhandledHttpErr">HTTP päring tagastas veakoodi =</string>
|
||||
<string id="TrailingSlashErr">API URL-i lõpus ei tohi olla kaldkriipsu „/”</string>
|
||||
</strings>
|
@ -29,5 +29,9 @@
|
||||
<string id="NoAPIKey">Sovellusasetuksissa ei ole API-avainta</string>
|
||||
<string id="NoApiUrl">Sovellusasetuksissa ei ole API URL-osoitetta</string>
|
||||
<string id="NoConfigUrl">Sovelluksen asetuksissa ei ole konfigurointi-URL-osoitetta</string>
|
||||
<string id="ApiFlood">API-kutsut liian nopeita. Ilmoita tästä virheestä laitteen tiedoilla.</string>
|
||||
<string id="ApiFlood">API-kutsut liian nopeita. Hidasta pyyntöjäsi.</string>
|
||||
<string id="ApiUrlNotFound">URL-osoitetta ei löydy. Mahdollinen API URL -virhe asetuksissa.</string>
|
||||
<string id="ConfigUrlNotFound">URL-osoitetta ei löydy. Mahdollinen konfigurointi-URL-virhe asetuksissa.</string>
|
||||
<string id="UnhandledHttpErr">HTTP-pyyntö palautti virhekoodin =</string>
|
||||
<string id="TrailingSlashErr">API-URL-osoitteessa ei saa olla perässä olevaa kauttaviivaa '/'</string>
|
||||
</strings>
|
@ -30,4 +30,8 @@
|
||||
<string id="NoApiUrl">Aucune URL API dans les paramètres de l'application</string>
|
||||
<string id="NoConfigUrl">Aucune URL de configuration dans les paramètres de l'application</string>
|
||||
<string id="ApiFlood">Appels API trop rapide. Veuillez signaler cette erreur avec les détails de l'appareil.</string>
|
||||
<string id="ApiUrlNotFound">URL introuvable. Erreur potentielle d'URL d'API dans les paramètres.</string>
|
||||
<string id="ConfigUrlNotFound">URL introuvable. Erreur potentielle d'URL de configuration dans les paramètres.</string>
|
||||
<string id="UnhandledHttpErr">La requête HTTP a renvoyé un code d'erreur =</string>
|
||||
<string id="TrailingSlashErr">L'URL de l'API ne doit pas comporter de barre oblique finale '/'</string>
|
||||
</strings>
|
||||
|
@ -29,5 +29,9 @@
|
||||
<string id="NoAPIKey">Δεν υπάρχει κλειδί API στις ρυθμίσεις της εφαρμογής</string>
|
||||
<string id="NoApiUrl">Δεν υπάρχει URL API στις ρυθμίσεις της εφαρμογής</string>
|
||||
<string id="NoConfigUrl">Δεν υπάρχει διεύθυνση URL διαμόρφωσης στις ρυθμίσεις της εφαρμογής</string>
|
||||
<string id="ApiFlood">Κλήσεις API πολύ γρήγορες. Αναφέρετε αυτό το σφάλμα με τα στοιχεία της συσκευής.</string>
|
||||
<string id="ApiFlood">Κλήσεις API πολύ γρήγορες. Παρακαλώ επιβραδύνετε τα αιτήματά σας.</string>
|
||||
<string id="ApiUrlNotFound">Η διεύθυνση URL δεν βρέθηκε. Πιθανό σφάλμα διεύθυνσης URL API στις ρυθμίσεις.</string>
|
||||
<string id="ConfigUrlNotFound">Η διεύθυνση URL δεν βρέθηκε. Πιθανό σφάλμα διεύθυνσης URL διαμόρφωσης στις ρυθμίσεις.</string>
|
||||
<string id="UnhandledHttpErr">Το αίτημα HTTP επέστρεψε κωδικό σφάλματος =</string>
|
||||
<string id="TrailingSlashErr">Η διεύθυνση URL του API δεν πρέπει να έχει τελική κάθετο "/"</string>
|
||||
</strings>
|
@ -29,5 +29,9 @@
|
||||
<string id="NoAPIKey">אין מפתח API בהגדרות האפליקציה</string>
|
||||
<string id="NoApiUrl">אין כתובת API בהגדרות האפליקציה</string>
|
||||
<string id="NoConfigUrl">אין כתובת אתר תצורה בהגדרות האפליקציה</string>
|
||||
<string id="ApiFlood">קריאות API מהירות מדי. אנא דווח על שגיאה זו עם פרטי המכשיר.</string>
|
||||
<string id="ApiFlood">קריאות API מהירות מדי. נא להאט את הבקשות שלך.</string>
|
||||
<string id="ApiUrlNotFound">כתובת האתר לא נמצאה. שגיאה פוטנציאלית של כתובת ה-API בהגדרות.</string>
|
||||
<string id="ConfigUrlNotFound">כתובת האתר לא נמצאה. שגיאת כתובת אתר פוטנציאלית של תצורה בהגדרות.</string>
|
||||
<string id="UnhandledHttpErr">בקשת HTTP החזירה קוד שגיאה =</string>
|
||||
<string id="TrailingSlashErr">כתובת ה-API לא חייבת לכלול לוכסן אחורי '/'</string>
|
||||
</strings>
|
@ -29,5 +29,9 @@
|
||||
<string id="NoAPIKey">Nema API ključa u postavkama aplikacije</string>
|
||||
<string id="NoApiUrl">Nema API URL-a u postavkama aplikacije</string>
|
||||
<string id="NoConfigUrl">Nema konfiguracijskog URL-a u postavkama aplikacije</string>
|
||||
<string id="ApiFlood">API pozivi su prebrzi. Prijavite ovu pogrešku s pojedinostima o uređaju.</string>
|
||||
<string id="ApiFlood">API pozivi su prebrzi. Molimo usporite svoje zahtjeve.</string>
|
||||
<string id="ApiUrlNotFound">URL nije pronađen. Potencijalna pogreška API URL-a u postavkama.</string>
|
||||
<string id="ConfigUrlNotFound">URL nije pronađen. Potencijalna pogreška URL-a konfiguracije u postavkama.</string>
|
||||
<string id="UnhandledHttpErr">HTTP zahtjev vratio je kod greške =</string>
|
||||
<string id="TrailingSlashErr">API URL ne smije imati kosu crtu na kraju '/'</string>
|
||||
</strings>
|
@ -29,5 +29,9 @@
|
||||
<string id="NoAPIKey">Nincs API kulcs az alkalmazás beállításaiban</string>
|
||||
<string id="NoApiUrl">Nincs API URL az alkalmazás beállításai között</string>
|
||||
<string id="NoConfigUrl">Nincs konfigurációs URL az alkalmazás beállításai között</string>
|
||||
<string id="ApiFlood">Az API-hívások túl gyorsak. Kérjük, jelentse ezt a hibát az eszköz részleteivel.</string>
|
||||
<string id="ApiFlood">Az API-hívások túl gyorsak. Kérjük, lassítsa a kérések teljesítését.</string>
|
||||
<string id="ApiUrlNotFound">Az URL nem található. Lehetséges API URL hiba a beállításokban.</string>
|
||||
<string id="ConfigUrlNotFound">Az URL nem található. Lehetséges konfigurációs URL hiba a beállításokban.</string>
|
||||
<string id="UnhandledHttpErr">A HTTP-kérés = hibakódot adott vissza</string>
|
||||
<string id="TrailingSlashErr">Az API URL-ben nem lehet perjel a „/”</string>
|
||||
</strings>
|
@ -29,5 +29,9 @@
|
||||
<string id="NoAPIKey">Tidak ada kunci API di pengaturan aplikasi</string>
|
||||
<string id="NoApiUrl">Tidak ada URL API di pengaturan aplikasi</string>
|
||||
<string id="NoConfigUrl">Tidak ada URL konfigurasi di pengaturan aplikasi</string>
|
||||
<string id="ApiFlood">Panggilan API terlalu cepat. Silakan laporkan kesalahan ini dengan detail perangkat.</string>
|
||||
<string id="ApiFlood">Panggilan API terlalu cepat. Harap memperlambat permintaan Anda.</string>
|
||||
<string id="ApiUrlNotFound">URL tidak ditemukan. Potensi kesalahan URL API dalam pengaturan.</string>
|
||||
<string id="ConfigUrlNotFound">URL tidak ditemukan. Potensi kesalahan URL Konfigurasi dalam pengaturan.</string>
|
||||
<string id="UnhandledHttpErr">Permintaan HTTP mengembalikan kode kesalahan =</string>
|
||||
<string id="TrailingSlashErr">URL API tidak boleh memiliki garis miring '/'</string>
|
||||
</strings>
|
@ -29,5 +29,9 @@
|
||||
<string id="NoAPIKey">Nessuna chiave API nelle impostazioni dell'applicazione</string>
|
||||
<string id="NoApiUrl">Nessun URL API nelle impostazioni dell'applicazione</string>
|
||||
<string id="NoConfigUrl">Nessun URL di configurazione nelle impostazioni dell'applicazione</string>
|
||||
<string id="ApiFlood">Chiamate API troppo rapide. Segnala questo errore con i dettagli del dispositivo.</string>
|
||||
<string id="ApiFlood">Chiamate API troppo rapide. Per favore rallenta le tue richieste.</string>
|
||||
<string id="ApiUrlNotFound">URL non trovato. Potenziale errore URL API nelle impostazioni.</string>
|
||||
<string id="ConfigUrlNotFound">URL non trovato. Potenziale errore dell'URL di configurazione nelle impostazioni.</string>
|
||||
<string id="UnhandledHttpErr">La richiesta HTTP ha restituito il codice di errore =</string>
|
||||
<string id="TrailingSlashErr">L'URL dell'API non deve avere una barra finale "/"</string>
|
||||
</strings>
|
@ -29,5 +29,9 @@
|
||||
<string id="NoAPIKey">アプリケーション設定に API キーがありません</string>
|
||||
<string id="NoApiUrl">アプリケーション設定に API URL がありません</string>
|
||||
<string id="NoConfigUrl">アプリケーション設定に構成 URL がありません</string>
|
||||
<string id="ApiFlood">API 呼び出しが速すぎます。このエラーをデバイスの詳細とともに報告してください。</string>
|
||||
<string id="ApiFlood">API 呼び出しが速すぎます。リクエストは遅くしてください。</string>
|
||||
<string id="ApiUrlNotFound">URLが見つかりません。設定における API URL エラーの可能性があります。</string>
|
||||
<string id="ConfigUrlNotFound">URLが見つかりません。設定内の構成 URL エラーの可能性があります。</string>
|
||||
<string id="UnhandledHttpErr">HTTP リクエストがエラー コードを返しました =</string>
|
||||
<string id="TrailingSlashErr">API URL の末尾にスラッシュ「/」を含めることはできません</string>
|
||||
</strings>
|
@ -29,5 +29,9 @@
|
||||
<string id="NoAPIKey">애플리케이션 설정에 API 키가 없습니다.</string>
|
||||
<string id="NoApiUrl">애플리케이션 설정에 API URL이 없습니다.</string>
|
||||
<string id="NoConfigUrl">애플리케이션 설정에 구성 URL이 없습니다.</string>
|
||||
<string id="ApiFlood">API 호출이 너무 빠릅니다. 기기 세부정보와 함께 이 오류를 신고해 주세요.</string>
|
||||
<string id="ApiFlood">API 호출이 너무 빠릅니다. 요청 속도를 늦추시기 바랍니다.</string>
|
||||
<string id="ApiUrlNotFound">URL을 찾을 수 없습니다. 설정에 잠재적인 API URL 오류가 있습니다.</string>
|
||||
<string id="ConfigUrlNotFound">URL을 찾을 수 없습니다. 설정에 잠재적인 구성 URL 오류가 있습니다.</string>
|
||||
<string id="UnhandledHttpErr">HTTP 요청이 오류 코드를 반환했습니다 =</string>
|
||||
<string id="TrailingSlashErr">API URL에는 후행 슬래시 '/'가 있어서는 안 됩니다.</string>
|
||||
</strings>
|
Binary file not shown.
Before Width: | Height: | Size: 3.8 KiB After Width: | Height: | Size: 3.8 KiB |
@ -29,5 +29,9 @@
|
||||
<string id="NoAPIKey">Lietojumprogrammas iestatījumos nav API atslēgas</string>
|
||||
<string id="NoApiUrl">Lietojumprogrammas iestatījumos nav API URL</string>
|
||||
<string id="NoConfigUrl">Lietojumprogrammas iestatījumos nav konfigurācijas URL</string>
|
||||
<string id="ApiFlood">API izsaukumi ir pārāk ātri. Lūdzu, ziņojiet par šo kļūdu, norādot informāciju par ierīci.</string>
|
||||
<string id="ApiFlood">API izsaukumi ir pārāk ātri. Lūdzu, palēniniet pieprasījumu izpildi.</string>
|
||||
<string id="ApiUrlNotFound">URL nav atrasts. Iespējama API URL kļūda iestatījumos.</string>
|
||||
<string id="ConfigUrlNotFound">URL nav atrasts. Iespējama konfigurācijas URL kļūda iestatījumos.</string>
|
||||
<string id="UnhandledHttpErr">HTTP pieprasījums atgrieza kļūdas kodu =</string>
|
||||
<string id="TrailingSlashErr">API URL beigās nedrīkst būt slīpsvītra “/”</string>
|
||||
</strings>
|
@ -29,5 +29,9 @@
|
||||
<string id="NoAPIKey">Programos nustatymuose nėra API rakto</string>
|
||||
<string id="NoApiUrl">Programos nustatymuose nėra API URL</string>
|
||||
<string id="NoConfigUrl">Programos nustatymuose nėra konfigūracijos URL</string>
|
||||
<string id="ApiFlood">API skambučiai per greiti. Praneškite apie šią klaidą pateikdami išsamią įrenginio informaciją.</string>
|
||||
<string id="ApiFlood">API skambučiai per greiti. Sulėtinkite prašymų vykdymą.</string>
|
||||
<string id="ApiUrlNotFound">URL nerastas. Galima API URL klaida nustatymuose.</string>
|
||||
<string id="ConfigUrlNotFound">URL nerastas. Galima konfigūracijos URL klaida nustatymuose.</string>
|
||||
<string id="UnhandledHttpErr">HTTP užklausa grąžino klaidos kodą =</string>
|
||||
<string id="TrailingSlashErr">API URL pabaigoje negali būti pasvirojo brūkšnio „/“</string>
|
||||
</strings>
|
@ -29,5 +29,9 @@
|
||||
<string id="NoAPIKey">Ingen API-nøkkel i applikasjonsinnstillingene</string>
|
||||
<string id="NoApiUrl">Ingen API-URL i applikasjonsinnstillingene</string>
|
||||
<string id="NoConfigUrl">Ingen konfigurasjons-URL i applikasjonsinnstillingene</string>
|
||||
<string id="ApiFlood">API-kall for raske. Rapporter denne feilen med enhetsdetaljer.</string>
|
||||
<string id="ApiFlood">API-kall for raske. Vennligst senke forespørslene dine.</string>
|
||||
<string id="ApiUrlNotFound">Finner ikke URL. Potensiell API URL-feil i innstillingene.</string>
|
||||
<string id="ConfigUrlNotFound">Finner ikke URL. Potensiell konfigurasjons-URL-feil i innstillingene.</string>
|
||||
<string id="UnhandledHttpErr">HTTP-forespørsel returnerte feilkode =</string>
|
||||
<string id="TrailingSlashErr">API URL må ikke ha en etterfølgende skråstrek '/'</string>
|
||||
</strings>
|
@ -29,5 +29,9 @@
|
||||
<string id="NoAPIKey">Brak klucza API w ustawieniach aplikacji</string>
|
||||
<string id="NoApiUrl">Brak adresu API w ustawieniach aplikacji</string>
|
||||
<string id="NoConfigUrl">Brak adresu URL konfiguracji w ustawieniach aplikacji</string>
|
||||
<string id="ApiFlood">Wywołania API są zbyt szybkie. Zgłoś ten błąd, podając szczegóły urządzenia.</string>
|
||||
<string id="ApiFlood">Wywołania API są zbyt szybkie. Proszę spowolnić swoje żądania.</string>
|
||||
<string id="ApiUrlNotFound">Nie znaleziono adresu URL. Potencjalny błąd adresu URL interfejsu API w ustawieniach.</string>
|
||||
<string id="ConfigUrlNotFound">Nie znaleziono adresu URL. Potencjalny błąd adresu URL konfiguracji w ustawieniach.</string>
|
||||
<string id="UnhandledHttpErr">Żądanie HTTP zwróciło kod błędu =</string>
|
||||
<string id="TrailingSlashErr">Adres URL interfejsu API nie może zawierać końcowego ukośnika „/”</string>
|
||||
</strings>
|
@ -29,5 +29,9 @@
|
||||
<string id="NoAPIKey">Nenhuma chave de API nas configurações do aplicativo</string>
|
||||
<string id="NoApiUrl">Nenhum URL de API nas configurações do aplicativo</string>
|
||||
<string id="NoConfigUrl">Nenhum URL de configuração nas configurações do aplicativo</string>
|
||||
<string id="ApiFlood">Chamadas de API muito rápidas. Por favor, relate este erro com detalhes do dispositivo.</string>
|
||||
<string id="ApiFlood">Chamadas de API muito rápidas. Por favor, diminua a velocidade de seus pedidos.</string>
|
||||
<string id="ApiUrlNotFound">URL não encontrado. Possível erro de URL da API nas configurações.</string>
|
||||
<string id="ConfigUrlNotFound">URL não encontrado. Possível erro de URL de configuração nas configurações.</string>
|
||||
<string id="UnhandledHttpErr">Solicitação HTTP retornou código de erro =</string>
|
||||
<string id="TrailingSlashErr">O URL da API não deve ter uma barra final '/'</string>
|
||||
</strings>
|
@ -29,5 +29,9 @@
|
||||
<string id="NoAPIKey">Nicio cheie API în setările aplicației</string>
|
||||
<string id="NoApiUrl">Nicio adresă URL API în setările aplicației</string>
|
||||
<string id="NoConfigUrl">Nicio adresă URL de configurare în setările aplicației</string>
|
||||
<string id="ApiFlood">Apeluri API prea rapide. Vă rugăm să raportați această eroare cu detaliile dispozitivului.</string>
|
||||
<string id="ApiFlood">Apeluri API prea rapide. Vă rugăm să vă încetiniți solicitările.</string>
|
||||
<string id="ApiUrlNotFound">Adresa URL nu a fost găsită. Potențială eroare URL API în setări.</string>
|
||||
<string id="ConfigUrlNotFound">Adresa URL nu a fost găsită. Potențială eroare URL de configurare în setări.</string>
|
||||
<string id="UnhandledHttpErr">Solicitarea HTTP a returnat codul de eroare =</string>
|
||||
<string id="TrailingSlashErr">Adresa URL API nu trebuie să aibă o bară oblică „/”</string>
|
||||
</strings>
|
@ -29,5 +29,9 @@
|
||||
<string id="NoAPIKey">V nastaveniach aplikácie nie je žiadny kľúč API</string>
|
||||
<string id="NoApiUrl">V nastaveniach aplikácie nie je žiadna adresa URL rozhrania API</string>
|
||||
<string id="NoConfigUrl">V nastaveniach aplikácie nie je žiadna konfiguračná URL</string>
|
||||
<string id="ApiFlood">Volania API sú príliš rýchle. Nahláste túto chybu s podrobnosťami o zariadení.</string>
|
||||
<string id="ApiFlood">Volania API sú príliš rýchle. Spomaľte svoje požiadavky.</string>
|
||||
<string id="ApiUrlNotFound">Adresa URL sa nenašla. Potenciálna chyba webovej adresy rozhrania API v nastaveniach.</string>
|
||||
<string id="ConfigUrlNotFound">Adresa URL sa nenašla. Potenciálna chyba konfiguračnej adresy URL v nastaveniach.</string>
|
||||
<string id="UnhandledHttpErr">Požiadavka HTTP vrátila kód chyby =</string>
|
||||
<string id="TrailingSlashErr">Adresa URL rozhrania API nesmie obsahovať koncovú lomku „/“</string>
|
||||
</strings>
|
@ -29,5 +29,9 @@
|
||||
<string id="NoAPIKey">V nastavitvah aplikacije ni ključa API</string>
|
||||
<string id="NoApiUrl">V nastavitvah aplikacije ni URL-ja API-ja</string>
|
||||
<string id="NoConfigUrl">V nastavitvah aplikacije ni konfiguracijskega URL-ja</string>
|
||||
<string id="ApiFlood">API klici so prehitri. Prijavite to napako s podrobnostmi o napravi.</string>
|
||||
<string id="ApiFlood">API klici so prehitri. Prosim, upočasnite svoje zahteve.</string>
|
||||
<string id="ApiUrlNotFound">URL-ja ni bilo mogoče najti. Morebitna napaka URL-ja API-ja v nastavitvah.</string>
|
||||
<string id="ConfigUrlNotFound">URL-ja ni bilo mogoče najti. Morebitna napaka URL-ja konfiguracije v nastavitvah.</string>
|
||||
<string id="UnhandledHttpErr">Zahteva HTTP je vrnila kodo napake =</string>
|
||||
<string id="TrailingSlashErr">URL API-ja ne sme imeti končne poševnice '/'</string>
|
||||
</strings>
|
@ -29,5 +29,9 @@
|
||||
<string id="NoAPIKey">Sin clave API en la configuración de la aplicación</string>
|
||||
<string id="NoApiUrl">No hay URL de API en la configuración de la aplicación</string>
|
||||
<string id="NoConfigUrl">No hay URL de configuración en la configuración de la aplicación.</string>
|
||||
<string id="ApiFlood">Llamadas API demasiado rápidas. Informe este error con los detalles del dispositivo.</string>
|
||||
<string id="ApiFlood">Llamadas API demasiado rápidas. Por favor, ralentice sus solicitudes.</string>
|
||||
<string id="ApiUrlNotFound">URL no encontrada. Posible error de URL de API en la configuración.</string>
|
||||
<string id="ConfigUrlNotFound">URL no encontrada. Posible error de URL de configuración en la configuración.</string>
|
||||
<string id="UnhandledHttpErr">La solicitud HTTP devolvió el código de error =</string>
|
||||
<string id="TrailingSlashErr">La URL de API no debe tener una barra diagonal '/'</string>
|
||||
</strings>
|
@ -27,7 +27,11 @@
|
||||
<string id="NoInternet">Ingen internetanslutning</string>
|
||||
<string id="NoMenu">Menyhämtningsfel</string>
|
||||
<string id="NoAPIKey">Ingen API-nyckel i applikationsinställningarna</string>
|
||||
<string id="NoApiUrl">Ingen API-URL i applikationsinställningarna</string>
|
||||
<string id="NoApiUrl">Ingen API-URL i programinställningarna</string>
|
||||
<string id="NoConfigUrl">Ingen konfigurations-URL i programinställningarna</string>
|
||||
<string id="ApiFlood">API-anrop för snabba. Rapportera detta fel med enhetsinformation.</string>
|
||||
<string id="ApiFlood">API-anrop för snabba. Vänligen sakta ner dina förfrågningar.</string>
|
||||
<string id="ApiUrlNotFound">Webbadressen hittades inte. Potentiellt API-URL-fel i inställningarna.</string>
|
||||
<string id="ConfigUrlNotFound">Webbadressen hittades inte. Potentiellt konfigurations-URL-fel i inställningarna.</string>
|
||||
<string id="UnhandledHttpErr">HTTP-begäran returnerade felkod =</string>
|
||||
<string id="TrailingSlashErr">API-URL får inte ha ett snedstreck '/'</string>
|
||||
</strings>
|
@ -29,5 +29,9 @@
|
||||
<string id="NoAPIKey">ไม่มีคีย์ API ในการตั้งค่าแอปพลิเคชัน</string>
|
||||
<string id="NoApiUrl">ไม่มี URL API ในการตั้งค่าแอปพลิเคชัน</string>
|
||||
<string id="NoConfigUrl">ไม่มี URL การกำหนดค่าในการตั้งค่าแอปพลิเคชัน</string>
|
||||
<string id="ApiFlood">การเรียก API เร็วเกินไป โปรดรายงานข้อผิดพลาดนี้พร้อมรายละเอียดอุปกรณ์</string>
|
||||
<string id="ApiFlood">การเรียก API เร็วเกินไป กรุณาชะลอคำขอของคุณ</string>
|
||||
<string id="ApiUrlNotFound">ไม่พบ URL ข้อผิดพลาด URL API ที่อาจเกิดขึ้นในการตั้งค่า</string>
|
||||
<string id="ConfigUrlNotFound">ไม่พบ URL ข้อผิดพลาด URL การกำหนดค่าที่อาจเกิดขึ้นในการตั้งค่า</string>
|
||||
<string id="UnhandledHttpErr">คำขอ HTTP ส่งคืนรหัสข้อผิดพลาด =</string>
|
||||
<string id="TrailingSlashErr">URL ของ API ต้องไม่มีเครื่องหมายทับต่อท้าย '/'</string>
|
||||
</strings>
|
@ -29,5 +29,9 @@
|
||||
<string id="NoAPIKey">Uygulama ayarlarında API anahtarı yok</string>
|
||||
<string id="NoApiUrl">Uygulama ayarlarında API URL'si yok</string>
|
||||
<string id="NoConfigUrl">Uygulama ayarlarında yapılandırma URL'si yok</string>
|
||||
<string id="ApiFlood">API çağrıları çok hızlı. Lütfen bu hatayı cihaz ayrıntılarıyla birlikte bildirin.</string>
|
||||
<string id="ApiFlood">API çağrıları çok hızlı. Lütfen isteklerinizi yavaşlatın.</string>
|
||||
<string id="ApiUrlNotFound">URL bulunamadı. Ayarlarda olası API URL hatası.</string>
|
||||
<string id="ConfigUrlNotFound">URL bulunamadı. Ayarlarda Olası Yapılandırma URL'si hatası.</string>
|
||||
<string id="UnhandledHttpErr">HTTP isteği hata kodunu döndürdü =</string>
|
||||
<string id="TrailingSlashErr">API URL'sinin sonunda '/' eğik çizgi olmamalıdır</string>
|
||||
</strings>
|
@ -15,7 +15,7 @@
|
||||
|
||||
<!--
|
||||
Generated by Google Translate: English to Ukrainian
|
||||
Згенеровано Google Translate з англійської
|
||||
Створено Google Translate з англійської
|
||||
-->
|
||||
|
||||
<strings>
|
||||
@ -29,5 +29,9 @@
|
||||
<string id="NoAPIKey">У налаштуваннях програми немає ключа API</string>
|
||||
<string id="NoApiUrl">У налаштуваннях програми немає URL-адреси API</string>
|
||||
<string id="NoConfigUrl">У налаштуваннях програми немає URL-адреси конфігурації</string>
|
||||
<string id="ApiFlood">Надто швидкі виклики API. Повідомте про цю помилку з деталями пристрою.</string>
|
||||
<string id="ApiFlood">Надто швидкі виклики API. Будь ласка, сповільніть свої запити.</string>
|
||||
<string id="ApiUrlNotFound">URL не знайдено. Потенційна помилка URL-адреси API в налаштуваннях.</string>
|
||||
<string id="ConfigUrlNotFound">URL не знайдено. Потенційна помилка URL-адреси конфігурації в налаштуваннях.</string>
|
||||
<string id="UnhandledHttpErr">Запит HTTP повернув код помилки =</string>
|
||||
<string id="TrailingSlashErr">URL-адреса API не повинна містити косу риску '/'</string>
|
||||
</strings>
|
@ -29,5 +29,9 @@
|
||||
<string id="NoAPIKey">Không có khóa API trong cài đặt ứng dụng</string>
|
||||
<string id="NoApiUrl">Không có URL API trong cài đặt ứng dụng</string>
|
||||
<string id="NoConfigUrl">Không có URL cấu hình trong cài đặt ứng dụng</string>
|
||||
<string id="ApiFlood">Cuộc gọi API quá nhanh. Vui lòng báo cáo lỗi này với các chi tiết thiết bị.</string>
|
||||
<string id="ApiFlood">Cuộc gọi API quá nhanh. Hãy làm chậm yêu cầu của bạn.</string>
|
||||
<string id="ApiUrlNotFound">Không tìm thấy URL. Lỗi URL API tiềm ẩn trong cài đặt.</string>
|
||||
<string id="ConfigUrlNotFound">Không tìm thấy URL. Lỗi URL cấu hình tiềm ẩn trong cài đặt.</string>
|
||||
<string id="UnhandledHttpErr">Yêu cầu HTTP trả về mã lỗi =</string>
|
||||
<string id="TrailingSlashErr">URL API không được có dấu gạch chéo ở cuối '/'</string>
|
||||
</strings>
|
@ -29,5 +29,9 @@
|
||||
<string id="NoAPIKey">应用程序设置中没有 API 密钥</string>
|
||||
<string id="NoApiUrl">应用程序设置中没有 API URL</string>
|
||||
<string id="NoConfigUrl">应用程序设置中没有配置 URL</string>
|
||||
<string id="ApiFlood">API 调用速度太快。请报告此错误并提供设备详细信息。</string>
|
||||
<string id="ApiFlood">API 调用速度太快。请放慢您的请求。</string>
|
||||
<string id="ApiUrlNotFound">找不到网址。设置中可能存在 API URL 错误。</string>
|
||||
<string id="ConfigUrlNotFound">找不到网址。设置中可能存在配置 URL 错误。</string>
|
||||
<string id="UnhandledHttpErr">HTTP请求返回错误码=</string>
|
||||
<string id="TrailingSlashErr">API URL 不得有尾部斜杠“/”</string>
|
||||
</strings>
|
@ -29,5 +29,9 @@
|
||||
<string id="NoAPIKey">應用程式設定中沒有 API 金鑰</string>
|
||||
<string id="NoApiUrl">應用程式設定中沒有 API URL</string>
|
||||
<string id="NoConfigUrl">應用程式設定中沒有配置 URL</string>
|
||||
<string id="ApiFlood">API 呼叫速度太快。請報告此錯誤並提供設備詳細資訊。</string>
|
||||
<string id="ApiFlood">API 呼叫速度太快。請放慢您的請求。</string>
|
||||
<string id="ApiUrlNotFound">找不到網址。設定中可能存在 API URL 錯誤。</string>
|
||||
<string id="ConfigUrlNotFound">找不到網址。設定中可能存在配置 URL 錯誤。</string>
|
||||
<string id="UnhandledHttpErr">HTTP請求回傳錯誤碼=</string>
|
||||
<string id="TrailingSlashErr">API URL 不得有尾部斜線“/”</string>
|
||||
</strings>
|
@ -29,5 +29,9 @@
|
||||
<string id="NoAPIKey">Tiada kunci API dalam tetapan aplikasi</string>
|
||||
<string id="NoApiUrl">Tiada URL API dalam tetapan aplikasi</string>
|
||||
<string id="NoConfigUrl">Tiada URL konfigurasi dalam tetapan aplikasi</string>
|
||||
<string id="ApiFlood">Panggilan API terlalu pantas. Sila laporkan ralat ini dengan butiran peranti.</string>
|
||||
<string id="ApiFlood">Panggilan API terlalu pantas. Sila perlahankan permintaan anda.</string>
|
||||
<string id="ApiUrlNotFound">URL tidak ditemui. Ralat URL API yang berpotensi dalam tetapan.</string>
|
||||
<string id="ConfigUrlNotFound">URL tidak ditemui. Ralat URL Konfigurasi Potensi dalam tetapan.</string>
|
||||
<string id="UnhandledHttpErr">Permintaan HTTP mengembalikan kod ralat =</string>
|
||||
<string id="TrailingSlashErr">URL API tidak boleh mempunyai garis miring '/'</string>
|
||||
</strings>
|
@ -23,5 +23,9 @@
|
||||
<string id="NoAPIKey">No API key in the application settings</string>
|
||||
<string id="NoApiUrl">No API URL in the application settings</string>
|
||||
<string id="NoConfigUrl">No configuration URL in the application settings</string>
|
||||
<string id="ApiFlood">API calls too rapid. Please report this error with device details.</string>
|
||||
<string id="ApiFlood">API calls too rapid. Please slow down your requests.</string>
|
||||
<string id="ApiUrlNotFound">URL not found. Potential API URL error in settings.</string>
|
||||
<string id="ConfigUrlNotFound">URL not found. Potential Configuration URL error in settings.</string>
|
||||
<string id="UnhandledHttpErr">HTTP request returned error code = </string>
|
||||
<string id="TrailingSlashErr">API URL must not have a trailing slash '/'</string>
|
||||
</strings>
|
||||
|
@ -23,9 +23,7 @@ using Toybox.Lang;
|
||||
class Globals {
|
||||
// Enable printing of messages to the debug console (don't make this a Property
|
||||
// as the messages can't be read from a watch!)
|
||||
static const scDebug = false;
|
||||
// There's a danger this time is device sensitive.
|
||||
static const scMenuItemUpdateInterval = 100; // ms, 100 ms seems okay for Venu2
|
||||
static const scAlertTimeout = 2000; // ms
|
||||
static const scTapTimeout = 1000; // ms
|
||||
static const scDebug = false;
|
||||
static const scAlertTimeout = 2000; // ms
|
||||
static const scTapTimeout = 1000; // ms
|
||||
}
|
||||
|
@ -26,25 +26,29 @@ using Toybox.Timer;
|
||||
|
||||
class HomeAssistantApp extends Application.AppBase {
|
||||
hidden var mHaMenu;
|
||||
hidden var strNoApiKey as Lang.String;
|
||||
hidden var strNoApiUrl as Lang.String;
|
||||
hidden var strNoConfigUrl as Lang.String;
|
||||
hidden var strNoInternet as Lang.String;
|
||||
hidden var strNoMenu as Lang.String;
|
||||
hidden var strApiFlood as Lang.String;
|
||||
hidden var mTimer as Timer.Timer;
|
||||
hidden var strNoApiKey as Lang.String;
|
||||
hidden var strNoApiUrl as Lang.String;
|
||||
hidden var strNoConfigUrl as Lang.String;
|
||||
hidden var strNoInternet as Lang.String;
|
||||
hidden var strNoMenu as Lang.String;
|
||||
hidden var strApiFlood as Lang.String;
|
||||
hidden var strConfigUrlNotFound as Lang.String;
|
||||
hidden var strUnhandledHttpErr as Lang.String;
|
||||
hidden var strTrailingSlashErr as Lang.String;
|
||||
hidden var mItemsToUpdate; // Array initialised by onReturnFetchMenuConfig()
|
||||
hidden var mNextItemToUpdate = 0; // Index into the above array
|
||||
|
||||
function initialize() {
|
||||
AppBase.initialize();
|
||||
strNoApiKey = WatchUi.loadResource($.Rez.Strings.NoAPIKey);
|
||||
strNoApiUrl = WatchUi.loadResource($.Rez.Strings.NoApiUrl);
|
||||
strNoConfigUrl = WatchUi.loadResource($.Rez.Strings.NoConfigUrl);
|
||||
strNoInternet = WatchUi.loadResource($.Rez.Strings.NoInternet);
|
||||
strNoMenu = WatchUi.loadResource($.Rez.Strings.NoMenu);
|
||||
strApiFlood = WatchUi.loadResource($.Rez.Strings.ApiFlood);
|
||||
mTimer = new Timer.Timer();
|
||||
strNoApiKey = WatchUi.loadResource($.Rez.Strings.NoAPIKey);
|
||||
strNoApiUrl = WatchUi.loadResource($.Rez.Strings.NoApiUrl);
|
||||
strNoConfigUrl = WatchUi.loadResource($.Rez.Strings.NoConfigUrl);
|
||||
strNoInternet = WatchUi.loadResource($.Rez.Strings.NoInternet);
|
||||
strNoMenu = WatchUi.loadResource($.Rez.Strings.NoMenu);
|
||||
strApiFlood = WatchUi.loadResource($.Rez.Strings.ApiFlood);
|
||||
strConfigUrlNotFound = WatchUi.loadResource($.Rez.Strings.ConfigUrlNotFound);
|
||||
strUnhandledHttpErr = WatchUi.loadResource($.Rez.Strings.UnhandledHttpErr);
|
||||
strTrailingSlashErr = WatchUi.loadResource($.Rez.Strings.TrailingSlashErr);
|
||||
}
|
||||
|
||||
// onStart() is called on application start up
|
||||
@ -52,27 +56,30 @@ class HomeAssistantApp extends Application.AppBase {
|
||||
}
|
||||
|
||||
// onStop() is called when your application is exiting
|
||||
function onStop(state as Lang.Dictionary?) as Void {
|
||||
if (mTimer != null) {
|
||||
mTimer.stop();
|
||||
}
|
||||
}
|
||||
function onStop(state as Lang.Dictionary?) as Void {}
|
||||
|
||||
// Return the initial view of your application here
|
||||
function getInitialView() as Lang.Array<WatchUi.Views or WatchUi.InputDelegates>? {
|
||||
var api_url = Properties.getValue("api_url") as Lang.String;
|
||||
|
||||
if ((Properties.getValue("api_key") as Lang.String).length() == 0) {
|
||||
if (Globals.scDebug) {
|
||||
System.println("HomeAssistantMenuItem Note - execScript(): No API key in the application settings.");
|
||||
System.println("HomeAssistantMenuItem execScript(): No API key in the application settings.");
|
||||
}
|
||||
return [new ErrorView(strNoApiKey + "."), new ErrorDelegate()] as Lang.Array<WatchUi.Views or WatchUi.InputDelegates>;
|
||||
} else if ((Properties.getValue("api_url") as Lang.String).length() == 0) {
|
||||
} else if (api_url.length() == 0) {
|
||||
if (Globals.scDebug) {
|
||||
System.println("HomeAssistantMenuItem Note - execScript(): No API URL in the application settings.");
|
||||
System.println("HomeAssistantMenuItem execScript(): No API URL in the application settings.");
|
||||
}
|
||||
return [new ErrorView(strNoApiUrl + "."), new ErrorDelegate()] as Lang.Array<WatchUi.Views or WatchUi.InputDelegates>;
|
||||
} else if (api_url.substring(-1, api_url.length()).equals("/")) {
|
||||
if (Globals.scDebug) {
|
||||
System.println("HomeAssistantMenuItem execScript(): API URL must not have a trailing slash '/'.");
|
||||
}
|
||||
return [new ErrorView(strTrailingSlashErr + "."), new ErrorDelegate()] as Lang.Array<WatchUi.Views or WatchUi.InputDelegates>;
|
||||
} else if ((Properties.getValue("config_url") as Lang.String).length() == 0) {
|
||||
if (Globals.scDebug) {
|
||||
System.println("HomeAssistantMenuItem Note - execScript(): No configuration URL in the application settings.");
|
||||
System.println("HomeAssistantMenuItem execScript(): No configuration URL in the application settings.");
|
||||
}
|
||||
return [new ErrorView(strNoConfigUrl + "."), new ErrorDelegate()] as Lang.Array<WatchUi.Views or WatchUi.InputDelegates>;
|
||||
} else if (System.getDeviceSettings().phoneConnected && System.getDeviceSettings().connectionAvailable) {
|
||||
@ -80,7 +87,7 @@ class HomeAssistantApp extends Application.AppBase {
|
||||
return [new WatchUi.View(), new WatchUi.BehaviorDelegate()] as Lang.Array<WatchUi.Views or WatchUi.InputDelegates>;
|
||||
} else {
|
||||
if (Globals.scDebug) {
|
||||
System.println("HomeAssistantApp Note - fetchMenuConfig(): No Internet connection, skipping API call.");
|
||||
System.println("HomeAssistantApp fetchMenuConfig(): No Internet connection, skipping API call.");
|
||||
}
|
||||
return [new ErrorView(strNoInternet + "."), new ErrorDelegate()] as Lang.Array<WatchUi.Views or WatchUi.InputDelegates>;
|
||||
}
|
||||
@ -102,25 +109,30 @@ class HomeAssistantApp extends Application.AppBase {
|
||||
// Avoid pushing multiple ErrorViews
|
||||
WatchUi.pushView(new ErrorView(strApiFlood), new ErrorDelegate(), WatchUi.SLIDE_UP);
|
||||
}
|
||||
} else if (responseCode == 404) {
|
||||
if (Globals.scDebug) {
|
||||
System.println("HomeAssistantApp onReturnFetchMenuConfig() Response Code: 404, page not found. Check Configuration URL setting.");
|
||||
}
|
||||
WatchUi.pushView(new ErrorView(strConfigUrlNotFound), new ErrorDelegate(), WatchUi.SLIDE_UP);
|
||||
} else if (responseCode == 200) {
|
||||
mHaMenu = new HomeAssistantView(data, null);
|
||||
WatchUi.switchToView(mHaMenu, new HomeAssistantViewDelegate(), WatchUi.SLIDE_IMMEDIATE);
|
||||
mItemsToUpdate = mHaMenu.getItemsToUpdate();
|
||||
mTimer.start(
|
||||
method(:updateNextMenuItem),
|
||||
Globals.scMenuItemUpdateInterval,
|
||||
true
|
||||
);
|
||||
} else if (responseCode == -300) {
|
||||
// Start the continuous update process that continues for as long as the application is running.
|
||||
// The chain of functions from 'updateNextMenuItem()' calls 'updateNextMenuItem()' on completion.
|
||||
if (mItemsToUpdate.size() > 0) {
|
||||
updateNextMenuItem();
|
||||
}
|
||||
} else if (responseCode == Communications.NETWORK_REQUEST_TIMED_OUT) {
|
||||
if (Globals.scDebug) {
|
||||
System.println("HomeAssistantApp Note - onReturnFetchMenuConfig(): Network request timeout.");
|
||||
System.println("HomeAssistantApp onReturnFetchMenuConfig(): Network request timeout.");
|
||||
}
|
||||
WatchUi.pushView(new ErrorView(strNoMenu + ". " + strNoInternet + "?"), new ErrorDelegate(), WatchUi.SLIDE_UP);
|
||||
} else {
|
||||
if (Globals.scDebug) {
|
||||
System.println("HomeAssistantApp Note - onReturnFetchMenuConfig(): Configuration not found or potential validation issue.");
|
||||
System.println("HomeAssistantApp onReturnFetchMenuConfig(): Unhandled HTTP response code = " + responseCode);
|
||||
}
|
||||
WatchUi.pushView(new ErrorView(strNoMenu + " code=" + responseCode ), new ErrorDelegate(), WatchUi.SLIDE_UP);
|
||||
WatchUi.pushView(new ErrorView(strUnhandledHttpErr + responseCode ), new ErrorDelegate(), WatchUi.SLIDE_UP);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -24,10 +24,12 @@ using Toybox.Graphics;
|
||||
using Toybox.Application.Properties;
|
||||
|
||||
class HomeAssistantMenuItem extends WatchUi.MenuItem {
|
||||
hidden var mApiKey = Properties.getValue("api_key");
|
||||
hidden var strNoInternet as Lang.String;
|
||||
hidden var strApiFlood as Lang.String;
|
||||
hidden var mService as Lang.String;
|
||||
hidden var mApiKey as Lang.String;
|
||||
hidden var strNoInternet as Lang.String;
|
||||
hidden var strApiFlood as Lang.String;
|
||||
hidden var strApiUrlNotFound as Lang.String;
|
||||
hidden var strUnhandledHttpErr as Lang.String;
|
||||
hidden var mService as Lang.String;
|
||||
|
||||
function initialize(
|
||||
label as Lang.String or Lang.Symbol,
|
||||
@ -39,8 +41,11 @@ class HomeAssistantMenuItem extends WatchUi.MenuItem {
|
||||
:icon as Graphics.BitmapType or WatchUi.Drawable or Lang.Symbol
|
||||
} or Null
|
||||
) {
|
||||
strNoInternet = WatchUi.loadResource($.Rez.Strings.NoInternet);
|
||||
strApiFlood = WatchUi.loadResource($.Rez.Strings.ApiFlood);
|
||||
strNoInternet = WatchUi.loadResource($.Rez.Strings.NoInternet);
|
||||
strApiFlood = WatchUi.loadResource($.Rez.Strings.ApiFlood);
|
||||
strApiUrlNotFound = WatchUi.loadResource($.Rez.Strings.ApiUrlNotFound);
|
||||
strUnhandledHttpErr = WatchUi.loadResource($.Rez.Strings.UnhandledHttpErr);
|
||||
mApiKey = Properties.getValue("api_key");
|
||||
mService = service;
|
||||
WatchUi.MenuItem.initialize(
|
||||
label,
|
||||
@ -66,37 +71,38 @@ class HomeAssistantMenuItem extends WatchUi.MenuItem {
|
||||
// Avoid pushing multiple ErrorViews
|
||||
WatchUi.pushView(new ErrorView(strApiFlood), new ErrorDelegate(), WatchUi.SLIDE_UP);
|
||||
}
|
||||
} else if (responseCode == 404) {
|
||||
if (Globals.scDebug) {
|
||||
System.println("HomeAssistantMenuItem onReturnExecScript() Response Code: 404, page not found. Check API URL setting.");
|
||||
}
|
||||
WatchUi.pushView(new ErrorView(strApiUrlNotFound), new ErrorDelegate(), WatchUi.SLIDE_UP);
|
||||
} else if (responseCode == 200) {
|
||||
var d = data as Lang.Array;
|
||||
if (Globals.scDebug) {
|
||||
System.println("HomeAssistantMenuItem onReturnExecScript(): Service executed.");
|
||||
}
|
||||
var d = data as Lang.Array;
|
||||
var toast = "Executed";
|
||||
for(var i = 0; i < d.size(); i++) {
|
||||
if ((d[i].get("entity_id") as Lang.String).equals(mIdentifier)) {
|
||||
if (Globals.scDebug) {
|
||||
System.println("HomeAssistantMenuItem Note - onReturnExecScript(): Correct script executed.");
|
||||
}
|
||||
if (WatchUi has :showToast) {
|
||||
WatchUi.showToast(
|
||||
(d[i].get("attributes") as Lang.Dictionary).get("friendly_name") as Lang.String,
|
||||
null
|
||||
);
|
||||
}
|
||||
if (Attention has :vibrate) {
|
||||
Attention.vibrate([
|
||||
new Attention.VibeProfile(50, 100), // On for 100ms
|
||||
new Attention.VibeProfile( 0, 100), // Off for 100ms
|
||||
new Attention.VibeProfile(50, 100) // On for 100ms
|
||||
]);
|
||||
}
|
||||
if (!(WatchUi has :showToast) && !(Attention has :vibrate)) {
|
||||
new Alert({
|
||||
:timeout => Globals.scAlertTimeout,
|
||||
:font => Graphics.FONT_MEDIUM,
|
||||
:text => (d[i].get("attributes") as Lang.Dictionary).get("friendly_name") as Lang.String,
|
||||
:fgcolor => Graphics.COLOR_WHITE,
|
||||
:bgcolor => Graphics.COLOR_BLACK
|
||||
}).pushView(WatchUi.SLIDE_IMMEDIATE);
|
||||
}
|
||||
toast = (d[i].get("attributes") as Lang.Dictionary).get("friendly_name") as Lang.String;
|
||||
}
|
||||
}
|
||||
if (WatchUi has :showToast) {
|
||||
WatchUi.showToast(toast, null);
|
||||
} else {
|
||||
new Alert({
|
||||
:timeout => Globals.scAlertTimeout,
|
||||
:font => Graphics.FONT_MEDIUM,
|
||||
:text => toast,
|
||||
:fgcolor => Graphics.COLOR_WHITE,
|
||||
:bgcolor => Graphics.COLOR_BLACK
|
||||
}).pushView(WatchUi.SLIDE_IMMEDIATE);
|
||||
}
|
||||
} else {
|
||||
if (Globals.scDebug) {
|
||||
System.println("HomeAssistantMenuItem onReturnExecScript(): Unhandled HTTP response code = " + responseCode);
|
||||
}
|
||||
WatchUi.pushView(new ErrorView(strUnhandledHttpErr + responseCode ), new ErrorDelegate(), WatchUi.SLIDE_UP);
|
||||
}
|
||||
}
|
||||
|
||||
@ -114,7 +120,7 @@ class HomeAssistantMenuItem extends WatchUi.MenuItem {
|
||||
// ERROR: venu: Cannot find symbol ':substring' on type 'PolyType<Null or $.Toybox.Lang.Object>'.
|
||||
var id = mIdentifier as Lang.String;
|
||||
if (mService == null) {
|
||||
var url = (Properties.getValue("api_url") as Lang.String) + "/services/" + id.substring(0, id.find(".")) + "/" + id.substring(id.find(".")+1, id.length());
|
||||
var url = (Properties.getValue("api_url") as Lang.String) + "/services/" + id.substring(0, id.find(".")) + "/" + id.substring(id.find(".")+1, null);
|
||||
if (Globals.scDebug) {
|
||||
System.println("HomeAssistantMenuItem execScript() URL=" + url);
|
||||
System.println("HomeAssistantMenuItem execScript() mIdentifier=" + mIdentifier);
|
||||
@ -129,7 +135,7 @@ class HomeAssistantMenuItem extends WatchUi.MenuItem {
|
||||
var url = (Properties.getValue("api_url") as Lang.String) + "/services/" + mService.substring(0, mService.find(".")) + "/" + mService.substring(mService.find(".")+1, null);
|
||||
if (Globals.scDebug) {
|
||||
System.println("HomeAssistantMenuItem execScript() URL=" + url);
|
||||
System.println("HomeAssistantMenuItem execScript() mIdentifier=" + mIdentifier);
|
||||
System.println("HomeAssistantMenuItem execScript() mService=" + mService);
|
||||
}
|
||||
Communications.makeWebRequest(
|
||||
url,
|
||||
@ -140,9 +146,16 @@ class HomeAssistantMenuItem extends WatchUi.MenuItem {
|
||||
method(:onReturnExecScript)
|
||||
);
|
||||
}
|
||||
if (Attention has :vibrate) {
|
||||
Attention.vibrate([
|
||||
new Attention.VibeProfile(50, 100), // On for 100ms
|
||||
new Attention.VibeProfile( 0, 100), // Off for 100ms
|
||||
new Attention.VibeProfile(50, 100) // On for 100ms
|
||||
]);
|
||||
}
|
||||
} else {
|
||||
if (Globals.scDebug) {
|
||||
System.println("HomeAssistantMenuItem Note - execScript(): No Internet connection, skipping API call.");
|
||||
System.println("HomeAssistantMenuItem execScript(): No Internet connection, skipping API call.");
|
||||
}
|
||||
WatchUi.pushView(new ErrorView(strNoInternet + "."), new ErrorDelegate(), WatchUi.SLIDE_UP);
|
||||
}
|
||||
|
@ -24,9 +24,11 @@ using Toybox.Graphics;
|
||||
using Toybox.Application.Properties;
|
||||
|
||||
class HomeAssistantToggleMenuItem extends WatchUi.ToggleMenuItem {
|
||||
hidden var mApiKey = Properties.getValue("api_key");
|
||||
hidden var strNoInternet as Lang.String;
|
||||
hidden var strApiFlood as Lang.String;
|
||||
hidden var mApiKey as Lang.String;
|
||||
hidden var strNoInternet as Lang.String;
|
||||
hidden var strApiFlood as Lang.String;
|
||||
hidden var strApiUrlNotFound as Lang.String;
|
||||
hidden var strUnhandledHttpErr as Lang.String;
|
||||
|
||||
function initialize(
|
||||
label as Lang.String or Lang.Symbol,
|
||||
@ -41,10 +43,12 @@ class HomeAssistantToggleMenuItem extends WatchUi.ToggleMenuItem {
|
||||
:icon as Graphics.BitmapType or WatchUi.Drawable or Lang.Symbol
|
||||
} or Null
|
||||
) {
|
||||
strNoInternet = WatchUi.loadResource($.Rez.Strings.NoInternet);
|
||||
strApiFlood = WatchUi.loadResource($.Rez.Strings.ApiFlood);
|
||||
strNoInternet = WatchUi.loadResource($.Rez.Strings.NoInternet);
|
||||
strApiFlood = WatchUi.loadResource($.Rez.Strings.ApiFlood);
|
||||
strApiUrlNotFound = WatchUi.loadResource($.Rez.Strings.ApiUrlNotFound);
|
||||
strUnhandledHttpErr = WatchUi.loadResource($.Rez.Strings.UnhandledHttpErr);
|
||||
mApiKey = Properties.getValue("api_key");
|
||||
WatchUi.ToggleMenuItem.initialize(label, subLabel, identifier, enabled, options);
|
||||
mApiKey = Properties.getValue("api_key");
|
||||
}
|
||||
|
||||
private function setUiToggle(state as Null or Lang.String) as Void {
|
||||
@ -75,6 +79,17 @@ class HomeAssistantToggleMenuItem extends WatchUi.ToggleMenuItem {
|
||||
// Avoid pushing multiple ErrorViews
|
||||
WatchUi.pushView(new ErrorView(strApiFlood), new ErrorDelegate(), WatchUi.SLIDE_UP);
|
||||
}
|
||||
// Now this feels very "closely coupled" to the application, but it is the most reliable method instead of using a timer.
|
||||
getApp().updateNextMenuItem();
|
||||
} else if (responseCode == 404) {
|
||||
if (Globals.scDebug) {
|
||||
System.println("HomeAssistantToggleMenuItem onReturnGetState() Response Code: 404, page not found. Check API URL setting.");
|
||||
}
|
||||
var cw = WatchUi.getCurrentView();
|
||||
if (!(cw[0] instanceof ErrorView)) {
|
||||
// Avoid pushing multiple ErrorViews
|
||||
WatchUi.pushView(new ErrorView(strApiUrlNotFound), new ErrorDelegate(), WatchUi.SLIDE_UP);
|
||||
}
|
||||
} else if (responseCode == 200) {
|
||||
var state = data.get("state") as Lang.String;
|
||||
if (Globals.scDebug) {
|
||||
@ -84,6 +99,13 @@ class HomeAssistantToggleMenuItem extends WatchUi.ToggleMenuItem {
|
||||
setLabel((data.get("attributes") as Lang.Dictionary).get("friendly_name") as Lang.String);
|
||||
}
|
||||
setUiToggle(state);
|
||||
// Now this feels very "closely coupled" to the application, but it is the most reliable method instead of using a timer.
|
||||
getApp().updateNextMenuItem();
|
||||
} else {
|
||||
if (Globals.scDebug) {
|
||||
System.println("HomeAssistantToggleMenuItem onReturnGetState(): Unhandled HTTP response code = " + responseCode);
|
||||
}
|
||||
WatchUi.pushView(new ErrorView(strUnhandledHttpErr + responseCode ), new ErrorDelegate(), WatchUi.SLIDE_UP);
|
||||
}
|
||||
}
|
||||
|
||||
@ -108,7 +130,7 @@ class HomeAssistantToggleMenuItem extends WatchUi.ToggleMenuItem {
|
||||
);
|
||||
} else {
|
||||
if (Globals.scDebug) {
|
||||
System.println("HomeAssistantToggleMenuItem Note - getState(): No Internet connection, skipping API call.");
|
||||
System.println("HomeAssistantToggleMenuItem getState(): No Internet connection, skipping API call.");
|
||||
}
|
||||
WatchUi.pushView(new ErrorView(strNoInternet + "."), new ErrorDelegate(), WatchUi.SLIDE_UP);
|
||||
}
|
||||
@ -125,10 +147,15 @@ class HomeAssistantToggleMenuItem extends WatchUi.ToggleMenuItem {
|
||||
if (Globals.scDebug) {
|
||||
System.println("HomeAssistantToggleMenuItem onReturnSetState() Response Code: BLE_QUEUE_FULL, API calls too rapid.");
|
||||
}
|
||||
WatchUi.pushView(new ErrorView(strApiFlood), new ErrorDelegate(), WatchUi.SLIDE_UP);
|
||||
} else if (responseCode == 404) {
|
||||
if (Globals.scDebug) {
|
||||
System.println("HomeAssistantToggleMenuItem onReturnSetState() Response Code: 404, page not found. Check API URL setting.");
|
||||
}
|
||||
var cw = WatchUi.getCurrentView();
|
||||
if (!(cw[0] instanceof ErrorView)) {
|
||||
// Avoid pushing multiple ErrorViews
|
||||
WatchUi.pushView(new ErrorView(strApiFlood), new ErrorDelegate(), WatchUi.SLIDE_UP);
|
||||
WatchUi.pushView(new ErrorView(strApiUrlNotFound), new ErrorDelegate(), WatchUi.SLIDE_UP);
|
||||
}
|
||||
} else if (responseCode == 200) {
|
||||
var state;
|
||||
@ -142,6 +169,11 @@ class HomeAssistantToggleMenuItem extends WatchUi.ToggleMenuItem {
|
||||
setUiToggle(state);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (Globals.scDebug) {
|
||||
System.println("HomeAssistantToggleMenuItem onReturnSetState(): Unhandled HTTP response code = " + responseCode);
|
||||
}
|
||||
WatchUi.pushView(new ErrorView(strUnhandledHttpErr + responseCode ), new ErrorDelegate(), WatchUi.SLIDE_UP);
|
||||
}
|
||||
}
|
||||
|
||||
@ -178,7 +210,7 @@ class HomeAssistantToggleMenuItem extends WatchUi.ToggleMenuItem {
|
||||
);
|
||||
} else {
|
||||
if (Globals.scDebug) {
|
||||
System.println("HomeAssistantToggleMenuItem Note - setState(): No Internet connection, skipping API call.");
|
||||
System.println("HomeAssistantToggleMenuItem setState(): No Internet connection, skipping API call.");
|
||||
}
|
||||
WatchUi.pushView(new ErrorView(strNoInternet + "."), new ErrorDelegate(), WatchUi.SLIDE_UP);
|
||||
}
|
||||
|
19
translate.py
19
translate.py
@ -18,7 +18,7 @@
|
||||
# language using Google Translate.
|
||||
#
|
||||
# Python installation:
|
||||
# pip install BeautifulSoup
|
||||
# pip install beautifulsoup4
|
||||
# pip install deep-translator
|
||||
# NB. For XML formatting:
|
||||
# pip install lxml
|
||||
@ -84,9 +84,15 @@ exceptionIds: list[str] = ["AppName", "AppVersionTitle"]
|
||||
titleIds: list[str] = ["setMode", "tapIcon"]
|
||||
|
||||
i = 1
|
||||
with open("./resources/strings/strings.xml") as f:
|
||||
with open("./resources/strings/strings.xml", "r") as f:
|
||||
c = f.read().replace('\r', '')
|
||||
for l in languages:
|
||||
os.makedirs(f"./resources-{l[0]}/strings/", exist_ok=True)
|
||||
try:
|
||||
with open(f"./resources-{l[0]}/strings/corrections.xml", "r") as r:
|
||||
curr = BeautifulSoup(r.read().replace('\r', ''), features="xml")
|
||||
except FileNotFoundError:
|
||||
curr = BeautifulSoup("", features=["xml"])
|
||||
print(f"{i} of {langLength}: Translating English to {l[2]}")
|
||||
soup = BeautifulSoup(c, features="xml")
|
||||
soup.find(name="strings").insert_before("\n\n")
|
||||
@ -99,7 +105,12 @@ with open("./resources/strings/strings.xml") as f:
|
||||
|
||||
for s in soup.find(name="strings").findAll(name="string"):
|
||||
s.insert_before(" ")
|
||||
if s["id"] not in exceptionIds:
|
||||
if s["id"] in exceptionIds: continue
|
||||
|
||||
s_curr = curr.find(name="string", attrs={ "id": s["id"] })
|
||||
if s_curr:
|
||||
s.string = s_curr.string
|
||||
else:
|
||||
a = GoogleTranslator(source='en', target=l[1]).translate(s.string)
|
||||
if s["id"] in titleIds:
|
||||
s.string = a.title()
|
||||
@ -108,8 +119,8 @@ with open("./resources/strings/strings.xml") as f:
|
||||
for s in soup.find(name="strings").findAll(text=lambda text:isinstance(text, Comment)):
|
||||
s.insert_before(" ")
|
||||
s.replace_with(Comment(" " + GoogleTranslator(source='en', target=l[1]).translate(s) + " "))
|
||||
|
||||
#print(str(soup))
|
||||
os.makedirs(f"./resources-{l[0]}/strings/", exist_ok=True)
|
||||
with open(f"./resources-{l[0]}/strings/strings.xml", "wb") as w:
|
||||
w.write(soup.encode("utf-8"))
|
||||
i += 1
|
||||
|
Reference in New Issue
Block a user