# aionisource

Async Python client for [NiSource](https://www.nisource.com/) utility customer portals (Columbia Gas, NIPSCO).

This is the backend library that powers the **[Home Assistant](https://www.home-assistant.io/) NiSource integration**. It handles all communication with the NiSource customer portals behind the scenes.

## Supported utilities

| Utility | Portal |
|---|---|
| Columbia Gas of Ohio | myaccount.columbiagasohio.com |
| Columbia Gas of Virginia | myaccount.columbiagasva.com |
| Columbia Gas of Maryland | myaccount.columbiagasmd.com |
| Columbia Gas of Kentucky | myaccount.columbiagasky.com |
| Columbia Gas of Pennsylvania | myaccount.columbiagaspa.com |
| NIPSCO | myaccount.nipsco.com |

All six utilities share the same web portal platform (SEW Digital Self-Service), so this single library works with all of them.

## For Home Assistant users

If you're here because you want to connect your Columbia Gas or NIPSCO account to Home Assistant, you don't need to install this library yourself. Home Assistant installs it automatically when you add the integration.

### What you'll need

Just your **email** and **password** for your utility's customer portal - the same credentials you use to log in at your utility's "My Account" website.

### Setting up in Home Assistant

Everything is done through the Home Assistant GUI. No code, no config files, no YAML.

1. Open Home Assistant
2. Go to **Settings** > **Devices & services**
3. Click **+ Add integration** (bottom right)
4. Search for your utility name (e.g., **Columbia Gas of Ohio** or **NIPSCO**)
5. Select your utility from the dropdown
6. Enter your email and password
7. Click **Submit**

That's it. Your gas usage data shows up as sensors automatically.

### About your password

Your password **is stored** by Home Assistant because it's needed to log in each time data is updated. This is the same approach used by the Opower integration for electric utilities. Here's why:

- NiSource portals use cookie-based sessions that expire quickly
- There's no OAuth or API token system available
- Each data refresh requires a fresh login with your credentials
- Your password is stored encrypted in Home Assistant's configuration

### What sensors do you get?

Once set up, you get these sensors:

| Sensor | What it shows |
|---|---|
| **Current bill gas usage** | Gas consumed this billing period (in CCF) |
| **Current bill amount** | Dollar amount of your current bill |
| **Gas cost per day** | Average daily cost this billing period |
| **Gas meter reading** | Cumulative meter reading (CCF) |
| **Billing period average temperature** | Average outdoor temp during billing period (°F) |
| **Billing period days** | Number of days in the current billing period |
| **Last meter read date** | When your meter was last read |
| **Meter read method** | How the meter was read (e.g., "Actual Read") |

Data updates every 12 hours. Usage data is also inserted into the **Energy dashboard** as historical statistics, so you can track your gas consumption and costs over time.

---

## For developers

If you want to use this library in your own Python project (outside of Home Assistant), here's how.

### Installation

```bash
pip install aionisource
```

### Quick start

```python
import asyncio
import aiohttp
from aionisource import NiSourceClient, NiSourceUtility

async def main():
    # Create a session with unsafe cookie jar (needed for cross-redirect cookies)
    jar = aiohttp.CookieJar(unsafe=True)
    async with aiohttp.ClientSession(cookie_jar=jar) as session:
        # Create a client for your utility
        client = NiSourceClient(
            session,
            utility=NiSourceUtility.COLUMBIA_GAS_OHIO,
            email="your_email@example.com",
            password="your_password",
        )

        # Log in to the portal
        account = await client.async_login()
        print(f"Logged in as: {account.display_name}")
        print(f"Account ID: {account.account_id}")

        # Get usage history (returns ~24 months of monthly data)
        reads = await client.async_get_usage()
        for read in reads[:3]:
            print(f"  {read.read_date.date()}: {read.units_used} CCF, ${read.bill_amount}")

        # Get billing history
        bills = await client.async_get_bills()
        for bill in bills[:3]:
            print(f"  {bill.date.date()}: {bill.description} - ${bill.amount}")

asyncio.run(main())
```

### Available methods

| Method | What it does |
|---|---|
| `client.async_login()` | Log in and return account info |
| `client.async_check_status()` | Check if the session is still active |
| `client.async_get_usage()` | Get monthly usage history (~24 records) |
| `client.async_get_bills()` | Get billing/payment history |

### Usage data fields

Every usage record (`UsageRead`) includes:

| Field | Type | Example |
|---|---|---|
| `service_account_id` | str | "12345678" |
| `meter_id` | str | "9876543210" |
| `read_date` | datetime | 2025-02-04 |
| `read_method` | str | "Actual Read" |
| `reading` | float | 1000.0 (cumulative CCF) |
| `units_used` | float | 85.0 (CCF this period) |
| `bill_amount` | float | 100.00 ($) |
| `cost_per_day` | float | 3.45 ($/day) |
| `average_temp` | float | 30.5 (°F) |
| `number_of_billing_days` | int | 29 |

### How it works

Since NiSource utilities don't have a public API, this library works by:

1. **Logging in** via the same form-based login as the website
2. **Scraping** the usage and billing pages
3. **Extracting** embedded JSON data from `window.VueTables.*` JavaScript objects

This is the same technique used by other energy integrations (like Opower) that scrape utility portals without public APIs.

### Important: Cookie jar

You **must** create the `aiohttp.ClientSession` with `CookieJar(unsafe=True)`. This is required because the portal uses cross-domain redirects during login, and the default cookie jar will reject cookies from different domains.

## Links

- Issues: https://github.com/scriptsandthings/aionisource/issues
- NiSource: https://www.nisource.com/

## License

MIT
