Skip to main content

python-evnex

CI PyPI

Python client for the Evnex API.

Author not affiliated with Evnex.

Features

  • Talks to your Evnex charger via Cloud API
  • Automatic retries with exponential backoff
  • Automatic re-authentication
  • Optionally pass in a httpx client
  • Optionally pass in tokens to resume an existing session

Installation

pip install evnex

Requirements: Python 3.11+

Usage

import asyncio
from pydantic import SecretStr
from pydantic_settings import BaseSettings
from evnex.api import Evnex


class EvnexAuthDetails(BaseSettings):
    EVNEX_CLIENT_USERNAME: str
    EVNEX_CLIENT_PASSWORD: SecretStr


async def main():
    creds = EvnexAuthDetails()
    evnex = Evnex(username=creds.EVNEX_CLIENT_USERNAME,
                  password=creds.EVNEX_CLIENT_PASSWORD.get_secret_value())

    user_data = await evnex.get_user_detail()

    for org in user_data.organisations:
        print("Getting 7 day insight for", org.name, "User:", user_data.name)
        insights = await evnex.get_org_insight(days=7, org_id=org.id)

        for segment in insights:
            print(segment)


if __name__ == '__main__':
    asyncio.run(main())

Multifactor authentication

Accounts with MFA enabled can't authenticate with username and password alone: the first API call raises a challenge exception. Catch it, obtain a code from the user, then respond to the challenge:

from pycognito.exceptions import (
    SMSMFAChallengeException,
    SoftwareTokenMFAChallengeException,
)

evnex = Evnex(username=username, password=password)
try:
    evnex.authenticate()
except SoftwareTokenMFAChallengeException:
    code = input("Enter the 6-digit code from your authenticator application: ")
    evnex.respond_to_mfa_challenge(code, "TOTP")
except SMSMFAChallengeException:
    code = input("Enter the 6-digit code you received by SMS: ")
    evnex.respond_to_mfa_challenge(code, "SMS")

Note the Cognito challenge session is short-lived (around 3 minutes), so prompt for the code promptly.

The pending challenge is stored on the Evnex instance, so the example above works because the same instance calls authenticate() and respond_to_mfa_challenge(). If the response happens somewhere else — a different process, or a web backend handling a later request — capture the challenge session from the exception and hand it to the new instance:

try:
    evnex.authenticate()
except SoftwareTokenMFAChallengeException as challenge:
    challenge_session = challenge.get_tokens()  # JSON-serializable dict

# later, on a fresh Evnex instance
evnex.respond_to_mfa_challenge(code, "TOTP", mfa_tokens=challenge_session)

Resuming a session

To avoid interactive MFA on every start, store the tokens after a successful authentication and pass them back in later — the refresh token alone is enough. When the API rejects an expired or revoked access token, the client refreshes it and retries the request automatically:

evnex = Evnex(username=username, password=password, refresh_token=refresh_token)
user_data = await evnex.get_user_detail()  # no MFA prompt needed

See examples/get_token.py for a complete MFA + token resumption flow.

Examples

python-evnex is intended as a library, but a few example scripts are provided in the examples folder.

Providing authentication for the examples is via environment variables, e.g. on nix systems:

export EVNEX_CLIENT_USERNAME=you@example.com
export EVNEX_CLIENT_PASSWORD=<your password>

python -m examples.get_charge_point_detail

Developer Notes

Development Setup

# Install dependencies with development tools
uv sync --group dev

# Set up pre-commit hooks (recommended)
uv run pre-commit install

# Alternatively, format and lint manually
uv run ruff format .
uv run ruff check .

Making a new release

What ends up on PyPi is what really matters. Creating a release in GitHub triggers a release workflow that builds and publishes to PyPi.

To manually release, update the version in pyproject.toml, build and publish with uv:

uv build
uv publish

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

evnex-0.6.1.tar.gz (87.9 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

evnex-0.6.1-py3-none-any.whl (20.9 kB view details)

Uploaded Python 3

File details

Details for the file evnex-0.6.1.tar.gz.

File metadata

  • Download URL: evnex-0.6.1.tar.gz
  • Upload date:
  • Size: 87.9 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for evnex-0.6.1.tar.gz
Algorithm Hash digest
SHA256 a2d9aa0df9026c9b75eb44d94bb2fef7ff157df325cb2c19ed460fc04681259d
MD5 7e04e3090ebf42d6dc6e4b552b65a925
BLAKE2b-256 d5c401875121cdb70cf08aa5d445285476688f087e396f4eedc201bb209b27da

See more details on using hashes here.

Provenance

The following attestation bundles were made for evnex-0.6.1.tar.gz:

Publisher: ci.yml on hardbyte/python-evnex

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file evnex-0.6.1-py3-none-any.whl.

File metadata

  • Download URL: evnex-0.6.1-py3-none-any.whl
  • Upload date:
  • Size: 20.9 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for evnex-0.6.1-py3-none-any.whl
Algorithm Hash digest
SHA256 d76d8c0255fa023496c53779159ee139ba658b59a66a714623c8e5c6f3863ea9
MD5 64124e87df0d8495e9b08d6a7daf22d0
BLAKE2b-256 c1b1eafaae081ccca24e6ce459fb7baca8b62cbe1c2f636c9493f5307b1c2b25

See more details on using hashes here.

Provenance

The following attestation bundles were made for evnex-0.6.1-py3-none-any.whl:

Publisher: ci.yml on hardbyte/python-evnex

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Release history Release notifications | RSS feed

0.7.0

2 files

This release

0.6.1 This release

2 files

0.6.0

2 files

0.5.0

2 files

0.4.9

2 files

0.4.8

2 files

0.4.7

2 files

0.4.6

2 files

0.4.5

2 files

0.4.4

2 files

0.4.3

2 files

0.4.1

2 files

0.4.0

2 files

0.3.9

2 files

0.3.8

2 files

0.3.6

2 files

0.3.5

2 files

0.3.4

2 files

0.3.3

2 files

0.3.2

2 files

0.3.1

2 files

0.3.0

2 files

0.2.15

2 files

0.2.14

2 files

0.2.13

2 files

0.2.12

2 files

0.2.11

2 files

0.2.10

2 files

0.2.9

2 files

0.2.8

2 files

0.2.7

2 files

0.2.6

2 files

0.2.5

2 files

0.2.4

2 files

0.2.3

2 files

0.2.2

2 files

0.2.1

2 files

0.2.0

2 files

0.1.1

2 files

0.1.0

2 files

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page