Skip to content

support ChemSync (pH/ORP) device type + disambiguate multiple ChlorSync units #6

Description

@ottoloco-tech

Environment

  • Integration version: 1.0.4
  • Home Assistant: 2026.7.2 (Home Assistant OS 18.1, aarch64)
  • PoolSync controller: firmware 860, hardware 3.0
  • Equipment attached: 1x ChemSync (pH/ORP), 2x ChlorSync chlorinators — one plumbed to the pool, one to the spa

Summary

After pairing, the integration correctly creates the PoolSync controller device and one chlorinator device — but my system actually has three pieces of equipment attached (visible in the PoolSync app: a Chemistry tile showing pH/ORP, plus two separate Chlorinator tiles, one for the pool and one for the spa). Three issues:

  1. ChemSync (pH/ORP) isn't supported at all — no entities are created for deviceType: "chemSync", even though the local API returns full pH/ORP/feed data for it.
  2. The second ChlorSync unit is dropped. Both chlorinators report nodeAttr.name: "Chlorinator" (differing only by nodeAddr: 18 vs 19), and only one ends up with entities — I'm guessing they collide because the device/unique_id isn't keyed by node address when the name is identical. Since one unit serves the pool and the other the spa, this isn't a redundant reading — I need both.
  3. sensor.chlorinator_water_temperature is mislabeled as °C but the raw value is actually °F. The entity carries unit_of_measurement: "°C" but reports the device's native Fahrenheit reading unconverted (e.g. state 94.96 tagged °C — a scary number for water, and physically impossible for a home pool). Converting that same raw value as Fahrenheit gives ~35°C, which lines up with the ~36°C the PoolSync app shows for that loop.

Issue 1 — ChemSync not created

Raw payload for the Chemistry device (devices.0, deviceType.0 == "chemSync"):

json { "nodeAttr": { "name": "Chemistry", "pid": 10752, "nodeAddr": 21, "idmpAddr": 0, "online": true, "flags": 0, "bootMode": 2 }, "status": { "flags": 368, "ph": 8.16, "orp": 709, "boostRemaining": 0, "acidConsumed": 1941, "boardTemp": 114.41 }, "system": { "fwVersion": 533, "hwVersion": "F", "modelNum": "ChemSync", "serialNum": "REDACTED" }, "config": { "sysMode": 3, "phEnabled": true, "phSetpoint": 7.2, "phMin": 7.2, "phMax": 7.8, "phOffset": 0.02, "orpEnabled": true, "orpSetpoint": 650, "feedRate": 87662, "feedRateUnits": 0, "feedAmount": 0, "maxDailyFeed": 100, "flowSensorEnable": true, "flowPolarity": 0, "acidTankAlertAmount": 640, "manualMode": true }, "faults": [4] } ​

Would love to see this exposed roughly as:

  • sensor — pH, ORP, board temp, acid consumed
  • binary_sensor — fault, flow present
  • number (optional) — pH setpoint, ORP setpoint, if writable via the same PATCH pattern used for chlorinator output

Issue 2 — second ChlorSync unit collides with the first

Both units, for comparison — note identical nodeAttr.name, distinct nodeAddr:

Chlorinator A (devices.1, nodeAddr 18) — this one gets entities today:
json { "nodeAttr": { "name": "Chlorinator", "nodeAddr": 18, "idmpAddr": 0, "online": true }, "status": { "waterTemp": 94.96, "boardTemp": 99.95, "fwdCurrent": 890, "revCurrent": 890, "outVoltage": 577, "cellRailVoltage": 4959, "saltPPM": 3716, "boostRemaining": 0 }, "config": { "chlorOutput": 0, "poolCoverCtrl": true, "tempCompEnable": false, "gallons": 60000 }, "system": { "drvModelNum": "PCR0002A", "drvFwVersion": 773, "cellFwVersion": 9, "cellHwVersion": 66 }, "faults": [0] } ​

Chlorinator B (devices.2, nodeAddr 19) — missing from HA entirely:
json { "nodeAttr": { "name": "Chlorinator", "nodeAddr": 19, "idmpAddr": 0, "online": true }, "status": { "waterTemp": 96.33, "boardTemp": 99.17, "fwdCurrent": 1246, "revCurrent": 1141, "outVoltage": 0, "cellRailVoltage": 4865, "saltPPM": 3877, "boostRemaining": 0 }, "config": { "chlorOutput": 0, "poolCoverCtrl": true, "tempCompEnable": true, "gallons": 60000 }, "system": { "drvModelNum": "", "drvFwVersion": 773, "cellFwVersion": 9, "cellHwVersion": 66 }, "faults": [0] } ​

Suggested fix: key the device/unique_id off nodeAddr (or pid+nodeAddr) rather than the display name, and fall back to a suffix like "Chlorinator 2" for the friendly name when duplicates are detected. Since these are functionally pool vs. spa units, it'd also be great if the integration (or a config option) let us label each by nodeAddr, e.g. "Chlorinator — Pool" / "Chlorinator — Spa".

Issue 3 — water temperature reported in °F but labeled °C

sensor.chlorinator_water_temperature currently returns:

state: 94.96 unit_of_measurement: "°C" device_class: "temperature" ​

waterTemp in the raw API payload is in Fahrenheit — 94.96°F converts to 34.98°C, consistent with a heated pool/spa in the Bahamas in July and with the ~36°C shown in the PoolSync app. Right now Home Assistant shows the raw Fahrenheit number under a Celsius label, which reads as an alarming/impossible water temperature until you realize the unit tag is wrong.

As a stop-gap on my end I added a template sensor that converts the raw value:
jinja {{ (((states('sensor.chlorinator_water_temperature') | float(0)) - 32) * 5 / 9) | round(1) }} ​
but obviously this should be fixed at the source so °C and °F installs both display correctly without a workaround.

Confirming evidence from a second, simpler system

I have a second PoolSync controller ("Beach Spa") with just one ChemSync and one ChlorSync cell. Pairing that one was clean — because I'd already given the chlorinator a unique name on the device itself ("Chlor Cell Beach Spa" instead of the generic default "Chlorinator"), it didn't hit the name-collision problem from Issue 2, which supports that diagnosis.

However, the same two other bugs reproduce exactly:

  • The ChemSync on this system also reports live pH/ORP (ph: 7.4, orp: 705) but gets no entities — Issue 1 again.
  • sensor.chlor_cell_beach_spa_water_temperature shows 91.65 tagged °C — same unit bug as Issue 3 (91.65°F ≈ 33.1°C, which matches this spa's actual temperature).

So this isn't specific to one controller/firmware — happy to provide diagnostics from either system.

Happy to help test

I have two PoolSync controllers (1x ChemSync + 2x ChlorSync on one, 1x ChemSync + 1x ChlorSync on the other) running and can pull more diagnostics, test builds, or before/after payloads on request.

Metadata

Metadata

Assignees

Labels

bugSomething isn't workingenhancementNew feature or request

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions