Helmsman - a new semi-native Home-Assistant companion app

There was some talk about upping it to 14x at some point, but then they decided to go to 153 directly too!

1 Like

Sounds reasonable, 153 is pretty good already. I’m using it as my main browser, it just needs the prefs change I mentioned before (but it doesn’t always work in the webview for some reason). Apart from being smoother, I like that it shows pages with the proper mobile layout instead of desktop like the stock browser often does.

I’ve been trying out the latest version for a couple of days now, and it’s useful to have, though please consider:

  • rewriting the English texts the way you would describe those buttons and functions. LLM-generated descriptions are always needlessly wordy, explaining things that need no explanation. This gets even worse when those descriptions are then also LLM-translated, which gets into my next point to also please consider:
  • removing LLM-generated translations. They sound unnatural to native speakers, tend to use the wrong words or wrong style, and if people want to use software in their own language, they’ll just do the translations themselves like they’ve always done (especially if they can do so from an easy translation platform like Hosted Weblate). There’s a reason Jolla asks community members to do their translations instead of just running all strings through Google Translate. I understand it can feel like you’re doing the community a huge service by including those LLM-generated translations for (nearly) all supported languages instead of only having your software available in English at first, but those LLM-generated translations only give the impression of being translations, in reality they’re just words a machine deemed most likely to be used in that place, and translations simply don’t work on a ‘most likely’ basis.

Other than my gripes with LLM-generated text, I’m not sure why Helmsman permanently hogs 5.5% of the CPU on my Jolla Phone. Is it due to the buttons in the Events view? I think those are an interesting function to have, but it seems like the only way to disable them entirely is to uninstall Helmsman (is that correct?), and design-wise they don’t look bad in and of themselves, but they look out-of-place in Sailfish. I’m no design expert, though, so no idea how they could look better.

Edit: ah, just thought to check the Events view settings in Settings, and lo and behold, I can turn off Helmsman’s Events view widget there. Should’ve checked first!

1 Like

The events view items can be removed one by one from the settings, and the whole events view widget can be disabled from the system events view menu. My guess though is that the cpu consumption comes from the websocket being active all the time (in order to receive notifications and keep the ui up to date). I haven’t monitored cpu/memory/battery on this yet and that’s probably one of the next things to do now that the core features are mostly implemented.

There isn’t really much choice if we want notifications though. Android has FCM and Apple has APNS, which are basically one big websocket that gets notifications for every app and distributes to the right place, but SFOS doesn’t have such a system so every app has to implement their own thing. I hope Jolla will deal with this at some point as it’s potentially a pretty big deal for battery consumption…

And yeah, I guess you’re right about the translations. I only ever use anything IT related in English, so I didn’t give that much thought. The idea with the LLM translations is to have a slot for each phrase, so it’ll be easy to translate later, but I guess I got a little speedblind with it when I put all the translations in there.

Regarding the long texts in a few places - yup :smiley: I keep thinking “I really should shorten that” everytime I visit the settings (which is pretty much the only place that has longer phrases) but then I keep forgetting because of something more urgent.

3 Likes

That (websocket) could be it (speaking as someone with no idea what he’s talking about), but in that case I’m sure there’s still plenty of room for future optimisation, because other apps with websockets, like Whisperfish, consume significantly less. The high CPU usage right now makes me hesitant to keep it running all day, but I’ll keep an eye out for future releases.

They could be doing it in a different way altogether - maybe the signal backend has a notifications service that can be subscribed to with lower consumption. Either way, optimization is definitely on the todo list :slight_smile:

Is there a way to enable debug info? In my case the app spend a couple of minutes on “Loading dashboard” during startup, raising “Helmsman is not responding”. Auth is working. I only use external url for simplicity. i’ve tried to reboot HA during this load, but did not affect anything

It should already have debug logging on. Logs are in Documents/Helmsman/. For example to read today’s log, do this in the terminal:

cat ~/Documents/Helmsman/helmsman-2026-10-07.log

One gripe I noticed is that the selections (sliders, buttons, etc.) don’t always work. Tried turning off the TV yesterday - nothing. I have the LG integration in HA. Also this morning, tried to increase a LED brightness from the dashboard - nothing. I had to open the LED entity page and only then the selection worked. So this could be something HA card related, the card control doesn’t work but the entity control does. Still, this doesn’t explain why the LG control didn’t work as I used it from the entity page, not the dashboard.

I’ve also noticed slight update issues with the automations. I have location off, but I use the change in WiFi to determine if I’m home or at the office (otherwise I’m just "away). Sometimes it works ok, sometimes I need to:
a) close and reopen Helmsman to get the template sensor triggered
b) turn WiFi off and on again (Hello, this is IT, how may I help)
c) or open the Android version

So some fine tuning would be nice - I haven’t used the Android app in a while, Helmsman is good enough for daily use (Harbour relese, maybe, yes? :wink:).

Long story short, thanks a lot for the work you have put into this app - really much appreciated! :saluting_face:

It seems like my problem with native rendering of dashboards on J2. When in use, I’m getting the following in logs:

W] unknown:0 - Helmsman: using "stock" webview embed
[D] unknown:0 - Using Wayland-EGL
library "libselinux.so" not found
Could not open module param file '/sys/module/mali_kbase/parameters/large_page_conf'
[22768.293264] (harbour-helmsma) [MEMPROF] Memory instrumentation via debugfs enabled
[W] unknown:0 - Helmsman widget: DBus registered as org.helmsman.harbour-helmsman
[W] unknown:0 - Helmsman: session loaded from "/home/defaultuser/.local/share/org.helmsman/harbour-helmsman/session.json" host= "" refreshLen= 128 clientId= "http://:8123/"
[W] unknown:0 - Helmsman: session saved to "/home/defaultuser/.local/share/org.helmsman/harbour-helmsman/session.json" refreshLen= 128 clientId= "http://penguinarium.localdomain:8123/" webhook= true
[W] unknown:0 - Helmsman mdi: ready= true family= "Material Design Icons" icons= 7447
library "/vendor/lib64/egl/mt6858/libGLES_mali.so" needed or dlopened by "(unknown)" is not accessible for the namespace "(default)"
library "/vendor/lib64/egl/mt6858/libGLES_mali.so" ("/vendor/lib64/egl/mt6858/libGLES_mali.so") needed or dlopened by "(unknown)" is not accessible for the namespace: [name="(default)", ld_library_paths="/usr/libexec/droid-hybris/system/lib64:/system/lib64:/vendor/lib64", default_library_paths="/system/lib64:/system_ext/lib64", permitted_paths="/system/lib64/drm:/system/lib64/extractors:/system/lib64/hw:/system_ext/lib64:/usr/libexec/droid-hybris/system/lib64:/system/framework:/system/app:/system/priv-app:/system_ext/framework:/system_ext/app:/system_ext/priv-app:/vendor/framework:/vendor/app:/vendor/priv-app:/system/vendor/framework:/system/vendor/app:/system/vendor/priv-app:/odm/framework:/odm/app:/odm/priv-app:/oem/app:/product/framework:/product/app:/product/priv-app:/data:/mnt/expand:/apex/com.android.runtime/lib64/bionic:/system/lib64/bootstrap"]
library "/vendor/lib64/hw/mt6858/mapper.mediatek.so" needed or dlopened by "(unknown)" is not accessible for the namespace "(default)"
library "/vendor/lib64/hw/mt6858/mapper.mediatek.so" ("/vendor/lib64/hw/mt6858/mapper.mediatek.so") needed or dlopened by "(unknown)" is not accessible for the namespace: [name="(default)", ld_library_paths="/usr/libexec/droid-hybris/system/lib64:/system/lib64:/vendor/lib64", default_library_paths="/system/lib64:/system_ext/lib64", permitted_paths="/system/lib64/drm:/system/lib64/extractors:/system/lib64/hw:/system_ext/lib64:/usr/libexec/droid-hybris/system/lib64:/system/framework:/system/app:/system/priv-app:/system_ext/framework:/system_ext/app:/system_ext/priv-app:/vendor/framework:/vendor/app:/vendor/priv-app:/system/vendor/framework:/system/vendor/app:/system/vendor/priv-app:/odm/framework:/odm/app:/odm/priv-app:/oem/app:/product/framework:/product/app:/product/priv-app:/data:/mnt/expand:/apex/com.android.runtime/lib64/bionic:/system/lib64/bootstrap"]
[D] onApplicationActiveChanged:409 - Helmsman: applicationActive= true
[W] unknown:0 - Helmsman: network is "wifi:penguome" home= "penguome"
[W] unknown:0 - Helmsman: endpoint now "http://:8123" (external) wifi= "xxx"
[W] unknown:0 - Helmsman: session saved to "/home/defaultuser/.local/share/org.helmsman/harbour-helmsman/session.json" refreshLen= 128 clientId= "http://:8123/" webhook= true
[W] unknown:0 - Helmsman: session saved to "/home/defaultuser/.local/share/org.helmsman/harbour-helmsman/session.json" refreshLen= 128 clientId= "http://penguinarium.localdomain:8123/" webhook= true
[W] unknown:0 - Helmsman ws: connecting to "ws://:8123/api/websocket"
[W] unknown:0 - Helmsman ws: io open "ws://:8123/api/websocket"
[W] unknown:0 - Helmsman ws: socket connected, waiting for auth_required
[W] unknown:0 - Helmsman ws: ping id= 2
[W] unknown:0 - Helmsman push: subscribed channel id= 3
[W] unknown:0 - Helmsman lovelace: subscribeAll path= "(default)" keepStates= false
[W] unknown:0 - Helmsman ws: pong id= 2
[W] unknown:0 - Helmsman push: subscribe ok id= 3
[D] expression for onPushConnectedChanged:472 - Helmsman: pushConnected= true registered= true
[W] unknown:0 - Helmsman lovelace: ready= true path= "dashboard-mobile"
[D] unknown:0 - QOpenGLFramebufferObject: Framebuffer incomplete attachment.
[D] unknown:0 - QOpenGLFramebufferObject: Framebuffer incomplete, missing attachment.
[D] unknown:0 - QOpenGLFramebufferObject: Framebuffer incomplete attachment.
[D] unknown:0 - QOpenGLFramebufferObject: Framebuffer incomplete, missing attachment.
[D] onApplicationActiveChanged:409 - Helmsman: applicationActive= false
[W] unknown:0 - Helmsman lovelace: "media" failed "Connection closed"
[W] unknown:0 - Helmsman sensors: started
[W] unknown:0 - Helmsman ws: ping id= 20
[W] unknown:0 - Helmsman ws: pong id= 20
[W] unknown:0 - Helmsman: renewing access token before it expires
[W] unknown:0 - Helmsman: token response missing refresh_token; keeping existing token
[W] unknown:0 - Helmsman: session saved to "/home/defaultuser/.local/share/org.helmsman/harbour-helmsman/session.json" refreshLen= 128 clientId= "http://:8123/" webhook= true
[W] unknown:0 - Helmsman: access token refreshed for "http://penguinarium.localdomain:8123"
[D] unknown:0 - QOpenGLFramebufferObject: Framebuffer incomplete attachment.
[D] unknown:0 - QOpenGLFramebufferObject: Framebuffer incomplete, missing attachment.
[D] unknown:0 - QOpenGLFramebufferObject: Framebuffer incomplete attachment.
[D] unknown:0 - QOpenGLFramebufferObject: Framebuffer incomplete, missing attachment.
[D] onApplicationActiveChanged:409 - Helmsman: applicationActive= true
[D] onApplicationActiveChanged:409 - Helmsman: applicationActive= false
[D] unknown:0 - QOpenGLFramebufferObject: Framebuffer incomplete attachment.
[D] unknown:0 - QOpenGLFramebufferObject: Framebuffer incomplete, missing attachment.
[D] unknown:0 - QOpenGLFramebufferObject: Framebuffer incomplete attachment.
[D] unknown:0 - QOpenGLFramebufferObject: Framebuffer incomplete, missing attachment.
[23231.259926] (harbour-helmsma) EGL: eglp_unload_callback <unknown>
==>[WARN] EGLDisplay (0x5acf60fb80) was not properly terminated by the application before unloading the driver.

And this does not happening when using webview of HA.

[W] unknown:0 - Helmsman ws: io open "ws://:8123/api/websocket"

seems like a bug at least. Looks like the internal/external system is not fully disabled and it’s trying to open a socket on an empty address that just gets a fallback port and api path. Maybe check if you have an empty space in the internal address field?

By the way, you might want to remove your hostname from that log - even if none of the forum users have any malicious intent, some bot could find it and try to brute force it.

Oh, no, ignore that. I just removed my url. All urls are fine there

I’ve also noticed some little bug with location updating - sometimes when I’m home it just sits at some location I passed while driving earlier, even though it should send a heartbeat of being home at a 2-3 minute interval. My guess is that the webhook it uses to update the sensors get stuck in some inbetween-state.

And yeah, I think a harbour release could be relatively close now. Just gotta get those bugs ironed out. I’m also thinking about contacting the Open Home Foundation and asking if they’d like to name Helmsman the official Sailfish OS companion app.

Oh and regarding the translations - I’m now working on making them less complicated → currently they’re in files defining stuff like “replace string ‘xxxx which could be several lines long’ with string ‘yyyy which is probably just as long’ on line zzz in file ååå“. The update will be that translations use a short key (“save”, for example), and the translation is loaded from json files containing {“save”: “Spara”, …} (for the Swedish translation, for example). That will make them much easier to manage.

1 Like

New version up on OpenRepos. Can you check @blackish whether that solves your problem?

1 Like

No, same behavior, unfortunately. Once I enable “Native dashboard”, app goes into “Loading dashboard” for a couple of minutes.

I might have an idea - well I do have an idea, but also a reason why the change is slow. :smiley: When you have the Web UI selected and go to settings and select the native UI, it loads the default Overview, and this can be quite heavy if you have a lot of entities. I don’t have that much (972, not sure if all are in the Overview) and it still loads for a few seconds and scrolling is slow.

I actually have very light custom default dashboard.

So do I, but if I set the app to use the Web UI and then close/reopen and choose the native UI, it doesn’t open my default UI set in profile preferences, but the HA system created Overview with possibly all available entities that could have a card of some sort.

^ I had that issue too at some point. I don’t have that many entities but when it falls back to the default “everything in a stack” it’s borderline unusable. Maybe I should force it to never use that dashboard unless it’s the only one (and then try to split it into pages or something).

1 Like

New version is on openrepos again. If @raketti guessed right, this should solve @blackish 's problem. If not, it at least makes the app more usable.

So yeah, now when changing from web to native, it should land on the same dashboard that was open, and if a dashboard has more than 50 cards, it splits it into pages of 50. Please tell me whether that helped or if I need to dig more. Also the constant cpu consuption should be fixed now - I observed around 0.1-0.3% usage with occasional little peaks when something actually happens.

[Update]
Another new version is on OpenRepos. I noticed some little issues with buttons inside a grid - they weren’t getting properties properly and for example a 3-column grid wrapped into 2 columns. I also added some opacity change so you actually notice that the element reacts when you tap it.
And I added some new debug settings. Logging can be disabled altogether now (I would personally only turn it on while debugging something), and I also added extra touch-logging, which could be used for example to dig into @raketti‘s “nothing happens” issue (I suspect something could be swallowing the taps).

3 Likes