Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
107 changes: 107 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
# Created by .ignore support plugin (hsz.mobi)
### Python template
# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
*$py.class

# C extensions
*.so

# Distribution / packaging
.Python
build/
develop-eggs/
dist/
downloads/
eggs/
.eggs/
lib/
lib64/
parts/
sdist/
var/
wheels/
*.egg-info/
.installed.cfg
*.egg
MANIFEST

# PyInstaller
# Usually these files are written by a python script from a template
# before PyInstaller builds the exe, so as to inject date/other infos into it.
*.manifest
*.spec

# Installer logs
pip-log.txt
pip-delete-this-directory.txt

# Unit test / coverage reports
htmlcov/
.tox/
.coverage
.coverage.*
.cache
nosetests.xml
coverage.xml
*.cover
.hypothesis/
.pytest_cache/

# Translations
*.mo
*.pot

# Django stuff:
*.log
local_settings.py
db.sqlite3

# Flask stuff:
instance/
.webassets-cache

# Scrapy stuff:
.scrapy

# Sphinx documentation
docs/_build/

# PyBuilder
target/

# Jupyter Notebook
.ipynb_checkpoints

# pyenv
.python-version

# celery beat schedule file
celerybeat-schedule

# SageMath parsed files
*.sage.py

# Environments
.env
.venv
env/
venv/
ENV/
env.bak/
venv.bak/

# Spyder project settings
.spyderproject
.spyproject

# Rope project settings
.ropeproject

# mkdocs documentation
/site

# mypy
.mypy_cache/

26 changes: 26 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,28 @@
# EnphaseInterface
Python implementation interface to the Enphase Developer API

## Installation

`python3 -m pip install pyenface`

## Usage

```python
from pyEnFace.EnphaseInterface import PandasEnphaseInterface

client = client = PandasEnphaseInterface(userId=<YOUR USERID>, api_key=<YOUR API KEY>)

# Request all systems
client.index()

# Request inventory
client.inventory(system_id=<SYSTEM ID>)

# Summary
client.summary(system_id=<SYSTEM ID>)

# Get data as pandas dataframe
start = pd.Timestamp('20180101')

client.energy_lifetime(system_id=<SYSTEM ID>, start_date=start)
```
34 changes: 26 additions & 8 deletions pyEnFace/EnphaseInterface.py
Original file line number Diff line number Diff line change
Expand Up @@ -151,7 +151,7 @@ class RawEnphaseInterface(object):

def __init__(self, userId, max_wait=DEFAULT_MAX_WAIT,
useragent='Mozilla/5.0', datetimeType=DateTimeType.Enphase,
errorhandler=None):
errorhandler=None, api_key=None):

if errorhandler==None:
errorhandler=EnphaseErrorHandler(datetimeType,max_wait)
Expand All @@ -165,6 +165,9 @@ def __init__(self, userId, max_wait=DEFAULT_MAX_WAIT,
self.opener.addheaders = [('User-agent',useragent)]
self.apiDest = APIV2

if api_key is not None:
APIKEYRING.append(api_key)

def _execQuery(self, system_id, command, extraParams = dict()):
'''Generates a request url for the Enphase API'''

Expand Down Expand Up @@ -259,6 +262,12 @@ def energy_lifetime(self, system_id, **kwargs):
validArgs = self._filterAttributes(('start_date','end_date'),kwargs)
return self._execQuery(system_id, 'energy_lifetime', validArgs)

def consumption_lifetime(self, system_id, **kwargs):
"""Get the lifetime energy consumption measured by the system"""

validArgs = self._filterAttributes(('start_date','end_date'), kwargs)
return self._execQuery(system_id, 'consumption_lifetime', validArgs)

def envoys(self, system_id, **kwargs):
'''List the envoys associated with the system'''

Expand Down Expand Up @@ -328,6 +337,8 @@ def _execQuery(self, system_id, command, extraParams = dict()):

if command == 'energy_lifetime':
output = self._energy_lifetime(data)
elif command == 'consumption_lifetime':
output = self._consumption_lifetime(data)
elif command == 'envoys':
output = self._envoys(data)
elif command == 'index' or command == '':
Expand All @@ -348,15 +359,22 @@ def _execQuery(self, system_id, command, extraParams = dict()):
indexes = output.index.names
return self._datetimeify(output).set_index(indexes)

def _energy_lifetime(self,data):
d = json_normalize(data, 'production',['start_date','system_id'])
ts = to_timedelta(Series(d.index),unit='D')
d['start_date'] = to_datetime(d['start_date'],unit='s') + ts
def _lifetime(self, data, column):
"""column can be 'production', or 'consumption'"""
d = json_normalize(data, column, ['start_date', 'system_id'])
ts = to_timedelta(Series(d.index), unit='D')
d['start_date'] = to_datetime(d['start_date']) + ts
d['start_date'] = d['start_date'].apply(
lambda x:self.dtt.stringify('start_date',x))
d.rename(columns={0:'production'},inplace=True)
lambda x: self.dtt.stringify('start_date', x))
d.rename(columns={0: column}, inplace=True)

return d.set_index(['system_id', 'start_date'])

def _energy_lifetime(self, data):
return self._lifetime(data, "production")

return d.set_index(['system_id','start_date'])
def _consumption_lifetime(self, data):
return self._lifetime(data, "consumption")

def _envoys(self,data):
return json_normalize(data, 'envoys',
Expand Down