Best screen for a Pi Zero W energy monitor project - inky hat?


Thanks Zarch for the description of the code, sounds good.

The fronius inverter (generation data) and smart meter (consumption data) has an API that i can access via the web browser. So when i go to http://fronius/solar_api/v1/GetPowerFlowRealtimeData.fcgi (fronius being DNS’d to its local internal IP address) i get a JSON response back like this:

   "Body" : {
      "Data" : {
         "Inverters" : {
            "1" : {
               "DT" : 81,
               "E_Day" : 19786,
               "E_Total" : 4222050,
               "E_Year" : 4222055.5,
               "P" : 0
         "Site" : {
            "E_Day" : 19786,
            "E_Total" : 4222050,
            "E_Year" : 4222055.5,
            "Meter_Location" : "grid",
            "Mode" : "meter",
            "P_Akku" : null,
            "P_Grid" : 427.27999044954777,
            "P_Load" : -427.27999044954777,
            "P_PV" : null,
            "rel_Autonomy" : 0,
            "rel_SelfConsumption" : null
         "Version" : "10"
   "Head" : {
      "RequestArguments" : {},
      "Status" : {
         "Code" : 0,
         "Reason" : "",
         "UserMessage" : ""
      "Timestamp" : "2018-12-07T21:45:42+11:00"

The values I am interested in are:

  • P_Grid - when it is positive, it is how much power is been used from the grid, a negative value is power fed back to the grid
  • P_Load - how much power is been used
  • P_PV - How much power is been generated by the PV system

So i think i have all the data accessible, a little kick start with your code will get me on my way with also lots of help from mr google!


@Zarch Yes it would likely be overkill. I’m still mulling over what I will do with my 3A+ when it arrives.

I have one of those 16x2 displays you linked to earlier. It came in an Arduino kit I just got. Can’t play with it until Christmas though. ;) I’ll likely just plug it into a solderless breadboard to test it out and tinker with it. Female to female jumper wires work well with stuff like that. Plug one end into the Pi’s GPIO and the other end to the header on the display. I’ve done that many times with breakout boards like the BME680 etc. Works well for testing too if you don’t have a solderless bread board.


@mrLaw Here you go… its not great code, its messy and probably got some bits no longer required in… but haven’t had time to tidy it up as its working. :)

#!/usr/bin/env python

import time
import signal
import json
import requests

from gfxhat import touch, lcd, backlight, fonts
from PIL import Image, ImageFont, ImageDraw

# A slightly rounded, Ubuntu-inspired version of Bitocra
#font = ImageFont.truetype(fonts.BitbuntuFull, 10)
#font = ImageFont.truetype(fonts.BitocraFull, 11)
#font = ImageFont.truetype(fonts.AmaticSCBold, 30)
font = ImageFont.truetype('/home/pi/codebase/fonts/BebasNeue-Regular.ttf',32)
#font = ImageFont.truetype('/home/pi/codebase/fonts/VCR_OSD_MONO_1.001.ttf', 20)

def set_backlight(r, g, b):
    backlight.set_all(r, g, b)

def cleanup():
    backlight.set_all(0, 0, 0)

def handler(ch, event):
    if event == 'press':
        led_states[ch] = not led_states[ch]
        touch.set_led(ch, led_states[ch])
        if led_states[ch]:
            backlight.set_pixel(ch, 0, 255, 255)
            backlight.set_pixel(ch, 0, 255, 0)

# Code Starts Here

width, height = lcd.dimensions()


print "width: ", width
print "height: ", height

w, h = font.getsize('>')

print "font width: ", w
print "font height: ", h

usage_result = 0
solar_result = 0

#print "x: ", x
#print "y: ", y

feed_id_a = 10 #Solar
#feed_id_a = 374693
feed_id_b = 8 # Use
feed_ids = str(feed_id_a) + ',' + str(feed_id_b)

mylist =(feed_id_a,feed_id_b)
feed_ids = ",".join(map(str, mylist))
#print feed_ids

emonapikey = "187a7b179b402xxxxxxxx75fae969" #local
using = 0
delay = 10

gap = (width / delay)
print gap

while True:

	for countdown in range (delay,0,-1):
		if countdown == 1:
			milli_sec_end = int(round(time.time() * 1000))
			milli_sec_start = milli_sec_end - 300000
			solar_result = 0
			usage_result = 0
			payload = {'ids': feed_ids, 'apikey': emonapikey}
				response = requests.get("http://emonpi/emoncms/feed/fetch.json", params=payload)
			except requests.exceptions.RequestException as e:
				print e
            #print response.status_code

			if response.status_code == 200:
				result_numbers = (response.content)
				#print result_numbers
				result_numbers = str(result_numbers).strip('[]')
				results_list = result_numbers.split(',')
				usage_result = int(float(results_list[0]))
				solar_result = int(float(results_list[1]))
				usage_result = 0
				solar_result = 0

			if usage_result < solar_result:
				set_backlight(0, 155, 0)
				set_backlight(155, 0, 0)

			# Set X and Y to top left of lcd
			x = 0
			y = 0
			image ='P', (width, height))
			draw = ImageDraw.Draw(image)
			text = "Use: "+str(usage_result)+"w"

			draw.text((x, y), text, 1, font)
			y = y + h

			text = "Gen: " + str(solar_result) + "w"

			draw.text((x, y), text, 1, font)
			y = y + h

			# This clears the display ready for next display, otherwise the countdown over-prints
			for x in range(128):
				for y in range(64):
					pixel = image.getpixel((x, y))
					lcd.set_pixel(x, y, pixel)


# Closedown the display and end the program

for x in range(6):
    backlight.set_pixel(x, 0, 0, 0)
    touch.set_led(x, 0)

Hope this makes some sense and is useful? :)


Thanks Zarch, I will have a look though and see what I need to change to get it to read the data from my fronius inverter and hopefully report back with something working!

Many thanks.


It’s alive! Now for a bit of playing around with what to display. Then a case for it, my son loves the lego case you have done, so that is his preference, i will see what other options i can come up with :)

Thanks again @Zarch for your code and explanation to help get me going with this.


YEAH!!! Looks fab @mrLaw … and you chose a sunny day to test it on!! A rarity in the past 4 weeks or so!! LOL.

My original thinking was to pull the weather info from Dark Sky and maybe have daily totals etc and even PVGIS targets. But in the end the display is too small to fit all that info on, especially if you want to glance across the room.

Maybe you’d need something like a Google Home Hub 7" size for all that type of info?

So i’m sticking with the two basics and a big font. It means the wife can glance at it and understand what its saying. She has no idea about my obsession with PVGIS targets!! ;)

Although I do fancy a little progress indicator along the bottom of the display… maybe 10 pixels per second (so on every loop), just to show its still collecting info. Cos when it crashes it just permanently shows the last figures obtained.

Let me know how you progress your little project.



Finally added that progress monitor / countdown bar!! About time!! :)


Looks great @Zarch I changed the update to be every 5 seconds, so i just count to 5 to make sure it is still running! So far it has been pretty stable, don’t think i have had any lockups.

I have had a play with the code and added an extra background colour and line of text at the bottom. I set the colour thresholds to be if sending more than 1500w to the grid, turn green, if sending between 1500w and 1w turn orange and if below 1, turn red. Also cased it in lego, that was my son’s first choice and the easiest thing to do for now!


Looking good @mrLaw. :)

I also dropped my delay down to five seconds when I added the little progress bar.

One of the main reasons for the progress bar was to show the code was still working as it did have a tendency to crap out from time to time, usually network related. So as well as the progress bar I’ve added some extra try/except code to hopefully pick up where it had been crashing.

So fingers crossed that all helps things become more stable.