-
-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
8bc44f4
commit e4fd48d
Showing
361 changed files
with
53,697 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,129 @@ | ||
# 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/ | ||
pip-wheel-metadata/ | ||
share/python-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/ | ||
.nox/ | ||
.coverage | ||
.coverage.* | ||
.cache | ||
nosetests.xml | ||
coverage.xml | ||
*.cover | ||
*.py,cover | ||
.hypothesis/ | ||
.pytest_cache/ | ||
|
||
# Translations | ||
*.mo | ||
*.pot | ||
|
||
# Django stuff: | ||
*.log | ||
local_settings.py | ||
db.sqlite3 | ||
db.sqlite3-journal | ||
|
||
# Flask stuff: | ||
instance/ | ||
.webassets-cache | ||
|
||
# Scrapy stuff: | ||
.scrapy | ||
|
||
# Sphinx documentation | ||
docs/_build/ | ||
|
||
# PyBuilder | ||
target/ | ||
|
||
# Jupyter Notebook | ||
.ipynb_checkpoints | ||
|
||
# IPython | ||
profile_default/ | ||
ipython_config.py | ||
|
||
# pyenv | ||
.python-version | ||
|
||
# pipenv | ||
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. | ||
# However, in case of collaboration, if having platform-specific dependencies or dependencies | ||
# having no cross-platform support, pipenv may install dependencies that don't work, or not | ||
# install all needed dependencies. | ||
#Pipfile.lock | ||
|
||
# PEP 582; used by e.g. github.com/David-OConnor/pyflow | ||
__pypackages__/ | ||
|
||
# Celery stuff | ||
celerybeat-schedule | ||
celerybeat.pid | ||
|
||
# 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/ | ||
.dmypy.json | ||
dmypy.json | ||
|
||
# Pyre type checker | ||
.pyre/ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1,47 @@ | ||
# home-assistant-gama-300-dlms-meter | ||
Home Assistant Integration for reading data from ELGama GAMA300 meters via RS485-TCP Gateway | ||
# Home Assistant ELGAMA GAMA300 DLMS over TCPIP | ||
Home Assistant Integration for reading data from ELGAMA GAMA300 electricity meter (GAMA100 not tested, but possibly supported too) via RS485-TCP Gateway | ||
|
||
## Features | ||
|
||
- Get most of live values from meter | ||
- Add energy sensors for integration with energy usage | ||
- Tracks daily / total energy consumption | ||
|
||
## Notes | ||
|
||
This code was written for couple of days without any skills in Python and HA architecture. That is second time I've used Python, so anyone is welcome to make this code better. | ||
|
||
## Connecting meter to gateway and HA | ||
|
||
First your meter must support RS485 interface (check your meter manual or model number to ensure your meter support it, but also you can try to connect optical reader to gateway). To connect meter to HA you need any RS485->TCP gateway (I've used HI-FLYING HF5142B, coz prefer wires, but you can use any other or try to connect it with esp32 / 8266 with RS485 converter bridging it to TCP socket). | ||
On gateway side you should configure TCP server to forward data from RS485 port, it should be tcp server without authorization, you can choose any port to listen. | ||
|
||
#### RS485 params: | ||
- Baud rate: 9600 | ||
- Data bit: 8 | ||
- Stop bit: 1 | ||
- Parity: None | ||
|
||
![HF5142B_connection](https://raw.githubusercontent.com/astraliens/home-assistant-gama-300-dlms-meter/main/images/HF5142B_connection.jpg) | ||
![HF5142B_TCP_Server](https://raw.githubusercontent.com/astraliens/home-assistant-gama-300-dlms-meter/main/images/HF5142B_TCP_Server.jpg) | ||
|
||
After connecting meter you need to add `home-assistant-gama-300-dlms-meter` integration using HACS to your HA. In you HA go to *Main Menu -> HACS -> Integrations*, in top right corner press 3 dots and click to "Custom Repositories". Add repository `https://github.com/astraliens/home-assistant-gama_300_dlms_meter_reader` and category `Integration`. After this step close modal add repository window and press "Explore & Download Repositories" blue button at the bottom right corner of screen and search for `Gama 300 DLMS Meter` integration. Press on it and in right bottom corner of screen press "Download" button. | ||
After this you can simply add it like regular integration, specifiying IP and port of gateway and your meter serial number (you can find it on meter itself). In several seconds integration get data from meter, create all found sensors and will update them constantly. | ||
|
||
Pinout of meter shown on photo: | ||
![gama_300_rs485_pinout](https://raw.githubusercontent.com/astraliens/home-assistant-gama-300-dlms-meter/main/images/gama_300_rs485_pinout.jpg) | ||
|
||
|
||
## Energy consumption monitoring | ||
|
||
You can add `Sum Li Active power+ (QI+QIV) Time integral 1 Rate 0` sensor to your energy consumption monitoring to calculate your overall spents | ||
|
||
## DLMS Protocol | ||
|
||
Many thanks to <a href="https://www.gurux.fi/Gurux.DLMS">Gurux</a> for Python library implementation which used in this integration to retrieve data from meter | ||
|
||
## Donations | ||
|
||
You can say thanks by donating for buying pizza at: | ||
|
||
<a href="https://www.buymeacoffee.com/astraliens" target="_blank"><img src="https://cdn.buymeacoffee.com/buttons/default-orange.png" alt="Buy Me A Pizza" height="41" width="174"></a> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
# Home Assistant ELGAMA GAMA300 DLMS over TCPIP | ||
Home Assistant Integration for reading data from ELGAMA GAMA300 electricity meter (GAMA100 not tested, but possibly supported too) via RS485-TCP Gateway | ||
|
||
## Features | ||
|
||
- Get most of live values from meter | ||
- Add energy sensors for integration with energy usage | ||
- Tracks daily / total energy consumption | ||
|
||
## Notes | ||
|
||
This code was written for couple of days without any skills in Python and HA architecture. That is second time I've used Python, so anyone is welcome to make this code better. | ||
|
||
## Connecting meter to gateway and HA | ||
|
||
First your meter must support RS485 interface (check your meter manual or model number to ensure your meter support it, but also you can try to connect optical reader to gateway). To connect meter to HA you need any RS485->TCP gateway (I've used HI-FLYING HF5142B, coz prefer wires, but you can use any other or try to connect it with esp32 / 8266 with RS485 converter bridging it to TCP socket). | ||
On gateway side you should configure TCP server to forward data from RS485 port, it should be tcp server without authorization, you can choose any port to listen. | ||
|
||
#### RS485 params: | ||
- Baud rate: 9600 | ||
- Data bit: 8 | ||
- Stop bit: 1 | ||
- Parity: None | ||
|
||
![HF5142B_connection](https://raw.githubusercontent.com/astraliens/home-assistant-gama-300-dlms-meter/main/images/HF5142B_connection.jpg) | ||
![HF5142B_TCP_Server](https://raw.githubusercontent.com/astraliens/home-assistant-gama-300-dlms-meter/main/images/HF5142B_TCP_Server.jpg) | ||
|
||
After connecting meter you need to add `home-assistant-gama-300-dlms-meter` integration using HACS to your HA. In you HA go to *Main Menu -> HACS -> Integrations*, in top right corner press 3 dots and click to "Custom Repositories". Add repository `https://github.com/astraliens/home-assistant-gama_300_dlms_meter_reader` and category `Integration`. After this step close modal add repository window and press "Explore & Download Repositories" blue button at the bottom right corner of screen and search for `Gama 300 DLMS Meter` integration. Press on it and in right bottom corner of screen press "Download" button. | ||
After this you can simply add it like regular integration, specifiying IP and port of gateway and your meter serial number (you can find it on meter itself). In several seconds integration get data from meter, create all found sensors and will update them constantly. | ||
|
||
Pinout of meter shown on photo: | ||
![gama_300_rs485_pinout](https://raw.githubusercontent.com/astraliens/home-assistant-gama-300-dlms-meter/main/images/gama_300_rs485_pinout.jpg) | ||
|
||
|
||
## Energy consumption monitoring | ||
|
||
You can add `Sum Li Active power+ (QI+QIV) Time integral 1 Rate 0` sensor to your energy consumption monitoring to calculate your overall spents | ||
|
||
## DLMS Protocol | ||
|
||
Many thanks to <a href="https://www.gurux.fi/Gurux.DLMS">Gurux</a> for Python library implementation which used in this integration to retrieve data from meter | ||
|
||
## Donations | ||
|
||
You can say thanks by donating for buying pizza at: | ||
|
||
<a href="https://www.buymeacoffee.com/astraliens" target="_blank"><img src="https://cdn.buymeacoffee.com/buttons/default-orange.png" alt="Buy Me A Pizza" height="41" width="174"></a> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
from __future__ import annotations | ||
|
||
from homeassistant.config_entries import ConfigEntry | ||
from homeassistant.core import HomeAssistant | ||
|
||
from . import hub | ||
from .const import DOMAIN | ||
|
||
# List of platforms to support. There should be a matching .py file for each, | ||
# eg <cover.py> and <sensor.py> | ||
PLATFORMS: list[str] = ["sensor"] | ||
|
||
|
||
async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool: | ||
# Store an instance of the "connecting" class that does the work of speaking | ||
# with your actual devices. | ||
hass.data.setdefault(DOMAIN, {})[entry.entry_id] = hub.Hub(hass, entry.data["host"], entry.data["port"], entry.data["serial"]) | ||
|
||
# This creates each HA object for each platform your device requires. | ||
# It's done by calling the `async_setup_entry` function in each platform module. | ||
await hass.config_entries.async_forward_entry_setups(entry, PLATFORMS) | ||
return True | ||
|
||
|
||
async def async_unload_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool: | ||
"""Unload a config entry.""" | ||
# This is called when an entry/configured device is to be removed. The class | ||
# needs to unload itself, and remove callbacks. See the classes for further | ||
# details | ||
unload_ok = await hass.config_entries.async_unload_platforms(entry, PLATFORMS) | ||
if unload_ok: | ||
hass.data[DOMAIN].pop(entry.entry_id) | ||
|
||
return unload_ok |
119 changes: 119 additions & 0 deletions
119
custom_components/gama_300_dlms_meter_reader/config_flow.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,119 @@ | ||
from __future__ import annotations | ||
|
||
import logging | ||
from typing import Any | ||
|
||
import voluptuous as vol | ||
|
||
from homeassistant import config_entries, exceptions | ||
from homeassistant.core import HomeAssistant | ||
|
||
from .const import DOMAIN # pylint:disable=unused-import | ||
from .hub import Hub | ||
|
||
_LOGGER = logging.getLogger(__name__) | ||
|
||
# This is the schema that used to display the UI to the user. This simple | ||
# schema has a single required host field, but it could include a number of fields | ||
# such as username, password etc. See other components in the HA core code for | ||
# further examples. | ||
# Note the input displayed to the user will be translated. See the | ||
# translations/<lang>.json file and strings.json. See here for further information: | ||
# https://developers.home-assistant.io/docs/config_entries_config_flow_handler/#translations | ||
# At the time of writing I found the translations created by the scaffold didn't | ||
# quite work as documented and always gave me the "Lokalise key references" string | ||
# (in square brackets), rather than the actual translated value. I did not attempt to | ||
# figure this out or look further into it. | ||
DATA_SCHEMA = vol.Schema({ | ||
("host"): str, | ||
("port"): int, | ||
("serial"): int, | ||
}) | ||
|
||
async def validate_input(hass: HomeAssistant, data: dict) -> dict[str, Any]: | ||
"""Validate the user input allows us to connect. | ||
Data has the keys from DATA_SCHEMA with values provided by the user. | ||
""" | ||
# Validate the data can be used to set up a connection. | ||
|
||
# This is a simple example to show an error in the UI for a short hostname | ||
# The exceptions are defined at the end of this file, and are used in the | ||
# `async_step_user` method below. | ||
if len(data["host"]) < 3: | ||
raise InvalidHost | ||
|
||
hub = Hub(hass, data["host"],data["port"],data["serial"]) | ||
# The dummy hub provides a `test_connection` method to ensure it's working | ||
# as expected | ||
result = await hub.test_connection() | ||
#if not result: | ||
# If there is an error, raise an exception to notify HA that there was a | ||
# problem. The UI will also show there was a problem | ||
# raise CannotConnect | ||
|
||
# If your PyPI package is not built with async, pass your methods | ||
# to the executor: | ||
# await hass.async_add_executor_job( | ||
# your_validate_func, data["username"], data["password"] | ||
# ) | ||
|
||
# If you cannot connect: | ||
# throw CannotConnect | ||
# If the authentication is wrong: | ||
# InvalidAuth | ||
|
||
# Return info that you want to store in the config entry. | ||
# "Title" is what is displayed to the user for this hub device | ||
# It is stored internally in HA as part of the device config. | ||
# See `async_step_user` below for how this is used | ||
return {"title": data["host"]} | ||
|
||
|
||
class ConfigFlow(config_entries.ConfigFlow, domain=DOMAIN): | ||
|
||
VERSION = 1 | ||
# Pick one of the available connection classes in homeassistant/config_entries.py | ||
# This tells HA if it should be asking for updates, or it'll be notified of updates | ||
# automatically. This example uses PUSH, as the dummy hub will notify HA of | ||
# changes. | ||
CONNECTION_CLASS = config_entries.CONN_CLASS_LOCAL_PUSH | ||
|
||
async def async_step_user(self, user_input=None): | ||
"""Handle the initial step.""" | ||
# This goes through the steps to take the user through the setup process. | ||
# Using this it is possible to update the UI and prompt for additional | ||
# information. This example provides a single form (built from `DATA_SCHEMA`), | ||
# and when that has some validated input, it calls `async_create_entry` to | ||
# actually create the HA config entry. Note the "title" value is returned by | ||
# `validate_input` above. | ||
errors = {} | ||
if user_input is not None: | ||
try: | ||
info = await validate_input(self.hass, user_input) | ||
|
||
return self.async_create_entry(title=info["title"], data=user_input) | ||
except CannotConnect: | ||
errors["base"] = "cannot_connect" | ||
except InvalidHost: | ||
# The error string is set here, and should be translated. | ||
# This example does not currently cover translations, see the | ||
# comments on `DATA_SCHEMA` for further details. | ||
# Set the error on the `host` field, not the entire form. | ||
errors["host"] = "cannot_connect" | ||
except Exception: # pylint: disable=broad-except | ||
_LOGGER.exception("Unexpected exception") | ||
errors["base"] = "unknown" | ||
|
||
# If there is no user input or there were errors, show the form again, including any errors that were found with the input. | ||
return self.async_show_form( | ||
step_id="user", data_schema=DATA_SCHEMA, errors=errors | ||
) | ||
|
||
|
||
class CannotConnect(exceptions.HomeAssistantError): | ||
"""Error to indicate we cannot connect.""" | ||
|
||
|
||
class InvalidHost(exceptions.HomeAssistantError): | ||
"""Error to indicate there is an invalid hostname.""" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
# This is the internal name of the integration, it should also match the directory | ||
# name for the integration. | ||
DOMAIN = "gama_300_dlms_meter_reader" |
Oops, something went wrong.