I recently was in the market for a watch. I wanted a smartwatch, but I wanted something that looked more like a normal watch, as opposed to a slab of silicon and a screen mounted on my wrist. I still wanted sleep tracking, athletic tracking, and notifications, but not with the changed appearance. I settled on a hybrid smartwatch from the Fossil Q Commuter series. However, I got to thinking: given that it interacted with an iOS app on my phone, maybe there was a way to hijack the commands, and run my own! A way to make the "dumb" smartwatch a little bit smarter.
Now there's some interesting work that's been done to write to the smartwatch, for functionality such as setting vibrations strength and some other things. This is being worked on as part of GadgetBridge, a GitHub repo for an Android application that allows you to write your own code to interact with a variety of smartwatches. It's not strictly speaking compatible with Fossil Q, but a Github user named dakhnod has been working on it. You can read about some of the discussion here on a post in the master repo. However, for my purposes I didn't need to be able to write to the device, just listen.
For the majority of the actions that you can map to one of the buttons, there's no direct interaction with the app. For things like pause, play, taking a photograph, and adjusting volume, it just acts like a normal input device, and goes through the main BT stack to trigger these actions. That seemed a little low level for me, but I realized that the "Ring Phone" and the "Commute Time" actions both needed actual information from the application, and that this could be hijacked. After logging a few of the
handleCharacteristicValueUpdated calls in the CBPeripheral stack within the Fossil app on my jailbroken iPhone, I realized that the handle 526 was used for both of these actions, and that the beginning (minus the first two characters which represented an increasing counter that looped) of the data indicated if it was "Ring Phone" or "Commute Time". Admittedly, this call was invoked almost 20 times for each button press, meaning that it was constantly polling, or making sure it went through.
All I had to do was hijack this call, listen for one of the two specific types, filter out all of the additional repeats of the same action (with the first two characters changing), and then invoke my own code. I packaged it up into a Cydia tweak, that is integrated with Victor. When you press the top button, it wakes up, and when you press the bottom button it goes into sleep mode. These two modes are reactive to what time it is, so the functionality varies, but it mainly involves controlling various electronics and lights in my room, alarms, and notifications. You can look at the source code here, although the compiled .deb isn't available (because it interacts with my personal system). Feel free to mess around with it, or turn it into an Activator tweak.