Amber Electricity Real-time price widget for iOS 14

Amber pass on wholesale electricity costs. This widget makes it super easy to see current prices to help change your behaviour.

Posted by Ross Poulton on Thu 15 October 2020

UPDATED MAY 2023 The code in this post is no longer usable, as we no longer personally use Amber and their API has since changed. Thank you to Brad Thomson, who got in touch with an updated Amber Electric widget that uses this new API. I can't vouch for how well it works as our household no longer use Amber, but those who are looking for the functionality documented below might find it useful.


We recently moved our home electricity supply to Amber Electric, a new(ish) provider who pass on market rates to home users. Given Australia's energy supply is made up of coal, gas, and renewables we have a fluctuating supply throughout the day - and most residential usage follows a pretty predictable peak / off-peak pattern that doesn't match the supply.

As a result of these out-of-sync supply and demand curves, there's an opportunity - if you're keen - to capitalise on the gaps and spend significantly less (or more!) on your electricity at home. All it takes is an interest in numbers and a willingness to turn off your appliances.

Our home and hot water are heated by gas, and our cooktop is also gas powered. This means our major electricity consumption is from our dishwasher, washing machine, and our outdoor spa / hot tub. (We've been an LED-only household for quite a while, and where practical we don't leave appliances on that we aren't using). These three high-demand appliances are all pretty easy to use at ad-hoc times of the day thanks to timers - so it makes sense for us to run them when power is cheap and turn them off when the price spikes.

My iPhone Home Screen with my Amber Widget at the right hand side.

The Amber Electric app is very good at showing you the current wholesale price plus the expected price over the next few hours. This helps you plan your electricity usage through the day. I wanted something more visible, though - and when iOS 14 came out I thought I'd have a play with Widgets to show the current Amber rate for my postcode right there on my homescreen.

To achieve this, you'll need an iPhone or iPad running iOS 14. You'll also need to be an Amber Electric customer (if you aren't a customer, signing up with this referral link should earn us both a $25 gift card. The link at the top of the post is direct to their homepage if you'd prefer).

You'll then need to install Scriptable from the App Store. This is a nifty little app that lets you write JavaScript snippets to do all sorts of things, including - you guessed it - create your own iOS widgets.

Open Scriptable, hit the 'Plus' button at the top right, and paste the code below.

// Change this to your postcode. Amber rates vary by region.
let postcode = "3089";

// Rest of this doesn't need to be changed unless you want to get your hands dirty

// Initialise variables. These will be set based on Amber API
var currentPrice = 0
var nextPrice = 0
var currentRenewables = 0

// API call to get prices for the provided postcode
let req = new Request("https://api.amberelectric.com.au/prices/listprices")
req.method = 'POST'
req.headers = {'Content-Type': 'application/json'}
req.body = '{ "postcode": "' + postcode + '" }'

let json = await req.loadJSON()
let data = json.data

// Static per-kwh prices: these include supply charges, the Amber fee, green energy rates, etc.
var staticKwhPrice = parseFloat(data.staticPrices.E1.totalfixedKWHPrice)
var lossFactor = parseFloat(data.staticPrices.E1.lossFactor)

// Variable prices: This is a list of 30-minute intervals of past/current (ACTUAL) and future (FORECAST) 
// power prices.
for (i=0; i<data.variablePricesAndRenewables.length; i++) {
    var thisPeriod = data.variablePricesAndRenewables[i]
    if (thisPeriod.periodType == 'ACTUAL') {
        // We push the actual figures into currentPrice/currentRenewables. These are in time order so we'll end up 
        // using the last one for 'current'.
        currentPrice = Math.round((parseFloat(thisPeriod.wholesaleKWHPrice) * lossFactor) + staticKwhPrice, 4) / 100
        currentRenewables = Math.round(parseFloat(thisPeriod.renewablesPercentage) * 100)
    } else if (thisPeriod.periodType == 'FORECAST' && nextPrice == 0) {
        // the first 'FORECAST' becomes the next period price.
        nextPrice = Math.round((parseFloat(thisPeriod.wholesaleKWHPrice) * lossFactor) + staticKwhPrice, 4) / 100

    }
}

if (config.runsInWidget) {
    let widget = createWidget()
    Script.setWidget(widget)
    Script.complete()
} else {
    QuickLook.present(createWidget());
}

function createWidget() {
    let w = new ListWidget()

    // Set background color to green / orange / red based on current rate.
    if (currentPrice <= 0.20) {
        bgColor = '#18df95'
    } else if (currentPrice <= 0.25) {
        bgColor = '#ffad10'
    } else {
        bgColor = '#e23a3b'
    }
    w.backgroundColor = new Color(bgColor)

    // Add 'AMBER' heading
    let header = w.addText('AMBER ELECTRICITY')
    header.textColor = Color.white()
    header.textOpacity = 0.7

    // Add 'Current price' in 22pt font
    let bodyText = w.addText("$" + currentPrice + "/kwh")
    bodyText.font = Font.mediumRoundedSystemFont(22)
    bodyText.textColor = Color.white()

    // Add 'Next price' in smaller 14pt font
    let nextText = w.addText("Next $" + nextPrice + "/kwh")
    nextText.font = Font.mediumRoundedSystemFont(14)
    nextText.textColor = Color.white()

    // Add '% Renewables' annotation in 14pt font, lower opacity
    let renewableText = w.addText(currentRenewables + "% renewables")
    renewableText.font = Font.mediumRoundedSystemFont(14)
    renewableText.textColor = Color.white()
    renewableText.textOpacity = 0.8


    // Add 'last updated' date to footer   
    var nowDate = new Date()
    var nowFormDate = nowDate.toLocaleTimeString('en-AU')
    let footer = w.addText("as at " + nowFormDate)
    footer.font = Font.footnote()
    footer.textColor = Color.white()
    footer.textOpacity = 0.8

    return w
}

Be sure to grab the whole thing, starting with the line above let postcode... ad ending with the curly bracket beneath return w. Tap 'Untitled Script 1' to rename it to 'Amber Price', then change the postcode from 3089 to your local postcode (unless you live near me - howdy, neighbour!)

Last of all, you'll need to add the widget to your home screen. Long-press your home screen so it enters 'Wiggle' mode, tap the Plus button at the top of the screen, and select the 'Scriptable' widget. Once the widget drops onto the homepage (and while it'=s still wiggling) tap on the empty Scriptable widget, select the Amber Price script, and you're done!

You could improve this by adding in a trend line, longer forecast, or more - but for my purposes right now this is a pretty good outcome.

Cover photo: American Public Power Association via Unsplash.