Home | Switches | Actions | Templates | Background Service | Trouble Shooting | Version History
Before raising an issue 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.
- Best! Use the GarminHomeAssistantWidget Web-based Editor which includes
entity
andservice
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. - Use the Studio Code Server addon for Home Assistant. You can then edit your JSON file in place.
- Locally installed VSCode, or if not installed, try
- 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 for the list of error code you might be presented with on your device.
There are some cases where the file format may be valid JSON, but invalid against the schema, and the failure to catch this error could cause the application to crash. Whilst we have taken care to manage many issues, there may still be cases that are uncaught.
Make sure you can browse to the URL of your JSON file in a standard web browser to make sure it is accessible.
With either of the following setups, there are inevitably some problems along the way. GarminHomeAssistantWidget 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.
You can purchase cloud-based access to your Home Assistant from Nabu Casa, and then your setup will look something like this.
- Your API URL would be of the format
https://<id>.ui.nabu.casa/api
- Your Garmin Watch Menu would be of the format Menu:
https://<id>.ui.nabu.casa/local/garmin/menu.json
Where <id>
is your personal Nabu Casa account ID.
Before Nabu Casa, or if you wanted to manage your own infrastructure, you might have something like the following:
Now you have to manage:
- Dynamic DNS
- Public access via router port forwarding
- Security via HTTPS and URL forwarding
- Certificates for HTTPS via say Let's Encrypt (an Nginx proxy web server helps here)
- Proxy allow list in
configuration.yaml
as follows:
http:
use_x_forwarded_for: true
trusted_proxies:
- 127.0.0.1
- 192.168.xx.xx # Server IP - AMEND THIS
- 172.30.32.0/23 # Docker IPs for NGINX
- 172.30.33.0/24 # SSL proxy server
- 172.16.0.0/12 #
This URL is very simple, you should be able to read the contents returned in a standard web browser.
(Other browsers are available...)
The browser page should then display the JSON string you saved to the file on the web server. The point is this is a simple HTTP GET request with no bells and whistles.
The menu configuration can be hosted anywhere, it does not have to be on the Home Assistant web server. Just as long as it is reachable from your phone from which you Bluetooth connect to your watch, or you watch if it has direct Internet access.
This is slightly trickier owning to the need to supply the API key. Here are three ways you can test your API URL is correctly configured. If successful, each of these should produce a JSON string output looking like:
{ "message": "API running." }
Save the following as a file called api_test.sh
, edit to include your personal values for the variables, chmod +x api_test.sh
and then execute with ./api_test.sh
.
#!/bin/bash
API_KEY="<Your API key>"
URL="https://<Your Domain>/api"
curl -s -X GET \
-H "Authorization: Bearer ${API_KEY}" \
-H "Content-Type: application/json" \
${URL}/
Save the following as a file called api_test.cmd
, edit to include your personal values for the variables and then double click.
@echo off
set API_KEY=<Your API key>
set URL=https://<Your Domain>/api
curl -s -X GET ^
-H "Authorization: Bearer %API_KEY%" ^
-H "Content-Type: application/json" ^
%URL%/
echo.
pause
There's an online way of testing the API URL too, thanks to REQBIN. This has less setup and it can be saved if you log into the web site.
- Failure to copy & paste keys and URLs leading to minor and hard to see errors in strings, even with protestations they are the same! (No they weren't...)
- Accessibility of URLs, hence the above help guide.
For this you will need to have already got the main application or widget working with a menu in order to prove that the API calls are successful. We have proven this works with both our home brew infrastructure as well as Nabu Casa. Now with a script similar to one of the following two, you should be able to fake the watch API call and verify receipt by Home Assistant.
Assume a file called: send_battery.bash
#!/bin/bash
#
# battery% charging {0|1}
# ./send_battery.bash 19 0
#
WEBHOOK_ID="<Your Webhook ID>"
URL="https://<Your Domain>/api"
level=${1:-50}
is_charging=${2:-0}
echo "Battery Level = ${level}"
if [ ${is_charging} -eq 1 ]; then
is_charging=true
else
is_charging=false
fi
echo "Battery Charging? = ${is_charging}"
echo ""
curl -s -X POST \
-H "Content-Type: application/json" \
-d '{ "type": "update_sensor_states", "data": [ {"state": '${level}',"type": "sensor","unique_id": "battery_level"}, {"state": '${is_charging}',"type": "binary_sensor","unique_id": "battery_is_charging"} ] }' \
${URL}/webhook/${WEBHOOK_ID}
Execute:
$ ./send_battery.bash 45 1
The output looks like this:
Battery Level = 45
Battery Charging? = true
{
"battery_level": {
"success": true
},
"battery_is_charging": {
"success": true
}
}
NB. The device ID can be any string for the purposes of this testing. Your Garmin device will choose this ID for you when it submits the readings.
Assume a file called: home_assistant_battery_level.cmd
@echo off
rem battery% charging {0|1}
rem ./home_assistant_battery_level 19 0
rem
set WEBHOOK_ID=<Your Webhook ID>
set URL=https://<Your Domain>/api
if [%1] == [] (
set level=50
) else (
set level=%1
)
if [%1] == [] (
set is_charging=0
) else (
set is_charging=%2
)
echo "Battery Level = %level%"
if "%is_charging%"=="1" (
set is_charging=true
) else (
set is_charging=false
)
echo "Battery Charging? = %is_charging%"
echo.
curl -s -X POST ^
-H "Content-Type: application/json" ^
-d "{ \"type\": \"update_sensor_states\", \"data\": [ {\"state\": %level%,\"type\": \"sensor\",\"unique_id\": \"battery_level\"}, {\"state\": %is_charging%,\"type\": \"binary_sensor\",\"unique_id\": \"battery_is_charging\"} ] }" ^
%URL%/webhook/%WEBHOOK_ID%
echo.
pause
Execute:
> home_assistant_battery_level.cmd 41 1
The output looks like this:
"Battery Level = 41"
"Battery Charging? = true"
{
"battery_level": {
"success": true
},
"battery_is_charging": {
"success": true
}
}
Press any key to continue . . .
NB. The device ID can be any string for the purposes of this testing. Your Garmin device will choose this ID for you when it submits the readings.
There's an online way of testing the API URL too, thanks to REQBIN. This has less setup and it can be saved if you log into the web site.
URL for copy & paste:
https://<Your Domain>/api/webhook/<Your Webhook ID>
JSON for copy & paste:
{
"type": "update_sensor_states",
"data": [
{
"state": 40,
"type": "sensor",
"unique_id": "battery_level"
},
{
"state": true,
"type": "binary_sensor",
"unique_id": "battery_is_charging"
}
]
}