tronikos / opower

A Python library for getting historical and forecasted usage/cost from utilities that use opower.com such as PG&E
Apache License 2.0
53 stars 49 forks source link

Request: Support opower guest accounts for coautilities #81

Open trv opened 1 month ago

trv commented 1 month ago

For coautilities (not sure about others), you can create a guest account at https://dss-coa.opower.com/dss/account/manage-web-account under "Connected accounts > + Add guest user". This allows you to set the access level to effectively read-only ("Usage & Financial Info"). It'd be nice if we could take advantage of this access control to apply the principle of least privilege.

The main login credentials work fine with demo.py (release version 0.4.6).

I can use this guest login via the browser to access usage data, but demo.py fails with:

DEBUG:/config/custom_components/opower-0.4.6/src/opower/opower.py:Fetching: https://dss-coa.opower.com/webcenter/edge/apis/dss-invite-v1/cws/v1/utilities/connectedaccounts?pageOffset=0&pageLimit=100
Level 9:/config/custom_components/opower-0.4.6/src/opower/opower.py:Fetched: {
  "accounts": [],
  "totalRecords": 0
}
Traceback (most recent call last):
  File "/config/custom_components/opower-0.4.6/src/demo.py", line 172, in <module>
    asyncio.run(_main())
  File "/usr/local/lib/python3.12/asyncio/runners.py", line 194, in run
    return runner.run(main)
           ^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.12/asyncio/runners.py", line 118, in run
    return self._loop.run_until_complete(task)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.12/asyncio/base_events.py", line 685, in run_until_complete
    return future.result()
           ^^^^^^^^^^^^^^^
  File "/config/custom_components/opower-0.4.6/src/demo.py", line 91, in _main
    for forecast in await opower.async_get_forecast():
                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/config/custom_components/opower-0.4.6/src/opower/opower.py", line 247, in async_get_forecast
    for customer in await self._async_get_customers():
                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/config/custom_components/opower-0.4.6/src/opower/opower.py", line 327, in _async_get_customers
    await self._async_get_user_accounts()
  File "/config/custom_components/opower-0.4.6/src/opower/opower.py", line 374, in _async_get_user_accounts
    assert self.user_accounts
AssertionError

Tracing the network calls when using the guest account from a browser session, I see

Presumably guest logins require a less-direct method to dig up the missing accounts info?