Skip to content

Commit

Permalink
Merge pull request #96 from house-of-abbey/94-add-gps-reporting-to-th…
Browse files Browse the repository at this point in the history
…e-background-service

GPS and current activity reporting
  • Loading branch information
JosephAbbey authored Jan 30, 2024
2 parents 1d5ee73 + 2ad0480 commit 9c5aad8
Show file tree
Hide file tree
Showing 14 changed files with 447 additions and 269 deletions.
2 changes: 2 additions & 0 deletions .github/restyled.yml
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
exclude:
- '**/*.md'
- '**/pnpm-lock.yaml'
- 'manifest.xml'
- 'manifest-widget.xml'
45 changes: 44 additions & 1 deletion BatteryReporting.md → BackgroundService.md
Original file line number Diff line number Diff line change
@@ -1,9 +1,52 @@
[Home](README.md) | [Switches](examples/Switches.md) | [Actions](examples/Actions.md) | [Templates](examples/Templates.md) | Battery Reporting | [Trouble Shooting](TroubleShooting.md) | [Version History](HISTORY.md)

# Battery Reporting
# Background Service

The background service can report the following statuses from your device to your Home Assistant:

- Battery Level with charging status.
- Location and location accuracy.
- Activity information, but only if your device supports API level 3.2.0. If your device does not support this API level, this information is simply omitted. How do you know? Easiest way is to see if the data is reported.

## Limits

The values are merely samples of your device's current status. They are sent by a single background service at the repetition frequency you chose in the settings. The samples are sent at that one rate only, they _do not vary_ for example on in activity, on charge, time of day. You get one refresh interval and that is it. If you want to change the refresh interval, you change your settings. We do appreciate that may not be what you would ideally like to trigger actions on Home Assistant. Messing with the repeat interval of the background service requires more code, more settings and more complexity. That means older devices using widgets would have to be taken out of support to achieve it.

**Please do not ask for these to be made 'events'.** Garmin's [Connect IQ background service](https://developer.garmin.com/connect-iq/api-docs/Toybox/System/ServiceDelegate.html) is limited in that while it does provide an `onActivityCompleted()` method, it does not provide an `onActivityStarted()` method, so you would not have the complete activity life cycle anyway. So we're keeping this implementation simple, you just get a sampling at one refresh rate. This probably limits you to updating a status on a Home Assistant Dashboard only.

## 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.

## Location Reporting

From version 2.6 the application includes reporting your location. The location data reported includes:

- Location (latitude and longitude)
- Location accuracy
- Speed
- Direction
- Altitude

You get whatever your device provides at the moment, i.e. at the accuracy the device currently provides. If your watch is not calibrated you get poor data. It might mean that you get more accurate location data when you are in a location tracking activity (i.e. not swimming pool lengths). The device [indicates an accuracy](https://developer.garmin.com/connect-iq/api-docs/Toybox/Position.html#Quality-module) in units of:

- `Position.QUALITY_NOT_AVAILABLE` - No update provided
- `Position.QUALITY_LAST_KNOWN` - No update provided
- `Position.QUALITY_POOR` - We translate that to 500 m arbitrarily
- `Position.QUALITY_USABLE` - We translate that to 100 m arbitrarily
- `Position.QUALITY_GOOD` - We translate that to 10 m arbitrarily

**You cannot rely on the radius of the circle of accuracy in any resulting maps as any meaningful indication of error.**

## Activity Reporting

From version 2.6 the application includes reporting your activity. The activity data includes:

- Activity - This is an integer as defined by [Toybox.Activity `SPORT`](https://developer.garmin.com/connect-iq/api-docs/Toybox/Activity.html#Sport-module)
- Sub-activity - This is an integer as defined by [Toybox.Activity `SUB_SPORT`](https://developer.garmin.com/connect-iq/api-docs/Toybox/Activity.html#SubSport-module)

The application only provides the integers without translation. When using the values in Home Assistant, you will need to provide you own mapping from the `Activity` enumerated type to the human readable text. As developers of the application we are pushing this translation to the server to keep the Garmin application code 'lean'. You will also need to add to both the list of activities (sports) and sub-activities (sub-sports) an interpretation of integer `-1` for no activity/sub-activity at present.

## 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.
Expand Down
5 changes: 3 additions & 2 deletions HISTORY.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
[Home](README.md) | [Switches](examples/Switches.md) | [Actions](examples/Actions.md) | [Templates](examples/Templates.md) | [Battery Reporting](BatteryReporting.md) | [Trouble Shooting](TroubleShooting.md) | Version History
[Home](README.md) | [Switches](examples/Switches.md) | [Actions](examples/Actions.md) | [Templates](examples/Templates.md) | [Background Service](BackgroundService.md) | [Trouble Shooting](TroubleShooting.md) | Version History

# Version History

Expand All @@ -13,8 +13,9 @@
| 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 hence is 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. |
| 2.1 | Deployment of an idea to provide Home Assistant with access to the watch battery level. Using this requires [significant setup](BackgroundService.md) on the Home Assistant configuration and hence is 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. |
| 2.2 | Adds a feature to cache the menu configuration and save the time taken for an HTTP request to fetch it. You as the user are responsible for managing the cache by clearing it when you update your configuration. Improvement to widget root display updates. Bug fix for battery level reporting when in the glance carousel. Fixed an uninternationalised string, "Execute". Unfixed issue with battery level updates when the user is not an administrator. |
| 2.3 | Fix for battery level updates where previously the function only worked for administrator accounts. The new solution is based on Webhooks and is simpler to implement on Home Assistant. Language support fix where an automatic translation produced an inappropriate word, possibly in more than one language. |
| 2.4 | Sensor status reporting via Home Assistant 'templates'. This provides a generalised way of viewing the status of any entity as long as the result can be rendered as text, e.g. 'uncovered', 'open', '76%', '21 °C'. Removal of the menu style option. The original style was kept after the introduction of the icon style solely to keep the code for a possible re-use for sensor statuses. This version delivers that new feature, hence the style option has been removed. The new JSON configuration file format allows for the old style to be replicated if you are desperate! Added a feature to provide parameters to actions (`tap` or `template`). Added a feature to confirm `toggle` menu items. |
| 2.5 | A small memory efficiency of about 1kB by removing `RezStrings.mc`. This will aid widgets on old watches that only have 60kB available to an application and are using about 45kB before the menu is fetched, hence 1kB is more significant to those devices. |
| 2.6 | Added more information reporting to the background service, in addition to the device battery level and charging status, we now include location, location accuracy, and (if supported by your device) the activity information. Note the updates are sent periodically and are not event driven. |
6 changes: 4 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
Home | [Switches](examples/Switches.md) | [Actions](examples/Actions.md) | [Templates](examples/Templates.md) | [Battery Reporting](BatteryReporting.md) | [Trouble Shooting](TroubleShooting.md) | [Version History](HISTORY.md)
Home | [Switches](examples/Switches.md) | [Actions](examples/Actions.md) | [Templates](examples/Templates.md) | [Background Service](BackgroundService.md) | [Trouble Shooting](TroubleShooting.md) | [Version History](HISTORY.md)

# GarminHomeAssistant

Expand Down Expand Up @@ -249,7 +249,9 @@ Home Assistant will inevitably change the state of devices you are also controll

The per toggle item delay is caused by a queue of responses to web requests. The responses fill up a buffer and in early testing we observed [`Communications.BLE_QUEUE_FULL`](https://developer.garmin.com/connect-iq/api-docs/Toybox/Communications.html) response codes. For a Venu 2 Garmin watch an API call delay of 600 ms was found to be sustainable (500 ms was still too fast). The code now chains a sequence of updates, so as one finishes it invokes the next item's update. **The more items requiring a status update that you pack into your dashboard, the slower each individual item will be updated!**

The thinking here is that the watch application will only ever be open briefly not persistently, so the delay in picking up state changes won't be observed often for any race condition between two controllers. As a consequence of this update mechanism, if you request changes too quickly you will be notified that your device cannot keep up with the rate of API responses and you will have to dismiss the error in order to continue. The is a _feature not a bug_!
The thinking here is that the watch application will only ever be open briefly not persistently, so the delay in picking up state changes won't be observed often for any race condition between two controllers. As a consequence of this update mechanism, if you request changes too quickly you will be notified that your device cannot keep up with the rate of API responses and you will have to dismiss the error in order to continue. This is a _feature not a bug_! If the application reduces the rate of "round robin" status update requests it becomes less responsive to external changes.

To prevent excessive battery usage, set the application timeout in the settings. This will prevent you from leaving the application open and forgotten when not being used, and the polling mechanism will then cease, saving battery life. Again, the thinking here is that the watch application will only ever be open briefly not persistently, and hence not be a constant source of battery usage unless the [background service](BackgroundService.md) for sending any watch status is used aggressively fast.

## Changes to the (JSON) Dashboard Definition

Expand Down
2 changes: 1 addition & 1 deletion TroubleShooting.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
[Home](README.md) | [Switches](examples/Switches.md) | [Actions](examples/Actions.md) | [Templates](examples/Templates.md) | [Battery Reporting](BatteryReporting.md) | Trouble Shooting | [Version History](HISTORY.md)
[Home](README.md) | [Switches](examples/Switches.md) | [Actions](examples/Actions.md) | [Templates](examples/Templates.md) | [Background Service](BackgroundService.md) | Trouble Shooting | [Version History](HISTORY.md)

# Troubleshooting Guides

Expand Down
2 changes: 1 addition & 1 deletion examples/Actions.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
[Home](../README.md) | [Switches](Switches.md) | Actions | [Templates](Templates.md) | [Battery Reporting](../BatteryReporting.md) | [Trouble Shooting](../TroubleShooting.md) | [Version History](../HISTORY.md)
[Home](../README.md) | [Switches](Switches.md) | Actions | [Templates](Templates.md) | [Background Service](../BackgroundService.md) | [Trouble Shooting](../TroubleShooting.md) | [Version History](../HISTORY.md)

# Actions

Expand Down
2 changes: 1 addition & 1 deletion examples/Switches.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
[Home](../README.md) | Switches | [Actions](Actions.md) | [Templates](Templates.md) | [Battery Reporting](../BatteryReporting.md) | [Trouble Shooting](../TroubleShooting.md) | [Version History](../HISTORY.md)
[Home](../README.md) | Switches | [Actions](Actions.md) | [Templates](Templates.md) | [Background Service](../BackgroundService.md) | [Trouble Shooting](../TroubleShooting.md) | [Version History](../HISTORY.md)

# Switches

Expand Down
19 changes: 16 additions & 3 deletions examples/Templates.md
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
[Home](../README.md) | [Switches](Switches.md) | [Actions](Actions.md) | Templates | [Battery Reporting](../BatteryReporting.md) | [Trouble Shooting](../TroubleShooting.md) | [Version History](../HISTORY.md)
[Home](../README.md) | [Switches](Switches.md) | [Actions](Actions.md) | Templates | [Background Service](../BackgroundService.md) | [Trouble Shooting](../TroubleShooting.md) | [Version History](../HISTORY.md)

# Templates

In order to provide the most functionality possible the content of the menu item comes from a user-defined template (i.e. you generate your own text). This allows you to do some pretty cool things. It also makes the config a bit more complicated. This page will help you understand how to use templates.
In order to provide the most functionality possible the content of the menu item comes from a user-defined template (i.e. you generate your own text). This allows you to do some pretty cool things. It also makes the configuration a bit more complicated. This page will help you understand how to use templates.

- In this file anything between `<` and `>` is a placeholder. Replace it with the appropriate value.
- Anything between `{{` and `}}` is a template. Templates are used to dynamically insert values into the content. For more info see [the docs](https://www.home-assistant.io/docs/configuration/templating/).
- [Jinga2](https://palletsprojects.com/p/jinja/) syntax is used by Home Assistant [Templates](https://www.home-assistant.io/docs/configuration/templating/). Templates are used to dynamically insert values into the content. The syntax includes:
- `{%` ... `%}` for Statements
- `{{` ... `}}` for Expressions to print to the template output
- `{#` ... `#}` for Comments not included in the template output

## States

Expand Down Expand Up @@ -45,6 +48,16 @@ The first two keep to the simple proposal above. The last combines them into a s
}
```

In order to keep the formatting of floating point numbers under control, you might also like to include a format string as follows. `states()` seems to return a `string` that needs converting to a `float` before the `format()` call can manage the conversion to the required number fo decimal places.

```json
{
"name": "Hallway",
"type": "template",
"content": "T:{{ '%.1f'|format(states('sensor.hallway_temperature')|float) }}°C, H:{{ '%.1f'|format(states('sensor.hallway_humidity')|float) }}%"
},
```

## Conditionals

Anything between `{%` and `%}` is a directive (`if`, `else`, `elif`, `endif`, etc.). Conditionals are used to dynamically change the content based on the state of the entity.
Expand Down
Binary file modified images/GarminHomeAssistantSettings.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading

0 comments on commit 9c5aad8

Please sign in to comment.