mirror of
https://github.com/house-of-abbey/GarminHomeAssistant.git
synced 2025-06-17 11:58:30 +00:00
Compare commits
13 Commits
restyled/9
...
restyled/9
Author | SHA1 | Date | |
---|---|---|---|
cf6552410e | |||
6b3a17bea3 | |||
8f372c03e3 | |||
f5f88ced4e | |||
96abff9339 | |||
4ff1509046 | |||
1ec80a1704 | |||
e3288c9353 | |||
2ba102f8dd | |||
3e0789e808 | |||
bd56c6b4e6 | |||
6063ae8ba3 | |||
f00bbdcb13 |
2
.github/restyled.yml
vendored
2
.github/restyled.yml
vendored
@ -1,3 +1,5 @@
|
||||
exclude:
|
||||
- '**/*.md'
|
||||
- '**/pnpm-lock.yaml'
|
||||
- 'manifest.xml'
|
||||
- 'manifest-widget.xml'
|
||||
|
@ -184,9 +184,10 @@ This allows the `confirm` field to be accommodated in the `tap_action` along sid
|
||||
## Editing the JSON file
|
||||
|
||||
You have options. The first is what we use.
|
||||
1. **Best!** Use the [Studio Code Server](https://community.home-assistant.io/t/home-assistant-community-add-on-visual-studio-code/107863) addon for Home Assistant. You can then edit your JSON file in place.
|
||||
2. Locally installed VSCode, or if not installed,
|
||||
3. try the on-line version at https://vscode.dev/, which works really well.
|
||||
1. **Best!** Use the GarminHomeAssistant [Web-based Editor](https://house-of-abbey.github.io/GarminHomeAssistant/web/) which includes `entity` and `service` name completion and validation by fetching data from your own Home Assistant instance. _Pretty nifty eh?_ The other method listed below do not add this convenience and checking.
|
||||
2. Use the [Studio Code Server](https://community.home-assistant.io/t/home-assistant-community-add-on-visual-studio-code/107863) addon for Home Assistant. You can then edit your JSON file in place.
|
||||
3. Locally installed VSCode, or if not installed, try
|
||||
4. The on-line version at https://vscode.dev/, which works really well.
|
||||
|
||||
Paste in your JSON (and change the file type to JSON if not saving), it will then verify your file format and schema for you, highlighting any errors for you to fix.
|
||||
|
||||
|
@ -2,6 +2,19 @@
|
||||
|
||||
# Troubleshooting Guides
|
||||
|
||||
## Check your JSON Schema
|
||||
|
||||
Before [raising an issue](https://github.com/house-of-abbey/GarminHomeAssistant/issues) about a possible bug, _please, please_ check your JSON is compliant with both the JSON format and our schema. To do this you have options. The first is what we use.
|
||||
|
||||
1. **Best!** Use the GarminHomeAssistant [Web-based Editor](https://house-of-abbey.github.io/GarminHomeAssistant/web/) which includes `entity` and `service` name completion and validation by fetching data from your own Home Assistant instance. _Pretty nifty eh?_ The other method listed below do not add this convenience and checking.
|
||||
2. Use the [Studio Code Server](https://community.home-assistant.io/t/home-assistant-community-add-on-visual-studio-code/107863) addon for Home Assistant. You can then edit your JSON file in place.
|
||||
3. Locally installed VSCode, or if not installed, try
|
||||
4. The on-line version at https://vscode.dev/, which works really well. Paste in your JSON (and change the file type to JSON if not saving), it will then verify your file format and schema for you, highlighting any errors for you to fix.
|
||||
|
||||
A failure to get the file format right tends to mean that the response to the application errors with `INVALID_HTTP_BODY_IN_NETWORK_RESPONSE` (code of -400). This means the response did not contain JSON, it was probably an error message in plain text that could not be parsed by the Connect IQ API call. See [Toybox.Communications](https://developer.garmin.com/connect-iq/api-docs/Toybox/Communications.html) for the list of error code you might be presented with on your device.
|
||||
|
||||
Make sure you can browse to the URL of your JSON file in a standard web browser to make sure it is accessible.
|
||||
|
||||
## Watch Menu and API
|
||||
|
||||
With either of the following setups, there are inevitably some problems along the way. GarminHomeAssistant is careful to rely only on having working URLs. Getting them working is the user's responsibility. However, we have developed some fault finding tools.
|
||||
|
@ -44,30 +44,60 @@
|
||||
"additionalProperties": false
|
||||
},
|
||||
"template": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"entity": {
|
||||
"$ref": "#/$defs/entity"
|
||||
"oneOf": [
|
||||
{
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"entity": {
|
||||
"$ref": "#/$defs/entity",
|
||||
"deprecated": true,
|
||||
"title": "Schema change:",
|
||||
"description": "Use 'tap_action' instead to mirror Home Assistant."
|
||||
},
|
||||
"name": {
|
||||
"title": "Your familiar name",
|
||||
"type": "string"
|
||||
},
|
||||
"content": {
|
||||
"title": "What to display (template)",
|
||||
"type": "string"
|
||||
},
|
||||
"type": {
|
||||
"title": "Menu item type",
|
||||
"description": "One of 'tap', 'template', 'toggle' or 'group'.",
|
||||
"const": "template"
|
||||
}
|
||||
},
|
||||
"required": ["name", "content", "type"],
|
||||
"additionalProperties": false
|
||||
},
|
||||
"name": {
|
||||
"title": "Your familiar name",
|
||||
"type": "string"
|
||||
},
|
||||
"content": {
|
||||
"title": "What to display (template)",
|
||||
"type": "string"
|
||||
},
|
||||
"type": {
|
||||
"title": "Menu item type",
|
||||
"description": "One of 'tap', 'template', 'toggle' or 'group'.",
|
||||
"const": "template"
|
||||
},
|
||||
"tap_action": {
|
||||
"$ref": "#/$defs/tap_action"
|
||||
{
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"entity": {
|
||||
"$ref": "#/$defs/entity"
|
||||
},
|
||||
"name": {
|
||||
"title": "Your familiar name",
|
||||
"type": "string"
|
||||
},
|
||||
"content": {
|
||||
"title": "What to display (template)",
|
||||
"type": "string"
|
||||
},
|
||||
"type": {
|
||||
"title": "Menu item type",
|
||||
"description": "One of 'tap', 'template', 'toggle' or 'group'.",
|
||||
"const": "template"
|
||||
},
|
||||
"tap_action": {
|
||||
"$ref": "#/$defs/tap_action"
|
||||
}
|
||||
},
|
||||
"required": ["name", "content", "type", "tap_action"],
|
||||
"additionalProperties": false
|
||||
}
|
||||
},
|
||||
"required": ["name", "content", "type"],
|
||||
"additionalProperties": false
|
||||
]
|
||||
},
|
||||
"tap": {
|
||||
"type": "object",
|
||||
@ -110,7 +140,6 @@
|
||||
"entity": {
|
||||
"$ref": "#/$defs/entity",
|
||||
"type": "string",
|
||||
"pattern": "^[^.]+\\.[^.]+$",
|
||||
"deprecated": true,
|
||||
"title": "Schema change:",
|
||||
"description": "'entity' is no longer necessary and should now be removed."
|
||||
|
@ -34,115 +34,116 @@
|
||||
"Monkey C: Edit Products" - Lets you add or remove any product
|
||||
-->
|
||||
<iq:products>
|
||||
<iq:product id="approachs7042mm"/>
|
||||
<iq:product id="approachs7047mm"/>
|
||||
<iq:product id="d2air"/>
|
||||
<iq:product id="d2airx10"/>
|
||||
<iq:product id="d2delta"/>
|
||||
<iq:product id="d2deltapx"/>
|
||||
<iq:product id="d2deltas"/>
|
||||
<iq:product id="d2mach1"/>
|
||||
<iq:product id="descentg1"/>
|
||||
<iq:product id="descentmk2"/>
|
||||
<iq:product id="descentmk2s"/>
|
||||
<iq:product id="edge1030"/>
|
||||
<iq:product id="edge1030bontrager"/>
|
||||
<iq:product id="edge1030plus"/>
|
||||
<iq:product id="edge1040"/>
|
||||
<iq:product id="edge520plus"/>
|
||||
<iq:product id="edge530"/>
|
||||
<iq:product id="edge820"/>
|
||||
<iq:product id="edge830"/>
|
||||
<iq:product id="edgeexplore"/>
|
||||
<iq:product id="edgeexplore2"/>
|
||||
<iq:product id="enduro"/>
|
||||
<iq:product id="epix2"/>
|
||||
<iq:product id="epix2pro42mm"/>
|
||||
<iq:product id="epix2pro47mm"/>
|
||||
<iq:product id="epix2pro51mm"/>
|
||||
<iq:product id="fenix5"/>
|
||||
<iq:product id="fenix5plus"/>
|
||||
<iq:product id="fenix5s"/>
|
||||
<iq:product id="fenix5splus"/>
|
||||
<iq:product id="fenix5x"/>
|
||||
<iq:product id="fenix5xplus"/>
|
||||
<iq:product id="fenix6"/>
|
||||
<iq:product id="fenix6pro"/>
|
||||
<iq:product id="fenix6s"/>
|
||||
<iq:product id="fenix6spro"/>
|
||||
<iq:product id="fenix6xpro"/>
|
||||
<iq:product id="fenix7"/>
|
||||
<iq:product id="fenix7pro"/>
|
||||
<iq:product id="fenix7pronowifi"/>
|
||||
<iq:product id="fenix7s"/>
|
||||
<iq:product id="fenix7spro"/>
|
||||
<iq:product id="fenix7x"/>
|
||||
<iq:product id="fenix7xpro"/>
|
||||
<iq:product id="fenix7xpronowifi"/>
|
||||
<iq:product id="fenixchronos"/>
|
||||
<iq:product id="fr245"/>
|
||||
<iq:product id="fr245m"/>
|
||||
<iq:product id="fr255"/>
|
||||
<iq:product id="fr255m"/>
|
||||
<iq:product id="fr255s"/>
|
||||
<iq:product id="fr255sm"/>
|
||||
<iq:product id="fr265"/>
|
||||
<iq:product id="fr265s"/>
|
||||
<iq:product id="fr55"/>
|
||||
<iq:product id="fr645"/>
|
||||
<iq:product id="fr645m"/>
|
||||
<iq:product id="fr745"/>
|
||||
<iq:product id="fr935"/>
|
||||
<iq:product id="fr945"/>
|
||||
<iq:product id="fr945lte"/>
|
||||
<iq:product id="fr955"/>
|
||||
<iq:product id="fr965"/>
|
||||
<iq:product id="gpsmap67"/>
|
||||
<iq:product id="instinct2"/>
|
||||
<iq:product id="instinct2s"/>
|
||||
<iq:product id="instinct2x"/>
|
||||
<iq:product id="instinctcrossover"/>
|
||||
<iq:product id="legacyherocaptainmarvel"/>
|
||||
<iq:product id="legacyherofirstavenger"/>
|
||||
<iq:product id="legacysagadarthvader"/>
|
||||
<iq:product id="legacysagarey"/>
|
||||
<iq:product id="marq2"/>
|
||||
<iq:product id="marq2aviator"/>
|
||||
<iq:product id="marqadventurer"/>
|
||||
<iq:product id="marqathlete"/>
|
||||
<iq:product id="marqaviator"/>
|
||||
<iq:product id="marqcaptain"/>
|
||||
<iq:product id="marqcommander"/>
|
||||
<iq:product id="marqdriver"/>
|
||||
<iq:product id="marqexpedition"/>
|
||||
<iq:product id="marqgolfer"/>
|
||||
<iq:product id="montana7xx"/>
|
||||
<iq:product id="venu"/>
|
||||
<iq:product id="venu2"/>
|
||||
<iq:product id="venu2plus"/>
|
||||
<iq:product id="venu2s"/>
|
||||
<iq:product id="venu3"/>
|
||||
<iq:product id="venu3s"/>
|
||||
<iq:product id="venud"/>
|
||||
<iq:product id="venusq"/>
|
||||
<iq:product id="venusq2"/>
|
||||
<iq:product id="venusq2m"/>
|
||||
<iq:product id="venusqm"/>
|
||||
<iq:product id="vivoactive3"/>
|
||||
<iq:product id="vivoactive3m"/>
|
||||
<iq:product id="vivoactive3mlte"/>
|
||||
<iq:product id="vivoactive4"/>
|
||||
<iq:product id="vivoactive4s"/>
|
||||
<iq:product id="vivoactive5"/>
|
||||
<iq:product id="approachs7042mm" />
|
||||
<iq:product id="approachs7047mm" />
|
||||
<iq:product id="d2air" />
|
||||
<iq:product id="d2airx10" />
|
||||
<iq:product id="d2delta" />
|
||||
<iq:product id="d2deltapx" />
|
||||
<iq:product id="d2deltas" />
|
||||
<iq:product id="d2mach1" />
|
||||
<iq:product id="descentg1" />
|
||||
<iq:product id="descentmk2" />
|
||||
<iq:product id="descentmk2s" />
|
||||
<iq:product id="edge1030" />
|
||||
<iq:product id="edge1030bontrager" />
|
||||
<iq:product id="edge1030plus" />
|
||||
<iq:product id="edge1040" />
|
||||
<iq:product id="edge520plus" />
|
||||
<iq:product id="edge530" />
|
||||
<iq:product id="edge820" />
|
||||
<iq:product id="edge830" />
|
||||
<iq:product id="edgeexplore" />
|
||||
<iq:product id="edgeexplore2" />
|
||||
<iq:product id="enduro" />
|
||||
<iq:product id="epix2" />
|
||||
<iq:product id="epix2pro42mm" />
|
||||
<iq:product id="epix2pro47mm" />
|
||||
<iq:product id="epix2pro51mm" />
|
||||
<iq:product id="fenix5" />
|
||||
<iq:product id="fenix5plus" />
|
||||
<iq:product id="fenix5s" />
|
||||
<iq:product id="fenix5splus" />
|
||||
<iq:product id="fenix5x" />
|
||||
<iq:product id="fenix5xplus" />
|
||||
<iq:product id="fenix6" />
|
||||
<iq:product id="fenix6pro" />
|
||||
<iq:product id="fenix6s" />
|
||||
<iq:product id="fenix6spro" />
|
||||
<iq:product id="fenix6xpro" />
|
||||
<iq:product id="fenix7" />
|
||||
<iq:product id="fenix7pro" />
|
||||
<iq:product id="fenix7pronowifi" />
|
||||
<iq:product id="fenix7s" />
|
||||
<iq:product id="fenix7spro" />
|
||||
<iq:product id="fenix7x" />
|
||||
<iq:product id="fenix7xpro" />
|
||||
<iq:product id="fenix7xpronowifi" />
|
||||
<iq:product id="fenixchronos" />
|
||||
<iq:product id="fr245" />
|
||||
<iq:product id="fr245m" />
|
||||
<iq:product id="fr255" />
|
||||
<iq:product id="fr255m" />
|
||||
<iq:product id="fr255s" />
|
||||
<iq:product id="fr255sm" />
|
||||
<iq:product id="fr265" />
|
||||
<iq:product id="fr265s" />
|
||||
<iq:product id="fr55" />
|
||||
<iq:product id="fr645" />
|
||||
<iq:product id="fr645m" />
|
||||
<iq:product id="fr745" />
|
||||
<iq:product id="fr935" />
|
||||
<iq:product id="fr945" />
|
||||
<iq:product id="fr945lte" />
|
||||
<iq:product id="fr955" />
|
||||
<iq:product id="fr965" />
|
||||
<iq:product id="gpsmap67" />
|
||||
<iq:product id="instinct2" />
|
||||
<iq:product id="instinct2s" />
|
||||
<iq:product id="instinct2x" />
|
||||
<iq:product id="instinctcrossover" />
|
||||
<iq:product id="legacyherocaptainmarvel" />
|
||||
<iq:product id="legacyherofirstavenger" />
|
||||
<iq:product id="legacysagadarthvader" />
|
||||
<iq:product id="legacysagarey" />
|
||||
<iq:product id="marq2" />
|
||||
<iq:product id="marq2aviator" />
|
||||
<iq:product id="marqadventurer" />
|
||||
<iq:product id="marqathlete" />
|
||||
<iq:product id="marqaviator" />
|
||||
<iq:product id="marqcaptain" />
|
||||
<iq:product id="marqcommander" />
|
||||
<iq:product id="marqdriver" />
|
||||
<iq:product id="marqexpedition" />
|
||||
<iq:product id="marqgolfer" />
|
||||
<iq:product id="montana7xx" />
|
||||
<iq:product id="venu" />
|
||||
<iq:product id="venu2" />
|
||||
<iq:product id="venu2plus" />
|
||||
<iq:product id="venu2s" />
|
||||
<iq:product id="venu3" />
|
||||
<iq:product id="venu3s" />
|
||||
<iq:product id="venud" />
|
||||
<iq:product id="venusq" />
|
||||
<iq:product id="venusq2" />
|
||||
<iq:product id="venusq2m" />
|
||||
<iq:product id="venusqm" />
|
||||
<iq:product id="vivoactive3" />
|
||||
<iq:product id="vivoactive3m" />
|
||||
<iq:product id="vivoactive3mlte" />
|
||||
<iq:product id="vivoactive4" />
|
||||
<iq:product id="vivoactive4s" />
|
||||
<iq:product id="vivoactive5" />
|
||||
</iq:products>
|
||||
<!--
|
||||
Use "Monkey C: Edit Permissions" from the Visual Studio Code command
|
||||
palette to update permissions.
|
||||
-->
|
||||
<iq:permissions>
|
||||
<iq:uses-permission id="Background"/>
|
||||
<iq:uses-permission id="BluetoothLowEnergy"/>
|
||||
<iq:uses-permission id="Communications"/>
|
||||
<iq:uses-permission id="Background" />
|
||||
<iq:uses-permission id="BluetoothLowEnergy" />
|
||||
<iq:uses-permission id="Communications" />
|
||||
<iq:uses-permission id="Positioning" />
|
||||
</iq:permissions>
|
||||
<!--
|
||||
Use "Monkey C: Edit Languages" from the Visual Studio Code command
|
||||
@ -190,6 +191,6 @@
|
||||
Use "Monkey C: Configure Monkey Barrel" from the Visual Studio Code
|
||||
command palette to edit the included barrels.
|
||||
-->
|
||||
<iq:barrels/>
|
||||
<iq:barrels />
|
||||
</iq:application>
|
||||
</iq:manifest>
|
209
manifest.xml
209
manifest.xml
@ -40,115 +40,116 @@
|
||||
"Monkey C: Edit Products" - Lets you add or remove any product
|
||||
-->
|
||||
<iq:products>
|
||||
<iq:product id="approachs7042mm"/>
|
||||
<iq:product id="approachs7047mm"/>
|
||||
<iq:product id="d2air"/>
|
||||
<iq:product id="d2airx10"/>
|
||||
<iq:product id="d2delta"/>
|
||||
<iq:product id="d2deltapx"/>
|
||||
<iq:product id="d2deltas"/>
|
||||
<iq:product id="d2mach1"/>
|
||||
<iq:product id="descentg1"/>
|
||||
<iq:product id="descentmk2"/>
|
||||
<iq:product id="descentmk2s"/>
|
||||
<iq:product id="edge1030"/>
|
||||
<iq:product id="edge1030bontrager"/>
|
||||
<iq:product id="edge1030plus"/>
|
||||
<iq:product id="edge1040"/>
|
||||
<iq:product id="edge520plus"/>
|
||||
<iq:product id="edge530"/>
|
||||
<iq:product id="edge820"/>
|
||||
<iq:product id="edge830"/>
|
||||
<iq:product id="edgeexplore"/>
|
||||
<iq:product id="edgeexplore2"/>
|
||||
<iq:product id="enduro"/>
|
||||
<iq:product id="epix2"/>
|
||||
<iq:product id="epix2pro42mm"/>
|
||||
<iq:product id="epix2pro47mm"/>
|
||||
<iq:product id="epix2pro51mm"/>
|
||||
<iq:product id="fenix5"/>
|
||||
<iq:product id="fenix5plus"/>
|
||||
<iq:product id="fenix5s"/>
|
||||
<iq:product id="fenix5splus"/>
|
||||
<iq:product id="fenix5x"/>
|
||||
<iq:product id="fenix5xplus"/>
|
||||
<iq:product id="fenix6"/>
|
||||
<iq:product id="fenix6pro"/>
|
||||
<iq:product id="fenix6s"/>
|
||||
<iq:product id="fenix6spro"/>
|
||||
<iq:product id="fenix6xpro"/>
|
||||
<iq:product id="fenix7"/>
|
||||
<iq:product id="fenix7pro"/>
|
||||
<iq:product id="fenix7pronowifi"/>
|
||||
<iq:product id="fenix7s"/>
|
||||
<iq:product id="fenix7spro"/>
|
||||
<iq:product id="fenix7x"/>
|
||||
<iq:product id="fenix7xpro"/>
|
||||
<iq:product id="fenix7xpronowifi"/>
|
||||
<iq:product id="fenixchronos"/>
|
||||
<iq:product id="fr245"/>
|
||||
<iq:product id="fr245m"/>
|
||||
<iq:product id="fr255"/>
|
||||
<iq:product id="fr255m"/>
|
||||
<iq:product id="fr255s"/>
|
||||
<iq:product id="fr255sm"/>
|
||||
<iq:product id="fr265"/>
|
||||
<iq:product id="fr265s"/>
|
||||
<iq:product id="fr55"/>
|
||||
<iq:product id="fr645"/>
|
||||
<iq:product id="fr645m"/>
|
||||
<iq:product id="fr745"/>
|
||||
<iq:product id="fr935"/>
|
||||
<iq:product id="fr945"/>
|
||||
<iq:product id="fr945lte"/>
|
||||
<iq:product id="fr955"/>
|
||||
<iq:product id="fr965"/>
|
||||
<iq:product id="gpsmap67"/>
|
||||
<iq:product id="instinct2"/>
|
||||
<iq:product id="instinct2s"/>
|
||||
<iq:product id="instinct2x"/>
|
||||
<iq:product id="instinctcrossover"/>
|
||||
<iq:product id="legacyherocaptainmarvel"/>
|
||||
<iq:product id="legacyherofirstavenger"/>
|
||||
<iq:product id="legacysagadarthvader"/>
|
||||
<iq:product id="legacysagarey"/>
|
||||
<iq:product id="marq2"/>
|
||||
<iq:product id="marq2aviator"/>
|
||||
<iq:product id="marqadventurer"/>
|
||||
<iq:product id="marqathlete"/>
|
||||
<iq:product id="marqaviator"/>
|
||||
<iq:product id="marqcaptain"/>
|
||||
<iq:product id="marqcommander"/>
|
||||
<iq:product id="marqdriver"/>
|
||||
<iq:product id="marqexpedition"/>
|
||||
<iq:product id="marqgolfer"/>
|
||||
<iq:product id="montana7xx"/>
|
||||
<iq:product id="venu"/>
|
||||
<iq:product id="venu2"/>
|
||||
<iq:product id="venu2plus"/>
|
||||
<iq:product id="venu2s"/>
|
||||
<iq:product id="venu3"/>
|
||||
<iq:product id="venu3s"/>
|
||||
<iq:product id="venud"/>
|
||||
<iq:product id="venusq"/>
|
||||
<iq:product id="venusq2"/>
|
||||
<iq:product id="venusq2m"/>
|
||||
<iq:product id="venusqm"/>
|
||||
<iq:product id="vivoactive3"/>
|
||||
<iq:product id="vivoactive3m"/>
|
||||
<iq:product id="vivoactive3mlte"/>
|
||||
<iq:product id="vivoactive4"/>
|
||||
<iq:product id="vivoactive4s"/>
|
||||
<iq:product id="vivoactive5"/>
|
||||
<iq:product id="approachs7042mm" />
|
||||
<iq:product id="approachs7047mm" />
|
||||
<iq:product id="d2air" />
|
||||
<iq:product id="d2airx10" />
|
||||
<iq:product id="d2delta" />
|
||||
<iq:product id="d2deltapx" />
|
||||
<iq:product id="d2deltas" />
|
||||
<iq:product id="d2mach1" />
|
||||
<iq:product id="descentg1" />
|
||||
<iq:product id="descentmk2" />
|
||||
<iq:product id="descentmk2s" />
|
||||
<iq:product id="edge1030" />
|
||||
<iq:product id="edge1030bontrager" />
|
||||
<iq:product id="edge1030plus" />
|
||||
<iq:product id="edge1040" />
|
||||
<iq:product id="edge520plus" />
|
||||
<iq:product id="edge530" />
|
||||
<iq:product id="edge820" />
|
||||
<iq:product id="edge830" />
|
||||
<iq:product id="edgeexplore" />
|
||||
<iq:product id="edgeexplore2" />
|
||||
<iq:product id="enduro" />
|
||||
<iq:product id="epix2" />
|
||||
<iq:product id="epix2pro42mm" />
|
||||
<iq:product id="epix2pro47mm" />
|
||||
<iq:product id="epix2pro51mm" />
|
||||
<iq:product id="fenix5" />
|
||||
<iq:product id="fenix5plus" />
|
||||
<iq:product id="fenix5s" />
|
||||
<iq:product id="fenix5splus" />
|
||||
<iq:product id="fenix5x" />
|
||||
<iq:product id="fenix5xplus" />
|
||||
<iq:product id="fenix6" />
|
||||
<iq:product id="fenix6pro" />
|
||||
<iq:product id="fenix6s" />
|
||||
<iq:product id="fenix6spro" />
|
||||
<iq:product id="fenix6xpro" />
|
||||
<iq:product id="fenix7" />
|
||||
<iq:product id="fenix7pro" />
|
||||
<iq:product id="fenix7pronowifi" />
|
||||
<iq:product id="fenix7s" />
|
||||
<iq:product id="fenix7spro" />
|
||||
<iq:product id="fenix7x" />
|
||||
<iq:product id="fenix7xpro" />
|
||||
<iq:product id="fenix7xpronowifi" />
|
||||
<iq:product id="fenixchronos" />
|
||||
<iq:product id="fr245" />
|
||||
<iq:product id="fr245m" />
|
||||
<iq:product id="fr255" />
|
||||
<iq:product id="fr255m" />
|
||||
<iq:product id="fr255s" />
|
||||
<iq:product id="fr255sm" />
|
||||
<iq:product id="fr265" />
|
||||
<iq:product id="fr265s" />
|
||||
<iq:product id="fr55" />
|
||||
<iq:product id="fr645" />
|
||||
<iq:product id="fr645m" />
|
||||
<iq:product id="fr745" />
|
||||
<iq:product id="fr935" />
|
||||
<iq:product id="fr945" />
|
||||
<iq:product id="fr945lte" />
|
||||
<iq:product id="fr955" />
|
||||
<iq:product id="fr965" />
|
||||
<iq:product id="gpsmap67" />
|
||||
<iq:product id="instinct2" />
|
||||
<iq:product id="instinct2s" />
|
||||
<iq:product id="instinct2x" />
|
||||
<iq:product id="instinctcrossover" />
|
||||
<iq:product id="legacyherocaptainmarvel" />
|
||||
<iq:product id="legacyherofirstavenger" />
|
||||
<iq:product id="legacysagadarthvader" />
|
||||
<iq:product id="legacysagarey" />
|
||||
<iq:product id="marq2" />
|
||||
<iq:product id="marq2aviator" />
|
||||
<iq:product id="marqadventurer" />
|
||||
<iq:product id="marqathlete" />
|
||||
<iq:product id="marqaviator" />
|
||||
<iq:product id="marqcaptain" />
|
||||
<iq:product id="marqcommander" />
|
||||
<iq:product id="marqdriver" />
|
||||
<iq:product id="marqexpedition" />
|
||||
<iq:product id="marqgolfer" />
|
||||
<iq:product id="montana7xx" />
|
||||
<iq:product id="venu" />
|
||||
<iq:product id="venu2" />
|
||||
<iq:product id="venu2plus" />
|
||||
<iq:product id="venu2s" />
|
||||
<iq:product id="venu3" />
|
||||
<iq:product id="venu3s" />
|
||||
<iq:product id="venud" />
|
||||
<iq:product id="venusq" />
|
||||
<iq:product id="venusq2" />
|
||||
<iq:product id="venusq2m" />
|
||||
<iq:product id="venusqm" />
|
||||
<iq:product id="vivoactive3" />
|
||||
<iq:product id="vivoactive3m" />
|
||||
<iq:product id="vivoactive3mlte" />
|
||||
<iq:product id="vivoactive4" />
|
||||
<iq:product id="vivoactive4s" />
|
||||
<iq:product id="vivoactive5" />
|
||||
</iq:products>
|
||||
<!--
|
||||
Use "Monkey C: Edit Permissions" from the Visual Studio Code command
|
||||
palette to update permissions.
|
||||
-->
|
||||
<iq:permissions>
|
||||
<iq:uses-permission id="Background"/>
|
||||
<iq:uses-permission id="BluetoothLowEnergy"/>
|
||||
<iq:uses-permission id="Communications"/>
|
||||
<iq:uses-permission id="Background" />
|
||||
<iq:uses-permission id="BluetoothLowEnergy" />
|
||||
<iq:uses-permission id="Communications" />
|
||||
<iq:uses-permission id="Positioning" />
|
||||
</iq:permissions>
|
||||
<!--
|
||||
Use "Monkey C: Edit Languages" from the Visual Studio Code command
|
||||
@ -196,6 +197,6 @@
|
||||
Use "Monkey C: Configure Monkey Barrel" from the Visual Studio Code
|
||||
command palette to edit the included barrels.
|
||||
-->
|
||||
<iq:barrels/>
|
||||
<iq:barrels />
|
||||
</iq:application>
|
||||
</iq:manifest>
|
@ -38,28 +38,87 @@ class BackgroundServiceDelegate extends System.ServiceDelegate {
|
||||
}
|
||||
|
||||
function onTemporalEvent() as Void {
|
||||
if (! System.getDeviceSettings().phoneConnected) {
|
||||
if (!System.getDeviceSettings().phoneConnected) {
|
||||
// System.println("BackgroundServiceDelegate onTemporalEvent(): No Phone connection, skipping API call.");
|
||||
} else if (! System.getDeviceSettings().connectionAvailable) {
|
||||
} else if (!System.getDeviceSettings().connectionAvailable) {
|
||||
// System.println("BackgroundServiceDelegate onTemporalEvent(): No Internet connection, skipping API call.");
|
||||
} else {
|
||||
// System.println("BackgroundServiceDelegate onTemporalEvent(): Making API call.");
|
||||
var position = Position.getInfo();
|
||||
// System.println("BackgroundServiceDelegate onTemporalEvent(): gps: " + position.position.toDegrees());
|
||||
// System.println("BackgroundServiceDelegate onTemporalEvent(): speed: " + position.speed);
|
||||
// System.println("BackgroundServiceDelegate onTemporalEvent(): course: " + position.heading + "rad (" + (position.heading * 180 / Math.PI) + "°)");
|
||||
// System.println("BackgroundServiceDelegate onTemporalEvent(): altitude: " + position.altitude);
|
||||
// System.println("BackgroundServiceDelegate onTemporalEvent(): battery: " + System.getSystemStats().battery);
|
||||
// System.println("BackgroundServiceDelegate onTemporalEvent(): charging: " + System.getSystemStats().charging);
|
||||
// System.println("BackgroundServiceDelegate onTemporalEvent(): activity: " + Activity.getProfileInfo().name);
|
||||
|
||||
// Don't use Settings.* here as the object lasts < 30 secs and is recreated each time the background service is run
|
||||
|
||||
if (position.accuracy != Position.QUALITY_NOT_AVAILABLE && position.accuracy != Position.QUALITY_LAST_KNOWN) {
|
||||
var accuracy = 0;
|
||||
switch (position.accuracy) {
|
||||
case Position.QUALITY_POOR:
|
||||
accuracy = 500;
|
||||
break;
|
||||
case Position.QUALITY_USABLE:
|
||||
accuracy = 100;
|
||||
break;
|
||||
case Position.QUALITY_GOOD:
|
||||
accuracy = 10;
|
||||
break;
|
||||
}
|
||||
Communications.makeWebRequest(
|
||||
(Properties.getValue("api_url") as Lang.String) + "/webhook/" + (Properties.getValue("webhook_id") as Lang.String),
|
||||
{
|
||||
"type" => "update_location",
|
||||
"data" => {
|
||||
"gps" => position.position.toDegrees(),
|
||||
"gps_accuracy" => accuracy,
|
||||
"speed" => Math.round(position.speed),
|
||||
"course" => Math.round(position.heading * 180 / Math.PI),
|
||||
"altitude" => Math.round(position.altitude),
|
||||
}
|
||||
},
|
||||
{
|
||||
:method => Communications.HTTP_REQUEST_METHOD_POST,
|
||||
:headers => {
|
||||
"Content-Type" => Communications.REQUEST_CONTENT_TYPE_JSON
|
||||
},
|
||||
:responseType => Communications.HTTP_RESPONSE_CONTENT_TYPE_JSON
|
||||
},
|
||||
method(:onReturnBatteryUpdate)
|
||||
);
|
||||
}
|
||||
var data = [
|
||||
{
|
||||
"state" => System.getSystemStats().battery,
|
||||
"type" => "sensor",
|
||||
"unique_id" => "battery_level"
|
||||
},
|
||||
{
|
||||
"state" => System.getSystemStats().charging,
|
||||
"type" => "binary_sensor",
|
||||
"unique_id" => "battery_is_charging"
|
||||
}
|
||||
];
|
||||
if (Activity has :getProfileInfo) {
|
||||
data.add({
|
||||
"state" => Activity.getProfileInfo().sport,
|
||||
"type" => "sensor",
|
||||
"unique_id" => "activity"
|
||||
});
|
||||
data.add({
|
||||
"state" => Activity.getProfileInfo().subSport,
|
||||
"type" => "sensor",
|
||||
"unique_id" => "sub_activity"
|
||||
});
|
||||
}
|
||||
Communications.makeWebRequest(
|
||||
(Properties.getValue("api_url") as Lang.String) + "/webhook/" + (Properties.getValue("webhook_id") as Lang.String),
|
||||
{
|
||||
"type" => "update_sensor_states",
|
||||
"data" => [
|
||||
{
|
||||
"state" => System.getSystemStats().battery,
|
||||
"type" => "sensor",
|
||||
"unique_id" => "battery_level"
|
||||
},
|
||||
{
|
||||
"state" => System.getSystemStats().charging,
|
||||
"type" => "binary_sensor",
|
||||
"unique_id" => "battery_is_charging"
|
||||
}
|
||||
]
|
||||
"data" => data
|
||||
},
|
||||
{
|
||||
:method => Communications.HTTP_REQUEST_METHOD_POST,
|
||||
|
@ -62,10 +62,12 @@ class WebhookManager {
|
||||
ErrorView.show(WatchUi.loadResource($.Rez.Strings.WebhookFailed) as Lang.String + "\n" + WatchUi.loadResource($.Rez.Strings.ApiUrlNotFound) as Lang.String);
|
||||
break;
|
||||
|
||||
case 200:
|
||||
case 201:
|
||||
var id = data.get("webhook_id") as Lang.String or Null;
|
||||
if (id != null) {
|
||||
Settings.setWebhookId(id);
|
||||
// System.println("WebhookManager onReturnRegisterWebhookSensor(): Registering first sensor: Battery Level");
|
||||
registerWebhookSensor({
|
||||
"device_class" => "battery",
|
||||
"name" => "Battery Level",
|
||||
@ -76,16 +78,7 @@ class WebhookManager {
|
||||
"state_class" => "measurement",
|
||||
"entity_category" => "diagnostic",
|
||||
"disabled" => false
|
||||
});
|
||||
registerWebhookSensor({
|
||||
"device_class" => "battery_charging",
|
||||
"name" => "Battery is Charging",
|
||||
"state" => System.getSystemStats().charging,
|
||||
"type" => "binary_sensor",
|
||||
"unique_id" => "battery_is_charging",
|
||||
"entity_category" => "diagnostic",
|
||||
"disabled" => false
|
||||
});
|
||||
}, 0);
|
||||
} else {
|
||||
// System.println("WebhookManager onReturnRequestWebhookId(): No webhook id in response data.");
|
||||
Settings.unsetIsBatteryLevelEnabled();
|
||||
@ -129,7 +122,7 @@ class WebhookManager {
|
||||
);
|
||||
}
|
||||
|
||||
function onReturnRegisterWebhookSensor(responseCode as Lang.Number, data as Null or Lang.Dictionary or Lang.String) as Void {
|
||||
function onReturnRegisterWebhookSensor(responseCode as Lang.Number, data as Null or Lang.Dictionary or Lang.String, step as Lang.Number) as Void {
|
||||
switch (responseCode) {
|
||||
case Communications.BLE_HOST_TIMEOUT:
|
||||
case Communications.BLE_CONNECTION_UNAVAILABLE:
|
||||
@ -155,6 +148,7 @@ class WebhookManager {
|
||||
Settings.unsetWebhookId();
|
||||
// Ignore and see if we can carry on
|
||||
break;
|
||||
|
||||
case Communications.INVALID_HTTP_BODY_IN_NETWORK_RESPONSE:
|
||||
// System.println("WebhookManager onReturnRegisterWebhookSensor() Response Code: INVALID_HTTP_BODY_IN_NETWORK_RESPONSE, check JSON is returned.");
|
||||
Settings.unsetWebhookId();
|
||||
@ -169,12 +163,51 @@ class WebhookManager {
|
||||
ErrorView.show(WatchUi.loadResource($.Rez.Strings.WebhookFailed) as Lang.String + "\n" + WatchUi.loadResource($.Rez.Strings.ApiUrlNotFound) as Lang.String);
|
||||
break;
|
||||
|
||||
case 200:
|
||||
case 201:
|
||||
if ((data.get("success") as Lang.Boolean or Null) != true) {
|
||||
// When uncommenting, invert the condition above.
|
||||
// System.println("WebhookManager onReturnRegisterWebhookSensor(): Success");
|
||||
// } else {
|
||||
// System.println("WebhookManager onReturnRegisterWebhookSensor(): Failure");
|
||||
if ((data.get("success") as Lang.Boolean or Null) != false) {
|
||||
// System.println("WebhookManager onReturnRegisterWebhookSensor(): Success");
|
||||
switch (step) {
|
||||
case 0:
|
||||
// System.println("WebhookManager onReturnRegisterWebhookSensor(): Registering next sensor: Battery is Charging");
|
||||
registerWebhookSensor({
|
||||
"device_class" => "battery_charging",
|
||||
"name" => "Battery is Charging",
|
||||
"state" => System.getSystemStats().charging,
|
||||
"type" => "binary_sensor",
|
||||
"unique_id" => "battery_is_charging",
|
||||
"entity_category" => "diagnostic",
|
||||
"disabled" => false
|
||||
}, 1);
|
||||
break;
|
||||
case 1:
|
||||
// System.println("WebhookManager onReturnRegisterWebhookSensor(): Registering next sensor: Activity");
|
||||
if (Activity has :getProfileInfo) {
|
||||
registerWebhookSensor({
|
||||
"name" => "Activity",
|
||||
"state" => Activity.getProfileInfo().sport,
|
||||
"type" => "sensor",
|
||||
"unique_id" => "activity",
|
||||
"disabled" => false
|
||||
}, 2);
|
||||
break;
|
||||
}
|
||||
case 2:
|
||||
// System.println("WebhookManager onReturnRegisterWebhookSensor(): Registering next sensor: Activity");
|
||||
if (Activity has :getProfileInfo) {
|
||||
registerWebhookSensor({
|
||||
"name" => "Sub-activity",
|
||||
"state" => Activity.getProfileInfo().subSport,
|
||||
"type" => "sensor",
|
||||
"unique_id" => "sub_activity",
|
||||
"disabled" => false
|
||||
}, 3);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
}
|
||||
} else {
|
||||
// System.println("WebhookManager onReturnRegisterWebhookSensor(): Failure");
|
||||
Settings.unsetWebhookId();
|
||||
Settings.unsetIsBatteryLevelEnabled();
|
||||
ErrorView.show(WatchUi.loadResource($.Rez.Strings.WebhookFailed) as Lang.String);
|
||||
@ -189,7 +222,7 @@ class WebhookManager {
|
||||
}
|
||||
}
|
||||
|
||||
function registerWebhookSensor(sensor as Lang.Object) {
|
||||
function registerWebhookSensor(sensor as Lang.Object, step as Lang.Number) {
|
||||
// System.println("WebhookManager registerWebhookSensor(): Registering webhook sensor: " + sensor.toString());
|
||||
Communications.makeWebRequest(
|
||||
Settings.getApiUrl() + "/webhook/" + Settings.getWebhookId(),
|
||||
@ -202,7 +235,8 @@ class WebhookManager {
|
||||
:headers => {
|
||||
"Content-Type" => Communications.REQUEST_CONTENT_TYPE_JSON
|
||||
},
|
||||
:responseType => Communications.HTTP_RESPONSE_CONTENT_TYPE_JSON
|
||||
:responseType => Communications.HTTP_RESPONSE_CONTENT_TYPE_JSON,
|
||||
:context => step
|
||||
},
|
||||
method(:onReturnRegisterWebhookSensor)
|
||||
);
|
||||
|
@ -221,21 +221,29 @@
|
||||
<input
|
||||
required
|
||||
placeholder="https://<home-assistant>/api"
|
||||
title="Home Assistant API URL `https://<home-assistant>/api`"
|
||||
type="url"
|
||||
name="api_url"
|
||||
id="api_url"
|
||||
pattern="https://.*/api" />
|
||||
<input
|
||||
placeholder="https://<home-assistant>/local/garmin/menu.json"
|
||||
title="Menu JSON URL `https://<home-assistant>/local/garmin/menu.json`"
|
||||
type="url"
|
||||
name="menu_url"
|
||||
id="menu_url"
|
||||
pattern="https://.*\.json" />
|
||||
<button class="icon" icon="download" id="download" type="button"></button>
|
||||
<button
|
||||
title="Download content of menu url and put it in the editor"
|
||||
class="icon"
|
||||
icon="download"
|
||||
id="download"
|
||||
type="button"></button>
|
||||
<input
|
||||
required
|
||||
autocomplete="new-password"
|
||||
placeholder="token"
|
||||
placeholder="API Token"
|
||||
title="Home Assistant Long-lived Access Token"
|
||||
type="password"
|
||||
name="api_token"
|
||||
id="api_token" />
|
||||
@ -249,6 +257,7 @@
|
||||
<div class="row">
|
||||
<h2>GarminHomeAssistant Troubleshooting</h2>
|
||||
<button
|
||||
title="Close"
|
||||
class="icon"
|
||||
icon="close"
|
||||
onclick="this.parentElement.parentElement.parentElement.close()"
|
||||
@ -262,11 +271,21 @@
|
||||
|
||||
<div class="row">
|
||||
<div id="test-api-response">Check now!</div>
|
||||
<button id="test-api" type="button">Test API</button>
|
||||
<button
|
||||
title="Check the status of the API"
|
||||
id="test-api"
|
||||
type="button">
|
||||
Test API
|
||||
</button>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div id="test-menu-response">Check now!</div>
|
||||
<button id="test-menu" type="button">Test menu</button>
|
||||
<button
|
||||
title="Check the availability of the menu configuration"
|
||||
id="test-menu"
|
||||
type="button">
|
||||
Test menu
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</dialog>
|
||||
|
Reference in New Issue
Block a user