#!/usr/bin/env python from requests.auth import HTTPDigestAuth import copy import threading import json import requests import sys import time import urlparse with open('creds.txt') as fp: ip, username, password = fp.readline().split() def fetch_envoy_data(envoy_ip, path, username, password): url = urlparse.urlunsplit(('http', envoy_ip, path, '', '')) resp = requests.get(url, auth=HTTPDigestAuth(username, password)) return json.loads(resp.text) def myenvoy(x): while True: try: return fetch_envoy_data(ip, x, username, password) except ValueError: time.sleep(5) loglock = threading.Lock() def logdata(hdr, obj): with loglock: print '%s %.3f %s' % (hdr, time.time(), json.dumps(obj)) sys.stdout.flush() if False: data = myenvoy('/api/v1/production/inverters/') print(repr(data)) import pprint pprint.pprint([ x[u'lastReportWatts'] for x in data ]) print sum([ int(x[u'lastReportWatts']) for x in data ], 0) lrdates = [ x['lastReportDate'] for x in data ] lrdates.sort() pprint.pprint([ lrdates[x] - lrdates[x - 1] for x in xrange(1, len(lrdates)) ]) def shortprodcmp(a, b): if b is None or a is None: return cmp(a, b) a = copy.deepcopy(a) b = copy.deepcopy(b) del a['eim']['readingTime'] del b['eim']['readingTime'] return cmp(a, b) def thread_production(): global doexit lastfulllog = 0 lastdata = None s = time.time() while not doexit: r = myenvoy('/production.json?details=1') # full, every 5 minutes if time.time() > lastfulllog + 5*60: logdata('production', r) lastfulllog = time.time() # remap by type tmap = { x['type']: x for x in r['production'] } # take what fields we want eim = tmap['eim'] eimfields = [ 'readingTime', 'wNow', 'whLifetime', ] data = { 'inverters': tmap['inverters'], 'eim': { k: eim[k] for k in eimfields }, } # log if it's different if shortprodcmp(data, lastdata) != 0: logdata('shortprod', data) lastdata = data s += 10 e = time.time() if s > e: time.sleep(s - time.time()) else: # catch up s to e: s += ((e - s) // 10) * 10 def thread_inventory(): global doexit lastr = None lastlog = 0 while not doexit: r = myenvoy('/inventory.json') # if it changes, or every 24hrs if lastr != r or time.time() > lastlog + 24*60*60: logdata('inventory', r) lastlog = time.time() lastr = r time.sleep(60*60) def thread_panels(): global doexit lastr = None while not doexit: r = myenvoy('/api/v1/production/inverters/') if lastr != r: logdata('panel', r) lastr = r #reps = [ x['lastReportDate'] for x in r ] #reps.sort() #print '\n'.join(time.ctime(x) for x in reps) try: lastrepdate = max(x['lastReportDate'] for x in r) waittotime = lastrepdate + 300 + 10 except ValueError: waittotime = 0 curtime = time.time() if waittotime < curtime: wait = 120 # 2 minutes else: wait = waittotime - curtime print 'debug waiting:', wait time.sleep(wait) if __name__ == '__main__': doexit = False threadfuns = [ x for x in dir() if x.startswith('thread_') ] threadobjs = { x: threading.Thread(target=globals()[x]) for x in threadfuns } for i in threadobjs.itervalues(): i.setDaemon(True) i.start() while True: time.sleep(120) time.sleep(3) sys.exit()