Metadata-Version: 2.4
Name: sapnmeterdata
Version: 0.3.2
Summary: Retrieve interval meter data from SA Power Networks
Author-email: Brady Fulham <bfulham@bradyfulham.com>
License-Expression: MIT
Project-URL: Homepage, https://github.com/bfulham/sapnmeterdata
Project-URL: Issues, https://github.com/bfulham/sapnmeterdata/issues
Classifier: Development Status :: 3 - Alpha
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Programming Language :: Python :: 3.14
Requires-Python: >=3.12
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: beautifulsoup4<5,>=4.15.0
Requires-Dist: nemreader<1,>=0.9.2
Requires-Dist: pandas<4,>=2.3.3
Requires-Dist: requests<3,>=2.34.2
Provides-Extra: dev
Requires-Dist: build<2,>=1.5.0; extra == "dev"
Requires-Dist: ruff<1,>=0.16.0; extra == "dev"
Requires-Dist: twine<7,>=6.2.0; extra == "dev"
Dynamic: license-file

# sapnmeterdata

`sapnmeterdata` is an unofficial Python client for downloading NEM12 interval
meter data from SA Power Networks' **Your Meter Data** customer portal.

It signs in with an existing SAPN portal account, discovers the NMIs assigned
to that account, requests a detailed NEM12 report, and returns the readings as
a Pandas DataFrame.

> This project is not affiliated with or supported by SA Power Networks. It
> relies on the portal's web interface and may require updates when that
> interface changes.

## Installation

```console
python -m pip install sapnmeterdata
```

Version 0.3.2 requires Python 3.12 or newer. It uses the pandas-based
`nemreader` 0.9 parser so it remains compatible with older processors used by
some Home Assistant hosts. The public result is a Pandas DataFrame.

## SAPN account

Register for the free **Your Meter Data** service before using this package:

<https://www.sapowernetworks.com.au/your-power/manage-your-power-use/your-meter-data/>

Only access NMIs for which you are the customer or an authorised
representative. Do not commit SAPN credentials to source control.

## Example

```python
import os
from datetime import datetime, timedelta

from sapnmeterdata import login


sapn = login(
    os.environ["SAPN_EMAIL"],
    os.environ["SAPN_PASSWORD"],
)

print(sapn.getNMIs())

end = datetime.now()
start = end - timedelta(days=14)
data = sapn.getAllData(start, end)

print(data)
```

Retrieve one NMI:

```python
from sapnmeterdata import meter


single_meter = meter("YOUR_NMI", sapn)
data = single_meter.getdata(start, end)
```

Retrieve selected NMIs:

```python
from sapnmeterdata import getall


data = getall(
    ["FIRST_NMI", "SECOND_NMI"],
    start,
    end,
    sapn,
)
```

If one NMI has no downloadable data for the requested period, `getall()` emits
a `MeterDataWarning`, skips only that NMI, and continues retrieving the others.
The returned DataFrame records those NMIs in
`data.attrs["skipped_nmis"]`. Calling `meter.getdata()` directly for the same
NMI raises `NoDataError`.

## Returned data

Meter readings are returned as a Pandas DataFrame:

- the index contains the interval start timestamp;
- columns use a two-level `meter` / `channel` MultiIndex;
- multiple NMIs are outer-joined by timestamp.

Common NEM12 channels include `E1` for general consumption, `E2` for
controlled load, and `B1` for solar export. The exact channels depend on the
meter configuration.

SAPN data is historical interval data, not a real-time power feed.

## Errors

The public exception types are:

- `LoginError` — the login form changed, credentials were rejected, or SAPN
  requested another authentication step;
- `AuthError` — the authenticated session expired or Salesforce remoting
  metadata could not be found;
- `NoDataError` — SAPN returned no downloadable NEM12 payload for a particular
  NMI and date range;
- `FetchError` — another portal request, RPC response, or NEM12 parse failed.

`MeterDataWarning` is emitted when `getall()` catches `NoDataError` for one NMI
and continues with the rest.

## Development

Create a Python 3.12+ virtual environment and install the package with its
current development tools:

```console
python -m pip install ".[dev]"
```

Run the unit tests:

```console
python -m unittest discover -s tests -v
```

Build the source distribution and wheel:

```console
python -m build
```

See [RELEASING.md](RELEASING.md) for the GitHub Actions and PyPI Trusted
Publishing setup.
