Mercurial > ~darius > hgwebdir.cgi > pw2log
annotate pw2log.py @ 1:7edf54ec37f2
Improve logging.
author | Daniel O'Connor <darius@dons.net.au> |
---|---|
date | Tue, 18 Feb 2020 13:18:25 +1030 |
parents | a5a196b3ba63 |
children | 393a879db9eb |
rev | line source |
---|---|
0
a5a196b3ba63
Initial version of powerwall logger
Daniel O'Connor <darius@dons.net.au>
parents:
diff
changeset
|
1 #!/usr/bin/env python3 |
a5a196b3ba63
Initial version of powerwall logger
Daniel O'Connor <darius@dons.net.au>
parents:
diff
changeset
|
2 |
a5a196b3ba63
Initial version of powerwall logger
Daniel O'Connor <darius@dons.net.au>
parents:
diff
changeset
|
3 import configparser |
a5a196b3ba63
Initial version of powerwall logger
Daniel O'Connor <darius@dons.net.au>
parents:
diff
changeset
|
4 import daemon |
a5a196b3ba63
Initial version of powerwall logger
Daniel O'Connor <darius@dons.net.au>
parents:
diff
changeset
|
5 import daemon.pidfile |
a5a196b3ba63
Initial version of powerwall logger
Daniel O'Connor <darius@dons.net.au>
parents:
diff
changeset
|
6 import datetime |
a5a196b3ba63
Initial version of powerwall logger
Daniel O'Connor <darius@dons.net.au>
parents:
diff
changeset
|
7 import logging |
a5a196b3ba63
Initial version of powerwall logger
Daniel O'Connor <darius@dons.net.au>
parents:
diff
changeset
|
8 from logging.handlers import RotatingFileHandler |
a5a196b3ba63
Initial version of powerwall logger
Daniel O'Connor <darius@dons.net.au>
parents:
diff
changeset
|
9 import psycopg2 |
a5a196b3ba63
Initial version of powerwall logger
Daniel O'Connor <darius@dons.net.au>
parents:
diff
changeset
|
10 import requests |
a5a196b3ba63
Initial version of powerwall logger
Daniel O'Connor <darius@dons.net.au>
parents:
diff
changeset
|
11 import sys |
a5a196b3ba63
Initial version of powerwall logger
Daniel O'Connor <darius@dons.net.au>
parents:
diff
changeset
|
12 import tesla_powerwall # https://github.com/jrester/tesla_powerwall |
a5a196b3ba63
Initial version of powerwall logger
Daniel O'Connor <darius@dons.net.au>
parents:
diff
changeset
|
13 import time |
a5a196b3ba63
Initial version of powerwall logger
Daniel O'Connor <darius@dons.net.au>
parents:
diff
changeset
|
14 |
a5a196b3ba63
Initial version of powerwall logger
Daniel O'Connor <darius@dons.net.au>
parents:
diff
changeset
|
15 # Standard in 3.7.. |
a5a196b3ba63
Initial version of powerwall logger
Daniel O'Connor <darius@dons.net.au>
parents:
diff
changeset
|
16 class NullContextManager(object): |
a5a196b3ba63
Initial version of powerwall logger
Daniel O'Connor <darius@dons.net.au>
parents:
diff
changeset
|
17 def __init__(self, dummy_resource=None): |
a5a196b3ba63
Initial version of powerwall logger
Daniel O'Connor <darius@dons.net.au>
parents:
diff
changeset
|
18 self.dummy_resource = dummy_resource |
a5a196b3ba63
Initial version of powerwall logger
Daniel O'Connor <darius@dons.net.au>
parents:
diff
changeset
|
19 def __enter__(self): |
a5a196b3ba63
Initial version of powerwall logger
Daniel O'Connor <darius@dons.net.au>
parents:
diff
changeset
|
20 return self.dummy_resource |
a5a196b3ba63
Initial version of powerwall logger
Daniel O'Connor <darius@dons.net.au>
parents:
diff
changeset
|
21 def __exit__(self, *args): |
a5a196b3ba63
Initial version of powerwall logger
Daniel O'Connor <darius@dons.net.au>
parents:
diff
changeset
|
22 pass |
a5a196b3ba63
Initial version of powerwall logger
Daniel O'Connor <darius@dons.net.au>
parents:
diff
changeset
|
23 |
a5a196b3ba63
Initial version of powerwall logger
Daniel O'Connor <darius@dons.net.au>
parents:
diff
changeset
|
24 # Otherwise it's very noisy |
a5a196b3ba63
Initial version of powerwall logger
Daniel O'Connor <darius@dons.net.au>
parents:
diff
changeset
|
25 logging.getLogger('tesla_powerwall').setLevel(logging.WARN) |
a5a196b3ba63
Initial version of powerwall logger
Daniel O'Connor <darius@dons.net.au>
parents:
diff
changeset
|
26 |
a5a196b3ba63
Initial version of powerwall logger
Daniel O'Connor <darius@dons.net.au>
parents:
diff
changeset
|
27 def main(): |
a5a196b3ba63
Initial version of powerwall logger
Daniel O'Connor <darius@dons.net.au>
parents:
diff
changeset
|
28 if len(sys.argv) != 2: |
a5a196b3ba63
Initial version of powerwall logger
Daniel O'Connor <darius@dons.net.au>
parents:
diff
changeset
|
29 print('Bad usage', file = sys.stderr) |
a5a196b3ba63
Initial version of powerwall logger
Daniel O'Connor <darius@dons.net.au>
parents:
diff
changeset
|
30 print('\t%s conf.ini' % (sys.argv[0]), file = sys.stderr) |
a5a196b3ba63
Initial version of powerwall logger
Daniel O'Connor <darius@dons.net.au>
parents:
diff
changeset
|
31 sys.exit(1) |
a5a196b3ba63
Initial version of powerwall logger
Daniel O'Connor <darius@dons.net.au>
parents:
diff
changeset
|
32 |
a5a196b3ba63
Initial version of powerwall logger
Daniel O'Connor <darius@dons.net.au>
parents:
diff
changeset
|
33 cp = configparser.ConfigParser() |
a5a196b3ba63
Initial version of powerwall logger
Daniel O'Connor <darius@dons.net.au>
parents:
diff
changeset
|
34 cp.read(sys.argv[1]) |
a5a196b3ba63
Initial version of powerwall logger
Daniel O'Connor <darius@dons.net.au>
parents:
diff
changeset
|
35 if not cp.has_section('db'): |
a5a196b3ba63
Initial version of powerwall logger
Daniel O'Connor <darius@dons.net.au>
parents:
diff
changeset
|
36 print('Config file missing db section', file = sys.stderr) |
a5a196b3ba63
Initial version of powerwall logger
Daniel O'Connor <darius@dons.net.au>
parents:
diff
changeset
|
37 sys.exit(1) |
a5a196b3ba63
Initial version of powerwall logger
Daniel O'Connor <darius@dons.net.au>
parents:
diff
changeset
|
38 if not cp.has_option('db', 'dsn'): |
a5a196b3ba63
Initial version of powerwall logger
Daniel O'Connor <darius@dons.net.au>
parents:
diff
changeset
|
39 print('db section missing dsn parameter', file = sys.stderr) |
a5a196b3ba63
Initial version of powerwall logger
Daniel O'Connor <darius@dons.net.au>
parents:
diff
changeset
|
40 sys.exit(1) |
a5a196b3ba63
Initial version of powerwall logger
Daniel O'Connor <darius@dons.net.au>
parents:
diff
changeset
|
41 if not cp.has_option('db', 'logtime'): |
a5a196b3ba63
Initial version of powerwall logger
Daniel O'Connor <darius@dons.net.au>
parents:
diff
changeset
|
42 print('db section missing logtime parameter', file = sys.stderr) |
a5a196b3ba63
Initial version of powerwall logger
Daniel O'Connor <darius@dons.net.au>
parents:
diff
changeset
|
43 sys.exit(1) |
a5a196b3ba63
Initial version of powerwall logger
Daniel O'Connor <darius@dons.net.au>
parents:
diff
changeset
|
44 |
a5a196b3ba63
Initial version of powerwall logger
Daniel O'Connor <darius@dons.net.au>
parents:
diff
changeset
|
45 if not cp.has_section('pw'): |
a5a196b3ba63
Initial version of powerwall logger
Daniel O'Connor <darius@dons.net.au>
parents:
diff
changeset
|
46 print('Config file missing pw section', file = sys.stderr) |
a5a196b3ba63
Initial version of powerwall logger
Daniel O'Connor <darius@dons.net.au>
parents:
diff
changeset
|
47 sys.exit(1) |
a5a196b3ba63
Initial version of powerwall logger
Daniel O'Connor <darius@dons.net.au>
parents:
diff
changeset
|
48 if not cp.has_option('pw', 'ip'): |
a5a196b3ba63
Initial version of powerwall logger
Daniel O'Connor <darius@dons.net.au>
parents:
diff
changeset
|
49 print('pw section missing ip parameter', file = sys.stderr) |
a5a196b3ba63
Initial version of powerwall logger
Daniel O'Connor <darius@dons.net.au>
parents:
diff
changeset
|
50 sys.exit(1) |
a5a196b3ba63
Initial version of powerwall logger
Daniel O'Connor <darius@dons.net.au>
parents:
diff
changeset
|
51 |
a5a196b3ba63
Initial version of powerwall logger
Daniel O'Connor <darius@dons.net.au>
parents:
diff
changeset
|
52 if cp.has_option('pw2log', 'logfile'): |
a5a196b3ba63
Initial version of powerwall logger
Daniel O'Connor <darius@dons.net.au>
parents:
diff
changeset
|
53 logfile = cp.get('pw2log', 'logfile') |
a5a196b3ba63
Initial version of powerwall logger
Daniel O'Connor <darius@dons.net.au>
parents:
diff
changeset
|
54 else: |
a5a196b3ba63
Initial version of powerwall logger
Daniel O'Connor <darius@dons.net.au>
parents:
diff
changeset
|
55 logfile = None |
a5a196b3ba63
Initial version of powerwall logger
Daniel O'Connor <darius@dons.net.au>
parents:
diff
changeset
|
56 if cp.has_option('pw2log', 'pidfile'): |
a5a196b3ba63
Initial version of powerwall logger
Daniel O'Connor <darius@dons.net.au>
parents:
diff
changeset
|
57 pidfile = cp.get('pw2log', 'pidfile') |
a5a196b3ba63
Initial version of powerwall logger
Daniel O'Connor <darius@dons.net.au>
parents:
diff
changeset
|
58 else: |
a5a196b3ba63
Initial version of powerwall logger
Daniel O'Connor <darius@dons.net.au>
parents:
diff
changeset
|
59 pidfile = None |
a5a196b3ba63
Initial version of powerwall logger
Daniel O'Connor <darius@dons.net.au>
parents:
diff
changeset
|
60 |
a5a196b3ba63
Initial version of powerwall logger
Daniel O'Connor <darius@dons.net.au>
parents:
diff
changeset
|
61 global logger |
a5a196b3ba63
Initial version of powerwall logger
Daniel O'Connor <darius@dons.net.au>
parents:
diff
changeset
|
62 logger = logging.getLogger('pw2log') |
a5a196b3ba63
Initial version of powerwall logger
Daniel O'Connor <darius@dons.net.au>
parents:
diff
changeset
|
63 logger.setLevel(logging.WARN) |
a5a196b3ba63
Initial version of powerwall logger
Daniel O'Connor <darius@dons.net.au>
parents:
diff
changeset
|
64 fmt = logging.Formatter('%(asctime)s: %(message)s', datefmt = '%Y/%m/%d %H:%M:%S') |
a5a196b3ba63
Initial version of powerwall logger
Daniel O'Connor <darius@dons.net.au>
parents:
diff
changeset
|
65 if logfile == None: |
a5a196b3ba63
Initial version of powerwall logger
Daniel O'Connor <darius@dons.net.au>
parents:
diff
changeset
|
66 ch = logging.StreamHandler() |
a5a196b3ba63
Initial version of powerwall logger
Daniel O'Connor <darius@dons.net.au>
parents:
diff
changeset
|
67 ch.setFormatter(fmt) |
a5a196b3ba63
Initial version of powerwall logger
Daniel O'Connor <darius@dons.net.au>
parents:
diff
changeset
|
68 logger.addHandler(ch) |
1 | 69 keepfh = None |
0
a5a196b3ba63
Initial version of powerwall logger
Daniel O'Connor <darius@dons.net.au>
parents:
diff
changeset
|
70 else: |
a5a196b3ba63
Initial version of powerwall logger
Daniel O'Connor <darius@dons.net.au>
parents:
diff
changeset
|
71 fh = RotatingFileHandler(logfile, maxBytes = 2000, backupCount = 10) |
a5a196b3ba63
Initial version of powerwall logger
Daniel O'Connor <darius@dons.net.au>
parents:
diff
changeset
|
72 fh.setFormatter(fmt) |
a5a196b3ba63
Initial version of powerwall logger
Daniel O'Connor <darius@dons.net.au>
parents:
diff
changeset
|
73 logger.addHandler(fh) |
1 | 74 keepfhs = [fh.stream.fileno()] # XXX: gross |
0
a5a196b3ba63
Initial version of powerwall logger
Daniel O'Connor <darius@dons.net.au>
parents:
diff
changeset
|
75 |
a5a196b3ba63
Initial version of powerwall logger
Daniel O'Connor <darius@dons.net.au>
parents:
diff
changeset
|
76 if pidfile == None: |
a5a196b3ba63
Initial version of powerwall logger
Daniel O'Connor <darius@dons.net.au>
parents:
diff
changeset
|
77 ctx = NullContextManager() |
a5a196b3ba63
Initial version of powerwall logger
Daniel O'Connor <darius@dons.net.au>
parents:
diff
changeset
|
78 else: |
1 | 79 try: |
80 #fh = open('/tmp/pw2errs.log', 'a') | |
81 fh = None | |
82 ctx = daemon.DaemonContext(pidfile = daemon.pidfile.PIDLockFile(pidfile), stdout = fh, stderr = fh, files_preserve = keepfhs) | |
83 except Exception as e: | |
84 logger.critical('Unable to get daemon context') | |
0
a5a196b3ba63
Initial version of powerwall logger
Daniel O'Connor <darius@dons.net.au>
parents:
diff
changeset
|
85 |
1 | 86 try: |
87 with ctx: | |
88 logger.critical('Starting') | |
89 try: | |
90 collectdata(cp.get('pw', 'ip'), cp.get('db', 'dsn'), cp.getint('db', 'logtime')) | |
91 except Exception as e: | |
92 logger.critical('Unable to collect data: ' + str(e)) | |
93 except Exception as e: | |
94 logger.critical('Unable to enter daemon context: ' + str(e)) | |
0
a5a196b3ba63
Initial version of powerwall logger
Daniel O'Connor <darius@dons.net.au>
parents:
diff
changeset
|
95 |
a5a196b3ba63
Initial version of powerwall logger
Daniel O'Connor <darius@dons.net.au>
parents:
diff
changeset
|
96 def collectdata(pwip, dsn, logtime): |
a5a196b3ba63
Initial version of powerwall logger
Daniel O'Connor <darius@dons.net.au>
parents:
diff
changeset
|
97 dbh = psycopg2.connect(dsn) |
a5a196b3ba63
Initial version of powerwall logger
Daniel O'Connor <darius@dons.net.au>
parents:
diff
changeset
|
98 cur = dbh.cursor() |
a5a196b3ba63
Initial version of powerwall logger
Daniel O'Connor <darius@dons.net.au>
parents:
diff
changeset
|
99 |
a5a196b3ba63
Initial version of powerwall logger
Daniel O'Connor <darius@dons.net.au>
parents:
diff
changeset
|
100 pw = tesla_powerwall.PowerWall(pwip) |
a5a196b3ba63
Initial version of powerwall logger
Daniel O'Connor <darius@dons.net.au>
parents:
diff
changeset
|
101 |
a5a196b3ba63
Initial version of powerwall logger
Daniel O'Connor <darius@dons.net.au>
parents:
diff
changeset
|
102 while True: |
a5a196b3ba63
Initial version of powerwall logger
Daniel O'Connor <darius@dons.net.au>
parents:
diff
changeset
|
103 try: |
a5a196b3ba63
Initial version of powerwall logger
Daniel O'Connor <darius@dons.net.au>
parents:
diff
changeset
|
104 # As per.. https://github.com/vloschiavo/powerwall2 |
a5a196b3ba63
Initial version of powerwall logger
Daniel O'Connor <darius@dons.net.au>
parents:
diff
changeset
|
105 # | | Load | Grid | Battery | Solar | |
a5a196b3ba63
Initial version of powerwall logger
Daniel O'Connor <darius@dons.net.au>
parents:
diff
changeset
|
106 # |==========+==============+===================+======================+==================| |
a5a196b3ba63
Initial version of powerwall logger
Daniel O'Connor <darius@dons.net.au>
parents:
diff
changeset
|
107 # | Positive | Supply house | Drawing from grid | Drawing from battery | Solar generation | |
a5a196b3ba63
Initial version of powerwall logger
Daniel O'Connor <darius@dons.net.au>
parents:
diff
changeset
|
108 # | Negative | n/a | Feeding grid | Charging battery | n/a | |
a5a196b3ba63
Initial version of powerwall logger
Daniel O'Connor <darius@dons.net.au>
parents:
diff
changeset
|
109 # |
a5a196b3ba63
Initial version of powerwall logger
Daniel O'Connor <darius@dons.net.au>
parents:
diff
changeset
|
110 grid = pw.grid |
a5a196b3ba63
Initial version of powerwall logger
Daniel O'Connor <darius@dons.net.au>
parents:
diff
changeset
|
111 load = pw.load |
a5a196b3ba63
Initial version of powerwall logger
Daniel O'Connor <darius@dons.net.au>
parents:
diff
changeset
|
112 battery = pw.battery |
a5a196b3ba63
Initial version of powerwall logger
Daniel O'Connor <darius@dons.net.au>
parents:
diff
changeset
|
113 solar = pw.solar |
a5a196b3ba63
Initial version of powerwall logger
Daniel O'Connor <darius@dons.net.au>
parents:
diff
changeset
|
114 charge = pw.charge |
a5a196b3ba63
Initial version of powerwall logger
Daniel O'Connor <darius@dons.net.au>
parents:
diff
changeset
|
115 except requests.ConnectionError as e: |
a5a196b3ba63
Initial version of powerwall logger
Daniel O'Connor <darius@dons.net.au>
parents:
diff
changeset
|
116 logger.error('Error communicating with Powerwall: ' + str(e)) |
a5a196b3ba63
Initial version of powerwall logger
Daniel O'Connor <darius@dons.net.au>
parents:
diff
changeset
|
117 time.sleep(300) |
a5a196b3ba63
Initial version of powerwall logger
Daniel O'Connor <darius@dons.net.au>
parents:
diff
changeset
|
118 continue |
a5a196b3ba63
Initial version of powerwall logger
Daniel O'Connor <darius@dons.net.au>
parents:
diff
changeset
|
119 try: |
a5a196b3ba63
Initial version of powerwall logger
Daniel O'Connor <darius@dons.net.au>
parents:
diff
changeset
|
120 cur.execute('INSERT INTO pw2 (date, grid_voltage, grid_freq, grid_power, load_power, battery_power, battery_charge, solar_power) VALUES (%s, %s, %s, %s, %s, %s, %s, %s)', |
a5a196b3ba63
Initial version of powerwall logger
Daniel O'Connor <darius@dons.net.au>
parents:
diff
changeset
|
121 (datetime.datetime.now(), grid.instant_average_voltage, grid.frequency, grid.instant_power, load.instant_power, battery.instant_power, charge, solar.instant_power)) |
a5a196b3ba63
Initial version of powerwall logger
Daniel O'Connor <darius@dons.net.au>
parents:
diff
changeset
|
122 dbh.commit() |
a5a196b3ba63
Initial version of powerwall logger
Daniel O'Connor <darius@dons.net.au>
parents:
diff
changeset
|
123 except psycopg2.OperationalError as e: |
a5a196b3ba63
Initial version of powerwall logger
Daniel O'Connor <darius@dons.net.au>
parents:
diff
changeset
|
124 logger.error('Reconnecting after database error:' + str(e)) |
a5a196b3ba63
Initial version of powerwall logger
Daniel O'Connor <darius@dons.net.au>
parents:
diff
changeset
|
125 time.sleep(60) |
a5a196b3ba63
Initial version of powerwall logger
Daniel O'Connor <darius@dons.net.au>
parents:
diff
changeset
|
126 dbh = psycopg2.connect(dsn) |
a5a196b3ba63
Initial version of powerwall logger
Daniel O'Connor <darius@dons.net.au>
parents:
diff
changeset
|
127 cur = dbh.cursor() |
a5a196b3ba63
Initial version of powerwall logger
Daniel O'Connor <darius@dons.net.au>
parents:
diff
changeset
|
128 continue |
a5a196b3ba63
Initial version of powerwall logger
Daniel O'Connor <darius@dons.net.au>
parents:
diff
changeset
|
129 |
a5a196b3ba63
Initial version of powerwall logger
Daniel O'Connor <darius@dons.net.au>
parents:
diff
changeset
|
130 time.sleep(logtime) |
a5a196b3ba63
Initial version of powerwall logger
Daniel O'Connor <darius@dons.net.au>
parents:
diff
changeset
|
131 |
a5a196b3ba63
Initial version of powerwall logger
Daniel O'Connor <darius@dons.net.au>
parents:
diff
changeset
|
132 def createdb(dbh): |
a5a196b3ba63
Initial version of powerwall logger
Daniel O'Connor <darius@dons.net.au>
parents:
diff
changeset
|
133 cur = dbh.cursor() |
a5a196b3ba63
Initial version of powerwall logger
Daniel O'Connor <darius@dons.net.au>
parents:
diff
changeset
|
134 cur.execute(''' |
a5a196b3ba63
Initial version of powerwall logger
Daniel O'Connor <darius@dons.net.au>
parents:
diff
changeset
|
135 CREATE TABLE pw2 ( |
a5a196b3ba63
Initial version of powerwall logger
Daniel O'Connor <darius@dons.net.au>
parents:
diff
changeset
|
136 date TIMESTAMP WITH TIME ZONE PRIMARY KEY, |
a5a196b3ba63
Initial version of powerwall logger
Daniel O'Connor <darius@dons.net.au>
parents:
diff
changeset
|
137 grid_voltage REAL, |
a5a196b3ba63
Initial version of powerwall logger
Daniel O'Connor <darius@dons.net.au>
parents:
diff
changeset
|
138 grid_freq REAL, |
a5a196b3ba63
Initial version of powerwall logger
Daniel O'Connor <darius@dons.net.au>
parents:
diff
changeset
|
139 grid_power REAL, |
a5a196b3ba63
Initial version of powerwall logger
Daniel O'Connor <darius@dons.net.au>
parents:
diff
changeset
|
140 load_power REAL, |
a5a196b3ba63
Initial version of powerwall logger
Daniel O'Connor <darius@dons.net.au>
parents:
diff
changeset
|
141 battery_power REAL, |
a5a196b3ba63
Initial version of powerwall logger
Daniel O'Connor <darius@dons.net.au>
parents:
diff
changeset
|
142 battery_charge REAL, |
a5a196b3ba63
Initial version of powerwall logger
Daniel O'Connor <darius@dons.net.au>
parents:
diff
changeset
|
143 solar_power REAL |
a5a196b3ba63
Initial version of powerwall logger
Daniel O'Connor <darius@dons.net.au>
parents:
diff
changeset
|
144 ); |
a5a196b3ba63
Initial version of powerwall logger
Daniel O'Connor <darius@dons.net.au>
parents:
diff
changeset
|
145 ''') |
a5a196b3ba63
Initial version of powerwall logger
Daniel O'Connor <darius@dons.net.au>
parents:
diff
changeset
|
146 cur.execute(''' |
a5a196b3ba63
Initial version of powerwall logger
Daniel O'Connor <darius@dons.net.au>
parents:
diff
changeset
|
147 CREATE INDEX IF NOT EXISTS pw2_date_brin_idx ON pw2 USING brin (date); |
a5a196b3ba63
Initial version of powerwall logger
Daniel O'Connor <darius@dons.net.au>
parents:
diff
changeset
|
148 ''') |
a5a196b3ba63
Initial version of powerwall logger
Daniel O'Connor <darius@dons.net.au>
parents:
diff
changeset
|
149 |
a5a196b3ba63
Initial version of powerwall logger
Daniel O'Connor <darius@dons.net.au>
parents:
diff
changeset
|
150 if __name__ == '__main__': |
a5a196b3ba63
Initial version of powerwall logger
Daniel O'Connor <darius@dons.net.au>
parents:
diff
changeset
|
151 main() |