Skip to content

Commit

Permalink
feat #48: add meter details (#51)
Browse files Browse the repository at this point in the history
  • Loading branch information
jrester authored Sep 16, 2023
1 parent 525281b commit b6a5f10
Show file tree
Hide file tree
Showing 36 changed files with 1,202 additions and 540 deletions.
1 change: 1 addition & 0 deletions .envrc
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
layout python
2 changes: 1 addition & 1 deletion .github/workflows/python-publish.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ on:
- created
- published
- released

jobs:
deploy:

Expand Down
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -123,4 +123,5 @@ dmypy.json
.pyre/

.js
.vscode
.vscode
.direnv
29 changes: 29 additions & 0 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
repos:
- repo: https://github.com/astral-sh/ruff-pre-commit
# Ruff version.
rev: v0.0.285
hooks:
- id: ruff
args: [--fix, --exit-non-zero-on-fix]
- repo: https://github.com/pre-commit/mirrors-mypy
rev: v1.5.1
hooks:
- id: mypy
additional_dependencies: ["types-requests"]
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v3.4.0
hooks:
- id: trailing-whitespace
- id: end-of-file-fixer
- id: pretty-format-json
args: [--autofix]
- repo: https://github.com/pycqa/isort
rev: 5.12.0
hooks:
- id: isort
args: [--settings-path=pyproject.toml]
- repo: https://github.com/psf/black
rev: 23.7.0
hooks:
- id: black
args: [--config=pyproject.toml]
13 changes: 11 additions & 2 deletions CHANGELOG
Original file line number Diff line number Diff line change
@@ -1,5 +1,14 @@
# Changelog

## [0.4.0]

- fix logout (https://github.com/jrester/tesla_powerwall/issues/50)
- add meter details for site and solar (https://github.com/jrester/tesla_powerwall/issues/48)
- rework response handling to now parse the responses directly instead of relying on lazy evaluation
- extend pre-commit hooks
- move to pyproject.toml and remove old setup.py


## [0.3.19]

- add ability to take powerwall on/off grid. Thanks to @daniel-simpson (https://github.com/jrester/tesla_powerwall/pull/42)
Expand Down Expand Up @@ -28,7 +37,7 @@

## [0.3.14]

- revert changes from 0.3.11:
- revert changes from 0.3.11:
- meters can now be accessed using the old, direct method (e.g. `meters.solar.instant_power`)
- if a meter is not available a `MeterNotAvailableError` will be thrown
- move from `distutils.version` to `packaging.version`
Expand All @@ -45,4 +54,4 @@ Implement `system_status` endpoint (https://github.com/jrester/tesla_powerwall/i

## [0.3.11]

- meters of `MetersAggregates` can now only be accessed via `get_meter` (https://github.com/home-assistant/core/issues/56660)
- meters of `MetersAggregates` can now only be accessed via `get_meter` (https://github.com/home-assistant/core/issues/56660)
4 changes: 2 additions & 2 deletions LICENSE
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
MIT License

Copyright (c) 2022 Jrester
Copyright (c) 2023 Jrester

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
Expand All @@ -18,4 +18,4 @@ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
SOFTWARE.
108 changes: 72 additions & 36 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,16 @@
![PyPI - Downloads](https://img.shields.io/pypi/dm/tesla_powerwall?color=blue&style=for-the-badge)
![PyPI](https://img.shields.io/pypi/v/tesla_powerwall?style=for-the-badge)

Python Tesla Powerwall API for consuming a local endpoint. The API is by no means complete and mainly features methods which are considered to be of common use. If you feel like methods should be included you are welcome to open an Issue or create a Pull Request.

> Note: This is not an official API provided by Tesla and not affilated in anyways with Tesla.
Powerwall Software versions from 1.47.0 to 1.50.1 as well as 20.40 to 22.9.2 are tested, but others will probably work too. If you encounter an error regarding a change in the API of the Powerwall because your Powerwall has a different version than listed here please open an Issue to report this change so it can be fixed.
Python Tesla Powerwall API for consuming a local endpoint.
> Note: This is not an official API provided by Tesla and this project is not affilated with Tesla in any way.
Powerwall Software versions from 1.47.0 to 1.50.1 as well as 20.40 to 22.9.2 are tested, but others will probably work too.

# Table of Contents <!-- omit in TOC -->

- [Installation](#installation)
- [Limitations](#limitations)
- [Adjusting Backup Reserve Percentage](#adjusting-backup-reserve-percentage)
- [Usage](#usage)
- [Setup](#setup)
- [Authentication](#authentication)
Expand All @@ -28,13 +28,15 @@ Powerwall Software versions from 1.47.0 to 1.50.1 as well as 20.40 to 22.9.2 are
- [Aggregates](#aggregates)
- [Current power supply/draw](#current-power-supplydraw)
- [Energy exported/imported](#energy-exportedimported)
- [Details](#details)
- [Device Type](#device-type)
- [Grid Status](#grid-status)
- [Operation mode](#operation-mode)
- [Powerwalls Serial Numbers](#powerwalls-serial-numbers)
- [Gateway DIN](#gateway-din)
- [VIN](#vin)
- [Off-grid status](#off-grid-status-set-island-mode)

## Installation

Install the library via pip:
Expand All @@ -43,6 +45,13 @@ Install the library via pip:
$ pip install tesla_powerwall
```

## Limitations

### Adjusting Backup Reserve Percentage

Currently it is not possible to control the Backup Percentage, because you need to be logged in as installer, which requires physical switch toggle. There is an ongoing discussion about a possible solution [here](https://github.com/vloschiavo/powerwall2/issues/55).
However, if you believe there exists a solution, feel free to open an issue detailing the solution.

## Usage

For a basic Overview of the functionality of this library you can take a look at `examples/example.py`:
Expand All @@ -67,7 +76,7 @@ powerwall = Powerwall(
endpoint="<ip of your powerwall>",
# Configure timeout; default is 10
timeout=10,
# Provide a requests.Session or None to have one created
# Provide a requests.Session or None. If None is provided, a Session will be created.
http_session=None,
# Whether to verify the SSL certificate or not
verify_ssl=False,
Expand All @@ -82,7 +91,7 @@ powerwall = Powerwall(
### Authentication

Since version 20.49.0 authentication is required for all methods. For that reason you must call `login` before making a request to the API.
When you perform a request without being loggedin a `AccessDeniedError` will be thrown.
When you perform a request without being authenticated, an `AccessDeniedError` will be thrown.

To login you can either use `login` or `login_as`. `login` logs you in as `User.CUSTOMER` whereas with `login_as` you can choose a different user:

Expand Down Expand Up @@ -110,6 +119,8 @@ powerwall.is_authenticated()

# Logout
powerwall.logout()
powerwall.is_authenticated()
#=> False
```

### General
Expand All @@ -132,29 +143,6 @@ api.get_system_status_soe()

The `Powerwall` objet provides a wrapper around the API and exposes common methods.

#### Errors

As the powerwall REST API varies widley between version and country it may happen that an attribute may not be included in your response. If that is the case a `MissingAttributeError` will be thrown indicating what attribute wasn't available.

#### Response

Responses are usally wrapped inside a `Response` object to provide convenience methods. An Example is the `Meter` class which is a sublass of `Response`. Each `Response` object includes the `response` member which consists of the plain json response.

```python
from helpers import assert_attribute

status = powerwall.get_status()
#=> <PowerwallStatus ...>

status.version
# is the same as
assert_attribute(status.response, "version")
# or
status.assert_attribute("version")
```

For retriving the version you could also alternativly use `powerwall.get_version`.

### Battery level

Get charge in percent:
Expand Down Expand Up @@ -221,9 +209,9 @@ status.device_type
### Sitemaster

```python
sm = powerwall.sitemaster
sm = powerwall.sitemaster
#=> <SiteMaster ...>
sm.status
sm.status
#=> StatusUp
sm.running
#=> true
Expand Down Expand Up @@ -264,10 +252,10 @@ meters.get_meter(MeterType.SOLAR)

# access meter, but may raise MeterNotAvailableError when the meter is not available at your powerwall (e.g. no solar panels installed)
meters.solar
#=> <Meter ...>
#=> <MeterResponse ...>

# get all available meters at the current powerwall
meters.meters
meters.meters.keys()
#=> [<MeterType.SITE: 'site'>, <MeterType.BATTERY: 'battery'>, <MeterType.LOAD: 'load'>, <MeterType.SOLAR: 'solar'>]
```

Expand Down Expand Up @@ -312,6 +300,30 @@ meters.battery.get_energy_imported()
#=> 7576.6 (kWh)
```

### Details

You can receive more detailed information about the meters `site` and `solar`:

```python
meter_details = powerwall.get_meter_site() # or get_meter_solar() for the solar meter
#=> <MeterDetailsResponse ...>
readings = meter_details.readings
#=> <MeterDetailsReadings ...>
readings.real_power_a # same for real_power_b and real_power_c
#=> 619.13532458
readings.i_a_current # same for i_b_current and i_c_current
#=> 3.02
readings.v_l1n # smae for v_l2n and v_l3n
#=> 235.82
readings.instant_power
#=> -18.000023458
readings.is_sending()
```

As `MeterDetailsReadings` inherits from `MeterResponse` (which is used in `MetersAggratesResponse`) it exposes the same data and methods.

> For the meters battery and grid no additional details are provided, therefore no methods exist for those meters
### Device Type

```python
Expand All @@ -321,7 +333,7 @@ powerwall.get_device_type()

### Grid Status

Get current grid status.
Get current grid status.

```python
powerwall.get_grid_status()
Expand Down Expand Up @@ -361,7 +373,7 @@ vin = powerwall.get_vin()

### Off-grid status (Set Island mode)

Take your powerwall on- and off-grid similar to the "Take off-grid" button in the Tesla app.
Take your powerwall on- and off-grid similar to the "Take off-grid" button in the Tesla app.

#### Set powerwall to off-grid (Islanded)

Expand All @@ -374,3 +386,27 @@ powerwall.set_island_mode(IslandMode.OFFGRID)
```python
powerwall.set_island_mode(IslandMode.ONGRID)
```

# Development

## Building

```sh
$ python -m build
```

## Testing

### Unit-Tests

To run unit tests use tox:

```sh
$ tox -e unit
```

### Integration-Tests

```sh
$ tox -e integration
```
12 changes: 7 additions & 5 deletions examples/example.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import os
from tesla_powerwall import Powerwall, Meter

from tesla_powerwall import MeterResponse, Powerwall


def getenv(var):
Expand All @@ -9,7 +10,7 @@ def getenv(var):
return val


def print_meter_row(meter_data: Meter):
def print_meter_row(meter_data: MeterResponse):
print(
"{:>8} {:>8} {:>17} {:>17} {!r:>8} {!r:>17} {!r:>17}".format(
meter_data.meter.value,
Expand Down Expand Up @@ -42,7 +43,7 @@ def print_meter_row(meter_data: Meter):
("Grid Status", power_wall.get_grid_status().value),
("Backup Reserve (%)", round(power_wall.get_backup_reserve_percentage())),
("Device Type", power_wall.get_device_type().value),
("Software Version", power_wall.get_version())
("Software Version", power_wall.get_version()),
]


Expand All @@ -62,5 +63,6 @@ def print_meter_row(meter_data: Meter):
"Sending to",
)
)
for meter in meters_agg.meters:
print_meter_row(meters_agg.get_meter(meter))

for meter in meters_agg.meters.values():
print_meter_row(meter)
47 changes: 0 additions & 47 deletions examples/influxDB.py

This file was deleted.

Loading

0 comments on commit b6a5f10

Please sign in to comment.