User story:
I would like to see a graphical representation of the hourly Tibber rates for today and tomorrow on a matrix display.
BOM:
- Matrix display, e.g. Ulanzi TC001
- AWTRIX
- MQTT broker
- Your personal Tibber API token
- optional: MQTT Explorer
Setup:
- Get your TC001 up and running (just follow the installation instructions).
- If you can’t read Chinese, I strongly recommend to switch the UI to English, see Ulanzi Desktop Pixel Clock TC001 Review | Blakadder's Smarthome Shenanigans.
- Install AWTRIX.
- Configure your TC001 as an AWTRIX controller (‘Atrix Simulator’, port 7001), see Ulanzi Desktop Pixel Clock TC001 Review | Blakadder's Smarthome Shenanigans.
- Use the AWTRIX UI to enable MQTT.
- Install
lua
andjson-lua
(sudo luarocks install json-lua
). - Copy the following script to your filesystem:
#!/bin/bash
mosquitto_pub -m "{\"remove\":\"TibberApp\"}" -h <MQTT broker IP address> -u <MQTT user> -P <MQTT password> -t awtrix/temporaryapp
curl 2>/dev/null \
-H "Authorization: Bearer <your personal Tibber API token>" \
-H "Content-Type: application/json" \
-X POST \
-d '{ "query": "{ viewer { homes { currentSubscription{ priceInfo{ today { total } tomorrow { total } } } } } }" }' https://api.tibber.com/v1-beta/gql \
| lua create_awtrix_tibber_app.lua | tr -d '\n' | mosquitto_pub -l -h <MQTT broker IP address> -u <MQTT user> -P <MQTT password> -t awtrix/temporaryapp
- Adjust
<your personal Tibber API token>
and the MQTT parameters. - Copy the following Lua script into
create_awtrix_tibber_app.lua
and place it in the same directory as the shell script:
json = require "JSON"
function print_color( p )
if p <= red
then
print( ' "color":[255,0,0]' )
else
if p <= orange
then
print( ' "color":[255,165,0]' )
else
print( ' "color":[0,255,0]' )
end
end
end
function analyse_day( res, today )
red = 0.35
orange = 0.30
prices = {}
min = math.huge
max = -math.huge
if today
then
dataset = "today"
else
dataset = "tomorrow"
end
if #res["data"]["viewer"]["homes"][1]["currentSubscription"]["priceInfo"][ dataset ] == 24
then
for x,y in pairs( res["data"]["viewer"]["homes"][1]["currentSubscription"]["priceInfo"][ dataset ])
do
prices[x-1] = ( y["total"] ) * 1.0
if prices[x-1] > max
then
max = prices[x-1]
max_pos = x-1
end
if prices[x-1] < min
then
min = prices[x-1]
min_pos = x-1
end
end
diff = max - min
red = 7 - math.floor( ( red - min ) * 7 / diff + 0.5 )
orange = 7 - math.floor( ( orange - min ) * 7 / diff + 0.5 )
min_pixel = 7 - math.floor( ( min - min ) * 7 / diff + 0.5 )
max_pixel = 7 - math.floor( ( max - min ) * 7 / diff + 0.5 )
current_hour = os.date("*t").hour
price_current = prices[ current_hour ]
if not today
then
print(' {')
print( ' "type": "fill",')
print( ' "color": [50,50,50]')
print( ' },')
end
if today
then
print( '{ "type":"pixel",' )
print( ' "position":['..current_hour..",0]," )
print( ' "color":[255,255,255]' )
print( '},')
print( '{ "type":"pixel",' )
print( ' "position":['..current_hour..",7]," )
print( ' "color":[255,255,255]' )
print( '},')
end
for i = 0,23 do prices[i] = 7 - math.floor( ( prices[i]-min ) * 7 / diff + 0.5 ) end
for i = 0,23
do
print( '{ "type":"pixel",' )
print( ' "position":['..i..","..prices[i].."]," )
print_color( prices[i] )
print( '},')
end
if today
then
print( '{ "type":"text",' )
print( ' "string":"' .. math.floor( price_current * 100 + 0.5 )..'",')
print( ' "position":[24,0],' )
print_color( prices[ current_hour ] )
print( '},')
print( '{')
print( ' "type": "show"')
print( ' },')
print( ' {')
print( ' "type": "wait",')
print( ' "ms": 10000')
print( ' },')
else
print( '{ "type":"text",' )
print( ' "string":"' .. math.floor( min * 100 + 0.5 )..'",')
print( ' "position":[24,0],' )
print_color( min_pixel )
print( '},')
print( '{ "type":"pixel",' )
print( ' "position":['..min_pos..",0]," )
print( ' "color":[255,255,255]' )
print( '},')
print(' {')
print( ' "type": "line",')
print( ' "start": [27,7],')
print( ' "end": [29,7],')
print( ' "color": [255,255,255]')
print( ' },')
print(' {')
print( ' "type": "pixel",')
print( ' "position": [28,6],')
print( ' "color": [255,255,255]')
print( ' },')
print( ' {')
print( ' "type": "show"')
print( ' },')
print( ' {')
print( ' "type": "wait",')
print( ' "ms": 3000')
print( ' },')
if not today
then
print(' {')
print( ' "type": "fill",')
print( ' "color": [50,50,50]')
print( ' },')
print(' {')
print( ' "type": "line",')
print( ' "start": [27,6],')
print( ' "end": [29,6],')
print( ' "color": [255,255,255]')
print( ' },')
print(' {')
print( ' "type": "pixel",')
print( ' "position": [28,7],')
print( ' "color": [255,255,255]')
print( ' },')
for i = 0,23
do
print( '{ "type":"pixel",' )
print( ' "position":['..i..","..prices[i].."]," )
print_color( prices[i] )
print( '},')
end
end
--[[
for i = 0, 7
do
print(' {')
print( ' "type": "line",')
print( ' "start": [24,'..i..'],')
print( ' "end": [31,'..i..'],')
print( ' "color": [50,50,50]')
print( ' },')
end
--]]
print( '{ "type":"text",' )
print( ' "string":"' .. math.floor( max * 100 + 0.5 )..'",')
print( ' "position":[24,0],' )
print_color( max_pixel )
print( '},')
print( '{ "type":"pixel",' )
print( ' "position":['..max_pos..",7]," )
print( ' "color":[255,255,255]' )
print( '},')
print( '{')
print( ' "type": "show"')
print( ' },')
print( ' {')
print( ' "type": "wait",')
print( ' "ms": 3000')
print( ' },')
end
end -- data available
end -- function analyse_day
txt = io.read( '*a' )
res = json:decode( txt )
print( '{')
print( ' "name":"TibberApp",')
print( ' "lifetime":9999,')
print( ' "drawing":true,')
print( ' "data":[')
analyse_day( res, true )
analyse_day( res, false )
print( ' {')
print( ' "type": "exit"')
print( ' }')
print( ' ]')
print( '}')
- Execute the shell script to test your installation. I strongly recommend to use MQTT Explorer to check the installation (topic
awtrix/temporaryapp
):
The result should look like:
Today from 7 pm to 8 pm (current hour): 30 ct/kWh
Tomorrow from 12 noon to 1 pm lowest rate: 23 ct/kWh:
Tomorrow from 7 pm to 8 pm highest rate: 36 ct/kWh:
Screen #1 and screen #2 are from the AWTRIX Time App and screens #3 - #5 were created by the new temporary Tibber App for AWTRIX. The white cursor marks the current hour (screen #3) and the hour with the lowest rate (screen #4) and the hour with the highest rate (screen #5), the number in the upper right corner is the current rate (screen #3), lowest (screen #4) and highest rate (screen #5) for tomorrow (unit: ct/kWh). The thresholds for the color of the graphs and the rates can be configured in the Lua script.
11. Setup a rule or use the Exec Binding to run the shell script every hour on the hour.
I am open to suggestions on how to integrate this framework into openHAB.
Edit #1:
If you are going to use the shell script via executeCommandLine
: Make sure you prepend the correct path to create_awtrix_tibber_app.lua
in the shell script - it took me some time to debug my openHAB rule.
Edit #2:
Min/max rates for tomorrow added, shell script and Lua script updated.