192 lines
10 KiB
Python
192 lines
10 KiB
Python
#!/usr/bin/env python
|
|
# -*- coding: utf-8 -*-
|
|
|
|
from PIL import Image
|
|
from urllib import urlopen
|
|
import datetime
|
|
import StringIO
|
|
import sys
|
|
import wx
|
|
import wx.grid
|
|
|
|
class SharpNinja:
|
|
def return_monthly_kWh_cuz_python_is_a_bitch(self):
|
|
return self.monthly_kWh
|
|
|
|
def __init__(self, year):
|
|
|
|
bmp_url = self.fetch_bmp_url(year)
|
|
bmp = StringIO.StringIO(urlopen(bmp_url).read())
|
|
|
|
try:
|
|
im = Image.open(bmp)
|
|
except IOError as errno:
|
|
sys.exit("Error opening image:\n" + str(errno))
|
|
|
|
pix = im.load() # pix is array containing pixel data
|
|
|
|
monthly_totals = self.detect_monthly_totals(pix)
|
|
#print "Monthly totals [month #, kWh]:"
|
|
|
|
y_axis_labels = self.detect_y_axis_labels(pix)
|
|
#print "y-axis label heights:"
|
|
#print y_axis_labels
|
|
|
|
self.monthly_kWh = self.calculate_kWh_per_month(monthly_totals, y_axis_labels)
|
|
|
|
output = ''
|
|
for [month_num, month_kWh] in self.monthly_kWh:
|
|
print "Month " + str(month_num) + ": " + str(month_kWh) + " kWh"
|
|
output += "Month " + str(month_num) + ": " + str(month_kWh) + " kWh\n"
|
|
|
|
def gen_sig(self, x_start, y_start, pix): # returns black pixels
|
|
sig_0 = [[2, 0], [3, 0], [4, 0], [5, 0], [1, 1], [2, 1], [3, 1], [4, 1], [5, 1], [6, 1], [0, 2], [1, 2], [2, 2], [5, 2], [6, 2], [7, 2], [0, 3], [1, 3], [6, 3], [7, 3], [0, 4], [1, 4], [6, 4], [7, 4], [0, 5], [1, 5], [6, 5], [7, 5], [0, 6], [1, 6], [6, 6], [7, 6], [0, 7], [1, 7], [6, 7], [7, 7], [0, 8], [1, 8], [6, 8], [7, 8], [0, 9], [1, 9], [6, 9], [7, 9], [0, 10], [1, 10], [6, 10], [7, 10], [0, 11], [1, 11], [6, 11], [7, 11], [0, 12], [1, 12], [2, 12], [5, 12], [6, 12], [7, 12], [1, 13], [2, 13], [3, 13], [4, 13], [5, 13], [6, 13], [2, 14], [3, 14], [4, 14], [5, 14]]
|
|
sig_1 = [[3, 0], [4, 0], [1, 1], [2, 1], [3, 1], [4, 1], [1, 2], [2, 2], [3, 2], [4, 2], [3, 3], [4, 3], [3, 4], [4, 4], [3, 5], [4, 5], [3, 6], [4, 6], [3, 7], [4, 7], [3, 8], [4, 8], [3, 9], [4, 9], [3, 10], [4, 10], [3, 11], [4, 11], [3, 12], [4, 12], [3, 13], [4, 13], [3, 14], [4, 14]]
|
|
sig_2 = [[2, 0], [3, 0], [4, 0], [5, 0], [1, 1], [2, 1], [3, 1], [4, 1], [5, 1], [6, 1], [0, 2], [1, 2], [2, 2], [5, 2], [6, 2], [7, 2], [0, 3], [1, 3], [6, 3], [7, 3], [0, 4], [1, 4], [6, 4], [7, 4], [5, 5], [6, 5], [7, 5], [4, 6], [5, 6], [6, 6], [4, 7], [5, 7], [3, 8], [4, 8], [5, 8], [2, 9], [3, 9], [4, 9], [2, 10], [3, 10], [1, 11], [2, 11], [3, 11], [0, 12], [1, 12], [2, 12], [0, 13], [1, 13], [2, 13], [3, 13], [4, 13], [5, 13], [6, 13], [7, 13], [0, 14], [1, 14], [2, 14], [3, 14], [4, 14], [5, 14], [6, 14], [7, 14]]
|
|
sig_3 = [[2, 0], [3, 0], [4, 0], [5, 0], [1, 1], [2, 1], [3, 1], [4, 1], [5, 1], [6, 1], [0, 2], [1, 2], [2, 2], [5, 2], [6, 2], [7, 2], [0, 3], [1, 3], [6, 3], [7, 3], [0, 4], [1, 4], [6, 4], [7, 4], [5, 5], [6, 5], [7, 5], [2, 6], [3, 6], [4, 6], [5, 6], [6, 6], [2, 7], [3, 7], [4, 7], [5, 7], [6, 7], [5, 8], [6, 8], [7, 8], [6, 9], [7, 9], [0, 10], [1, 10], [6, 10], [7, 10], [0, 11], [1, 11], [6, 11], [7, 11], [0, 12], [1, 12], [2, 12], [5, 12], [6, 12], [7, 12], [1, 13], [2, 13], [3, 13], [4, 13], [5, 13], [6, 13], [2, 14], [3, 14], [4, 14], [5, 14]]
|
|
sig_4 = [[5, 0], [6, 0], [5, 1], [6, 1], [4, 2], [5, 2], [6, 2], [4, 3], [5, 3], [6, 3], [3, 4], [4, 4], [5, 4], [6, 4], [3, 5], [4, 5], [5, 5], [6, 5], [2, 6], [3, 6], [4, 6], [5, 6], [6, 6], [2, 7], [3, 7], [5, 7], [6, 7], [1, 8], [2, 8], [3, 8], [5, 8], [6, 8], [1, 9], [2, 9], [5, 9], [6, 9], [0, 10], [1, 10], [2, 10], [3, 10], [4, 10], [5, 10], [6, 10], [7, 10], [0, 11], [1, 11], [2, 11], [3, 11], [4, 11], [5, 11], [6, 11], [7, 11], [5, 12], [6, 12], [5, 13], [6, 13], [5, 14], [6, 14]]
|
|
sig_5 = [[0, 0], [1, 0], [2, 0], [3, 0], [4, 0], [5, 0], [6, 0], [0, 1], [1, 1], [2, 1], [3, 1], [4, 1], [5, 1], [6, 1], [0, 2], [1, 2], [0, 3], [1, 3], [0, 4], [1, 4], [0, 5], [1, 5], [2, 5], [3, 5], [4, 5], [5, 5], [0, 6], [1, 6], [2, 6], [3, 6], [4, 6], [5, 6], [6, 6], [0, 7], [1, 7], [2, 7], [5, 7], [6, 7], [7, 7], [0, 8], [1, 8], [6, 8], [7, 8], [6, 9], [7, 9], [0, 10], [1, 10], [6, 10], [7, 10], [0, 11], [1, 11], [6, 11], [7, 11], [0, 12], [1, 12], [2, 12], [5, 12], [6, 12], [7, 12], [1, 13], [2, 13], [3, 13], [4, 13], [5, 13], [6, 13], [2, 14], [3, 14], [4, 14], [5, 14]]
|
|
sig_6 = [[2, 0], [3, 0], [4, 0], [5, 0], [1, 1], [2, 1], [3, 1], [4, 1], [5, 1], [6, 1], [0, 2], [1, 2], [2, 2], [5, 2], [6, 2], [7, 2], [0, 3], [1, 3], [6, 3], [7, 3], [0, 4], [1, 4], [6, 4], [7, 4], [0, 5], [1, 5], [2, 5], [3, 5], [4, 5], [5, 5], [0, 6], [1, 6], [2, 6], [3, 6], [4, 6], [5, 6], [6, 6], [0, 7], [1, 7], [2, 7], [5, 7], [6, 7], [7, 7], [0, 8], [1, 8], [6, 8], [7, 8], [0, 9], [1, 9], [6, 9], [7, 9], [0, 10], [1, 10], [6, 10], [7, 10], [0, 11], [1, 11], [6, 11], [7, 11], [0, 12], [1, 12], [2, 12], [5, 12], [6, 12], [7, 12], [1, 13], [2, 13], [3, 13], [4, 13], [5, 13], [6, 13], [2, 14], [3, 14], [4, 14], [5, 14]]
|
|
sig_8 = [[2, 0], [3, 0], [4, 0], [5, 0], [1, 1], [2, 1], [3, 1], [4, 1], [5, 1], [6, 1], [0, 2], [1, 2], [2, 2], [5, 2], [6, 2], [7, 2], [0, 3], [1, 3], [6, 3], [7, 3], [0, 4], [1, 4], [6, 4], [7, 4], [0, 5], [1, 5], [2, 5], [5, 5], [6, 5], [7, 5], [1, 6], [2, 6], [3, 6], [4, 6], [5, 6], [6, 6], [1, 7], [2, 7], [3, 7], [4, 7], [5, 7], [6, 7], [0, 8], [1, 8], [2, 8], [5, 8], [6, 8], [7, 8], [0, 9], [1, 9], [6, 9], [7, 9], [0, 10], [1, 10], [6, 10], [7, 10], [0, 11], [1, 11], [6, 11], [7, 11], [0, 12], [1, 12], [2, 12], [5, 12], [6, 12], [7, 12], [1, 13], [2, 13], [3, 13], [4, 13], [5, 13], [6, 13], [2, 14], [3, 14], [4, 14], [5, 14]]
|
|
char_width = 8
|
|
char_height = 15
|
|
space = 2
|
|
english_sig = ""
|
|
|
|
for digit_num in range(1,4):
|
|
this_sig = []
|
|
for check_y in range(y_start, y_start + char_height):
|
|
for check_x in range(x_start, x_start + char_width):
|
|
(curr_r, curr_g, curr_b) = pix[check_x,check_y]
|
|
if (curr_r, curr_g, curr_b) == (0,0,0): # if pixel is black
|
|
this_sig.append([check_x - x_start,check_y - y_start])
|
|
|
|
for ref_sig in (["0",sig_0], ["1",sig_1], ["2",sig_2], ["3",sig_3], ["4",sig_4], ["5",sig_5], ["6",sig_6], ["8",sig_8]): # array of known sigs added to arrays with element [0] being the English name of the number
|
|
if this_sig == ref_sig[1]:
|
|
english_sig += ref_sig[0]
|
|
|
|
x_start += char_width + space
|
|
return int(english_sig)
|
|
|
|
def detect_y_axis_labels(self, pix): # Detect the y_axis labels
|
|
x_offset = 38 # 38 is x coordinate of 1st character of y-axis labels
|
|
y_axis_labels = []
|
|
for y in (29, 75, 122, 168, 214, 260, 306): # y coordinates of y-axis kWh labels
|
|
# print "Captain, our sensors detected the number: " + gen_sig(38,y)
|
|
y_axis_labels.append([self.gen_sig(38,y,pix), y + 7]) # adding 7 to mark y-coord of cooresponding black line (always 7 pixels lower than start of text label)
|
|
return y_axis_labels
|
|
|
|
def detect_monthly_totals(self, pix): # Read the green bars and push to array
|
|
# static variables
|
|
image_dimy = 350 # height of image
|
|
(green_r, green_g, green_b) = (130,185,6) # RGB values of the deepest green value, used to detect bar heights
|
|
column_offset = 119 # starting x coord of 1st graph in bar graph
|
|
column_increment = 55 # spare between bars
|
|
|
|
month = 1
|
|
monthly_totals = []
|
|
check_x = column_offset
|
|
for check_x in range(column_offset, column_offset + (12 * column_increment), column_increment): # LOOP to check a year
|
|
for check_y in range(36,image_dimy): # LOOP to check a month
|
|
(curr_r, curr_g, curr_b) = pix[check_x,check_y]
|
|
if (curr_r, curr_g, curr_b) == (green_r, green_g, green_b):
|
|
# print "Month " + str(month) + " total: y=" + str(check_y)
|
|
monthly_totals.append([month,check_y])
|
|
break
|
|
if check_y == image_dimy - 1: # if a green bar was not discovered, insert 0 for the monthly total
|
|
monthly_totals.append([month,0])
|
|
month += 1
|
|
return monthly_totals
|
|
|
|
def calculate_kWh_per_month(self, monthly_totals, y_axis_labels):
|
|
monthly_kWh = []
|
|
for [month_num, month_y] in monthly_totals: # loop for each month
|
|
if month_y == 0:
|
|
monthly_kWh.append([month_num, 0])
|
|
continue
|
|
for x in range(0, len(y_axis_labels)): # x = [int kWh, int y-axis]:
|
|
if (y_axis_labels[x][1] > month_y and y_axis_labels[x-1][1] < month_y):
|
|
kWh_label_increment = y_axis_labels[x-1][0] - y_axis_labels[x][0]
|
|
y_label_increment = y_axis_labels[x][1] - y_axis_labels[x-1][1]
|
|
kWh_per_pixel = float(kWh_label_increment) / float(y_label_increment)
|
|
kWh_bonus = kWh_per_pixel * (y_axis_labels[x][1] - month_y)
|
|
kWh_this_month = kWh_bonus + float(y_axis_labels[x][0])
|
|
monthly_kWh.append([month_num, round(kWh_this_month,2)])
|
|
return monthly_kWh
|
|
|
|
def fetch_bmp_url(self, year):
|
|
url_base = "http://192.168.0.11/pc/"
|
|
|
|
filename_header = "graph_pc.bmp?"
|
|
filename_header_len = len(filename_header)
|
|
|
|
html = urlopen(url_base + "?befor_hs_y_pc.html+"+year).read()
|
|
html = html.split("\r")
|
|
for line in html:
|
|
pos_of_graphic = line.find(filename_header)
|
|
if pos_of_graphic == -1:
|
|
continue
|
|
bmp_filename = line[pos_of_graphic:pos_of_graphic+filename_header_len+14] # extract substring contai$
|
|
return url_base + bmp_filename
|
|
|
|
|
|
|
|
class MyFrame(wx.Frame):
|
|
def EvtComboBox(self, event):
|
|
year = event.GetString()
|
|
cached_record = self.output_cache.get(year)
|
|
if cached_record:
|
|
output = cached_record
|
|
else:
|
|
MySharpNinja = SharpNinja(year)
|
|
output = MySharpNinja.return_monthly_kWh_cuz_python_is_a_bitch()
|
|
for [month,kWh] in output:
|
|
self.grid.SetCellValue(month - 1, 0, str(kWh))
|
|
self.grid.SetReadOnly(month -1 , 0, True)
|
|
self.grid.SetCellAlignment(month - 1, 0, wx.ALIGN_RIGHT, wx.ALIGN_CENTER)
|
|
self.output_cache[year] = output
|
|
|
|
def __init__(self, parent, id, title):
|
|
wx.Frame.__init__(self, parent, id, title, wx.DefaultPosition, wx.Size(350, 600))
|
|
first_year = 2011
|
|
self.output_cache = {}
|
|
|
|
# Container
|
|
vbox = wx.BoxSizer(wx.VERTICAL)
|
|
|
|
# Label
|
|
label = wx.StaticText(self, label="年度を選んでください")
|
|
vbox.Add(label, 0, wx.ALIGN_CENTER | wx.ALL, 30)
|
|
|
|
# Dropdown
|
|
now = datetime.datetime.now()
|
|
cb_choices = []
|
|
for x in range(now.year, now.year - 7, -1): # display last 7 years
|
|
if x >= first_year:
|
|
cb_choices.append(str(x))
|
|
cb = wx.ComboBox(self, 1, choices=cb_choices)
|
|
wx.EVT_COMBOBOX(self, 1, self.EvtComboBox)
|
|
vbox.Add(cb, 0, wx.ALIGN_CENTER | wx.ALL, 10)
|
|
|
|
# Grid
|
|
self.grid = wx.grid.Grid(self)
|
|
self.grid.CreateGrid(12, 1)
|
|
self.grid.SetColLabelValue(0, "kWh")
|
|
self.grid.SetColMinimalAcceptableWidth(80)
|
|
for x in range(1,13):
|
|
self.grid.SetRowLabelValue(x - 1,str(x) + "月")
|
|
self.grid.Fit()
|
|
vbox.Add(self.grid, 0, wx.ALIGN_CENTER | wx.ALL, 10)
|
|
|
|
# Open the curtain
|
|
self.SetSizer(vbox)
|
|
|
|
class MyApp(wx.App):
|
|
def OnInit(self):
|
|
frame = MyFrame(None, -1, 'BM: 年間発電計算ツール')
|
|
frame.Show(True)
|
|
return True
|
|
|
|
app = MyApp(0)
|
|
app.MainLoop()
|