Skip to content

Commit

Permalink
Initial stage of rewrite.
Browse files Browse the repository at this point in the history
  • Loading branch information
mtnorthcott committed Aug 20, 2016
1 parent 5dcdae5 commit 8bef9df
Show file tree
Hide file tree
Showing 4 changed files with 219 additions and 35 deletions.
29 changes: 29 additions & 0 deletions interface.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
# Northcott Monitor
# Written by Matthew Northcott
# 20-08-2016
# Python 3.4.3

__author__ = "Matthew Northcott"


# IMPORTS
import RPi.GPIO
from importlib.machinery import SourceFileLoader


# GLOBALS
ON = GPIO.LOW
OFF = GPIO.HIGH
LEFT = "left"
CENTRE = "centre"
RIGHT = "right"

GPIO_OUT = { "buzzer": 22, "led_green": 9, "led_orange": 10, "led_red": 11 }
GPIO_IN = { "switch": 27 }

FILE_CONFIG = "E:/Programming/SpotpriceMonitor/spotprice.cfg"


# MAIN BODY
conf = SourceFileLoader("conf", FILE_CONFIG).load_module()

61 changes: 32 additions & 29 deletions lcd.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,16 +18,18 @@
LCD_D5 = 24
LCD_D6 = 23
LCD_D7 = 18
# LED_ON = 15
LED_ON = 15

# Device constants
LCD_WIDTH = 16 # Maximum characters per line
LCD_WIDTH = 20 # Maximum characters per line
LCD_CHR = True
LCD_CMD = False

# RAM addresses
LCD_LINE_1 = 0x80
LCD_LINE_2 = 0xC0
LCD_LINE_3 = 0x94
LCD_LINE_4 = 0xD4

# Timing constants
E_PULSE = 0.0005
Expand All @@ -43,52 +45,55 @@ def __init__(self):
GPIO.setup(LCD_D5, GPIO.OUT) # DB5
GPIO.setup(LCD_D6, GPIO.OUT) # DB6
GPIO.setup(LCD_D7, GPIO.OUT) # DB7
# GPIO.setup(LED_ON, GPIO.OUT) # Backlight enable

self._byte(0x33,LCD_CMD) # 110011 Initialise
self._byte(0x32,LCD_CMD) # 110010 Initialise
self._byte(0x06,LCD_CMD) # 000110 Cursor move direction
self._byte(0x0C,LCD_CMD) # 001100 Display On,Cursor Off, Blink Off
self._byte(0x28,LCD_CMD) # 101000 Data length, number of lines, font size
self._byte(0x01,LCD_CMD) # 000001 Clear display

GPIO.setup(LED_ON, GPIO.OUT) # Backlight enable
# Initialise display
self._byte(0x33, LCD_CMD) # 110011 Initialise
self._byte(0x32, LCD_CMD) # 110010 Initialise
self._byte(0x06, LCD_CMD) # 000110 Cursor move direction
self._byte(0x0C, LCD_CMD) # 001100 Display On,Cursor Off, Blink Off
self._byte(0x28, LCD_CMD) # 101000 Data length, number of lines, font size
self._byte(0x01, LCD_CMD) # 000001 Clear display
time.sleep(E_DELAY)


def _byte(self, bits, mode):
GPIO.output(LCD_RS, mode)
"""Send byte to data pins. Mode is true for character, false for a command """

GPIO.output(LCD_RS, mode) # RS

# High bits
GPIO.output(LCD_D4, False)
GPIO.output(LCD_D5, False)
GPIO.output(LCD_D6, False)
GPIO.output(LCD_D7, False)

if bits&0x10==0x10:
if bits & 0x10 == 0x10:
GPIO.output(LCD_D4, True)
if bits&0x20==0x20:
if bits & 0x20 == 0x20:
GPIO.output(LCD_D5, True)
if bits&0x40==0x40:
if bits & 0x40 == 0x40:
GPIO.output(LCD_D6, True)
if bits&0x80==0x80:
if bits & 0x80 == 0x80:
GPIO.output(LCD_D7, True)

# Toggle 'Enable' pin
self._toggle_enable()

# Low bits
GPIO.output(LCD_D4, False)
GPIO.output(LCD_D5, False)
GPIO.output(LCD_D6, False)
GPIO.output(LCD_D7, False)
if bits&0x01==0x01:

if bits & 0x01 == 0x01:
GPIO.output(LCD_D4, True)
if bits&0x02==0x02:
if bits & 0x02 == 0x02:
GPIO.output(LCD_D5, True)
if bits&0x04==0x04:
if bits & 0x04 == 0x04:
GPIO.output(LCD_D6, True)
if bits&0x08==0x08:
if bits & 0x08 == 0x08:
GPIO.output(LCD_D7, True)

# Toggle 'Enable' pin
self._toggle_enable()

def _toggle_enable(self):
Expand All @@ -98,20 +103,18 @@ def _toggle_enable(self):
GPIO.output(LCD_E, False)
time.sleep(E_DELAY)

def string_out(self, string, line=1, justify="left"):
def set_backlight(self, flag):
GPIO.output(LED_ON, flag)

def string_out(self, string, line=0, justify="left"):
if justify == "left":
string = string.ljust(LCD_WIDTH, " ")
elif justify == "centre":
string = string.center(LCD_WIDTH, " ")
elif justify == "right":
string = string.rjust(LCD_WIDTH, " ")

if line == 1:
line = LCD_LINE_1
else:
line = LCD_LINE_2

self._byte(line, LCD_CMD)
self._byte([LCD_LINE_1, LCD_LINE_2, LCD_LINE_3, LCD_LINE_4][line], LCD_CMD)

for c in string:
self._byte(ord(c), LCD_CHR)
153 changes: 153 additions & 0 deletions monitor.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,153 @@
# Northcott Monitor
# Written by Matthew Northcott
# 20-08-2016
# Python 3.4.3

__author__ = "Matthew Northcott"

# IMPORTS
import pickle
import datetime
import time
import holidays
import webpage
# import RPi.GPIO
from importlib.machinery import SourceFileLoader




# GLOBALS
WEBPAGE_SPOTPRICE = "http://electricityinfo.co.nz/comitFta/ftapage.main"
WEBPAGE_WEATHER = "http://192.168.0.150/wx_data/data.txt"

REGEX_SPOTPRICE = "(?<=ISL2201 \$)\d{1,4}\.\d{2}"
REGEX_SPOTPRICE_TIME = "(?<=Last updated at )[\d\/]{10} [\d\:]{8}"

# ON = GPIO.LOW
# OFF = GPIO.HIGH
LEFT = "left"
CENTRE = "centre"
RIGHT = "right"

GPIO_OUT = { "buzzer": 22, "led_green": 9, "led_orange": 10, "led_red": 11 }
GPIO_IN = { "switch": 27 }

FILE_CONFIG = "E:/Programming/SpotpriceMonitor/spotprice.cfg"


# MAIN BODY
conf = SourceFileLoader("conf", FILE_CONFIG).load_module()

class Monitor(object):
def __init__(self, url):
self.webpage = webpage.Webpage(url)
self._open_webpage(url)
self.update_values()

def _open_webpage(self, url):
success = self.webpage.open()


def update_values(self):
pass


class SpotpriceMonitor(Monitor):
def __init__(self):
super().__init__(WEBPAGE_SPOTPRICE)

def update_values(self):
self.update_spotprice()
self.update_network_charge()

def update_spotprice(self):
if not self.webpage.open(): return

self.spotprice = float(self.webpage.search(REGEX_SPOTPRICE))
self.time = datetime.datetime.strptime(self.webpage.search(REGEX_SPOTPRICE_TIME), "%d/%m/%Y %H:%M:%S")

def update_network_charge(self):
if self.spotprice == 0: return

weekday = datetime.datetime.weekday(self.time)
is_weekend = weekday > 4
is_holiday = self.time in holidays.NewZealand()
is_winter = 4 < self.time.month < 9

filename = conf.FILE_NETWORK_SUMMER
if is_winter:
filename = conf.FILE_NETWORK_WINTER
if is_weekend or is_holiday:
filename = conf.FILE_NETWORK_WEEKEND

with open(filename, 'r') as cfg:
data = [(datetime.time(int(h), int(m)), float(price)) for h, m, price in (line.split() for line in cfg)]

#
# data.sort(key=lambda x: x[0])
#
# network_charge = data[-1][1]
#
# for i in range(1, len(data)):
# if data[i-1][0] <= self.time.time() < data[i][0]:
# network_charge = data[i-1][1]
# break
#
# self.network_charge = (self.spotprice / 10.0) + network_charge + conf.PROVIDER_CHARGE


class WeatherMonitor(Monitor):
def __init__(self):
super().__init__(WEBPAGE_WEATHER)

def update_values(self):
weather_data = pickle.loads(self.webpage.response, encoding="latin1")

self.temperature = weather_data[2]
self.wind_dir = weather_data[3]
self.rainfall = weather_data[4]
self.wind_speed_gust = weather_data[5]
self.wind_speed_mean = weather_data[6]
self.wind_run = weather_data[7]
self.humidity = weather_data[8]
self.barometer = weather_data[9]
self.dewpoint = weather_data[10]

self.weather_data = weather_data


class MonitorInterface(object):
def __init__(self):
self.weather_mon = WeatherMonitor()
self.spotprice_mon = SpotpriceMonitor()


def mainloop(self, length):
""" Create a loop in which to perform tasks, updating weather information at every 11-minute point and the
spotprice every 5 minutes from start (possibly every 6 and 11 minute point)
"""

while True:
now = datetime.datetime.now()

if now.minute % 5 == 1:
self.spotprice_mon.update_values()

if now.minute % 10 == 1:
self.weather_mon.update_values()


def main():
x = SpotpriceMonitor()
print(x.spotprice)
print(x.time)


if __name__ == '__main__':
try:
main()
except KeyboardInterrupt:
pass
finally:
# RPi.GPIO.cleanup()
11 changes: 5 additions & 6 deletions webpage.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,10 @@
class Webpage(object):
def __init__(self, url):
self.url = url
self._response = None
self.response = None

def __str__(self):
return self._response
return str(self.response)

def __enter__(self):
self.open()
Expand All @@ -31,7 +31,6 @@ def __enter__(self):
def __exit__(self, type, value, traceback):
del self


def _open(self, request, q):
try:
response = urllib.request.urlopen(request).read()
Expand Down Expand Up @@ -59,15 +58,15 @@ def open(self, timeout=10.0):
if response is None:
return False

self._response = str(response)
self.response = response
return True

def search(self, regex_term):
try:
result = re.search(regex_term, self._response).group(0)
result = re.search(regex_term, str(self)).group(0)
except AttributeError:
return None
return result

def find_all(self, regex_term):
return re.findall(regex_term, self._response)
return re.findall(regex_term, str(self))

0 comments on commit 8bef9df

Please sign in to comment.