Async Python client for the Fresh-r / bw-log.com API.
Project description
pyfreshr
Python library around the Fresh-r web interface for use in a Home Assistant integration.
Installation
pip install pyfreshr
Quick start
import asyncio
from pyfreshr import FreshrClient
async def main():
async with FreshrClient() as client:
await client.login("user@example.com", "password")
devices = await client.fetch_devices()
for device in devices:
readings = await client.fetch_device_current(device)
print(device.id, readings.t1, readings.flow, readings.co2)
asyncio.run(main())
Session persistence
The login sequence performs three HTTP round-trips. To avoid repeating this on every Home Assistant restart, save the session token after login and restore it on the next startup. The client re-authenticates automatically if the restored token has expired.
from pyfreshr import FreshrClient
async def setup(hass, stored_token):
client = FreshrClient(on_session_update=lambda token: hass.store.save(token))
if stored_token:
client.restore_session(stored_token) # skip login if token is still valid
else:
await client.login("user@example.com", "password")
return client
Example script
Run the example script (without installing the package) from the repository root:
PYTHONPATH=src python examples/example_usage.py
You can also set credentials via environment variables FRESHR_USER and FRESHR_PASS before running the script.
Models
DeviceSummary
Returned by fetch_devices(). Contains the device identifier and metadata.
| Field | Type | Description |
|---|---|---|
id |
str | None |
Device serial number |
type |
str |
Raw type string from the API (e.g. "fresh-r-itw") |
active_from |
str | None |
Activation date |
device_type |
DeviceType |
Categorised type derived from type (property) |
extras |
dict |
Any additional fields returned by the API |
DeviceReadings
Returned by fetch_device_current(). All numeric fields are None when the API does not return a value for the device type. See Value processing for fields that are calibrated before being returned.
| Field | Type | Unit | Description |
|---|---|---|---|
t1 |
float | None |
°C | Supply air temperature |
t2 |
float | None |
°C | Extract air temperature |
t3 |
float | None |
°C | Temperature sensor 3 |
t4 |
float | None |
°C | Temperature sensor 4 |
flow |
float | None |
m³/h | Ventilation flow (calibrated) |
co2 |
int | None |
ppm | CO₂ concentration |
hum |
float | None |
%RH | Relative humidity (temperature-adjusted) |
dp |
float | None |
°C | Dew point |
temp |
float | None |
°C | Temperature sensor (Forward and Monitor only) |
extras |
dict |
— | All other fields from the API, including particle measurements (d5_25, d1_25, etc. in µg/m³) |
Supported devices
The dashboard exposes four device types. Three are supported; the fourth (Extract) uses a separate external API that is not covered by this library.
| Device type | DeviceType |
Supported |
|---|---|---|
| Fresh-R | DeviceType.FRESH_R |
Yes |
| Forward | DeviceType.FORWARD |
Yes (untested) |
| Monitor | DeviceType.MONITOR |
Yes (untested) |
| Fresh-R Extract | — | No |
The device type is detected automatically from the type string returned by the API (substring match, mirroring the dashboard JS). fetch_device_current accepts a DeviceSummary directly and uses its type to select the correct API request name and default field list.
Value processing
Raw API values are calibrated before being returned, matching the processing performed by the dashboard JavaScript (processCurrentData). The processed values are reflected in the DeviceReadings fields.
Flow (DeviceReadings.flow)
Flow is calibrated through a piecewise curve. For Forward devices the raw sensor value is first divided by 3 before the curve is applied.
if raw_flow > 200:
flow = (raw_flow − 700) / 30 + 20
else:
flow = raw_flow
flow = round(flow, 1) # m³/h
Humidity (DeviceReadings.hum)
Humidity is adjusted for the supply-air temperature using the Magnus-Tetens formula. The reference temperature used depends on device type:
| Device type | Reference temperature |
|---|---|
| Fresh-R | t1 (supply air temperature) |
| Forward | temp (temperature sensor) |
| Monitor | None — raw humidity is rounded to 1 dp |
T_sh = 243.04 × (a − ln(hum/100)) / (17.625 + ln(hum/100) − a)
where a = 17.625 × dp / (243.04 + dp)
hum_adj = hum × exp(4283.78 × (T_sh − T_ref) / (243.12 + T_sh) / (243.12 + T_ref))
hum_adj = round(hum_adj, 1) # %RH
If any input value is missing or the formula produces NaN the raw humidity (rounded to 1 dp) is returned instead.
Project details
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 pyfreshr-1.0.0.tar.gz.
File metadata
- Download URL: pyfreshr-1.0.0.tar.gz
- Upload date:
- Size: 23.6 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
4fb684b32a208c11cb661ab984624d27833c94240ba69e8287ffed4f67cdc76b
|
|
| MD5 |
8c78fd10514735ac8df4d1c5a52902fb
|
|
| BLAKE2b-256 |
c17a4137fdc27efc63be4686ef737c1acaa946d617ba7982367a5820fa8c51a5
|
Provenance
The following attestation bundles were made for pyfreshr-1.0.0.tar.gz:
Publisher:
build.yml on SierraNL/pyfreshr
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
pyfreshr-1.0.0.tar.gz -
Subject digest:
4fb684b32a208c11cb661ab984624d27833c94240ba69e8287ffed4f67cdc76b - Sigstore transparency entry: 1006702195
- Sigstore integration time:
-
Permalink:
SierraNL/pyfreshr@b6c20c0327d8d77858ea4bc57ca43499c7a4037f -
Branch / Tag:
refs/tags/v1.0.0 - Owner: https://github.com/SierraNL
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
build.yml@b6c20c0327d8d77858ea4bc57ca43499c7a4037f -
Trigger Event:
push
-
Statement type:
File details
Details for the file pyfreshr-1.0.0-py3-none-any.whl.
File metadata
- Download URL: pyfreshr-1.0.0-py3-none-any.whl
- Upload date:
- Size: 13.3 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
b05a3ee955296a7477c52b29408c2e586b6f7f98a818fa56091d8acd00e0e474
|
|
| MD5 |
ff3918cbf8e593e18a15856f553da576
|
|
| BLAKE2b-256 |
d2f45a226dfcdb2f1bdd3b4d42bf9a11db6ea062d16c4c2121f7f78fcc520065
|
Provenance
The following attestation bundles were made for pyfreshr-1.0.0-py3-none-any.whl:
Publisher:
build.yml on SierraNL/pyfreshr
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
pyfreshr-1.0.0-py3-none-any.whl -
Subject digest:
b05a3ee955296a7477c52b29408c2e586b6f7f98a818fa56091d8acd00e0e474 - Sigstore transparency entry: 1006702197
- Sigstore integration time:
-
Permalink:
SierraNL/pyfreshr@b6c20c0327d8d77858ea4bc57ca43499c7a4037f -
Branch / Tag:
refs/tags/v1.0.0 - Owner: https://github.com/SierraNL
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
build.yml@b6c20c0327d8d77858ea4bc57ca43499c7a4037f -
Trigger Event:
push
-
Statement type: