My Home Assistant dashboard with deep details

Hello everyone,

After much tinkering with my main dashboard, I am satisfied with its current look. There are several improvements still to be made, but I’m mostly there.

If you only want to look at pretty pictures, you can do that here:

All screenshots at once

Integrations:


HACS:

Main Page:

Weather:

ACs:

Surveillance:

Power:

TVs:

3D Printers:

Wired Networking:

Wireless Networking:

Host Monitoring:

Pi-Hole Information:

Internet radios:

HA Host Troubleshooting Data:

HA System Logs AI Analyzer:

Before delving into details, here’s some general information about my Home Assistant setup:

Hardware:

Mini PC Asus NUC 14 Essential RNUC14MNK1500002 (SKU: 90AR00M2-M000F0), Intel N150, 16 GB DDR5 4800, 250 GB nVME SSD. It’s a dedicated machine.
Hardware Add-On: The laughably-named “USB2.0 DAB FM Radio DVB-T RTL2832U R820T2 RTL SDR TV Stick Dongle Digital USB TV HDTV Tuner Receiver IR Remote with Antenna” - which allows me to get data from my weather station.

Integrations:

I decided to place a screenshot, rather than list them all. If you are curious about any of them, feel free to ask. Ignore the Android Remote and Roku errors, those are ignored on purpose :slight_smile:

Integrations screenshot

Add-Ons:

Advanced SSH & Web Terminal
Anycubic 3D Printer (for my Anycubic Mono X)
Glances
HassOS SSH port 22222 Configurator
Mosquitto broker
openWakeWord
rtl_433 (next)
SQLite Web

HACS stuff

A pretty long list, I have taken a screenshot and tried to mention the relevant item in the descriptions below, together with a link to its repository.

HACS Items screenshot

External resources

A non-exhaustive list of external software that works together with Home Assistant:

  • InfluxDB: Home Assistant historical data goes there. This allows me to have long-term history outside of HA.
  • Grafana: Nice graphs with historical and real-time data, leveraging InfluxDB
  • Node-RED: Used to automate tasks such as remote LLMs
  • Piper and faster-Whisper: Speech-To-Text (STT) and Text-To-Speech (TTS) used for Home Assistant’s Assist. These are installed in dockers on my Unraid server.
  • Ollama with 3.2b - Squeezed in my Blue Iris surveillance dedicated machine, on a measly 5 GB of GPU VRAM.

Now, let me present you my current dashboard configuration:

Main View

This is the main view, the default one that loads whenever I access Home Assistant.

Home View screenshot

Temperatures section

  • Displays various data from sensors, mainly temperature sensors, that I want to know about most often. The bottom entry displays the last call I received on my phone, from whom, and the phone number of the caller.
    TODO: Add an entry for last outgoing call

Switches

  • This section allows me to turn on and off various lights that I use most, as well as see their statuses. The “Workshop Lights” entry triggers a template which turns on and off all three lights below it. “Workshop LEDs” is a smart plug which controls a LED strip.
    TODO: *Add a smart plug and include configuration for another dumb LED strip that I already have installed

Spotify

Status Section

Sensors section

  • Not much here, just some light sensors from my Shelly DW2 devices, they allow me to make sure the lights are not left on in unautomated areas.

Statuses and Updates sections

  • These contain several entities which display battery statuses (or toner load for my printer) and whether there are any updates available for various integrated devices. The entities are hidden or visible based on thresholds. If battery charges are e.g. less than 20%, the entity becomes visible. Same with Updates, if a component e.g. Pi-Hole or Ubiquiti devices has a firmware update, it will show here. Otherwise, they are hidden.

Weather View

This is, obviously, a weather-specific view.

Weather View screenshot

Bresser Weather Station

  • This is another HACS card, called Weather Chart Card. It displays data coming from my Bresser weather station, which I integrated with Home Assistant using this useful tutorial, with some modifications (I also have a Bresser PM2.5 and PM10 add-on which I integrated using the same method).

Bresser Wind Rose

Sun + Moon

  • Yes, you guessed right, one more HACS card. This is actually the very first HACS component I ever installed: Lovelace Horizon Card. I kept the simpler variant in the dashboard.

Air

  • This section leverages Air Quality and Wind data coming off my Bresser Weather Station. I didn’t like the value spikes displayed in the standard view, so I used some templating to smooth out the values for wind, wind gust, PM2.5 and PM10. Another change was the display units for wind. They are originally shown in m/s, and I converted those values to km/h. The card used for displaying the data is mini-graph-card, with an extra day/night layer.
    TODO: Add a graph for temperature. It’s easy, but I don’t really need historical data in the dashboard, I use Grafana for that.

NOTE: Sometimes, there are flat periods in the graphs. This is due to poor radio receiver antenna quality. I will eventually change it.

AC View

AC View screenshot

This is a simple and straightforward view, containing my AC controls, thermostat control and the garage average temperature (based on several sensors placed in various areas). really, nothing special going on in this view that is worth mentioning.

Camera View

Camera View screenshot

Again, a pretty simple dashboard view. I am not using this much, because I have a dedicated Blue Iris surveillance machine. However, the three buttons at the bottom allow me to manually start recording with any of those cameras. They are commands which are sent to the Blue Iris server.

Power View

Power View screenshot

I am not yet fully happy with this view, it needs some improvement, but it works well enough for now. The first four graphs display energy consumption, as recorded through Shelly smart plugs. They use the Plotly Graph Card HACS component. The bottom-left graph is also a Plotly graph, which displays my UPS status. I also placed here two buttons which allow me to cut power off to my Garage and Workshop AC units, just in case.

Since I don’t yet have solar panels (they are planned, but some health issues need to be solved first, and they are costly), this is not of much importance, but it’s a foundation.

Media View

Media View screenshot

Simple view, really. It displays the status and some basic controls for my TVs and soundbar, as well as an overview of my media files.
This needs a lot of work, to be honest, because I am not satisfied with my Samsung integrations. But that’s another story for another time.

3D Printer View

Media View screenshot

Now, this is where the awesome Moonraker integration kicks in. It’s an awesome implementation, which allows me to monitor and control my 3D printers without accessing their separate webpages. A lot of details in the image, but this wouldn’t have been possible without the multiple-entity-row HACS card.
The two little buttons at the top allow me to turn the printers off and on. When a printer is turned off, everything related to it becomes hidden in the dashboard (apart from the on/off switch, of course). I have also added system log filters in configuration.yaml to avoid Moonraker connection error spamming, while the printer(s) are turned off.

Wired Networking View

Wired Network View screenshot

This is 100% SNMP integration. Yes, I know, SNMP is bad, SNMP should die, I’ve heard it all. Point is, it works.
The view allows me to see and monitor my wired network stack, such as PoE status, power consumption, temperatures, connectivity speed, the essentials.

Wireless Networking View

Wireless Network View screenshot

A mix of UniFi Controller integration and SNMP data. Pretty straightforward. Each section you see there is actually a single “card of cards” :slight_smile:

Host Monitoring

Host Monitoring View screenshot

This view monitors four hosts:

  • Home Assistant itself (via Glances)
  • A Raspberry Pi 4 with my VPN server, Pi-Hole and the UniFi Controller (via Glances)
  • My Unraid server (via Glances)
  • My Blue Iris (Windows 11) host via fip-ha

Some views leverage the mushroom-template-card functionality. This enables me to see, at a glance, possible issues, e.g. if a disk becomes too full.

Pi-Hole information

Pi-Hole View screenshot

Simple dashboard view, pretty rarely used, mmostly informational.

Radio Page

Radio View screenshot

This is a set of custom integrations for my Internet-enabled radios. I have four such devices, and only one of them has a Media Player functionality.

Three Internet radios (SAL INR 5000)don’t have much functionality by default, except a very simple webpage which I integrated by analyzing their webpages and creating some RESTful custom YAML configs for them.
When they are offline, their Home Assistant controls are hidden and the RESTful error messages are filtered out of the System Logs.

The fourth one (Audizio Canzo) does have a Media Player component which is detected by Home Assistant. It’s pretty basic, but at least there’s something.

Home Assistant Host Troubleshooting monitoring

HA Host Troubleshooting screenshot

This is a temporary dashboard view, which I created shortly after buying the NUC. It was suddenly restarting and it corrupted the SQLite Database twice in a week. This dashboard view allowed me to see whether it suddenly rebooted overnight.
After some more troubleshooting and a revealing memtest86 run, it turned out the RAM was defecyive, so I replaced it, and after that, everything went back to normal. I should consolidate with the Host Monitoring view delete this dashboard page soon.

Home Assistant AI Log Analysis

AI Log Analysis screenshot

This last view displays an analysis of my Home Assistant System log.
The issue displayed (Gree Air Conditioner Integration is Failing to Connect) stems from the stupid Gree AC Units which randomly decide to no longer respond to pings or any queries, until I force a wireless reconnect from my UniFi Controller.
I tried a couple automations, using entity states, but I wasn’t very successful, and I plan to switch to ping-based monitoring, which is flawless.

That concludes my current dashboard. If you have any questions, or would like me to detail some of the integrations, customizations and other shenanigans, feel free to post a comment.
If you have advice for further optimizing my configurations, ideas for nice custom cards to add, or anything, really, I’d much appreciate it. I am always open to discovering more :slight_smile:

8 Likes

Can you also share the yaml files? I’m especially curious about the troubleshooting and log dashboard.
Very nice dashboards!:ok_hand:

Thank you. I’ve seen some truly beautiful dashboards out there, mine are, well, usable. I am not a good designer, nor very creative, I’m afraid.

Which YAML files would you like to have?

The log dashboard page is really simple, the heavy lifting is actually done in NodeRED.

Log view YAML
  - type: sections
    max_columns: 4
    icon: mdi:auto-fix
    path: ''
    sections:
      - type: grid
        cards:
          - type: heading
            heading: Home Assistant Log Analysis
            heading_style: title
            icon: mdi:home-analytics
          - type: entities
            entities:
              - entity: input_button.analyze_home_assistant_logs
          - type: iframe
            url: http://192.168.2.10:1881/log_analysis
            aspect_ratio: 50%
            grid_options:
              columns: full
              rows: 8
            title: Home Assistant Log Analyzer by Gemini
        column_span: 4
    background:
      opacity: 33
      alignment: center
      size: cover
      repeat: repeat
      attachment: fixed
      image: /api/image/serve/11c5e281ecf41d919b91439ea44b257d/original
    cards: []

Here’s the NodeRED exported flow, I have redacted the Google API key for obvious reasons :slight_smile:
I also left the Debug nodes active, in case you need to troubleshoot it.

NodeRED Flow
[
    {
        "id": "a53ac07949673da9",
        "type": "tab",
        "label": "HA Log Analysis (Gemini v2)",
        "disabled": false,
        "info": "",
        "env": []
    },
    {
        "id": "e663e26210f882a2",
        "type": "inject",
        "z": "a53ac07949673da9",
        "name": "Run Weekly (or click to test)",
        "props": [],
        "repeat": "604800",
        "crontab": "",
        "once": true,
        "onceDelay": "300",
        "topic": "",
        "x": 170,
        "y": 140,
        "wires": [
            [
                "01a357f495b6c37c"
            ]
        ]
    },
    {
        "id": "d9715a3bb6e987c0",
        "type": "http request",
        "z": "a53ac07949673da9",
        "name": "Call Gemini API",
        "method": "POST",
        "ret": "obj",
        "paytoqs": "body",
        "url": "",
        "tls": "",
        "persist": false,
        "proxy": "",
        "insecureHTTPParser": false,
        "authType": "basic",
        "senderr": false,
        "headers": [
            {
                "keyType": "other",
                "keyValue": "",
                "valueType": "other",
                "valueValue": ""
            }
        ],
        "x": 300,
        "y": 460,
        "wires": [
            [
                "c6b907c0879577c2",
                "5e746f6d3552fa4e"
            ]
        ]
    },
    {
        "id": "a54a01c4c81b22e1",
        "type": "function",
        "z": "a53ac07949673da9",
        "name": "Format Request for Gemini",
        "func": "// Paste your Google Gemini API Key here\nconst GEMINI_API_KEY = \"[REDACTED]\";\n\n// Get the log from the previous node\nlet log_content = msg.payload;\n\n// --- Log Truncation & Filtering ---\n// The command_line sensor already limits this to 500 lines,\n// so no further truncation is needed unless you have specific filtering needs.\n\n// Set the API endpoint URL, including the key\nmsg.url = `https://generativelanguage.googleapis.com/v1beta/models/gemini-2.5-pro:generateContent?key=${GEMINI_API_KEY}`;\n\n// Set up the API request body in the format Gemini expects\nmsg.payload = {\n  \"contents\": [{\n    \"parts\":[{\n      \"text\": `You are an expert Home Assistant administrator. Analyze the following Home Assistant log content, which covers the last {self.days_to_review} days. Your task is to provide a clear, human-readable summary of the issues found.\n                    \n                    Perform these actions:\n                    1. Identify all \"ERROR\" and \"WARNING\" messages.\n                    2. Group recurring issues.\n                    3. Structure your summary into two sections: \"Key Issues to Address\" and \"Minor Issues and Warnings\".\n                    4. Explain technical jargon in plain English.\n                    5. Adopt a helpful and concise tone. Here is the log content: \\n\\n ${log_content}`\n    }]\n  }]\n};\n\nreturn msg;",
        "outputs": 1,
        "timeout": "",
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 300,
        "y": 380,
        "wires": [
            [
                "d9715a3bb6e987c0"
            ]
        ]
    },
    {
        "id": "c6b907c0879577c2",
        "type": "change",
        "z": "a53ac07949673da9",
        "name": "Extract Analysis Text",
        "rules": [
            {
                "t": "set",
                "p": "payload",
                "pt": "msg",
                "to": "payload.candidates[0].content.parts[0].text",
                "tot": "msg"
            }
        ],
        "action": "",
        "property": "",
        "from": "",
        "to": "",
        "reg": false,
        "x": 360,
        "y": 540,
        "wires": [
            [
                "e50f1dba9eadd553"
            ]
        ]
    },
    {
        "id": "01a357f495b6c37c",
        "type": "api-call-service",
        "z": "a53ac07949673da9",
        "name": "Force-update the log sensor",
        "server": "d661c3f97886da4c",
        "version": 7,
        "debugenabled": false,
        "action": "homeassistant.update_entity",
        "floorId": [],
        "areaId": [],
        "deviceId": [],
        "entityId": [],
        "labelId": [],
        "data": "{\"entity_id\":\"sensor.ha_log_tail_2\"}",
        "dataType": "json",
        "mergeContext": "",
        "mustacheAltTags": false,
        "outputProperties": [],
        "queue": "one",
        "blockInputOverrides": false,
        "domain": "homeassistant",
        "service": "update_entity",
        "x": 230,
        "y": 220,
        "wires": [
            [
                "7d5e681c8f9d9402"
            ]
        ]
    },
    {
        "id": "aae9aa3c57663e50",
        "type": "catch",
        "z": "a53ac07949673da9",
        "name": "",
        "scope": null,
        "uncaught": false,
        "x": 740,
        "y": 440,
        "wires": [
            [
                "954f8c9d0a7234eb"
            ]
        ]
    },
    {
        "id": "954f8c9d0a7234eb",
        "type": "debug",
        "z": "a53ac07949673da9",
        "name": "debug 1",
        "active": true,
        "tosidebar": true,
        "console": false,
        "tostatus": false,
        "complete": "true",
        "targetType": "full",
        "statusVal": "",
        "statusType": "auto",
        "x": 880,
        "y": 520,
        "wires": []
    },
    {
        "id": "7d5e681c8f9d9402",
        "type": "api-render-template",
        "z": "a53ac07949673da9",
        "name": "Get Full Log Content",
        "server": "d661c3f97886da4c",
        "version": 0,
        "template": "{{ state_attr('sensor.ha_log_tail_2', 'log_data') }}",
        "resultsLocation": "payload",
        "resultsLocationType": "msg",
        "templateLocation": "",
        "templateLocationType": "none",
        "x": 260,
        "y": 300,
        "wires": [
            [
                "a54a01c4c81b22e1"
            ]
        ]
    },
    {
        "id": "e50f1dba9eadd553",
        "type": "change",
        "z": "a53ac07949673da9",
        "name": "Store Response in Flow Variable",
        "rules": [
            {
                "t": "set",
                "p": "log_analysis_response",
                "pt": "global",
                "to": "payload",
                "tot": "msg"
            }
        ],
        "action": "",
        "property": "",
        "from": "",
        "to": "",
        "reg": false,
        "x": 430,
        "y": 620,
        "wires": [
            [
                "ab02f8a13af1001a"
            ]
        ]
    },
    {
        "id": "52f168d1c81b0c1f",
        "type": "http in",
        "z": "a53ac07949673da9",
        "name": "GET /log_analysis",
        "url": "/log_analysis",
        "method": "get",
        "upload": false,
        "swaggerDoc": "",
        "x": 470,
        "y": 740,
        "wires": [
            [
                "b7df78454ec12925",
                "1f61c65ebf49a83c"
            ]
        ]
    },
    {
        "id": "b7df78454ec12925",
        "type": "change",
        "z": "a53ac07949673da9",
        "name": "Get Response from Flow Variable",
        "rules": [
            {
                "t": "set",
                "p": "payload",
                "pt": "msg",
                "to": "log_analysis_response",
                "tot": "global"
            }
        ],
        "action": "",
        "property": "",
        "from": "",
        "to": "",
        "reg": false,
        "x": 560,
        "y": 820,
        "wires": [
            [
                "4c0893cb6c3572c6",
                "453d4f07f4c0b35f"
            ]
        ]
    },
    {
        "id": "0c24efb19d6cf7a1",
        "type": "http response",
        "z": "a53ac07949673da9",
        "name": "",
        "statusCode": "",
        "headers": {},
        "x": 550,
        "y": 980,
        "wires": []
    },
    {
        "id": "ab02f8a13af1001a",
        "type": "debug",
        "z": "a53ac07949673da9",
        "name": "debug 2",
        "active": true,
        "tosidebar": true,
        "console": false,
        "tostatus": false,
        "complete": "true",
        "targetType": "full",
        "statusVal": "",
        "statusType": "auto",
        "x": 880,
        "y": 620,
        "wires": []
    },
    {
        "id": "1f61c65ebf49a83c",
        "type": "debug",
        "z": "a53ac07949673da9",
        "name": "debug 3",
        "active": true,
        "tosidebar": true,
        "console": false,
        "tostatus": false,
        "complete": "true",
        "targetType": "full",
        "statusVal": "",
        "statusType": "auto",
        "x": 880,
        "y": 740,
        "wires": []
    },
    {
        "id": "4c0893cb6c3572c6",
        "type": "debug",
        "z": "a53ac07949673da9",
        "name": "debug 4",
        "active": true,
        "tosidebar": true,
        "console": false,
        "tostatus": false,
        "complete": "true",
        "targetType": "full",
        "statusVal": "",
        "statusType": "auto",
        "x": 880,
        "y": 820,
        "wires": []
    },
    {
        "id": "5e746f6d3552fa4e",
        "type": "debug",
        "z": "a53ac07949673da9",
        "name": "debug 5",
        "active": true,
        "tosidebar": true,
        "console": false,
        "tostatus": false,
        "complete": "true",
        "targetType": "full",
        "statusVal": "",
        "statusType": "auto",
        "x": 880,
        "y": 300,
        "wires": []
    },
    {
        "id": "453d4f07f4c0b35f",
        "type": "change",
        "z": "a53ac07949673da9",
        "name": "Set Content-Type Header",
        "rules": [
            {
                "t": "set",
                "p": "headers['content-type']",
                "pt": "msg",
                "to": "text/plain",
                "tot": "str"
            }
        ],
        "action": "",
        "property": "",
        "from": "",
        "to": "",
        "reg": false,
        "x": 570,
        "y": 900,
        "wires": [
            [
                "0c24efb19d6cf7a1"
            ]
        ]
    },
    {
        "id": "fe0cdb64c06b1c3e",
        "type": "server-state-changed",
        "z": "a53ac07949673da9",
        "name": "Listen for Log Analyze Button",
        "server": "d661c3f97886da4c",
        "version": 6,
        "outputs": 1,
        "exposeAsEntityConfig": "",
        "entities": {
            "entity": [
                "input_button.analyze_home_assistant_logs"
            ],
            "substring": [],
            "regex": []
        },
        "outputInitially": false,
        "stateType": "str",
        "ifState": "",
        "ifStateType": "str",
        "ifStateOperator": "is",
        "outputOnlyOnStateChange": true,
        "for": "0",
        "forType": "num",
        "forUnits": "minutes",
        "ignorePrevStateNull": false,
        "ignorePrevStateUnknown": false,
        "ignorePrevStateUnavailable": false,
        "ignoreCurrentStateUnknown": false,
        "ignoreCurrentStateUnavailable": false,
        "outputProperties": [
            {
                "property": "payload",
                "propertyType": "msg",
                "value": "",
                "valueType": "entityState"
            },
            {
                "property": "data",
                "propertyType": "msg",
                "value": "",
                "valueType": "eventData"
            },
            {
                "property": "topic",
                "propertyType": "msg",
                "value": "",
                "valueType": "triggerId"
            }
        ],
        "x": 460,
        "y": 140,
        "wires": [
            [
                "01a357f495b6c37c"
            ]
        ]
    },
    {
        "id": "d661c3f97886da4c",
        "type": "server",
        "name": "Home Assistant",
        "version": 5,
        "addon": false,
        "rejectUnauthorizedCerts": true,
        "ha_boolean": "y|yes|true|on|home|open",
        "connectionDelay": true,
        "cacheJson": true,
        "heartbeat": false,
        "heartbeatInterval": 30,
        "areaSelector": "friendlyName",
        "deviceSelector": "friendlyName",
        "entitySelector": "friendlyName",
        "statusSeparator": ": ",
        "statusYear": "hidden",
        "statusMonth": "short",
        "statusDay": "numeric",
        "statusHourCycle": "default",
        "statusTimeFormat": "h:m",
        "enableGlobalContextStore": false
    },
    {
        "id": "81935d4466014b4c",
        "type": "global-config",
        "env": [],
        "modules": {
            "node-red-contrib-home-assistant-websocket": "0.77.1"
        }
    }
]

The troubleshooting view is just a detailed display of data coming off Glances, with a couple templating sensors to make some values (such as uptime) more humen-readable.

If you need further details or explanations, please let me know.

Wow! This is absolutely amazing!
I’d love to do something similar, do you care to share your entire dashboard .yaml file?

Yes we need pleased.

Nice setup! I found this thread because I am looking how to setup monitoring of my site to site VPN. Have the Unifi Protect integration this shows some status of the controller but not what I need.
Would you please be so kind to share in baby steps how you use SNMP to monitor the Unifi controller?
Thanks!

Very nice dashboard you’ve designed here.

I particularly like the “Host Monitoring” Dashboard. Would you be willing to share the yaml code for this? Unfortunately, I can’t get the memory values to display properly…

I am so sorry, all, for not replying. For some reason, my reply notifications from here are disabled.

@joshuaabarker97

I have added the dashboard full YAML here. Some sensor names and sensitive data have been obfuscated, I hope I haven’t broken something in the process. It’s pretty lengthy. You have been warned :slight_smile:
Bonus: I have added my dashboard background PNGs to the archive.

@Benneton about SNMP: I have been heavily relying on Google Gemini to make sense of UniFi SNMP values, specifically, but in a nutshell, it went like this:

  1. I enabled and configured SNMP in the UniFi controller;
  2. I used SnmpWalk to extract the SNMP OIDs and values from each device, as a CSV file. One file per device.
  3. I asked Google Gemini to generate sensor configs and dashboard YAMLs for each device. This required several iterations and improvements, of course, as well as my own manual work, but as it is, I am now satisfied with how it looks.

@anym001 I have linked the YAML as an archive, it contains the whole dashboard, but it’s fairly easy to navigate.

1 Like

I am considering transferring my home automation system from HomeSeer to HomeAssistant, but my biggest concern is losing the flexibility that HStouch gave me for configuring my supervision and control screens, both on iPad and PC-Win. I came across your post, and it really encourages me. You seem to be an expert; in your opinion, which ADD-ONS will I need to achieve a result similar to the attached photo?

Thank you in advance.

JYA

Hello and thank you for showing your interest.

Home Assistant offers a plethora of add-ons. You will need to perform some searches to find out whether there are add-ons for your devices.

As for the dashboards themselves, the possibilities are endless. I’ve seen some extreme stuff out in the wild, made by others with more knowledge than mine.