|  |  | @@ -0,0 +1,156 @@ | 
		
	
		
			
			|  |  |  | #!/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()) | 
		
	
		
			
			|  |  |  | 
 | 
		
	
		
			
			|  |  |  | 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) | 
		
	
		
			
			|  |  |  | 
 | 
		
	
		
			
			|  |  |  | lastrepdate = max(x['lastReportDate'] for x in r) | 
		
	
		
			
			|  |  |  | 
 | 
		
	
		
			
			|  |  |  | waittotime = lastrepdate + 300 + 10 | 
		
	
		
			
			|  |  |  | 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() |