NSPanel Pro, but smooth: a card pack and a native Flutter app for the Sonoff NSPanel Pro 86

I bought a Sonoff NSPanel Pro 86 for the dining room and spent the first weeks being slightly annoyed by it. Sonoff’s own firmware is a walled garden, and every Home Assistant route I tried came down to a browser on a 2018-class SoC: the companion app in a WebView, kiosk browsers, the popular card packs made for phones. They all work. None of them felt smooth. Sliders lagged behind the finger, animations stuttered, and tap targets designed for a hand-held phone are small on a wall at arm’s length.

I am a Flutter developer by day, and the panel is just an Android 8.1 device with a 480×480 screen, a Rockchip PX30 and a Mali-G31. So I stopped fighting the browser and built two things that share one config.

1. NSPanel Cards (HACS)

A set of Lovelace cards designed for exactly this panel: a square 480×480 canvas, big drag surfaces, no continuous animation, and everything tuned to the frame budget of that GPU. They run in any browser, so the same dashboard also looks right on a phone or tablet.

[light, climate, status images]

Cards for lights, covers, climate, media players, scene/script buttons, sensors (single and a strip), a status grid, weather, a clock, an alarm panel and a screensaver; pages are swiped with the usual swipe card. Controls follow one gesture language: drag anywhere on the card to set a value, tap to act, long-press for a full-screen version. Every option has a GUI editor, so no YAML is needed if you do not want it.

[media, scenes, alarm images]

Repo: GitHub - mennovanhout/NSPanel-cards: Custom lovelace cards for NSPanel Pro · GitHub

2. The native app (Flutter)

This is the part that made the difference. A Flutter app that you sideload on the panel once, which then reads your Lovelace dashboard from Home Assistant over the websocket and renders the same nspanel-* cards natively, straight to the GPU. No browser, no HA frontend running in the background.

You keep editing the dashboard in HA, YAML or the GUI editor, and the panel reloads on its own. The result is what I wanted from day one: sliders that stay under your finger, page swipes at a steady frame rate, and a card that reacts the moment you touch it.

[two panel photos]

What it does beyond the cards:

  • Screensaver with your own photos, a wandering clock and proximity wake using the panel’s built-in sensor.
  • A device in Home Assistant through MQTT discovery. Each panel exposes brightness, volume, the current page, the screensaver as a switch, proximity and presence, illuminance, plus an update entity.
  • A notify entity per panel: send it text and it speaks through HA’s TTS, or sound:doorbell to play one of twenty built-in sounds (doorbell, alarm, laundry, timer, goodnight and so on).
  • Alarm card with a keypad: when your alarm wants a code, arming or disarming opens a full-screen keypad, and a refused code says so. The code check is Home Assistant’s, so the panel cannot bypass it.
  • Starts on boot and can optionally take over as the launcher.
  • Updates itself: the update entity in HA shows new releases, and Install downloads and installs the APK on the panel. No adb after the first time.

Repo: GitHub - mennovanhout/nspanelpro-flutter · GitHub

Why two renderers

The config is the contract. Every card option exists in both the web cards and the app, or the README says which one lacks it. So you can build and preview a dashboard in your browser with the web cards, and the panel shows the same thing, only faster. If you would rather not sideload anything, the cards alone already work in a kiosk browser on the panel. The app is the upgrade.

Status and what I would like from you

The cards are at 0.8, the app at 0.3. It runs my house every day, but it has been tested on one house and one panel, so I expect edge cases. Things I would love to hear about:

  • Cards or entity types you miss.
  • How it behaves on your NSPanel Pro (120 or 86, older or newer firmware).
  • Ideas for the panel as a device: I am thinking about a doorbell camera view, notification banners and BLE presence.

Everything is MIT and on GitHub, issues and PRs welcome

Tutorial from an empty HA to a working panel: nspanelpro-flutter/TUTORIAL.md at 2aa4689d6d1ed1e3956c083172053161726e96ee · mennovanhout/nspanelpro-flutter · GitHub

Extra note:
Yes i did use Claude for this project!

1 Like

Looks very nice and promosing, trying to build some dashboard currently, and was wondering about 2 things:

  • I cannot choose the entity ID from the visual configurator, only in yaml mode
  • Will there be a “button” card as well in future? Light doesn’t suit physical switches, and the button card is more for a “one-off” action, not to control light switches..

Thanks an BR

For the first item thanks, will do a push tomorrow to update the visual configurator.

Buttons are already there.


Hey Menno,

dankjeweil :slight_smile:
Sorry I saw the button, but they seem for one-off actions, like starting scripts etc. I meant a “switch” card, as not all my lights are turned on by the light, but some by wall switches..

Thanks and BR

Good idea will see if I can add these tomorrow

Hi there,

Updated the visual dahboard editor.
Also added new: custom:nspanel-switch-card

So far we are many updates later, here are some of the improvements:

  • Next to wall panel add option to sleep nspanel with LCD off
  • Communicate back to Home Assistant
  • Expose as MQTT device to play sounds, music or notifications or text to speech
  • Added MQTT set-up on screen for easier installation
  • Added clock optiosn, static, position and size
  • And more…

This looks really good.

I’ve tried quite a few different solutions for the NSPanel Pro over the years, and there was always some compromise, especially with speed and responsiveness.

This one feels different. The native Flutter approach makes the interface look much smoother, and the whole project already seems very well thought out.

Definitely one of the most interesting NSPanel Pro projects I’ve seen so far.

Great job, Menno, and thanks for sharing it with the community. I’m looking forward to seeing how it develops.

Thanks a lot!

After finishing yesterday with more settings directly configurable on the mqtt device:

I have also made a flow that turns the screens of at night and on in the morning. Or when we leave the house.

Amazing job, my NSPanal is super responsive and working like a charm. Any possibility to :

  1. implement the full custom:simple-swipe-card → show_pagination: false in the OS (for the moment my dashboard still shows the “…” at the bottom despite that feature deactivated in the code
  2. Change the color of the nspanel-button-card based on the status of a bolean
  3. on nspanel-button-card the possibility to remove the name of the card and only show the icon. Currently I’ve put
- type: custom:nspanel-button-card
                height: 140
                columns: 2
                buttons:
                  - name: ' '
                    icon: mdi:minus
                    service: script.office_hvac_manual_decrease
                  - name: ' '
                    icon: mdi:plus
                    service: script.office_hvac_manual_increase

but then the name ’ ’ is centered on the buton and icon is on top of this empty name

again thanks for this development

Fred

No worries thanks for the feedback. I will pick it up after the holidays. All 3 options seem fairly easy to implement :slight_smile:

Firstly, thanks for taking the time to develop this. I’m not creative at all so my dashboards are pure function. Now with this solution it’s made a massive difference. My wife is now comfortable using the NSPanels, I have 3 of them at the moment. Keep up the great work.

I have a couple of doorbell cameras, are you likely to work on a component for that? Just being able to view the stream would be handy.

To show my appreciation I’d at least like to buy you a coffee but don’t see anything for that in github.

Yes i will first work on the feedback of @Fvanoost .
Then I will take a look into doorbell camera’s, just installed a Hikvision doorbell myself so got the perfect set-up to start working on it and to try it out!

Thanks for considering buying me a coffee! my donation link is: Send me money with bunq.me . I’ll add that to the repo’s

I currently also have 3 panels, planning on buying more as now they finally work smooth. I was very hesitant at first seeing the poor performance with home assistant and other softwares and tricks i’ve tried.

I also played already with the doorbell sounds and custom sound using my own Flutter NSPanel software, let me share the example:

alias: Doorbell Press
description: ''
triggers:
  - trigger: state
    entity_id: sensor.doorbell_call_state
    to: ringing
actions:
    - action: notify.send_message
      data:
        message: '{"sound": "doorbell", "wake": false, "volume": 100}'
      target:
        entity_id: notify.nspanel_living_announce

Or with a custom ring tone:

alias: Doorbell Press
description: ''
triggers:
  - trigger: state
    entity_id: sensor.doorbell_call_state
    to: ringing
actions:
    - action: notify.send_message
      data:
        message: '{"url": "/local/doorbell.mp3", "wake": false, "volume": 100}'
      target:
        entity_id: notify.nspanel_living_announce

This atleast makes the NSPanels work like a chime, next thing is indeed video!

Release: cards v0.10.0 and app v0.5.1

1. Own swipe card: custom:nspanel-swipe-card

The bundle now has its own pager, so nothing else from HACS is needed. It is a native scroll-snap container, so the browser pans on the compositor during a swipe with no script running, the same technique the kiosk page used. Pages are built with HA’s own card helpers, so any card works as a page.

type: custom:nspanel-swipe-card
dots: false           # page dots at the bottom; default true
start: 0              # page to open on; default 0
card_spacing: 12      # px between pages; default 12
cards:
  - type: vertical-stack
    cards: [...]
  - type: vertical-stack
    cards: [...]

Backwords compatible

2. Buttons lit by a boolean

A button is lit while its own entity is on, as before. New per-button keys:

  • state_entity: another entity that lights it, typically the input_boolean an automation sets.
  • color: the button’s own lit colour instead of the card accent.
type: custom:nspanel-button-card
columns: 2
buttons:
  - entity: script.movie_mode
    name: Movie
    icon: mdi:movie-open
    state_entity: input_boolean.movie_mode
    color: '#a78bfa'
  - entity: script.normal
    name: Normal
    icon: mdi:skip-backward

3. Icon only

show_name: false on the card, or per button. The icon grows to take the room the name had. A button waiting for its confirmation tap still shows “Tap again” on that line, since that has to be said.

type: custom:nspanel-button-card
columns: 3
show_name: false
buttons:
  - entity: script.movie_mode
    icon: mdi:movie-open
    state_entity: input_boolean.movie_mode
    color: '#a78bfa'
  - entity: script.normal
    icon: mdi:skip-backward
  - entity: scene.bright
    icon: mdi:white-balance-sunny
    show_name: true     # this one keeps its name
    name: Bright

works perfect, thanks a lot, any chance to also add the show_name into the custom:nspanel-switch-card?

Wil do in the next update

New update for @Fvanoost and @Maximo

Thanks for the great feedback.

1. show_name on the switch card

Added, plus show_state for the On/Off line. Both work on the card or per switch. With both off the tile is the icon alone, lit while on.

type: custom:nspanel-switch-card
columns: 3
show_name: false
show_state: false
switches:
  - switch.garden_lights
  - switch.fountain
  - entity: input_boolean.guest_mode
    show_name: true        # this one keeps its nam

2. Camera card: custom:nspanel-camera-card

type: custom:nspanel-camera-card
entity: camera.doorbell
title: Front door
height: 440
interval: 1        # seconds between pictures; default 1
fit: cover         # or contain
show_name: true

To get the camera to work when someone pressed the doorbell, here is an example automation:

alias: Doorbell on the hallway panel
triggers:
  - trigger: state
    entity_id: binary_sensor.doorbell_button
    to: "on"
actions:
  - action: switch.turn_off            # wake it, backlight included
    target:
      entity_id: switch.nspanel_hallway_screensaver
  - action: number.set_value           # turn to the camera page
    target:
      entity_id: number.nspanel_hallway_page
    data:
      value: 2
  - action: notify.send_message        # and ring
    target:
      entity_id: notify.nspanel_hallway_announce
    data:
      message: '{"sound": "doorbell", "volume": 100}'
  - delay: "00:01:00"
  - action: number.set_value           # back to the first page
    target:
      entity_id: number.nspanel_hallway_page
    data:
      value: 0
mode: restart

This will do a doorbell sound + it wil show the camera, hope this helps !