Sugar Valley NeoPool - Home Assistant Integration

Sugar Valley NeoPool - Home Assistant Integration

GitHub ReleaseBuy Me A CoffeeTestsGitHub Downloads

This integration replaces the old HA-NeoPool-MQTT YAML package,
which is now archived. All support and future development happen here.
A built-in migration wizard preserves your existing entities and history —
see Migration from YAML Package.

Introduction

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.

Full documentation, deep-dive reference sections, and the complete
troubleshooting guide live in the
GitHub README.

Features

Sensors

  • 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)

Binary Sensors

  • 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%)

Controls

  • Switches - Filtration, Light, AUX1-AUX4 relays

    AUX1–4 control requires the Tasmota Berry NeoPool command
    extension
    (ESP32). NPAux<n> is not a built-in Tasmota command —
    by design, not a bug. Without the extension, AUX state reads work but
    toggles are ignored by the firmware. See
    Adding user-defined NeoPool commands.

  • Selects - Filtration mode/speed, Boost mode

  • Numbers - pH Min/Max, Redox setpoint, Hydrolysis setpoint, Chlorine setpoint,
    Ionization setpoint

  • Buttons - Clear error state, Sync controller time

Additional Features

  • 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
  • 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 to g/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

Requirements

  • Home Assistant 2024.1.0 or newer
  • Tasmota firmware with NeoPool support
    (Documentation)
  • MQTT broker configured in Home Assistant

NodeID and SetOption157

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 with XXXX.
  • 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.

Installation

HACS (Recommended)

  1. Open HACS in your Home Assistant instance
  2. Click on "Integrations"
  3. Click the three dots menu in the top right corner
  4. Select "Custom repositories"
  5. Add https://github.com/alexdelprete/ha-sugar-valley-neopool as an Integration
  6. Click "Download" and install the integration
  7. Restart Home Assistant

Manual Installation

  1. Download the latest release from GitHub Releases
  2. Extract the custom_components/sugar_valley_neopool folder
  3. Copy it to your Home Assistant config/custom_components/ directory
  4. Restart Home Assistant

Configuration

Initial Setup

  1. Go to SettingsDevices & Services
  2. Click Add Integration
  3. Search for "Sugar Valley NeoPool"
  4. 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.
  5. 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.

Runtime Options

After installation, you can adjust runtime settings without restart:

  1. Go to Settings > Devices & Services > Sugar Valley NeoPool
  2. Click Configure to open the options dialog
  3. 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)
  4. Click Submit - changes apply immediately

Reconfiguring Connection Settings

To change the device name or MQTT topic:

  1. Go to Settings > Devices & Services > Sugar Valley NeoPool
  2. Click the three-dot menu (⋮) on the integration card
  3. Select Reconfigure
  4. 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.

Migration from YAML Package

If you're currently using the YAML package (ha_neopool_mqtt_package.yaml):

:warning: 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.

Migration Steps

  1. Remove/comment out the YAML package from your configuration.yaml
  2. 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)
  3. Install this custom integration through HACS or manually (see above)
  4. Add the integration in Home Assistant:
    • Go to SettingsDevices & ServicesAdd Integration
    • Search for "Sugar Valley NeoPool"
    • Confirm that no active YAML package is running
    • Check "Yes, migrate my entities from the old YAML package"
  5. Auto-detection: The integration will automatically scan for NeoPool
    messages, detect your MQTT topic, find migratable entities (default
    neopool_mqtt_ prefix or smart detection), and acquire the device NodeID
  6. Active entity check: If entities are still receiving updates (YAML
    package still running), it warns you to remove the YAML package first
  7. Custom prefix support: If your YAML used a custom unique_id prefix,
    smart detection finds your entities and asks you to confirm the detected
    prefix — or you can enter it manually, or skip migration for a fresh setup
  8. Review and confirm: You'll see the validated MQTT topic and NodeID, the
    list of entities to be migrated, and a confirmation checkbox
  9. Migration result: After confirming, you'll see how many entities were
    found and migrated, plus any errors

How it works (auto-detection, history, NodeID)

  • Auto-detection — the integration subscribes to tele/+/SENSOR, waits
    up to 10 s for a "NeoPool" payload, and extracts your topic. When migrating
    it finds entities by the neopool_mqtt_ prefix, or falls back to smart
    detection via NeoPool-specific unique_id signatures (and asks you to
    confirm). Multi-level custom topics (e.g. tasmota/GA_po_IO_Oxilife) must be
    entered manually, since the + wildcard only matches single-level topics.
  • History preservation — migration deletes the old MQTT entities and
    recreates them with the same entity_id, so the recorder keeps all
    graphs, statistics, and long-term data. Your device name is extracted from
    the migrated entity IDs to preserve customizations (e.g. sensor.my_pool_*
    → device named "My Pool").
  • Why NodeID — entities use the hardware NodeID
    (neopool_mqtt_{nodeid}_{entity_key}) for stable IDs that survive MQTT topic
    changes and support multiple controllers. Old masked/real-format NodeIDs are
    migrated to the canonical hashed NodeID automatically on startup, preserving
    all history and customizations.

On every startup the integration re-validates NodeID format, entity-ID mapping,
orphaned-entity cleanup, and the device registry — all idempotent operations.
Full details are in the GitHub README.

Troubleshooting Migration

  • "Cannot read from this MQTT topic" — verify the Tasmota device is online
    and publishing; the topic is case-sensitive.
  • "No migratable entities found" — confirm neopool_mqtt_ entities exist;
    entities already owned by the integration can't be migrated again. You can
    enter a custom prefix manually or skip migration.
  • "YAML package still active" warning — you haven't removed the YAML
    package yet. Remove it, restart HA, then click "Retry".
  • Entities appear duplicated — you added the integration before removing
    the YAML package, so both sets are live. Remove the package, restart HA, and
    delete any leftover unavailable entities under Settings → Devices &
    Services → Entities
    .

See the GitHub README for the full migration troubleshooting guide, including
how to find a custom unique_id prefix.

Device Triggers

The integration provides device triggers that allow you to create automations
based on device connection events.

Available Triggers

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

How to Use Device Triggers

  1. Go to Settings > Automations & Scenes > Create Automation
  2. Click Add Trigger and select Device
  3. Select your NeoPool device
  4. Choose from the available triggers

Device Trigger Automation Example

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."

Recovery Script

You can configure a recovery script in Runtime Options.
The script runs automatically when the device has been offline for the
configured failure threshold.

Recovery Script Variables

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

Example Recovery Script

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 }})"

Lovelace Dashboards

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.

How to apply a dashboard

  1. Install the required custom cards via HACS — see
    lovelace/README.md in the repo for the full list.
  2. Open Settings → Dashboards → pick a dashboard → ⋮ → Edit
    dashboard → ⋮ → Raw configuration editor
    .
  3. Paste the chosen file's contents under views:.
  4. Save. The new view appears as a tab.

Caveats

  • 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.yaml files. Starts with sensor.neopool_…
    (no _mqtt_)? Fresh install, use the others.

MQTT Topic Configuration

In your Tasmota device, the MQTT topic is configured under
ConfigurationConfigure MQTTTopic.

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

Tasmota NeoPool Setup

For detailed Tasmota NeoPool setup instructions, see the
official documentation.
NodeID handling is covered in Requirements.

Known Limitations

  • 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 NPTelePeriod setting

Dynamic Entity Management

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.

What gets managed

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 matching relay_*_state binary sensors are disabled when the
    relay isn't assigned on the controller (key not emitted).
  • NeoPool.Hydrolysis.Unit (% or g/h) — the three g/h-labeled
    hydrolysis sensors (hydrolysis_data g/h, hydrolysis_setpoint_gh,
    hydrolysis_max) are disabled in % mode, where the absolute g/h
    value isn't recoverable from telemetry.

End-to-end scenarios

  • Install a chlorine module mid-session → next SENSOR telemetry reports
    Modules.Chlorine = 1 → integration re-enables sensor.chlorine_data and
    number.chlorine_setpoint → schedules an automatic reload → ~1-2 second blip
    → chlorine entities now live, with no manual intervention.
  • Remove a relay assignment from the controller → Tasmota stops emitting
    that relay key → integration disables the matching binary sensor on the next
    telemetry tick. No reload — the entity is just hidden immediately.
  • Flip the controller display unit g/h% → the three g/h-labeled
    sensors get disabled (disable-only, no reload).
  • Flip %g/h → g/h sensors re-enabled → reload scheduled so the
    entities materialize with live values.
  • No change → identical signals to last seen, no registry writes, no
    reload. Watching is cheap.

Manual control is sticky

If you disable an entity yourself via the UI, 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 switching on debug logging.

Connection Health Monitoring

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.

sensor.neopool_connection_error_rate

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.

binary_sensor.neopool_connection_problem

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.

Tuning the threshold

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.

Example automation

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.

Recorder Considerations

A handful of entities update frequently. The integration keeps the default
configuration sensible at any TelePeriod setting:

  • Throttlingsensor.neopool_controller_time tracks every SENSOR
    message in memory but writes to the recorder only once per 5 minutes
    (~288 rows/day).
  • 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 (~96 rows/day total). State persists
    across HA restarts via RestoreEntity.
  • Hydrolysis runtime counters (hydrolysis_runtime_*, polarity_changes)
    come from the controller's persistent storage and record on every SENSOR
    tick — they only change while hydrolysis is actively running.

Raw row counts per day

Assuming hydrolysis runs ~6 h/day, per device, all 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

Most of the variance comes from the hydrolysis runtime counters during active
hydrolysis. If you run an aggressive TelePeriod (≤10s) and want to cut that
churn, exclude them from raw history — the hourly long-term statistics are
stored separately and remain available for trend graphs:

recorder:
  exclude:
    entities:
      - 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

Migrated installs use the neopool_mqtt_* prefix. For broader recorder tuning
see the Home Assistant recorder docs.

Troubleshooting

Enable Debug Logging

Add this to your configuration.yaml and restart Home Assistant:

logger:
  default: warning
  logs:
    custom_components.sugar_valley_neopool: debug

To enable it temporarily without a restart, call the logger.set_level
service with custom_components.sugar_valley_neopool: debug.

Download Diagnostics

Settings → Devices & Services → Sugar Valley NeoPool → ⋮ → Download
diagnostics
. The file is sanitized — NodeID and MQTT topics are redacted.

Common Issues

  • Entities unavailable — check the Tasmota device is online and publishing
    to MQTT, the topic matches your config, and the LWT topic shows "Online".
  • Commands not working — ensure Tasmota has write access to NeoPool and
    your MQTT broker permissions allow it.

Reporting Issues

When opening an issue,
please attach the diagnostics file, your Home Assistant and
integration versions, full debug logs, and the steps to reproduce.
The GitHub README has a step-by-step "Getting FULL Debug Logs" guide.

Development

This project ships a comprehensive test suite (pytest + coverage), ruff
linting/formatting, type checking, and CI workflows (Tests, Validate,
Release). See the GitHub repository
for contributor setup.

Coffee

If you like this integration, I'll gladly accept some quality coffee,
but please don't feel obliged.
:slight_smile:

BuyMeCoffee

License

This project is licensed under the MIT License.

Acknowledgments

2 Likes

Wow! What a spectacular job! Thank you so much!

I migrated everything without any problems.

1 Like

Thanks!! Worked a lot on the migration part, but I needed some feedbacks from users. Luckily it seems to be working fine.

Did you use the new lovelace files? Any issues on those?

awesome job! I also migrated without any issues :smiling_face_with_sunglasses:

1 Like

I'm still using my custom dashboard, sorry