1 Home Assistant SSH Configuration#
1.1 Add SSH Keys#
To enable passwordless SSH access to your Home Assistant instance, you must have the SSH & Web Terminal add-on installed and Advanced Mode enabled for your user profile.
1.2 Configure Authorized Keys#
- Open the terminal within Home Assistant or via a console.
- Edit the authorized keys file:
nano /data/.ssh/authorized_keys- Paste your public SSH key (e.g., from your Mac Studio or MacBook Air) into the file.
- Save and exit (
Ctrl+O,Enter,Ctrl+X).
Ensure the SSH add-on configuration has the correct port (usually
22or2222) and that the “SFTP” or “SSH” services are started in the add-on’s dashboard.
2 Cloudflare Tunnel#
- Add Repo:
https://github.com/brenner-tobias/ha-addons - Install: Cloudflared Add-on.
- Configure: Add your tunnel token/link and start.
3 Audi Kilometer Tracker: System Architecture & Setup#
The system operates like a Switchboard. Instead of using multiple separate scripts, a single “smart” script routes information to the correct tab based on the “label” (the car name) attached to the data sent from Home Assistant.
3.1 Home Assistant (The Dispatcher)#
When the automation runs, it sends two separate messages (HTTP POST requests) to the same URL in quick succession.
- Request 1:
{"date": "2026-05-10", "odometer": "15000", "car": "Audi A5"} - Request 2:
{"date": "2026-05-10", "odometer": "500", "car": "Audi A6"}
3.2 Google Apps Script (The Switchboard)#
The doPost(e) function is the receiver. Every time a message arrives, it inspects the car field to decide which tab to open.
var carName = data.car;
var tabName = "";
if (carName === "Audi A5") {
tabName = "A5 2025"; // Routes to the A5 tab
} else if (carName === "Audi A6") {
tabName = "A6 2027"; // Routes to the A6 tab
}- Message 1 arrives → Script opens “A5 2025” → Logs mileage.
- Message 2 arrives → Script opens “A6 2027” → Logs mileage.
3.3 The Spreadsheet (The Warehouse)#
The data is now stored in two separate “rooms” (tabs) within the same file. This keeps your data organized and prevents the logs from getting mixed up.
3.4 The Reporting (The Delivery)#
A separate function, sendSundayReports, runs on a time-based trigger (e.g., Sunday at 6:15 PM). This function:
- Checks the A5 2025 tab for the latest data.
- Checks the A6 2027 tab for the latest data.
- Email 1: Sends a Combined Report of both cars to your primary email.
- Email 2: Sends a Standalone A6 Report to both you and the second recipient.
3.5 Home Assistant Configuration#
Step A: The REST Command#
Add this to your configuration.yaml. It creates a single command that handles both cars using variables.
rest_command:
update_audi_spreadsheet:
url: "https://script.google.com/macros/s/AKfycbzfy9VhKmikEGqFDOt8_mUzL0adZFm0JnrjrUbWX23-FeJdYwo-MOoUuPYy2BVhe7i8/exec"
method: post
content_type: "application/json"
payload: '{"date": "{{ date }}", "odometer": "{{ odometer }}", "car": "{{ car }}"}'Step B: The Automation#
Add this to your automations.yaml. It triggers every Sunday at 6:00 PM and performs two actions (one for each car).
alias: Audi - Update Odometer Weekly
description: Automatically updates the spreadsheet for both cars every Sunday at 6:00 PM
triggers:
- trigger: time
at: "18:00:00"
conditions:
- condition: time
weekday:
- sun
actions:
- action: rest_command.update_audi_spreadsheet
data:
date: "{{ now().strftime('%Y-%m-%d') }}"
odometer: "{{ states('sensor.audi_a5_sedan_mileage') }}"
car: "Audi A5"
- action: rest_command.update_audi_spreadsheet
data:
date: "{{ now().strftime('%Y-%m-%d') }}"
odometer: "{{ states('sensor.audi_a6_sportback_e_tron_mileage') }}"
car: "Audi A6"
mode: single3.6 Key Benefits#
- One URL: You only have to manage one Webhook URL in Home Assistant.
- One Security Key: You only authorize one script to access your Google account.
- Synced Data: The reports are generated simultaneously, ensuring your combined email is always accurate and up-to-date for both vehicles.
4 Meross Ghost Entity & VLAN Routing Fix#
4.1 The Issue#
When deleting and re-adding a Meross device, Home Assistant might refuse to connect and continuously restore the old ghost entity name while throwing a KeyError and AttributeError: 'NoneType' object has no attribute 'attach' in the logs.
4.2 Why it happens#
- The Registry Ghost: When a device is deleted from the UI, Home Assistant sometimes keeps its UUID permanently trapped in the hidden
deleted_devicesanddeleted_entitiesrecycle bins inside the.storageregistry. Whenever you re-add the device, HA automatically restores the old, corrupted data. - The Cloud Profile Cache: The
meross_lanintegration caches the Meross Cloud Profile. If you re-add a device to the Meross app,meross_lanmay still use an expired offline cache (e.g.,meross_lan.profile.xxxxxx) which lacks the new UUID or MQTT keys, causing aKeyError. - The VLAN Block: If Home Assistant is on a different VLAN than the IoT devices and HTTP (Port 80) is blocked,
meross_lancannot push the local MQTT configuration to the new device, leaving it “Unavailable”.
4.3 The Complete Fix & Automation Script#
Target SSH Host: root@10.1.2.200
Step 1: Purge the Registry & Cache via SSH (Automated One-Liner)#
Replace TARGET_UUID with the actual device UUID (e.g. 2105088987914955854648e1e9707285):
TARGET_UUID="<UUID_HERE>"
# 1. Stop Home Assistant Core
ha core stop
# 2. Backup & Purge core.device_registry (Active + Deleted)
cp /config/.storage/core.device_registry /config/.storage/core.device_registry.bak
jq --arg uuid "$TARGET_UUID" '.data.devices |= (if type=="array" then map(select((.identifiers | tostring | contains($uuid)) | not)) else . end) | .data.deleted_devices |= (if type=="array" then map(select((.identifiers | tostring | contains($uuid)) | not)) else . end)' /config/.storage/core.device_registry > /tmp/cdr.json && mv /tmp/cdr.json /config/.storage/core.device_registry
# 3. Backup & Purge core.entity_registry (Active + Deleted)
cp /config/.storage/core.entity_registry /config/.storage/core.entity_registry.bak
jq --arg uuid "$TARGET_UUID" '.data.entities |= (if type=="array" then map(select((.unique_id | tostring | contains($uuid)) | not)) else . end) | .data.deleted_entities |= (if type=="array" then map(select((.unique_id | tostring | contains($uuid)) | not)) else . end)' /config/.storage/core.entity_registry > /tmp/cer.json && mv /tmp/cer.json /config/.storage/core.entity_registry
# 4. Remove Stale Meross Cloud Profile Cache
rm -f /config/.storage/meross_lan.profile.*
# 5. Restart Home Assistant Core
ha core startStep 2: Re-Add & UI Dashboard Configuration#
- Wait ~60s for HA Core to restart and re-sync the profile from the Meross Cloud.
- In Settings > Devices & Services, re-add the device.
- Important Dashboard Tip: If the switch fails to control from a Light Card or shows as
Offwhile physicallyON, go to Settings > Devices & Services > Entities, open the switch entity, click the gear icon, and change “Show as” fromOutlettoLight.