WearDash: build Wear OS dashboards for your HA entities from a YAML file

Hello, I’m new to the forum but I’ve been running Home Assistant for years.

I built WearDash because I wanted to run my home from my watch. Check the living room sensors, drive the fan, arm the alarm, without using my phone.

The Home Assistant companion was not working for me: my instance sits behind my own CA, Wear OS gives apps no way to trust a custom certificate, and everything I tried failed the handshake. So I wrote an app that carries its own trust, and it ended up polished enough to share.

It’s a standalone Wear OS app, nothing runs on the phone. You describe your dashboard in a YAML file and the watch renders it as swipeable screens, tiles and watch face complications. It talks to your HA directly on your network, and it’s not limited to HA: any REST API works as a source. Some of my screens pull from Open-Meteo and CoinGecko next to my HA entities using the same YAML file.

I also built a wysiwyg editor in the browser. You drag blocks onto a live watch preview, pair with a code shown on the watch, hit send. The watch keeps the config, my server stores nothing.

You declare your Home Assistant connector once, sources and actions stay short:

connectors:
  ha: { type: home_assistant, url: "https://ha.example.com:8123" }

secrets: [ha_token] # entered once on the watch, never stored on my servers

sources:
  fan: { entity: fan.living_room, refresh: 30 }
  temp: { entity: sensor.living_room_temperature, refresh: 120 }
  co2: { entity: sensor.living_room_co2, refresh: 120 }

actions:
  guard_home:
    type: ha
    service: select.select_option
    data: { entity_id: select.house_guard_mode, option: Home }
    then_refresh: [guard]

Buttons can react to state:

- {
    type: button,
    label: "Home",
    icon: shield-home,
    action: guard_home,
    color: "{{ guard.state == 'Home' ? '#2e7d32' : '#2c2c2c' }}",
  }

You can try the app without Home Assistant. There’s a public demo config on open APIs, no account or token: install the app, Settings → Config URL, paste https://weardash.app/c/demo. You get five screens with live data (weather, air quality, GitHub status + ISS, Bitcoin, ECB rates). If you only want to try the editor without a watch, there is a demo with example configs, including HA here: weardash.app/demo

In terms of security:

  • your tokens never reach my servers. Pairing derives a key from a short-lived code shown on the watch, and the config and secrets travel encrypted end to end. The relay can’t read them.
  • TLS is handled per host: custom CA, pinning on first connection (like SSH), client certificates from a .p12. Nothing is ever trusted globally.
  • the editor and relay are open source (AGPL) and self-host in one container: github.com/weardash/selfhost. If my server disappears, the app keeps working!

There’s also a native Android TV connector (the Remote v2 protocol, pairs directly with the TV), so you get a d-pad and voice search without going through HA.

Play Store: WearDash.

Free tier is one screen and one tile with no limit on what you put in them. Premium unlocks the rest, one-time $6.99, no subscription!

Curious what you’d want to write in the YAML that it can’t do today, the format is still easy to change. I built this for myself and use it daily, but I’ve only tested it on my own Galaxy Watch and the emulator, so reports from other watches are welcome. I can also add presets to the wysiwyg editor :slightly_smiling_face:




5 Likes

This message was translated from Japanese into English with the help of AI.

I’ve been testing WearDash on a Google Pixel Watch 4.

I really like how easy it is to create Wear OS screens and tiles using only YAML, especially for simple control interfaces that use HTTP actions.

At the moment, I’m using WearDash to control a SESAME smart lock through Google Apps Script.

My setup is:

  • Google Pixel Watch 4
  • WearDash Screen / Tile
  • HTTP GET actions
  • Google Apps Script calling the SESAME API

One thing I noticed is the response time when executing HTTP actions.

Using the same Pixel Watch 4, the same Google Apps Script, and the same SESAME lock, I get roughly the following:

  • AutoWear: about 3 seconds until the lock starts moving
  • WearDash: about 5 seconds
  • WearDash can sometimes take around 7–8 seconds

This is not a precise benchmark, just a real-world observation from using both on the same device and backend.

I also noticed a difference in haptic feedback.

On a WearDash Screen, the watch sometimes vibrates when I press a button, but on a Tile it appears not to vibrate.

For something like a smart lock, where the result is not always immediately visible on the screen, a short haptic feedback on Tile button presses would be very useful because it would confirm that the tap was registered.

So far, on the Pixel Watch 4, the basic Screen display, Tile display, HTTP actions, and then_refresh are working.

I’ve only recently started using WearDash, but I find the concept very interesting and plan to keep testing it.

I hope this Pixel Watch 4 feedback is useful.

2 Likes

Hi, thanks a lot for the detailed report. Your feedback is really useful, especially since you’re testing on a device I don’t have!

About the latency: I think part of the difference comes from how the two apps work. As far as I know, AutoWear sends the HTTP request from the phone through Tasker. WearDash is standalone, so the request leaves from the watch itself, usually through the Bluetooth connection to the phone, and that makes the HTTPS handshake slow. Google Apps Script also redirects /exec to a second host, so the watch pays that cost twice.

Still, 7 to 8 seconds is too much. I have a few ideas to try: keep the connection open between requests, connect in advance to the hosts from your YAML when a screen opens, and speed up startup when the action comes from a Tile. I’ll add some timing logs first to see where the time really goes and I will try to optimize that.

About haptics: you’re totally right. Tiles are drawn by the system, so nothing vibrates on tap unless I trigger it myself. I’ll add a short vibration on button press for both Tiles and Screens. I’m also thinking about a different vibration for success and failure of the HTTP action, which makes sense for a lock.

One question: when you test, is your watch connected to the phone over Bluetooth, or directly on Wi-Fi or LTE? It would help me reproduce your numbers.

Also, since you’re my first real user, I’d like to give you a free premium code. I’ll send it to you by private message :smiley:
(Edit: it seems that this board does not have private messages. If you send me an email at [email protected], I’ll reply with the code!)

1 Like

Actually it does but you likely need a few posts under your belt before that permission is granted.

(This message was translated from Japanese into English with the help of AI.)

Thanks for the detailed explanation!

Just to clarify one point: in my AutoWear test, I’m not using Tasker for the HTTP request.

Both AutoWear and WearDash are configured to call the Google Apps Script URL directly, so as far as I understand, the network path should be basically the same in my comparison.

For the test, I disconnected the Watch from my main phone over Bluetooth and connected it to the Internet through Wi-Fi tethering from a second phone. The intention was to simulate a more independent mobile connection, similar to LTE.

I also tested both again recently, and now AutoWear and WearDash are both taking about 3 seconds from pressing the button until the SESAME lock starts moving. So the larger difference I originally observed is no longer consistently reproducible.

There is one other behavior I’ve noticed with WearDash.

Sometimes the SESAME lock/unlock operation succeeds, but WearDash still shows Failed:network in red afterward.

Since the lock itself moves successfully, the HTTP request seems to reach GAS, and something may be happening afterward while processing the response.

In terms of usability, I personally prefer WearDash quite a lot.
For my use case, WearDash is much easier to configure, and the YAML-based screen design and customization are much better suited to what I want to build.

At the moment, the one area where AutoWear is clearly better for me is haptic feedback.
So I’d definitely like to see haptic feedback added to WearDash for Tile button presses.

And thank you very much for the Premium code offer!
I’ll send you an email shortly.

Hello folks, just wanted to chime in here. I just found WearDash and I am in love with it. Bought the premium version today, started using it yesterday.

Years ago I used to have an app that would control my thermostat from my watch and then google or someone changed the rules stopping it from functioning and there was no workaround (I don’t remember the details).

So I now have a Samsung Galaxy Watch Ultra2 - and Home Assistant - and did alot of digging, there is a thermostat tile in the HA Wear OS app - but it does not (as far as I can tell) allow you to switch between air conditioning and heating, etc… it’s very basic.

So I used WearDash and created a very slick fully functional thermostat tile - and now I am building my next (unrelated) tile now. Anyway, I thought I’d show folks the one I built (fully functional with heat, air conditioning, Auto, or just Fan, and On/Off)…

I had to come back say I just created my second one. It’s a little ugly but very useful:

@Nand42 , Hi, thank you for all this, see my screenshots above… could you explain the intended purpose of the Added Tiles section under Settings?

I now have two WearDash Tiles added to my watch, Thermostat and Forecast, and both are working correctly. However, I’m having trouble understanding what the settings entries under Added Tiles represent.

For example, I’ve seen the same Tile name appear more than once, some entries have checkmarks and others don’t, and I’ve seen them grouped under entries such as Tile #45. The contents don’t seem to map in an obvious way to the two WearDash Tiles that I actually have added to Wear OS.

Is each Tile #xx supposed to represent a particular Wear OS Tile instance? And within that, what do the repeated Tile names and checkmark indicate?

In other words, I’m not necessarily reporting a problem. I’m mainly trying to understand what Added Tiles is intended to show and how I should interpret it.

Thanks!

@ah1060815 thanks for the clarification, it changes how I read your first numbers. With both apps calling the Apps Script URL directly and the watch on its own Wi-Fi, the network path is the same, and 3 seconds on both sides is what I’d expect from Apps Script itself: it runs the whole script, including the SESAME call, before it answers.

The “Failed: network” you saw after a successful unlock is on me. WearDash gave Apps Script 4 seconds to answer. When the script took longer (cold start plus the SESAME API), the watch gave up and reported a failure while the lock was already moving. Two changes in the next version: a tile action now waits up to 10 seconds for the answer (15 on a screen), and when it does run out of time it says “timeout” instead of “network”, so you know the request left the watch.

Haptics on tiles are in that same version: a short click as soon as the watch receives the tap, and a long buzz if the action fails. Nothing on success, the tile just redraws. I tried a double tick there and found it annoying.

That version is uploaded and waiting for Google’s review. I’ll post here when it’s live!

@KruseLuds thanks a lot for the purchase, and for the screenshots. That thermostat tile is exactly the kind of thing I hoped people would build: the HA Wear OS app gives you a basic one, WearDash lets you decide what goes on it. Your “A Wear OS app” screen also gave me ideas for new UI components, in particular a curved text that follows the top edge of the round screen. I’ll add that to the list.

About “Added tiles” in Settings, you’re not missing anything, it’s just not explained anywhere. Each “Tile #45” line is one tile slot you added to the Wear OS carousel. The number comes from the system, it’s the id Wear OS gave that slot, which is why it doesn’t mean anything. The arrow after it shows which panel of your YAML that slot is currently displaying.

When you tap a slot, you get the list of everything that can go in a slot: every entry under `tiles:` plus every screen that no tile already uses. The highlighted one with “shown” is the panel this slot displays, the others are just the available choices. The same names appear under every slot because each slot lists the same catalogue, not because anything is duplicated.

If you see more slots than tiles you actually have on the watch, those are leftovers: when you remove a tile from the carousel, Wear OS doesn’t always tell the app, so the old slot stays in the list. Picking any of them does nothing harmful.

I agree it’s confusing, and I’ll clean it up: show the panel name instead of the system number and drop the slots that no longer exist. If you noticed a name appearing twice inside the same slot, tell me which one, that may be a real duplicate in the catalogue.

Thank you @Nand42 for your thorough answers.

There are some duplicates it appears under “Added Tiles” so here is what my watch shows. My first tile on the watch is Thermostat, the second one is Forecast (I only have two right now) :slight_smile:



Also for the thermostat for example, since the temp change message goes all the way back to the ha server and then back to the watch, there is a slight delay, but with the current implementation each press is only 1 degree, so I added the double arrows which are actually a 3 degree change. Ideally there would be sliders (can yoo make one that has two values on it which wouild be great for Auto for a thermostat?) , and I know you offer a single value horizontal slider, but with tiles sliding left and right I believe would just move you to another tile, no? I was thinking the resolution to this for my thermostat it to have vertical sliders, but you do not offer those it seems. How hard would it be to offer vertical sliders without affecting where text and buttons can be shown on each side of the sliders? And since you are making curved text - how about a curved slider, two versions, with one point on the line and with two pooints on the line. Also maybe specify the size, degrees of curvature (of course less than 360 which would be a circle) and mayb e the angle of the curvature? (That may be overkill lol!) Maybe the curve could be around the outer edge of the watch and all the text and other buttons inside it :slight_smile:

lastly as an architectural question -

I was surprised to see all the code for all of the files goes into one file. At first I thought it would be better if they were in different files, but actually, this is a better architecture because code can be shared across tiles. So I do have one broader architecture question.

I see that sources and actions are defined globally, and actions can be called by multiple blocks. That means several screens/Tiles can already share common data and logic rather than each Tile being a completely separate little application.

How far do you envision taking that idea? :slight_smile:

For example, could WearDash eventually support reusable components/layout fragments, shared local state or variables, and especially local navigation between screens?

The navigation part is particularly interesting to me. Could a button on a Tile someday say, in effect, “display screen X in this same Tile,” without making a Home Assistant/API call?

If so, one physical Wear OS Tile could become an entry point into several related WearDash screens. For example, a Home Tile might have buttons for Climate, Alarm, Network, etc., with each opening another locally rendered WearDash screen and a Back/Home button returning to the first screen - all on the first tile if the user wants it so, and also the buttons would work instantly!

Since Wear OS limits an app to five Tiles, that could make the five Tiles more like five entry points into a much larger WearDash interface.

Is the current architecture capable of evolving in that direction, or are screens/Tiles deliberately isolated at the layout/state level?

Thank you for this!