diff --git a/.gitignore b/.gitignore
index dbd8c63..f2e2d14 100644
--- a/.gitignore
+++ b/.gitignore
@@ -2,3 +2,6 @@ bin/
export/
**/Thumbs.db
settings.txt
+Thumbs.db
+# This file contain credentials, instead provide the empty file ClientId.mc.unpopulated
+source/ClientId.mc
diff --git a/BatteryReporting.md b/BatteryReporting.md
new file mode 100644
index 0000000..0fff892
--- /dev/null
+++ b/BatteryReporting.md
@@ -0,0 +1,136 @@
+# Battery Reporting
+
+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.
+
+## 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.
+
+## 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`
+
+
+
+```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](https://my.home-assistant.io/redirect/developer_events/) 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).
+4. Restart HomeAssistant or reload the YAML [here](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):
+
+
+
+```yaml
+type: custom:stack-in-card
+direction: vertical
+cards:
+ - type: custom:mushroom-chips-card
+ card_mod:
+ style: |
+ ha-card {
+ height: 0.25rem;
+ }
+ chips:
+ - type: conditional
+ conditions:
+ - condition: state
+ entity: binary_sensor._is_charging
+ state: 'on'
+ chip:
+ type: entity
+ icon_color: yellow
+ entity: sensor._battery_level
+ content_info: none
+ use_entity_picture: false
+ card_mod:
+ style: |
+ ha-card {
+ border: none !important;
+ }
+ - type: conditional
+ conditions:
+ - condition: state
+ entity: binary_sensor._is_charging
+ state: 'off'
+ chip:
+ type: entity
+ entity: sensor._battery_level
+ content_info: none
+ use_entity_picture: false
+ card_mod:
+ style: |
+ ha-card {
+ border: none !important;
+ }
+ - type: gauge
+ entity: sensor._battery_level
+ unit: '%'
+ name: Watch
+ needle: false
+ severity:
+ green: 50
+ yellow: 20
+ red: 0
+ card_mod:
+ style: |
+ ha-card {
+ border: none !important;
+ }
+```
diff --git a/README.md b/README.md
index 8ab4c00..9af4cae 100644
--- a/README.md
+++ b/README.md
@@ -138,9 +138,9 @@ Possible future extensions might include specifying the alternative texts to use
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.
-### Old depricated format
+### Old deprecated format
-Version 1.5 brought in a change to the JSON schema so the follow old format remains useable but is no longer favoured. The schema now marks it as 'depracated' to nudge people over.
+Version 1.5 brought in a change to the JSON schema so the follow old format remains useable but is no longer favoured. The schema now marks it as 'deprecated' to nudge people over.
```json
{
@@ -181,16 +181,30 @@ Make sure you can browse to the URL of your JSON file in a standard web browser
## API Key Creation
-Having created your JSON definition for your dashboard, you need to create an API key for your personal account on Home Assistant.
+Having created your JSON definition for your dashboard, you need to create an API key for your personal account on Home Assistant. You will need a [Long-Lived Access Token](https://developers.home-assistant.io/docs/auth_api/#long-lived-access-token). This is not obvious and is bound to your own Home Assistant account.
+
+Follow the menu sequence: `HA -> user profile -> Long-lived access tokens`. Make sure you save the generated token before dismissing it. You may like to perform this task on your phone so that you can copy and paste it (and message yourself a copy too ;-).

Having created that token, before you dismiss the dialogue box with the value you will never see again, copy it somewhere safe. You need to paste this into the Garmin Application's settings.
-**Please, please, please!** Copy and paste this API key, do not retype as it will be wrong.
+## API URL
+
+If you are using Nabu Casa then your Cloud API URL can be found by looking up your URL via `HA -> Settings -> Home Assistant Cloud -> Remote Control -> Nabu Casa URL`.
+
+
+
+If you have built your own infrastructure, you really don't need any assistance with the API URL!
## Settings
+Unfortunately the Settings dialogue box in the Garmin IQ application times out in Android when you go to a different screen (browser for example). When you go back to the Connect IQ application (select the view again) the settings dialogue box is broken and you have to open the Settings again, so you will need to save the settings every time before you switch applications to avoid losing the information you just put in.
+
+You can instead use an application like [Microsoft's "Phone Link"](https://apps.microsoft.com/detail/9NMPJ99VJBWV?hl=en-gb&gl=US) that allows you to copy and paste between your PC and your phone.
+
+**Please, please, please!** Copy and paste your API key and all URLs, do not retype as it will be wrong.
+
1. Copy and paste your API key you've just created into the top field.
@@ -251,6 +265,10 @@ The `id` attribute values are taken from the same names used in [`strings.xml`](
* The Python script will use the corrections in preference to translating, and
* Your pull request will be honoured without comment as we will take your corrections on trust.
+## Battery Level Reporting
+
+The application and widget both now include a background service to report your watch's battery level and charging status. This requires [significant setup](BatteryReporting.md) via YAML in Home Assistant to work. This is not for the feint hearted! We are keen to received improvements, but are reluctant to provide much in the way of support. The Home Assistant community, in particular the posts on the forum at [Bluetooth Battery Levels (Android)](https://community.home-assistant.io/t/bluetooth-battery-levels-android/661525), are your best source of support for this feature.
+
## Version History
| Version | Comment |
@@ -264,6 +282,7 @@ The `id` attribute values are taken from the same names used in [`strings.xml`](
| 1.6 | Added a user configurable 'timeout' in seconds so that when no action is taken the application automatically closes, stopping the continuous polling for changes of status and hence saving the drain on the battery. This can be disabled with timeout=0. |
| 1.7 | Added timeout to confirmation views so that when used for security devices it does not linger when left unconfirmed. Thanks to [Jan Schneider](https://github.com/j-a-n) for the contribution. Known bug for devices not supporting [`WatchUi.getCurrentView()`](https://developer.garmin.com/connect-iq/api-docs/Toybox/WatchUi.html#getCurrentView-instance_function) API call which is only available on API Level 3.4.0, e.g. Vivoactive 4S. |
| 2.0 | A significant code base change to enable both a 'widget' version for older devices, e.g. Venu (1), and an application with a glance, e.g. Venu2. These two versions must now be distributed under separate application IDs, but they have the same code base. A further 20 more devices are now supported, the settings have been internationalised, and there's a bug fix for older devices when trying to display a helpful error message but instead the application crashed. This version has come from a significant collaboration with [Someone0nEarth](https://github.com/Someone0nEarth). |
+| 2.1 | Deployment of an idea to provide Home Assistant with access to the watch battery level. Using this requires [significant setup](BatteryReporting.md) on the Home Assistant configuration and will be detailed separately. Due to this, the default state for this battery option is _off_. Changed the application settings user interface to be more intuitive, and hence amended the way settings are managed in the background. |
## Known Issues
diff --git a/compile_sim.cmd b/compile_sim.cmd
new file mode 100644
index 0000000..a3f3159
--- /dev/null
+++ b/compile_sim.cmd
@@ -0,0 +1,110 @@
+@echo off
+rem -----------------------------------------------------------------------------------
+rem
+rem Distributed under MIT Licence
+rem See https://github.com/house-of-abbey/GarminHomeAssistant/blob/main/LICENSE.
+rem
+rem -----------------------------------------------------------------------------------
+rem
+rem GarminHomeAssistant is a Garmin IQ application written in Monkey C and routinely
+rem tested on a Venu 2 device. The source code is provided at:
+rem https://github.com/house-of-abbey/GarminHomeAssistant.
+rem
+rem J D Abbey & P A Abbey, 28 December 2022
+rem
+rem For use when VS Code is misbehaving and failing to recompile before starting a simulation.
+rem
+rem Reference:
+rem * Using Monkey C from the Command Line
+rem https://developer.garmin.com/connect-iq/reference-guides/monkey-c-command-line-setup/
+rem
+rem -----------------------------------------------------------------------------------
+
+rem Check this path is correct for your Java installation
+set JAVA_PATH=C:\Program Files (x86)\Common Files\Oracle\Java\javapath
+rem SDK_PATH should work for all users
+set /p SDK_PATH=<"%USERPROFILE%\AppData\Roaming\Garmin\ConnectIQ\current-sdk.cfg"
+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 C:\>java -jar %SDK_PATH%\monkeybrains.jar -h
+rem usage: monkeyc [-a ] [-b ] [--build-stats ] [-c ] [-d ]
+rem [--debug-log-level ] [--debug-log-output ] [-e]
+rem [--Eno-invalid-symbol] [-f ] [-g] [-h] [-i ] [-k] [-l ]
+rem [-m ] [--no-gen-styles] [-o ] [-O ] [-p ] [-r] [-s
+rem ] [-t] [-u ] [-v] [-w] [-x ] [-y ] [-z ]
+rem -a,--apidb API import file
+rem -b,--apimir API MIR file
+rem --build-stats Print build stats [0=basic]
+rem -c,--api-level API Level to target
+rem -d,--device Target device
+rem --debug-log-level Debug logging verbosity [0=errors, 1=basic,
+rem 2=intermediate, 3=verbose]
+rem --debug-log-output Output log zip file
+rem -e,--package-app Create an application package.
+rem --Eno-invalid-symbol Do not error when a symbol is found to be invalid
+rem -f,--jungles Jungle files
+rem -g,--debug Print debug output
+rem -h,--help Prints help information
+rem -i,--import-dbg Import api.debug.xml
+rem -k,--profile Enable profiling support
+rem -l,--typecheck Type check [0=off, 1=gradual, 2=informative,
+rem 3=strict]
+rem -m,--manifest Manifest file (deprecated)
+rem --no-gen-styles Do not generate Rez.Styles module
+rem -o,--output Output file to create
+rem -O,--optimization Optimization level [0=none, 1=basic, 2=fast
+rem optimizations, 3=slow optimizations] [p=optimize
+rem performance, z=optimize code space]
+rem -p,--project-info projectInfo.xml file to use when compiling
+rem -r,--release Strip debug information
+rem -s,--sdk-version SDK version to target (deprecated, use -c
+rem -t,--unit-test Enables compilation of unit tests
+rem -u,--devices devices.xml file to use when compiling (deprecated)
+rem -v,--version Prints the compiler version
+rem -w,--warn Show compiler warnings
+rem -x,--excludes Add annotations to the exclude list (deprecated)
+rem -y,--private-key Private key to sign builds with
+rem -z,--rez Resource files (deprecated)
+
+rem Batch file's directory where the source code is
+set SRC=%~dp0
+rem drop last character '\'
+set SRC=%SRC:~0,-1%
+
+if not exist %DEST% (
+ md %DEST%
+)
+
+if exist %SRC%\export\HomeAssistant*.iq (
+ del /f /q %SRC%\export\HomeAssistant*.iq
+)
+
+echo.
+echo Starting compilation for simulation on %DEVICE%.
+echo.
+
+rem call %SDK_PATH%\connectiq.bat
+start "Simulator" "%SDK_PATH%\simulator.exe"
+
+rem Compile PRG for a single device for side loading
+"%JAVA_PATH%\java.exe" ^
+ -Xms1g ^
+ -Dfile.encoding=UTF-8 ^
+ -Dapple.awt.UIElement=true ^
+ -jar %SDK_PATH%\monkeybrains.jar ^
+ --output %SRC%\bin\HomeAssistant.prg ^
+ --jungles %SRC%\monkey.jungle ^
+ --private-key %SRC%\..\developer_key ^
+ --device %DEVICE%_sim ^
+ --warn
+
+if %ERRORLEVEL% equ 0 (
+ %SDK_PATH%\monkeydo.bat %SRC%\bin\HomeAssistant.prg %DEVICE%
+) else (
+ rem Wait to see errors
+ pause
+)
diff --git a/export.cmd b/export.cmd
index 8ce3b82..4f5315f 100644
--- a/export.cmd
+++ b/export.cmd
@@ -1,21 +1,23 @@
@echo off
rem -----------------------------------------------------------------------------------
-rem
+rem
rem Distributed under MIT Licence
rem See https://github.com/house-of-abbey/GarminHomeAssistant/blob/main/LICENSE.
-rem
+rem
rem -----------------------------------------------------------------------------------
-rem
+rem
rem GarminHomeAssistant is a Garmin IQ application written in Monkey C and routinely
rem tested on a Venu 2 device. The source code is provided at:
rem https://github.com/house-of-abbey/GarminHomeAssistant.
-rem
+rem
rem J D Abbey & P A Abbey, 28 December 2022
-rem
+rem
+rem Export both the Application and the Widget IQ files for upload to Garmin's App Store.
+rem
rem Reference:
rem * Using Monkey C from the Command Line
-rem * https://developer.garmin.com/connect-iq/reference-guides/monkey-c-command-line-setup/
-rem
+rem https://developer.garmin.com/connect-iq/reference-guides/monkey-c-command-line-setup/
+rem
rem -----------------------------------------------------------------------------------
rem Check this path is correct for your Java installation
@@ -118,16 +120,3 @@ echo Finished exporting HomeAssistant
dir %SRC%\export\HomeAssistant*.iq
pause
-exit /b
-
-rem Compile PRG for a single device for side loading
-"%JAVA_PATH%\java.exe" ^
- -Xms1g ^
- -Dfile.encoding=UTF-8 ^
- -Dapple.awt.UIElement=true ^
- -jar %SDK_PATH%\monkeybrains.jar ^
- --output %SRC%\bin\HomeAssistant.prg ^
- --jungles %SRC%\monkey.jungle ^
- --private-key %SRC%\..\developer_key ^
- --device venu2_sim ^
- --warn
diff --git a/images/Battery_Event_Screenshot.png b/images/Battery_Event_Screenshot.png
new file mode 100644
index 0000000..60a1574
Binary files /dev/null and b/images/Battery_Event_Screenshot.png differ
diff --git a/images/Battery_Guage_Screenshot.png b/images/Battery_Guage_Screenshot.png
new file mode 100644
index 0000000..c7ad54a
Binary files /dev/null and b/images/Battery_Guage_Screenshot.png differ
diff --git a/images/GarminHomeAssistantSettings.png b/images/GarminHomeAssistantSettings.png
index 7d4e228..2583f59 100644
Binary files a/images/GarminHomeAssistantSettings.png and b/images/GarminHomeAssistantSettings.png differ
diff --git a/images/Nabu_Casa_Remote_Control.png b/images/Nabu_Casa_Remote_Control.png
new file mode 100644
index 0000000..9da8044
Binary files /dev/null and b/images/Nabu_Casa_Remote_Control.png differ
diff --git a/images/Venu2_glance_start.png b/images/Venu2_glance_start.png
index 4d4a126..57238da 100644
Binary files a/images/Venu2_glance_start.png and b/images/Venu2_glance_start.png differ
diff --git a/images/source/Options1.jpg b/images/source/Options1.jpg
new file mode 100644
index 0000000..3c87b68
Binary files /dev/null and b/images/source/Options1.jpg differ
diff --git a/images/source/Options2.jpg b/images/source/Options2.jpg
new file mode 100644
index 0000000..d6755b2
Binary files /dev/null and b/images/source/Options2.jpg differ
diff --git a/launcherIconResize.py b/launcherIconResize.py
new file mode 100644
index 0000000..0dc8b1a
--- /dev/null
+++ b/launcherIconResize.py
@@ -0,0 +1,70 @@
+####################################################################################
+#
+# Distributed under MIT Licence
+# See https://github.com/house-of-abbey/GarminHomeAssistant/blob/main/LICENSE.
+#
+####################################################################################
+#
+# GarminHomeAssistant is a Garmin IQ application written in Monkey C and routinely
+# tested on a Venu 2 device. The source code is provided at:
+# https://github.com/house-of-abbey/GarminHomeAssistant.
+#
+# J D Abbey & P A Abbey, 29 December 2023
+#
+#
+# Description:
+#
+# Python script to automatically resize the application launcher icon from the
+# original 70x70 pixel width to something more appropriate for different screen
+# sizes.
+#
+# Python installation:
+# pip install BeautifulSoup
+# NB. For XML formatting:
+# pip install lxml
+#
+# References:
+# * https://www.crummy.com/software/BeautifulSoup/bs4/doc/
+# * https://realpython.com/beautiful-soup-web-scraper-python/
+# * https://www.crummy.com/software/BeautifulSoup/bs4/doc/#parsing-xml
+# * https://www.crummy.com/software/BeautifulSoup/bs4/doc/#xml
+#
+####################################################################################
+
+from bs4 import BeautifulSoup, Comment
+import os
+import shutil
+
+output_dir_prefix = 'resources-launcher-'
+# Original icons for 416x416 screen size with 70x70 icons
+input_dir = output_dir_prefix + '70-70'
+
+# Convert icons to different screen sizes by these parameters
+lookup = [26, 30, 33, 35, 36, 40, 54, 60, 61, 62, 65, 80]
+
+# Delete all but the original 48x48 icon directories
+for entry in os.listdir("."):
+ if entry.startswith(output_dir_prefix) and entry != input_dir:
+ shutil.rmtree(entry)
+
+# (Re-)Create the resized icon directories
+for icon_size in lookup:
+ output_dir = output_dir_prefix + str(icon_size) + "-" + str(icon_size)
+ print("\nCreate directory:", output_dir)
+ if os.path.exists(output_dir) and os.path.isdir(output_dir):
+ shutil.rmtree(output_dir)
+ os.makedirs(output_dir)
+ for entry in os.listdir(input_dir):
+ if entry.endswith(".svg"):
+ print("Create file: ", entry.ljust(40) + " SVG - Change file")
+ with open(input_dir + "/" + entry, "r") as f:
+ soup = BeautifulSoup(f.read(), features="xml")
+ svg: BeautifulSoup = list(soup.children)[0]
+ h = int(svg.attrs["height"])
+ svg.attrs["width"] = icon_size
+ svg.attrs["height"] = icon_size
+ with open(output_dir + "/" + entry, "wb") as o:
+ o.write(svg.encode("utf-8"))
+ elif entry.endswith(".xml"):
+ print("Create file: ", entry.ljust(40) + " XML - Copy file")
+ shutil.copyfile(input_dir + "/" + entry, output_dir + "/" + entry)
diff --git a/manifest-widget.xml b/manifest-widget.xml
index 6fdc41b..227f805 100644
--- a/manifest-widget.xml
+++ b/manifest-widget.xml
@@ -17,7 +17,7 @@
Someone0nEarth's Test Widget id="bf69be91-5833-4d96-92ea-c5f1a9db5dcc" type="widget"
philipabbey's Test Widget id="4901cdfb-b4a2-4f33-96c7-f5be5992809e" type="widget"
- Live Widget id="" type="widget"
+ Live Widget id="585af26f-6ff7-44e8-80dc-b3670e5b8648" type="widget"
-->
@@ -140,8 +140,9 @@
palette to update permissions.
-->
-
+
+
-
+
+
+ يختار...مفتاح API لـ HomeAssistant.رمز الوصول طويل الأمد.عنوان URL لواجهة برمجة تطبيقات HomeAssistant.عنوان URL لتكوين القائمة (JSON).المهلة بالثواني. قم بالخروج من التطبيق بعد هذه الفترة من عدم النشاط لحفظ بطارية الجهاز.بعد هذا الوقت (بالثواني)، يتم إغلاق مربع حوار تأكيد الإجراء تلقائيًا ويتم إلغاء الإجراء. اضبط على 0 لتعطيل المهلة.
- تمثيل الأنواع بأيقونات (إيقاف) أو بالتسميات (تشغيل).
+ نمط عنصر القائمة.
+ أيقونات
+ نص إضافيمحاذاة القائمة لليسار (إيقاف) أو لليمين (تشغيل).
+ من اليسار إلى اليمين
+ من اليمين الى اليسار(القطعة فقط) قم بتشغيل التطبيق تلقائيًا من الأداة دون انتظار نقرة واحدة.
+ قم بتمكين خدمة الخلفية لإرسال مستوى بطارية الساعة إلى Home Assistant.
+ معدل التحديث (بالدقائق) الذي يجب أن تكرر عنده خدمة الخلفية إرسال مستوى البطارية.
\ No newline at end of file
diff --git a/resources-bul/strings/strings.xml b/resources-bul/strings/strings.xml
index 7c70a3c..e7b5dd3 100644
--- a/resources-bul/strings/strings.xml
+++ b/resources-bul/strings/strings.xml
@@ -43,13 +43,20 @@
НеконфигуриранМеню
+ Изберете...API ключ за HomeAssistant.Токен за дълготраен достъп.URL адрес за API на HomeAssistant.URL за конфигурация на менюто (JSON).Изчакване в секунди. Излезте от приложението след този период на неактивност, за да запазите батерията на устройството.След това време (в секунди) диалоговият прозорец за потвърждение за действие се затваря автоматично и действието се отменя. Задайте 0, за да деактивирате изчакването.
- Представяне на типове с икони (изключено) или с етикети (включено).
+ Стил на елемент от менюто.
+ Икони
+ Допълнителен текстЛяво (изключено) или дясно (включено) подравняване на менюто.
+ Отляво надясно
+ От дясно на ляво(Само за джаджа) Автоматично стартирайте приложението от джаджата, без да чакате докосване.
+ Активирайте фоновата услуга, за да изпратите нивото на батерията на часовника до Home Assistant.
+ Честотата на опресняване (в минути), с която фоновата услуга трябва да повтори изпращането на нивото на батерията.
\ No newline at end of file
diff --git a/resources-ces/strings/strings.xml b/resources-ces/strings/strings.xml
index 80217d0..6511964 100644
--- a/resources-ces/strings/strings.xml
+++ b/resources-ces/strings/strings.xml
@@ -32,7 +32,7 @@
V nastavení aplikace není žádná adresa URL APIV nastavení aplikace není žádná konfigurační URLPříliš rychlá volání API. Zpomalte prosím své požadavky.
- Adresa URL nenalezena. Potenciální chyba URL API v nastavení.
+ Adresa URL nenalezena. Potenciální chyba adresy URL rozhraní API v nastavení.Adresa URL nenalezena. Potenciální chyba konfigurační adresy URL v nastavení.Z požadavku HTTP se nevrátil žádný JSON.Požadavek HTTP vrátil kód chyby =
@@ -43,13 +43,20 @@
NenakonfigurovánoJídelní lístek
+ Vybrat...Klíč API pro HomeAssistant.Přístupový token s dlouhou životností.URL pro HomeAssistant API.Adresa URL pro konfiguraci nabídky (JSON).Časový limit v sekundách. Po této době nečinnosti aplikaci ukončete, abyste šetřili baterii zařízení.Po uplynutí této doby (v sekundách) se dialog pro potvrzení akce automaticky zavře a akce se zruší. Nastavením na 0 deaktivujete časový limit.
- Znázornění typů pomocí ikon (vypnuto) nebo pomocí štítků (zapnuto).
+ Styl položky menu.
+ ikony
+ Doplňkový textZarovnání nabídky vlevo (vypnuto) nebo vpravo (zapnuto).
+ Zleva do prava
+ Zprava doleva(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 0eb465d..fbf8946 100644
--- a/resources-dan/strings/strings.xml
+++ b/resources-dan/strings/strings.xml
@@ -43,13 +43,20 @@
UkonfigureretMenu
+ Vælg...API-nøgle til HomeAssistant.Adgangstoken med lang levetid.URL til HomeAssistant API.URL til menukonfiguration (JSON).Timeout i sekunder. Afslut applikationen efter denne periode med inaktivitet for at spare på enhedens batteri.Efter dette tidspunkt (i sekunder) lukkes en bekræftelsesdialog for en handling automatisk, og handlingen annulleres. Indstil til 0 for at deaktivere timeout.
- Repræsenterer typer med ikoner (fra) eller med etiketter (til).
+ Menupunkt stil.
+ Ikoner
+ Yderligere tekstVenstre (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 057d090..bfeb8b8 100644
--- a/resources-deu/strings/strings.xml
+++ b/resources-deu/strings/strings.xml
@@ -43,13 +43,20 @@
UnkonfiguriertSpeisekarte
+ Wählen...API-Schlüssel für HomeAssistant.Langlebiges Zugriffstoken.URL für die HomeAssistant-API.URL zur Menükonfiguration (JSON).Timeout in Sekunden. Beenden Sie die Anwendung nach dieser Zeit der Inaktivität, um den Akku des Geräts zu schonen.Nach dieser Zeit (in Sekunden) wird automatisch ein Bestätigungsdialog für eine Aktion geschlossen und die Aktion abgebrochen. Auf 0 setzen, um das Timeout zu deaktivieren.
- Darstellen von Typen mit Symbolen (aus) oder mit Beschriftungen (ein).
+ Menüelementstil.
+ Symbole
+ Zusätzlicher TextMenüausrichtung links (aus) oder rechts (ein).
+ Links nach rechts
+ Rechts nach links(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 20b60e1..a799e61 100644
--- a/resources-dut/strings/strings.xml
+++ b/resources-dut/strings/strings.xml
@@ -43,13 +43,20 @@
Niet geconfigureerdMenu
+ Selecteer...API-sleutel voor HomeAssistant.Toegangstoken met lange levensduur.URL voor HomeAssistant API.URL voor menuconfiguratie (JSON).Time-out in seconden. Sluit de applicatie af na deze periode van inactiviteit om de batterij van het apparaat te sparen.Na deze tijd (in seconden) wordt automatisch een bevestigingsvenster voor een actie gesloten en wordt de actie geannuleerd. Stel in op 0 om de time-out uit te schakelen.
- Typen weergeven met pictogrammen (uit) of met labels (aan).
+ Stijl van menu-items.
+ Pictogrammen
+ Aanvullende tekstLinks (uit) of rechts (aan) Menu-uitlijning.
+ Van links naar rechts
+ Rechts naar links(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 7ab95cc..bd74727 100644
--- a/resources-est/strings/strings.xml
+++ b/resources-est/strings/strings.xml
@@ -31,10 +31,10 @@
Rakenduse seadetes pole API-võtitRakenduse seadetes pole API URL-iRakenduse seadetes pole konfiguratsiooni URL-i
- API-kõned liiga kiired. Palun aeglustage oma taotlusi.
+ API-kutsed liiga kiired. Palun aeglustage taotluste esitamist.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 „/”Saadaval
@@ -43,13 +43,20 @@
KonfigureerimataMenüü
+ Vali...API-võti HomeAssistantile.Pikaealine juurdepääsuluba.HomeAssistant API URL.URL menüü konfigureerimiseks (JSON).Aegumine sekundites. Seadme aku säästmiseks sulgege rakendus pärast seda tegevusetusperioodi.Pärast seda aega (sekundites) suletakse automaatselt toimingu kinnitusdialoog ja toiming tühistatakse. Ajalõpu keelamiseks määrake väärtusele 0.
- Tüüpide tähistamine ikoonidega (väljas) või siltidega (sees).
+ Menüüelemendi stiil.
+ Ikoonid
+ Täiendav tekstVasak (väljas) või parem (sees) menüü joondamine.
+ Vasakult paremale
+ Paremalt vasakule(Ainult vidin) Käivitage rakendus automaatselt vidinast ilma puudutust ootamata.
+ Lubage taustteenus, 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 fd70bc2..11a1495 100644
--- a/resources-fin/strings/strings.xml
+++ b/resources-fin/strings/strings.xml
@@ -43,13 +43,20 @@
MäärittämätönValikko
+ Valitse...API-avain HomeAssistantille.Pitkäikäinen pääsytunnus.HomeAssistant API:n URL-osoite.URL-osoite valikon määrityksiä varten (JSON).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 poistaaksesi aikakatkaisun käytöstä.
- Esittää tyyppejä kuvakkeilla (pois päältä) tai tarroilla (päällä).
+ Valikkokohdan tyyli.
+ Kuvakkeet
+ LisätekstiVasen (pois) tai oikea (päällä) valikon kohdistus.
+ Vasemmalta oikealle
+ Oikealta vasemmalle(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 ab02a1f..55666b2 100644
--- a/resources-fre/strings/strings.xml
+++ b/resources-fre/strings/strings.xml
@@ -43,13 +43,20 @@
Non configuréMenu
+ Sélectionner...Clé API pour HomeAssistant.Jeton d'accès de longue durée.URL de l’API HomeAssistant.URL de configuration des menus (JSON).
- 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.
- Représentation des types avec des icônes (off) ou avec des étiquettes (on).
+ Style des éléments de menu.
+ Icônes
+ Texte supplémentaireAlignement du menu à gauche (désactivé) ou à droite (activé).
+ De gauche à droite
+ De droite à gauche(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 7e77b57..a2d10bd 100644
--- a/resources-gre/strings/strings.xml
+++ b/resources-gre/strings/strings.xml
@@ -43,13 +43,20 @@
Μη διαμορφωμένοΜενού
+ Επιλέγω...Κλειδί API για το HomeAssistant.Διακριτικό πρόσβασης μακράς διαρκείας.URL για το HomeAssistant API.URL για τη διαμόρφωση μενού (JSON).Timeout σε δευτερόλεπτα. Κλείστε την εφαρμογή μετά από αυτήν την περίοδο αδράνειας για να εξοικονομήσετε την μπαταρία της συσκευής.Μετά από αυτό το χρονικό διάστημα (σε δευτερόλεπτα), ένα παράθυρο διαλόγου επιβεβαίωσης για μια ενέργεια κλείνει αυτόματα και η ενέργεια ακυρώνεται. Ορίστε στο 0 για να απενεργοποιήσετε το χρονικό όριο.
- Αναπαράσταση τύπων με εικονίδια (απενεργοποίηση) ή με ετικέτες (ενεργό).
+ Στυλ στοιχείου μενού.
+ εικονίδια
+ Πρόσθετο ΚείμενοΑριστερά (απενεργοποίηση) ή Δεξιά (ενεργό) Ευθυγράμμιση μενού.
+ Από αριστερά προς τα δεξιά
+ Δεξιά προς τα αριστερά(Μόνο 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 f3fbb14..d9c55e1 100644
--- a/resources-heb/strings/strings.xml
+++ b/resources-heb/strings/strings.xml
@@ -30,7 +30,7 @@
אין תגובה, בדוק חיבור לאינטרנטאין מפתח API בהגדרות האפליקציהאין כתובת API בהגדרות האפליקציה
- אין כתובת אתר תצורה בהגדרות האפליקציה
+ אין כתובת URL לתצורה בהגדרות האפליקציהקריאות API מהירות מדי. נא להאט את הבקשות שלך.כתובת האתר לא נמצאה. שגיאה פוטנציאלית של כתובת ה-API בהגדרות.כתובת האתר לא נמצאה. שגיאת כתובת אתר פוטנציאלית של תצורה בהגדרות.
@@ -43,13 +43,20 @@
לא מוגדרתַפרִיט
+ בחר...מפתח API עבור HomeAssistant.אסימון גישה ארוך-חיים.כתובת URL עבור HomeAssistant API.כתובת URL לתצורת תפריט (JSON).פסק זמן בשניות. צא מהאפליקציה לאחר תקופה זו של חוסר פעילות כדי לחסוך בסוללת המכשיר.
- לאחר זמן זה (בשניות), תיבת דו-שיח לאישור פעולה נסגרת אוטומטית והפעולה מבוטלת. הגדר ל-0 כדי לבטל את הזמן הקצוב.
- ייצוג סוגים עם סמלים (כבוי) או עם תוויות (מופעל).
+ לאחר זמן זה (בשניות), תיבת דו-שיח לאישור פעולה נסגרת אוטומטית והפעולה מבוטלת. הגדר ל-0 כדי להשבית את הזמן הקצוב.
+ סגנון פריט בתפריט.
+ אייקונים
+ טקסט נוסףיישור תפריט שמאלה (כבוי) או ימינה (מופעל).
+ משמאל לימין
+ מימין לשמאל(יישומון בלבד) הפעל אוטומטית את האפליקציה מהווידג'ט מבלי לחכות להקשה.
+ אפשר את שירות הרקע כדי לשלוח את רמת הסוללה של השעון אל Home Assistant.
+ קצב הרענון (בדקות) שבו שירות הרקע אמור לחזור על שליחת רמת הסוללה.
\ No newline at end of file
diff --git a/resources-hrv/strings/strings.xml b/resources-hrv/strings/strings.xml
index 79ac32c..5b8d9db 100644
--- a/resources-hrv/strings/strings.xml
+++ b/resources-hrv/strings/strings.xml
@@ -43,13 +43,20 @@
NekonfiguriranoJelovnik
+ Izaberi...API ključ za HomeAssistant.Dugotrajni pristupni token.URL za HomeAssistant API.URL za konfiguraciju izbornika (JSON).Istek u sekundama. Izađite iz aplikacije nakon ovog razdoblja neaktivnosti kako biste uštedjeli bateriju uređaja.Nakon tog vremena (u sekundama), dijaloški okvir za potvrdu radnje automatski se zatvara i radnja se poništava. Postavite na 0 da onemogućite vremensko ograničenje.
- Predstavljanje tipova ikonama (isključeno) ili oznakama (uključeno).
+ Stil stavke izbornika.
+ Ikone
+ Dodatni tekstLijevo (isključeno) ili desno (uključeno) poravnanje izbornika.
+ S lijeva nadesno
+ S desna na lijevo(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 22da591..4f0d427 100644
--- a/resources-hun/strings/strings.xml
+++ b/resources-hun/strings/strings.xml
@@ -43,13 +43,20 @@
Nincs konfigurálvaMenü
+ Válassz...API-kulcs a HomeAssistant számára.Hosszú életű hozzáférési token.A HomeAssistant API URL-je.URL a menükonfigurációhoz (JSON).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ő 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.
- A típusokat ikonokkal (kikapcsolva) vagy címkékkel (bekapcsolva) ábrázolja.
+ 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.
+ Menüelem stílusa.
+ Ikonok
+ Kiegészítő szövegBalra (ki) vagy Jobbra (be) Menüigazítás.
- (Csak widget) Az alkalmazás automatikus indítása a widgetről anélkül, hogy egy érintésre várna.
+ 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.
+ 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 0a8591d..cde4a6f 100644
--- a/resources-ind/strings/strings.xml
+++ b/resources-ind/strings/strings.xml
@@ -43,13 +43,20 @@
Tidak dikonfigurasiMenu
+ Pilih...Kunci API untuk HomeAssistant.Token Akses Berumur Panjang.URL untuk API HomeAssistant.URL untuk konfigurasi menu (JSON).Batas waktu dalam hitungan detik. Keluar dari aplikasi setelah periode tidak aktif ini untuk menghemat baterai perangkat.Setelah waktu ini (dalam detik), dialog konfirmasi untuk suatu tindakan secara otomatis ditutup dan tindakan tersebut dibatalkan. Setel ke 0 untuk menonaktifkan batas waktu.
- Mewakili tipe dengan ikon (mati) atau dengan label (aktif).
+ Gaya item menu.
+ Ikon
+ Teks TambahanPenyelarasan Menu Kiri (mati) atau Kanan (hidup).
+ Kiri ke kanan
+ Kanan ke kiri(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 1c02546..8fc873a 100644
--- a/resources-ita/strings/strings.xml
+++ b/resources-ita/strings/strings.xml
@@ -43,13 +43,20 @@
Non configuratoMenù
+ Selezionare...Chiave API per HomeAssistant.Token di accesso di lunga durata.URL per l'API HomeAssistant.URL per la configurazione del menu (JSON).Timeout in secondi. Uscire dall'applicazione dopo questo periodo di inattività per risparmiare la batteria del dispositivo.Trascorso questo tempo (in secondi), una finestra di dialogo di conferma per un'azione viene chiusa automaticamente e l'azione viene annullata. Impostare su 0 per disabilitare il timeout.
- Rappresentazione dei tipi con icone (disattivata) o con etichette (attivata).
+ Stile della voce di menu.
+ Icone
+ Testo aggiuntivoAllineamento del menu a sinistra (spento) o a destra (acceso).
+ Da sinistra a destra
+ Da destra a sinistra(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 da834ac..180f7e5 100644
--- a/resources-jpn/strings/strings.xml
+++ b/resources-jpn/strings/strings.xml
@@ -43,13 +43,20 @@
未構成メニュー
+ 選択する...ホームアシスタントの API キー。有効期間の長いアクセス トークン。ホームアシスタント API の URL。メニュー構成の URL (JSON)。秒単位のタイムアウト。デバイスのバッテリーを節約するために、この期間非アクティブになった後はアプリケーションを終了してください。この時間 (秒単位) が経過すると、アクションの確認ダイアログが自動的に閉じられ、アクションがキャンセルされます。タイムアウトを無効にするには、0 に設定します。
- タイプをアイコン (オフ) またはラベル (オン) で表します。
+ メニュー項目のスタイル。
+ アイコン
+ 追加テキスト左 (オフ) または右 (オン) メニューの配置。
+ 左から右へ
+ 右から左に(ウィジェットのみ)タップを待たずにウィジェットからアプリを自動起動します。
+ バックグラウンド サービスを有効にして、時計のバッテリー レベルをホーム アシスタントに送信します。
+ バックグラウンド サービスがバッテリー レベルの送信を繰り返すリフレッシュ レート (分単位)。
\ No newline at end of file
diff --git a/resources-kor/strings/strings.xml b/resources-kor/strings/strings.xml
index e54002c..49d94f0 100644
--- a/resources-kor/strings/strings.xml
+++ b/resources-kor/strings/strings.xml
@@ -36,20 +36,27 @@
URL을 찾을 수 없습니다. 설정에 잠재적인 구성 URL 오류가 있습니다.HTTP 요청에서 JSON이 반환되지 않았습니다.HTTP 요청이 오류 코드를 반환했습니다 =
- API URL에는 후행 슬래시 '/'가 없어야 합니다.
+ API URL에는 후행 슬래시 '/'가 있어서는 안 됩니다.사용 가능확인 중...없는구성되지 않음메뉴
+ 선택하다...HomeAssistant용 API 키.장기 액세스 토큰.HomeAssistant API의 URL입니다.메뉴 구성을 위한 URL(JSON)입니다.시간 초과(초)입니다. 장치 배터리를 절약하려면 이 비활성 기간 후에 애플리케이션을 종료하십시오.이 시간(초)이 지나면 작업에 대한 확인 대화 상자가 자동으로 닫히고 작업이 취소됩니다. 시간 초과를 비활성화하려면 0으로 설정합니다.
- 아이콘(끄기) 또는 레이블(켜기)로 유형을 나타냅니다.
+ 메뉴 항목 스타일.
+ 아이콘
+ 추가 텍스트왼쪽(끄기) 또는 오른쪽(켜기) 메뉴 정렬.
+ 왼쪽에서 오른쪽으로
+ 오른쪽에서 왼쪽으로(위젯만 해당) 탭을 기다리지 않고 위젯에서 애플리케이션을 자동으로 시작합니다.
+ 시계 배터리 수준을 홈어시스턴트로 보내려면 백그라운드 서비스를 활성화하세요.
+ 백그라운드 서비스가 배터리 수준 전송을 반복해야 하는 새로 고침 빈도(분)입니다.
\ No newline at end of file
diff --git a/resources-launcher-26-26/drawables.xml b/resources-launcher-26-26/drawables.xml
index b9e68f9..44c0b71 100644
--- a/resources-launcher-26-26/drawables.xml
+++ b/resources-launcher-26-26/drawables.xml
@@ -13,5 +13,5 @@
-->
-
+
diff --git a/resources-launcher-26-26/launcher.png b/resources-launcher-26-26/launcher.png
deleted file mode 100644
index c82ef3a..0000000
Binary files a/resources-launcher-26-26/launcher.png and /dev/null differ
diff --git a/resources-launcher-26-26/launcher.svg b/resources-launcher-26-26/launcher.svg
new file mode 100644
index 0000000..8d7af19
--- /dev/null
+++ b/resources-launcher-26-26/launcher.svg
@@ -0,0 +1,4 @@
+
\ No newline at end of file
diff --git a/resources-launcher-30-30/drawables.xml b/resources-launcher-30-30/drawables.xml
index b9e68f9..44c0b71 100644
--- a/resources-launcher-30-30/drawables.xml
+++ b/resources-launcher-30-30/drawables.xml
@@ -13,5 +13,5 @@
-->
-
+
diff --git a/resources-launcher-30-30/launcher.png b/resources-launcher-30-30/launcher.png
deleted file mode 100644
index 6ee0210..0000000
Binary files a/resources-launcher-30-30/launcher.png and /dev/null differ
diff --git a/resources-launcher-30-30/launcher.svg b/resources-launcher-30-30/launcher.svg
new file mode 100644
index 0000000..779de26
--- /dev/null
+++ b/resources-launcher-30-30/launcher.svg
@@ -0,0 +1,4 @@
+
\ No newline at end of file
diff --git a/resources-launcher-33-33/drawables.xml b/resources-launcher-33-33/drawables.xml
index b9e68f9..44c0b71 100644
--- a/resources-launcher-33-33/drawables.xml
+++ b/resources-launcher-33-33/drawables.xml
@@ -13,5 +13,5 @@
-->
-
+
diff --git a/resources-launcher-33-33/launcher.png b/resources-launcher-33-33/launcher.png
deleted file mode 100644
index 8dfd712..0000000
Binary files a/resources-launcher-33-33/launcher.png and /dev/null differ
diff --git a/resources-launcher-33-33/launcher.svg b/resources-launcher-33-33/launcher.svg
new file mode 100644
index 0000000..6943515
--- /dev/null
+++ b/resources-launcher-33-33/launcher.svg
@@ -0,0 +1,4 @@
+
\ No newline at end of file
diff --git a/resources-launcher-35-35/drawables.xml b/resources-launcher-35-35/drawables.xml
index b9e68f9..44c0b71 100644
--- a/resources-launcher-35-35/drawables.xml
+++ b/resources-launcher-35-35/drawables.xml
@@ -13,5 +13,5 @@
-->
-
+
diff --git a/resources-launcher-35-35/launcher.png b/resources-launcher-35-35/launcher.png
deleted file mode 100644
index 1d51ea4..0000000
Binary files a/resources-launcher-35-35/launcher.png and /dev/null differ
diff --git a/resources-launcher-35-35/launcher.svg b/resources-launcher-35-35/launcher.svg
new file mode 100644
index 0000000..b8cfded
--- /dev/null
+++ b/resources-launcher-35-35/launcher.svg
@@ -0,0 +1,4 @@
+
\ No newline at end of file
diff --git a/resources-launcher-36-36/drawables.xml b/resources-launcher-36-36/drawables.xml
index b9e68f9..44c0b71 100644
--- a/resources-launcher-36-36/drawables.xml
+++ b/resources-launcher-36-36/drawables.xml
@@ -13,5 +13,5 @@
-->
-
+
diff --git a/resources-launcher-36-36/launcher.png b/resources-launcher-36-36/launcher.png
deleted file mode 100644
index f1fbe43..0000000
Binary files a/resources-launcher-36-36/launcher.png and /dev/null differ
diff --git a/resources-launcher-36-36/launcher.svg b/resources-launcher-36-36/launcher.svg
new file mode 100644
index 0000000..e6f1a96
--- /dev/null
+++ b/resources-launcher-36-36/launcher.svg
@@ -0,0 +1,4 @@
+
\ No newline at end of file
diff --git a/resources-launcher-40-40/drawables.xml b/resources-launcher-40-40/drawables.xml
index b9e68f9..44c0b71 100644
--- a/resources-launcher-40-40/drawables.xml
+++ b/resources-launcher-40-40/drawables.xml
@@ -13,5 +13,5 @@
-->
-
+
diff --git a/resources-launcher-40-40/launcher.png b/resources-launcher-40-40/launcher.png
deleted file mode 100644
index 2bfe588..0000000
Binary files a/resources-launcher-40-40/launcher.png and /dev/null differ
diff --git a/resources-launcher-40-40/launcher.svg b/resources-launcher-40-40/launcher.svg
new file mode 100644
index 0000000..e0104c0
--- /dev/null
+++ b/resources-launcher-40-40/launcher.svg
@@ -0,0 +1,4 @@
+
\ No newline at end of file
diff --git a/resources-launcher-54-54/drawables.xml b/resources-launcher-54-54/drawables.xml
index b9e68f9..44c0b71 100644
--- a/resources-launcher-54-54/drawables.xml
+++ b/resources-launcher-54-54/drawables.xml
@@ -13,5 +13,5 @@
-->
-
+
diff --git a/resources-launcher-54-54/launcher.png b/resources-launcher-54-54/launcher.png
deleted file mode 100644
index 76bfe31..0000000
Binary files a/resources-launcher-54-54/launcher.png and /dev/null differ
diff --git a/resources-launcher-54-54/launcher.svg b/resources-launcher-54-54/launcher.svg
new file mode 100644
index 0000000..841014b
--- /dev/null
+++ b/resources-launcher-54-54/launcher.svg
@@ -0,0 +1,4 @@
+
\ No newline at end of file
diff --git a/resources-launcher-60-60/drawables.xml b/resources-launcher-60-60/drawables.xml
index b9e68f9..44c0b71 100644
--- a/resources-launcher-60-60/drawables.xml
+++ b/resources-launcher-60-60/drawables.xml
@@ -13,5 +13,5 @@
-->
-
+
diff --git a/resources-launcher-60-60/launcher.png b/resources-launcher-60-60/launcher.png
deleted file mode 100644
index 3a2d836..0000000
Binary files a/resources-launcher-60-60/launcher.png and /dev/null differ
diff --git a/resources-launcher-60-60/launcher.svg b/resources-launcher-60-60/launcher.svg
new file mode 100644
index 0000000..2322997
--- /dev/null
+++ b/resources-launcher-60-60/launcher.svg
@@ -0,0 +1,4 @@
+
\ No newline at end of file
diff --git a/resources-launcher-61-61/drawables.xml b/resources-launcher-61-61/drawables.xml
index b9e68f9..44c0b71 100644
--- a/resources-launcher-61-61/drawables.xml
+++ b/resources-launcher-61-61/drawables.xml
@@ -13,5 +13,5 @@
-->
-
+
diff --git a/resources-launcher-61-61/launcher.png b/resources-launcher-61-61/launcher.png
deleted file mode 100644
index 4b0ac64..0000000
Binary files a/resources-launcher-61-61/launcher.png and /dev/null differ
diff --git a/resources-launcher-61-61/launcher.svg b/resources-launcher-61-61/launcher.svg
new file mode 100644
index 0000000..c1f5dd8
--- /dev/null
+++ b/resources-launcher-61-61/launcher.svg
@@ -0,0 +1,4 @@
+
\ No newline at end of file
diff --git a/resources-launcher-62-62/drawables.xml b/resources-launcher-62-62/drawables.xml
index b9e68f9..44c0b71 100644
--- a/resources-launcher-62-62/drawables.xml
+++ b/resources-launcher-62-62/drawables.xml
@@ -13,5 +13,5 @@
-->
-
+
diff --git a/resources-launcher-62-62/launcher.png b/resources-launcher-62-62/launcher.png
deleted file mode 100644
index bfd1b08..0000000
Binary files a/resources-launcher-62-62/launcher.png and /dev/null differ
diff --git a/resources-launcher-62-62/launcher.svg b/resources-launcher-62-62/launcher.svg
new file mode 100644
index 0000000..22aac99
--- /dev/null
+++ b/resources-launcher-62-62/launcher.svg
@@ -0,0 +1,4 @@
+
\ No newline at end of file
diff --git a/resources-launcher-65-65/drawables.xml b/resources-launcher-65-65/drawables.xml
index b9e68f9..44c0b71 100644
--- a/resources-launcher-65-65/drawables.xml
+++ b/resources-launcher-65-65/drawables.xml
@@ -13,5 +13,5 @@
-->
-
+
diff --git a/resources-launcher-65-65/launcher.png b/resources-launcher-65-65/launcher.png
deleted file mode 100644
index 16d697f..0000000
Binary files a/resources-launcher-65-65/launcher.png and /dev/null differ
diff --git a/resources-launcher-65-65/launcher.svg b/resources-launcher-65-65/launcher.svg
new file mode 100644
index 0000000..8a9cee9
--- /dev/null
+++ b/resources-launcher-65-65/launcher.svg
@@ -0,0 +1,4 @@
+
\ No newline at end of file
diff --git a/resources-launcher-70-70/drawables.xml b/resources-launcher-70-70/drawables.xml
index b9e68f9..44c0b71 100644
--- a/resources-launcher-70-70/drawables.xml
+++ b/resources-launcher-70-70/drawables.xml
@@ -13,5 +13,5 @@
-->
-
+
diff --git a/resources-launcher-70-70/launcher.png b/resources-launcher-70-70/launcher.png
deleted file mode 100644
index ec89b58..0000000
Binary files a/resources-launcher-70-70/launcher.png and /dev/null differ
diff --git a/resources-launcher-70-70/launcher.svg b/resources-launcher-70-70/launcher.svg
new file mode 100644
index 0000000..cceb497
--- /dev/null
+++ b/resources-launcher-70-70/launcher.svg
@@ -0,0 +1,4 @@
+
diff --git a/resources-launcher-80-80/drawables.xml b/resources-launcher-80-80/drawables.xml
index b9e68f9..44c0b71 100644
--- a/resources-launcher-80-80/drawables.xml
+++ b/resources-launcher-80-80/drawables.xml
@@ -13,5 +13,5 @@
-->
-
+
diff --git a/resources-launcher-80-80/launcher.png b/resources-launcher-80-80/launcher.png
deleted file mode 100644
index 3feefd1..0000000
Binary files a/resources-launcher-80-80/launcher.png and /dev/null differ
diff --git a/resources-launcher-80-80/launcher.svg b/resources-launcher-80-80/launcher.svg
new file mode 100644
index 0000000..11141b8
--- /dev/null
+++ b/resources-launcher-80-80/launcher.svg
@@ -0,0 +1,4 @@
+
\ No newline at end of file
diff --git a/resources-lav/strings/strings.xml b/resources-lav/strings/strings.xml
index 4b5088b..4409f8c 100644
--- a/resources-lav/strings/strings.xml
+++ b/resources-lav/strings/strings.xml
@@ -43,13 +43,20 @@
Nav konfigurētsIzvēlne
+ Izvēlieties...API atslēga Home Assistant.Ilgmūžīgs piekļuves marķieris.HomeAssistant API URL.URL izvēlnes konfigurācijai (JSON).Taimauts sekundēs. Pēc šī neaktivitātes perioda izejiet no lietojumprogrammas, lai taupītu ierīces akumulatoru.Pēc šī laika (sekundēs) tiek automātiski aizvērts darbības apstiprinājuma dialoglodziņš un darbība tiek atcelta. Iestatiet uz 0, lai atspējotu taimautu.
- Apzīmē veidus ar ikonām (izslēgts) vai ar etiķetēm (ieslēgts).
- Kreisā (izslēgta) vai labā (ieslēgta) izvēlnes līdzināšana.
+ Izvēlnes vienuma stils.
+ Ikonas
+ Papildu teksts
+ Kreisā (izslēgta) vai labā (ieslēgta) izvēlnes izlī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 ab3a3e2..e74d56b 100644
--- a/resources-lit/strings/strings.xml
+++ b/resources-lit/strings/strings.xml
@@ -37,19 +37,26 @@
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 „/“
- Yra
+ GalimaTikrinama...NepasiekiamasNesukonfigūruotasMeniu
- API raktas, skirtas HomeAssistant.
+ Pasirinkite...
+ API raktas, skirtas „HomeAssistant“.Ilgalaikis prieigos raktas.„HomeAssistant“ API URL.Meniu konfigūravimo URL (JSON).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ą.
- Tipai su piktogramomis (išjungta) arba etiketėmis (įjungta).
+ Meniu elemento stilius.
+ Piktogramos
+ Papildomas tekstasKairysis (išjungtas) arba dešinysis (įjungtas) meniu lygiavimas.
- (Tik valdiklis) Automatiškai paleiskite programą iš valdiklio, nelaukdami palietimo.
+ Iš kairės į dešinę
+ Iš dešinės į kairę
+ (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 044215f..871526f 100644
--- a/resources-nob/strings/strings.xml
+++ b/resources-nob/strings/strings.xml
@@ -43,13 +43,20 @@
UkonfigurertMeny
+ Plukke ut...API-nøkkel for HomeAssistant.Langlevd tilgangstoken.URL for HomeAssistant API.URL for menykonfigurasjon (JSON).Tidsavbrudd i sekunder. Avslutt applikasjonen etter denne perioden med inaktivitet for å spare enhetens batteri.Etter denne tiden (i sekunder), lukkes en bekreftelsesdialog for en handling automatisk og handlingen avbrytes. Sett til 0 for å deaktivere tidsavbruddet.
- Representerer typer med ikoner (av) eller med etiketter (på).
+ Menyelementstil.
+ Ikoner
+ Ekstra tekstVenstre (av) eller Høyre (på) Menyjustering.
+ Venstre til høyre
+ Høyre til venstre(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 adf1b27..38066f3 100644
--- a/resources-pol/strings/strings.xml
+++ b/resources-pol/strings/strings.xml
@@ -43,13 +43,20 @@
NieskonfigurowaneMenu
+ Wybierać...Klucz API dla HomeAssistant.Długowieczny token dostępu.Adres URL interfejsu API HomeAssistant.Adres URL konfiguracji menu (JSON).Limit czasu w sekundach. Wyjdź z aplikacji po tym okresie bezczynności, aby oszczędzać baterię urządzenia.Po tym czasie (w sekundach) okno dialogowe z potwierdzeniem akcji zamyka się automatycznie, a akcja zostaje anulowana. Ustaw na 0, aby wyłączyć limit czasu.
- Reprezentowanie typów za pomocą ikon (wyłączone) lub etykiet (włączone).
+ Styl pozycji menu.
+ Ikony
+ Dodatkowy tekstWyrównanie menu do lewej (wyłączone) lub do prawej (włączone).
+ Od lewej do prawej
+ Od prawej do lewej(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 620fc13..6ac7b7a 100644
--- a/resources-por/strings/strings.xml
+++ b/resources-por/strings/strings.xml
@@ -43,13 +43,20 @@
Não configuradoCardápio
+ Selecione...Chave de API para HomeAssistant.Token de acesso de longa duração.URL para API HomeAssistant.URL para configuração do menu (JSON).Tempo limite em segundos. Saia do aplicativo após esse período de inatividade para economizar bateria do aparelho.Após esse tempo (em segundos), uma caixa de diálogo de confirmação de uma ação é automaticamente fechada e a ação é cancelada. Defina como 0 para desativar o tempo limite.
- Representando tipos com ícones (desligado) ou com rótulos (ligado).
+ Estilo do item de menu.
+ Ícones
+ Texto AdicionalAlinhamento do menu à esquerda (desligado) ou à direita (ligado).
+ Da esquerda para direita
+ Direita para esquerda(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 2327d7f..0e9ff57 100644
--- a/resources-ron/strings/strings.xml
+++ b/resources-ron/strings/strings.xml
@@ -43,13 +43,20 @@
NeconfiguratMeniul
+ Selectați...Cheie API pentru HomeAssistant.Token de acces cu viață lungă.Adresa URL pentru API-ul HomeAssistant.URL pentru configurarea meniului (JSON).Timeout în secunde. Ieșiți din aplicație după această perioadă de inactivitate pentru a economisi bateria dispozitivului.După acest timp (în secunde), un dialog de confirmare pentru o acțiune este închis automat și acțiunea este anulată. Setați la 0 pentru a dezactiva timeout-ul.
- Reprezentarea tipurilor cu pictograme (dezactivate) sau cu etichete (activate).
+ Stilul elementului de meniu.
+ Pictograme
+ Text suplimentarAlinierea meniului la stânga (dezactivată) sau la dreapta (activată).
+ De la stânga la dreapta
+ De la dreapta la stanga(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 4e2c3f0..6042314 100644
--- a/resources-slo/strings/strings.xml
+++ b/resources-slo/strings/strings.xml
@@ -43,13 +43,20 @@
NekonfigurovanéPonuka
+ Vybrať...Kľúč API pre HomeAssistant.
- Prístupový token s dlhou životnosťou.
+ Dlhotrvajúci prístupový token.URL pre HomeAssistant API.Webová adresa pre konfiguráciu ponuky (JSON).Časový limit v sekundách. Po tejto dobe nečinnosti ukončite aplikáciu, aby ste šetrili batériu zariadenia.Po tomto čase (v sekundách) sa dialógové okno s potvrdením akcie automaticky zatvorí a akcia sa zruší. Ak chcete časový limit deaktivovať, nastavte na 0.
- Typy predstavujú ikony (vypnuté) alebo štítky (zapnuté).
+ Štýl položky menu.
+ ikony
+ Doplnkový textZarovnanie ponuky vľavo (vypnuté) alebo vpravo (zapnuté).
+ Zľava doprava
+ Zprava doľava(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 512dc90..f757138 100644
--- a/resources-slv/strings/strings.xml
+++ b/resources-slv/strings/strings.xml
@@ -43,13 +43,20 @@
Nekonfiguriranomeni
+ Izberite ...API ključ za HomeAssistant.Dolgoživ dostopni žeton.URL za HomeAssistant API.URL za konfiguracijo menija (JSON).Časovna omejitev v sekundah. Po tem obdobju nedejavnosti zaprite aplikacijo, da prihranite baterijo naprave.Po tem času (v sekundah) se potrditveno pogovorno okno za dejanje samodejno zapre in dejanje je preklicano. Nastavite na 0, da onemogočite časovno omejitev.
- Predstavljanje tipov z ikonami (izklopljeno) ali z oznakami (vklopljeno).
+ Slog elementa menija.
+ Ikone
+ Dodatno besediloLeva (izklopljena) ali desna (vklopljena) poravnava menija.
+ Od leve proti desni
+ Od desne proti levi(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 5961adb..18ae970 100644
--- a/resources-spa/strings/strings.xml
+++ b/resources-spa/strings/strings.xml
@@ -43,13 +43,20 @@
DesconfiguradoMenú
+ Seleccionar...Clave API para HomeAssistant.Token de acceso de larga duración.URL para la API de HomeAssistant.URL para configuración del menú (JSON).Tiempo de espera en segundos. Salga de la aplicación después de este período de inactividad para ahorrar batería del dispositivo.Después de este tiempo (en segundos), se cierra automáticamente un cuadro de diálogo de confirmación de una acción y se cancela la acción. Establezca en 0 para desactivar el tiempo de espera.
- Representando tipos con iconos (apagados) o con etiquetas (encendido).
+ Estilo de elemento de menú.
+ Iconos
+ Texto adicionalAlineación del menú izquierda (desactivada) o derecha (activada).
+ De izquierda a derecha
+ De derecha a izquierda(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 f5eb436..bd6466f 100644
--- a/resources-swe/strings/strings.xml
+++ b/resources-swe/strings/strings.xml
@@ -29,7 +29,7 @@
Ingen internetanslutningInget svar, kontrollera internetanslutningenIngen API-nyckel i applikationsinställningarna
- Ingen API-URL i applikationsinställningarna
+ Ingen API-URL i programinställningarnaIngen konfigurations-URL i programinställningarnaAPI-anrop för snabba. Vänligen sakta ner dina förfrågningar.Webbadressen hittades inte. Potentiellt API-URL-fel i inställningarna.
@@ -43,13 +43,20 @@
OkonfigureradMeny
+ Välj...API-nyckel för HomeAssistant.Långlivad åtkomsttoken.URL för HomeAssistant API.URL för menykonfiguration (JSON).
- Timeout i sekunder. Avsluta programmet efter denna period av inaktivitet för att spara enhetens batteri.
+ Timeout på 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.
- Representerar typer med ikoner (av) eller med etiketter (på).
+ Menyalternativ stil.
+ Ikoner
+ Ytterligare textVänster (av) eller höger (på) menyjustering.
+ Vänster till höger
+ Höger till vänster(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 7ebd76a..4cbaa49 100644
--- a/resources-tha/strings/strings.xml
+++ b/resources-tha/strings/strings.xml
@@ -43,13 +43,20 @@
ไม่ได้กำหนดค่าเมนู
+ เลือก...คีย์ API สำหรับ HomeAssistantโทเค็นการเข้าถึงที่มีอายุการใช้งานยาวนานURL สำหรับ HomeAssistant APIURL สำหรับการกำหนดค่าเมนู (JSON)หมดเวลาเป็นวินาที ออกจากแอปพลิเคชันหลังจากไม่มีการใช้งานเป็นระยะเวลาหนึ่งเพื่อประหยัดแบตเตอรี่ของอุปกรณ์หลังจากเวลานี้ (เป็นวินาที) กล่องโต้ตอบการยืนยันสำหรับการดำเนินการจะปิดโดยอัตโนมัติและการดำเนินการจะถูกยกเลิก ตั้งค่าเป็น 0 เพื่อปิดใช้งานการหมดเวลา
- เป็นตัวแทนประเภทด้วยไอคอน (ปิด) หรือมีป้ายกำกับ (เปิด)
+ รูปแบบรายการเมนู
+ ไอคอน
+ ข้อความเพิ่มเติมการจัดตำแหน่งเมนูซ้าย (ปิด) หรือขวา (เปิด)
+ จากซ้ายไปขวา
+ จากขวาไปซ้าย(วิดเจ็ตเท่านั้น) เริ่มแอปพลิเคชันโดยอัตโนมัติจากวิดเจ็ตโดยไม่ต้องรอการแตะ
+ เปิดใช้บริการพื้นหลังเพื่อส่งระดับแบตเตอรี่นาฬิกาไปยัง Home Assistant
+ อัตรารีเฟรช (เป็นนาที) ที่บริการพื้นหลังควรส่งระดับแบตเตอรี่ซ้ำ
\ No newline at end of file
diff --git a/resources-tur/strings/strings.xml b/resources-tur/strings/strings.xml
index 379ec54..63fac54 100644
--- a/resources-tur/strings/strings.xml
+++ b/resources-tur/strings/strings.xml
@@ -36,20 +36,27 @@
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ırMevcutKontrol etme...Kullanım dışıYapılandırılmamışMenü
+ Seçme...HomeAssistant için API Anahtarı.Uzun Ömürlü Erişim Jetonu.HomeAssistant API'sinin URL'si.Menü yapılandırmasının URL'si (JSON).Saniye cinsinden zaman aşımı. Cihazın pilinden tasarruf etmek için bu süre boyunca işlem yapılmadığında uygulamadan çıkın.
- Bu sürenin sonunda (saniye cinsinden), bir eyleme ilişkin onay iletişim kutusu otomatik olarak kapatılır ve eylem iptal edilir. Zaman aşımını devre dışı bırakmak için 0'a ayarlayın.
- Türleri simgelerle (kapalı) veya etiketlerle (açık) temsil etme.
+ Bu sürenin sonunda (saniye olarak), bir eyleme ilişkin onay iletişim kutusu otomatik olarak kapatılır ve eylem iptal edilir. Zaman aşımını devre dışı bırakmak için 0'a ayarlayın.
+ Menü öğesi stili.
+ Simgeler
+ Ek MetinSol (kapalı) veya Sağ (açık) Menü Hizalaması.
+ Soldan sağa
+ Sağdan sola(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 fe951b2..c3d948d 100644
--- a/resources-ukr/strings/strings.xml
+++ b/resources-ukr/strings/strings.xml
@@ -15,7 +15,7 @@
@@ -43,13 +43,20 @@
НеналаштованийМеню
+ Виберіть...Ключ API для HomeAssistant.Довговічний маркер доступу.URL для HomeAssistant API.
- URL-адреса для налаштування меню (JSON).
+ URL для налаштування меню (JSON).Час очікування в секундах. Вийдіть із програми після цього періоду бездіяльності, щоб заощадити батарею пристрою.Після закінчення цього часу (у секундах) діалогове вікно підтвердження дії автоматично закривається, а дія скасовується. Встановіть 0, щоб вимкнути тайм-аут.
- Представлення типів піктограмами (вимкнено) або мітками (увімкнено).
+ Стиль пункту меню.
+ іконки
+ Додатковий текстЛіворуч (вимкнено) або праворуч (увімкнено) вирівнювання меню.
+ Зліва направо
+ Справа наліво(Лише віджет) Автоматично запускайте програму з віджета, не чекаючи дотику.
+ Увімкніть фонову службу, щоб надсилати інформацію про рівень заряду акумулятора годинника до Home Assistant.
+ Частота оновлення (у хвилинах), з якою фонова служба має повторно надсилати рівень заряду акумулятора.
\ No newline at end of file
diff --git a/resources-vie/strings/strings.xml b/resources-vie/strings/strings.xml
index ca576fa..99cdd48 100644
--- a/resources-vie/strings/strings.xml
+++ b/resources-vie/strings/strings.xml
@@ -43,13 +43,20 @@
Chưa được định cấu hìnhThực đơn
+ Lựa chọn...Khóa API cho HomeAssistant.Mã thông báo truy cập tồn tại lâu dài.URL cho API HomeAssistant.URL cho cấu hình menu (JSON).Thời gian chờ tính bằng giây. Thoát khỏi ứng dụng sau khoảng thời gian không hoạt động này để tiết kiệm pin cho thiết bị.
- Sau thời gian này (tính bằng giây), hộp thoại xác nhận cho một hành động sẽ tự động đóng và hành động đó sẽ bị hủy. Đặt thành 0 để tắt thời gian chờ.
- Biểu diễn các loại bằng biểu tượng (tắt) hoặc bằng nhãn (bật).
+ Sau thời gian này (tính bằng giây), hộp thoại xác nhận cho một hành động sẽ tự động đóng lại và hành động đó sẽ bị hủy. Đặt thành 0 để tắt thời gian chờ.
+ Phong cách mục menu.
+ Biểu tượng
+ Văn bản bổ sungCăn chỉnh menu Trái (tắt) hoặc Phải (bật).
+ Trái sang phải
+ Phải sang trái(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 72928d5..4b5c996 100644
--- a/resources-zhs/strings/strings.xml
+++ b/resources-zhs/strings/strings.xml
@@ -43,13 +43,20 @@
未配置菜单
+ 选择...HomeAssistant 的 API 密钥。长期访问令牌。HomeAssistant API 的 URL。菜单配置的 URL (JSON)。超时(以秒为单位)。闲置一段时间后退出应用程序以节省设备电池。在此时间(以秒为单位)之后,操作的确认对话框将自动关闭并取消该操作。设置为 0 以禁用超时。
- 用图标(关闭)或标签(打开)表示类型。
+ 菜单项样式。
+ 图标
+ 附加文本左(关)或右(开)菜单对齐。
+ 左到右
+ 右到左(仅限小部件)从小部件自动启动应用程序,无需等待点击。
+ 启用后台服务将时钟电池电量发送到 Home Assistant。
+ 后台服务应重复发送电池电量的刷新率(以分钟为单位)。
\ No newline at end of file
diff --git a/resources-zht/strings/strings.xml b/resources-zht/strings/strings.xml
index 3196f55..2ca5a39 100644
--- a/resources-zht/strings/strings.xml
+++ b/resources-zht/strings/strings.xml
@@ -43,13 +43,20 @@
未配置選單
+ 選擇...HomeAssistant 的 API 金鑰。長期訪問令牌。HomeAssistant API 的 URL。選單配置的 URL (JSON)。超時(以秒為單位)。閒置一段時間後退出應用程式以節省設備電池。在此時間(以秒為單位)之後,操作的確認對話方塊將自動關閉並取消該操作。設定為 0 以停用逾時。
- 用圖示(關閉)或標籤(開啟)表示類型。
+ 選單項目樣式。
+ 圖示
+ 附加文字左(關)或右(開)選單對齊。
+ 左至右
+ 右到左(僅限小部件)從小部件自動啟動應用程序,無需等待點擊。
+ 啟用後台服務將時鐘電池電量傳送到 Home Assistant。
+ 後台服務應重複發送電池電量的更新率(以分鐘為單位)。
\ No newline at end of file
diff --git a/resources-zsm/strings/strings.xml b/resources-zsm/strings/strings.xml
index d5d5c20..0afa9c0 100644
--- a/resources-zsm/strings/strings.xml
+++ b/resources-zsm/strings/strings.xml
@@ -43,13 +43,20 @@
Tidak dikonfigurasikanMenu
+ Pilih...Kunci API untuk HomeAssistant.Token Akses Berumur Panjang.URL untuk API HomeAssistant.URL untuk konfigurasi menu (JSON).Tamat masa dalam beberapa saat. Keluar dari aplikasi selepas tempoh tidak aktif ini untuk menjimatkan bateri peranti.Selepas masa ini (dalam beberapa saat), dialog pengesahan untuk tindakan ditutup secara automatik dan tindakan itu dibatalkan. Tetapkan kepada 0 untuk melumpuhkan tamat masa.
- Mewakili jenis dengan ikon (dimatikan) atau dengan label (dihidupkan).
+ Gaya item menu.
+ ikon
+ Teks TambahanPenjajaran Menu Kiri (mati) atau Kanan (hidup).
+ Kiri ke kanan
+ Kanan ke kiri(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/drawables/launcher.png b/resources/drawables/launcher.png
deleted file mode 100644
index 2d74c0f..0000000
Binary files a/resources/drawables/launcher.png and /dev/null differ
diff --git a/resources/settings/properties.xml b/resources/settings/properties.xml
index 03fd708..2f928a2 100644
--- a/resources/settings/properties.xml
+++ b/resources/settings/properties.xml
@@ -31,20 +31,20 @@
03
-
+ 0
-
+ 1
-
+ false
+
+
+ false
+
+
+ 15
diff --git a/resources/settings/settings.xml b/resources/settings/settings.xml
index 22aab55..59e55c5 100644
--- a/resources/settings/settings.xml
+++ b/resources/settings/settings.xml
@@ -18,9 +18,7 @@
title="@Strings.SettingsApiKey"
prompt="@Strings.SettingsApiKeyPrompt"
>
-
+
-
+
-
+
-
+
-
+
-
+
+ @Strings.SettingsMenuItemStyleIcons
+ @Strings.SettingsMenuItemStyleText
+
-
+
+ @Strings.LeftToRight
+ @Strings.RightToLeft
+
-
+
+
+
+
+
+
+
+
+
diff --git a/resources/strings/strings.xml b/resources/strings/strings.xml
index b93f732..11c8e6b 100644
--- a/resources/strings/strings.xml
+++ b/resources/strings/strings.xml
@@ -38,13 +38,20 @@
Menu
+ Select...API Key for HomeAssistant.Long-Lived Access Token.URL for HomeAssistant API.URL for menu configuration (JSON).Timeout in seconds. Exit the application after this period of inactivity to save the device battery.After this time (in seconds), a confirmation dialog for an action is automatically closed and the action is cancelled. Set to 0 to disable the timeout.
- Representing types with icons (off) or with labels (on).
+ Menu item style.
+ Icons
+ Additional TextLeft (off) or Right (on) Menu Alignment.
+ Left to right
+ Right to Left(Widget only) Automatically start the application from the widget without waiting for a tap.
+ Enable the background service to send the clock battery level to Home Assistant.
+ The refresh rate (in minutes) at which the background service should repeat sending the battery level.
diff --git a/source/BackgroundServiceDelegate.mc b/source/BackgroundServiceDelegate.mc
new file mode 100644
index 0000000..e398065
--- /dev/null
+++ b/source/BackgroundServiceDelegate.mc
@@ -0,0 +1,73 @@
+//-----------------------------------------------------------------------------------
+//
+// Distributed under MIT Licence
+// See https://github.com/house-of-abbey/GarminHomeAssistant/blob/main/LICENSE.
+//
+//-----------------------------------------------------------------------------------
+//
+// GarminHomeAssistant is a Garmin IQ application written in Monkey C and routinely
+// tested on a Venu 2 device. The source code is provided at:
+// https://github.com/house-of-abbey/GarminHomeAssistant.
+//
+// P A Abbey & J D Abbey & Someone0nEarth, 31 October 2023
+//
+//
+// Description:
+//
+// The background service delegate currently just reports the Garmin watch's battery
+// level.
+//
+//-----------------------------------------------------------------------------------
+
+using Toybox.Lang;
+using Toybox.Application.Properties;
+using Toybox.Background;
+using Toybox.System;
+
+(:background)
+class BackgroundServiceDelegate extends System.ServiceDelegate {
+
+ function initialize() {
+ ServiceDelegate.initialize();
+ }
+
+ function onReturnBatteryUpdate(responseCode as Lang.Number, data as Null or Lang.Dictionary or Lang.String) as Void {
+ if (Globals.scDebug) {
+ System.println("BackgroundServiceDelegate onReturnBatteryUpdate() Response Code: " + responseCode);
+ System.println("BackgroundServiceDelegate onReturnBatteryUpdate() Response Data: " + data);
+ }
+ Background.exit(null);
+ }
+
+ function onTemporalEvent() as Void {
+ if (! System.getDeviceSettings().phoneConnected) {
+ if (Globals.scDebug) {
+ System.println("BackgroundServiceDelegate onTemporalEvent(): No Phone connection, skipping API call.");
+ }
+ } else if (! System.getDeviceSettings().connectionAvailable) {
+ if (Globals.scDebug) {
+ System.println("BackgroundServiceDelegate onTemporalEvent(): No Internet connection, skipping API call.");
+ }
+ } 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",
+ {
+ "level" => System.getSystemStats().battery,
+ "is_charging" => System.getSystemStats().charging,
+ "device_id" => System.getDeviceSettings().uniqueIdentifier
+ },
+ {
+ :method => Communications.HTTP_REQUEST_METHOD_POST,
+ :headers => {
+ "Content-Type" => Communications.REQUEST_CONTENT_TYPE_JSON,
+ "Authorization" => "Bearer " + (Properties.getValue("api_key") as Lang.String)
+ },
+ :responseType => Communications.HTTP_RESPONSE_CONTENT_TYPE_JSON
+ },
+ method(:onReturnBatteryUpdate)
+ );
+ }
+ }
+
+}
diff --git a/source/ClientId.mc.unpopulated b/source/ClientId.mc.unpopulated
new file mode 100644
index 0000000..236b902
--- /dev/null
+++ b/source/ClientId.mc.unpopulated
@@ -0,0 +1,27 @@
+//-----------------------------------------------------------------------------------
+//
+// Distributed under MIT Licence
+// See https://github.com/house-of-abbey/GarminHomeAssistant/blob/main/LICENSE.
+//
+//-----------------------------------------------------------------------------------
+//
+// GarminHomeAssistant is a Garmin IQ application written in Monkey C and routinely
+// tested on a Venu 2 device. The source code is provided at:
+// https://github.com/house-of-abbey/GarminHomeAssistant.
+//
+// J D Abbey & P A Abbey, 28 December 2022
+//
+//
+// Description:
+//
+// ClientId is somewhere to store personal credentials that should not be shared in
+// a separate file that is locally customised to the source code and not commited
+// back to GitHub.
+//
+//-----------------------------------------------------------------------------------
+
+(:glance)
+class ClientId {
+ static const webLogUrl = "https://...";
+ static const webLogClearUrl = "https://..._clear.php";
+}
diff --git a/source/Globals.mc b/source/Globals.mc
index 6089b16..8fbf034 100644
--- a/source/Globals.mc
+++ b/source/Globals.mc
@@ -20,6 +20,7 @@
using Toybox.Lang;
+(:glance)
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!)
diff --git a/source/HomeAssistantApp.mc b/source/HomeAssistantApp.mc
index 13169d1..23a5385 100644
--- a/source/HomeAssistantApp.mc
+++ b/source/HomeAssistantApp.mc
@@ -21,40 +21,24 @@
using Toybox.Application;
using Toybox.Lang;
using Toybox.WatchUi;
+using Toybox.System;
using Toybox.Application.Properties;
using Toybox.Timer;
+(:glance, :background)
class HomeAssistantApp extends Application.AppBase {
- private var strNoApiKey as Lang.String or Null;
- private var strNoApiUrl as Lang.String or Null;
- private var strNoConfigUrl as Lang.String or Null;
- private var strNoPhone as Lang.String or Null;
- private var strNoInternet as Lang.String or Null;
- private var strNoResponse as Lang.String or Null;
- private var strApiFlood as Lang.String or Null;
- private var strConfigUrlNotFound as Lang.String or Null;
- private var strNoJson as Lang.String or Null;
- private var strUnhandledHttpErr as Lang.String or Null;
- private var strTrailingSlashErr as Lang.String or Null;
- private var strAvailable = WatchUi.loadResource($.Rez.Strings.Available);
- private var strUnavailable = WatchUi.loadResource($.Rez.Strings.Unavailable);
- private var strUnconfigured = WatchUi.loadResource($.Rez.Strings.Unconfigured);
-
- private var mApiKey as Lang.String or Null; // The compiler can't tell these are updated by
- private var mApiUrl as Lang.String or Null; // initialize(), hence the "or Null".
- private var mConfigUrl as Lang.String or Null; //
- private var mApiStatus as Lang.String = WatchUi.loadResource($.Rez.Strings.Checking);
- private var mMenuStatus as Lang.String = WatchUi.loadResource($.Rez.Strings.Checking);
+ private var mApiStatus as Lang.String or Null;
+ private var mMenuStatus as Lang.String or Null;
private var mHaMenu as HomeAssistantView or Null;
private var mQuitTimer as QuitTimer or Null;
private var mTimer as Timer.Timer or Null;
- private var mItemsToUpdate; // Array initialised by onReturnFetchMenuConfig()
- private var mNextItemToUpdate = 0; // Index into the above array
+ private var mItemsToUpdate as Lang.Array or Null; // Array initialised by onReturnFetchMenuConfig()
+ private var mNextItemToUpdate as Lang.Number = 0; // Index into the above array
private var mIsGlance as Lang.Boolean = false;
+ private var mIsApp as Lang.Boolean = false; // Or Widget
function initialize() {
AppBase.initialize();
- onSettingsChanged();
// ATTENTION when adding stuff into this block:
// Because of the >>GlanceView<<, it should contain only
// code, which is used as well for the glance:
@@ -102,49 +86,43 @@ class HomeAssistantApp extends Application.AppBase {
// Return the initial view of your application here
function getInitialView() as Lang.Array? {
- strNoApiKey = WatchUi.loadResource($.Rez.Strings.NoAPIKey);
- strNoApiUrl = WatchUi.loadResource($.Rez.Strings.NoApiUrl);
- strNoConfigUrl = WatchUi.loadResource($.Rez.Strings.NoConfigUrl);
- strNoPhone = WatchUi.loadResource($.Rez.Strings.NoPhone);
- strNoInternet = WatchUi.loadResource($.Rez.Strings.NoInternet);
- strNoResponse = WatchUi.loadResource($.Rez.Strings.NoResponse);
- strApiFlood = WatchUi.loadResource($.Rez.Strings.ApiFlood);
- strConfigUrlNotFound = WatchUi.loadResource($.Rez.Strings.ConfigUrlNotFound);
- strNoJson = WatchUi.loadResource($.Rez.Strings.NoJson);
- strUnhandledHttpErr = WatchUi.loadResource($.Rez.Strings.UnhandledHttpErr);
- strTrailingSlashErr = WatchUi.loadResource($.Rez.Strings.TrailingSlashErr);
+ mIsApp = true;
mQuitTimer = new QuitTimer();
+ RezStrings.update();
+ mApiStatus = RezStrings.getChecking();
+ mMenuStatus = RezStrings.getChecking();
+ Settings.update();
- if (mApiKey.length() == 0) {
+ if (Settings.getApiKey().length() == 0) {
if (Globals.scDebug) {
- System.println("HomeAssistantApp getInitialView(): No API key in the application settings.");
+ System.println("HomeAssistantApp getInitialView(): No API key in the application Settings.");
}
- return ErrorView.create(strNoApiKey + ".");
- } else if (mApiUrl.length() == 0) {
+ return ErrorView.create(RezStrings.getNoApiKey() + ".");
+ } else if (Settings.getApiUrl().length() == 0) {
if (Globals.scDebug) {
- System.println("HomeAssistantApp getInitialView(): No API URL in the application settings.");
+ System.println("HomeAssistantApp getInitialView(): No API URL in the application Settings.");
}
- return ErrorView.create(strNoApiUrl + ".");
- } else if (mApiUrl.substring(-1, mApiUrl.length()).equals("/")) {
+ return ErrorView.create(RezStrings.getNoApiUrl() + ".");
+ } else if (Settings.getApiUrl().substring(-1, Settings.getApiUrl().length()).equals("/")) {
if (Globals.scDebug) {
System.println("HomeAssistantApp getInitialView(): API URL must not have a trailing slash '/'.");
}
- return ErrorView.create(strTrailingSlashErr + ".");
- } else if (mConfigUrl.length() == 0) {
+ return ErrorView.create(RezStrings.getTrailingSlashErr() + ".");
+ } else if (Settings.getConfigUrl().length() == 0) {
if (Globals.scDebug) {
System.println("HomeAssistantApp getInitialView(): No configuration URL in the application settings.");
}
- return ErrorView.create(strNoConfigUrl + ".");
+ return ErrorView.create(RezStrings.getNoConfigUrl() + ".");
} else if (! System.getDeviceSettings().phoneConnected) {
if (Globals.scDebug) {
System.println("HomeAssistantApp fetchMenuConfig(): No Phone connection, skipping API call.");
}
- return ErrorView.create(strNoPhone + ".");
+ return ErrorView.create(RezStrings.getNoPhone() + ".");
} else if (! System.getDeviceSettings().connectionAvailable) {
if (Globals.scDebug) {
System.println("HomeAssistantApp fetchMenuConfig(): No Internet connection, skipping API call.");
}
- return ErrorView.create(strNoInternet + ".");
+ return ErrorView.create(RezStrings.getNoInternet() + ".");
} else {
fetchMenuConfig();
fetchApiStatus();
@@ -165,7 +143,7 @@ class HomeAssistantApp extends Application.AppBase {
System.println("HomeAssistantApp onReturnFetchMenuConfig() Response Data: " + data);
}
- mMenuStatus = strUnavailable;
+ mMenuStatus = RezStrings.getUnavailable();
switch (responseCode) {
case Communications.BLE_HOST_TIMEOUT:
case Communications.BLE_CONNECTION_UNAVAILABLE:
@@ -173,7 +151,7 @@ class HomeAssistantApp extends Application.AppBase {
System.println("HomeAssistantApp onReturnFetchMenuConfig() Response Code: BLE_HOST_TIMEOUT or BLE_CONNECTION_UNAVAILABLE, Bluetooth connection severed.");
}
if (!mIsGlance) {
- ErrorView.show(strNoPhone + ".");
+ ErrorView.show(RezStrings.getNoPhone() + ".");
}
break;
@@ -182,7 +160,7 @@ class HomeAssistantApp extends Application.AppBase {
System.println("HomeAssistantApp onReturnFetchMenuConfig() Response Code: BLE_QUEUE_FULL, API calls too rapid.");
}
if (!mIsGlance) {
- ErrorView.show(strApiFlood);
+ ErrorView.show(RezStrings.getApiFlood());
}
break;
@@ -191,7 +169,7 @@ class HomeAssistantApp extends Application.AppBase {
System.println("HomeAssistantApp onReturnFetchMenuConfig() Response Code: NETWORK_REQUEST_TIMED_OUT, check Internet connection.");
}
if (!mIsGlance) {
- ErrorView.show(strNoResponse);
+ ErrorView.show(RezStrings.getNoResponse());
}
break;
@@ -200,7 +178,7 @@ class HomeAssistantApp extends Application.AppBase {
System.println("HomeAssistantApp onReturnFetchMenuConfig() Response Code: INVALID_HTTP_BODY_IN_NETWORK_RESPONSE, check JSON is returned.");
}
if (!mIsGlance) {
- ErrorView.show(strNoJson);
+ ErrorView.show(RezStrings.getNoJson());
}
break;
@@ -209,16 +187,16 @@ class HomeAssistantApp extends Application.AppBase {
System.println("HomeAssistantApp onReturnFetchMenuConfig() Response Code: 404, page not found. Check Configuration URL setting.");
}
if (!mIsGlance) {
- ErrorView.show(strConfigUrlNotFound);
+ ErrorView.show(RezStrings.getConfigUrlNotFound());
}
break;
case 200:
- mMenuStatus = strAvailable;
+ mMenuStatus = RezStrings.getAvailable();
if (!mIsGlance) {
mHaMenu = new HomeAssistantView(data, null);
mQuitTimer.begin();
- if (Properties.getValue("widget_start_no_tap")) {
+ if (Settings.getIsWidgetStartNoTap()) {
// As soon as the menu has been fetched start show the menu of items.
// This behaviour is inconsistent with the standard Garmin User Interface, but has been
// requested by users so has been made the non-default option.
@@ -241,7 +219,7 @@ class HomeAssistantApp extends Application.AppBase {
System.println("HomeAssistantApp onReturnFetchMenuConfig(): Unhandled HTTP response code = " + responseCode);
}
if (!mIsGlance) {
- ErrorView.show(strUnhandledHttpErr + responseCode);
+ ErrorView.show(RezStrings.getUnhandledHttpErr() + responseCode);
}
break;
}
@@ -250,14 +228,10 @@ class HomeAssistantApp extends Application.AppBase {
(:glance)
function fetchMenuConfig() as Void {
- if (mConfigUrl.equals("")) {
- mMenuStatus = strUnconfigured;
+ if (Settings.getConfigUrl().equals("")) {
+ mMenuStatus = RezStrings.getUnconfigured();
WatchUi.requestUpdate();
} else {
- var options = {
- :method => Communications.HTTP_REQUEST_METHOD_GET,
- :responseType => Communications.HTTP_RESPONSE_CONTENT_TYPE_JSON
- };
if (! System.getDeviceSettings().phoneConnected) {
if (Globals.scDebug) {
System.println("HomeAssistantToggleMenuItem getState(): No Phone connection, skipping API call.");
@@ -265,9 +239,9 @@ class HomeAssistantApp extends Application.AppBase {
if (mIsGlance) {
WatchUi.requestUpdate();
} else {
- ErrorView.show(strNoPhone + ".");
+ ErrorView.show(RezStrings.getNoPhone() + ".");
}
- mMenuStatus = strUnavailable;
+ mMenuStatus = RezStrings.getUnavailable();
} else if (! System.getDeviceSettings().connectionAvailable) {
if (Globals.scDebug) {
System.println("HomeAssistantToggleMenuItem getState(): No Internet connection, skipping API call.");
@@ -275,14 +249,17 @@ class HomeAssistantApp extends Application.AppBase {
if (mIsGlance) {
WatchUi.requestUpdate();
} else {
- ErrorView.show(strNoInternet + ".");
+ ErrorView.show(RezStrings.getNoInternet() + ".");
}
- mMenuStatus = strUnavailable;
+ mMenuStatus = RezStrings.getUnavailable();
} else {
Communications.makeWebRequest(
- mConfigUrl,
+ Settings.getConfigUrl(),
null,
- options,
+ {
+ :method => Communications.HTTP_REQUEST_METHOD_GET,
+ :responseType => Communications.HTTP_RESPONSE_CONTENT_TYPE_JSON
+ },
method(:onReturnFetchMenuConfig)
);
}
@@ -298,7 +275,7 @@ class HomeAssistantApp extends Application.AppBase {
System.println("HomeAssistantApp onReturnFetchApiStatus() Response Data: " + data);
}
- mApiStatus = strUnavailable;
+ mApiStatus = RezStrings.getUnavailable();
switch (responseCode) {
case Communications.BLE_HOST_TIMEOUT:
case Communications.BLE_CONNECTION_UNAVAILABLE:
@@ -306,7 +283,7 @@ class HomeAssistantApp extends Application.AppBase {
System.println("HomeAssistantApp onReturnFetchApiStatus() Response Code: BLE_HOST_TIMEOUT or BLE_CONNECTION_UNAVAILABLE, Bluetooth connection severed.");
}
if (!mIsGlance) {
- ErrorView.show(strNoPhone + ".");
+ ErrorView.show(RezStrings.getNoPhone() + ".");
}
break;
@@ -315,7 +292,7 @@ class HomeAssistantApp extends Application.AppBase {
System.println("HomeAssistantApp onReturnFetchApiStatus() Response Code: BLE_QUEUE_FULL, API calls too rapid.");
}
if (!mIsGlance) {
- ErrorView.show(strApiFlood);
+ ErrorView.show(RezStrings.getApiFlood());
}
break;
@@ -324,7 +301,7 @@ class HomeAssistantApp extends Application.AppBase {
System.println("HomeAssistantApp onReturnFetchApiStatus() Response Code: NETWORK_REQUEST_TIMED_OUT, check Internet connection.");
}
if (!mIsGlance) {
- ErrorView.show(strNoResponse);
+ ErrorView.show(RezStrings.getNoResponse());
}
break;
@@ -333,7 +310,7 @@ class HomeAssistantApp extends Application.AppBase {
System.println("HomeAssistantApp onReturnFetchApiStatus() Response Code: INVALID_HTTP_BODY_IN_NETWORK_RESPONSE, check JSON is returned.");
}
if (!mIsGlance) {
- ErrorView.show(strNoJson);
+ ErrorView.show(RezStrings.getNoJson());
}
break;
@@ -342,7 +319,7 @@ class HomeAssistantApp extends Application.AppBase {
System.println("HomeAssistantApp onReturnFetchApiStatus() Response Code: 404, page not found. Check Configuration URL setting.");
}
if (!mIsGlance) {
- ErrorView.show(strConfigUrlNotFound);
+ ErrorView.show(RezStrings.getConfigUrlNotFound());
}
break;
@@ -352,7 +329,7 @@ class HomeAssistantApp extends Application.AppBase {
msg = data.get("message");
}
if (msg.equals("API running.")) {
- mApiStatus = strAvailable;
+ mApiStatus = RezStrings.getAvailable();
} else {
if (!mIsGlance) {
ErrorView.show("API " + mApiStatus + ".");
@@ -365,7 +342,7 @@ class HomeAssistantApp extends Application.AppBase {
System.println("HomeAssistantApp onReturnFetchApiStatus(): Unhandled HTTP response code = " + responseCode);
}
if (!mIsGlance) {
- ErrorView.show(strUnhandledHttpErr + responseCode);
+ ErrorView.show(RezStrings.getUnhandledHttpErr() + responseCode);
}
}
WatchUi.requestUpdate();
@@ -373,42 +350,41 @@ class HomeAssistantApp extends Application.AppBase {
(:glance)
function fetchApiStatus() as Void {
- if (mApiUrl.equals("")) {
- mApiStatus = strUnconfigured;
+ if (Settings.getApiUrl().equals("")) {
+ mApiStatus = RezStrings.getUnconfigured();
WatchUi.requestUpdate();
} else {
- var options = {
- :method => Communications.HTTP_REQUEST_METHOD_GET,
- :headers => {
- "Authorization" => "Bearer " + mApiKey
- },
- :responseType => Communications.HTTP_RESPONSE_CONTENT_TYPE_JSON
- };
if (! System.getDeviceSettings().phoneConnected) {
if (Globals.scDebug) {
System.println("HomeAssistantToggleMenuItem getState(): No Phone connection, skipping API call.");
}
- mApiStatus = strUnavailable;
+ mApiStatus = RezStrings.getUnavailable();
if (mIsGlance) {
WatchUi.requestUpdate();
} else {
- ErrorView.show(strNoPhone + ".");
+ ErrorView.show(RezStrings.getNoPhone() + ".");
}
} else if (! System.getDeviceSettings().connectionAvailable) {
if (Globals.scDebug) {
System.println("HomeAssistantToggleMenuItem getState(): No Internet connection, skipping API call.");
}
- mApiStatus = strUnavailable;
+ mApiStatus = RezStrings.getUnavailable();
if (mIsGlance) {
WatchUi.requestUpdate();
} else {
- ErrorView.show(strNoInternet + ".");
+ ErrorView.show(RezStrings.getNoInternet() + ".");
}
} else {
Communications.makeWebRequest(
- mApiUrl + "/",
+ Settings.getApiUrl() + "/",
null,
- options,
+ {
+ :method => Communications.HTTP_REQUEST_METHOD_GET,
+ :headers => {
+ "Authorization" => "Bearer " + Settings.getApiKey()
+ },
+ :responseType => Communications.HTTP_RESPONSE_CONTENT_TYPE_JSON
+ },
method(:onReturnFetchApiStatus)
);
}
@@ -437,8 +413,8 @@ class HomeAssistantApp extends Application.AppBase {
WatchUi.pushView(mHaMenu, new HomeAssistantViewDelegate(true), WatchUi.SLIDE_IMMEDIATE);
}
- // We need to spread out the API calls so as not to overload the results queue and cause Communications.BLE_QUEUE_FULL (-101) error.
- // This function is called by a timer every Globals.menuItemUpdateInterval ms.
+ // We need to spread out the API calls so as not to overload the results queue and cause Communications.BLE_QUEUE_FULL
+ // (-101) error. This function is called by a timer every Globals.menuItemUpdateInterval ms.
function updateNextMenuItem() as Void {
var itu = mItemsToUpdate as Lang.Array;
if (itu == null) {
@@ -446,7 +422,7 @@ class HomeAssistantApp extends Application.AppBase {
System.println("HomeAssistantApp updateNextMenuItem(): No menu items to update");
}
if (!mIsGlance) {
- ErrorView.show(WatchUi.loadResource($.Rez.Strings.ConfigUrlNotFound));
+ ErrorView.show(RezStrings.getConfigUrlNotFound());
}
} else {
itu[mNextItemToUpdate].getState();
@@ -458,10 +434,13 @@ class HomeAssistantApp extends Application.AppBase {
return mQuitTimer;
}
- (:glance)
function getGlanceView() as Lang.Array or Null {
mIsGlance = true;
+ RezStrings.update_glance();
+ mApiStatus = RezStrings.getChecking();
+ mMenuStatus = RezStrings.getChecking();
updateGlance();
+ Settings.update();
mTimer = new Timer.Timer();
mTimer.start(method(:updateGlance), Globals.scApiBackoff, true);
return [new HomeAssistantGlanceView(self)];
@@ -476,12 +455,25 @@ class HomeAssistantApp extends Application.AppBase {
// Replace this functionality with a more central settings class as proposed in
// https://github.com/house-of-abbey/GarminHomeAssistant/pull/17.
function onSettingsChanged() as Void {
- mApiKey = Properties.getValue("api_key");
- mApiUrl = Properties.getValue("api_url");
- mConfigUrl = Properties.getValue("config_url");
+ if (Globals.scDebug) {
+ System.println("HomeAssistantApp onSettingsChanged()");
+ }
+ Settings.update();
}
+
+ // Called each time the Registered Temporal Event is to be invoked. So the object is created each time on request and
+ // then destroyed on completion (to save resources).
+ function getServiceDelegate() as Lang.Array {
+ return [new BackgroundServiceDelegate()];
+ }
+
+ function getIsApp() as Lang.Boolean {
+ return mIsApp;
+ }
+
}
+(:glance, :background)
function getApp() as HomeAssistantApp {
return Application.getApp() as HomeAssistantApp;
}
diff --git a/source/HomeAssistantConfirmation.mc b/source/HomeAssistantConfirmation.mc
index 414552d..ce3abe7 100644
--- a/source/HomeAssistantConfirmation.mc
+++ b/source/HomeAssistantConfirmation.mc
@@ -28,7 +28,7 @@ using Toybox.Application.Properties;
class HomeAssistantConfirmation extends WatchUi.Confirmation {
function initialize() {
- WatchUi.Confirmation.initialize(WatchUi.loadResource($.Rez.Strings.Confirm));
+ WatchUi.Confirmation.initialize(RezStrings.getConfirm());
}
}
@@ -40,10 +40,10 @@ class HomeAssistantConfirmationDelegate extends WatchUi.ConfirmationDelegate {
function initialize(callback as Method() as Void) {
WatchUi.ConfirmationDelegate.initialize();
mConfirmMethod = callback;
- var timeoutSeconds = Properties.getValue("confirm_timeout") as Lang.Number;
- if (timeoutSeconds > 0) {
+ var timeout = Settings.getConfirmTimeout(); // ms
+ if (timeout > 0) {
mTimer = new Timer.Timer();
- mTimer.start(method(:onTimeout), timeoutSeconds * 1000, true);
+ mTimer.start(method(:onTimeout), timeout, true);
}
}
diff --git a/source/HomeAssistantGlanceView.mc b/source/HomeAssistantGlanceView.mc
index 8e5d9d8..123228b 100644
--- a/source/HomeAssistantGlanceView.mc
+++ b/source/HomeAssistantGlanceView.mc
@@ -24,8 +24,7 @@ using Toybox.Graphics;
(:glance)
class HomeAssistantGlanceView extends WatchUi.GlanceView {
- private static const scLeftMargin = 20; // in pixels
- private static const scLeftIndent = 10; // Left Indent "_text:" in pixels
+ private static const scLeftMargin = 5; // in pixels
private static const scMidSep = 10; // Middle Separator "text:_text" in pixels
private var mApp as HomeAssistantApp;
private var mTitle as WatchUi.Text or Null;
@@ -40,13 +39,11 @@ class HomeAssistantGlanceView extends WatchUi.GlanceView {
}
function onLayout(dc as Graphics.Dc) as Void {
- var strChecking = WatchUi.loadResource($.Rez.Strings.Checking);
- var strGlanceMenu = WatchUi.loadResource($.Rez.Strings.GlanceMenu);
- var h = dc.getHeight();
- var tw = dc.getTextWidthInPixels(strGlanceMenu, Graphics.FONT_XTINY);
+ var h = dc.getHeight();
+ var tw = dc.getTextWidthInPixels(RezStrings.getGlanceMenu(), Graphics.FONT_XTINY);
mTitle = new WatchUi.Text({
- :text => WatchUi.loadResource($.Rez.Strings.AppName),
+ :text => RezStrings.getAppName(),
:color => Graphics.COLOR_WHITE,
:font => Graphics.FONT_TINY,
:justification => Graphics.TEXT_JUSTIFY_LEFT | Graphics.TEXT_JUSTIFY_VCENTER,
@@ -58,32 +55,32 @@ class HomeAssistantGlanceView extends WatchUi.GlanceView {
:text => "API:",
:color => Graphics.COLOR_WHITE,
:font => Graphics.FONT_XTINY,
- :justification => Graphics.TEXT_JUSTIFY_RIGHT | Graphics.TEXT_JUSTIFY_VCENTER,
- :locX => scLeftMargin + scLeftIndent + tw,
+ :justification => Graphics.TEXT_JUSTIFY_LEFT | Graphics.TEXT_JUSTIFY_VCENTER,
+ :locX => scLeftMargin,
:locY => 3 * h / 6
});
mApiStatus = new WatchUi.Text({
- :text => strChecking,
+ :text => RezStrings.getChecking(),
:color => Graphics.COLOR_WHITE,
:font => Graphics.FONT_XTINY,
:justification => Graphics.TEXT_JUSTIFY_LEFT | Graphics.TEXT_JUSTIFY_VCENTER,
- :locX => scLeftMargin + scLeftIndent + scMidSep + tw,
+ :locX => scLeftMargin + scMidSep + tw,
:locY => 3 * h / 6
});
mMenuText = new WatchUi.Text({
- :text => strGlanceMenu + ":",
- :color => Graphics.COLOR_WHITE,
- :font => Graphics.FONT_XTINY,
- :justification => Graphics.TEXT_JUSTIFY_RIGHT | Graphics.TEXT_JUSTIFY_VCENTER,
- :locX => scLeftMargin + scLeftIndent + tw,
- :locY => 5 * h / 6
- });
- mMenuStatus = new WatchUi.Text({
- :text => strChecking,
+ :text => RezStrings.getGlanceMenu() + ":",
:color => Graphics.COLOR_WHITE,
:font => Graphics.FONT_XTINY,
:justification => Graphics.TEXT_JUSTIFY_LEFT | Graphics.TEXT_JUSTIFY_VCENTER,
- :locX => scLeftMargin + scLeftIndent + scMidSep + tw,
+ :locX => scLeftMargin,
+ :locY => 5 * h / 6
+ });
+ mMenuStatus = new WatchUi.Text({
+ :text => RezStrings.getChecking(),
+ :color => Graphics.COLOR_WHITE,
+ :font => Graphics.FONT_XTINY,
+ :justification => Graphics.TEXT_JUSTIFY_LEFT | Graphics.TEXT_JUSTIFY_VCENTER,
+ :locX => scLeftMargin + scMidSep + tw,
:locY => 5 * h / 6
});
}
@@ -95,7 +92,7 @@ class HomeAssistantGlanceView extends WatchUi.GlanceView {
}
dc.setColor(
Graphics.COLOR_WHITE,
- Graphics.COLOR_BLUE
+ Graphics.COLOR_TRANSPARENT
);
dc.clear();
mTitle.draw(dc);
diff --git a/source/HomeAssistantMenuItemFactory.mc b/source/HomeAssistantMenuItemFactory.mc
index 21eb111..a90ce38 100644
--- a/source/HomeAssistantMenuItemFactory.mc
+++ b/source/HomeAssistantMenuItemFactory.mc
@@ -23,35 +23,18 @@ using Toybox.Lang;
using Toybox.WatchUi;
class HomeAssistantMenuItemFactory {
- private var mMenuItemOptions as Lang.Dictionary;
- private var mLabelToggle as Lang.Dictionary;
- private var strMenuItemTap as Lang.String;
- private var bRepresentTypesWithLabels as Lang.Boolean;
- private var mTapTypeIcon as WatchUi.Bitmap;
- private var mGroupTypeIcon as WatchUi.Bitmap;
- private var mHomeAssistantService as HomeAssistantService;
+ private var mMenuItemOptions as Lang.Dictionary;
+ private var mTapTypeIcon as WatchUi.Bitmap;
+ private var mGroupTypeIcon as WatchUi.Bitmap;
+ private var mHomeAssistantService as HomeAssistantService;
private static var instance;
private function initialize() {
- mLabelToggle = {
- :enabled => WatchUi.loadResource($.Rez.Strings.MenuItemOn) as Lang.String,
- :disabled => WatchUi.loadResource($.Rez.Strings.MenuItemOff) as Lang.String
+ mMenuItemOptions = {
+ :alignment => Settings.getMenuAlignment()
};
- bRepresentTypesWithLabels = Application.Properties.getValue("types_representation") as Lang.Boolean;
- var menuItemAlignment = Application.Properties.getValue("menu_alignment") as Lang.Boolean;
- if(menuItemAlignment){
- mMenuItemOptions = {
- :alignment => WatchUi.MenuItem.MENU_ITEM_LABEL_ALIGN_RIGHT
- };
- } else {
- mMenuItemOptions = {
- :alignment => WatchUi.MenuItem.MENU_ITEM_LABEL_ALIGN_LEFT
- };
- }
-
- strMenuItemTap = WatchUi.loadResource($.Rez.Strings.MenuItemTap);
mTapTypeIcon = new WatchUi.Bitmap({
:rezId => $.Rez.Drawables.TapTypeIcon,
:locX => WatchUi.LAYOUT_HALIGN_CENTER,
@@ -74,15 +57,9 @@ class HomeAssistantMenuItemFactory {
}
function toggle(label as Lang.String or Lang.Symbol, identifier as Lang.Object or Null) as WatchUi.MenuItem {
- var subLabel = null;
-
- if (bRepresentTypesWithLabels == true){
- subLabel=mLabelToggle;
- }
-
return new HomeAssistantToggleMenuItem(
label,
- subLabel,
+ Settings.getMenuStyle() == Settings.MENU_STYLE_TEXT ? RezStrings.getLabelToggle() : null,
identifier,
false,
mMenuItemOptions
@@ -95,10 +72,10 @@ class HomeAssistantMenuItemFactory {
service as Lang.String or Null,
confirm as Lang.Boolean
) as WatchUi.MenuItem {
- if (bRepresentTypesWithLabels) {
+ if (Settings.getMenuStyle() == Settings.MENU_STYLE_TEXT) {
return new HomeAssistantMenuItem(
label,
- strMenuItemTap,
+ RezStrings.getMenuItemTap(),
identifier,
service,
confirm,
@@ -120,7 +97,7 @@ class HomeAssistantMenuItemFactory {
}
function group(definition as Lang.Dictionary) as WatchUi.MenuItem {
- if (bRepresentTypesWithLabels) {
+ if (Settings.getMenuStyle() == Settings.MENU_STYLE_TEXT) {
return new HomeAssistantViewMenuItem(definition);
} else {
return new HomeAssistantViewIconMenuItem(definition, mGroupTypeIcon, mMenuItemOptions);
diff --git a/source/HomeAssistantService.mc b/source/HomeAssistantService.mc
index d5a84bd..fb77371 100644
--- a/source/HomeAssistantService.mc
+++ b/source/HomeAssistantService.mc
@@ -24,19 +24,6 @@ using Toybox.Graphics;
using Toybox.Application.Properties;
class HomeAssistantService {
- private var strNoPhone = WatchUi.loadResource($.Rez.Strings.NoPhone);
- private var strNoInternet = WatchUi.loadResource($.Rez.Strings.NoInternet);
- private var strNoResponse = WatchUi.loadResource($.Rez.Strings.NoResponse);
- private var strNoJson = WatchUi.loadResource($.Rez.Strings.NoJson);
- private var strApiFlood = WatchUi.loadResource($.Rez.Strings.ApiFlood);
- private var strApiUrlNotFound = WatchUi.loadResource($.Rez.Strings.ApiUrlNotFound);
- private var strUnhandledHttpErr = WatchUi.loadResource($.Rez.Strings.UnhandledHttpErr);
-
- private var mApiKey as Lang.String;
-
- function initialize() {
- mApiKey = Properties.getValue("api_key");
- }
// Callback function after completing the POST request to call a service.
//
@@ -53,21 +40,21 @@ class HomeAssistantService {
if (Globals.scDebug) {
System.println("HomeAssistantService onReturnCall() Response Code: BLE_HOST_TIMEOUT or BLE_CONNECTION_UNAVAILABLE, Bluetooth connection severed.");
}
- ErrorView.show(strNoPhone + ".");
+ ErrorView.show(RezStrings.getNoPhone() + ".");
break;
case Communications.BLE_QUEUE_FULL:
if (Globals.scDebug) {
System.println("HomeAssistantService onReturnCall() Response Code: BLE_QUEUE_FULL, API calls too rapid.");
}
- ErrorView.show(strApiFlood);
+ ErrorView.show(RezStrings.getApiFlood());
break;
case Communications.NETWORK_REQUEST_TIMED_OUT:
if (Globals.scDebug) {
System.println("HomeAssistantService onReturnCall() Response Code: NETWORK_REQUEST_TIMED_OUT, check Internet connection.");
}
- ErrorView.show(strNoResponse);
+ ErrorView.show(RezStrings.getNoResponse());
break;
case Communications.NETWORK_RESPONSE_OUT_OF_MEMORY:
@@ -80,14 +67,14 @@ class HomeAssistantService {
if (Globals.scDebug) {
System.println("HomeAssistantService onReturnCall() Response Code: INVALID_HTTP_BODY_IN_NETWORK_RESPONSE, check JSON is returned.");
}
- ErrorView.show(strNoJson);
+ ErrorView.show(RezStrings.getNoJson());
break;
case 404:
if (Globals.scDebug) {
System.println("HomeAssistantService onReturnCall() Response Code: 404, page not found. Check API URL setting.");
}
- ErrorView.show(strApiUrlNotFound);
+ ErrorView.show(RezStrings.getApiUrlNotFound());
break;
case 200:
@@ -118,33 +105,24 @@ class HomeAssistantService {
if (Globals.scDebug) {
System.println("HomeAssistantService onReturnCall(): Unhandled HTTP response code = " + responseCode);
}
- ErrorView.show(strUnhandledHttpErr + responseCode);
+ ErrorView.show(RezStrings.getUnhandledHttpErr() + responseCode);
}
}
function call(identifier as Lang.String, service as Lang.String) as Void {
- var options = {
- :method => Communications.HTTP_REQUEST_METHOD_POST,
- :headers => {
- "Content-Type" => Communications.REQUEST_CONTENT_TYPE_JSON,
- "Authorization" => "Bearer " + mApiKey
- },
- :responseType => Communications.HTTP_RESPONSE_CONTENT_TYPE_JSON,
- :context => identifier
- };
if (! System.getDeviceSettings().phoneConnected) {
if (Globals.scDebug) {
System.println("HomeAssistantService call(): No Phone connection, skipping API call.");
}
- ErrorView.show(strNoPhone + ".");
+ ErrorView.show(RezStrings.getNoPhone() + ".");
} else if (! System.getDeviceSettings().connectionAvailable) {
if (Globals.scDebug) {
System.println("HomeAssistantService call(): No Internet connection, skipping API call.");
}
- ErrorView.show(strNoInternet + ".");
+ ErrorView.show(RezStrings.getNoInternet() + ".");
} else {
// Can't use null for substring() parameters due to API version level.
- var url = (Properties.getValue("api_url") as Lang.String) + "/services/" + service.substring(0, service.find(".")) + "/" + service.substring(service.find(".")+1, service.length());
+ var url = Settings.getApiUrl() + "/services/" + service.substring(0, service.find(".")) + "/" + service.substring(service.find(".")+1, service.length());
if (Globals.scDebug) {
System.println("HomeAssistantService call() URL=" + url);
System.println("HomeAssistantService call() service=" + service);
@@ -154,7 +132,15 @@ class HomeAssistantService {
{
"entity_id" => identifier
},
- options,
+ {
+ :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,
+ :context => identifier
+ },
method(:onReturnCall)
);
if (Attention has :vibrate) {
diff --git a/source/HomeAssistantToggleMenuItem.mc b/source/HomeAssistantToggleMenuItem.mc
index c27024f..3e9c068 100644
--- a/source/HomeAssistantToggleMenuItem.mc
+++ b/source/HomeAssistantToggleMenuItem.mc
@@ -25,17 +25,6 @@ using Toybox.Application.Properties;
using Toybox.Timer;
class HomeAssistantToggleMenuItem extends WatchUi.ToggleMenuItem {
- private var strNoPhone = WatchUi.loadResource($.Rez.Strings.NoPhone);
- private var strNoInternet = WatchUi.loadResource($.Rez.Strings.NoInternet);
- private var strNoResponse = WatchUi.loadResource($.Rez.Strings.NoResponse);
- private var strNoJson = WatchUi.loadResource($.Rez.Strings.NoJson);
- private var strApiFlood = WatchUi.loadResource($.Rez.Strings.ApiFlood);
- private var strApiUrlNotFound = WatchUi.loadResource($.Rez.Strings.ApiUrlNotFound);
- private var strUnhandledHttpErr = WatchUi.loadResource($.Rez.Strings.UnhandledHttpErr);
- private var strUnavailable = WatchUi.loadResource($.Rez.Strings.Unavailable);
- private var strAvailable = WatchUi.loadResource($.Rez.Strings.Available);
-
- private var mApiKey as Lang.String;
function initialize(
label as Lang.String or Lang.Symbol,
@@ -50,7 +39,6 @@ class HomeAssistantToggleMenuItem extends WatchUi.ToggleMenuItem {
:icon as Graphics.BitmapType or WatchUi.Drawable or Lang.Symbol
} or Null
) {
- mApiKey = Properties.getValue("api_key");
WatchUi.ToggleMenuItem.initialize(label, subLabel, identifier, enabled, options);
}
@@ -76,35 +64,35 @@ class HomeAssistantToggleMenuItem extends WatchUi.ToggleMenuItem {
System.println("HomeAssistantToggleMenuItem onReturnGetState() Response Data: " + data);
}
- var status = strUnavailable;
+ var status = RezStrings.getUnavailable();
switch (responseCode) {
case Communications.BLE_HOST_TIMEOUT:
case Communications.BLE_CONNECTION_UNAVAILABLE:
if (Globals.scDebug) {
System.println("HomeAssistantToggleMenuItem onReturnGetState() Response Code: BLE_HOST_TIMEOUT or BLE_CONNECTION_UNAVAILABLE, Bluetooth connection severed.");
}
- ErrorView.show(strNoPhone + ".");
+ ErrorView.show(RezStrings.getNoPhone() + ".");
break;
case Communications.BLE_QUEUE_FULL:
if (Globals.scDebug) {
System.println("HomeAssistantToggleMenuItem onReturnGetState() Response Code: BLE_QUEUE_FULL, API calls too rapid.");
}
- ErrorView.show(strApiFlood);
+ ErrorView.show(RezStrings.getApiFlood());
break;
case Communications.NETWORK_REQUEST_TIMED_OUT:
if (Globals.scDebug) {
System.println("HomeAssistantToggleMenuItem onReturnGetState() Response Code: NETWORK_REQUEST_TIMED_OUT, check Internet connection.");
}
- ErrorView.show(strNoResponse);
+ ErrorView.show(RezStrings.getNoResponse());
break;
case Communications.INVALID_HTTP_BODY_IN_NETWORK_RESPONSE:
if (Globals.scDebug) {
System.println("HomeAssistantToggleMenuItem onReturnGetState() Response Code: INVALID_HTTP_BODY_IN_NETWORK_RESPONSE, check JSON is returned.");
}
- ErrorView.show(strNoJson);
+ ErrorView.show(RezStrings.getNoJson());
break;
case Communications.NETWORK_RESPONSE_OUT_OF_MEMORY:
@@ -131,7 +119,7 @@ class HomeAssistantToggleMenuItem extends WatchUi.ToggleMenuItem {
if (Globals.scDebug) {
System.println("HomeAssistantToggleMenuItem onReturnGetState() Response Code: 404, page not found. Check API URL setting.");
}
- ErrorView.show(strApiUrlNotFound);
+ ErrorView.show(RezStrings.getApiUrlNotFound());
}
break;
@@ -144,7 +132,7 @@ class HomeAssistantToggleMenuItem extends WatchUi.ToggleMenuItem {
break;
case 200:
- status = strAvailable;
+ status = RezStrings.getAvailable();
var state = data.get("state") as Lang.String;
if (Globals.scDebug) {
System.println((data.get("attributes") as Lang.Dictionary).get("friendly_name") + " State=" + state);
@@ -162,40 +150,39 @@ class HomeAssistantToggleMenuItem extends WatchUi.ToggleMenuItem {
if (Globals.scDebug) {
System.println("HomeAssistantToggleMenuItem onReturnGetState(): Unhandled HTTP response code = " + responseCode);
}
- ErrorView.show(strUnhandledHttpErr + responseCode);
+ ErrorView.show(RezStrings.getUnhandledHttpErr() + responseCode);
}
getApp().setApiStatus(status);
}
function getState() as Void {
- var options = {
- :method => Communications.HTTP_REQUEST_METHOD_GET,
- :headers => {
- "Authorization" => "Bearer " + mApiKey
- },
- :responseType => Communications.HTTP_RESPONSE_CONTENT_TYPE_JSON
- };
if (! System.getDeviceSettings().phoneConnected) {
if (Globals.scDebug) {
System.println("HomeAssistantToggleMenuItem getState(): No Phone connection, skipping API call.");
}
- ErrorView.show(strNoPhone + ".");
- getApp().setApiStatus(strUnavailable);
+ ErrorView.show(RezStrings.getNoPhone() + ".");
+ getApp().setApiStatus(RezStrings.getUnavailable());
} else if (! System.getDeviceSettings().connectionAvailable) {
if (Globals.scDebug) {
System.println("HomeAssistantToggleMenuItem getState(): No Internet connection, skipping API call.");
}
- ErrorView.show(strNoInternet + ".");
- getApp().setApiStatus(strUnavailable);
+ ErrorView.show(RezStrings.getNoInternet() + ".");
+ getApp().setApiStatus(RezStrings.getUnavailable());
} else {
- var url = Properties.getValue("api_url") + "/states/" + mIdentifier;
+ var url = Settings.getApiUrl() + "/states/" + mIdentifier;
if (Globals.scDebug) {
System.println("HomeAssistantToggleMenuItem getState() URL=" + url);
}
Communications.makeWebRequest(
url,
null,
- options,
+ {
+ :method => Communications.HTTP_REQUEST_METHOD_GET,
+ :headers => {
+ "Authorization" => "Bearer " + Settings.getApiKey()
+ },
+ :responseType => Communications.HTTP_RESPONSE_CONTENT_TYPE_JSON
+ },
method(:onReturnGetState)
);
}
@@ -209,42 +196,42 @@ class HomeAssistantToggleMenuItem extends WatchUi.ToggleMenuItem {
System.println("HomeAssistantToggleMenuItem onReturnSetState() Response Data: " + data);
}
- var status = strUnavailable;
+ var status = RezStrings.getUnavailable();
switch (responseCode) {
case Communications.BLE_HOST_TIMEOUT:
case Communications.BLE_CONNECTION_UNAVAILABLE:
if (Globals.scDebug) {
System.println("HomeAssistantToggleMenuItem onReturnSetState() Response Code: BLE_HOST_TIMEOUT or BLE_CONNECTION_UNAVAILABLE, Bluetooth connection severed.");
}
- ErrorView.show(strNoPhone + ".");
+ ErrorView.show(RezStrings.getNoPhone() + ".");
break;
case Communications.BLE_QUEUE_FULL:
if (Globals.scDebug) {
System.println("HomeAssistantToggleMenuItem onReturnSetState() Response Code: BLE_QUEUE_FULL, API calls too rapid.");
}
- ErrorView.show(strApiFlood);
+ ErrorView.show(RezStrings.getApiFlood());
break;
case Communications.NETWORK_REQUEST_TIMED_OUT:
if (Globals.scDebug) {
System.println("HomeAssistantToggleMenuItem onReturnSetState() Response Code: NETWORK_REQUEST_TIMED_OUT, check Internet connection.");
}
- ErrorView.show(strNoResponse);
+ ErrorView.show(RezStrings.getNoResponse());
break;
case Communications.INVALID_HTTP_BODY_IN_NETWORK_RESPONSE:
if (Globals.scDebug) {
System.println("HomeAssistantToggleMenuItem onReturnSetState() Response Code: INVALID_HTTP_BODY_IN_NETWORK_RESPONSE, check JSON is returned.");
}
- ErrorView.show(strNoJson);
+ ErrorView.show(RezStrings.getNoJson());
break;
case 404:
if (Globals.scDebug) {
System.println("HomeAssistantToggleMenuItem onReturnSetState() Response Code: 404, page not found. Check API URL setting.");
}
- ErrorView.show(strApiUrlNotFound);
+ ErrorView.show(RezStrings.getApiUrlNotFound());
break;
case 200:
@@ -259,50 +246,42 @@ class HomeAssistantToggleMenuItem extends WatchUi.ToggleMenuItem {
setUiToggle(state);
}
}
- status = strAvailable;
+ status = RezStrings.getAvailable();
break;
default:
if (Globals.scDebug) {
System.println("HomeAssistantToggleMenuItem onReturnSetState(): Unhandled HTTP response code = " + responseCode);
}
- ErrorView.show(strUnhandledHttpErr + responseCode);
+ ErrorView.show(RezStrings.getUnhandledHttpErr() + responseCode);
}
getApp().setApiStatus(status);
}
function setState(s as Lang.Boolean) as Void {
- var options = {
- :method => Communications.HTTP_REQUEST_METHOD_POST,
- :headers => {
- "Content-Type" => Communications.REQUEST_CONTENT_TYPE_JSON,
- "Authorization" => "Bearer " + mApiKey
- },
- :responseType => Communications.HTTP_RESPONSE_CONTENT_TYPE_JSON
- };
if (! System.getDeviceSettings().phoneConnected) {
if (Globals.scDebug) {
System.println("HomeAssistantToggleMenuItem getState(): No Phone connection, skipping API call.");
}
// Toggle the UI back
setEnabled(!isEnabled());
- ErrorView.show(strNoPhone + ".");
+ ErrorView.show(RezStrings.getNoPhone() + ".");
} else if (! System.getDeviceSettings().connectionAvailable) {
if (Globals.scDebug) {
System.println("HomeAssistantToggleMenuItem getState(): No Internet connection, skipping API call.");
}
// Toggle the UI back
setEnabled(!isEnabled());
- ErrorView.show(strNoInternet + ".");
+ ErrorView.show(RezStrings.getNoInternet() + ".");
} else {
// Updated SDK and got a new error
// ERROR: venu: Cannot find symbol ':substring' on type 'PolyType'.
- var id = mIdentifier as Lang.String;
- var url;
+ var id = mIdentifier as Lang.String;
+ var url = Settings.getApiUrl() + "/services/";
if (s) {
- url = Properties.getValue("api_url") + "/services/" + id.substring(0, id.find(".")) + "/turn_on";
+ url = url + id.substring(0, id.find(".")) + "/turn_on";
} else {
- url = Properties.getValue("api_url") + "/services/" + id.substring(0, id.find(".")) + "/turn_off";
+ url = url + id.substring(0, id.find(".")) + "/turn_off";
}
if (Globals.scDebug) {
System.println("HomeAssistantToggleMenuItem setState() URL=" + url);
@@ -313,7 +292,14 @@ class HomeAssistantToggleMenuItem extends WatchUi.ToggleMenuItem {
{
"entity_id" => mIdentifier
},
- options,
+ {
+ :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(:onReturnSetState)
);
}
diff --git a/source/HomeAssistantView.mc b/source/HomeAssistantView.mc
index 747adcb..78afe1b 100644
--- a/source/HomeAssistantView.mc
+++ b/source/HomeAssistantView.mc
@@ -49,11 +49,11 @@ class HomeAssistantView extends WatchUi.Menu2 {
var items = definition.get("items") as Lang.Dictionary;
for(var i = 0; i < items.size(); i++) {
- var type = items[i].get("type") as Lang.String or Null;
- var name = items[i].get("name") as Lang.String or Null;
- var entity = items[i].get("entity") as Lang.String or Null;
+ var type = items[i].get("type") as Lang.String or Null;
+ var name = items[i].get("name") as Lang.String or Null;
+ var entity = items[i].get("entity") as Lang.String or Null;
var tap_action = items[i].get("tap_action") as Lang.Dictionary or Null;
- var service = items[i].get("service") as Lang.String or Null;
+ var service = items[i].get("service") as Lang.String or Null;
var confirm = false as Lang.Boolean;
if (tap_action != null) {
service = tap_action.get("service");
diff --git a/source/HomeAssistantViewMenuItem.mc b/source/HomeAssistantViewMenuItem.mc
index 7ed91ea..1c0ccb7 100644
--- a/source/HomeAssistantViewMenuItem.mc
+++ b/source/HomeAssistantViewMenuItem.mc
@@ -28,7 +28,7 @@ class HomeAssistantViewMenuItem extends WatchUi.MenuItem {
// definitions.get(...) are Strings here as they have been checked by HomeAssistantView first
WatchUi.MenuItem.initialize(
definition.get("name") as Lang.String,
- WatchUi.loadResource($.Rez.Strings.MenuItemMenu) as Lang.String,
+ RezStrings.getMenuItemMenu(),
definition.get("entity") as Lang.String,
null
);
diff --git a/source/QuitTimer.mc b/source/QuitTimer.mc
index fdc7d63..a5901b8 100644
--- a/source/QuitTimer.mc
+++ b/source/QuitTimer.mc
@@ -24,12 +24,9 @@ using Toybox.Application.Properties;
using Toybox.WatchUi;
class QuitTimer extends Timer.Timer {
- private var api_timeout;
-
+
function initialize() {
Timer.Timer.initialize();
- // Timer needs delay in milliseconds.
- api_timeout = (Properties.getValue("app_timeout") as Lang.Number) * 1000;
}
function exitApp() as Void {
@@ -41,6 +38,7 @@ class QuitTimer extends Timer.Timer {
}
function begin() {
+ var api_timeout = Settings.getAppTimeout(); // ms
if (api_timeout > 0) {
start(method(:exitApp), api_timeout, false);
}
diff --git a/source/RezStrings.mc b/source/RezStrings.mc
new file mode 100644
index 0000000..3243d42
--- /dev/null
+++ b/source/RezStrings.mc
@@ -0,0 +1,195 @@
+//-----------------------------------------------------------------------------------
+//
+// Distributed under MIT Licence
+// See https://github.com/house-of-abbey/GarminHomeAssistant/blob/main/LICENSE.
+//
+//-----------------------------------------------------------------------------------
+//
+// GarminHomeAssistant is a Garmin IQ application written in Monkey C and routinely
+// tested on a Venu 2 device. The source code is provided at:
+// https://github.com/house-of-abbey/GarminHomeAssistant.
+//
+// P A Abbey & J D Abbey & Someone0nEarth, 31 October 2023
+//
+//
+// Description:
+//
+// Load the strings centrally once rather than initialising locally within separate
+// classes. This is to solve a problem with out of memory errors in some devices,
+// e.g. Vivoactive 3.
+//
+//-----------------------------------------------------------------------------------
+
+using Toybox.Lang;
+using Toybox.WatchUi;
+
+class RezStrings {
+
+ (:glance)
+ private static var strAppName as Lang.String or Null;
+ private static var strMenuItemTap as Lang.String or Null;
+ private static var strMenuItemMenu as Lang.String or Null;
+ private static var strConfirm as Lang.String or Null;
+ (:glance)
+ private static var strNoPhone as Lang.String or Null;
+ private static var strNoInternet as Lang.String or Null;
+ private static var strNoResponse as Lang.String or Null;
+ (:glance)
+ private static var strNoApiKey as Lang.String or Null;
+ (:glance)
+ private static var strNoApiUrl as Lang.String or Null;
+ (:glance)
+ private static var strNoConfigUrl as Lang.String or Null;
+ private static var strApiFlood as Lang.String or Null;
+ private static var strApiUrlNotFound as Lang.String or Null;
+ private static var strConfigUrlNotFound as Lang.String or Null;
+ 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;
+ (:glance)
+ private static var strAvailable as Lang.String or Null;
+ (:glance)
+ private static var strChecking as Lang.String or Null;
+ (:glance)
+ private static var strUnavailable as Lang.String or Null;
+ (:glance)
+ private static var strUnconfigured as Lang.String or Null;
+ (:glance)
+ private static var strGlanceMenu as Lang.String or Null;
+ private static var strLabelToggle as Lang.Dictionary or Null;
+
+ // Can't initialise a constant directly, have to be initialised via a function
+ // for 'WatchUi.loadResource' to be available.
+ (:glance)
+ static function update_glance() {
+ strAppName = WatchUi.loadResource($.Rez.Strings.AppName);
+ strNoPhone = WatchUi.loadResource($.Rez.Strings.NoPhone);
+ strNoApiKey = WatchUi.loadResource($.Rez.Strings.NoAPIKey);
+ strNoApiUrl = WatchUi.loadResource($.Rez.Strings.NoApiUrl);
+ strNoConfigUrl = WatchUi.loadResource($.Rez.Strings.NoConfigUrl);
+ strAvailable = WatchUi.loadResource($.Rez.Strings.Available);
+ strChecking = WatchUi.loadResource($.Rez.Strings.Checking);
+ strUnavailable = WatchUi.loadResource($.Rez.Strings.Unavailable);
+ strUnconfigured = WatchUi.loadResource($.Rez.Strings.Unconfigured);
+ strGlanceMenu = WatchUi.loadResource($.Rez.Strings.GlanceMenu);
+ }
+
+ // Can't initialise a constant directly, have to be initialised via a function
+ // for 'WatchUi.loadResource' to be available.
+ static function update() {
+ strAppName = WatchUi.loadResource($.Rez.Strings.AppName);
+ strMenuItemTap = WatchUi.loadResource($.Rez.Strings.MenuItemTap);
+ strMenuItemMenu = WatchUi.loadResource($.Rez.Strings.MenuItemMenu);
+ strConfirm = WatchUi.loadResource($.Rez.Strings.Confirm);
+ strNoPhone = WatchUi.loadResource($.Rez.Strings.NoPhone);
+ strNoInternet = WatchUi.loadResource($.Rez.Strings.NoInternet);
+ strNoResponse = WatchUi.loadResource($.Rez.Strings.NoResponse);
+ strNoApiKey = WatchUi.loadResource($.Rez.Strings.NoAPIKey);
+ strNoApiUrl = WatchUi.loadResource($.Rez.Strings.NoApiUrl);
+ strNoConfigUrl = WatchUi.loadResource($.Rez.Strings.NoConfigUrl);
+ strApiFlood = WatchUi.loadResource($.Rez.Strings.ApiFlood);
+ strApiUrlNotFound = WatchUi.loadResource($.Rez.Strings.ApiUrlNotFound);
+ strConfigUrlNotFound = WatchUi.loadResource($.Rez.Strings.ConfigUrlNotFound);
+ strNoJson = WatchUi.loadResource($.Rez.Strings.NoJson);
+ strUnhandledHttpErr = WatchUi.loadResource($.Rez.Strings.UnhandledHttpErr);
+ strTrailingSlashErr = WatchUi.loadResource($.Rez.Strings.TrailingSlashErr);
+ strAvailable = WatchUi.loadResource($.Rez.Strings.Available);
+ strChecking = WatchUi.loadResource($.Rez.Strings.Checking);
+ strUnavailable = WatchUi.loadResource($.Rez.Strings.Unavailable);
+ strUnconfigured = WatchUi.loadResource($.Rez.Strings.Unconfigured);
+ strGlanceMenu = WatchUi.loadResource($.Rez.Strings.GlanceMenu);
+ strLabelToggle = {
+ :enabled => WatchUi.loadResource($.Rez.Strings.MenuItemOn) as Lang.String,
+ :disabled => WatchUi.loadResource($.Rez.Strings.MenuItemOff) as Lang.String
+ };
+ }
+
+ static function getAppName() as Lang.String {
+ return strAppName;
+ }
+
+ static function getMenuItemTap() as Lang.String {
+ return strMenuItemTap;
+ }
+
+ static function getMenuItemMenu() as Lang.String {
+ return strMenuItemMenu;
+ }
+
+ static function getConfirm() as Lang.String {
+ return strConfirm;
+ }
+
+ static function getNoPhone() as Lang.String {
+ return strNoPhone;
+ }
+
+ static function getNoInternet() as Lang.String {
+ return strNoInternet;
+ }
+
+ static function getNoResponse() as Lang.String {
+ return strNoResponse;
+ }
+
+ static function getNoApiKey() as Lang.String {
+ return strNoApiKey;
+ }
+
+ static function getNoApiUrl() as Lang.String {
+ return strNoApiUrl;
+ }
+
+ static function getNoConfigUrl() as Lang.String {
+ return strNoConfigUrl;
+ }
+
+ static function getApiFlood() as Lang.String {
+ return strApiFlood;
+ }
+
+ static function getApiUrlNotFound() as Lang.String {
+ return strApiUrlNotFound;
+ }
+
+ static function getConfigUrlNotFound() as Lang.String {
+ return strConfigUrlNotFound;
+ }
+
+ static function getNoJson() as Lang.String {
+ return strNoJson;
+ }
+
+ static function getUnhandledHttpErr() as Lang.String {
+ return strUnhandledHttpErr;
+ }
+
+ static function getTrailingSlashErr() as Lang.String {
+ return strTrailingSlashErr;
+ }
+
+ static function getAvailable() as Lang.String {
+ return strAvailable;
+ }
+
+ static function getChecking() as Lang.String {
+ return strChecking;
+ }
+
+ static function getUnavailable() as Lang.String {
+ return strUnavailable;
+ }
+
+ static function getUnconfigured() as Lang.String {
+ return strUnconfigured;
+ }
+
+ static function getGlanceMenu() as Lang.String {
+ return strGlanceMenu;
+ }
+
+ static function getLabelToggle() as Lang.Dictionary {
+ return strLabelToggle;
+ }
+
+}
diff --git a/source/RootView.mc b/source/RootView.mc
index 1d412d5..860a785 100644
--- a/source/RootView.mc
+++ b/source/RootView.mc
@@ -51,11 +51,10 @@ class RootView extends ScalableView {
}
function onLayout(dc as Graphics.Dc) as Void {
- var strChecking = WatchUi.loadResource($.Rez.Strings.Checking);
- var w = dc.getWidth();
+ var w = dc.getWidth();
mTitle = new WatchUi.Text({
- :text => WatchUi.loadResource($.Rez.Strings.AppName),
+ :text => RezStrings.getAppName(),
:color => Graphics.COLOR_WHITE,
:font => Graphics.FONT_TINY,
:justification => Graphics.TEXT_JUSTIFY_CENTER | Graphics.TEXT_JUSTIFY_VCENTER,
@@ -72,7 +71,7 @@ class RootView extends ScalableView {
:locY => pixelsForScreen(50.0)
});
mApiStatus = new WatchUi.Text({
- :text => strChecking,
+ :text => RezStrings.getChecking(),
:color => Graphics.COLOR_WHITE,
:font => Graphics.FONT_XTINY,
:justification => Graphics.TEXT_JUSTIFY_LEFT | Graphics.TEXT_JUSTIFY_VCENTER,
@@ -80,7 +79,7 @@ class RootView extends ScalableView {
:locY => pixelsForScreen(50.0)
});
mMenuText = new WatchUi.Text({
- :text => WatchUi.loadResource($.Rez.Strings.GlanceMenu) + ":",
+ :text => RezStrings.getGlanceMenu() + ":",
:color => Graphics.COLOR_WHITE,
:font => Graphics.FONT_XTINY,
:justification => Graphics.TEXT_JUSTIFY_RIGHT | Graphics.TEXT_JUSTIFY_VCENTER,
@@ -88,7 +87,7 @@ class RootView extends ScalableView {
:locY => pixelsForScreen(70.0)
});
mMenuStatus = new WatchUi.Text({
- :text => strChecking,
+ :text => RezStrings.getChecking(),
:color => Graphics.COLOR_WHITE,
:font => Graphics.FONT_XTINY,
:justification => Graphics.TEXT_JUSTIFY_LEFT | Graphics.TEXT_JUSTIFY_VCENTER,
diff --git a/source/Settings.mc b/source/Settings.mc
new file mode 100644
index 0000000..8faa54f
--- /dev/null
+++ b/source/Settings.mc
@@ -0,0 +1,123 @@
+//-----------------------------------------------------------------------------------
+//
+// Distributed under MIT Licence
+// See https://github.com/house-of-abbey/GarminHomeAssistant/blob/main/LICENSE.
+//
+//-----------------------------------------------------------------------------------
+//
+// GarminHomeAssistant is a Garmin IQ application written in Monkey C and routinely
+// tested on a Venu 2 device. The source code is provided at:
+// https://github.com/house-of-abbey/GarminHomeAssistant.
+//
+// P A Abbey & J D Abbey, SomeoneOnEarth, 23 November 2023
+//
+//
+// Description:
+//
+// Home Assistant settings.
+//
+//-----------------------------------------------------------------------------------
+
+using Toybox.Lang;
+using Toybox.Application.Properties;
+using Toybox.WatchUi;
+using Toybox.System;
+// Battery Level Reporting
+using Toybox.Background;
+using Toybox.Time;
+
+(:glance, :background)
+class Settings {
+ public static const MENU_STYLE_ICONS = 0;
+ public static const MENU_STYLE_TEXT = 1;
+
+ private static var mApiKey as Lang.String = "";
+ private static var mApiUrl as Lang.String = "";
+ private static var mConfigUrl as Lang.String = "";
+ private static var mAppTimeout as Lang.Number = 0; // seconds
+ private static var mConfirmTimeout as Lang.Number = 3; // seconds
+ private static var mMenuStyle as Lang.Number = MENU_STYLE_ICONS;
+ private static var mMenuAlignment as Lang.Number = WatchUi.MenuItem.MENU_ITEM_LABEL_ALIGN_LEFT;
+ private static var mIsWidgetStartNoTap as Lang.Boolean = false;
+ private static var mIsBatteryLevelEnabled as Lang.Boolean = false;
+ private static var mBatteryRefreshRate as Lang.Number = 15; // minutes
+ private static var mIsApp as Lang.Boolean = false;
+
+ // Called on application start and then whenever the settings are changed.
+ static function update() {
+ mIsApp = getApp().getIsApp();
+ mApiKey = Properties.getValue("api_key");
+ mApiUrl = Properties.getValue("api_url");
+ mConfigUrl = Properties.getValue("config_url");
+ mAppTimeout = Properties.getValue("app_timeout");
+ mConfirmTimeout = Properties.getValue("confirm_timeout");
+ mMenuStyle = Properties.getValue("menu_theme");
+ mMenuAlignment = Properties.getValue("menu_alignment");
+ mIsWidgetStartNoTap = Properties.getValue("widget_start_no_tap");
+ mIsBatteryLevelEnabled = Properties.getValue("enable_battery_level");
+ mBatteryRefreshRate = Properties.getValue("battery_level_refresh_rate");
+
+ // Manage this inside the application or widget only (not a glance or background service process)
+ if (mIsApp) {
+ if (mIsBatteryLevelEnabled) {
+ if ((System has :ServiceDelegate) and
+ ((Background.getTemporalEventRegisteredTime() == null) or
+ (Background.getTemporalEventRegisteredTime() != (mBatteryRefreshRate * 60)))) {
+ Background.registerForTemporalEvent(new Time.Duration(mBatteryRefreshRate * 60)); // Convert to seconds
+ }
+ } else {
+ // Explicitly disable the background event which persists when the application closes.
+ if ((System has :ServiceDelegate) and (Background.getTemporalEventRegisteredTime() != null)) {
+ Background.deleteTemporalEvent();
+ }
+ }
+ } else {
+ // Explicitly disable the background events for glances and ironically any use by the background service. However
+ // that has been avoided more recently by not using this object in BackgroundServiceDelegate.
+ if ((System has :ServiceDelegate) and (Background.getTemporalEventRegisteredTime() != null)) {
+ Background.deleteTemporalEvent();
+ }
+ }
+ if (Globals.scDebug) {
+ System.println("Settings update(): getTemporalEventRegisteredTime() = " + Background.getTemporalEventRegisteredTime());
+ if (Background.getTemporalEventRegisteredTime() != null) {
+ System.println("Settings update(): getTemporalEventRegisteredTime().value() = " + Background.getTemporalEventRegisteredTime().value().format("%d") + " seconds");
+ } else {
+ System.println("Settings update(): getTemporalEventRegisteredTime() = null");
+ }
+ }
+ }
+
+ static function getApiKey() as Lang.String {
+ return mApiKey;
+ }
+
+ static function getApiUrl() as Lang.String {
+ return mApiUrl;
+ }
+
+ static function getConfigUrl() as Lang.String {
+ return mConfigUrl;
+ }
+
+ static function getAppTimeout() as Lang.Number {
+ return mAppTimeout * 1000; // Convert to milliseconds
+ }
+
+ static function getConfirmTimeout() as Lang.Number {
+ return mConfirmTimeout * 1000; // Convert to milliseconds
+ }
+
+ static function getMenuStyle() as Lang.Number {
+ return mMenuStyle; // Either MENU_STYLE_ICONS or MENU_STYLE_TEXT
+ }
+
+ static function getMenuAlignment() as Lang.Number {
+ return mMenuAlignment; // Either WatchUi.MenuItem.MENU_ITEM_LABEL_ALIGN_RIGHT or WatchUi.MenuItem.MENU_ITEM_LABEL_ALIGN_LEFT
+ }
+
+ static function getIsWidgetStartNoTap() as Lang.Boolean {
+ return mIsWidgetStartNoTap;
+ }
+
+}
diff --git a/source/WebLog.mc b/source/WebLog.mc
new file mode 100644
index 0000000..d845a46
--- /dev/null
+++ b/source/WebLog.mc
@@ -0,0 +1,179 @@
+//-----------------------------------------------------------------------------------
+//
+// Distributed under MIT Licence
+// See https://github.com/house-of-abbey/GarminHomeAssistant/blob/main/LICENSE.
+//
+//-----------------------------------------------------------------------------------
+//
+// GarminHomeAssistant is a Garmin IQ application written in Monkey C and routinely
+// tested on a Venu 2 device. The source code is provided at:
+// https://github.com/house-of-abbey/GarminHomeAssistant.
+//
+// J D Abbey & P A Abbey, 28 December 2022
+//
+//
+// Description:
+//
+// WebLog provides a logging and hence debugging aid for when the application is
+// deployed to the watch. This is only used for development and use of it must not
+// persist into a deployed version. It uses a string buffer to group log entries into
+// larger submissions in order to prevent overflow of the blue tooth stack.
+//
+//-----------------------------------------------------------------------------------
+//
+// Usage:
+// wl = new WebLog();
+// wl.clear();
+// wl.println("Debug Message");
+// wl.flush();
+//
+// https://domain.name/path/log.php
+//
+//
+//
+// Logs published to: https://domain.name/path/log
+//
+// https://domain.name/path/log_clear.php
+//
+//
+
+using Toybox.Communications;
+using Toybox.Lang;
+using Toybox.System;
+
+(:glance, :background)
+class WebLog {
+ private var callsbuffer = 4 as Lang.Number;
+ private var numCalls = 0 as Lang.Number;
+ private var buffer = "" as Lang.String;
+
+ // Set the number of calls to print() before sending the buffer to the online
+ // logger.
+ //
+ function setCallsBuffer(l as Lang.Number) {
+ callsbuffer = l;
+ }
+
+ // Get the number of calls to print() before sending the buffer to the online
+ // logger.
+ //
+ function getCallsBuffer() as Lang.Number {
+ return callsbuffer;
+ }
+
+ // Create a debug log over the Internet to keep track of the watch's runtime
+ // execution.
+ //
+ function print(str as Lang.String) {
+ var myTime = System.getClockTime();
+ buffer += myTime.hour.format("%02d") + ":" + myTime.min.format("%02d") + ":" + myTime.sec.format("%02d") + " " + str;
+ numCalls++;
+ if (Globals.scDebug) {
+ System.println("WebLog print() str = " + str);
+ }
+ if (numCalls >= callsbuffer) {
+ doPrint();
+ }
+ }
+
+ // Create a debug log over the Internet to keep track of the watch's runtime
+ // execution. Add a new line character to the end.
+ //
+ function println(str as Lang.String) {
+ print(str + "\n");
+ }
+
+ // Flush the current buffer to the online logger even if it has not reach the
+ // submission level set by 'callsbuffer'.
+ //
+ function flush() {
+ if (Globals.scDebug) {
+ System.println("WebLog flush()");
+ }
+ if (numCalls > 0) {
+ doPrint();
+ }
+ }
+
+ // Perform the submission to the online logger.
+ //
+ function doPrint() {
+ if (Globals.scDebug) {
+ System.println("WebLog doPrint()");
+ System.println(buffer);
+ }
+ Communications.makeWebRequest(
+ ClientId.webLogUrl,
+ {
+ "log" => buffer
+ },
+ {
+ :method => Communications.HTTP_REQUEST_METHOD_GET,
+ :headers => {
+ "Content-Type" => Communications.REQUEST_CONTENT_TYPE_URL_ENCODED
+ },
+ :responseType => Communications.HTTP_RESPONSE_CONTENT_TYPE_TEXT_PLAIN
+ },
+ method(:onLog)
+ );
+ numCalls = 0;
+ buffer = "";
+ }
+
+ // Clear the debug log over the Internet to start a new track of the watch's runtime
+ // execution.
+ //
+ function clear() {
+ if (Globals.scDebug) {
+ System.println("WebLog clear()");
+ }
+ Communications.makeWebRequest(
+ ClientId.webLogClearUrl,
+ {},
+ {
+ :method => Communications.HTTP_REQUEST_METHOD_GET,
+ :headers => {
+ "Content-Type" => Communications.REQUEST_CONTENT_TYPE_URL_ENCODED
+ },
+ :responseType => Communications.HTTP_RESPONSE_CONTENT_TYPE_TEXT_PLAIN
+ },
+ method(:onClear)
+ );
+ numCalls = 0;
+ buffer = "";
+ }
+
+ // Callback function to print the outcome of a doPrint() method.
+ //
+ function onLog(responseCode as Lang.Number, data as Null or Lang.Dictionary or Lang.String) as Void {
+ if (Globals.scDebug) {
+ if (responseCode != 200) {
+ System.println("WebLog onLog() Failed");
+ System.println("WebLog onLog() Response Code: " + responseCode);
+ System.println("WebLog onLog() Response Data: " + data);
+ }
+ }
+ }
+
+ // Callback function to print the outcome of a clear() method.
+ //
+ function onClear(responseCode as Lang.Number, data as Null or Lang.Dictionary or Lang.String) as Void {
+ if (Globals.scDebug) {
+ if (responseCode != 200) {
+ System.println("WebLog onClear() Failed");
+ System.println("WebLog onClear() Response Code: " + responseCode);
+ System.println("WebLog onClear() Response Data: " + data);
+ }
+ }
+ }
+}
diff --git a/translate.py b/translate.py
index 1c5f013..69ecdfe 100644
--- a/translate.py
+++ b/translate.py
@@ -116,7 +116,7 @@ with open("./resources/strings/strings.xml", "r") as f:
s.string = a.title()
else:
s.string = a
- for s in soup.find(name="strings").findAll(text=lambda text:isinstance(text, Comment)):
+ for s in soup.find(name="strings").findAll(string=lambda text:isinstance(text, Comment)):
s.insert_before(" ")
s.replace_with(Comment(" " + GoogleTranslator(source='en', target=l[1]).translate(s) + " "))