Update app.py#14
Conversation
Added try/catch to both Aemo and Amber fetch processes to cater for internet failure scenarios
Reviewer's GuidePeriodic 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 fetchsequenceDiagram
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
Sequence diagram for error handling in AEMO price fetchsequenceDiagram
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
File-Level Changes
Possibly linked issues
Tips and commandsInteracting with Sourcery
Customizing Your ExperienceAccess your dashboard to:
Getting Help
|
There was a problem hiding this comment.
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>Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.
| if aemoPriceFirm: | ||
| if amber2mqtt: | ||
| a2m.publishAemoStateCurrent(client, aemoData) |
There was a problem hiding this comment.
suggestion (code-quality): Merge nested if conditions (merge-nested-ifs)
| if aemoPriceFirm: | |
| if amber2mqtt: | |
| a2m.publishAemoStateCurrent(client, aemoData) | |
| if aemoPriceFirm and amber2mqtt: | |
| a2m.publishAemoStateCurrent(client, aemoData) | |
Explanation
Too much nesting can make code difficult to understand, and this is especiallytrue 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.
| responseTime = dt.now() | ||
| amberEstimatePrice = amberData["current"]["general"].estimate | ||
| if not amberEstimatePrice: | ||
| print("Amber Current Period data confirmed") |
There was a problem hiding this comment.
issue (code-quality): Extract code out into function (extract-method)
| aemoPriceFirm = aemo.checkAemoSettlementDate(aemoData["ELEC_NEM_SUMMARY"][0]) | ||
| if aemoPriceFirm: |
There was a problem hiding this comment.
suggestion (code-quality): Use named expression to simplify assignment and conditional (use-named-expression)
| aemoPriceFirm = aemo.checkAemoSettlementDate(aemoData["ELEC_NEM_SUMMARY"][0]) | |
| if aemoPriceFirm: | |
| if aemoPriceFirm := aemo.checkAemoSettlementDate( | |
| aemoData["ELEC_NEM_SUMMARY"][0] | |
| ): |
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: