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

New Provider: SMUD #70

Closed BrianHenryIE closed 4 months ago

BrianHenryIE commented 4 months ago

It works, and is unit tested.

Reviewed at https://github.com/andylittle/opower-smud/pull/1 by @kitchung, @Swanky-Bubbles, @nebhead, @v-yarotsky, @Borillion.

DEBUG:/Users/brianhenry/Sites/opower-smud/src/opower/utilities/smud.py:Fetching SMUD login page: https://myaccount.smud.org/
DEBUG:/Users/brianhenry/Sites/opower-smud/src/opower/utilities/smud.py:Set new cookies: `NSC_wt_abc_nzbddpvou-abcd-psh-tx`, `ABCDM_BTa`, `language`, `ASP.NET_SessionId`, `__RequestVerificationToken`
DEBUG:/Users/brianhenry/Sites/opower-smud/src/opower/utilities/smud.py:SMUD self verify token: oS1wABCd1EzD8FJbpJ1osABCJF9PPn0iqwYvLtjXY6KI1RSktMeL4s7aPKaovSo1ykOorXrfOc8Yd_4RbaHpEdTGPhGaaeN_RmduIo4dWhs1
DEBUG:/Users/brianhenry/Sites/opower-smud/src/opower/utilities/smud.py:Performing SMUD login to: https://myaccount.smud.org/
DEBUG:/Users/brianhenry/Sites/opower-smud/src/opower/utilities/smud.py:Performed 1 redirects
DEBUG:/Users/brianhenry/Sites/opower-smud/src/opower/utilities/smud.py:-> https://myaccount.smud.org/manage/residential
DEBUG:/Users/brianhenry/Sites/opower-smud/src/opower/utilities/smud.py:Set new cookies: `.ASPXAUTH`, `ADRUM_BT1`
DEBUG:/Users/brianhenry/Sites/opower-smud/src/opower/utilities/smud.py:Opening SMUD energy usage page: https://myaccount.smud.org/manage/opowerresidential/energyusage
DEBUG:/Users/brianhenry/Sites/opower-smud/src/opower/utilities/smud.py:Performed 1 redirects
DEBUG:/Users/brianhenry/Sites/opower-smud/src/opower/utilities/smud.py:-> https://smud.okta.com/login/sessionCookieRedirect?token=20111owABCDEv7eqyW5BtpokhEzocxMjinJNTsABCjXk6lTuSlZ6UdT&redirectUrl=https://smud.okta.com/app/sacramentomunicipalutilitydistrict_opower_1/exk2iie3ABCDEicF0x7/sso/saml?RelayState=https://smud.opower.com/ei/app/myEnergyUse
DEBUG:/Users/brianhenry/Sites/opower-smud/src/opower/utilities/smud.py:Set new cookies: `sid`, `proximity_b5b7cabc8e6dafc3300abcd63b415d49`, `JSESSIONID`, `DT`, `t`
DEBUG:/Users/brianhenry/Sites/opower-smud/src/opower/utilities/smud.py:Fetching second OKTA login page: https://smud.okta.com/app/sacramentomunicipalutilitydistrict_opower_1/exk2iie3ABCDlW7iAF0x7/sso/saml?RelayState=https://smud.opower.com/ei/app/myEnergyUse
DEBUG:/Users/brianhenry/Sites/opower-smud/src/opower/utilities/smud.py:Parsed SAMLResponse: PD94b...lPg== (9932 characters)
DEBUG:/Users/brianhenry/Sites/opower-smud/src/opower/utilities/smud.py:POSTing opower sso page with SAMLResponse: https://sso.opower.com/sp/ACS.saml2
DEBUG:/Users/brianhenry/Sites/opower-smud/src/opower/utilities/smud.py:Performed 2 redirects
DEBUG:/Users/brianhenry/Sites/opower-smud/src/opower/utilities/smud.py:-> https://smud.opower.com/ei/app/myEnergyUse?opentoken=TABCAQIg-PcKvJVUcABCDkwdOKPaQGzOBD-4eV1ZScEXKa2ycEBstXRAADA20wMXZVZ3AT-Wjs4MENa67iu2hb7ZbxMCVEqgZ12Djs7bJ0UBWEu0L4ExYkRV2FaFmKGHy0c0yABCi9TAEP_r7UnsVrIOXqPgcH6B01PBAzLwYQEHTl8nueVRcPKawyV_hny0VIMWiKWLoJ20T-miJaijdewLh7Url05WpECp7ABC1tdQF7J44wbL-5f_gn7tINUhM_G937Rf6ydkiXPyfXs9bVLf8Q2cJDK66VLy3oEK_8UlkY3ypp7LSG7mWg
DEBUG:/Users/brianhenry/Sites/opower-smud/src/opower/utilities/smud.py:-> https://smud.opower.com/ei/app/myEnergyUse
DEBUG:/Users/brianhenry/Sites/opower-smud/src/opower/utilities/smud.py:Set new cookies: `JSESSIONID-samesite`, `JSESSIONID`
DEBUG:/Users/brianhenry/Sites/opower-smud/src/opower/opower.py:Fetching: https://smud.opower.com/ei/edge/apis/multi-account-v1/cws/smud/customers?offset=0&batchSize=100&addressFilter=
DEBUG:/Users/brianhenry/Sites/opower-smud/src/opower/opower.py:Fetching: https://smud.opower.com/ei/edge/apis/bill-forecast-cws-v1/cws/smud/customers/123123d1-76c1-11ed-a3ac-01231708442c/combined-forecast

Current bill forecast: Forecast(account=Account(customer=Customer(uuid='123123d1-76c1-11ed-a3ac-02001708442c'), uuid='12346e54-76c1-11ed-a3ac-02001708442c', utility_account_id='1233317578', meter_type=<MeterType.ELEC: 'ELEC'>, read_resolution=None), start_date=datetime.date(2024, 2, 6), end_date=datetime.date(2024, 3, 7), current_date=datetime.date(2024, 2, 24), unit_of_measure=<UnitOfMeasure.KWH: 'KWH'>, usage_to_date=179.0, cost_to_date=22.0, forecasted_usage=348.0, forecasted_cost=43.0, typical_usage=294.0, typical_cost=34.0)

Getting historical data: account= Account(customer=Customer(uuid='123123d1-76c1-11ed-a3ac-02001708442c'), uuid='12346e54-76c1-11ed-a3ac-02001708442c', utility_account_id='1233317578', meter_type=<MeterType.ELEC: 'ELEC'>, read_resolution=<ReadResolution.HOUR: 'HOUR'>) aggregate_type= day start_date= 2024-02-17 09:25:35.556275 end_date= 2024-02-24 09:25:35.556293
DEBUG:/Users/brianhenry/Sites/opower-smud/src/opower/opower.py:Fetching: https://smud.opower.com/ei/edge/apis/DataBrowser-v1/cws/cost/utilityAccount/12346e54-76c1-11ed-a3ac-02001708442c?aggregateType=day&startDate=2024-02-17T00%3A00%3A00-08%3A00&endDate=2024-02-25T00%3A00%3A00-08%3A00
start_time  end_time    consumption provided_cost   start_minus_prev_end    end_minus_prev_end
2024-02-17 00:00:00-08:00   2024-02-18 00:00:00-08:00   10.6296 1.22346696  None    None
2024-02-18 00:00:00-08:00   2024-02-19 00:00:00-08:00   7.4316  0.85537716  0:00:00 1 day, 0:00:00
2024-02-19 00:00:00-08:00   2024-02-20 00:00:00-08:00   8.0004  0.92084604  0:00:00 1 day, 0:00:00
2024-02-20 00:00:00-08:00   2024-02-21 00:00:00-08:00   11.1372 1.33741644  0:00:00 1 day, 0:00:00
2024-02-21 00:00:00-08:00   2024-02-22 00:00:00-08:00   8.0208  0.95938524  0:00:00 1 day, 0:00:00
2024-02-22 00:00:00-08:00   2024-02-23 00:00:00-08:00   7.7832  0.96522588  0:00:00 1 day, 0:00:00

There is an error during linting:

$ mypy --install-types .

src/opower/utilities/smud.py: error: Source file found twice under different module names: "opower.utilities.smud" and "src.opower.utilities.smud"
Found 1 error in 1 file (errors prevented further checking)

And you mentioned async_auth_saml() – I tried it briefly and didn't get it to work. The reason I hadn't used it earlier was that I had forked a fork which was out of date so hadn't seen it.

I added a check to confirm any existing cookie is valid as discussed in #66.

Closes #54

tronikos commented 4 months ago

Can you fix the mypy warnings?

BrianHenryIE commented 4 months ago

I fixed them all except:

 error: X | Y syntax for unions requires Python 3.10 

AIUI, Home Assistant doesn't support < 3.11, so maybe it would be easier to just increase the version used by this library? LMK.

tronikos commented 4 months ago

I released v0.4.0. Please bump the version on the home assistant side, update documentation to mention support for this utility and add a virtual integration with icon.

fgonza2 commented 4 months ago

will this be on home assistant 2024.3 ?

tronikos commented 4 months ago

No. According to https://github.com/home-assistant/core/blob/dev/homeassistant/components/opower/manifest.json the version isn't bumped yet. Someone needs to do it and, in a separate PR, create a virtual integration.

teliseo commented 3 months ago

This integration was working for a while for me, and then stopped working around a week ago. I tried deleting and re-adding the entry, but now it fails to add. Nothing has changed with my SMUD account, and I can log in normally using a browser.

2024-03-28 14:44:39.555 ERROR (MainThread) [homeassistant.components.opower.coordinator] Unexpected error fetching Opower data: 500, message='Internal Server Error', url=URL('https://myaccount.smud.org/')
Traceback (most recent call last):
  File "/opt/hass/lib64/python3.12/site-packages/opower/opower.py", line 194, in async_login
    self.access_token = await self.utility.async_login(
                        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/opt/hass/lib64/python3.12/site-packages/opower/utilities/smud.py", line 130, in async_login
    login_response = await session.post(
                     ^^^^^^^^^^^^^^^^^^^
  File "/opt/hass/lib64/python3.12/site-packages/aiohttp/client.py", line 693, in _request
    resp.raise_for_status()
  File "/opt/hass/lib64/python3.12/site-packages/aiohttp/client_reqrep.py", line 1060, in raise_for_status
    raise ClientResponseError(
aiohttp.client_exceptions.ClientResponseError: 500, message='Internal Server Error', url=URL('https://myaccount.smud.org/')

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/opt/hass/lib64/python3.12/site-packages/homeassistant/helpers/update_coordinator.py", line 318, in _async_refresh
    self.data = await self._async_update_data()
                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/opt/hass/lib64/python3.12/site-packages/homeassistant/components/opower/coordinator.py", line 80, in _async_update_data
    await self.api.async_login()
  File "/opt/hass/lib64/python3.12/site-packages/opower/opower.py", line 202, in async_login
    raise CannotConnect(err)
opower.exceptions.CannotConnect: 500, message='Internal Server Error', url=URL('https://myaccount.smud.org/')