#!/usr/bin/python2.7 from PIL import Image from urllib import urlopen import sys import StringIO def gen_sig(x_start, y_start): # 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_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_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], ["4",sig_4], ["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(): # 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([gen_sig(38,y), 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(): # 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 month += 1 return monthly_totals def calculate_kWh_per_month(monthly_totals, y_axis_labels): monthly_kWh = [] for [month_num, month_y] in monthly_totals: # loop for each month 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(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 if len(sys.argv) == 2: year = sys.argv[1] else: sys.exit("Please feed me a 4-digit year as an argument.") bmp_url = 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 = detect_monthly_totals() #print "Monthly totals [month #, kWh]:" #print monthly_totals y_axis_labels = detect_y_axis_labels() #print "y-axis label heights:" #print y_axis_labels monthly_kWh = calculate_kWh_per_month(monthly_totals, y_axis_labels) for [month_num, month_kWh] in monthly_kWh: print "Month " + str(month_num) + ": " + str(month_kWh) + " kWh"