Skip to content

Instantly share code, notes, and snippets.

@helgibbons
Last active March 14, 2023 13:42
Show Gist options
  • Save helgibbons/bf5d33edded96646594566a36ea019ad to your computer and use it in GitHub Desktop.
Save helgibbons/bf5d33edded96646594566a36ea019ad to your computer and use it in GitHub Desktop.
Get regional Carbon Intensity data ( https://www.carbonintensity.org.uk/ ) and display it on Inky Frame
"""
This example connects to the Carbon Intensity API to give you a regional forecast of how
your (UK) electricity is being generated and its carbon impact.
Carbon Intensity API only reports data from the UK National Grid.
Find out more about what the numbers mean at:
https://carbonintensity.org.uk/
Make sure to uncomment the correct size for your display!
"""
from picographics import PicoGraphics, DISPLAY_INKY_FRAME_4 as DISPLAY # 4.0"
# from picographics import PicoGraphics, DISPLAY_INKY_FRAME as DISPLAY # 5.7"
# from picographics import PicoGraphics, DISPLAY_INKY_FRAME_7 as DISPLAY # 7.3"
import urequests
import inky_frame
import uasyncio
from network_manager import NetworkManager
import WIFI_CONFIG
# Set (the first half) of your UK postcode here
POSTCODE = "S9"
URL = "https://api.carbonintensity.org.uk/regional/postcode/" + str(POSTCODE)
def get_data():
global region, forecast, index, power_list, datetime_to, datetime_from
print(f"Requesting URL: {URL}")
r = urequests.get(URL)
# open the json data
j = r.json()
print("Data obtained!")
print(j)
# parse the json data
region = j["data"][0]["shortname"]
forecast = j["data"][0]["data"][0]["intensity"]["forecast"]
index = j["data"][0]["data"][0]["intensity"]["index"]
power_list = []
for power in j["data"][0]["data"][0]["generationmix"]:
power_list.append(power['perc'])
datetime_to = j["data"][0]["data"][0]["to"].split("T")
datetime_from = j["data"][0]["data"][0]["from"].split("T")
# close the socket
r.close()
def draw():
global graphics
# we're setting up our PicoGraphics buffer after we've made our RAM intensive https request
graphics = PicoGraphics(DISPLAY)
w, h = graphics.get_bounds()
graphics.set_pen(inky_frame.WHITE)
graphics.clear()
# draw lines
graphics.set_pen(inky_frame.BLACK)
graphics.line(0, int((h / 100) * 0), w, int((h / 100) * 0))
graphics.line(0, int((h / 100) * 50), w, int((h / 100) * 50))
graphics.set_font("bitmap8")
graphics.text('100%', w - 40, 10, scale=2)
graphics.text('50%', w - 40, int((h / 100) * 50 + 10), scale=2)
# draw bars
bar_colours = [inky_frame.ORANGE, inky_frame.RED, inky_frame.ORANGE, inky_frame.RED, inky_frame.BLUE, inky_frame.ORANGE, inky_frame.GREEN, inky_frame.GREEN, inky_frame.GREEN]
for p in power_list:
graphics.set_pen(bar_colours[power_list.index(p)])
graphics.rectangle(int(power_list.index(p) * w / 9), int(h - p * (h / 100)), int(w / 9), int(h / 100 * p))
# draw labels
graphics.set_font('sans')
# once in white for a background
graphics.set_pen(inky_frame.WHITE)
labels = ['biomass', 'coal', 'imports', 'gas', 'nuclear', 'other', 'hydro', 'solar', 'wind']
graphics.set_thickness(4)
for l in labels:
graphics.text(f'{l}', int((labels.index(l) * w / 9) + (w / 9) / 2), h - 10, angle=270, scale=1)
# again in black
graphics.set_pen(inky_frame.BLACK)
labels = ['biomass', 'coal', 'imports', 'gas', 'nuclear', 'other', 'hydro', 'solar', 'wind']
graphics.set_thickness(2)
for l in labels:
graphics.text(f'{l}', int((labels.index(l) * w / 9) + (w / 9) / 2), h - 10, angle=270, scale=1)
# draw header
graphics.set_thickness(3)
graphics.set_pen(inky_frame.GREEN)
if index in ['high','very high']:
graphics.set_pen(inky_frame.RED)
if index in ['moderate']:
graphics.set_pen(inky_frame.ORANGE)
graphics.set_font("sans")
graphics.text('Carbon Intensity', 10, 35, scale=1.2, angle=0)
graphics.set_pen(inky_frame.BLACK)
graphics.set_font("bitmap8")
graphics.text(f'Region: {region}', int((w / 2) + 30), 10, scale=2)
graphics.text(f'{forecast} gCO2/kWh ({index})', int((w / 2) + 30), 30, scale=2)
graphics.text(f'{datetime_from[0]} {datetime_from[1]} to {datetime_to[1]}', int((w / 2) + 30), 50, scale=2)
graphics.update()
def status_handler(mode, status, ip):
print(mode, status, ip)
inky_frame.led_busy.on()
network_manager = NetworkManager(WIFI_CONFIG.COUNTRY, status_handler=status_handler)
# connect to wifi
try:
uasyncio.get_event_loop().run_until_complete(network_manager.client(WIFI_CONFIG.SSID, WIFI_CONFIG.PSK))
except ImportError:
print("Add WIFI_CONFIG.py with your WiFi credentials")
get_data()
draw()
# Go to sleep if on battery power
inky_frame.turn_off()
"""
Pico W RAM seems insufficient to decode a https request whilst having a PicoGraphics instance active?
If you are running off USB and want this to update periodically, you could incorporate a time.sleep()
and then a machine.reset() to reset the Pico and start afresh every time.
"""
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment