Skip to main content

pyCheckwatt

Python package for communicating with CheckWatt EnergyInBalance targeted for Home Assistant integrations and other use-cases.

Warning

This library is provided as-is and is not supported or approved by CheckWatt. CheckWatt can implement breaking changes at any time that renders this module useless. The module may not be updated promptly, or not at all if the changes are not possible to reverse engineer.

Status

The library is experimental and pulls basic info from EnergyInBalance. Use with care as it loads the servers of CheckWatt

Example

The following example will login to EnergyInBalance and retrieve information.

Create a file called example.py that looks like this:

"""Example-module for pyCheckwatt."""

import argparse
import json

from pycheckwatt import CheckwattManager


async def main(show_details=False):
    """Fetch username and password from environment variables."""
    username = "EIB username"
    password = "EiB password"

    # Create the async class
    async with CheckwattManager(username, password) as check_watt_instance:
        try:
            # Login to EnergyInBalance and check kill switch
            if await check_watt_instance.login():
                # Fetch customer detail
                await check_watt_instance.get_customer_details()

                # Do a sample
                print("Customer Details\n================")
                print(check_watt_instance.registered_owner)

                print("\nSystem\n======")
                print("Charge peak AC", check_watt_instance.battery_peak_data[0])
                print("Charge peak DC", check_watt_instance.battery_peak_data[1])
                print("Discharge peak AC", check_watt_instance.battery_peak_data[2])
                print("Discharge peak DC", check_watt_instance.battery_peak_data[3])
                print(check_watt_instance.battery_make_and_model)
                print(check_watt_instance.electricity_provider)

                print("\nLogbook Entries\n===============")
                for entry in check_watt_instance.logbook_entries:
                    print(entry)

                print("\nComments\n========")
                print(check_watt_instance.comments)

                await check_watt_instance.get_fcrd_today_net_revenue()
                await check_watt_instance.get_fcrd_year_net_revenue()
                await check_watt_instance.get_fcrd_month_net_revenue()
                print("\nFCR-D\n=====")
                print(f"FCR-D State: {check_watt_instance.fcrd_state}")
                print(f"FCR-D Discharge: {check_watt_instance.fcrd_percentage_up}% of {check_watt_instance.fcrd_power}kW")
                print(f"FCR-D Charge: {check_watt_instance.fcrd_percentage_down}% of {check_watt_instance.fcrd_power}kW")
                print(f"FCR-D Response: {check_watt_instance.fcrd_percentage_response} seconds")
                print(f"FCR-D Date: {check_watt_instance.fcrd_timestamp}")

                print("\nRevenue\n=======")
                print(
                    "{:<24}  {:>6}  {:>0}".format(
                        "Daily average:",
                        int(check_watt_instance.fcrd_daily_net_average),
                        "kr",
                    )
                )
                print(
                    "{:<24}  {:>6}  {:>0}".format(
                        "Month estimate:",
                        int(check_watt_instance.fcrd_month_net_estimate),
                        "kr",
                    )
                )
                print(
                    "{:<24}  {:>6}  {:>0}".format(
                        "Month revenue:",
                        int(check_watt_instance.fcrd_month_net_revenue),
                        "kr",
                    )
                )
                print(
                    "{:<24}  {:>6}  {:>0}".format(
                        "Year revenue:",
                        int(check_watt_instance.fcrd_year_net_revenue),
                        "kr",
                    )
                )
                print(
                    "{:<24}  {:>6}  {:>0}".format(
                        "Today revenue:",
                        int(check_watt_instance.fcrd_today_net_revenue),
                        "kr",
                    )
                )


                await check_watt_instance.get_ems_settings()
                print("\nEMS Setting\n===========")
                print(check_watt_instance.ems_settings)

                await check_watt_instance.get_power_data()
                print("\nEnergy\n======")
                print(f"Solar: {check_watt_instance.total_solar_energy/1000} kWh")
                print(f"Charging: {check_watt_instance.total_charging_energy/1000} kWh")
                print(
                    f"Discharging: {check_watt_instance.total_discharging_energy/1000} kWh"  # noqa: E501
                )
                print(f"Import: {check_watt_instance.total_import_energy/1000} kWh")
                print(f"Export: {check_watt_instance.total_export_energy/1000} kWh")

                if show_details:
                    print("\nCustomer Details\n===============")
                    print(json.dumps(check_watt_instance.customer_details, indent=2))

        except Exception as e:
            print(f"An error occurred: {e}")


if __name__ == "__main__":
    parser = argparse.ArgumentParser(description="Checkwatt Information")
    parser.add_argument(
        "-d", "--details", action="store_true", help="Show system details"
    )
    args = parser.parse_args()

    import asyncio

    loop = asyncio.new_event_loop()
    asyncio.set_event_loop(loop)
    loop.run_until_complete(main(args.details))

Long-running applications should retain one CheckwattManager instance instead of creating one for every poll. Repeated calls to login() reuse a valid JWT and refresh it when necessary. An application-owned aiohttp.ClientSession can be passed with session=...; pyCheckwatt reuses an injected session but does not close it. Set raise_on_rate_limit=True to receive CheckwattRateLimitError with the requested retry delay. The default retains the legacy False return behavior.

Create a virtual environment and install pyCheckwatt:

$ python -m venv venv
$ ./venv/Scripts/activate
$ pip install pycheckwatt

Run the example code:

$ python example.py

Watch the output:

Customer Details
================
First name Surname(Street number postal code city)

System
======
Charge peak AC 15.0
Charge peak DC 15.0
Discharge peak AC 15.0
Discharge peak DC 15.0
Growatt APX 30 kWh/Could not get any information about your battery
Bixia AB via E.ON Energidistribution AB

Logbook Entries
===============
[ FCR-D ACTIVATED ] email@email.com --11111-- 97,5/0,6/96,0 % (15 kW) 2022-01-28 00:03:42 API-BACKEND
[ FCR-D DEACTIVATE ]  DOWN 50,19 Hz 46,0 %  (15 kW) 2022-01-22 12:00:25 API-BACKEND
[ FCR-D ACTIVATED ] email@email.com --11111-- 98,2/0,8/97,0 % (15 kW) 2022-01-18 00:02:28 API-BACKEND
[ FCR-D DEACTIVATE ]  UP 49,84 Hz 0,0 %  (15 kW) 2022-01-09 23:09:03 API-BACKEND

Comments
========
Kund har utökat till 20 kWh / 20 kW.

System
======
Charge peak AC 15.0
Charge peak DC 15.0
Discharge peak AC 15.0
Discharge peak DC 15.0
Could not get any information about your battery
Bixia AB via E.ON Energidistribution AB

Revenue
=======
Daily average:                48  kr
Month estimate:             1504  kr
Month revenue:               145  kr
Year revenue:               4008  kr
Today revenue:                39  kr

EMS Setting
===========
Currently optimized (CO)

Energy
======
Solar: 779.365 kWh
Charging: 719.286 kWh
Discharging: 185.699 kWh
Import: 1684.686 kWh
Export: 668.539 kWh

Docker Development

For developers who prefer not to install Python locally, a Docker-based development environment is available.

Prerequisites

  • Docker and Docker Compose installed
  • CheckWatt EnergyInBalance credentials

Quick Start

  1. Set up credentials

    cp .env.example .env
    # Edit .env with your CheckWatt credentials
    
  2. Build, run & cleanup

    # Build the development container
    docker compose -f docker-compose.dev.yml build
    
    # Run the example
    docker compose -f docker-compose.dev.yml run --rm pycheckwatt-dev python examples/example.py
    
    # Run the tests
    docker compose -f docker-compose.dev.yml run --rm pycheckwatt-dev pytest
    
    # Clean up containers
    docker compose -f docker-compose.dev.yml down
    

Inside the container local code changes are automatically synced and you can run standard Python development commands.

Development tools

The library requires Python 3.10 or newer. CI tests Python 3.10 through 3.14, including installation of the built wheel. The development container uses Python 3.14; library code retains Python 3.10 syntax compatibility.

The same lint commands used in CI can be run through Docker Compose:

docker compose -f docker-compose.dev.yml run --rm --build pycheckwatt-dev poetry run isort --check-only --diff .
docker compose -f docker-compose.dev.yml run --rm --build pycheckwatt-dev poetry run black --check --diff .
docker compose -f docker-compose.dev.yml run --rm --build pycheckwatt-dev poetry run flake8 .

Acknowledgements

This module was developed as a team effort by the following contributors.

This integration could not have been made without the excellent work done by the Home Assistant team.

If you like what have been done here and want to help I would recommend that you firstly look into supporting Home Assistant.

You can do this by purchasing some swag from their store or paying for a Nabu Casa subscription. None of this could happen without them.

Licenses

The integration is provided as-is without any warranties and published under The MIT License.

Metadata

Release files for pycheckwatt 0.3.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for pycheckwatt 0.3.0
File Size Uploaded Provenance
pycheckwatt-0.3.0.tar.gz 18.1 kB With provenance Details

Built distribution (wheel)

Table of built distributions (wheels) for pycheckwatt 0.3.0
File Interpreter ABI Platform
pycheckwatt-0.3.0-py3-none-any.whl Python 3 none any Details

Total release size: 34.0 kB

Release files / pycheckwatt-0.3.0.tar.gz

Download URL pycheckwatt-0.3.0.tar.gz
Size 18.1 kB
Tags Source
SHA-256 checksum
How to use checksums
f463b6d16802cc78a84b5c703154a63c631712ada4934c9f1da50ceba3f3e559
BLAKE2b-256 checksum
How to use checksums
125458ad9e7a214a78a5ad9c97cda0a00b44a20b6c89f1f0a71dd8d4c1a3b877
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 Sep 30, 2026.

Transparency log

Release files / pycheckwatt-0.3.0-py3-none-any.whl

Download URL pycheckwatt-0.3.0-py3-none-any.whl
Size 15.9 kB
Tags Python 3
SHA-256 checksum
How to use checksums
147f78758aebbd678c59ba425b025e671ff1ca7f28c835ff02f2cfc251640f81
BLAKE2b-256 checksum
How to use checksums
5b046e48f2151210c348b3bbb88f9a02640dacf16de3c935dc941b62a47ea43f
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 Sep 30, 2026.

Transparency log

Security for pycheckwatt 0.3.0

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.

Full provenance

All 2 files in this release have been uploaded with provenance metadata.

Select from 2 files

Attestation for pycheckwatt-0.3.0.tar.gz

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 Sep 30, 2026.

Transparency log

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page