A module for interacting w/ the Enphase Enjoy solar controller. It currently has a simple program for logging data, such as production and per panel data.
Nelze vybrat více než 25 témat Téma musí začínat písmenem nebo číslem, může obsahovat pomlčky („-“) a může být dlouhé až 35 znaků.
 
 

164 řádky
3.2 KiB

  1. #!/usr/bin/env python
  2. from requests.auth import HTTPDigestAuth
  3. import copy
  4. import threading
  5. import json
  6. import requests
  7. import sys
  8. import time
  9. import urlparse
  10. with open('creds.txt') as fp:
  11. ip, username, password = fp.readline().split()
  12. def fetch_envoy_data(envoy_ip, path, username, password):
  13. url = urlparse.urlunsplit(('http', envoy_ip, path, '', ''))
  14. resp = requests.get(url, auth=HTTPDigestAuth(username, password))
  15. return json.loads(resp.text)
  16. def myenvoy(x):
  17. while True:
  18. try:
  19. return fetch_envoy_data(ip, x, username, password)
  20. except ValueError:
  21. time.sleep(5)
  22. loglock = threading.Lock()
  23. def logdata(hdr, obj):
  24. with loglock:
  25. print '%s %.3f %s' % (hdr, time.time(), json.dumps(obj))
  26. sys.stdout.flush()
  27. if False:
  28. data = myenvoy('/api/v1/production/inverters/')
  29. print(repr(data))
  30. import pprint
  31. pprint.pprint([ x[u'lastReportWatts'] for x in data ])
  32. print sum([ int(x[u'lastReportWatts']) for x in data ], 0)
  33. lrdates = [ x['lastReportDate'] for x in data ]
  34. lrdates.sort()
  35. pprint.pprint([ lrdates[x] - lrdates[x - 1] for x in xrange(1, len(lrdates)) ])
  36. def shortprodcmp(a, b):
  37. if b is None or a is None:
  38. return cmp(a, b)
  39. a = copy.deepcopy(a)
  40. b = copy.deepcopy(b)
  41. del a['eim']['readingTime']
  42. del b['eim']['readingTime']
  43. return cmp(a, b)
  44. def thread_production():
  45. global doexit
  46. lastfulllog = 0
  47. lastdata = None
  48. s = time.time()
  49. while not doexit:
  50. r = myenvoy('/production.json?details=1')
  51. # full, every 5 minutes
  52. if time.time() > lastfulllog + 5*60:
  53. logdata('production', r)
  54. lastfulllog = time.time()
  55. # remap by type
  56. tmap = { x['type']: x for x in r['production'] }
  57. # take what fields we want
  58. eim = tmap['eim']
  59. eimfields = [ 'readingTime', 'wNow', 'whLifetime', ]
  60. data = {
  61. 'inverters': tmap['inverters'],
  62. 'eim': { k: eim[k] for k in eimfields },
  63. }
  64. # log if it's different
  65. if shortprodcmp(data, lastdata) != 0:
  66. logdata('shortprod', data)
  67. lastdata = data
  68. s += 10
  69. e = time.time()
  70. if s > e:
  71. time.sleep(s - time.time())
  72. else:
  73. # catch up s to e:
  74. s += ((e - s) // 10) * 10
  75. def thread_inventory():
  76. global doexit
  77. lastr = None
  78. lastlog = 0
  79. while not doexit:
  80. r = myenvoy('/inventory.json')
  81. # if it changes, or every 24hrs
  82. if lastr != r or time.time() > lastlog + 24*60*60:
  83. logdata('inventory', r)
  84. lastlog = time.time()
  85. lastr = r
  86. time.sleep(60*60)
  87. def thread_panels():
  88. global doexit
  89. lastr = None
  90. while not doexit:
  91. r = myenvoy('/api/v1/production/inverters/')
  92. if lastr != r:
  93. logdata('panel', r)
  94. lastr = r
  95. #reps = [ x['lastReportDate'] for x in r ]
  96. #reps.sort()
  97. #print '\n'.join(time.ctime(x) for x in reps)
  98. try:
  99. lastrepdate = max(x['lastReportDate'] for x in r)
  100. waittotime = lastrepdate + 300 + 10
  101. except ValueError:
  102. waittotime = 0
  103. curtime = time.time()
  104. if waittotime < curtime:
  105. wait = 120 # 2 minutes
  106. else:
  107. wait = waittotime - curtime
  108. print 'debug waiting:', wait
  109. time.sleep(wait)
  110. if __name__ == '__main__':
  111. doexit = False
  112. threadfuns = [ x for x in dir() if x.startswith('thread_') ]
  113. threadobjs = { x: threading.Thread(target=globals()[x]) for x in threadfuns }
  114. for i in threadobjs.itervalues():
  115. i.setDaemon(True)
  116. i.start()
  117. while True:
  118. time.sleep(120)
  119. time.sleep(3)
  120. sys.exit()