89 Fossil Hybrid HR
MortenHannemose edited this page 1 month ago
Table of Contents

Fossil / Skagen Hybrid HR

The support for the Fossil Hybrid HR in Gadgetbridge is considered stable and mature.

Contents

Screenshots

Screenshots and photos to give an impression of the actual usage. Click on the images for larger versions.

The main screen, the watchface designer, the app manager, and the custom menu editor

Watchface with regular widgets, watchface with custom widgets, custom menu, and snake game

About the device

The Fossil Hybrid HR is an ePaper Hybrid smartwatch with real hands on a round epaper display with over two weeks of battery. The same device is also sold with slightly different cases under the Skagen brand.

Feature support matrix

Feature Gadgetbridge Official app Notes
Time synchronization Yes Yes
Hands calibration Yes Yes
Steps Yes Yes
Heart rate Yes Yes
Sleep tracking No Yes Not tracked by watch but calculated by algorithm in official app
GPS workouts Yes Yes Needs OpenTracks 3.29.0 or later installed
Phone notifications Yes Yes Settings under Notification settings in Gadgetbride menu, not in device settings
Call accept/decline Yes Yes
Dismiss call with SMS Yes Yes
Weather info Yes Yes See https://codeberg.org/Freeyourgadget/Gadgetbridge/wiki/Weather
Physical buttons Yes Yes
Music info and control Yes Yes
Alarms Yes Yes Last alarm slot is used for quick alarm set from the Widget.
Watchface configuration Yes Yes Watchfaces on firmware DN1.0.2.20r and up are only supported by Gadgetbridge 0.59.0 and up
Google Fit integration No Yes Gadgetbridge has no internet permissions
Privacy friendly Yes No
Tasker/Intent actions Yes No See below for configuration examples
Custom apps Yes No
Custom menu Yes No Requires extra companion app
Custom widgets Yes No Requires Tasker or other Intent sending app

Known watch apps

App name Version Official Description
launcherApp 3.8 Yes New on-watch menu introduced with official app v5
settingApp 3.12 Yes Settings menu
notificationsPanelApp 3.5 Yes Notifications list and actions
musicApp 3.9 Yes Music control
ringPhoneApp 3.7 Yes Locate phone from watch by ringing it
stopwatchApp 3.5 Yes Stopwatch
timerApp 3.8 Yes Countdown timer
weatherApp 3.10 Yes Shows weather info
wellnessApp 3.15 Yes Health dashboard
commuteApp 2.5 Yes Displays commute times, but can be used to interface with Easer/Tasker. Discontinued in official app v5.
workoutApp N/A Yes Records workouts. Built into firmware.
themeApp N/A Yes Hidden on-watch watchface switcher. Built into firmware.
snakeApp 2.4 No Snake game
timerApp 2.4 No Integrated timer/stopwatch/alarm app

The app names in the table above can be used in the custom menu companion app. See below for details.

Known firmware versions

Version From Fossil app md5sum Comments
DN1.0.2.3r.prod.v8 unknown Pre-installed, probably no real functionality except firmware update
DN1.0.2.12r.v2 be93342d27f6b837688a05098d240051
DN1.0.2.14r.v4 2af029ab917ed7825287f69abd2b4904
DN1.0.2.16r.v9 06a7f6d32c36ddea28019805e76c6c32 ok
DN1.0.2.17r.v5 4.3.0 387a2645c5f4117e294afeeb2c17b797 ok
DN1.0.2.18r.v9 4.4.0 9695d8562b4d6b8ee0f4461dc5633370 ok
DN1.0.2.19r.v5 ok
DN1.0.2.19r.v7 4.5.0 b0194f9ad9346319d20ee29b67c22dd6 ok
DN1.0.2.20r.v5 4.6.0 ok
DN1.0.2.21r.v1 4.6.0 ec75a07a151ef6b57a8fe4ad607371eb upgrading to this version will invalidate your auth key, see notes
DN1.0.2.22r.v4 4.7.0 b9b9bafcbcde0b6c08f8cdb6c086de9c ok
DN1.0.2.22r.v5 4.8.0 0cb3bc6391b3c9a546afecbc53e70f07 ok
DN1.0.2.23r.v2 4.9.0 981c168fb879047accdc22a5b695393c ok
DN1.0.3.0r.v3 5.0.0 6f650adf6da0ffde0d432a8edcc721bc ok
DN1.0.3.0r.v8 5.0.1 c9a2cca8f2bd2b09869c648ef8b4de15 ok
DN1.0.3.0r.v9 5.0.3 3dac8e6cdc2abad18883d23c4fa58fdb ok

Notes:

  • From DN1.0.2.18 up, more and more watch functions have moved from the firmware to watch apps. They can be uploaded with Gadgetbridge but we cannot re-distribute them. To make sure the watch is in fully working condition, upgrade it using the latest official Fossil app before switching to Gadgetbridge.
  • It's possible to switch back and forth between the original app and Gadgetbridge if required for some reason. However the watches' secret key may change if you re-pair it with the official app, so you may need to repeat the key extraction process described below after switching back and forth.

Connecting to Gadgetbridge

Obtaining the necessary secret key

Unfortunately the device is pretty locked down and it is necessary to use the official app at least once. This is has two reasons:

  1. The device seems to come with a demo firmware that is not functional and needs to be updated once. This can only be done in an official app. 2) There is a secret per-device key that gets negotiated with the Fossil servers. This process seems to be cryptographically secure, unfortunately.

You have to (later) make sure that the official app and Gadgetbridge do not collide with each other, perhaps have the official app installed on some other device and keep the device/bluetooth off...

We currently know of 4 methods to authenticate the watch and retrieve the auth key. They are outlined here, in increasing complexity:

Method 1: Using FossilHRAuthenticator

  1. Fetch the secret key from official servers. This allows the same key to be used in Gadgetbridge and in the official app. 2) Create a shared secret for Fossil HR watches and more - this app allows authenticating against all endpoints that support the same protocol. Use the values displayed in the README for retrieving the key from the Fossil servers.

https://github.com/dakhnod/WatchAuthenticator

Method 2: Use a python script to fetch the key

Click to see the code of the python script
#!/usr/bin/env python3
import requests
import sys
import json
import base64

def die(s, r):
	print(s, file=sys.stderr)
	print(r.text, file=sys.stderr)
	sys.exit(1)

if len(sys.argv) != 3:
	print("Usage: %s username password" % (sys.argv[0]), file=sys.stderr)
	exit(1)

email = sys.argv[1]
password = sys.argv[2]

base_url = 'https://c.fossil.com/v2.1'  # use for fossil watches
#base_url = 'https://api.skagen.linkplatforms.com/v2.1'  # use for skagen watches
auth_url = base_url + '/rpc/auth/login'
keys_url = base_url + '/users/me/device-secret-keys'

# add in the email and password
auth_fields = {
	"email": email,
	"password": password,
	"clientId": "xxx",
}

# try to fetch the auth URL with this username / password
r = requests.post(auth_url, json=auth_fields)
if r.status_code != 200:
	die("wrong username/password?", r)

token = json.loads(r.text).get("accessToken")
if not token:
	die("no access token in results?", r)

# now we can fetch the device keys using the bearer token
r = requests.get(keys_url, headers={
	"Authorization": "Bearer " + token,
})
if r.status_code != 200:
	die("access token not valid?", r)

devices = json.loads(r.text).get("_items")
if not devices:
	die("no devices in response?", r)

for dev in devices:
	devid = dev.get("id")
	key = dev.get("secretKey")
	if not key:
		die(devid + ": no secret key?", r)
	
	# only output the first 16 bytes of the secret key
	print(devid, base64.b64decode(key).hex()[0:32])

Method 3: Using a patched official app

There is a patched official app which will reveal the key. This will downgrade the watch firmware though, so after retrieving the auth key with the patched app, you will need to install the latest official app from the Play Store to upgrade the watch to the latest firmware. This will not change the auth key.

https://www.reddit.com/r/FossilHybrids/comments/k81kkq/unofficial_enhanced_android_app_based_on_v460/

Method 4: Get secret key from app cache (Skagen only)

NOTE: This method needs independent verification, at the time of writing only the author did it

You need a rooted phone for this to work

  1. Start with a clean slate, i.e. the official app must not be paired with your watch yet.
  2. Pair the watch as usual.
  3. Search for secret in the apps internal cache directory, e.g. for the Skagen app that is /data/data/com.skagen.connected/cache. There are many ways to do that, I used adb and the command grep -rIi secret ., you can do the same with termux or just copy that directory to your compute and search the directory with your favourite tools. I found the following (truncating some potential PI):
./cacheResponse/c4280c8aa94ab69d6fa8a9521d3dccc5.0:https://api.skagen.linkplatforms.com/v2/users/me/devices/D0S00212GU/secret-key
./cacheResponse/c4280c8aa94ab69d6fa8a9521d3dccc5.1:{"id":"...","uid":"...","secretKey":"DIcI3xns...d4K4mOh0=","createdAt":"2022-05-24T18:53:29.624Z","updatedAt":"2022-05-24T20:06:09.736Z","_links":{"self":"/v2/users/me/devices/.../..."},"_etag":"...","_isNew":false}

What we are interested in is the secretKey value.

  1. Convert the key to be used in Gadgebridge, see instructions below for mitmproxy (command includes hexdump).

Method 5: Using mitmproxy (sniffing decrypted https traffic)

NOTE: this section is probably outdated and needs testing

Requirements

To do it this way, you need the following

  • A rooted Android device (if you can use a junk tablet which is not your phone)
  • A PC running Linux on the same network
  • mitmproxy and knowledge of using of how to use it.

The procedure is generally speaking (there should be detailed tutorials on using mitmproxy elsewhere)

  • Run mitmproxy
  • Convert the auto-generated certificate to your rooted android phone in the appropriate folder
  • Setup iptables to forward traffic though mitmproxy
  • Test if mitmproxy works (you should see decryted output when you use the browser and go so some https site)

Running the Fossil App with mitmproxy enabled

  • Now when you register a new device you can inspect the traffic from/to Fossil servers in mitmproxy. Facebook is also fed with data. You cannot opt out, but you can block the traffic.
  • Look for a PATCH request to the Fossil server ending with /secret-key (even if it has a 404 response)
  • press enter on that request and loop at the JSON. There your will see a 256 byte key that is base64 encoded, it will look something like this: "secretKey": "eriwogvjmerighDFGWERj45jdfgsd345FDGdfgdfgdf="
  • Do the following (insert your key) echo "eriwogvjmerighDFGWERj45jdfgsd345FDGdfgdfgdf=" | base64 -d | hexdump -C
  • Take the first 16 bytes of the output, in our example this is 7a b8 b0 a2 0b e3 99 ea e2 82 10 c5 19 61 11 8f, remove the spaces and prefix with 0x, igrore the second 16 bytes (second line), we don't need it.
  • This is your key you need for Gadgetbridge (here: 0x7ab8b0a20be399eae28210c51961118f)

NOTE: You need to fininsh the firmware installation to the Watch, and then activate your watch, if the process is interrupted, you need to start over, and you will get a new key, the old one will be invalid, so make sure to keep mitmproxy running until the watch is usable.

Pairing and connecting to Gadgetbridge

  • Uninstall the fossil app if you plan to use Gadgetbridge on the same device you obtained the key on, unpair the Watch from Android settings if it is paired
  • Press the + button (Connect new device in the menu) in Gadgetbridge
  • In the "Discovery and pairing options" of this screen, you must have the "Disable new BLE scanning" unchecked, otherwise the Fossil will not be discovered. (Or, if you have "Discover unsupported devices" checked, the Fossil watch will be discovered as UNSUPPORTED. You should also check the "Companion device pairing", to allow for example "Find my phone" to work correctly in Android 10 and up.
  • Start discovery and wait for the Fossil watch to be discovered
  • After the watch is found, long tap on the "Fossil" Watch in the device list and enter (paste) the secret key into the Auth key. Make sure you have no line breaks or spaces in your input and that it starts with 0x. Then go back to the list of devices.
  • Tap on the Fossil watch in the list, the watch should start connecting now
  • You will be asked to Pair with Fossil. You should pair, otherwise the watch will keep asking to confirm device connection. Companion device pairing may ask for confirmation - confirm it.
  • Watch should connect

Factory reset

If you have hard time pairing the watch and you need to factory reset it, here is how. Source and more details on reddit.

  • Remove My Watch in the watch settings in the fossil app
  • Go to Bluetooth settings and forget the Fossil Watch
  • Press and hold the middle button until the watch buzzes hard and it resets
  • Set the watch on its charger
  • Press and hold the center button AGAIN until the watch resets again
  • Open the fossil app and “Pair my First Watch”

Device name

Depending on your model, the device should show a correct name (Q Commuter, Q Activist, Hybrid HR Collider).

Widgets on the watchface

In order to have widgets (complications) like date, steps, weather... on the watchface, you must enable it in the watch settings: long press middle button → Settings - Dial info → ON

Usage

Using Tasker, Easer or another automation app

Note: information taken from here, here and here.

Several of the usage descriptions below require the use of Tasker, Easer or another app that can send custom broadcast Intents.

Commute app

  1. Configure one or more Actions in Gadgetbridge. These will be your Commute destinations. Example: "Test"
  2. Create a profile in Tasker with the event "Intent Received" with the following content:
    • Action: nodomain.freeyourgadget.gadgetbridge.Q_COMMUTE_MENU
  3. Create a task in Tasker with the following content:
    • If: %extra_action EQ Test
    • Send Intent
      • Action: nodomain.freeyourgadget.gadgetbridge.Q_SET_MENU_MESSAGE
      • Extra: EXTRA_MESSAGE:Test action received!
      • Extra: EXTRA_FINISHED:true

You may set EXTRA_FINISHED to false if the watch is to wait for more content from the phone, and then send another intent with more content.

Custom widgets (firmware DN1.0.2.20r and newer)

  1. Configure one or more custom widgets in Gadgetbridge 0.63.0 or higher
  2. Note down the widget numbers as shown on the watch
  3. Create a task with name Send custom widget 0 config in Tasker and add the action Send Intent with the following content:
    • Action: nodomain.freeyourgadget.gadgetbridge.Q_PUSH_CONFIG
    • Extra: EXTRA_CONFIG_JSON:{"push":{"set":{"widgetCustom0._.config.upper_text":"%par1","widgetCustom0._.config.lower_text":"%par2"}}}
  4. Create more tasks like the above for every custom widget number. This greatly reduces complexity in using it later on
  5. To send data to the custom widgets, create another task which will retrieve/generate the text and add the action Perform Task with for example the following content:
    • Name: Send custom widget 0 config
    • Parameter 1: Home
    • Parameter 2: 21°C

Custom widgets (firmware DN1.0.2.19r and older)

  1. Configure a custom widget in Gadgetbridge
  2. Create a task in Tasker and add the action Send Intent with the following content:
    • Action: nodomain.freeyourgadget.gadgetbridge.Q_SET_WIDGET_CONTENT
    • Extra: EXTRA_WIDGET_ID_temp:21°C

Custom menu

Gadgetbridge 0.67.0 introduced a new custom menu functionality for the Fossil/Skagen HR watches. The setup and usage of this custom menu is considered applicable for advanced users only, so no direct support was built into Gadgetbridge. Instead, a separate Fossil HR Menu Companion App was introduced to configure the custom menu.

Because the custom menu is integrated in the Fossil HR Gadgetbridge watchface code, it is necessary to re-upload the watchface to the watch using Gadgetbridge 0.67.0 or newer. Watchfaces uploaded with older Gadgetbridge versions do not contain the custom menu functionality yet.

When a custom menu action is configured to send data to the phone, it will do so using a commute app event. Refer to Commute app for details on how to handle these events.

Custom text can be shown on the left side of custom menu screens. To do so, send a broadcast Intent using one of the apps mentioned before, in this format:

  • Action: nodomain.freeyourgadget.gadgetbridge.Q_PUSH_CONFIG
  • Extra: EXTRA_CONFIG_JSON:{"push":{"set":{"customWatchFace._.config.response":{"message":"text here","is_finished":true}}}}

NOTE: the physical menu buttons configured in Gadgetbridge will override the watchface-level buttons configuration from the Menu Companion app.

Custom apps

The Hybrid HR supports installing apps from non-official sources, even though the official Fossil app doesn't allow this. Gadgetbridge includes an App Manager that can upload apps to the watch and delete apps on the watch. Internally, uploaded watchfaces are apps as well, so they can be managed through the App Manager too.

Developers can use the Fossil HR SDK and its examples to develop new apps.

One example of a ready made app is Better Timer. It replaces the default Stopwatch App and includes timer, stopwatch and alarm functionality combined in one app. To install, simply download the .wapp file on your phone, then upload it using the Gadgetbridge App Manager.

Automatic watchface switching

With the latest firmware (DN1.0.3.0*), the watch can contain 2 watchfaces. It is possible to switch between these watchfaces via the app manager by tapping on them. Starting with Gadgetbridge 0.68.0 it is also possible to automate this step by sending an Intent from an app like Tasker.

Use the following contents in a broadcast Intent to switch watchface:

  • Action: nodomain.freeyourgadget.gadgetbridge.Q_SWITCH_WATCHFACE
  • Extra: WATCHFACE_NAME:NewWatchface

Activity tracking with OpenTracks integration

The official Workout app is supported by the OpenTracks integration. Just start a run or cycling workout and Gadgetbridge will automatically use OpenTracks for recording the track and providing statistics to the watch, exactly like the official app does without OpenTracks.

Do Not Disturb functionality

In the Hybrid HR settings on the watch, there is an option to mirror the Do Not Disturb mode on the phone. For this feature to work as expected, notifications will have to be sent to the watch regardless of the active Do Not Disturb mode on the phone. To achieve this, Gadgetbridge's global Do Not Disturb option in Notification Settings must be disabled. If this setting is enabled, all notifications that are suppressed by the phone's Do Not Disturb setting will be ignored completely.

Common issues and solutions

The watch asks for confirmation on every reconnect

Try pairing with the watch

Starting from some firmware version, the watch asks the user to confirm connecting devices. If this keeps happening every time GB is reconnecting, the watch is probably not bonded. To fix this, delete and watch from your phone's native bluetooth settings and disconnect GB. Then, open your phones native bluetooth settings again and try connecting to the watch from there, which should perform pairing with the watch. That way, the watch should memorize your phone and stop asking for confirmation every time GB reconnects. After you parired the watch to your phone, you can delete the watch from your phones settings again.