Skip to content

Commit 3e2d387

Browse files
committed
Welcome myelectricaldata integration
0 parents  commit 3e2d387

19 files changed

+1931
-0
lines changed

.github/workflows/check-lint.yml

+42
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
name: Check Lint
2+
3+
on: [push, pull_request]
4+
5+
jobs:
6+
build:
7+
runs-on: ubuntu-latest
8+
strategy:
9+
max-parallel: 2
10+
matrix:
11+
python-version: ["3.9", "3.10"]
12+
13+
steps:
14+
- name: 📥 Checkout the repository
15+
uses: actions/checkout@v3
16+
17+
- name: Set up Python ${{ matrix.python-version }}
18+
uses: actions/setup-python@v4
19+
with:
20+
python-version: ${{ matrix.python-version }}
21+
22+
- name: Install dependencies
23+
run: |
24+
python -m pip install --upgrade pip
25+
python -m pip install flake8 pylint
26+
if [ -f requirements.txt ]; then pip install -r requirements.txt; fi
27+
28+
- name: Lint with flake8
29+
run: |
30+
pip install flake8
31+
# stop the build if there are Python syntax errors or undefined names
32+
flake8 . --count --select=E9,F63,F7,F82 --show-source --statistics
33+
# exit-zero treats all errors as warnings. The GitHub editor is 127 chars wide
34+
flake8 . --count --exit-zero --max-complexity=10 --max-line-length=127 --statistics
35+
36+
- name: Lint with pylint
37+
run: |
38+
pip install pylint
39+
# stop the build if there are Pylint errors
40+
# there is a bug with E1136 (https://github.com/PyCQA/pylint/issues/1498)
41+
# so we temporarily disable it.
42+
pylint --disable=I,C,R,E0401 --extension-pkg-whitelist=numpy custom_components

.github/workflows/hacs.yml

+20
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
name: HACS Action
2+
3+
on:
4+
push:
5+
pull_request:
6+
schedule:
7+
- cron: "0 0 * * *"
8+
9+
jobs:
10+
hacs:
11+
name: HACS Action
12+
runs-on: "ubuntu-latest"
13+
steps:
14+
- name: 📥 Checkout the repository
15+
uses: actions/checkout@v3
16+
17+
- name: HACS Action
18+
uses: "hacs/action@main"
19+
with:
20+
category: "integration"

.github/workflows/hassfest.yaml

+14
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
name: Validate with hassfest
2+
3+
on:
4+
push:
5+
pull_request:
6+
schedule:
7+
- cron: '0 0 * * *'
8+
9+
jobs:
10+
validate:
11+
runs-on: "ubuntu-latest"
12+
steps:
13+
- uses: "actions/checkout@v3"
14+
- uses: "home-assistant/actions/hassfest@master"

.gitignore

+128
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,128 @@
1+
2+
# Created by https://www.gitignore.io/api/python
3+
# Edit at https://www.gitignore.io/?templates=python
4+
5+
### Python ###
6+
# Byte-compiled / optimized / DLL files
7+
__pycache__/
8+
*.py[cod]
9+
*$py.class
10+
11+
# C extensions
12+
*.so
13+
14+
# Distribution / packaging
15+
.Python
16+
build/
17+
develop-eggs/
18+
dist/
19+
downloads/
20+
eggs/
21+
.eggs/
22+
lib/
23+
lib64/
24+
parts/
25+
sdist/
26+
var/
27+
wheels/
28+
share/python-wheels/
29+
*.egg-info/
30+
.installed.cfg
31+
*.egg
32+
MANIFEST
33+
34+
# PyInstaller
35+
# Usually these files are written by a python script from a template
36+
# before PyInstaller builds the exe, so as to inject date/other infos into it.
37+
*.manifest
38+
*.spec
39+
40+
# Installer logs
41+
pip-log.txt
42+
pip-delete-this-directory.txt
43+
44+
# Unit test / coverage reports
45+
htmlcov/
46+
.tox/
47+
.nox/
48+
.coverage
49+
.coverage.*
50+
.cache
51+
nosetests.xml
52+
coverage.xml
53+
*.cover
54+
.hypothesis/
55+
.pytest_cache/
56+
57+
# Translations
58+
*.mo
59+
*.pot
60+
61+
# Django stuff:
62+
*.log
63+
local_settings.py
64+
db.sqlite3
65+
66+
# Flask stuff:
67+
instance/
68+
.webassets-cache
69+
70+
# Scrapy stuff:
71+
.scrapy
72+
73+
# Sphinx documentation
74+
docs/_build/
75+
76+
# PyBuilder
77+
target/
78+
79+
# Jupyter Notebook
80+
.ipynb_checkpoints
81+
82+
# IPython
83+
profile_default/
84+
ipython_config.py
85+
86+
# pyenv
87+
.python-version
88+
89+
# celery beat schedule file
90+
celerybeat-schedule
91+
92+
# SageMath parsed files
93+
*.sage.py
94+
95+
# Environments
96+
.env
97+
.venv
98+
env/
99+
venv/
100+
ENV/
101+
env.bak/
102+
venv.bak/
103+
104+
# Spyder project settings
105+
.spyderproject
106+
.spyproject
107+
108+
# Rope project settings
109+
.ropeproject
110+
111+
# VSCode setting
112+
.vscode
113+
114+
# mkdocs documentation
115+
/site
116+
117+
# mypy
118+
.mypy_cache/
119+
.dmypy.json
120+
dmypy.json
121+
122+
# Pyre type checker
123+
.pyre/
124+
125+
### Python Patch ###
126+
.venv/
127+
128+
# End of https://www.gitignore.io/api/python

LICENSE

+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
MIT License
2+
3+
Copyright (c) 2019 Antoine Colmard
4+
5+
Permission is hereby granted, free of charge, to any person obtaining a copy
6+
of this software and associated documentation files (the "Software"), to deal
7+
in the Software without restriction, including without limitation the rights
8+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
copies of the Software, and to permit persons to whom the Software is
10+
furnished to do so, subject to the following conditions:
11+
12+
The above copyright notice and this permission notice shall be included in all
13+
copies or substantial portions of the Software.
14+
15+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21+
SOFTWARE.

README.md

+67
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
# Enedis gateway
2+
This a *custom component* for [Home Assistant](https://www.home-assistant.io/).
3+
4+
With Enedis, get datas from [MyElectricalData](https://myelectricaldata.fr)
5+
6+
There is currently support for the following device types within Home Assistant:
7+
* [Power_sensor](#sensor)
8+
9+
10+
11+
### HACS [![hacs_badge](https://img.shields.io/badge/HACS-Custom-orange.svg)](https://github.com/custom-components/hacs)
12+
Once HACS is installed,
13+
14+
Click on the 3 dots at the top right
15+
16+
Add custom repositories
17+
18+
Integration : https://github.com/Cyr-ius/hass-myelectricaldata
19+
20+
Add install Enedis [![Open your Home Assistant instance and start setting up a new integration.](https://my.home-assistant.io/badges/config_flow_start.svg)](https://my.home-assistant.io/redirect/config_flow_start/?domain=enedis)
21+
22+
## Features
23+
24+
- Supports the consumption and production of Linky meters
25+
26+
- Supports multiple billing ranges in consumption mode.
27+
28+
- Possibility of defining the cost of tariffs on the energy produced, consumed, peak hours, off-peak hours.
29+
30+
- Possibility to add a specific price on a time slot
31+
32+
![GitHub release](https://img.shields.io/github/release/Cyr-ius/hass-myelectricaldata)
33+
34+
35+
## Configuration
36+
37+
The preferred way to setup the platform is by enabling the discovery component.
38+
Add your equipment via the Integration menu
39+
40+
[![Open your Home Assistant instance and start setting up a new integration.](https://my.home-assistant.io/badges/config_flow_start.svg)](https://my.home-assistant.io/redirect/config_flow_start/?domain=myelectricaldata)
41+
42+
43+
44+
### Within the Options menu:
45+
46+
The ranges must be set from midnight to midnight. (00H00 - 00H00)
47+
A range that has the same billing must have the same name so that HA can perform the sum.
48+
On each beach, it is necessary to add an hourly rate
49+
50+
Example :
51+
My contract stipulates off-peak hours from 01H30 to 08H00 and from 12H30 to 14H30.
52+
53+
The following ranges should be defined:
54+
55+
Peak hours 00H00 01H30 0.12
56+
Off-peak hours 01H00 08H00 0.08
57+
Peak hours 08H00 12:30 0.12
58+
Off-peak hours 12H30 14H00 0.08
59+
Peak hours 14H00 00H00 0.12
60+
61+
62+
![image](https://user-images.githubusercontent.com/1258123/194921798-3bf9a495-e1af-4291-93ef-d5bb4783535c.png)
63+
64+
65+
66+
67+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
"""The Enedis integration."""
2+
from __future__ import annotations
3+
4+
import logging
5+
6+
from homeassistant.config_entries import ConfigEntry
7+
from homeassistant.core import HomeAssistant
8+
9+
from .const import DOMAIN, PLATFORMS
10+
from .coordinator import EnedisDataUpdateCoordinator
11+
from .services import async_services
12+
13+
_LOGGER = logging.getLogger(__name__)
14+
15+
16+
async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
17+
"""Set up Enedis as config entry."""
18+
hass.data.setdefault(DOMAIN, {})
19+
20+
coordinator = EnedisDataUpdateCoordinator(hass, entry)
21+
await coordinator.async_config_entry_first_refresh()
22+
23+
hass.data[DOMAIN][entry.entry_id] = coordinator
24+
await hass.config_entries.async_forward_entry_setups(entry, PLATFORMS)
25+
26+
await async_services(hass, entry, coordinator)
27+
entry.async_on_unload(entry.add_update_listener(_async_update_listener))
28+
29+
return True
30+
31+
32+
async def async_unload_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
33+
"""Unload a config entry."""
34+
if unload_ok := await hass.config_entries.async_unload_platforms(entry, PLATFORMS):
35+
hass.data[DOMAIN].pop(entry.entry_id)
36+
return unload_ok
37+
38+
39+
async def _async_update_listener(hass: HomeAssistant, entry: ConfigEntry) -> None:
40+
"""Handle options update."""
41+
await hass.config_entries.async_reload(entry.entry_id)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
"""Binary Sensor for power energy."""
2+
from __future__ import annotations
3+
4+
import logging
5+
6+
from homeassistant.components.binary_sensor import (
7+
BinarySensorDeviceClass,
8+
BinarySensorEntity,
9+
)
10+
from homeassistant.config_entries import ConfigEntry
11+
from homeassistant.core import HomeAssistant
12+
from homeassistant.helpers.entity import DeviceInfo, EntityCategory
13+
from homeassistant.helpers.entity_platform import AddEntitiesCallback
14+
from homeassistant.helpers.update_coordinator import CoordinatorEntity
15+
16+
from .const import DOMAIN
17+
18+
_LOGGER = logging.getLogger(__name__)
19+
20+
21+
async def async_setup_entry(
22+
hass: HomeAssistant,
23+
config_entry: ConfigEntry,
24+
async_add_entities: AddEntitiesCallback,
25+
) -> None:
26+
"""Set up the sensors."""
27+
coordinator = hass.data[DOMAIN][config_entry.entry_id]
28+
async_add_entities([CountdownSensor(coordinator)])
29+
30+
31+
class CountdownSensor(CoordinatorEntity, BinarySensorEntity):
32+
"""Sensor return token expiration date."""
33+
34+
_attr_device_class = BinarySensorDeviceClass.PROBLEM
35+
_attr_name = "MyElectricalData Token"
36+
_attr_has_entity_name = True
37+
_attr_entity_category = EntityCategory.DIAGNOSTIC
38+
39+
def __init__(self, coordinator):
40+
"""Initialize the sensor."""
41+
super().__init__(coordinator)
42+
access = coordinator.access
43+
self._attr_unique_id = f"{coordinator.pdl}_token_expire"
44+
self._attr_extra_state_attributes = {
45+
"Call number": access.get("call_number"),
46+
"Last call": access.get("last_call"),
47+
"Banned": access.get("ban"),
48+
"Quota": access.get("quota_limit"),
49+
"Quota reached": access.get("quota_reached"),
50+
"Expiration date": access.get("consent_expiration_date"),
51+
}
52+
self._attr_device_info = DeviceInfo(identifiers={(DOMAIN, coordinator.pdl)})
53+
54+
@property
55+
def is_on(self):
56+
"""Value power."""
57+
return self.coordinator.access.get("valid", False) is False

0 commit comments

Comments
 (0)