Async Python library for interacting with the ProCon.IP pool controller.
Project description
Python package for the ProCon.IP Pool Controller
Overview
- Introduction (What is this library for?)
- Requirements
- Installation
- Usage
- A brief description of the ProCon.IP pool controller
- Get support
- Give support
- Release Notes
- Disclaimer
Introduction
The name of this library refers to the ProCon.IP pool controller. It is a port of my procon-ip TypeScript library (available as NPM Package). As the TypeScript library was a byproduct of my ioBroker adapter for the pool controller unit, this library is primarily intended for the implementation of a Home Assistant integration.
The library is fully typed (PEP 561). An IDE with auto-completion will give you most of what you need; for the full reference see the documentation site:
- API reference: https://ylabonte.github.io/proconip-pypi/
Feel free to ask questions via GitHub Issues so others can benefit from the answers too. Thanks!
Requirements
- Python ≥ 3.13
aiohttp >= 3.10, < 4yarl >= 1.9, < 2
These dependency ranges are compatible with
Home Assistant Core 2026.5 pins
(aiohttp==3.13.5, yarl==1.23.0).
v2.0.0 breaking changes — see CHANGELOG.md for details:
- Python ≥ 3.13 required (was ≥ 3.10)
async-timeoutdependency removed (useasyncio.timeoutfrom stdlib)Relayvalue semantics fixed (offset+gain applied exactly once)TimeoutExceptionis now actually raised for timeouts
Installation
This library is available on PyPI. So you can easily install it with pip:
pip install proconip
or
python -m pip install proconip
In both cases you can add --upgrade to update to the latest version.
Usage examples
Reading the current state
import asyncio
import aiohttp
from proconip import ConfigObject, GetState
async def reading_data_example():
client_session = aiohttp.ClientSession()
config = ConfigObject("http://192.168.2.3", "admin", "admin")
get_state_api = GetState(client_session, config)
data = await get_state_api.async_get_state()
await client_session.close()
print(f"Redox (Chlor): {data.redox_electrode.display_value}")
print(f"pH: {data.ph_electrode.display_value}")
for relay in (r for r in data.relays() if r.name != "n.a."):
print(f"{relay.name}: {relay.display_value}")
for temp in (t for t in data.temperature_objects if t.name != "n.a."):
print(f"{temp.name}: {temp.display_value}")
asyncio.run(reading_data_example())
Switching relays
import asyncio
import aiohttp
from proconip import ConfigObject, GetState, RelaySwitch
async def relay_switching_example():
client_session = aiohttp.ClientSession()
config = ConfigObject("http://192.168.2.3", "admin", "admin")
get_state_api = GetState(client_session, config)
relay_switch = RelaySwitch(client_session, config)
data = await get_state_api.async_get_state()
print(f"Relay no. 2: {data.get_relay(1).display_value}")
print(f"Relay no. 3: {data.get_relay(2).display_value}")
await relay_switch.async_set_auto_mode(data, 1)
data = await get_state_api.async_get_state()
print(f"Relay no. 2: {data.get_relay(1).display_value}")
await relay_switch.async_switch_on(data, 2)
data = await get_state_api.async_get_state()
print(f"Relay no. 3: {data.get_relay(2).display_value}")
await relay_switch.async_switch_off(data, 1)
data = await get_state_api.async_get_state()
print(f"Relay no. 2: {data.get_relay(1).display_value}")
await relay_switch.async_switch_off(data, 2)
data = await get_state_api.async_get_state()
print(f"Relay no. 3: {data.get_relay(2).display_value}")
await client_session.close()
asyncio.run(relay_switching_example())
Starting manual dosage
Manual dosage depends on the same factors as if started from the web interface of the pool control itself.
import asyncio
import aiohttp
from proconip import ConfigObject, DosageControl
async def manual_dosage_example():
client_session = aiohttp.ClientSession()
config = ConfigObject("http://192.168.2.3", "admin", "admin")
dosage_control = DosageControl(client_session, config)
await dosage_control.async_chlorine_dosage(3600) # start for 1 hour
await dosage_control.async_ph_minus_dosage(60) # start for 1 minute
await client_session.close()
asyncio.run(manual_dosage_example())
Reading and changing DMX channel states
import asyncio
import aiohttp
from proconip import ConfigObject, DmxControl
async def dmx_example():
client_session = aiohttp.ClientSession()
config = ConfigObject("http://192.168.2.3", "admin", "admin")
dmx_control = DmxControl(client_session, config)
dmx_data = await dmx_control.async_get_dmx()
for channel in dmx_data:
print(f"{channel.name} before: {channel.value}")
dmx_data.set(channel.index, (channel.value + 128) % 256)
print(f"{channel.name} after: {dmx_data.get_value(channel.index)}")
await dmx_control.async_set(dmx_data)
await client_session.close()
asyncio.run(dmx_example())
A brief description of the ProCon.IP pool controller
The ProCon.IP pool controller is a low budget network attached control unit for
home swimming pools. With its software switched relays, it can control
multiple pumps (for the pool filter and different dosage aspects) either
simply planned per time schedule or depending on a reading/value from one of
its many input channels for measurements (eg. i/o flow sensors, Dallas 1-Wire
thermometers, redox and pH electrodes). At least there is also the option to
switch these relays on demand, which makes them also applicable for switching
lights (or anything else you want) on/off.
Not all of its functionality is reachable via API. In fact there is one
documented API for reading (polling) values as CSV (/GetState.csv). In my
memories there was another one for switching the relays on/off and on with
timer. But I cannot find the second one anymore. So not even pretty, but
functional: The ProCon.IP has two native web interfaces, which can be
analyzed, to some kind of reverse engineer a given functionality (like
switching the relays).
For more information see the following links (sorry it's only in german; haven't found an english documentation/information so far):
Get support
Need help? Please use the github issues system to ask your question. This way others can contribute or at least take advantage of the final solution.
Give support
If you want to support this project or my work in general, you can do so without having any coding abilities. Because programmers are described as machines that convert coffee (their habitual input) into code (their habitual output), there is a really simple way to support me:
Release Notes
See CHANGELOG.md for the full release history.
Disclaimer
Just to be clear: I have nothing to do with the development, selling, marketing or support of the pool controller
unit itself.
I just developed small TypeScript/JS and Python libraries as by-products of an ioBroker adapter and a Home Assistant
integration for integrating the pool controller unit with common smart home solutions.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file proconip-2.1.0.tar.gz.
File metadata
- Download URL: proconip-2.1.0.tar.gz
- Upload date:
- Size: 32.9 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
6ec43fff85dc2407c3e45cd16a0b9ab87d4e504df46faa8c12e091e1c1e7d4d5
|
|
| MD5 |
b29ff7a490dbb9d34cf12c067f224814
|
|
| BLAKE2b-256 |
70105a6aac9cd4405e664c442d1038471f0b73f5af74a48c9ffb60f1cbef94cf
|
Provenance
The following attestation bundles were made for proconip-2.1.0.tar.gz:
Publisher:
python-publish.yml on ylabonte/proconip-pypi
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
proconip-2.1.0.tar.gz -
Subject digest:
6ec43fff85dc2407c3e45cd16a0b9ab87d4e504df46faa8c12e091e1c1e7d4d5 - Sigstore transparency entry: 1564151715
- Sigstore integration time:
-
Permalink:
ylabonte/proconip-pypi@982d5a889344730d946a4c828bebfdd2418a6994 -
Branch / Tag:
refs/tags/v2.1.0 - Owner: https://github.com/ylabonte
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
python-publish.yml@982d5a889344730d946a4c828bebfdd2418a6994 -
Trigger Event:
release
-
Statement type:
File details
Details for the file proconip-2.1.0-py3-none-any.whl.
File metadata
- Download URL: proconip-2.1.0-py3-none-any.whl
- Upload date:
- Size: 24.0 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
19abc37ae8b846f2058e2f74aa5b1545a0d8b1621bdf476bd38ba337727fd286
|
|
| MD5 |
119e8b891626d85c9582af9bb37ec072
|
|
| BLAKE2b-256 |
182ae70919c82e6d408441d59d2623fb607710f28cb6d59631caeb56e6fd7c0b
|
Provenance
The following attestation bundles were made for proconip-2.1.0-py3-none-any.whl:
Publisher:
python-publish.yml on ylabonte/proconip-pypi
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
proconip-2.1.0-py3-none-any.whl -
Subject digest:
19abc37ae8b846f2058e2f74aa5b1545a0d8b1621bdf476bd38ba337727fd286 - Sigstore transparency entry: 1564151725
- Sigstore integration time:
-
Permalink:
ylabonte/proconip-pypi@982d5a889344730d946a4c828bebfdd2418a6994 -
Branch / Tag:
refs/tags/v2.1.0 - Owner: https://github.com/ylabonte
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
python-publish.yml@982d5a889344730d946a4c828bebfdd2418a6994 -
Trigger Event:
release
-
Statement type: