Skip to content

Update app.py#14

Open
AtomicGrog wants to merge 1 commit into
cabberley:mainfrom
AtomicGrog:internetresiliencyfix
Open

Update app.py#14
AtomicGrog wants to merge 1 commit into
cabberley:mainfrom
AtomicGrog:internetresiliencyfix

Conversation

@AtomicGrog
Copy link
Copy Markdown

@AtomicGrog AtomicGrog commented Oct 14, 2025

Added try/catch to both Aemo and Amber fetch processes to cater for internet failure scenarios.

Tested on startup with no internet access, and repeatedly with internet failing whilst adaper is running (Dozens of times, ty NBN) and it worked fine, for both loss of access to AEMO as well as Amber:

Summary by Sourcery

Wrap external Amber and AEMO API fetch routines in try/except blocks to handle internet failures gracefully and log errors.

Bug Fixes:

  • Add error handling to amber5minPrice to catch and log request and unexpected exceptions.
  • Add error handling to aemo5MinCurrentPrice to catch and log request and unexpected exceptions.

Added try/catch to both Aemo and Amber fetch processes to cater for internet failure scenarios
@sourcery-ai
Copy link
Copy Markdown

sourcery-ai Bot commented Oct 14, 2025

Reviewer's Guide

Periodic Amber and AEMO price fetch routines are now wrapped in try/except blocks to catch network failures and other exceptions, logging errors instead of allowing the adapter to crash.

Sequence diagram for error handling in Amber price fetch

sequenceDiagram
participant Scheduler
participant "amber5minPrice()"
participant AmberAPI
participant Logger
Scheduler->>"amber5minPrice()": Trigger periodic fetch
"amber5minPrice()"->>AmberAPI: getAmberData()
alt Success
    AmberAPI-->>"amber5minPrice()": Data
    "amber5minPrice()"->>Scheduler: Process data
else Network failure
    AmberAPI--x"amber5minPrice()": Exception
    "amber5minPrice()"->>Logger: Log error
end
Loading

Sequence diagram for error handling in AEMO price fetch

sequenceDiagram
participant Scheduler
participant "aemo5MinCurrentPrice()"
participant AEMOAPI
participant Logger
Scheduler->>"aemo5MinCurrentPrice()": Trigger periodic fetch
"aemo5MinCurrentPrice()"->>AEMOAPI: getAemoCurrentData()
alt Success
    AEMOAPI-->>"aemo5MinCurrentPrice()": Data
    "aemo5MinCurrentPrice()"->>Scheduler: Process data
else Network failure
    AEMOAPI--x"aemo5MinCurrentPrice()": Exception
    "aemo5MinCurrentPrice()"->>Logger: Log error
end
Loading

File-Level Changes

Change Details Files
Wrap Amber fetch logic in error handling to handle network failures gracefully
  • Enclose the amber5minPrice body in a try/except block
  • Catch requests.exceptions.RequestException and log specific error
  • Catch generic exceptions and log unexpected errors
app.py
Wrap AEMO fetch logic in error handling to handle network failures gracefully
  • Enclose the aemo5MinCurrentPrice body in a try/except block
  • Catch requests.exceptions.RequestException and log specific error
  • Catch generic exceptions and log unexpected errors
app.py

Possibly linked issues

  • #123: The PR adds error handling for network outages in AEMO and Amber data fetches, directly resolving the issue's described recovery failure.

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

Copy link
Copy Markdown

@sourcery-ai sourcery-ai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey there - I've reviewed your changes and they look great!

Prompt for AI Agents
Please address the comments from this code review:

## Individual Comments

### Comment 1
<location> `app.py:109-111` </location>
<code_context>
            if aemoPriceFirm:
                if amber2mqtt:
                    a2m.publishAemoStateCurrent(client, aemoData)

</code_context>

<issue_to_address>
**suggestion (code-quality):** Merge nested if conditions ([`merge-nested-ifs`](https://docs.sourcery.ai/Reference/Rules-and-In-Line-Suggestions/Python/Default-Rules/merge-nested-ifs))

```suggestion
            if aemoPriceFirm and amber2mqtt:
                a2m.publishAemoStateCurrent(client, aemoData)

```

<br/><details><summary>Explanation</summary>Too much nesting can make code difficult to understand, and this is especially
true in Python, where there are no brackets to help out with the delineation of
different nesting levels.

Reading deeply nested code is confusing, since you have to keep track of which
conditions relate to which levels. We therefore strive to reduce nesting where
possible, and the situation where two `if` conditions can be combined using
`and` is an easy win.
</details>
</issue_to_address>

### Comment 2
<location> `app.py:80` </location>
<code_context>
def amber5minPrice():
    """Get the current prices from the Amber API every 5 minutes"""
    global amberEstimatePrice
    try:
        if amberEstimatePrice:
            requestTime = dt.now()
            amberData = al.getAmberData(amberApiToken, amberSiteId,  13,5,5)
            responseTime = dt.now()
            amberEstimatePrice = amberData["current"]["general"].estimate
            if not amberEstimatePrice:
                print("Amber Current Period data confirmed")
                if amber2mqtt:
                    a2m.publishAmberStateCurrent(client, amberData)
                    a2m.publishAmberStatePeriods(client, amberData)
                if amber5minForecast:
                    amberData5 = al.getAmberData(amberApiToken, amberSiteId,15,0,5)
                    a2m.publishAmberState5MinForecasts(client, amberData5)
                if amber30minForecast:
                    amberData30 = al.getAmberData(amberApiToken, amberSiteId,99,0,30)
                    a2m.publishAmberState30MinForecasts(client, amberData30)
                if amberUserForecast:
                    amberData = al.getAmberData(amberApiToken, amberSiteId,288,0,0)
                    a2m.publishAmberStateUserForecasts(client, amberData)
                if amber288Forecast:
                    amberData288 = al.create_288_5min_intervals(amberData5, amberData30)
                    a2m.publishAmberState5MinExtendedForecasts(client, amberData288)
    except requests.exceptions.RequestException as e:
        logging.error(f"Failed to fetch Amber data: {e}")
    except Exception as e:
        logging.error(f"An unexpected error occurred in amber5minPrice: {e}")

</code_context>

<issue_to_address>
**issue (code-quality):** Extract code out into function ([`extract-method`](https://docs.sourcery.ai/Reference/Default-Rules/refactorings/extract-method/))
</issue_to_address>

### Comment 3
<location> `app.py:108-109` </location>
<code_context>
def aemo5MinCurrentPrice():
    """Get the current price from AEMO every 5 minutes"""
    global aemoPriceFirm
    try:
        if not aemoPriceFirm:
            aemoData = aemo.getAemoCurrentData()
            aemoPriceFirm = aemo.checkAemoSettlementDate(aemoData["ELEC_NEM_SUMMARY"][0])
            if aemoPriceFirm:
                if amber2mqtt:
                    a2m.publishAemoStateCurrent(client, aemoData)
    except requests.exceptions.RequestException as e:
        logging.error(f"Failed to fetch AEMO data: {e}")
    except Exception as e:
        logging.error(f"An unexpected error occurred in aemo5MinCurrentPrice: {e}")

</code_context>

<issue_to_address>
**suggestion (code-quality):** Use named expression to simplify assignment and conditional ([`use-named-expression`](https://docs.sourcery.ai/Reference/Default-Rules/refactorings/use-named-expression/))

```suggestion
            if aemoPriceFirm := aemo.checkAemoSettlementDate(
                aemoData["ELEC_NEM_SUMMARY"][0]
            ):
```
</issue_to_address>

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

Comment thread app.py
Comment on lines +109 to +111
if aemoPriceFirm:
if amber2mqtt:
a2m.publishAemoStateCurrent(client, aemoData)
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

suggestion (code-quality): Merge nested if conditions (merge-nested-ifs)

Suggested change
if aemoPriceFirm:
if amber2mqtt:
a2m.publishAemoStateCurrent(client, aemoData)
if aemoPriceFirm and amber2mqtt:
a2m.publishAemoStateCurrent(client, aemoData)


ExplanationToo much nesting can make code difficult to understand, and this is especially
true in Python, where there are no brackets to help out with the delineation of
different nesting levels.

Reading deeply nested code is confusing, since you have to keep track of which
conditions relate to which levels. We therefore strive to reduce nesting where
possible, and the situation where two if conditions can be combined using
and is an easy win.

Comment thread app.py
responseTime = dt.now()
amberEstimatePrice = amberData["current"]["general"].estimate
if not amberEstimatePrice:
print("Amber Current Period data confirmed")
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

issue (code-quality): Extract code out into function (extract-method)

Comment thread app.py
Comment on lines +108 to +109
aemoPriceFirm = aemo.checkAemoSettlementDate(aemoData["ELEC_NEM_SUMMARY"][0])
if aemoPriceFirm:
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

suggestion (code-quality): Use named expression to simplify assignment and conditional (use-named-expression)

Suggested change
aemoPriceFirm = aemo.checkAemoSettlementDate(aemoData["ELEC_NEM_SUMMARY"][0])
if aemoPriceFirm:
if aemoPriceFirm := aemo.checkAemoSettlementDate(
aemoData["ELEC_NEM_SUMMARY"][0]
):

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.

1 participant