Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix for crash when tariff code cant be found & consumption key is not found in tariff #7

Open
wants to merge 2 commits into
base: main
Choose a base branch
from

Conversation

Altirix
Copy link

@Altirix Altirix commented Apr 17, 2024

The first edge case only occurs if you are on a tariff that cannot be found.

the tariff we were on previously was E-FLAT2R-VAR-22-11-01-H which is never found by _find_links resulting in this crash

Traceback (most recent call last):
  File "C:\Users\Michael\Documents\GitHub\octograph\app\octopus_to_influxdb.py", line 298, in <module>
    cmd()
  File "C:\Users\Michael\AppData\Local\Programs\Python\Python312\Lib\site-packages\click\core.py", line 1157, in __call__
    return self.main(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\Michael\AppData\Local\Programs\Python\Python312\Lib\site-packages\click\core.py", line 1078, in main
    rv = self.invoke(ctx)
         ^^^^^^^^^^^^^^^^
  File "C:\Users\Michael\AppData\Local\Programs\Python\Python312\Lib\site-packages\click\core.py", line 1434, in invoke
    return ctx.invoke(self.callback, **ctx.params)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\Michael\AppData\Local\Programs\Python\Python312\Lib\site-packages\click\core.py", line 783, in invoke
    return __callback(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\Michael\Documents\GitHub\octograph\app\octopus_to_influxdb.py", line 294, in cmd
    app.collect(from_date, to_date)
  File "C:\Users\Michael\Documents\GitHub\octograph\app\octopus_to_influxdb.py", line 100, in collect
    self._process_property(p, collect_from, collect_to, tags)
  File "C:\Users\Michael\Documents\GitHub\octograph\app\octopus_to_influxdb.py", line 111, in _process_property
    self._process_emp(emp, collect_from, collect_to, tags)
  File "C:\Users\Michael\Documents\GitHub\octograph\app\octopus_to_influxdb.py", line 129, in _process_emp
    pricing_dict = self._get_pricing(emp['agreements'], collect_from, collect_to)
                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\Michael\Documents\GitHub\octograph\app\octopus_to_influxdb.py", line 240, in _get_pricing
    agreement_rates = self._octopus_api.retrieve_tariff_pricing(a['tariff_code'], DateUtils.iso8601(f), DateUtils.iso8601(t))
                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\Michael\Documents\GitHub\octograph\app\octopus_api_client.py", line 95, in retrieve_tariff_pricing
    for link in self._find_links(product, tariff_code):
TypeError: 'NoneType' object is not iterable

In this case, I believe we should just skip over the iteration when this occurs. ideally, there would be a way to get the correct tariff data but i dont see any way to do that.

The second edge case occurs when you have consumption data from before the start of the current tariff. the time won't be part of either standard_unit_rates or standing_charges so both should be checked before accessing.

I wasn't sure if it would be preferred to do this as an if key in dict or try: except keyerror: within this PR I've done it as the former, but happy to change to the latter if preferred.

Traceback (most recent call last):
  File "C:\Users\Michael\Documents\GitHub\octograph\app\octopus_to_influxdb.py", line 300, in <module>
    cmd()
  File "C:\Users\Michael\AppData\Local\Programs\Python\Python312\Lib\site-packages\click\core.py", line 1157, in __call__
    return self.main(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\Michael\AppData\Local\Programs\Python\Python312\Lib\site-packages\click\core.py", line 1078, in main
    rv = self.invoke(ctx)
         ^^^^^^^^^^^^^^^^
  File "C:\Users\Michael\AppData\Local\Programs\Python\Python312\Lib\site-packages\click\core.py", line 1434, in invoke
    return ctx.invoke(self.callback, **ctx.params)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\Michael\AppData\Local\Programs\Python\Python312\Lib\site-packages\click\core.py", line 783, in invoke
    return __callback(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\Michael\Documents\GitHub\octograph\app\octopus_to_influxdb.py", line 296, in cmd
    app.collect(from_date, to_date)
  File "C:\Users\Michael\Documents\GitHub\octograph\app\octopus_to_influxdb.py", line 100, in collect
    self._process_property(p, collect_from, collect_to, tags)
  File "C:\Users\Michael\Documents\GitHub\octograph\app\octopus_to_influxdb.py", line 111, in _process_property
    self._process_emp(emp, collect_from, collect_to, tags)
  File "C:\Users\Michael\Documents\GitHub\octograph\app\octopus_to_influxdb.py", line 151, in _process_emp
    self._process_em(emp['mpan'], em, collect_from, collect_to, standard_unit_rates, standing_charges, tags)
  File "C:\Users\Michael\Documents\GitHub\octograph\app\octopus_to_influxdb.py", line 161, in _process_em
    self._store_em_consumption(consumption, standard_unit_rates, standing_charges, tags)
  File "C:\Users\Michael\Documents\GitHub\octograph\app\octopus_to_influxdb.py", line 164, in _store_em_consumption
    self._store_consumption('electricity_consumption', consumption, standard_unit_rates, standing_charges, base_tags)
  File "C:\Users\Michael\Documents\GitHub\octograph\app\octopus_to_influxdb.py", line 175, in _store_consumption
    usage_cost_exc_vat_pence = standard_unit_rates[time]['value_exc_vat'] * c['consumption']
                               ~~~~~~~~~~~~~~~~~~~^^^^^^
KeyError: '2024-04-15T22:30:00Z'

@Yanson
Copy link
Owner

Yanson commented Apr 18, 2024

@Altirix - many thanks for raising this.

I've had a look at the tariff and it does indeed seem like a strange edge case.

The tariff is not listed in the product endpoint:

But it the pricing is there if you construct the URLs manually:

The second error is probably related to the first as the logic should use the appropriate tariff for the time of the consumption. If the missing tariff data is filled in, I'm hoping you won't get a key error.

Could you try manually specifying the missing URLs, e.g. add this to the beginning of def _find_links(product, tariff_code)::

        if tariff_code == 'E-FLAT2R-VAR-22-11-01-H':
            return [
                {
                    'rel': 'standing_charges',
                    'href': 'https://api.octopus.energy/v1/products/VAR-22-11-01/electricity-tariffs/E-FLAT2R-VAR-22-11-01-H/standing-charges/',
                },
                {
                    'rel': 'day_unit_rates',
                    'href': 'https://api.octopus.energy/v1/products/VAR-22-11-01/electricity-tariffs/E-FLAT2R-VAR-22-11-01-H/day-unit-rates/',
                },
                {
                    'rel': 'night_unit_rates',
                    'href': 'https://api.octopus.energy/v1/products/VAR-22-11-01/electricity-tariffs/E-FLAT2R-VAR-22-11-01-H/night-unit-rates/',
                },
            ]

If this works, we can find a neater way of adding special cases rather than silently skipping missing data.

@Altirix
Copy link
Author

Altirix commented Apr 19, 2024

The KeyError might have another cause, originally i had only tested with my account.

Recently I also tried to set up my parents account and theirs only gets the KeyError crash.

Originally I assumed these must have been the same problem, but now it seems they might be subtly different.

The manual link patch you provided seems to work as expected and does not crash when applied to 68bb26c (head)

Collecting data between 2024-01-01 and tomorrow
Processing property: REDACTED
Processing electricity meter point: 2000015437059
Storing 5326 points
Processing electricity meter: H08C22830
Storing 0 points
Processing electricity meter point: 2000015437040
Storing 5276 points
Processing electricity meter: H08C22830
Storing 0 points
Processing electricity meter: 23J0380709
Storing 169 points
No gas meter points found in property

Going to look into why my parents place produces the KeyError

Here's the crash for my parents place, at the time i didn't look over it too closely, but Could not find pricing for mpan: 2000010748269 sticks out. resulting in both standard_unit_rows and standing_charges being empty. for their meter, it seems _get_pricing returns nothing.

2024-04-19T14:45:40.621931794Z KeyError: '2024-04-17T23:30:00Z'
2024-04-19T14:45:53.834724043Z Collecting data between 2024-01-01 and tomorrow
2024-04-19T14:45:54.094462139Z Processing property: REDACTED
2024-04-19T14:45:54.094473791Z Processing electricity meter point: 2000010748269
2024-04-19T14:45:54.094476696Z Could not find pricing for mpan: 2000010748269
2024-04-19T14:45:54.094478760Z Storing 0 points
2024-04-19T14:45:54.094483880Z Processing electricity meter: 18K0189362
2024-04-19T14:45:54.385715633Z Traceback (most recent call last):
2024-04-19T14:45:54.385725292Z   File "/opt/octograph/app/octopus_to_influxdb.py", line 297, in <module>
2024-04-19T14:45:54.385769484Z     cmd()
2024-04-19T14:45:54.385791646Z   File "/usr/local/lib/python3.12/site-packages/click/core.py", line 1157, in __call__
2024-04-19T14:45:54.385978276Z     return self.main(*args, **kwargs)
2024-04-19T14:45:54.385981542Z            ^^^^^^^^^^^^^^^^^^^^^^^^^^
2024-04-19T14:45:54.385983636Z   File "/usr/local/lib/python3.12/site-packages/click/core.py", line 1078, in main
2024-04-19T14:45:54.386148345Z     rv = self.invoke(ctx)
2024-04-19T14:45:54.386151431Z          ^^^^^^^^^^^^^^^^
2024-04-19T14:45:54.386153555Z   File "/usr/local/lib/python3.12/site-packages/click/core.py", line 1434, in invoke
2024-04-19T14:45:54.386349372Z     return ctx.invoke(self.callback, **ctx.params)
2024-04-19T14:45:54.386352257Z            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
2024-04-19T14:45:54.386354201Z   File "/usr/local/lib/python3.12/site-packages/click/core.py", line 783, in invoke
2024-04-19T14:45:54.386476761Z     return __callback(*args, **kwargs)
2024-04-19T14:45:54.386479746Z            ^^^^^^^^^^^^^^^^^^^^^^^^^^^
2024-04-19T14:45:54.386481760Z   File "/opt/octograph/app/octopus_to_influxdb.py", line 293, in cmd
2024-04-19T14:45:54.386553184Z     app.collect(from_date, to_date)
2024-04-19T14:45:54.386571699Z   File "/opt/octograph/app/octopus_to_influxdb.py", line 100, in collect
2024-04-19T14:45:54.386604811Z     self._process_property(p, collect_from, collect_to, tags)
2024-04-19T14:45:54.386622234Z   File "/opt/octograph/app/octopus_to_influxdb.py", line 111, in _process_property
2024-04-19T14:45:54.386670715Z     self._process_emp(emp, collect_from, collect_to, tags)
2024-04-19T14:45:54.386679220Z   File "/opt/octograph/app/octopus_to_influxdb.py", line 151, in _process_emp
2024-04-19T14:45:54.386725218Z     self._process_em(emp['mpan'], em, collect_from, collect_to, standard_unit_rates, standing_charges, tags)
2024-04-19T14:45:54.386745045Z   File "/opt/octograph/app/octopus_to_influxdb.py", line 161, in _process_em
2024-04-19T14:45:54.386790701Z     self._store_em_consumption(consumption, standard_unit_rates, standing_charges, tags)
2024-04-19T14:45:54.386798665Z   File "/opt/octograph/app/octopus_to_influxdb.py", line 164, in _store_em_consumption
2024-04-19T14:45:54.386851645Z     self._store_consumption('electricity_consumption', consumption, standard_unit_rates, standing_charges, base_tags)
2024-04-19T14:45:54.386861042Z   File "/opt/octograph/app/octopus_to_influxdb.py", line 172, in _store_consumption
2024-04-19T14:45:54.386916927Z     usage_cost_exc_vat_pence = standard_unit_rates[t]['value_exc_vat'] * c['consumption']
2024-04-19T14:45:54.386922858Z                                ~~~~~~~~~~~~~~~~~~~^^^
2024-04-19T14:45:54.386925002Z KeyError: '2024-04-17T23:30:00Z'

@Altirix
Copy link
Author

Altirix commented Apr 19, 2024

I think i get what is happening, both agreements started after the requested backdating date. which was f = 2024-01-01 00:00:00+00:00

agreement_valid_from: 2024-03-14 00:00:00+00:00
agreement_valid_to: 2024-03-27 00:00:00+00:00

agreement_valid_from: 2024-03-27 00:00:00+00:00
agreement_valid_to: 2025-03-27 00:00:00+00:00

if agreement_valid_from <= f < agreement_valid_to: evaluates to False for both instances so we never query pricing data.

so it seems the KeyError can be caused if the user tries to backdate to a date that is outside of the oldest agreement, and i only stumbled into it originally as by skipping our old tariff we were outside of the remaining agreement's start date.

@Yanson
Copy link
Owner

Yanson commented Apr 19, 2024

Hi @Altirix, thank you for retesting.

For your parent's account could you try using the config included_meters and putting the meter serial numbers which match the Octopus portal + bill. I just want to make sure we're not trying to diagnose an error for a meter that's not in use.

If you still experience an error, I'd like to reproduce it. Could you send me either their API key + account number, or you could enable cache (see config options) and send me the resulting directory contents. This way you can obfuscate their address in the account response (and the account number as well if you prefer, which will also be in the filename).

@Yanson
Copy link
Owner

Yanson commented Apr 19, 2024

OK, got you. Yes, please don't try and backfill from a date before when the account was active. Perhaps we can add validation for that.

Does that mean the only real issue is your special FLAT2R tariff? How do you suggest handling that?

@Altirix
Copy link
Author

Altirix commented Apr 19, 2024

OK, got you. Yes, please don't try and backfill from a date before when the account was active. Perhaps we can add validation for that.

Does that mean the only real issue is your special FLAT2R tariff? How do you suggest handling that?

yes, the real issue is just the FLAT2R tariff missing from their endpoint, the issue with attempting to backdate before the agreement starts is mentioned in the readme

You can populate the metrics with all historic data in your account by specifying a --from-date equal to when your account was opened.

if _get_pricing clamps collect_from to the agreement_valid_from i think that might solve this and allow people to put any backdate and it'll just work out where it can start from. But I'm not sure if there are any pitfalls to doing this.

That should also allow _find_links to be hardened to just skip over tariffs that don't show on the product endpoint. When this happens maybe it should log something to the console just so the user knows why it cant fetch any data. (for me skipping over is fine as its our old tariff anyway, tho that wont be ideal for someone who actually wants that data.)

As for the product itself, I'm going to send Octopus an email and see what they say, id have to assume its an error on their end that the tariff isn't part of the product endpoint. Or maybe this endpoint only lists current products, and can't be relied upon to get the pricing links?

@Yanson
Copy link
Owner

Yanson commented Apr 19, 2024

yes, the real issue is just the FLAT2R tariff missing from their endpoint

As for the product itself, I'm going to send Octopus an email and see what they say, id have to assume its an error on their end that the tariff isn't part of the product endpoint. Or maybe this endpoint only lists current products, and can't be relied upon to get the pricing links?

The products endpoint has a parameter - tariffs_active_at. Could you try this to see if it does have your tariff if you use a date when the agreement was active? e.g.

curl -vs "https://api.octopus.energy/v1/products/VAR-22-11-01/?tariffs_active_at=2022-11-01T00:00:00Z"

Otherwise, yes, please email them and let me know what response you get.

@Altirix
Copy link
Author

Altirix commented May 19, 2024

just realised i missed the email, Response from octopus:


Hi Michael,

Thank you for reaching out to us. I apologise for any confusion or inconvenience caused.

Regarding the issue with the API endpoint not displaying your previous product (E-FLAT2R-VAR-22-11-01-H), I'm afraid I don't have access to our API system. However, I can assure you that our technical team will investigate this matter further and provide a resolution.

In the meantime, could you let me know which tariff you were interested in, so we can get this applied to your account

Best regards,
Octopus team

will check if the old product still causes issues when im back home

@Yanson
Copy link
Owner

Yanson commented Aug 4, 2024

Hi @Altirix, did you receive any further response from Octopus?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants