|
- #!/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()
|