I’m looking for advice or proven patterns to display a log of the last 10 (or 20) number plates on a dashboard card in Home Assistant. I’ve hit a wall with my current setup and the options I’ve tried, and I’d appreciate practical guidance or working examples.
What I have working so far:
Automated JSON Logging:
I have an automation that logs every new ANPR plate detection into a JSON log file. Each entry has a time, date, and the plate:
alias: Log ANPR Plate to JSON
description: Appends every new detected plate to plates_log.json
trigger:
- entity_id: sensor.driveway_anpr_last_recognized_plate
platform: state
condition:
- condition: template
value_template: >
{{ trigger.to_state.state | lower not in ['none', 'unknown', 'unavailable', ''] }}
action:
- data:
message: >
{"time": "{{ now().strftime('%H:%M:%S') }}", "date": "{{ now().strftime('%d-%m-%y') }}", "plate": "{{ trigger.to_state.state }}"}
service: notify.send_message
target:
entity_id: notify.file
# I also update an input_text.last_plate helper for the current plate (optional)
mode: queued
What I need:
Display the last 10 or 20 plate log entries (with date and time) on a Lovelace dashboard card.
It must work reliably and update in real-time or near real-time.
Solution must persist the log (not limited to input_text’s 255 characters).
What I’ve tried (and why it isn’t working):
SQL/MariaDB sensors:
Either too slow (plate changes are fast, SQL sensor often misses them), or I run into permission/time-out issues on my minimal hardware install.
python_script:
Tried to create a sensor to load last 10 lines from the JSON, but Python scripts in HA don’t support open()/file reading due to sandboxing.
command_line sensor:
Tried reading the file with tail or a bash script, but the platform doesn’t seem to work in my environment (barebones install, not HAOS/Supervised, limited shell access).
input_text helper:
Limited to 255 characters, so it overflows and loses older entries.
In summary:
I have a working JSON log, automation is solid, but I can’t find a robust way to read and display the last 10–20 entries in a dashboard card. I don’t want to lose historical entries and want a solution that works on minimal hardware (Core install, not Supervised/HAOS).
The Trigger-based Template Sensor is working because I see the first detection was AJ22EYW.
The second detection was Unknown (titlecase) which is different from what’s specified in not_to which is unknown (lowercase).
In other words, the sensor reported a literal Unknown because it wasn’t able to detect the license plate. That’s different from when Home Assistant uses unknown to report that the value hasn’t been received yet.
Im wondering if my issue is that im not applying this in the right way. Should this be done on the actual sensor sensor.driveway_anpr_last_recognized_plate or the one im creating sensor.anpr_plates like below?
From what I understand from your first post, the following sensor reports what your license plate recognition system detects.
sensor.driveway_anpr_last_recognized_plate
The first post in your example suggested that the sensor’s values are exclusively license plate codes like YE11TER, GH22TRG, etc. However, your screenshot of the Logbook shows that the values can be something other than a legitimate plate such as:
None
Unknown
Ir i weway (whatever that is)
So let’s apply the same conditional logic you used in your automation to the Trigger-based Template Sensor.
I have updated the example to use the latest syntax where trigger: is now triggers: - platform: is now - trigger:
In other words, a Trigger-based Template Sensor’s syntax was recently updated to match an automation’s syntax.
template:
- triggers:
- trigger: state
entity_id: sensor.driveway_anpr_last_recognized_plate
conditions:
- condition: template
value_template: >
{{ trigger.to_state.state | lower not in ['none', 'unknown', 'unavailable', ''] }}
sensor:
- name: ANPR Plates
state: "{{ now().timestamp() | timestamp_custom() }}"
attributes:
plates: >
{% set current = this.attributes.get('plates', []) %}
{% set new = [{
"time": now().strftime('%H:%M:%S'),
"date": now().strftime('%d-%m-%y'),
"plate": trigger.to_state.state }] %}
{{ (new + current)[:10] }}