Compare commits
20 Commits
Author | SHA1 | Date | |
---|---|---|---|
28f4ffc70b | |||
e8f2c0d3bb | |||
71cba8c21c | |||
236a4969d7 | |||
e41f451fbc | |||
c13e898e59 | |||
a77870c2eb | |||
155649f162 | |||
1ae4085113 | |||
7a14a65ba3 | |||
adf69d7dec | |||
d105e69484 | |||
184e2ac80e | |||
12c5766818 | |||
b82e63d191 | |||
ed4646511f | |||
fd58625640 | |||
816f2e6399 | |||
f171f913ac | |||
cca73a4069 |
@ -35,3 +35,7 @@
|
||||
| 2.20 | Simplified the code base now that templates have been requested in all menu items. This means the `template` menu item became a superset of `tap`. Therefore the `tap` code has been has been upgraded to include `template` and the latter deprecated. JSON menu definitions continue to support `template` items by instantiating a `tap` menu item, but the schema marks them as deprecated and users should migrate their menu definitions now. Use the [web editor](https://house-of-abbey.github.io/GarminHomeAssistant/web/) for assistance with changes. |
|
||||
| 2.21 | Added 7 new devices (`edge1050`, `enduro3`, `fenix843mm`, `fenix847mm`, `fenix8solar47mm`, `fenix8solar51mm`, `fenixe`) and upgraded the SDK to 7.3.0. Fix for a bug on Edge devices introduced by v2.16 activity reporting improvements. |
|
||||
| 2.22 | Major feature release adding an optional PIN to menu items. This significant new feature has been provided by [moesterheld](https://github.com/moesterheld). Please do not rely on this application for security. Use at your own risk! |
|
||||
| 2.23 | Added "info" menu item for displaying information via a template without a tap or toggle. Essentially like the old 'template' type that was deprecated when all items were amended to display evaluated templates. That action removed the display only items too hastily. Added 5 new devices in the model range Instinct 3 and Instinct E. |
|
||||
| 2.24 | Experiment to prevent new Webhook IDs being created unnecessarily. Reduced the latency for the first menu update. Added 4 new devices: approachs50, descentg2, descentmk1, and gpsmap66. |
|
||||
| 2.25 | 2 Bug fixes. First time startup issues caused by v2.24 change and a fix for pure numbers in returned templates. |
|
||||
| 2.26 | Retry responsive menu fix failed in v2.24. Cosmetic internal class changes. |
|
||||
|
61
README.md
@ -6,12 +6,14 @@ Home | [Switches](examples/Switches.md) | [Actions](examples/Actions.md) | [Temp
|
||||
|
||||
A Garmin application to provide a "dashboard" to control your devices via [Home Assistant](https://www.home-assistant.io/). The application will never be as fully fledged as a Home Assistant dashboard, so it is designed to be good enough for the simple and essential things. Those things that can be activated via an on/off toggle or a tap. That should cover lights, switches, and anything requiring a single press such as an automation. For anything more complicated, e.g. thermostat, it would always be quicker and simpler to reach for your phone or tablet... or the device's own remote control!
|
||||
|
||||
The application is designed around a simple scrollable menu where menu items have been extended to interface with the [Home Assistant API](https://developers.home-assistant.io/docs/api/rest/), e.g. to get the status of switches or lights for display on the toggle menu item, or a text status for an entity (template item). It is possible to nest menus, so there is a menu item to open a sub-menu. This can be arbitrarily deep and nested in the format of a tree of items, although you need to consider if reaching for your phone becomes quicker to select the device what you want to control.
|
||||
The application is designed around a simple scrollable menu where menu items have been extended to interface with the [Home Assistant API](https://developers.home-assistant.io/docs/api/rest/), e.g. to get the status of switches or lights for display on the `toggle` menu item, or a text status for an entity (`info` item). It is possible to nest menus, so there is a menu item to open a sub-menu. This can be arbitrarily deep and nested in the format of a tree of items, although you need to consider if reaching for your phone becomes quicker to select the device what you want to control.
|
||||
|
||||
**The intended audience for this application are those comfortable with configuring a Home Assistant** (e.g. editing the YAML configuration files) and debugging why URLs don't work. It does not require programming skills, but the menu is configured via JSON which feels like "coding". If you are not comfortable with this relatively low level of configuration, you may like to try other Garmin applications instead.
|
||||
**The intended audience for this application are those comfortable with configuring a Home Assistant** (e.g. editing the YAML configuration files) and debugging why URLs don't work. It does not require programming skills, but the menu is configured via JSON which feels like "coding" (more like "describing"). If you are not comfortable with this relatively low level of configuration, you may like to try other Garmin applications instead.
|
||||
|
||||
> [!IMPORTANT]
|
||||
> It is important to note that your Home Assistant instance will need to be accessible via HTTPS with public SSL or all requests from the Garmin will not work. This cannot be a self-signed certificate, it must be a public certificate. You can get one for free from [Let's Encrypt](https://letsencrypt.org/) or you can pay for [Home Assistant cloud](https://www.nabucasa.com/). (You can install a local [Nginx proxy server](https://my.home-assistant.io/redirect/supervisor_addon/?addon=a0d7b954_nginxproxymanager) to manage Let's Encrypt certificates.)
|
||||
> The Garmin SDK allows HTTP requests only to a limited number of domains specified in their app. Therefore, for your Garmin to communicate with your Home Assistant instance, your Home Assistant instance must be accessible via HTTPS (with a public certificate!) or through a local DNS server that overrides one of the whitelisted domains to communicate using HTTP.
|
||||
> To make your Home Assistant instance accessible via HTTPS, you will need a public certificate. You can get one for free from [Let's Encrypt](https://letsencrypt.org/) or you can pay for [Home Assistant cloud](https://www.nabucasa.com/). (You can install a local [Nginx proxy server](https://my.home-assistant.io/redirect/supervisor_addon/?addon=a0d7b954_nginxproxymanager) to manage Let's Encrypt certificates.)
|
||||
> If you use a local DNS server (like [Pi-Hole](https://pi-hole.net/)), you can create a local DNS record for the domain `garmincdn.com` (which is allowed for HTTP in the Garmin SDK) and map it to your Home Assistant instance's IP. You can find additional workarounds for HTTP request restrictions in the Garmin SDK [here](https://www.instructables.com/About-Communication-Between-Garmin-SDK-and-a-Raspb/).
|
||||
|
||||
**If you are struggling with getting the application to work, please consult the [trouble shooting](TroubleShooting.md#menu-configuration-url) guide first.**
|
||||
|
||||
@ -143,32 +145,33 @@ NB. Entity names are not real in case anyone's a hacker ;-).
|
||||
|
||||
The example above illustrates how to configure:
|
||||
|
||||
* Lights or switches (toggle), <img src="images/toggle_icon.png" height="20">
|
||||
* Enables for automations (toggle), <img src="images/toggle_icon.png" height="20">
|
||||
* Script invocation (tap)
|
||||
* Service invocation, e.g. Scene setting, (tap)
|
||||
* A sub-menu to open (group)
|
||||
* You can also display the status of devices (template) and add an optional 'tap' action. However that's a bit more involved and has its own [examples page](examples/Templates.md). Add those later!
|
||||
* Lights or switches (`toggle`), <img src="images/toggle_icon.png" height="20">
|
||||
* Enables for automations (`toggle`), <img src="images/toggle_icon.png" height="20">
|
||||
* Script invocation (`tap`)
|
||||
* Service invocation, e.g. Scene setting, (`tap`)
|
||||
* A sub-menu to open (`group`)
|
||||
* You can also display the status of devices (`info`) which is essentially a `tap` with no action
|
||||
* All menu items can display the results of evaluating [templates](examples/Templates.md).
|
||||
|
||||
The following table indicates how Home Assistant entity types can map to the Garmin applications menu types. Presently, an automation is the only one that can be either a 'tap' or a 'toggle'.
|
||||
The following table indicates how Home Assistant entity types can map to the Garmin applications menu types. Presently, an automation is the only one that can be either a `tap` or a `toggle`.
|
||||
|
||||
| HA Entity Type | Tap | Toggle | Template (custom status text with optional tap action) |
|
||||
|------------------|:---:|:------:|:------------------------------------------------------:|
|
||||
| Switch | ❌ | ✅ | ✅<br>Separate on and off, or anything in between |
|
||||
| Light | ❌ | ✅ | ✅<br>Separate on and off, or anything in between |
|
||||
| Automation | ✅ | ✅ | ✅ |
|
||||
| Script | ✅ | ❌ | ✅ |
|
||||
| Scene | ✅ | ❌ | ✅ |
|
||||
| Sensor | ❌ | ❌ | ✅ |
|
||||
| Binary Sensor | ❌ | ❌ | ✅ |
|
||||
| Any other entity | ❌ | ❌ | ✅ |
|
||||
| Any service | ✅ | ❌ | ✅ |
|
||||
| HA Entity Type | Tap | Toggle | Info (status)|
|
||||
|------------------|:---:|:------:|:------------:|
|
||||
| Switch | ❌ | ✅ | ✅ |
|
||||
| Light | ❌ | ✅ | ✅ |
|
||||
| Automation | ✅ | ✅ | ❌ |
|
||||
| Script | ✅ | ❌ | ❌ |
|
||||
| Scene | ✅ | ❌ | ❌ |
|
||||
| Sensor | ❌ | ❌ | ✅ |
|
||||
| Binary Sensor | ❌ | ❌ | ✅ |
|
||||
| Any other entity | ❌ | ❌ | ✅ |
|
||||
| Any service | ✅ | ❌ | ❌ |
|
||||
|
||||
Templates need separate HTTP requests to update their status and send an action. Only the toggle items have the on/off <img src="images/toggle_icon.png" height="20"> icon. A Tap does not require a status update and hence does not require the associated HTTP GET request. NB. All 'tap' items must specify a 'service' tag.
|
||||
Multiple templates are evaluated in a single HTTP request to update their status. Only the toggle items have the on/off <img src="images/toggle_icon.png" height="20"> icon. NB. All `tap` items must specify a `service` tag in the `tap_action` object (see example below).
|
||||
|
||||
You can now specify alternative texts to use instead of "On" and "Off", e.g. "Locked" and "Unlocked" or "Open" and "Closed" through the use of a [template menu item](examples/Templates.md). But wouldn't having locks operated from your watch be a security concern ;-) ?
|
||||
|
||||
The [schema](https://raw.githubusercontent.com/house-of-abbey/GarminHomeAssistant/main/config.schema.json) is checked by using a URL directly back to this GitHub source repository, so you do not need to install that file. You can just copy & paste your entity names from the YAML configuration files used to configure Home Assistant. With a submenu, there's a difference between "title" and "name". The "name" goes on the menu item, and the "title" at the head of the submenu. If your dashboard definition fails to meet the schema, the application will simply drop items with the wrong field names without warning to protect itself.
|
||||
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 to protect itself.
|
||||
|
||||
### Old deprecated format
|
||||
|
||||
@ -196,13 +199,13 @@ The above should be replaced by the following:
|
||||
}
|
||||
```
|
||||
|
||||
This allows the `confirm` field to be accommodated in the `tap_action` along side the `service` tag, and follows the Home Assistant YAML format more closely.
|
||||
This allows the `confirm` and `pin` fields to be accommodated in the `tap_action` along side the `service` tag, and follows the Home Assistant YAML format more closely.
|
||||
|
||||
### More Examples
|
||||
|
||||
- [Switches](examples/Switches.md)
|
||||
- [Actions](examples/Actions.md)
|
||||
- [Templates](examples/Templates.md)
|
||||
* [Switches](examples/Switches.md)
|
||||
* [Actions](examples/Actions.md)
|
||||
* [Templates](examples/Templates.md)
|
||||
|
||||
## Editing the JSON file
|
||||
|
||||
@ -326,8 +329,8 @@ The `id` attribute values are taken from the same names used in [`strings.xml`](
|
||||
|
||||
6. We are unable to support Edge 540, Edge 840 and Edge 1050 devices at this time. The simulation of these devices has two unexpected errors when toggling or executing taps. We get both `Communications.NETWORK_RESPONSE_OUT_OF_MEMORY` and `Communications.BLE_QUEUE_FULL` even though the memory usage is about 6% of the available RAM. Based on a lead from user @Petucky, both devices are being re-enabled as testing on a real Edge 840 device has proven successful, however we remain unable to support either devices until the simulator is fixed.
|
||||
|
||||
7. We are unable to support HTTP without HTTPS. This is a limitation placed upon us by the Connect IQ API which for security reasons refuses to work with HTTP requests. There is nothing developers can do about this limitation. You will have to put an HTTPS proxy in front of your local Home Assistant to work with this application. See the [Trouble Shooting](TroubleShooting.md#do-it-yourself-setup) guide for an example setup. We would appreciate it if users did not leave poor reviews for the lack of this feature which is beyond our control to fix.
|
||||
7. We are unable to support HTTP natively (without the workaround specified earlier). This is a limitation placed upon us by the Connect IQ API which for security reasons refuses to work with HTTP requests. There is nothing developers can do about this limitation. See the [Trouble Shooting](TroubleShooting.md#do-it-yourself-setup) guide for an example setup. We would appreciate it if users did not leave poor reviews for the lack of this feature which is beyond our control to fix.
|
||||
|
||||
8. There is a [bug in Garmin Express so that when you use that software to amend the application's settings](https://github.com/house-of-abbey/GarminHomeAssistant/issues/194), the page appears in a random language not of your choice. I would like to thank user [heviiguy](https://github.com/heviiguy) for his work researching the issue, leading to these references that indicate the authors of Garmin Home Assistant cannot resolve this issue as its a bug in Garmin Express that Garmin are refusing to believe exists! See these pages for details:
|
||||
- [Garmin Express - Wrong Language](https://forums.garmin.com/developer/connect-iq/i/bug-reports/garmin-express---wrong-language)
|
||||
- [Incorrect language displayed for custom data fields](https://forums.garmin.com/developer/connect-iq/f/discussion/388137/incorrect-language-displayed-for-custom-data-fields)
|
||||
- [Incorrect language displayed for custom data fields](https://forums.garmin.com/developer/connect-iq/f/discussion/388137/incorrect-language-displayed-for-custom-data-fields)
|
||||
|
@ -26,7 +26,7 @@ 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
|
||||
set DEST=bin
|
||||
|
||||
rem Device for simulation
|
||||
set DEVICE=venu2
|
||||
@ -72,17 +72,19 @@ rem -x,--excludes <arg> Add annotations to the exclude list (deprecated)
|
||||
rem -y,--private-key <arg> Private key to sign builds with
|
||||
rem -z,--rez <arg> Resource files (deprecated)
|
||||
|
||||
title Compiling for %DEVICE%
|
||||
|
||||
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 %DEST% (
|
||||
rmdir /s /q %DEST%
|
||||
)
|
||||
|
||||
if exist %SRC%\export\HomeAssistant*.iq (
|
||||
del /f /q %SRC%\export\HomeAssistant*.iq
|
||||
rem The above may not successfully delete the directory if there are locked files
|
||||
if not exist %DEST% (
|
||||
mkdir %DEST%
|
||||
)
|
||||
|
||||
echo.
|
||||
|
@ -70,7 +70,7 @@
|
||||
"const": "template",
|
||||
"deprecated": true,
|
||||
"title": "Schema change:",
|
||||
"description": "Use 'tap' instead."
|
||||
"description": "Use 'info' or 'tap' instead."
|
||||
}
|
||||
},
|
||||
"required": ["name", "content", "type"],
|
||||
@ -93,7 +93,7 @@
|
||||
"const": "template",
|
||||
"deprecated": true,
|
||||
"title": "Schema change:",
|
||||
"description": "Use 'tap' instead."
|
||||
"description": "Use 'info' or 'tap' instead."
|
||||
},
|
||||
"tap_action": {
|
||||
"$ref": "#/$defs/tap_action"
|
||||
@ -104,6 +104,23 @@
|
||||
}
|
||||
]
|
||||
},
|
||||
"info": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"name": {
|
||||
"$ref": "#/$defs/name"
|
||||
},
|
||||
"content": {
|
||||
"$ref": "#/$defs/content"
|
||||
},
|
||||
"type": {
|
||||
"$ref": "#/$defs/type",
|
||||
"const": "info"
|
||||
}
|
||||
},
|
||||
"required": ["name", "content", "type"],
|
||||
"additionalProperties": false
|
||||
},
|
||||
"tap": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
@ -169,7 +186,7 @@
|
||||
},
|
||||
"type": {
|
||||
"title": "Menu item type",
|
||||
"description": "One of 'tap', 'toggle' or 'group'."
|
||||
"description": "One of 'info', 'tap', 'toggle' or 'group'."
|
||||
},
|
||||
"items": {
|
||||
"type": "array",
|
||||
@ -185,6 +202,9 @@
|
||||
{
|
||||
"$ref": "#/$defs/tap"
|
||||
},
|
||||
{
|
||||
"$ref": "#/$defs/info"
|
||||
},
|
||||
{
|
||||
"$ref": "#/$defs/group"
|
||||
}
|
||||
@ -192,7 +212,7 @@
|
||||
}
|
||||
},
|
||||
"name": {
|
||||
"title": "Your familiar name",
|
||||
"title": "Your familiar name to display in the menu item",
|
||||
"type": "string"
|
||||
},
|
||||
"entity": {
|
||||
|
@ -70,3 +70,8 @@ Note that for notify events, you _must_ not supply an `entity_id` or the API cal
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
> [!IMPORTANT]
|
||||
> Be careful with the value of the `service` field.
|
||||
|
||||
Note that the `service` field will need to be a locally custom `script.<something>` as soon as any `data` fields are populated and not something more generic like `script.turn_on`. If the `service` field is wrong, the application will fail with a [`Communications.INVALID_HTTP_BODY_IN_NETWORK_RESPONSE`](https://developer.garmin.com/connect-iq/api-docs/Toybox/Communications.html) error in the response from your Home Assistant and show the error message as _"No JSON returned from HTTP request"_ on your device. In the [web-based editor](https://house-of-abbey.github.io/GarminHomeAssistant/web/) you can use the standard developer tools to observe an `HTTP 400` error which the application does not see. Here we are limited by the [Garmin Connect IQ](https://developer.garmin.com/connect-iq/overview/) software development kit (SDK). We do not have enough information at the point of execution in the application to determine the cause of the error. Nor is there an immediately obvious way of identifying this issue using the JSON schema checks.
|
||||
|
@ -20,7 +20,7 @@ In this example we get the battery level of the device and add the percent sign.
|
||||
```json
|
||||
{
|
||||
"name": "Phone",
|
||||
"type": "template",
|
||||
"type": "info",
|
||||
"content": "{{ states('sensor.<device>_battery_level') }}%"
|
||||
}
|
||||
```
|
||||
@ -32,17 +32,17 @@ The first two keep to the simple proposal above. The last combines them into a s
|
||||
```json
|
||||
{
|
||||
"name": "Hall Temp",
|
||||
"type": "template",
|
||||
"type": "info",
|
||||
"content": "{{ states('sensor.hallway_temperature') }}°C"
|
||||
},
|
||||
{
|
||||
"name": "Hall Humidity",
|
||||
"type": "template",
|
||||
"type": "info",
|
||||
"content": "{{ states('sensor.hallway_humidity') }}%"
|
||||
},
|
||||
{
|
||||
"name": "Hallway",
|
||||
"type": "template",
|
||||
"type": "info",
|
||||
"content": "{{ states('sensor.hallway_temperature') }}°C {{ states('sensor.hallway_humidity') }}%"
|
||||
}
|
||||
```
|
||||
@ -52,7 +52,7 @@ In order to keep the formatting of floating point numbers under control, you mig
|
||||
```json
|
||||
{
|
||||
"name": "Hallway",
|
||||
"type": "template",
|
||||
"type": "info",
|
||||
"content": "T:{{ '%.1f' | format(states('sensor.hallway_temperature') | float) }}°C, H:{{ '%.1f' | format(states('sensor.hallway_humidity') | float) }}%"
|
||||
},
|
||||
```
|
||||
@ -62,12 +62,12 @@ Where your device supports unicode characters these example may work.
|
||||
```json
|
||||
{
|
||||
"name": "Charge",
|
||||
"type": "template",
|
||||
"type": "info",
|
||||
"content": "☎ {{ states('sensor.my_phone_battery_level') }}%{% if is_state('binary_sensor.my_phone_is_charging', 'on') %}⚡{% endif %}, ⏳ {{ '%.0f'|format(states('sensor.my_watch_battery_level') | float) }}%{% if is_state('binary_binary_sensor.my_watch_battery_is_charging', 'on') %}⚡{% endif %}"
|
||||
},
|
||||
{
|
||||
"name": "Hallway",
|
||||
"type": "template",
|
||||
"type": "info",
|
||||
"content": "🌡{% if is_state('sensor.hallway_temperature', 'unavailable') %}-{% else %}{{ '%.1f'|format(states('sensor.hallway_temperature')|float) }}°C{% if is_state_attr('climate.hallway', 'hvac_action', 'heating') or is_state_attr('climate.hallway', 'hvac_action', 'preheating') -%}🔥{%- endif %}{% endif %}, 💧{% if is_state('sensor.hallway_humidity', 'unavailable') %}-{% else %}{{ '%.1f'|format(states('sensor.hallway_humidity')|float) }}%{% endif %}"
|
||||
}
|
||||
```
|
||||
@ -83,7 +83,7 @@ In this example we get the battery level of the device and add the percent sign.
|
||||
```json
|
||||
{
|
||||
"name": "Phone",
|
||||
"type": "template",
|
||||
"type": "info",
|
||||
"content": "{{ states('sensor.<device>_battery_level') }}%{% if is_state('binary_sensor.<device>_is_charging', 'on') %}+{% endif %}"
|
||||
}
|
||||
```
|
||||
@ -93,7 +93,7 @@ Here we also use the else clause as well to give proper text instead of just `on
|
||||
```json
|
||||
{
|
||||
"name": "Garage Doors",
|
||||
"type": "template",
|
||||
"type": "info",
|
||||
"content": "{% if is_state('binary_sensor.<door-0>', 'on') %}Open{% else %}Closed{% endif %} {% if is_state('binary_sensor.<door-1>', 'on') %}Open{% else %}Closed{% endif %}"
|
||||
}
|
||||
```
|
||||
@ -113,7 +113,7 @@ Note: Only when you use the `tap_action` field do you also need to include the `
|
||||
{
|
||||
"entity": "cover.garage_door",
|
||||
"name": "Garage Door",
|
||||
"type": "template",
|
||||
"type": "tap",
|
||||
"content": "{% if is_state('binary_sensor.garage_connected', 'on') %}{{state_translated('cover.garage_door')}} - {{state_attr('cover.garage_door', 'current_position')}}%{%else%}Unconnected{% endif %}",
|
||||
"tap_action": {
|
||||
"service": "cover.toggle",
|
||||
@ -150,7 +150,7 @@ Here we generate a bar graph of the battery level. We use the following steps to
|
||||
```json
|
||||
{
|
||||
"name": "Phone",
|
||||
"type": "template",
|
||||
"type": "info",
|
||||
"content": "{{ states('sensor.<device>_battery_level') }}%{% if is_state('binary_sensor.<device>_is_charging', 'on') %}+{% endif %} {{ '#' * (((states('sensor.<device>_battery_level') | int) / 100 * <width>) | int) }}{{ '_' * (<width> - (((states('sensor.<device>_battery_level') | int) / 100 * <width>) | int)) }}"
|
||||
}
|
||||
```
|
||||
@ -164,13 +164,13 @@ An example of a dimmer light with 4 brightness settings 0..3. Here our light wor
|
||||
"items": [
|
||||
{
|
||||
"name": "LEDs",
|
||||
"type": "template",
|
||||
"type": "info",
|
||||
"content": "{% if not (is_state('light.green_house', 'off') or is_state('light.green_house', 'unavailable')) %}{{ (((state_attr('light.green_house', 'brightness') | float) / 255 * 100) | round(0)) | int }}%{% else %}Off{% endif %}"
|
||||
},
|
||||
{
|
||||
"entity": "light.green_house",
|
||||
"name": "LEDs 0",
|
||||
"type": "template",
|
||||
"type": "tap",
|
||||
"content": "{% if not (is_state('light.green_house', 'off') or is_state('light.green_house', 'unavailable')) %}{{ (((state_attr('light.green_house', 'brightness') | float) / 255 * 100) | round(0)) | int }}%{% else %}Off{% endif %}",
|
||||
"tap_action": {
|
||||
"service": "light.turn_on",
|
||||
@ -193,7 +193,7 @@ An example of a dimmer light with 4 brightness settings 0..3. Here our light wor
|
||||
{
|
||||
"entity": "light.green_house",
|
||||
"name": "LEDs 2",
|
||||
"type": "template",
|
||||
"type": "tap",
|
||||
"content": "{% if not (is_state('light.green_house', 'off') or is_state('light.green_house', 'unavailable')) %}{{ (((state_attr('light.green_house', 'brightness') | float) / 255 * 100) | round(0)) | int }}%{% else %}Off{% endif %}",
|
||||
"tap_action": {
|
||||
"service": "light.turn_on",
|
||||
@ -205,7 +205,7 @@ An example of a dimmer light with 4 brightness settings 0..3. Here our light wor
|
||||
{
|
||||
"entity": "light.green_house",
|
||||
"name": "LEDs 3",
|
||||
"type": "template",
|
||||
"type": "tap",
|
||||
"content": "{% if not (is_state('light.green_house', 'off') or is_state('light.green_house', 'unavailable')) %}{{ (((state_attr('light.green_house', 'brightness') | float) / 255 * 100) | round(0))| int }}%{% else %}Off{% endif %}",
|
||||
"tap_action": {
|
||||
"service": "light.turn_on",
|
||||
|
11
manifest.xml
@ -30,13 +30,14 @@
|
||||
-->
|
||||
<iq:application id="98c36259-498a-4458-9cef-74a273ad2bc3" type="watch-app" name="@Strings.AppName" entry="HomeAssistantApp" launcherIcon="@Drawables.LauncherIcon" minApiLevel="3.1.0">
|
||||
<!--
|
||||
Use the following from the Visual Studio Code comand palette to edit
|
||||
Use the following from the Visual Studio Code command palette to edit
|
||||
the build targets:
|
||||
"Monkey C: Set Products by Product Category" - Lets you add all products
|
||||
that belong to the same product category
|
||||
"Monkey C: Edit Products" - Lets you add or remove any product
|
||||
-->
|
||||
<iq:products>
|
||||
<iq:product id="approachs50"/>
|
||||
<iq:product id="approachs7042mm"/>
|
||||
<iq:product id="approachs7047mm"/>
|
||||
<iq:product id="d2air"/>
|
||||
@ -46,6 +47,8 @@
|
||||
<iq:product id="d2deltas"/>
|
||||
<iq:product id="d2mach1"/>
|
||||
<iq:product id="descentg1"/>
|
||||
<iq:product id="descentg2"/>
|
||||
<iq:product id="descentmk1"/>
|
||||
<iq:product id="descentmk2"/>
|
||||
<iq:product id="descentmk2s"/>
|
||||
<iq:product id="descentmk343mm"/>
|
||||
@ -113,11 +116,17 @@
|
||||
<iq:product id="fr945lte"/>
|
||||
<iq:product id="fr955"/>
|
||||
<iq:product id="fr965"/>
|
||||
<iq:product id="gpsmap66"/>
|
||||
<iq:product id="gpsmap67"/>
|
||||
<iq:product id="instinct2"/>
|
||||
<iq:product id="instinct2s"/>
|
||||
<iq:product id="instinct2x"/>
|
||||
<iq:product id="instinct3amoled45mm"/>
|
||||
<iq:product id="instinct3amoled50mm"/>
|
||||
<iq:product id="instinct3solar45mm"/>
|
||||
<iq:product id="instinctcrossover"/>
|
||||
<iq:product id="instincte40mm"/>
|
||||
<iq:product id="instincte45mm"/>
|
||||
<iq:product id="legacyherocaptainmarvel"/>
|
||||
<iq:product id="legacyherofirstavenger"/>
|
||||
<iq:product id="legacysagadarthvader"/>
|
||||
|
@ -31,9 +31,11 @@ project.manifest = manifest.xml
|
||||
#
|
||||
# The icons need to scale as a ratio of screen size 48:416 pixels
|
||||
#
|
||||
# Icon 55 53 48 46 42 37 32 30 28 26 24 21 18
|
||||
# Screen 480 454 416 390 360 320 280 260 240 218 208 176 156
|
||||
# Icon 55 53 48 46 42 37 32 30 28 26 24 21 19 18
|
||||
# Screen 480 454 416 390 360 320 280 260 240 218 208 176 166 156
|
||||
|
||||
# Screen Size 390x390 launcher icon size 56x56
|
||||
approachs50.resourcePath = $(approachs50.resourcePath);resources-launcher-56-56;resources-icons-46
|
||||
# Screen Size 390x390 launcher icon size 70x70
|
||||
approachs7042mm.resourcePath = $(approachs7042mm.resourcePath);resources-launcher-70-70;resources-icons-46
|
||||
# Screen Size 454x454 launcher icon size 80x80
|
||||
@ -50,6 +52,10 @@ d2deltas.resourcePath = $(d2deltas.resourcePath);resources-launcher-40-40;resour
|
||||
d2mach1.resourcePath = $(d2mach1.resourcePath);resources-launcher-60-60;resources-icons-48
|
||||
# Screen Size 176x176 launcher icon size 62x62
|
||||
descentg1.resourcePath = $(descentg1.resourcePath);resources-launcher-62-62;resources-icons-21
|
||||
# Screen Size 390x390 launcher icon size 60x60
|
||||
descentg2.resourcePath = $(descentg2.resourcePath);resources-launcher-60-60;resources-icons-46
|
||||
# Screen Size 240x240 launcher icon size 40x40
|
||||
descentmk1.resourcePath = $(descentmk1.resourcePath);resources-launcher-40-40;resources-icons-28
|
||||
# Screen Size 280x280 launcher icon size 40x40
|
||||
descentmk2.resourcePath = $(descentmk2.resourcePath);resources-launcher-40-40;resources-icons-32
|
||||
# Screen Size 240x240 launcher icon size 40x40
|
||||
@ -164,15 +170,27 @@ fr955.resourcePath = $(fr955.resourcePath);resources-launcher-40-40;resources-ic
|
||||
# Screen Size 454x454 launcher icon size 65x65
|
||||
fr965.resourcePath = $(fr965.resourcePath);resources-launcher-65-65;resources-icons-53
|
||||
# Screen Size 240x400 launcher icon size 38x33
|
||||
gpsmap66.resourcePath = $(gpsmap66.resourcePath);resources-launcher-33-33;resources-icons-28
|
||||
# Screen Size 240x400 launcher icon size 38x33
|
||||
gpsmap67.resourcePath = $(gpsmap67.resourcePath);resources-launcher-33-33;resources-icons-28
|
||||
# Screen Size 176x176 launcher icon size 62x62
|
||||
instinct2.resourcePath = $(instinct2.resourcePath);resources-launcher-62-62;resources-icons-21
|
||||
instinct2.resourcePath = $(instinct2.resourcePath);resources-launcher-62-62;resources-icons-21-w
|
||||
# Screen Size 163x156 launcher icon size 54x54
|
||||
instinct2s.resourcePath = $(instinct2s.resourcePath);resources-launcher-54-54;resources-icons-18
|
||||
instinct2s.resourcePath = $(instinct2s.resourcePath);resources-launcher-54-54;resources-icons-18-w
|
||||
# Screen Size 176x176 launcher icon size 62x62
|
||||
instinct2x.resourcePath = $(instinct2x.resourcePath);resources-launcher-62-62;resources-icons-21
|
||||
instinct2x.resourcePath = $(instinct2x.resourcePath);resources-launcher-62-62;resources-icons-21-w
|
||||
# Screen Size 390x390 launcher icon size 60x60, but the icon size used here is reduced as the menu items were clipped.
|
||||
instinct3amoled45mm.resourcePath = $(instinct3amoled45mm.resourcePath);resources-launcher-60-60;resources-icons-32
|
||||
# Screen Size 416x416 launcher icon size 60x60, but the icon size used here is reduced as the menu items were clipped.
|
||||
instinct3amoled50mm.resourcePath = $(instinct3amoled50mm.resourcePath);resources-launcher-60-60;resources-icons-34
|
||||
# Screen Size 176x176 launcher icon size 62x62
|
||||
instinct3solar45mm.resourcePath = $(instinct3solar45mm.resourcePath);resources-launcher-62-62;resources-icons-18-w
|
||||
# Screen Size 176x176 launcher icon size 26x26
|
||||
instinctcrossover.resourcePath = $(instinctcrossover.resourcePath);resources-launcher-26-26;resources-icons-21
|
||||
instinctcrossover.resourcePath = $(instinctcrossover.resourcePath);resources-launcher-26-26;resources-icons-21-w
|
||||
# Screen Size 166x166 launcher icon size 52x52, but the icon size used here is reduced as the menu items were clipped.
|
||||
instincte40mm.resourcePath = $(instincte40mm.resourcePath);resources-launcher-52-52;resources-icons-18-w
|
||||
# Screen Size 176x176 launcher icon size 62x62, but the icon size used here is reduced as the menu items were clipped.
|
||||
instincte45mm.resourcePath = $(instincte45mm.resourcePath);resources-launcher-62-62;resources-icons-18-w
|
||||
# Screen Size 218x218 launcher icon size 30x30
|
||||
legacyherocaptainmarvel.resourcePath = $(legacyherocaptainmarvel.resourcePath);resources-launcher-30-30;resources-icons-26
|
||||
# Screen Size 260x260 launcher icon size 35x35
|
||||
|
23
resources-icons-18-w/drawables.xml
Normal file
@ -0,0 +1,23 @@
|
||||
<!--
|
||||
|
||||
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
|
||||
|
||||
References:
|
||||
* https://fonts.google.com/icons
|
||||
|
||||
-->
|
||||
|
||||
<drawables>
|
||||
<bitmap id="ErrorIcon" filename="error.svg"/>
|
||||
<bitmap id="GroupTypeIcon" filename="group_type.svg"/>
|
||||
<bitmap id="TapTypeIcon" filename="tap_type.svg"/>
|
||||
<bitmap id="InfoTypeIcon" filename="info_type.svg"/>
|
||||
</drawables>
|
1
resources-icons-18-w/error.svg
Normal file
@ -0,0 +1 @@
|
||||
<svg height="18" viewBox="0 0 48 48" width="18" xmlns="http://www.w3.org/2000/svg"><path d="M24 34q.7 0 1.175-.475.475-.475.475-1.175 0-.7-.475-1.175Q24.7 30.7 24 30.7q-.7 0-1.175.475-.475.475-.475 1.175 0 .7.475 1.175Q23.3 34 24 34Zm-1.35-7.65h3V13.7h-3ZM24 44q-4.1 0-7.75-1.575-3.65-1.575-6.375-4.3-2.725-2.725-4.3-6.375Q4 28.1 4 23.95q0-4.1 1.575-7.75 1.575-3.65 4.3-6.35 2.725-2.7 6.375-4.275Q19.9 4 24.05 4q4.1 0 7.75 1.575 3.65 1.575 6.35 4.275 2.7 2.7 4.275 6.35Q44 19.85 44 24q0 4.1-1.575 7.75-1.575 3.65-4.275 6.375t-6.35 4.3Q28.15 44 24 44Zm.05-3q7.05 0 12-4.975T41 23.95q0-7.05-4.95-12T24 7q-7.05 0-12.025 4.95Q7 16.9 7 24q0 7.05 4.975 12.025Q16.95 41 24.05 41ZM24 24Z" fill="white" stroke="white"/></svg>
|
After Width: | Height: | Size: 716 B |
7
resources-icons-18-w/group_type.svg
Normal file
@ -0,0 +1,7 @@
|
||||
<svg height="18" viewBox="0 0 200 500" width="18" xmlns="http://www.w3.org/2000/svg">
|
||||
<g transform="matrix(1, 0, 0, 1, 0, 0)">
|
||||
<rect fill="white" height="100" rx="40" ry="40" width="200" x="0" y="0"/>
|
||||
<rect fill="white" height="100" rx="40" ry="40" width="200" x="0" y="200"/>
|
||||
<rect fill="white" height="100" rx="40" ry="40" width="200" x="0" y="400"/>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 364 B |
1
resources-icons-18-w/info_type.svg
Normal file
@ -0,0 +1 @@
|
||||
<svg height="18" viewBox="0 -960 960 960" width="18" xmlns="http://www.w3.org/2000/svg"><path d="M440-280h80v-240h-80v240Zm40-320q17 0 28.5-11.5T520-640q0-17-11.5-28.5T480-680q-17 0-28.5 11.5T440-640q0 17 11.5 28.5T480-600Zm0 520q-83 0-156-31.5T197-197q-54-54-85.5-127T80-480q0-83 31.5-156T197-763q54-54 127-85.5T480-880q83 0 156 31.5T763-763q54 54 85.5 127T880-480q0 83-31.5 156T763-197q-54 54-127 85.5T480-80Zm0-80q134 0 227-93t93-227q0-134-93-227t-227-93q-134 0-227 93t-93 227q0 134 93 227t227 93Zm0-320Z" fill="white" stroke="white"/></svg>
|
After Width: | Height: | Size: 545 B |
1
resources-icons-18-w/tap_type.svg
Normal file
@ -0,0 +1 @@
|
||||
<svg height="18" viewBox="0 -960 960 960" width="18" xmlns="http://www.w3.org/2000/svg"><path d="M445-80q-29 0-56-12t-45-35L127-403l21-23q14-15 34.5-18.5T221-438l99 53v-365q0-12.75 8.675-21.375 8.676-8.625 21.5-8.625 12.825 0 21.325 8.625T380-750v465l-144-77 156 198q10 12 23.76 18 13.76 6 29.24 6h205q38 0 64-26t26-64v-170q0-25.5-17.25-42.75T680-460H460v-60h219.646q50.148 0 85.251 35T800-400v170q0 63-43.5 106.5T650-80H445ZM203-665q-11.074-18.754-17.037-40.492Q180-727.229 180-750.246 180-821 229.725-870.5T350-920q70.55 0 120.275 49.738Q520-820.524 520-749.956q0 22.956-5.963 44.614Q508.074-683.685 497-665l-52-30q7-12 11-26t4-29.478Q460-796 427.882-828q-32.117-32-78-32Q304-860 272-827.917 240-795.833 240-750q0 15 4 29t11 26l-52 30Zm285 335Z" fill="white" stroke="white"/></svg>
|
After Width: | Height: | Size: 783 B |
23
resources-icons-21-w/drawables.xml
Normal file
@ -0,0 +1,23 @@
|
||||
<!--
|
||||
|
||||
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
|
||||
|
||||
References:
|
||||
* https://fonts.google.com/icons
|
||||
|
||||
-->
|
||||
|
||||
<drawables>
|
||||
<bitmap id="ErrorIcon" filename="error.svg"/>
|
||||
<bitmap id="GroupTypeIcon" filename="group_type.svg"/>
|
||||
<bitmap id="TapTypeIcon" filename="tap_type.svg"/>
|
||||
<bitmap id="InfoTypeIcon" filename="info_type.svg"/>
|
||||
</drawables>
|
1
resources-icons-21-w/error.svg
Normal file
@ -0,0 +1 @@
|
||||
<svg height="21" viewBox="0 0 48 48" width="21" xmlns="http://www.w3.org/2000/svg"><path d="M24 34q.7 0 1.175-.475.475-.475.475-1.175 0-.7-.475-1.175Q24.7 30.7 24 30.7q-.7 0-1.175.475-.475.475-.475 1.175 0 .7.475 1.175Q23.3 34 24 34Zm-1.35-7.65h3V13.7h-3ZM24 44q-4.1 0-7.75-1.575-3.65-1.575-6.375-4.3-2.725-2.725-4.3-6.375Q4 28.1 4 23.95q0-4.1 1.575-7.75 1.575-3.65 4.3-6.35 2.725-2.7 6.375-4.275Q19.9 4 24.05 4q4.1 0 7.75 1.575 3.65 1.575 6.35 4.275 2.7 2.7 4.275 6.35Q44 19.85 44 24q0 4.1-1.575 7.75-1.575 3.65-4.275 6.375t-6.35 4.3Q28.15 44 24 44Zm.05-3q7.05 0 12-4.975T41 23.95q0-7.05-4.95-12T24 7q-7.05 0-12.025 4.95Q7 16.9 7 24q0 7.05 4.975 12.025Q16.95 41 24.05 41ZM24 24Z" fill="white" stroke="white"/></svg>
|
After Width: | Height: | Size: 716 B |
7
resources-icons-21-w/group_type.svg
Normal file
@ -0,0 +1,7 @@
|
||||
<svg height="21" viewBox="0 0 200 500" width="21" xmlns="http://www.w3.org/2000/svg">
|
||||
<g transform="matrix(1, 0, 0, 1, 0, 0)">
|
||||
<rect fill="white" height="100" rx="40" ry="40" width="200" x="0" y="0"/>
|
||||
<rect fill="white" height="100" rx="40" ry="40" width="200" x="0" y="200"/>
|
||||
<rect fill="white" height="100" rx="40" ry="40" width="200" x="0" y="400"/>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 364 B |
1
resources-icons-21-w/info_type.svg
Normal file
@ -0,0 +1 @@
|
||||
<svg height="21" viewBox="0 -960 960 960" width="21" xmlns="http://www.w3.org/2000/svg"><path d="M440-280h80v-240h-80v240Zm40-320q17 0 28.5-11.5T520-640q0-17-11.5-28.5T480-680q-17 0-28.5 11.5T440-640q0 17 11.5 28.5T480-600Zm0 520q-83 0-156-31.5T197-197q-54-54-85.5-127T80-480q0-83 31.5-156T197-763q54-54 127-85.5T480-880q83 0 156 31.5T763-763q54 54 85.5 127T880-480q0 83-31.5 156T763-197q-54 54-127 85.5T480-80Zm0-80q134 0 227-93t93-227q0-134-93-227t-227-93q-134 0-227 93t-93 227q0 134 93 227t227 93Zm0-320Z" fill="white" stroke="white"/></svg>
|
After Width: | Height: | Size: 545 B |
1
resources-icons-21-w/tap_type.svg
Normal file
@ -0,0 +1 @@
|
||||
<svg height="21" viewBox="0 -960 960 960" width="21" xmlns="http://www.w3.org/2000/svg"><path d="M445-80q-29 0-56-12t-45-35L127-403l21-23q14-15 34.5-18.5T221-438l99 53v-365q0-12.75 8.675-21.375 8.676-8.625 21.5-8.625 12.825 0 21.325 8.625T380-750v465l-144-77 156 198q10 12 23.76 18 13.76 6 29.24 6h205q38 0 64-26t26-64v-170q0-25.5-17.25-42.75T680-460H460v-60h219.646q50.148 0 85.251 35T800-400v170q0 63-43.5 106.5T650-80H445ZM203-665q-11.074-18.754-17.037-40.492Q180-727.229 180-750.246 180-821 229.725-870.5T350-920q70.55 0 120.275 49.738Q520-820.524 520-749.956q0 22.956-5.963 44.614Q508.074-683.685 497-665l-52-30q7-12 11-26t4-29.478Q460-796 427.882-828q-32.117-32-78-32Q304-860 272-827.917 240-795.833 240-750q0 15 4 29t11 26l-52 30Zm285 335Z" fill="white" stroke="white"/></svg>
|
After Width: | Height: | Size: 783 B |
23
resources-icons-34/drawables.xml
Normal file
@ -0,0 +1,23 @@
|
||||
<!--
|
||||
|
||||
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
|
||||
|
||||
References:
|
||||
* https://fonts.google.com/icons
|
||||
|
||||
-->
|
||||
|
||||
<drawables>
|
||||
<bitmap id="ErrorIcon" filename="error.svg"/>
|
||||
<bitmap id="GroupTypeIcon" filename="group_type.svg"/>
|
||||
<bitmap id="TapTypeIcon" filename="tap_type.svg"/>
|
||||
<bitmap id="InfoTypeIcon" filename="info_type.svg"/>
|
||||
</drawables>
|
1
resources-icons-34/error.svg
Normal file
@ -0,0 +1 @@
|
||||
<svg height="34" viewBox="0 0 48 48" width="34" xmlns="http://www.w3.org/2000/svg"><path d="M24 34q.7 0 1.175-.475.475-.475.475-1.175 0-.7-.475-1.175Q24.7 30.7 24 30.7q-.7 0-1.175.475-.475.475-.475 1.175 0 .7.475 1.175Q23.3 34 24 34Zm-1.35-7.65h3V13.7h-3ZM24 44q-4.1 0-7.75-1.575-3.65-1.575-6.375-4.3-2.725-2.725-4.3-6.375Q4 28.1 4 23.95q0-4.1 1.575-7.75 1.575-3.65 4.3-6.35 2.725-2.7 6.375-4.275Q19.9 4 24.05 4q4.1 0 7.75 1.575 3.65 1.575 6.35 4.275 2.7 2.7 4.275 6.35Q44 19.85 44 24q0 4.1-1.575 7.75-1.575 3.65-4.275 6.375t-6.35 4.3Q28.15 44 24 44Zm.05-3q7.05 0 12-4.975T41 23.95q0-7.05-4.95-12T24 7q-7.05 0-12.025 4.95Q7 16.9 7 24q0 7.05 4.975 12.025Q16.95 41 24.05 41ZM24 24Z" fill="red" stroke="red"/></svg>
|
After Width: | Height: | Size: 712 B |
7
resources-icons-34/group_type.svg
Normal file
@ -0,0 +1,7 @@
|
||||
<svg height="34" viewBox="0 0 200 500" width="34" xmlns="http://www.w3.org/2000/svg">
|
||||
<g transform="matrix(1, 0, 0, 1, 0, 0)">
|
||||
<rect fill="blue" height="100" rx="40" ry="40" width="200" x="0" y="0"/>
|
||||
<rect fill="blue" height="100" rx="40" ry="40" width="200" x="0" y="200"/>
|
||||
<rect fill="blue" height="100" rx="40" ry="40" width="200" x="0" y="400"/>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 361 B |
1
resources-icons-34/info_type.svg
Normal file
@ -0,0 +1 @@
|
||||
<svg height="34" viewBox="0 -960 960 960" width="34" xmlns="http://www.w3.org/2000/svg"><path d="M440-280h80v-240h-80v240Zm40-320q17 0 28.5-11.5T520-640q0-17-11.5-28.5T480-680q-17 0-28.5 11.5T440-640q0 17 11.5 28.5T480-600Zm0 520q-83 0-156-31.5T197-197q-54-54-85.5-127T80-480q0-83 31.5-156T197-763q54-54 127-85.5T480-880q83 0 156 31.5T763-763q54 54 85.5 127T880-480q0 83-31.5 156T763-197q-54 54-127 85.5T480-80Zm0-80q134 0 227-93t93-227q0-134-93-227t-227-93q-134 0-227 93t-93 227q0 134 93 227t227 93Zm0-320Z" fill="blue" stroke="blue"/></svg>
|
After Width: | Height: | Size: 543 B |
1
resources-icons-34/tap_type.svg
Normal file
@ -0,0 +1 @@
|
||||
<svg height="34" viewBox="0 -960 960 960" width="34" xmlns="http://www.w3.org/2000/svg"><path d="M445-80q-29 0-56-12t-45-35L127-403l21-23q14-15 34.5-18.5T221-438l99 53v-365q0-12.75 8.675-21.375 8.676-8.625 21.5-8.625 12.825 0 21.325 8.625T380-750v465l-144-77 156 198q10 12 23.76 18 13.76 6 29.24 6h205q38 0 64-26t26-64v-170q0-25.5-17.25-42.75T680-460H460v-60h219.646q50.148 0 85.251 35T800-400v170q0 63-43.5 106.5T650-80H445ZM203-665q-11.074-18.754-17.037-40.492Q180-727.229 180-750.246 180-821 229.725-870.5T350-920q70.55 0 120.275 49.738Q520-820.524 520-749.956q0 22.956-5.963 44.614Q508.074-683.685 497-665l-52-30q7-12 11-26t4-29.478Q460-796 427.882-828q-32.117-32-78-32Q304-860 272-827.917 240-795.833 240-750q0 15 4 29t11 26l-52 30Zm285 335Z" fill="blue" stroke="blue"/></svg>
|
After Width: | Height: | Size: 781 B |
@ -1,4 +1,3 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<svg viewBox="0 0 200 500" width="48" height="48" xmlns="http://www.w3.org/2000/svg">
|
||||
<g transform="matrix(1, 0, 0, 1, 0, 0)">
|
||||
<rect x="0" y="0" width="200" height="100" fill="blue" rx="40" ry="40"/>
|
||||
|
Before Width: | Height: | Size: 419 B After Width: | Height: | Size: 380 B |
17
resources-launcher-52-52/drawables.xml
Normal file
@ -0,0 +1,17 @@
|
||||
<!--
|
||||
|
||||
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
|
||||
|
||||
-->
|
||||
|
||||
<drawables>
|
||||
<bitmap id="LauncherIcon" filename="launcher.svg" />
|
||||
</drawables>
|
4
resources-launcher-52-52/launcher.svg
Normal file
@ -0,0 +1,4 @@
|
||||
<svg fill="none" height="52" viewBox="0 0 400 400" width="52" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M320 301.762C320 310.012 313.25 316.762 305 316.762H95C86.75 316.762 80 310.012 80 301.762V211.762C80 203.512 84.77 191.993 90.61 186.153L189.39 87.3725C195.22 81.5425 204.77 81.5425 210.6 87.3725L309.39 186.162C315.22 191.992 320 203.522 320 211.772V301.772V301.762Z" fill="#F2F4F9"/>
|
||||
<path d="M309.39 186.153L210.61 87.3725C204.78 81.5425 195.23 81.5425 189.4 87.3725L90.61 186.153C84.78 191.983 80 203.512 80 211.762V301.762C80 310.012 86.75 316.762 95 316.762H187.27L146.64 276.132C144.55 276.852 142.32 277.262 140 277.262C128.7 277.262 119.5 268.062 119.5 256.762C119.5 245.462 128.7 236.262 140 236.262C151.3 236.262 160.5 245.462 160.5 256.762C160.5 259.092 160.09 261.322 159.37 263.412L191 295.042V179.162C184.2 175.822 179.5 168.842 179.5 160.772C179.5 149.472 188.7 140.272 200 140.272C211.3 140.272 220.5 149.472 220.5 160.772C220.5 168.842 215.8 175.822 209 179.162V260.432L240.46 228.972C239.84 227.012 239.5 224.932 239.5 222.772C239.5 211.472 248.7 202.272 260 202.272C271.3 202.272 280.5 211.472 280.5 222.772C280.5 234.072 271.3 243.272 260 243.272C257.5 243.272 255.12 242.802 252.91 241.982L209 285.892V316.772H305C313.25 316.772 320 310.022 320 301.772V211.772C320 203.522 315.23 192.002 309.39 186.162V186.153Z" fill="#18BCF2"/>
|
||||
</svg>
|
After Width: | Height: | Size: 1.3 KiB |
17
resources-launcher-56-56/drawables.xml
Normal file
@ -0,0 +1,17 @@
|
||||
<!--
|
||||
|
||||
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
|
||||
|
||||
-->
|
||||
|
||||
<drawables>
|
||||
<bitmap id="LauncherIcon" filename="launcher.svg" />
|
||||
</drawables>
|
4
resources-launcher-56-56/launcher.svg
Normal file
@ -0,0 +1,4 @@
|
||||
<svg fill="none" height="56" viewBox="0 0 400 400" width="56" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M320 301.762C320 310.012 313.25 316.762 305 316.762H95C86.75 316.762 80 310.012 80 301.762V211.762C80 203.512 84.77 191.993 90.61 186.153L189.39 87.3725C195.22 81.5425 204.77 81.5425 210.6 87.3725L309.39 186.162C315.22 191.992 320 203.522 320 211.772V301.772V301.762Z" fill="#F2F4F9"/>
|
||||
<path d="M309.39 186.153L210.61 87.3725C204.78 81.5425 195.23 81.5425 189.4 87.3725L90.61 186.153C84.78 191.983 80 203.512 80 211.762V301.762C80 310.012 86.75 316.762 95 316.762H187.27L146.64 276.132C144.55 276.852 142.32 277.262 140 277.262C128.7 277.262 119.5 268.062 119.5 256.762C119.5 245.462 128.7 236.262 140 236.262C151.3 236.262 160.5 245.462 160.5 256.762C160.5 259.092 160.09 261.322 159.37 263.412L191 295.042V179.162C184.2 175.822 179.5 168.842 179.5 160.772C179.5 149.472 188.7 140.272 200 140.272C211.3 140.272 220.5 149.472 220.5 160.772C220.5 168.842 215.8 175.822 209 179.162V260.432L240.46 228.972C239.84 227.012 239.5 224.932 239.5 222.772C239.5 211.472 248.7 202.272 260 202.272C271.3 202.272 280.5 211.472 280.5 222.772C280.5 234.072 271.3 243.272 260 243.272C257.5 243.272 255.12 242.802 252.91 241.982L209 285.892V316.772H305C313.25 316.772 320 310.022 320 301.772V211.772C320 203.522 315.23 192.002 309.39 186.162V186.153Z" fill="#18BCF2"/>
|
||||
</svg>
|
After Width: | Height: | Size: 1.3 KiB |
@ -9,7 +9,7 @@
|
||||
// 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
|
||||
// P A Abbey & J D Abbey & Someone0nEarth & moesterheld, 31 October 2023
|
||||
//
|
||||
//
|
||||
// Description:
|
||||
|
@ -9,7 +9,7 @@
|
||||
// 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
|
||||
// P A Abbey & J D Abbey & Someone0nEarth & moesterheld, 31 October 2023
|
||||
//
|
||||
//
|
||||
// Description:
|
||||
@ -39,7 +39,6 @@ class HomeAssistantApp extends Application.AppBase {
|
||||
private var mIsApp as Lang.Boolean = false; // Or Widget
|
||||
private var mUpdating as Lang.Boolean = false; // Don't start a second chain of updates
|
||||
private var mTemplates as Lang.Dictionary = {};
|
||||
private var startUpdating as Lang.Boolean = false;
|
||||
|
||||
function initialize() {
|
||||
AppBase.initialize();
|
||||
@ -120,12 +119,16 @@ class HomeAssistantApp extends Application.AppBase {
|
||||
return ErrorView.create(WatchUi.loadResource($.Rez.Strings.NoInternet) as Lang.String);
|
||||
} else {
|
||||
var isCached = fetchMenuConfig();
|
||||
var ret = null;
|
||||
fetchApiStatus();
|
||||
if (isCached) {
|
||||
return [mHaMenu, new HomeAssistantViewDelegate(true)];
|
||||
ret = [mHaMenu, new HomeAssistantViewDelegate(true)];
|
||||
} else {
|
||||
return [new WatchUi.View(), new WatchUi.BehaviorDelegate()];
|
||||
ret = [new WatchUi.View(), new WatchUi.BehaviorDelegate()];
|
||||
}
|
||||
// Separated from Settings.update() in order to call after fetchMenuConfig() and not call it on changes settings.
|
||||
Settings.webhook();
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
@ -263,17 +266,17 @@ class HomeAssistantApp extends Application.AppBase {
|
||||
private function buildMenu(menu as Lang.Dictionary) {
|
||||
mHaMenu = new HomeAssistantView(menu, null);
|
||||
mQuitTimer.begin();
|
||||
if (startUpdating) {
|
||||
if (!Settings.getWebhookId().equals("")) {
|
||||
startUpdates();
|
||||
}
|
||||
} // If not, this will be done via a chain in Settings.webhook() and mWebhookManager.requestWebhookId() that registers the sensors.
|
||||
}
|
||||
|
||||
function startUpdates() {
|
||||
if (mHaMenu != null and !mUpdating) {
|
||||
// Start the continuous update process that continues for as long as the application is running.
|
||||
updateMenuItems();
|
||||
mUpdating = true;
|
||||
}
|
||||
startUpdating = true;
|
||||
}
|
||||
|
||||
function onReturnUpdateMenuItems(responseCode as Lang.Number, data as Null or Lang.Dictionary) as Void {
|
||||
|
@ -22,8 +22,7 @@
|
||||
using Toybox.Lang;
|
||||
using Toybox.WatchUi;
|
||||
|
||||
class HomeAssistantGroupMenuItem extends WatchUi.IconMenuItem {
|
||||
private var mTemplate as Lang.String or Null;
|
||||
class HomeAssistantGroupMenuItem extends HomeAssistantMenuItem {
|
||||
private var mMenu as HomeAssistantView;
|
||||
|
||||
function initialize(
|
||||
@ -34,48 +33,23 @@ class HomeAssistantGroupMenuItem extends WatchUi.IconMenuItem {
|
||||
:alignment as WatchUi.MenuItem.Alignment
|
||||
} or Null
|
||||
) {
|
||||
if (options != null) {
|
||||
options.put(:icon, icon);
|
||||
} else {
|
||||
options = { :icon => icon };
|
||||
}
|
||||
|
||||
WatchUi.IconMenuItem.initialize(
|
||||
HomeAssistantMenuItem.initialize(
|
||||
definition.get("name") as Lang.String,
|
||||
null,
|
||||
null,
|
||||
icon,
|
||||
template,
|
||||
options
|
||||
);
|
||||
|
||||
mTemplate = template;
|
||||
mMenu = new HomeAssistantView(definition, null);
|
||||
}
|
||||
|
||||
function buildTemplate() as Lang.String or Null {
|
||||
return mTemplate;
|
||||
}
|
||||
|
||||
function updateState(data as Lang.String or Lang.Dictionary or Null) as Void {
|
||||
if (data == null) {
|
||||
setSubLabel(null);
|
||||
} else if(data instanceof Lang.String) {
|
||||
setSubLabel(data);
|
||||
} else if(data instanceof Lang.Dictionary) {
|
||||
// System.println("HomeAsistantGroupMenuItem updateState() data = " + data);
|
||||
if (data.get("error") != null) {
|
||||
setSubLabel($.Rez.Strings.TemplateError);
|
||||
} else {
|
||||
setSubLabel($.Rez.Strings.PotentialError);
|
||||
}
|
||||
} else {
|
||||
// The template must return a Lang.String, a number can be either integer or float and hence cannot be formatted locally without error.
|
||||
setSubLabel(WatchUi.loadResource($.Rez.Strings.TemplateError) as Lang.String);
|
||||
}
|
||||
WatchUi.requestUpdate();
|
||||
}
|
||||
|
||||
function getMenuView() as HomeAssistantView {
|
||||
return mMenu;
|
||||
}
|
||||
|
||||
function hasTemplate() as Lang.Boolean {
|
||||
return mTemplate != null;
|
||||
}
|
||||
|
||||
}
|
||||
|
79
source/HomeAssistantMenuItem.mc
Normal file
@ -0,0 +1,79 @@
|
||||
//-----------------------------------------------------------------------------------
|
||||
//
|
||||
// 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:
|
||||
//
|
||||
// Generic menu button with an icon that optionally renders a Home Assistant Template.
|
||||
//
|
||||
//-----------------------------------------------------------------------------------
|
||||
|
||||
using Toybox.Lang;
|
||||
using Toybox.WatchUi;
|
||||
using Toybox.Graphics;
|
||||
|
||||
class HomeAssistantMenuItem extends WatchUi.IconMenuItem {
|
||||
private var mTemplate as Lang.String or Null;
|
||||
|
||||
function initialize(
|
||||
label as Lang.String or Lang.Symbol,
|
||||
template as Lang.String,
|
||||
options as {
|
||||
:alignment as WatchUi.MenuItem.Alignment,
|
||||
:icon as Graphics.BitmapType or WatchUi.Drawable or Lang.Symbol
|
||||
} or Null
|
||||
) {
|
||||
WatchUi.IconMenuItem.initialize(
|
||||
label,
|
||||
null,
|
||||
null,
|
||||
options.get(:icon),
|
||||
options
|
||||
);
|
||||
mTemplate = template;
|
||||
}
|
||||
|
||||
function hasTemplate() as Lang.Boolean {
|
||||
return mTemplate != null;
|
||||
}
|
||||
|
||||
function buildTemplate() as Lang.String or Null {
|
||||
return mTemplate;
|
||||
}
|
||||
|
||||
function updateState(data as Lang.String or Lang.Dictionary or Null) as Void {
|
||||
if (data == null) {
|
||||
setSubLabel($.Rez.Strings.Empty);
|
||||
} else if(data instanceof Lang.String) {
|
||||
setSubLabel(data);
|
||||
} else if(data instanceof Lang.Number) {
|
||||
var d = data as Lang.Number;
|
||||
setSubLabel(d.format("%d"));
|
||||
} else if(data instanceof Lang.Float) {
|
||||
var f = data as Lang.Float;
|
||||
setSubLabel(f.format("%f"));
|
||||
} else if(data instanceof Lang.Dictionary) {
|
||||
// System.println("HomeAssistantMenuItem updateState() data = " + data);
|
||||
if (data.get("error") != null) {
|
||||
setSubLabel($.Rez.Strings.TemplateError);
|
||||
} else {
|
||||
setSubLabel($.Rez.Strings.PotentialError);
|
||||
}
|
||||
} else {
|
||||
// The template must return a Lang.String, Number or Float, or the item cannot be formatted locally without error.
|
||||
setSubLabel(WatchUi.loadResource($.Rez.Strings.TemplateError) as Lang.String);
|
||||
}
|
||||
WatchUi.requestUpdate();
|
||||
}
|
||||
|
||||
}
|
@ -9,7 +9,7 @@
|
||||
// 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
|
||||
// P A Abbey & J D Abbey & Someone0nEarth & moesterheld, 31 October 2023
|
||||
//
|
||||
//
|
||||
// Description:
|
||||
|
@ -9,7 +9,7 @@
|
||||
// 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
|
||||
// P A Abbey & J D Abbey & Someone0nEarth & moesterheld, 31 October 2023
|
||||
//
|
||||
//
|
||||
// Description:
|
||||
@ -22,9 +22,8 @@ using Toybox.Lang;
|
||||
using Toybox.WatchUi;
|
||||
using Toybox.Graphics;
|
||||
|
||||
class HomeAssistantTapMenuItem extends WatchUi.IconMenuItem {
|
||||
class HomeAssistantTapMenuItem extends HomeAssistantMenuItem {
|
||||
private var mHomeAssistantService as HomeAssistantService;
|
||||
private var mTemplate as Lang.String;
|
||||
private var mService as Lang.String or Null;
|
||||
private var mConfirm as Lang.Boolean;
|
||||
private var mPin as Lang.Boolean;
|
||||
@ -39,53 +38,30 @@ class HomeAssistantTapMenuItem extends WatchUi.IconMenuItem {
|
||||
data as Lang.Dictionary or Null,
|
||||
icon as Graphics.BitmapType or WatchUi.Drawable,
|
||||
options as {
|
||||
:alignment as WatchUi.MenuItem.Alignment
|
||||
:alignment as WatchUi.MenuItem.Alignment,
|
||||
:icon as Graphics.BitmapType or WatchUi.Drawable or Lang.Symbol
|
||||
} or Null,
|
||||
haService as HomeAssistantService
|
||||
) {
|
||||
WatchUi.IconMenuItem.initialize(
|
||||
if (options != null) {
|
||||
options.put(:icon, icon);
|
||||
} else {
|
||||
options = { :icon => icon };
|
||||
}
|
||||
|
||||
HomeAssistantMenuItem.initialize(
|
||||
label,
|
||||
null,
|
||||
null,
|
||||
icon,
|
||||
template,
|
||||
options
|
||||
);
|
||||
|
||||
mHomeAssistantService = haService;
|
||||
mTemplate = template;
|
||||
mService = service;
|
||||
mConfirm = confirm;
|
||||
mPin = pin;
|
||||
mData = data;
|
||||
}
|
||||
|
||||
function hasTemplate() as Lang.Boolean {
|
||||
return mTemplate != null;
|
||||
}
|
||||
|
||||
function buildTemplate() as Lang.String or Null {
|
||||
return mTemplate;
|
||||
}
|
||||
|
||||
function updateState(data as Lang.String or Lang.Dictionary or Null) as Void {
|
||||
if (data == null) {
|
||||
setSubLabel($.Rez.Strings.Empty);
|
||||
} else if(data instanceof Lang.String) {
|
||||
setSubLabel(data);
|
||||
} else if(data instanceof Lang.Dictionary) {
|
||||
// System.println("HomeAsistantTemplateMenuItem updateState() data = " + data);
|
||||
if (data.get("error") != null) {
|
||||
setSubLabel($.Rez.Strings.TemplateError);
|
||||
} else {
|
||||
setSubLabel($.Rez.Strings.PotentialError);
|
||||
}
|
||||
} else {
|
||||
// The template must return a Lang.String, a number can be either integer or float and hence cannot be formatted locally without error.
|
||||
setSubLabel(WatchUi.loadResource($.Rez.Strings.TemplateError) as Lang.String);
|
||||
}
|
||||
WatchUi.requestUpdate();
|
||||
}
|
||||
|
||||
function callService() as Void {
|
||||
var hasTouchScreen = System.getDeviceSettings().isTouchScreen;
|
||||
if (mPin && hasTouchScreen) {
|
||||
|
@ -9,7 +9,7 @@
|
||||
// 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
|
||||
// P A Abbey & J D Abbey & Someone0nEarth & moesterheld, 31 October 2023
|
||||
//
|
||||
//
|
||||
// Description:
|
||||
@ -42,7 +42,13 @@ class HomeAssistantToggleMenuItem extends WatchUi.ToggleMenuItem {
|
||||
:icon as Graphics.BitmapType or WatchUi.Drawable or Lang.Symbol
|
||||
} or Null
|
||||
) {
|
||||
WatchUi.ToggleMenuItem.initialize(label, null, null, false, options);
|
||||
WatchUi.ToggleMenuItem.initialize(
|
||||
label,
|
||||
null,
|
||||
null,
|
||||
false,
|
||||
options
|
||||
);
|
||||
if (Attention has :vibrate) {
|
||||
mHasVibrate = true;
|
||||
}
|
||||
@ -74,19 +80,26 @@ class HomeAssistantToggleMenuItem extends WatchUi.ToggleMenuItem {
|
||||
setSubLabel(null);
|
||||
} else if(data instanceof Lang.String) {
|
||||
setSubLabel(data);
|
||||
} else if(data instanceof Lang.Number) {
|
||||
var d = data as Lang.Number;
|
||||
setSubLabel(d.format("%d"));
|
||||
} else if(data instanceof Lang.Float) {
|
||||
var f = data as Lang.Float;
|
||||
setSubLabel(f.format("%f"));
|
||||
} else if(data instanceof Lang.Dictionary) {
|
||||
// System.println("HomeAsistantToggleMenuItem updateState() data = " + data);
|
||||
// System.println("HomeAssistantToggleMenuItem updateState() data = " + data);
|
||||
if (data.get("error") != null) {
|
||||
setSubLabel($.Rez.Strings.TemplateError);
|
||||
} else {
|
||||
setSubLabel($.Rez.Strings.PotentialError);
|
||||
}
|
||||
} else {
|
||||
// The template must return a Lang.String, a number can be either integer or float and hence cannot be formatted locally without error.
|
||||
// The template must return a Lang.String, Number or Float, or the item cannot be formatted locally without error.
|
||||
setSubLabel(WatchUi.loadResource($.Rez.Strings.TemplateError) as Lang.String);
|
||||
}
|
||||
WatchUi.requestUpdate();
|
||||
}
|
||||
|
||||
function updateToggleState(data as Lang.String or Lang.Dictionary or Null) as Void {
|
||||
if (data == null) {
|
||||
setUiToggle("off");
|
||||
@ -96,7 +109,7 @@ class HomeAssistantToggleMenuItem extends WatchUi.ToggleMenuItem {
|
||||
setSubLabel($.Rez.Strings.Unavailable);
|
||||
}
|
||||
} else if(data instanceof Lang.Dictionary) {
|
||||
// System.println("HomeAsistantToggleMenuItem updateState() data = " + data);
|
||||
// System.println("HomeAssistantToggleMenuItem updateState() data = " + data);
|
||||
if (mTemplate == null) {
|
||||
if (data.get("error") != null) {
|
||||
setSubLabel($.Rez.Strings.TemplateError);
|
||||
|
@ -9,7 +9,7 @@
|
||||
// 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
|
||||
// P A Abbey & J D Abbey & Someone0nEarth & moesterheld, 31 October 2023
|
||||
//
|
||||
//
|
||||
// Description:
|
||||
@ -64,7 +64,8 @@ class HomeAssistantView extends WatchUi.Menu2 {
|
||||
if (type != null && name != null) {
|
||||
if (type.equals("toggle") && entity != null) {
|
||||
addItem(HomeAssistantMenuItemFactory.create().toggle(name, entity, content, confirm, pin));
|
||||
} else if ((type.equals("tap") && service != null) || (type.equals("template") && content != null)) {
|
||||
} else if ((type.equals("tap") && service != null) || (type.equals("info") && content != null) || (type.equals("template") && content != null)) {
|
||||
// NB. "template" is deprecated in the schema and remains only for backward compatibility. All menu items can now use templates, so the replacement is "info".
|
||||
addItem(HomeAssistantMenuItemFactory.create().tap(name, entity, content, service, confirm, pin, data));
|
||||
} else if (type.equals("group")) {
|
||||
addItem(HomeAssistantMenuItemFactory.create().group(items[i], content));
|
||||
|
@ -9,7 +9,7 @@
|
||||
// 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
|
||||
// P A Abbey & J D Abbey, SomeoneOnEarth & moesterheld, 23 November 2023
|
||||
//
|
||||
//
|
||||
// Description:
|
||||
@ -69,7 +69,9 @@ class Settings {
|
||||
mMenuAlignment = Properties.getValue("menu_alignment");
|
||||
mIsSensorsLevelEnabled = Properties.getValue("enable_battery_level");
|
||||
mBatteryRefreshRate = Properties.getValue("battery_level_refresh_rate");
|
||||
}
|
||||
|
||||
static function webhook() {
|
||||
if (System has :ServiceDelegate) {
|
||||
mHasService = true;
|
||||
}
|
||||
@ -106,13 +108,13 @@ class Settings {
|
||||
unsetWebhookId();
|
||||
}
|
||||
}
|
||||
// System.println("Settings update(): getTemporalEventRegisteredTime() = " + Background.getTemporalEventRegisteredTime());
|
||||
// System.println("Settings webhook(): getTemporalEventRegisteredTime() = " + Background.getTemporalEventRegisteredTime());
|
||||
// if (Background.getTemporalEventRegisteredTime() != null) {
|
||||
// System.println("Settings update(): getTemporalEventRegisteredTime().value() = " + Background.getTemporalEventRegisteredTime().value().format("%d") + " seconds");
|
||||
// System.println("Settings webhook(): getTemporalEventRegisteredTime().value() = " + Background.getTemporalEventRegisteredTime().value().format("%d") + " seconds");
|
||||
// } else {
|
||||
// System.println("Settings update(): getTemporalEventRegisteredTime() = null");
|
||||
// System.println("Settings webhook(): getTemporalEventRegisteredTime() = null");
|
||||
// }
|
||||
}
|
||||
}
|
||||
|
||||
static function getApiKey() as Lang.String {
|
||||
return mApiKey;
|
||||
|
@ -120,25 +120,21 @@ class WebhookManager {
|
||||
case Communications.BLE_HOST_TIMEOUT:
|
||||
case Communications.BLE_CONNECTION_UNAVAILABLE:
|
||||
// System.println("WebhookManager onReturnRegisterWebhookSensor() Response Code: BLE_HOST_TIMEOUT or BLE_CONNECTION_UNAVAILABLE, Bluetooth connection severed.");
|
||||
Settings.unsetWebhookId();
|
||||
ErrorView.show(WatchUi.loadResource($.Rez.Strings.WebhookFailed) as Lang.String + "\n" + WatchUi.loadResource($.Rez.Strings.NoPhone) as Lang.String);
|
||||
break;
|
||||
|
||||
case Communications.BLE_QUEUE_FULL:
|
||||
// System.println("WebhookManager onReturnRegisterWebhookSensor() Response Code: BLE_QUEUE_FULL, API calls too rapid.");
|
||||
Settings.unsetWebhookId();
|
||||
ErrorView.show(WatchUi.loadResource($.Rez.Strings.WebhookFailed) as Lang.String + "\n" + WatchUi.loadResource($.Rez.Strings.ApiFlood) as Lang.String);
|
||||
break;
|
||||
|
||||
case Communications.NETWORK_REQUEST_TIMED_OUT:
|
||||
// System.println("WebhookManager onReturnRegisterWebhookSensor() Response Code: NETWORK_REQUEST_TIMED_OUT, check Internet connection.");
|
||||
Settings.unsetWebhookId();
|
||||
ErrorView.show(WatchUi.loadResource($.Rez.Strings.WebhookFailed) as Lang.String + "\n" + WatchUi.loadResource($.Rez.Strings.NoResponse) as Lang.String);
|
||||
break;
|
||||
|
||||
case Communications.NETWORK_RESPONSE_OUT_OF_MEMORY:
|
||||
// System.println("WebhookManager onReturnRegisterWebhookSensor() Response Code: NETWORK_RESPONSE_OUT_OF_MEMORY, are we going too fast?");
|
||||
Settings.unsetWebhookId();
|
||||
// Ignore and see if we can carry on
|
||||
break;
|
||||
|
||||
|