Home Assistant custom integration for Sugar Valley NeoPool controllers connected via Tasmota MQTT. Provides comprehensive monitoring and control of your pool system through Home Assistant.
💬 Community support & discussion: join the official Sugar Valley NeoPool topic on the Home Assistant Community forum.
- Water Temperature - Current pool water temperature
- pH - pH level, state, and pump status
- Redox (ORP) - Oxidation-reduction potential
- Hydrolysis - Chlorine production level, state, runtime statistics, setpoint (g/h), max capacity, and unit
- Chlorine - Chlorine level (for controllers with chlorine module)
- Conductivity - Conductivity level (for controllers with conductivity module)
- Ionization - Current ionization level (for controllers with ionization module)
- Controller Time - NeoPool controller internal clock (diagnostic, throttled to 5-min updates)
- Filtration - Mode and speed
- Powerunit - Voltage diagnostics (5V, 12V, 24-30V, 4-20mA)
- Connection - Modbus communication statistics (lifetime cumulative, reset-aware across Tasmota reboots)
- Connection Error Rate - Rolling 10-minute Modbus failure percentage (diagnostic)
- Module presence (pH, Redox, Hydrolysis, Chlorine, Conductivity, Ionization)
- Named relay states (Acid, Base, Redox, Chlorine, Conductivity, Heating, UV, Valve)
- Water flow and tank level indicators
- Hydrolysis redox controlled
- Connection Problem - Triggered when the rolling Modbus error rate exceeds a configurable threshold (default 5%)
-
Switches - Filtration, plus configuration switches (UV mode, climate, smart antifreeze, hydrolysis cover reduction / temperature shutdown)
-
Light - Pool light (dedicated light entity)
-
Selects - Filtration mode/speed, Boost mode, and AUX1–4 mode (Auto / On / Off)
No Berry extension required for AUX. AUX relays are driven through their controller timer-block mode register using the built-in
NPWrite/NPExeccommands: Auto follows the controller schedule, On forces the relay on, Off forces it off. The live relay output is exposed separately as read-onlyAUX1–4binary sensors. -
Numbers - pH Min/Max, Redox setpoint, Hydrolysis setpoint, Chlorine setpoint, Ionization setpoint
-
Buttons - Clear error state, Sync controller time
- Dynamic device info: Device registry shows actual device metadata from
MQTT telemetry:
- Manufacturer: Actual brand from
NeoPool.Type(e.g., "Bayrol", "Hidrolife", "Aquascenic") instead of generic "Sugar Valley" - Firmware version: Combined Tasmota and Powerunit versions (e.g., "Tasmota 14.4.1 / Powerunit V3.45")
- Configuration URL: Links directly to the Tasmota device web UI
- Serial number: Hashed System ID for device identification
- Manufacturer: Actual brand from
- Translated sensor names: Sensor names displayed in your Home Assistant language (supports German, English, Spanish, Estonian, Finnish, French, Italian, Norwegian, Portuguese, and Swedish)
- Options flow: Adjust offline timeout, recovery script, repair notification settings, and the connection error-rate threshold at runtime
- Reconfigure flow: Change device name and MQTT topic
- Dynamic entity management: Sensor and number entities for chlorine,
ionization, and conductivity modules auto-enable when the controller
reports the module installed and auto-disable when it's removed.
Hydrolysis g/h-labeled entities auto-disable when the controller is
in
%display mode and re-enable when flipped back tog/h. See the Dynamic Entity Management section - Repair notifications: Device offline issues are surfaced in Home Assistant's repair system with configurable threshold
- Recovery notifications: Detailed timing info (downtime, script execution) when device recovers
- Device triggers: Automate based on device connection events (offline, online, recovered)
- Recovery script: Optionally execute a script when failure threshold is reached
- Diagnostics: Downloadable diagnostics file for troubleshooting
- Automatic NodeID migration: Detects and fixes entities created with masked NodeIDs on startup
- All changes apply immediately without Home Assistant restart
- Home Assistant 2024.1.0 or newer
- Tasmota firmware with NeoPool support (Documentation)
- MQTT broker configured in Home Assistant
The integration uses the NeoPool hardware NodeID to create stable,
unique identifiers for all entities. It works regardless of the Tasmota
SetOption157 setting:
- SO157=0 (default): Modern Tasmota versions output a hashed NodeID
(prefix
AA55). Older versions mask it withXXXX. - SO157=1: The real hardware NodeID is shown.
During setup, the integration automatically reads both the hashed and real NodeIDs by briefly toggling SO157. Both values are stored, so the device is recognized regardless of how SO157 is set afterward. No manual configuration of SO157 is required.
- Open HACS in your Home Assistant instance
- Click on "Integrations"
- Click the three dots menu in the top right corner
- Select "Custom repositories"
- Add
https://github.com/alexdelprete/ha-sugar-valley-neopoolas an Integration - Click "Download" and install the integration
- Restart Home Assistant
- Download the latest release from GitHub Releases
- Extract the
custom_components/sugar_valley_neopoolfolder - Copy it to your Home Assistant
config/custom_components/directory - Restart Home Assistant
- Go to Settings → Devices & Services
- Click Add Integration
- Search for "Sugar Valley NeoPool"
- Confirm prerequisites: If you previously used the YAML package, you must have already removed it and restarted Home Assistant. Confirm that no active YAML package is running.
- Choose setup path:
- Fresh installation: Leave the migration checkbox unchecked. You'll be asked to enter your device name and MQTT topic.
- Migrate from YAML: Check the migration checkbox to preserve your existing entities and historical data. See Migration Steps below.
The integration also supports automatic MQTT discovery - if your Tasmota device is publishing NeoPool data, it may be discovered automatically.
After installation, you can adjust runtime settings without restart:
- Go to Settings > Devices & Services > Sugar Valley NeoPool
- Click Configure to open the options dialog
- Adjust the available options:
- Recovery script: Script to execute when failure threshold is reached
- Enable repair notifications: Toggle repair issue creation on/off
- Failures threshold: Number of consecutive LWT offline messages before triggering notifications (1-10)
- Offline timeout: How long the device must be offline before triggering notifications (60-3600 seconds)
- Click Submit - changes apply immediately
To change the device name or MQTT topic:
- Go to Settings > Devices & Services > Sugar Valley NeoPool
- Click the three-dot menu (⋮) on the integration card
- Select Reconfigure
- Update the settings and click Submit
Note: Entity IDs are based on the device NodeID, so changing the device name or topic will not affect your historical data or automations.
If you're currently using the YAML package
(ha_neopool_mqtt_package.yaml):
⚠️ CRITICAL: You MUST remove the YAML package and restart Home Assistant BEFORE adding this integration. If you skip this step:
- You will get duplicate entities (both YAML and integration entities)
- Both sets will be active and receiving updates simultaneously
- You'll need to manually clean up the mess afterward
The YAML package creates entities dynamically - they won't "transfer" to the integration automatically. The migration deletes the old MQTT entities and recreates them with the same entity IDs to preserve history.
- Remove/comment out the YAML package from your
configuration.yaml - Restart Home Assistant - this is essential! After restart, the entities will remain in the registry but become "unavailable" (no longer receiving updates from the YAML package)
- Install this custom integration through HACS or manually (see above)
- Add the integration in Home Assistant:
- Go to Settings → Devices & Services → Add Integration
- Search for "Sugar Valley NeoPool"
- Confirm that no active YAML package is running
- Check "Yes, migrate my entities from the old YAML package"
- Auto-detection: The integration will automatically:
- Scan for NeoPool messages and detect your MQTT topic
- Find migratable entities using the default
neopool_mqtt_prefix - If not found, use smart detection with NeoPool-specific signatures
- Acquire device NodeID automatically
- Active entity check: If the integration detects entities are still receiving updates (YAML package still running), it will warn you and ask you to remove the YAML package first
- Custom prefix support: If your YAML used a custom
unique_idprefix:- Smart detection will find entities using NeoPool-specific signatures (hydrolysis_runtime, system_id, etc.)
- You'll be asked to confirm the detected prefix
- Or you can manually enter your custom prefix
- If no entities are found at all, you can skip migration and proceed with a fresh device setup instead
- Review and confirm: Before migration, you'll see:
- Validated MQTT topic and NodeID
- List of entities to be migrated
- Confirmation checkbox (required to proceed)
- Migration result: After confirming, you'll see:
- Number of entities found and migrated
- List of successfully migrated entities
- Any errors that occurred
The integration uses two auto-detection mechanisms during setup:
MQTT Topic Detection: The integration subscribes to the wildcard topic
tele/+/SENSOR and waits up to 10 seconds for a message containing
"NeoPool" in the JSON payload. If found, the device topic is extracted
automatically. Note that the + wildcard only matches single-level topics
(e.g., SmartPool). If you use a multi-level custom Tasmota topic (e.g.,
tasmota/GA_po_IO_Oxilife), auto-detection won't find it and you'll be
asked to enter the topic manually.
Entity Prefix Detection: When migrating, the integration first searches
for entities with the default neopool_mqtt_ prefix. If none are found, it
falls back to smart detection: it scans all MQTT platform entities and checks
if their unique_id values end with NeoPool-specific signatures such as
water_temperature, ph_data, hydrolysis_runtime_total, and others. Each
signature carries a confidence weight. If the total confidence score is high
enough, the detected prefix is presented for your confirmation. Otherwise,
you can enter a custom prefix manually or skip migration entirely.
The migration process preserves your historical data by:
- Finding your old MQTT entities by their
unique_idprefix - Extracting the actual
entity_idfrom each entity (handles custom names) - Deleting the old MQTT entities from the entity registry
- Creating new entities with the same
entity_idas the deleted ones
Since Home Assistant's recorder indexes history by entity_id, your graphs,
statistics, and long-term data are preserved when the new entity uses the
same entity_id as the old one.
The integration also extracts your device name from the migrated entity IDs
to preserve any customizations (e.g., if your entities were named
sensor.my_pool_ph_data, the device will be named "My Pool").
The integration uses the hardware NodeID from your NeoPool controller to create stable unique identifiers:
- Pattern:
neopool_mqtt_{nodeid}_{entity_key} - Example:
neopool_mqtt_4C7525BFB344_water_temperature - Benefits:
- Stable IDs that survive MQTT topic changes
- Support for multiple NeoPool controllers without conflicts
- Hardware-based identification instead of software configuration
If entities were created with old-format NodeIDs (masked XXXX or real), the integration automatically detects and migrates them on startup to use the hashed NodeID as the canonical identifier.
What gets preserved:
- All historical data (graphs, statistics, long-term statistics)
- Entity IDs (e.g.,
sensor.neopool_water_temperature) - Entity customizations (friendly names, icons, areas)
- Automation and script references
To monitor the migration process, enable debug logging.
The integration performs automatic validation and monitoring to ensure reliable operation.
On every Home Assistant startup, the integration runs a validation/reconciliation process to ensure everything is properly configured:
| Check | Description | Action if Failed |
|---|---|---|
| NodeID Migration | Scans for old-format unique_ids | Migrates to hashed NodeID |
| Entity ID Mapping | Checks YAML-migrated entity_ids | Renames to preserve original IDs |
| Orphaned Entity Cleanup | Finds replaced/renamed entities | Removes deprecated entities |
| Device Registry | Verifies device identifier | Updates if needed |
Why run on every startup?
- Users might restore backups with old entity configurations
- Safer to always verify than assume persisted state is correct
- Operations are idempotent (running multiple times produces same result)
After the first successful validation, subsequent startups quickly verify everything is aligned and log debug messages like "already correct" or "migration not needed".
While Home Assistant is running, the integration monitors:
| Monitor | Description | Action |
|---|---|---|
| Device Availability | Subscribes to LWT topic | Marks entities unavailable |
| NodeID Recognition | Matches NodeID against stored values | Recognizes hashed, real, or masked |
Entity registry changes (unique_id migration, entity cleanup) only run at startup.
Problem: "Cannot read from this MQTT topic"
- Verify your Tasmota device is online and publishing to the topic you entered
- Check the topic name matches exactly (case-sensitive)
- Verify MQTT broker is working: look for
tele/{topic}/SENSORmessages
Problem: "No migratable entities found"
- Verify entities with the
neopool_mqtt_prefix exist in your entity registry - Entities already owned by this integration cannot be migrated again
- The integration uses smart detection with NeoPool-specific signatures (hydrolysis_runtime, system_id, etc.) to find entities
- If smart detection finds your entities, you'll be asked to confirm the detected prefix and confidence level
- If automatic detection fails, you can manually enter your custom prefix
Problem: "YAML package still active" warning
- The integration detected entities are still receiving updates
- This means you haven't removed/commented out the YAML package yet
- To fix:
- Remove/comment out the YAML package from
configuration.yaml - Restart Home Assistant
- Click "Retry" in the config flow to check again
- Remove/comment out the YAML package from
Problem: "Failed to configure NodeID"
- Ensure the device is online and reachable via MQTT, then retry setup
Problem: Entities appear duplicated
- This happens if you didn't remove the YAML package before adding the
integration. The YAML package creates entities dynamically via MQTT, so:
- The old YAML entities continue to receive updates (active)
- The new integration creates its own entities with the migrated unique_ids
- Both sets of entities appear and update simultaneously
- To fix:
- Remove/comment out the YAML package from
configuration.yaml - Restart Home Assistant
- The YAML-created entities will become unavailable
- You may need to manually delete the orphaned entities from Settings → Devices & Services → Entities tab
- Remove/comment out the YAML package from
- Prevention: Always remove the YAML package and restart HA before running the migration wizard
Problem: Finding your custom unique_id prefix
If you need to find your custom prefix manually:
- Go to Settings → Devices & Services → Entities tab
- Search for any NeoPool entity (e.g.,
sensor.neopool_water_temperature) - Click the entity and then the gear icon to see its Unique ID
- The prefix is everything before the entity key (e.g., if unique_id is
my_pool_water_temperature, the prefix ismy_pool_)
The integration provides device triggers that allow you to create automations based on device connection events.
| Trigger | Description |
|---|---|
| Device offline | Fires when the device goes offline (MQTT LWT) |
| Device online | Fires when the device comes back online |
| Device recovered | Fires when the device recovers after extended outage |
- Go to Settings > Automations & Scenes > Create Automation
- Click Add Trigger and select Device
- Select your NeoPool device
- Choose from the available triggers
Get notified when your NeoPool device goes offline and comes back online:
automation:
- alias: "NeoPool Device Offline Alert"
trigger:
- platform: device
domain: sugar_valley_neopool
device_id: YOUR_DEVICE_ID
type: device_offline
action:
- service: notify.mobile_app
data:
title: "NeoPool Offline"
message: "The NeoPool device is unreachable. Check Tasmota device."
- alias: "NeoPool Device Recovered"
trigger:
- platform: device
domain: sugar_valley_neopool
device_id: YOUR_DEVICE_ID
type: device_recovered
action:
- service: notify.mobile_app
data:
title: "NeoPool Online"
message: "The NeoPool device is back online and responding."You can configure a recovery script in Runtime Options. The script runs automatically when the device has been offline for the configured failure threshold.
When the recovery script runs, it receives context variables that you can use
in your script actions. Access these using the trigger context:
| Variable | Description | Example Value |
|---|---|---|
device_name |
The configured device name | "Pool Controller" |
mqtt_topic |
The MQTT topic for the device | "SmartPool" |
nodeid |
The device's hardware NodeID | "ABC123" |
failures_count |
Number of consecutive failures | 3 |
Create a script that restarts a smart plug and sends a notification with device details:
script:
neopool_recovery:
alias: "NeoPool Recovery Script"
sequence:
- service: notify.mobile_app
data:
title: "NeoPool Recovery"
message: >
{{ device_name }} failed {{ failures_count }} times.
MQTT topic: {{ mqtt_topic }}. Restarting power...
- service: switch.turn_off
target:
entity_id: switch.tasmota_smart_plug
- delay:
seconds: 10
- service: switch.turn_on
target:
entity_id: switch.tasmota_smart_plug
- service: notify.mobile_app
data:
title: "NeoPool Recovery Complete"
message: "Power cycled for {{ device_name }} (NodeID: {{ nodeid }})"Four example dashboards are provided under lovelace/ —
two for fresh installs and two for users who migrated from the
YAML package.
Fresh install (default device name NeoPool):
ha_neopool_lovelace.yaml— full-width desktop layout (mushroom cards + masonry 400 px).ha_neopool_lovelace_responsive.yaml— mobile-friendly layout (tile cards + masonry 320 px).
Migrated from the YAML package (entity IDs still neopool_mqtt_*):
ha_neopool_lovelace_migrated.yaml— full-width variant.ha_neopool_lovelace_responsive_migrated.yaml— responsive variant.
All four files cover the same scope (sensors, controls, setpoints, modules, relay states, power-unit voltages, connection diagnostics) and use conditional cards so the chlorine, ionization, and conductivity sections auto-hide when those modules aren't installed.
The migrated variants additionally drop tiles for the three relay-state entities (pH / Filtration / Light) that the integration deletes during migration, and use the YAML package's entity-ID slugs.
All files are designed to be pasted under views: in an existing
dashboard's raw configuration.
- Install the required custom cards via HACS — see
lovelace/README.mdfor the full list. - Open Settings → Dashboards → pick a dashboard → ⋮ → Edit dashboard → ⋮ → Raw configuration editor.
- Paste the chosen file's contents under
views:. - Save. The new view appears as a tab.
- Device name assumption. Each file assumes a specific entity-ID
prefix (
neopool_for fresh installs,neopool_mqtt_for migrated installs). If you set a custom device name during setup, find/replace the prefix with your slug before applying. - Not sure which file? Open Settings → Devices & services →
NeoPool → Entities and look at one entity's ID. Starts with
sensor.neopool_mqtt_…? You migrated, use the_migrated.yamlfiles. Starts withsensor.neopool_…(no_mqtt_)? Fresh install, use the others.
See lovelace/README.md for the full custom-card
dependency list, installation notes, and entity-ID reference.
In your Tasmota device, the MQTT topic is configured under Configuration → Configure MQTT → Topic.
The integration expects MQTT messages on these topics:
tele/{topic}/SENSOR- Sensor data (JSON)tele/{topic}/LWT- Last Will and Testament (Online/Offline)cmnd/{topic}/{command}- Commands
For detailed Tasmota NeoPool setup instructions, see the official documentation. NodeID handling is covered in Requirements.
- Single device per integration: Each config entry supports one NeoPool device. To monitor multiple devices, add the integration multiple times
- Tasmota firmware required: The integration communicates via MQTT with Tasmota; direct RS485/Modbus is not supported
- Push-based updates: Data is received via MQTT push; frequency depends
on your
NPTelePeriodsetting
The integration watches the SENSOR telemetry stream continuously and automatically enables or disables entities based on what the controller reports — so your device page stays clean as you add, remove, or reconfigure pool equipment without needing to touch Home Assistant's entity settings manually.
Three signals from tele/{topic}/SENSOR drive the auto-management:
NeoPool.Modules.{Chlorine,Ionization,Conductivity}— the matching sensor / number entities (chlorine_data,chlorine_setpoint,ionization_data,ionization_setpoint,conductivity_data) are disabled when the module isn't installed (value == 0).NeoPool.Relay.{Acid,Base,Redox,Chlorine,Conductivity,Heating,UV,Valve}— the matchingrelay_*_statebinary sensors are disabled when the relay isn't assigned on the controller (key not emitted).NeoPool.Hydrolysis.Unit(%org/h) — the three g/h-labeled hydrolysis sensors (hydrolysis_datag/h,hydrolysis_setpoint_gh,hydrolysis_max) are disabled in%mode, where the absolute g/h value isn't recoverable from telemetry.
- Install a chlorine module mid-session → next SENSOR telemetry
reports
Modules.Chlorine = 1→ integration re-enablessensor.chlorine_dataandnumber.chlorine_setpointin the registry → schedules an automatic reload → ~1-2 second blip across the integration's entities → chlorine entities now live and reporting data, with no manual intervention. - Remove a relay assignment from the controller → Tasmota stops emitting that relay key in the JSON → integration disables the matching binary sensor on next telemetry tick. No reload — the entity just gets hidden from the UI immediately.
- Flip the controller display unit
g/h→%→ next telemetry carriesHydrolysis.Unit: "%"→ the three g/h-labeled sensors get disabled. No reload (disable-only). - Flip
%→g/h→ g/h sensors re-enabled → reload scheduled so the entities materialize with live values. - No change → integration sees identical signals to last seen, no registry writes, no reload. Watching is cheap.
If you disable an entity yourself via the UI (Settings → Devices & services → NeoPool → Entities → toggle off), the integration does not re-enable it even when the underlying module is present. Only entities that the integration itself disabled get auto-re-enabled.
Enable / disable transitions log at WARNING level so they're visible
in the default Home Assistant log without needing to switch on debug
logging:
WARNING (MainThread) [custom_components.sugar_valley_neopool]
Disabled module entity sensor.neopool_chlorine_data
(Chlorine module not installed)
WARNING (MainThread) [custom_components.sugar_valley_neopool]
Re-enabled mode entity sensor.neopool_hydrolysis_max
(controller is in g/h mode)
If a reload is triggered (re-enable transition), you'll also see:
WARNING (MainThread) [custom_components.sugar_valley_neopool]
Re-enabled 2 previously-disabled entities, scheduling integration
reload: ['sensor.neopool_chlorine_data', 'number.neopool_chlorine_setpoint']
Two diagnostic entities surface the health of the Modbus connection between the Tasmota device and the NeoPool controller — useful for spotting flaky RS485 wiring, interference, or controller-side issues.
Reports the rolling 10-minute Modbus failure rate as a percentage:
((no_response + out_of_range) / requests) × 100
The window is sliding rather than lifetime, so recent issues are reflected within minutes regardless of how big the cumulative denominator has grown. A healthy NeoPool/Tasmota pair runs at ~0%. Values above 5% sustained for more than a few minutes typically indicate a real connection problem (loose RS485 terminals, marginal cable run, electrical interference).
Goes unknown for the first few minutes after HA startup (the
window needs ≥2 samples to compute a delta) and clears itself when a
Tasmota reboot is detected within the window (so the reset's
counter-drop doesn't pollute the rate).
device_class=problem. Turns on when the rolling rate exceeds a
configurable threshold (default 5%), off when it drops back below.
Use as the trigger for any notification mechanism you prefer.
Settings → Devices & services → NeoPool → Configure → set Connection error-rate threshold (0.1% – 100%, default 5%).
Reasonable starting points:
- Short, shielded RS485 (≤5m): 1–2% — anything more is unusual
- Typical install (5–15m unshielded): 5% (default)
- Long / shared cable / known noisy environment: 10%+
The change takes effect immediately (the integration reloads automatically when options change). No HA restart needed.
Copy/paste into your automations YAML and tweak as you like:
automation:
- alias: NeoPool — connection error rate high
description: Notify when the Modbus connection becomes unhealthy
trigger:
- platform: state
entity_id: binary_sensor.neopool_connection_problem
to: "on"
for: "00:05:00" # sustained 5 min — ignore transient spikes
action:
- service: persistent_notification.create
data:
title: NeoPool connection unhealthy
message: >
Error rate is
{{ states('sensor.neopool_connection_error_rate') }}%
(threshold exceeded for 5+ min). Check RS485 wiring,
Tasmota logs, and the controller's Modbus settings.For migrated YAML-package installs, replace neopool_ with
neopool_mqtt_ in the entity IDs.
A handful of entities update frequently. The integration handles this
in two ways internally so the default configuration is sensible at any
TelePeriod setting:
- Throttling: entities like
sensor.neopool_controller_timetrack every SENSOR message in memory but only write a new state to the recorder once per fixed interval (5 minutes forcontroller_time). - Lifetime cumulative: the four
sensor.neopool_connection_*entities aggregate Tasmota's volatile RAM counters into smooth lifetime totals across Tasmota reboots, and write once per hour. State persists across HA restarts viaRestoreEntity.
Net effect: the entities most prone to recorder spam stay clean
regardless of how aggressive your TelePeriod setting is.
Updates the displayed value on every SENSOR tick (time always
advances), but only writes a new state to the recorder once per 5
minutes. Caps at ~288 rows/day regardless of TelePeriod. Useful as
a sanity-check for the controller's clock and for verifying the
Sync Controller Time button worked.
sensor.neopool_connection_requests, sensor.neopool_connection_responses,
sensor.neopool_connection_no_response,
sensor.neopool_connection_out_of_range.
The underlying Tasmota counters (MBRequests, MBNoError,
MBNoResponse, DataOutOfRange) live in Tasmota RAM and reset to 0
every Tasmota restart — same behaviour as MqttCount / Uptime etc.
The integration accumulates them across resets in memory: each new
raw value contributes its delta to the entity's lifetime cumulative,
and a drop (negative delta) is treated as a Tasmota-reboot signal so
the new value itself becomes the delta from 0. The cumulative
survives HA restarts via RestoreEntity.
State writes are throttled to once per hour — exactly what HA's
statistics engine needs to compute hourly aggregates, so long-term
trend graphs ("Modbus error rate over the last 30 days") work
cleanly. About 96 recorder rows per day total for all four entities,
no matter what TelePeriod you've set on the Tasmota side.
Snapshot diagnostics (current per-Tasmota-uptime counters) are still visible via Tasmota's own web UI / MQTT, but the lifetime numbers in Home Assistant are the canonical view now.
sensor.neopool_hydrolysis_runtime_total,
sensor.neopool_hydrolysis_runtime_part,
sensor.neopool_hydrolysis_runtime_pol1,
sensor.neopool_hydrolysis_runtime_pol2,
sensor.neopool_hydrolysis_polarity_changes.
These come from Modbus registers in the NeoPool controller's
persistent storage (MBF_CELL_RUNTIME_*). They survive both Tasmota
and NeoPool reboots — true lifetime counters of the electrolysis cell
hardware itself. They update on every SENSOR tick (no throttle)
because they only change while hydrolysis is actively running, and
each change is a small persistent increment that's worth recording
for cell-usage tracking.
Assuming hydrolysis runs ~6 h/day. Per device, all integration entities combined:
TelePeriod |
Recorder rows/day | 10-day DB footprint |
|---|---|---|
| 300s (default) | ~570 | ~1.4 MB |
| 60s | ~3,000 | ~7 MB |
| 30s | ~6,000 | ~15 MB |
| 10s | ~17,500 | ~44 MB |
| 1s | ~173,000 | ~430 MB |
The connection cumulative entities contribute a constant ~96 rows/day
regardless of TelePeriod. The hydrolysis runtime counters scale
with TelePeriod only during active hydrolysis. controller_time
contributes a constant ~288 rows/day. Most of the variance above
comes from the runtime counters.
For most users the defaults are fine. If you run an aggressive
TelePeriod (≤10s) and want to cut the per-tick runtime-counter
rows, add a recorder exclude block. The hourly long-term statistics
are stored separately and remain available for trend graphs even when
raw history is excluded.
recorder:
exclude:
entities:
# Hydrolysis runtime counters — NeoPool-persistent. Excluding
# them from raw history keeps the hourly long-term statistics,
# which are stored separately and remain available for trend
# graphs.
- sensor.neopool_hydrolysis_runtime_total
- sensor.neopool_hydrolysis_runtime_part
- sensor.neopool_hydrolysis_runtime_pol1
- sensor.neopool_hydrolysis_runtime_pol2
- sensor.neopool_hydrolysis_polarity_changesThe connection diagnostics no longer need a recorder.exclude entry
— their hourly throttling already caps their volume.
Note: entity IDs in the example assume the default device name
NeoPool. Migrated installs use the neopool_mqtt_* prefix instead —
see Lovelace Dashboards for the same naming
caveat.
For broader recorder tuning options (purge interval, commit interval, etc.) see the Home Assistant recorder documentation.
Add this to your configuration.yaml:
logger:
default: warning
logs:
custom_components.sugar_valley_neopool: debugAfter adding this configuration, restart Home Assistant for the changes to take effect.
When reporting issues, it's essential to provide complete debug logs. Follow these steps to capture a full debug log:
Add the logger configuration shown above to your configuration.yaml and
restart Home Assistant.
Before reproducing the issue, clear your log file to make it easier to find relevant entries:
- Go to Settings > System > Logs
- Click Clear (top-right) to clear the current logs
Perform the exact steps that cause the problem. For example:
- If entities go unavailable, wait for it to happen
- If a command fails, execute the command
- If setup fails, try adding/reconfiguring the integration
Option A: From the Home Assistant UI
- Go to Settings > System > Logs
- Click Download full log (top-right, download icon)
- Save the
home-assistant.logfile
Option B: From the File System
The log file is located at:
- Home Assistant OS/Supervised:
/config/home-assistant.log - Docker: Inside your config volume, e.g.,
/path/to/config/home-assistant.log - Core: In your config directory, typically
~/.homeassistant/home-assistant.log
To extract only NeoPool-related entries, use these commands:
# Linux/macOS
grep "sugar_valley_neopool" home-assistant.log > neopool-debug.log
# Windows PowerShell
Select-String -Path home-assistant.log `
-Pattern "sugar_valley_neopool" | Out-File neopool-debug.logWith debug logging enabled, you'll see:
- MQTT subscriptions: Topics being subscribed to
- MQTT messages: Received sensor data and LWT status
- Entity updates: State changes and value transformations
- Commands: Outgoing MQTT commands
- Migration: Entity migration process details
- Errors: Detailed error messages with stack traces
Example debug log entries:
DEBUG [custom_components.sugar_valley_neopool.sensor]
Sensor water_temperature subscribed to tele/SmartPool/SENSOR
DEBUG [custom_components.sugar_valley_neopool.entity]
Received MQTT message on tele/SmartPool/SENSOR
DEBUG [custom_components.sugar_valley_neopool.sensor]
Sensor water_temperature updated: 28.5
You can enable debug logging temporarily without restarting Home Assistant:
-
Go to Developer Tools > Services
-
Select service
logger.set_level -
Enter this YAML:
custom_components.sugar_valley_neopool: debug
-
Click Call Service
Note: This method only enables debug logging until the next Home Assistant restart. For persistent debug logging, use the
configuration.yamlmethod.
For MQTT-related issues, you may also need MQTT debug logs:
logger:
default: warning
logs:
custom_components.sugar_valley_neopool: debug
homeassistant.components.mqtt: debugWarning: MQTT debug logging can be very verbose. Only enable it when specifically troubleshooting MQTT connectivity issues, and disable it afterward.
- Go to Settings > Devices & Services > Sugar Valley NeoPool
- Click the three-dot menu (⋮) on the integration card
- Select Download diagnostics
The diagnostic file contains sanitized device information and configuration. Sensitive data like NodeID and MQTT topics are automatically redacted.
-
Entities show as unavailable
- Check that your Tasmota device is online and publishing to MQTT
- Verify the MQTT topic matches your configuration
- Check the LWT topic shows "Online"
-
Commands not working
- Ensure the Tasmota device has write access to NeoPool
- Check MQTT broker permissions
When opening an issue, please include:
- Diagnostic file: Download from Settings > Devices & Services > Sugar Valley NeoPool > three-dot menu (⋮) > Download diagnostics
- Home Assistant version (Settings > About)
- Integration version (Settings > Devices & Services > Sugar Valley NeoPool)
- Full debug logs: Follow the Getting FULL Debug Logs section above
- Steps to reproduce the issue with exact actions taken
This project uses a comprehensive test suite:
# Install development dependencies
uv sync --all-extras --dev
# Run tests with coverage
uv run pytest tests/ --cov=custom_components/sugar_valley_neopool \
--cov-report=term-missing -v
# Run linting
ruff format .
ruff check . --fix
# Run type checking
mypy custom_components/sugar_valley_neopool --ignore-missing-importsCI/CD Workflows:
- Tests: Runs pytest with coverage on every push/PR to main
- Validate: Runs hassfest and HACS validation
- Release: Automatically creates ZIP on GitHub release publish with version validation
Contributions are welcome! Please follow these steps:
- Fork the repository
- Create a feature branch (
git checkout -b feature/my-feature) - Make your changes
- Run linting:
pre-commit run --all-files - Commit your changes (
git commit -m "feat: add my feature") - Push to your branch (
git push origin feature/my-feature) - Open a Pull Request
Please ensure all CI checks pass before requesting a review.
This integration is built by Alessandro (@alexdelprete) & Claude — a human and an LLM working together. Architecture decisions, design trade-offs, the NeoPool/Tasmota domain grounding (Modbus register quirks, firmware behaviour, what each entity should actually represent), and the "what should this actually do?" calls are mine. A large share of the typing, refactors, test scaffolding, and tedious MQTT/entity-registry plumbing was done by Claude Code.
Every line is reviewed and tested — CI runs ruff lint + a 97%+ coverage
test suite + HACS/hassfest validation on every push, and releases are
version-gated. This note is here because transparency about how software is
made matters more than pretending otherwise.
If you like this integration, I'll gladly accept some quality coffee, but please don't feel obliged. :)
This project is licensed under the MIT License - see the LICENSE file for details.
- Tasmota for the excellent NeoPool support
- Home Assistant community
- ha-sinapsi-alfa for the integration template