Announcing openHAB for Wear OS

Hi everyone,

I’m happy to share a project I’ve been working on: a standalone Wear OS app for openHAB. It brings quick smart home control to your wrist — toggle lights, adjust temperature setpoints, check sensor values on your watch face, send voice commands — all without needing your phone.

This has been a long-requested feature in the community (thread 1, thread 2, thread 3), and with the Garmin app already available, the wearable ecosystem for openHAB is growing nicely.

How It Works

The app uses a Wear OS Tile as the primary interface — you swipe from the watch face and your openHAB controls are right there. No need to open an app. Configuration is done entirely on the openHAB server side using wearTile item metadata.

There is no dependency on the openHAB Android phone app. The watch connects directly to myopenhab.org (or your local server) over WiFi or LTE.

Features

Tile (Primary Interface)

  • 1-7 items per page in a concentric honeycomb layout, auto-sized to screen
  • Multi-page navigation — organize items into sub-pages (Security, Climate, etc.)
  • Toggle switches — lights, outlets, scenes. Tap to toggle, state updates via SSE in real-time
  • Range controls — use the rotating bezel/crown to adjust dimmers and temperature setpoints
  • Command buttons — send fixed commands (gate pulse, scene activation) with optional confirmation dialog
  • Read-only sensors — display Contact/Number item states without tap action
  • 5 color themes — amber, blue, green, purple, red. Selectable via long-press on the tile
  • Dim/Lit state machine — tile appears dimmed until fresh states arrive from server, preventing commands against stale state

Sub-Pages & Navigation

Organize items into pages — tap a navigation button to enter, back arrow to return:

Range Control (Bezel/Crown)

Tap a temperature or dimmer item to open a full-screen control. Rotate the bezel to adjust the value:

Watch Face Complications

Display openHAB item values directly on the watch face — no app needed:

  • SHORT_TEXT — compact value with label (e.g., “27.5 °C”)
  • LONG_TEXT — full label and value
  • RANGED_VALUE — progress arc for numeric values (dimmers, temperatures)

Items are marked for complications in the same wearTile metadata. Multiple complications can be added to the same watch face, each showing a different item.

Voice Commands

Tap the mic button on the tile → speak a command → it goes to openHAB’s voice interpreter. Uses the watch’s system speech recognizer and your configured Human Language Interpreter (system or rule-based).

Themes

5 color themes, selectable via long-press on the tile → pencil icon. Rotate the bezel to preview:

Configuration

All configuration happens on the openHAB server — the watch only reads. You add wearTile metadata to items, either via Main UI, REST API, or .items files:

// Simple light toggle
Switch Bedroom_Light "Bedroom" <light> { wearTile="tile" [position="1", icon="light", valueDisplay="color"] }

// Gate with confirmation and separate state sensor
Switch FrontGate "Gate" { wearTile="tile" [position="security:1", icon="iconify:mdi:gate", valueItem="Gate_State", action="command", commandValue="ON", needsConfirmation="true", valueDisplay="color"] }

// Temperature complication on watch face
Number:Temperature BDR_Temp "Bedroom [%.1f °C]" { wearTile="complication" }

// Both tile and complication
Number:Power Solar "Solar [%d W]" { wearTile="tile" [position="3", complication="true", icon="solarplant"] }

The metadata supports:

  • Custom icons (openHAB classic, Material, Iconify/MDI)
  • Display as color (accent/grey) or text value
  • Separate value source (valueItem) and command target (commandItem)
  • Navigation to sub-pages (action="page:security")
  • Confirmation dialogs for irreversible actions

Full configuration documentation: docs

Requirements

Requirement Details
Watch Wear OS 5+ (SDK 34). Tested on Samsung Galaxy Watch Ultra
Connection WiFi or LTE. Connects to myopenhab.org or local/remote server via HTTPS
openHAB 5.x recommended (uses REST API + SSE)
Phone Not required. Standalone operation.

Current Status

The app is functional and in daily use on my Samsung Galaxy Watch Ultra. It’s not yet on Google Play — I’d like to gather some community feedback first.

What works well:

  • All tile interaction modes (toggle, range, command, navigation, display-only)
  • Real-time SSE state updates
  • Complications with periodic refresh
  • Voice commands via openHAB interpreter
  • Push notifications
  • Theme picker with bezel rotation

Known limitations:

  • Tested only on one device (Galaxy Watch Ultra, 480×480 screen). The concentric layout adapts to screen size but hasn’t been verified on smaller watches
  • Complication refresh is system-managed (every ~15 minutes) — not instant
  • Requires HTTPS (works out of the box with myopenhab.org)

How to Get It

The app is distributed via Google Play — Wear OS does not allow sideloading APKs directly to the watch. It’s currently in internal testing on Google Play.

If you’d like to try it out, send me a private message with the email address associated with your Google Play account. I’ll add you to the internal testers group and you’ll be able to install it from the Play Store.

Requirements:

  • A Wear OS 5+ watch (Samsung Galaxy Watch 4/5/6/7/Ultra, Pixel Watch, etc.)
  • An openHAB 5.x instance accessible via HTTPS (myopenhab.org works out of the box)

I’d love to hear your feedback — especially from people with different watch models. Let me know if you have questions about the configuration approach or feature requests.

Source code | Documentation

Preliminary reports on a Pixel 4 Wear OS 7.

  • After entering the username and password tapping “Save and Connect” doesn’t seem to have any effect. Once I enter the user and password it lights up like I should be able to tap it but nothing happens. If the screen goes blank I get a connection error and when I click “retry” the username and password get reset to empty.
  • If I wait long enough I eventually get some sort of HTTP error. First I got a 401 but that makes sense as I misstyped my password. When I got the password correct I got a 502 gateway error and then “Unable to resolve host myopenhab.org”.
  • The password entry is a plain text entry which means the keyboard remembers the password. While this was convenient for me right now as I tried to connect several times and I use randomly generated passwords, long term it should be made a password field so the keyboard doesn’t remember it and potentially expose the password to other apps.

I’m pretty much stuck there.

hi,

Pls check you can reach https://home.myopenhab.org/ from any browser (openHAB Cloud can reach your instance). Make sure you enter https://myopenhab.org as server address. Works for me… And you are right - tha password field needs to be fixed…
BR

I installed Mini Web Browser and I can reach that address using it on the watch but it just returns “unauthorized” as expected since it’s not logged in. The phone can reach home.myopenhab.org as well and it pops up an auth dialog. I suspect the mini browser can’t do popups.

I tried leaving the address that was already in there in the openHAB app and I also tried to manually add the URL. Most of my tests I just left the default so I don’t know what combinations of what entries I tried (i.e. if I had the right password in combination with manually entering the URL).

Interestingly I went back to test it with entering the URL as well as username and password and my username and password were still there. But I still got the 502 error but then I got a Connected!. So definitely progress!

Eventually it would be nice to be able to do the LAN/Away type config as it’s in the Android app where it uses the local address when home and the cloud server when away. But I can at least progress to more testing.

I think the finding here is that even though the URL field looks like it’s prefilled, it doesn’t seem to be accepting it as being prefilled and needs to be manually entered.

yep, this was a bug. if you had a typo in the server name it did not let you to overwrite it… released a new version. remove pls the existing app and reinstall. current version is 0.9.0 (6)
br

Looks like I was able to just update, which was nice. Running 0.9.0 (6). the save and connect button still doesn’t seem to do anything though. It saved my server settings from before and “Reload Items” seems to work without error. I haven’t tagged any Items yet.

Is there anything specifically you want me to try? Maybe reenter the URL and credentials to break them and then correct them?

When you press save and connect it should confirm connection with “Connected! Done”. Items are cached - when you change items config hit “Reload Items”. Don’t bother with this login thing, i’ll have it covered with unit tests… Just set up your home as you like and give me a feedback later with the real life usage…

Looking at the metadata, it doesn’t appear to be possible to put the same Item on a tile and as a complication. Is that correct?

you can do that: config

# Tile only — a light switch
wearTile = "tile"          [position="main:1", icon="light"]

# Complication only — a temperature sensor shown on the watch face
wearTile = "complication"

# Both — solar power on the tile AND as a watch face complication
wearTile = "tile"          [position="main:3", complication="true", icon="solarplant"]

I’ll have more to report tomorrow. Out of time today.

@maniac103
Hey Danny,

Lets continue the watch - phone topic here. I agree the setup experience should be seamless — credential sharing via Data Layer is the clear path forward. The watch already has a receiver for it (WearDataLayerListenerService), I just haven’t added the sender to the phone app yet because I wanted to avoid touching both repos simultaneously during initial development. That’s next.

Beyond credentials though, I’d keep the watch as a direct REST client. In the openHAB model, the server is the configuration authority — the phone reads from it what to display, and the watch does the same (via wearTile item metadata, configured in MainUI). Both are first-class clients, neither needs the other for data flow.

Routing item state through the phone would mean watch-specific relay code in the phone app, a standalone fallback for when the phone isn’t reachable, and two data paths to maintain — for no real gain over the watch just talking to the server directly.

So the plan: share credentials via Data Layer (phone → watch), everything else stays server-driven on each client independently.

Does credential sync cover the UX concern you had, or is there something else you’d want the phone to push?

I seem to be having a similar issue as @rlkoshak. I put in my credentials for myopenhab cloud. I hit “Save & Connect” and nothing happens for a while. After a while I get some type of error, either a Bad Gateway and/or a connection timeout.

BTW, it’s incredibly annoying and time consuming to have to reenter my username and password every time I want to try to reconnect. :frowning:

Edit: BTW my Pixel 3 watch does not have LTE… just WiFi.

i know… sorry for the credentials… that will be the next to do but that is on the andoid app side…

Hi Gabor,
I played around with the app on a Samsungs Ultra (SM-L705F), pretty useful I must say,
being able to handle e.g. garage door, driveway lights or garden irrigation without the need for the phone is gold.

Some feedback that I can give to you:

  • For navigation tiles: Currently I see the “technical” name of the navigation target in the target tile as header label.
    Suggestion: Add a attribute for the target tile label (e.g. targetLabel) where one can override the technical name.
  • A navigation tile should be able to show the value of a specific item.
    Example: Fan speed, possible entries quiet, low, medium, high, power, auto
    Sending an explicit value as those requires me to setup a nav tile (“Fan”) for the fan speed, leading to a screen containing 6 tiles with fixed values that simply send the required value to the fan speed item. The initial “Fan” item should show the actual value, but I didn’t manage to show the value of an item .
  • Tile display type: Currently there is color and value.
    What I am missing is “none” - for e.g. command items this makes sense - see above:
    "color"does not fit, “value” either shows “-” when the item below is unbound/has no value. Should be possible to display nothing here.
    Otherwise the 6 tiles menioned above all show “-” or e.g. the actual fan value 6 times.
  • Multi value items in general:
    It is a bit hard to set up all the items needed to send predefined allowed values to an item (See fan speed example above).
    The information on allowed values is already present in the item/channel on OH, so how about a tile of type “choice” that, when clicked, automatically opens a screen with the allowed values as command tiles (Or maybe choosing them directly from a list you can scroll ?).
    The command item should be configurable from the “choice” tile, where also the actual value (display item) must be shown.
    Another possibility would be to define a list of values to be shown together with the text to be display in the “choice” tile that can then be used to build the options screen.
    Would make things way easier and limit the number of items (for each of such items you currently have to create n value items). A custom list would enable the user to limit the number of options for usability reasons.
  • When presenting values to be selected from the current values tile should be in a diffent color/ bold /… to see what would be a change and what not.
  • When the configuration of the meta data is not perfect or buggy the app does not show any error when manually syncing the config, it would be helpful to at least get a hint here.

Overall the app is very responsive, commands are sent fast, setup was easy, no issues with the credentials (except the keyboard on the watch is a tiny little beast…).

A general question arose during the setup:
I copied existing items to save time (tag, parent groups, naming convention). This works fine except the metadata is not being copied (OH5.2). Anyone knows if this is intentional or some sort of a bug?

Greetings,
Thomas

To be honest, I do not think this is a good idea. My reasoning for that bases on a few assumptions (which you are free to dispute):

  • Most watch users will use a Wifi-only watch
  • Most Wifi watch users will carry both phone and watch (because the watch isn’t too useful without phone)
  • Wifi is significantly more power hungry than the BT connection to the phone, LTE likely is as well (but I have personally experience only with the former)
  • A permanent SSE connection is needed (e.g. for updating a value in a complication)

I’ve also not looked at the actual code yet, but am basing judgement on the architecture.md file in your repo.

What will follow will sound a bit negative, because I’m questioning some base assumptions of the app design, but I want to mention beforehand that negativity is not what I want to express. I have had the thought of the need of a Wear OS app for quite some time now, but always lacked time, so I find it amazing that somebody (IOW, you) stepped up and started to work on that :+1: I’m just looking at it from the perspective of a maintainer of the official app, and in that view, some shortcuts that work in a private app don’t work in a global scale. I’m mentioning those points because I’d ideally want this approach/app to become official (tile + complication is a very good idea!), not because I want to belittle your work.

With that out of the way:

The not using it would waste the hardware seems like a weak argument. We should use it when needed (that is, if a more lightweight connection is not available), but not burn through the user’s watch battery needlessly.
For the phone connection is unreliable argument, I’d like to draw the following table:

Scenario Use watch only Use phone connection + watch as fallback
Watch connected to phone, phone and watch connected to Wifi Works, but inefficient Works
Watch connected to phone, phone connected to mobile network, Wifi-only watch does not work at all Works
Watch connected to phone, phone connected to mobile network, LTE watch Works, but inefficient Works
Watch not connected to phone, Watch connected to Wifi Works Works
Watch not connected to phone, Watch not connected can’t work can’t work
Watch not connected to phone, Watch connected to LTE Works Works

It becomes apparent that we need the phone connection handling anyway to cover Wifi-only watches when no Wifi is in reach. As soon as we have that in place, we can very well always use it if present to make the watch battery last longer.

The OH REST API is lightweight enough argument also doesn’t seem really strong: how was ‘lightweight enough’ determined? After all, we (might) need a permanent SSE connection.

This also doesn’t seem like a good choice to me. The cloud connector handles authentication and proxying transparently if (and only if) item access for the cloud connector is actually enabled. There will be plenty of users having this disabled for security/trust reasons. For those users, that approach does not work at all. Those users will happily accept that VPN [is] required on the home network.
Also, Same approach the existing mobile app uses is not true: the mobile app switches seamlessly between direct server connection and cloud connector, dependidng on the availability of the former. A lot of the app’s complexity is used for that switching (and could be reused when using the mobile app as proxy, see first item).

While I find the use of item metadata a creative and clever approach, it also has a clear downside: Multiple watches can share the same configuration actually should read Multiple watches *must* share the same configuration, because there’s no way to have different configurations for different users. This is different to at least sitemaps, where each user can have their own sitemap. I think the same applies to MainUI pages as well.
Also, there’s no way to adjust the presentation (e.g. choosing a different label or icon just for the watch presentation without changing the item itself).

Looking at how the 6 interfaces (mobile, auto, watch for Android and iOS, respectively) collect their data to display also makes me wonder whether we sholdn’t have core support in one way or another:

  • mobile apps use sitemaps (makes sense, all widgets supported)
  • Apple Watch uses sitemaps (but supports only a subset of widgets)
  • CarPlay uses sitemaps (but uses it only as a sorted set of items, I think)
  • Android Auto (preliminary PR) uses sitemaps (but supports only a subset of widgets and a limited nesting depth)
  • Wear OS (this thread) uses item metadata

I wonder whether we shouldn’t have some way to let the user prepare a sorted list of items with label and icon override. A sitemap that consists only of default widgets, if you will. And have the car and watch apps use that instead of each using their own workaround.
@timbms @Lolodomo @mueller-ma Thoughts on this?

I know that text is just AI glazing its own decisions, but as a co author of the mobile app I still have to comment on this:

  • There’s a reason for using XML layouts beyond ‘legacy’: compose widgets simply are very limited. There’s e.g. no WebView.
  • There’s also a reason for ‘no DI’: reducing complexity and code size at the cost of negligible gain (for the handful of global objects, using some extension methods is sufficient since we have a global object in the form of the application context anyway)
  • Retrofit would be worth a thought, but I’m not sure it’s worth it (we still need to keep compatibility with OH 1.x XML API, and using Retrofit would make this more complicated)
  • no shared code can also be seen as a negative point :slight_smile:

I can tell you for sure that mobile and wear app need both the same package name and same signature for the data layer API to work. On the plus side, that API also allows detecting whether a phone with installed app is around or not.

Thanks for the detailed response — I appreciate you taking the time and looking at this from the maintainer angle. Let me address your points and lay out where I think we align and where I see things differently.

Connectivity & Battery

I agree with your premise: most watch users carry both devices, most watches are WiFi-only, and BT is cheaper than WiFi for network traffic. No argument there.

Where I disagree is the conclusion that this requires an app-level relay through the phone app via Data Layer. Wear OS already handles this transparently at the OS network layer — when the watch is BT-connected to the phone and has no WiFi, HTTP requests are routed through the phone’s internet connection automatically (Bluetooth Network Proxy). The watch app just makes normal HTTPS calls to the server; the OS decides the transport (WiFi, LTE, or BT proxy through phone). The app doesn’t know and doesn’t need to know which path the packet takes.

So looking at your table: every “Use phone connection” scenario already works without any code in the phone app. The watch makes an HTTP request, the OS routes it through BT → phone’s network when WiFi/LTE isn’t available. No MessageClient, no Data Layer relay service, no custom proxy logic needed.

The only thing the Data Layer API is needed for is the one-time credential sync on first setup (so users don’t type passwords on a 1.5" screen). Runtime traffic stays as plain HTTPS, routed by the system.

Cloud vs. Direct Connection

The architecture doc frames myopenhab.org as the primary path, but direct server URLs work today — you just enter your local/VPN address instead. I agree seamless switching (local when home, cloud when away) is good UX and should be added. But it’s an enhancement, not an architectural gap.

The “plenty of users have cloud connector disabled” concern is addressed: they enter their server URL directly. Works the same as the mobile app’s remote URL setting.

Item Metadata vs. Sitemaps

This is where I want to push back more firmly.

Sitemaps are the legacy configuration interface. The mobile app’s primary mode is MainUI via WebView — a full Vue.js SPA rendered client-side. Sitemaps are the secondary/fallback. Apple Watch uses sitemaps and is limited because of it. Android Auto uses sitemaps (preliminary) and inherits those limitations. Building a new app in 2026 on sitemaps means building on a foundation the project itself is de-emphasizing.

Item metadata is how modern openHAB extensibility works. Semantic tags, widget configurations, persistence strategies — all metadata. Users who configure their home in MainUI are already familiar with this pattern. Adding wearTile metadata is the same mental model as adding a semantic tag. No separate file to maintain, no “I set up my home in MainUI but now I need a sitemap for the watch.”

The metadata approach also already provides the “sorted list of items with label and icon override” that you’re proposing as a new core concept. That’s literally what it is — position for ordering, label for override, icon for override, all attached to the item. The mechanism is already REST-queryable (GET /rest/items?metadata=wearTile), requires zero core changes, and works today.

Per-user configuration

Fair point — metadata is per-item, not per-user. In practice: I’ve yet to meet a household where two people each have their own Wear OS watch pointed at the same openHAB instance with different tile layouts. But if this becomes a real need, a user-scoped namespace (wearTile.{user}) is a natural extension that stays within the same architecture.

Unified config for thin clients

I like the concept — watch, auto, carplay all need roughly the same thing: a flat/shallow list of items with position + icon + label + interaction mode. But this is a core framework proposal with a multi-month timeline. It shouldn’t block shipping what works today. If a core mechanism emerges, the watch app migrates to it — the item-based model is the same regardless of whether the metadata namespace is wearTile or some future core concept.

Tech stack

No commentary intended on the mobile app’s choices — they make sense for its scope and history. The watch uses Compose because Wear Tiles require it (there’s no XML path for ProtoLayout tiles). Hilt/Retrofit/DataStore are appropriate for a small, new, Kotlin-only module. There’s no meaningful code to share between a WebView-based phone app and a tile-based watch app — they solve fundamentally different rendering problems.

Path forward

What I’d propose:

  1. Credential sync via Data Layer (phone → watch, one-time setup) — this requires same package/signature, which means either the watch ships under the org.openhab.habdroid umbrella or gets linked via Play Console.
  2. Runtime stays plain HTTPS, OS-routed. No app-level relay.
  3. Metadata stays as the config mechanism. If core introduces a “thin client presentation” concept someday, the watch adopts it.
  4. Local/remote URL switching as an enhancement (mirrors phone app behavior).

Happy to discuss further — especially interested in the practical path for the package/signing alignment if this moves toward official.

OK, I wasn’t aware of that yet. Point taken, network is not an issue then.

How does the Wear app handle loss and reestablishment of network connection? Because that’s what’s going to happen when connecting and disconnecting VPN.

Where do you get this blanket statement from? It’s for sure not true.
It’s true that sitemaps are older than MainUI pages. It’s also true that they’re less configurable. But: a lot of people use sitemaps because they’re less configurable, including quite a few maintainers. They’re not going anywhere soon. They’re in fact also not a fallback, the default UI of the mobile app (at least on Android, I think it’s the case for iOS as well), because they can be rendered using OS native UI. Apple Watch is not limited by the sitemap itself, but by the screen size. Android Auto is not limited by the sitemap, but by the AA limitations regarding UI options (I happen to have written that code).
Did the AI go a little overboard here?

More AI going overboard. It requires zero code changes, right. And at the same time, it provides a sub-par UX. Inserting a second item to a 6 item list requires me to make changes to metadata of 6 items (the new one and the ones at old positions 2 to 6). It also requires each client to do additional validation (non-unique positions).
And about the label and icon, I specifically mentioned being able to set per UI labels. A meaningful label depends on context. I might want to label some temperatures Indoor temperature and Outdoor temperature, but in a list of temperatures I might want to label them Indoor and Outdoor. Doing so is impossible if there’s only one label to work with.

In my book, Hilt is pretty much overengineering especially ina small app, no matter whether it’s new or not. Also, nobody was talking about a WebView-based phone app, that’s AI hallucination.

TBH, I’m starting to understand @Nadahar … talking to AI generated texts that only roughly answer the brought up points, make bold statements without justification and misinterpreting stuff feels exhausting even when only 2 answers into the discussion :slightly_frowning_face:

Where do you get the foundation is de-emphasizing sitemaps? A lot of development has gone in sitemaps recently, and continues to go into it. There is complete UI configurability. There is an alternative YAML format. Sitemaps can be UI or file defined. There have been functional enhancements (Buttongrid…).
Both UI’s serve their own purpose. It is very easy and quick to create a sitemap. It is less flexible than MainUI, but I see that as a benefit. For me (and I believe for many others), sitemaps are the prime configuration for mobile use UI’s. I honestly don’t see what you could not do with sitemaps if you don’t go the full MainUI route. And using item metadata is not doing that, it is duplicating functionality we have in sitemaps in a more restrictive way and without the configurability that is already there.

By the way, persistence strategies and widget configurations are not metadata. You can make a widget selection and drive some parameters of a widget through metadata, but not define widgets through metadata. Persistence strategies are not in metadata at all.

On the core mechanism, I don’t see what that will change. If the core mechanism is to create a sitemap with a sorted list of items tagged in metadata, a simple rule may do that today. But let me suggest adding a group to a sitemap. All items in the group will be displayed in most sitemap based UI’s in an alphabetic list with their default sitemap widget. So I think it is already there.

What groups lack is the ability to order items. According to @timbms that was the reason for using them on CarPlay (see his comment here). [That is using a sitemap to define a UI that isn’t a list of actual sitemap widgets, but only a grid of items.]
Maybe standardizing on using sitemaps with limited widget support indeed makes sense, it certainly is the easiest to implement.

Sitemaps come with all functionality necessary on watch and CarPlay. Allows to define reproducible order. label and icon can be overwritten.
We currently deliberately support only switches. Support for other item types can be added. But this requires careful judgement not to distract drivers.
Anyway, the release in testing will also support interactive widgets. On CarPlay with Touchscreen this will also allow interactions for RollerShutter and Setpoint and display Text.