pyhaseiq
Read-only Python library for Hase iQ wood stoves, over their local WebSocket. Fully local: no cloud, no vendor app, no account.
🔍 READ-ONLY — THIS LIBRARY COMMANDS NOTHING
pyhaseiqqueries the stove: temperature, combustion phase, performance. It writes nothing, sets nothing, lights nothing, extinguishes nothing. No write command has been observed in the protocol, none is implemented, and that is a permanent choice of the project — see the prohibitions.A wood stove is a combustion appliance: operating it stays manual and is the responsibility of its user. This library observes; it substitutes for no safety device.
⚠️ INDEPENDENT PROJECT, WITH NO AFFILIATION WHATSOEVER
pyhaseiqis in no way affiliated with, supported, endorsed or approved by HASE Kaminofenbau GmbH, or any of its subsidiaries, brands, related companies, subcontractors or partners. HASE, Hase iQ and flamemonitor are trademarks of their respective owners, cited solely to describe the hardware this library communicates with, for interoperability purposes.👉 Read the full disclaimer below before any use. It covers the complete absence of warranty, the manufacturer's warranty and the conditions of use. By using this library, you acknowledge having read and accepted them.
⚠️ Full disclaimer — read before any use
This project is entirely independent and is in no way affiliated with, supported, endorsed or approved by HASE Kaminofenbau GmbH (Niederkircher Straße 14, 54294 Trier, Amtsgericht Wittlich HRB 4937), or any of its subsidiaries, brands, related companies, subcontractors or partners.
HASE, Hase iQ and flamemonitor are trademarks of their respective owners. They are cited here only to describe the hardware this library may communicate with, for interoperability purposes. No code, binary, firmware, cryptographic key or manufacturer documentation is reproduced or redistributed in this repository.
Project name — pyhaseiq is a working name chosen for readability. It carries no
affiliation, and constitutes neither a trademark, nor a claim of origin, nor an
authorisation from the owner of the Hase trademark. This library is a third-party
component compatible with this hardware, and nothing more.
Method — the protocol documented here was reconstructed solely by observing the network dialogue between the vendor application and a legally acquired stove, on an installation belonging to the author. No firmware was decompiled, and no manufacturer cryptographic key was extracted or published. This work falls under the interoperability exception (art. L122-6-1 III and IV of the French Intellectual Property Code, directive 2009/24/EC art. 5 and 6).
Read-only — this library sends no write command to the stove. It changes no setting, and neither starts nor interrupts any combustion. Operating the stove stays entirely manual and under the responsibility of its user, in accordance with the manufacturer's manual.
No safety role — the values read are provided for information only. They constitute neither a certified measurement, nor an alarm, nor a safety device, and are no substitute whatsoever for a smoke detector, a carbon monoxide detector or the statutory sweeping of your installation. Base no safety decision on this library.
Use — this library is intended for reading equipment that you own or are the legitimate user of, and that alone.
No warranty — this software is provided "as is", without warranty of any kind, express or implied, including but not limited to the warranties of merchantability, fitness for a particular purpose and non-infringement. To the extent permitted by applicable law, the author shall not be held liable for any damage whatsoever: malfunction, hardware damage, data loss, or any direct or indirect damage resulting from the use of this library.
Manufacturer's warranty — using this software with your hardware may affect its warranty. Check before using it.
Support — provided on a voluntary basis, with no commitment as to delay or outcome.
License — MIT, see LICENSE.
By using this library, you acknowledge having read and accepted all of these conditions.
Contents
- Which generation?
- Quick start
- Project status
- Installation
- Usage
- Logging
- Development
- Contributing
- Security
Which generation?
Two generations of stoves carry the name "Hase iQ", and they do not speak the same language. They are told apart by the application you use:
| your application | generation | pyhaseiq |
|---|---|---|
flamemonitor |
old | ✅ supported |
HASE iQ |
new | ❌ not supported |
The new generation has not been observed and its protocol is unknown. Nothing is planned on that front, and feedback is welcome.
The protocol of the old one is described in full in
docs/SPEC-WS-PROTOCOL.md, where every statement carries a
✅ confirmed / 🟡 partial / ❓ assumed status.
Quick start
With uv and the IP address of your stove:
git clone https://github.com/bbayszczak/pyhaseiq
cd pyhaseiq
uv run demo.py 192.168.1.165
uv creates the environment and installs the dependencies on its own. demo.py writes
nothing: it displays a continuously refreshed table with the stove's phase and the available
readings. It is the quickest way to check that your stove answers.
Project status
🚧 Alpha. Reading works and the protocol is documented. The API may still change.
The changes of each version are recorded in the CHANGELOG, kept up to date automatically from the commit messages.
Installation
pip install pyhaseiq
Or straight from the repository:
pip install git+https://github.com/bbayszczak/pyhaseiq
Usage
The API is asynchronous: the stove is a WebSocket server, and that is the model a host such as Home Assistant expects.
import asyncio
from pyhaseiq import Client, Phase
async def main() -> None:
async with Client("192.168.1.165") as stove:
phase = await stove.get_phase()
print(phase) # Phase.HEATING_UP
if phase is Phase.HEATING_UP:
print(await stove.get_temperature()) # 163.3 °C in the firebox
print(await stove.get_heat_up_percent()) # 53.5 % of the heat-up
elif phase is Phase.NOMINAL:
print(await stove.get_performance()) # 69 % combustion performance
asyncio.run(main())
The phases
get_phase() returns a Phase, which is an IntEnum:
| value | name | meaning |
|---|---|---|
0 |
Phase.IDLE |
no fire, the stove is waiting |
1 |
Phase.HEATING_UP |
fire burning, the temperature is rising |
2 |
Phase.NOMINAL |
nominal temperature reached |
3 |
Phase.NEEDS_WOOD |
wood needs to be added |
4 |
Phase.BURNING_OUT |
the fire is dying down, add no more wood |
⚠️ Not every reading is available in every phase. The vendor application only asks for
appTandappAufheizin phaseHEATING_UP, and forappPin phaseNOMINAL. Whether the stove answers anyway outside those phases or stays silent is unknown — in which case the call ends in aResponseTimeoutError. Test the phase before reading, as the example above does. The one exception known so far: the stove answersappTin phaseNOMINALtoo.
get_status() does that test for you: it reads the phase, the temperature in every phase, then
only the other readings the vendor application asks for in that phase, and returns a
Status in which the others are None:
status = await stove.get_status()
print(status)
# Status(phase=<Phase.HEATING_UP: 1>, temperature=163.3, heat_up_percent=53.5, performance=None)
The errors
All of them derive from HaseIQError, which makes it possible to catch the whole library with
a single except:
| exception | when |
|---|---|
ConnectionFailedError |
stove unreachable, or connection lost mid-dialogue |
ResponseTimeoutError |
the stove did not answer within the allotted time |
ProtocolError |
unreadable answer, or unknown phase |
The client never reconnects on its own: it keeps no state, and the retry policy belongs to the caller. A lost connection stays lost — open a new client.
Raw requests
The requests that are documented but not exposed through a typed method — the measurement series, the firmware versions — remain reachable:
await stove.get("_wversion") # '1.4'
await stove.get("appP30Tx") # '30'
await stove.get("appP30T[15;29]") # '41;40;40;40;40;39;...'
The names are listed in docs/SPEC-WS-PROTOCOL.md.
Trying it without writing any code
uv run demo.py 192.168.1.165 # continuously refreshed table
uv run demo.py 192.168.1.165 --once # a single reading
uv run demo.py 192.168.1.165 --request _wversion # a raw request, repeated
uv run demo.py 192.168.1.165 --debug # show the WebSocket dialogue
Sample output:
┏━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━┓
┃ parameter ┃ value ┃
┡━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━┩
│ Last update │ 09/21/26 - 08:51:12 │
│ Phase │ heating up (1) │
│ Temperature (°C) │ 163.3 │
│ Heat-up (%) │ 53.5 │
│ Performance (%) │ — │
└──────────────────┴───────────────────────┘
Logging
The library uses the standard logging module and configures nothing: no handler, no
level, no format. The host application decides. Each module has its own logger, named after the
package — pyhaseiq.client — which allows filtering on the whole package as well as on a
single module.
Everything is at DEBUG: opening the connection, and each request / response pair. Errors are
not logged, they are raised; it is up to the caller to decide what to do with them.
In Home Assistant, through configuration.yaml:
logger:
logs:
pyhaseiq: debug
In a standalone script:
import logging
logging.basicConfig(level=logging.DEBUG)
Sample trace:
DEBUG pyhaseiq.client: connecting to ws://192.168.1.165:8080
DEBUG pyhaseiq.client: appPhase = 1
DEBUG pyhaseiq.client: appT = 163.3
DEBUG pyhaseiq.client: appAufheiz = 53.5
The stove exposes no identifier, no key and no personal data: a DEBUG trace can be attached
as is to a bug report.
Development
uv run ruff check . # lint
uv run ruff format . # formatting
uv run pytest # tests — no hardware required, the stove is faked
Contributing
Feedback is welcome, especially about other stove models and about the generation driven by
the HASE iQ application, which has never been observed.
- Report a bug or suggest a change — open an issue, stating which application you normally drive your stove with.
- Propose code — scope, conventions and prohibitions are described in CONTRIBUTING.md, to be read before opening a pull request.
Security
The stove exposes an unencrypted WebSocket with no authentication whatsoever on port
8080: any machine on your local network can query it. This is not a choice of this library,
it is how the stove is designed.
Never expose this port on the Internet, and do not forward it from your router. Leave the stove on the local network, behind your router.
To report a vulnerability in this library, use the private reporting — never a public issue.
Metadata
Release files for pyhaseiq 0.2.1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| pyhaseiq-0.2.1.tar.gz | 50.4 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| pyhaseiq-0.2.1-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 64.7 kB
Release files / pyhaseiq-0.2.1.tar.gz
| Download URL | pyhaseiq-0.2.1.tar.gz |
|---|---|
| Size | 50.4 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
1751545bbf13bf96116548e0aba6457eb4377d410a92c2ed3bc004d3d602dc10
|
|
BLAKE2b-256 checksum How to use checksums |
1f91b96d26595b746dd8d6cf323dcf593cb6f807b75a3150c94c6a82d2a1aae1
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 10, 2026.
Transparency logRelease files / pyhaseiq-0.2.1-py3-none-any.whl
| Download URL | pyhaseiq-0.2.1-py3-none-any.whl |
|---|---|
| Size | 14.2 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
34ee5e1d865483a9af35790528cf105c3c54a11e12fc41c8777af8850c2def7a
|
|
BLAKE2b-256 checksum How to use checksums |
b127b2393dac58bf8536a249d80cc0d1cde26637601d2a7c23519d4ef18c19eb
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 10, 2026.
Transparency log