Created
January 9, 2020 21:38
-
-
Save zerbfra/45ddaeb533374b1a1ecfdcc5851a95ce to your computer and use it in GitHub Desktop.
Get data from Tesla powerwall and display it on a I2C LCD
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# -*- coding: utf-8 -*- | |
# Original code found at: | |
# https://gist.github.com/DenisFromHR/cc863375a6e19dce359d | |
""" | |
Compiled, mashed and generally mutilated 2014-2015 by Denis Pleic | |
Made available under GNU GENERAL PUBLIC LICENSE | |
# Modified Python I2C library for Raspberry Pi | |
# as found on http://www.recantha.co.uk/blog/?p=4849 | |
# Joined existing 'i2c_lib.py' and 'lcddriver.py' into a single library | |
# added bits and pieces from various sources | |
# By DenisFromHR (Denis Pleic) | |
# 2015-02-10, ver 0.1 | |
""" | |
# i2c bus (0 -- original Pi, 1 -- Rev 2 Pi) | |
I2CBUS = 0 | |
# LCD Address | |
ADDRESS = 0x27 | |
import smbus | |
from time import sleep | |
class i2c_device: | |
def __init__(self, addr, port=I2CBUS): | |
self.addr = addr | |
self.bus = smbus.SMBus(port) | |
# Write a single command | |
def write_cmd(self, cmd): | |
self.bus.write_byte(self.addr, cmd) | |
sleep(0.0001) | |
# Write a command and argument | |
def write_cmd_arg(self, cmd, data): | |
self.bus.write_byte_data(self.addr, cmd, data) | |
sleep(0.0001) | |
# Write a block of data | |
def write_block_data(self, cmd, data): | |
self.bus.write_block_data(self.addr, cmd, data) | |
sleep(0.0001) | |
# Read a single byte | |
def read(self): | |
return self.bus.read_byte(self.addr) | |
# Read | |
def read_data(self, cmd): | |
return self.bus.read_byte_data(self.addr, cmd) | |
# Read a block of data | |
def read_block_data(self, cmd): | |
return self.bus.read_block_data(self.addr, cmd) | |
# commands | |
LCD_CLEARDISPLAY = 0x01 | |
LCD_RETURNHOME = 0x02 | |
LCD_ENTRYMODESET = 0x04 | |
LCD_DISPLAYCONTROL = 0x08 | |
LCD_CURSORSHIFT = 0x10 | |
LCD_FUNCTIONSET = 0x20 | |
LCD_SETCGRAMADDR = 0x40 | |
LCD_SETDDRAMADDR = 0x80 | |
# flags for display entry mode | |
LCD_ENTRYRIGHT = 0x00 | |
LCD_ENTRYLEFT = 0x02 | |
LCD_ENTRYSHIFTINCREMENT = 0x01 | |
LCD_ENTRYSHIFTDECREMENT = 0x00 | |
# flags for display on/off control | |
LCD_DISPLAYON = 0x04 | |
LCD_DISPLAYOFF = 0x00 | |
LCD_CURSORON = 0x02 | |
LCD_CURSOROFF = 0x00 | |
LCD_BLINKON = 0x01 | |
LCD_BLINKOFF = 0x00 | |
# flags for display/cursor shift | |
LCD_DISPLAYMOVE = 0x08 | |
LCD_CURSORMOVE = 0x00 | |
LCD_MOVERIGHT = 0x04 | |
LCD_MOVELEFT = 0x00 | |
# flags for function set | |
LCD_8BITMODE = 0x10 | |
LCD_4BITMODE = 0x00 | |
LCD_2LINE = 0x08 | |
LCD_1LINE = 0x00 | |
LCD_5x10DOTS = 0x04 | |
LCD_5x8DOTS = 0x00 | |
# flags for backlight control | |
LCD_BACKLIGHT = 0x08 | |
LCD_NOBACKLIGHT = 0x00 | |
En = 0b00000100 # Enable bit | |
Rw = 0b00000010 # Read/Write bit | |
Rs = 0b00000001 # Register select bit | |
class lcd: | |
#initializes objects and lcd | |
def __init__(self): | |
self.lcd_device = i2c_device(ADDRESS) | |
self.lcd_write(0x03) | |
self.lcd_write(0x03) | |
self.lcd_write(0x03) | |
self.lcd_write(0x02) | |
self.lcd_write(LCD_FUNCTIONSET | LCD_2LINE | LCD_5x8DOTS | LCD_4BITMODE) | |
self.lcd_write(LCD_DISPLAYCONTROL | LCD_DISPLAYON) | |
self.lcd_write(LCD_CLEARDISPLAY) | |
self.lcd_write(LCD_ENTRYMODESET | LCD_ENTRYLEFT) | |
sleep(0.2) | |
# clocks EN to latch command | |
def lcd_strobe(self, data): | |
self.lcd_device.write_cmd(data | En | LCD_BACKLIGHT) | |
sleep(.0005) | |
self.lcd_device.write_cmd(((data & ~En) | LCD_BACKLIGHT)) | |
sleep(.0001) | |
def lcd_write_four_bits(self, data): | |
self.lcd_device.write_cmd(data | LCD_BACKLIGHT) | |
self.lcd_strobe(data) | |
# write a command to lcd | |
def lcd_write(self, cmd, mode=0): | |
self.lcd_write_four_bits(mode | (cmd & 0xF0)) | |
self.lcd_write_four_bits(mode | ((cmd << 4) & 0xF0)) | |
# write a character to lcd (or character rom) 0x09: backlight | RS=DR< | |
# works! | |
def lcd_write_char(self, charvalue, mode=1): | |
self.lcd_write_four_bits(mode | (charvalue & 0xF0)) | |
self.lcd_write_four_bits(mode | ((charvalue << 4) & 0xF0)) | |
# put string function with optional char positioning | |
def lcd_display_string(self, string, line=1, pos=0): | |
if line == 1: | |
pos_new = pos | |
elif line == 2: | |
pos_new = 0x40 + pos | |
elif line == 3: | |
pos_new = 0x14 + pos | |
elif line == 4: | |
pos_new = 0x54 + pos | |
self.lcd_write(0x80 + pos_new) | |
for char in string: | |
self.lcd_write(ord(char), Rs) | |
# clear lcd and set to home | |
def lcd_clear(self): | |
self.lcd_write(LCD_CLEARDISPLAY) | |
self.lcd_write(LCD_RETURNHOME) | |
# define backlight on/off (lcd.backlight(1); off= lcd.backlight(0) | |
def backlight(self, state): # for state, 1 = on, 0 = off | |
if state == 1: | |
self.lcd_device.write_cmd(LCD_BACKLIGHT) | |
elif state == 0: | |
self.lcd_device.write_cmd(LCD_NOBACKLIGHT) | |
# add custom characters (0 - 7) | |
def lcd_load_custom_chars(self, fontdata): | |
self.lcd_write(0x40); | |
for char in fontdata: | |
for line in char: | |
self.lcd_write_char(line) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/sh | |
script='/home/pi/tesla.py' | |
/usr/bin/python $script & |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import I2C_LCD_driver | |
import urllib, json, ssl | |
from time import * | |
from random import randrange | |
mylcd = I2C_LCD_driver.lcd() | |
url_aggregates = "http://192.168.1.130/api/meters/aggregates" | |
url_soe = "https://192.168.1.130/api/system_status/soe" | |
ctx = ssl.create_default_context() | |
ctx.check_hostname = False | |
ctx.verify_mode = ssl.CERT_NONE | |
def wait_for_internet_connection(): | |
while True: | |
try: | |
response = urllib.urlopen(url_soe, context = ctx) | |
return | |
except: | |
pass | |
sleep(20) | |
def main(): | |
while True: | |
try: | |
aggregates_res = urllib.urlopen(url_aggregates, context = ctx) | |
data = json.loads(aggregates_res.read()) | |
soe_res = urllib.urlopen(url_soe, context = ctx) | |
soe = json.loads(soe_res.read()) | |
mylcd.lcd_clear() | |
solar = round(data["solar"]["instant_total_current"]/1000, 3) | |
site = round(data["site"]["instant_power"]/1000, 3) | |
load = round(data["load"]["instant_power"]/1000, 3) | |
battery = round(data["battery"]["instant_power"]/1000, 3) | |
battery_perc = round(soe["percentage"], 2); | |
mylcd.lcd_display_string("Consumo: " + str(load) + " kW", 2) | |
mylcd.lcd_display_string("Solare: " + str(solar) + " kW", 1) | |
mylcd.lcd_display_string("Batteria: " + str(battery_perc) + "%", 3) | |
mylcd.lcd_display_string("Enel: " + str(site) + " kW", 4) | |
sleep(10) | |
except: | |
pass | |
wait_for_internet_connection() | |
main() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment