Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix RFC2217 blocking calls #50

Open
wants to merge 7 commits into
base: main
Choose a base branch
from
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
2 changes: 1 addition & 1 deletion .github/workflows/hacs.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -15,4 +15,4 @@ jobs:
- name: HACS validation
uses: "hacs/action@main"
with:
category: "integration"
category: "integration"
38 changes: 38 additions & 0 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
# Adapted from https://github.com/home-assistant/core/blob/dev/.pre-commit-config.yaml
repos:
- repo: https://github.com/astral-sh/ruff-pre-commit
rev: v0.7.3
hooks:
- id: ruff
args: [--fix, --select, I]
- id: ruff-format
files: ^((custom_components)/.+)?[^/]+\.(py|pyi)$
- repo: https://github.com/codespell-project/codespell
rev: v2.3.0
hooks:
- id: codespell
args:
- --ignore-words-list=astroid,checkin,currenty,hass,iif,incomfort,lookin,nam,NotIn
- --skip="./.*,*.csv,*.json,*.ambr,*.md"
- --quiet-level=2
exclude_types: [csv, json, html, markdown]
exclude: ^serialserver/|res/
- repo: https://github.com/pre-commit/mirrors-prettier
rev: v3.0.3
hooks:
- id: prettier
- repo: local
hooks:
# Run mypy through our wrapper script in order to get the possible
# pyenv and/or virtualenv activated; it may not have been e.g. if
# committing from a GUI tool that was not launched from an activated
# shell.
- id: mypy
name: mypy
entry: mypy
language: python
types_or: [python, pyi]
args:
- --ignore-missing-imports
require_serial: true
files: ^(custom_components)/.+\.(py|pyi)$
132 changes: 66 additions & 66 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,12 @@ Cette intégration pour Home Assistant ajoute le support des Linky au travers de

Par exemple:

* [Module série USB développé par LiXee](https://lixee.fr/produits/30-tic-din-3770014375070.html) (celui que j'utilise)
* [Téléinfo 1 compteur USB rail DIN de Cartelectronic](https://www.cartelectronic.fr/teleinfo-compteur-enedis/17-teleinfo-1-compteur-usb-rail-din-3760313520028.html) (validé par un [utilisateur](https://github.com/hekmon/linkytic/issues/2#issuecomment-1364535337))
* [Circuit à faire soi-même](https://miniprojets.net/index.php/2019/06/28/recuperer-les-donnees-de-son-compteur-linky/), nécessitant peu de composants ([autre article avec un circuit similaire](https://hallard.me/pitinfov12/)). Validé par un [utilisateur](https://github.com/hekmon/linkytic/pull/4#issuecomment-1368877730).
* [Module Micro Téléinfo V3.0](https://github.com/hallard/uTeleinfo) à fabriquer soi-même ou pré-assemblé sur [Tindie](https://www.tindie.com/products/28873/)
* [Teleinfo ADTEK](https://doc.eedomus.com/view/T%C3%A9l%C3%A9info_USB_ADTEK) attention cependant [le baudrate ne semble pas standard](https://github.com/hekmon/linkytic/issues/40).
* et certainement bien d'autres ! (n'hésitez pas à m'ouvrir une issue pour rajouter le votre si vous avez validé que celui-ci fonctionne avec cette intégration afin d'aidez de potentiels futurs utilisateurs qui n'en auraient pas encore choisi un)
- [Module série USB développé par LiXee](https://lixee.fr/produits/30-tic-din-3770014375070.html) (celui que j'utilise)
- [Téléinfo 1 compteur USB rail DIN de Cartelectronic](https://www.cartelectronic.fr/teleinfo-compteur-enedis/17-teleinfo-1-compteur-usb-rail-din-3760313520028.html) (validé par un [utilisateur](https://github.com/hekmon/linkytic/issues/2#issuecomment-1364535337))
- [Circuit à faire soi-même](https://miniprojets.net/index.php/2019/06/28/recuperer-les-donnees-de-son-compteur-linky/), nécessitant peu de composants ([autre article avec un circuit similaire](https://hallard.me/pitinfov12/)). Validé par un [utilisateur](https://github.com/hekmon/linkytic/pull/4#issuecomment-1368877730).
- [Module Micro Téléinfo V3.0](https://github.com/hallard/uTeleinfo) à fabriquer soi-même ou pré-assemblé sur [Tindie](https://www.tindie.com/products/28873/)
- [Teleinfo ADTEK](https://doc.eedomus.com/view/T%C3%A9l%C3%A9info_USB_ADTEK) attention cependant [le baudrate ne semble pas standard](https://github.com/hekmon/linkytic/issues/40).
- et certainement bien d'autres ! (n'hésitez pas à m'ouvrir une issue pour rajouter le votre si vous avez validé que celui-ci fonctionne avec cette intégration afin d'aidez de potentiels futurs utilisateurs qui n'en auraient pas encore choisi un)

[Exemple sous Home Assistant](https://github.com/hekmon/linkytic/raw/v3.0.0-beta4/res/SCR-20221223-ink.png).

Expand All @@ -34,8 +34,8 @@ Cependant, certaines sondes peuvent avoir de la valeur dans leur "instantanéit

Suivant la configuration que vous choisirez pour votre installation vous trouverez dans ce fichier dans la liste des sondes avec les annotations suivantes:

* <sup>1</sup> sonde compatible avec le mode temps réel: si celui-ci est activé par l'utilisateur, les mises à jours seront bien plus fréquentes (dès qu'elles sont lues sur la connection série)
* <sup>2</sup> sonde dont le mode temps réel est forcé même si l'utilisateur n'a pas activé le mode temps réèl dans le cas où la valeur de la sonde est importante et/ou éphémère
- <sup>1</sup> sonde compatible avec le mode temps réel: si celui-ci est activé par l'utilisateur, les mises à jours seront bien plus fréquentes (dès qu'elles sont lues sur la connection série)
- <sup>2</sup> sonde dont le mode temps réel est forcé même si l'utilisateur n'a pas activé le mode temps réèl dans le cas où la valeur de la sonde est importante et/ou éphémère

### Mode historique

Expand All @@ -45,66 +45,66 @@ Le mode historique est le plus commun (existant pré Linky) : il est activé par

Les 23 champs des compteurs mono-phasé configurés en mode historique sont supportés:

* `ADCO` Adresse du compteur (avec parsing EURIDIS en attributs étendus et périphérique agrégateur sous Home Assistant)
* `OPTARIF` Option tarifaire choisie
* `ISOUSC` Intensité souscrite
* `BASE` Index option Base
* `HCHC` Index option Heures Creuses - Heures Creuses
* `HCHP` Index option Heures Creuses - Heures Pleines
* `EJPHN` Index option EJP - Heures Normales
* `EJPHPM` Index option EJP - Heures de Pointe Mobile
* `BBRHCJB` Index option Tempo - Heures Creuses Jours Bleus
* `BBRHPJB` Index option Tempo - Heures Pleines Jours Bleus
* `BBRHCJW` Index option Tempo - Heures Creuses Jours Blancs
* `BBRHPJW` Index option Tempo - Heures Pleines Jours Blancs
* `BBRHCJR` Index option Tempo - Heures Creuses Jours Rouges
* `BBRHPJR` Index option Tempo - Heures Pleines Jours Rouges
* `PEJP` Préavis Début EJP (30 min)
* `PTEC` Période Tarifaire en cours
* `DEMAIN` Couleur du lendemain
* `IINST` Intensité Instantanée <sup>1</sup>
* `ADPS` Avertissement de Dépassement De Puissance Souscrite <sup>2</sup>
* `IMAX` Intensité maximale appelée
* `PAPP` Puissance apparente <sup>1</sup>
* `HHPHC` Horaire Heures Pleines Heures Creuses
* `MOTDETAT` Mot d'état du compteur
- `ADCO` Adresse du compteur (avec parsing EURIDIS en attributs étendus et périphérique agrégateur sous Home Assistant)
- `OPTARIF` Option tarifaire choisie
- `ISOUSC` Intensité souscrite
- `BASE` Index option Base
- `HCHC` Index option Heures Creuses - Heures Creuses
- `HCHP` Index option Heures Creuses - Heures Pleines
- `EJPHN` Index option EJP - Heures Normales
- `EJPHPM` Index option EJP - Heures de Pointe Mobile
- `BBRHCJB` Index option Tempo - Heures Creuses Jours Bleus
- `BBRHPJB` Index option Tempo - Heures Pleines Jours Bleus
- `BBRHCJW` Index option Tempo - Heures Creuses Jours Blancs
- `BBRHPJW` Index option Tempo - Heures Pleines Jours Blancs
- `BBRHCJR` Index option Tempo - Heures Creuses Jours Rouges
- `BBRHPJR` Index option Tempo - Heures Pleines Jours Rouges
- `PEJP` Préavis Début EJP (30 min)
- `PTEC` Période Tarifaire en cours
- `DEMAIN` Couleur du lendemain
- `IINST` Intensité Instantanée <sup>1</sup>
- `ADPS` Avertissement de Dépassement De Puissance Souscrite <sup>2</sup>
- `IMAX` Intensité maximale appelée
- `PAPP` Puissance apparente <sup>1</sup>
- `HHPHC` Horaire Heures Pleines Heures Creuses
- `MOTDETAT` Mot d'état du compteur

#### Compteurs tri-phasés

⚠️ Actuellement en beta ⚠️

Des retours de log en `DEBUG` pendant l'émission de trames courtes sont nécessaires pour valider le bon fonctionnement de l'intégration sur ces compteurs, n'hésitez pas à ouvrir une [issue](https://github.com/hekmon/linkytic/issues) si vous avec un compteur triphasé pour aider à sa finalisation !

* `ADCO` Adresse du compteur (avec parsing EURIDIS en attributs étendus et périphérique agrégateur sous Home Assistant)
* `OPTARIF` Option tarifaire choisie
* `ISOUSC` Intensité souscrite
* `BASE` Index option Base
* `HCHC` Index option Heures Creuses - Heures Creuses
* `HCHP` Index option Heures Creuses - Heures Pleines
* `EJPHN` Index option EJP - Heures Normales
* `EJPHPM` Index option EJP - Heures de Pointe Mobile
* `BBRHCJB` Index option Tempo - Heures Creuses Jours Bleus
* `BBRHPJB` Index option Tempo - Heures Pleines Jours Bleus
* `BBRHCJW` Index option Tempo - Heures Creuses Jours Blancs
* `BBRHPJW` Index option Tempo - Heures Pleines Jours Blancs
* `BBRHCJR` Index option Tempo - Heures Creuses Jours Rouges
* `BBRHPJR` Index option Tempo - Heures Pleines Jours Rouges
* `PEJP` Préavis Début EJP (30 min)
* `PTEC` Période Tarifaire en cours
* `DEMAIN` Couleur du lendemain
* `IINST1` Intensité Instantanée (phase 1) <sup>1</sup> pour les trames longues <sup>2</sup> pour les trames courtes
* `IINST2` Intensité Instantanée (phase 2) <sup>1</sup> pour les trames longues <sup>2</sup> pour les trames courtes
* `IINST3` Intensité Instantanée (phase 3) <sup>1</sup> pour les trames longues <sup>2</sup> pour les trames courtes
* `IMAX1` Intensité maximale (phase 1)
* `IMAX2` Intensité maximale (phase 2)
* `IMAX3` Intensité maximale (phase 3)
* `PMAX` Puissance maximale triphasée atteinte
* `PAPP` Puissance apparente <sup>1</sup>
* `HHPHC` Horaire Heures Pleines Heures Creuses
* `MOTDETAT` Mot d'état du compteur
* `ADIR1` Avertissement de Dépassement d'intensité de réglage (phase 1) <sup>2</sup> trames courtes uniquement
* `ADIR2` Avertissement de Dépassement d'intensité de réglage (phase 2) <sup>2</sup> trames courtes uniquement
* `ADIR3` Avertissement de Dépassement d'intensité de réglage (phase 3) <sup>2</sup> trames courtes uniquement
- `ADCO` Adresse du compteur (avec parsing EURIDIS en attributs étendus et périphérique agrégateur sous Home Assistant)
- `OPTARIF` Option tarifaire choisie
- `ISOUSC` Intensité souscrite
- `BASE` Index option Base
- `HCHC` Index option Heures Creuses - Heures Creuses
- `HCHP` Index option Heures Creuses - Heures Pleines
- `EJPHN` Index option EJP - Heures Normales
- `EJPHPM` Index option EJP - Heures de Pointe Mobile
- `BBRHCJB` Index option Tempo - Heures Creuses Jours Bleus
- `BBRHPJB` Index option Tempo - Heures Pleines Jours Bleus
- `BBRHCJW` Index option Tempo - Heures Creuses Jours Blancs
- `BBRHPJW` Index option Tempo - Heures Pleines Jours Blancs
- `BBRHCJR` Index option Tempo - Heures Creuses Jours Rouges
- `BBRHPJR` Index option Tempo - Heures Pleines Jours Rouges
- `PEJP` Préavis Début EJP (30 min)
- `PTEC` Période Tarifaire en cours
- `DEMAIN` Couleur du lendemain
- `IINST1` Intensité Instantanée (phase 1) <sup>1</sup> pour les trames longues <sup>2</sup> pour les trames courtes
- `IINST2` Intensité Instantanée (phase 2) <sup>1</sup> pour les trames longues <sup>2</sup> pour les trames courtes
- `IINST3` Intensité Instantanée (phase 3) <sup>1</sup> pour les trames longues <sup>2</sup> pour les trames courtes
- `IMAX1` Intensité maximale (phase 1)
- `IMAX2` Intensité maximale (phase 2)
- `IMAX3` Intensité maximale (phase 3)
- `PMAX` Puissance maximale triphasée atteinte
- `PAPP` Puissance apparente <sup>1</sup>
- `HHPHC` Horaire Heures Pleines Heures Creuses
- `MOTDETAT` Mot d'état du compteur
- `ADIR1` Avertissement de Dépassement d'intensité de réglage (phase 1) <sup>2</sup> trames courtes uniquement
- `ADIR2` Avertissement de Dépassement d'intensité de réglage (phase 2) <sup>2</sup> trames courtes uniquement
- `ADIR3` Avertissement de Dépassement d'intensité de réglage (phase 3) <sup>2</sup> trames courtes uniquement

### Mode standard

Expand All @@ -118,13 +118,13 @@ Une fois que votre module TIC est installé et connecté à votre compteur ainsi

Exemple de configuration pour le module de [LiXee](https://faire-ca-soi-meme.fr/domotique/2016/09/12/module-teleinformation-tic/):

* Mode historique
- Mode historique

```bash
stty -F /dev/ttyUSB0 1200 sane evenp parenb cs7 -crtscts
```

* Mode standard
- Mode standard

```bash
stty -F /dev/ttyUSB0 9600 sane evenp parenb cs7 -crtscts
Expand Down Expand Up @@ -162,9 +162,9 @@ Une fois Home Assistant redémarré, allez dans: `Paramètres -> Appareils et se

Vous devriez passer sur le formulaire d'installation vous présentant les 3 champs suivants:

* `Chemin/Adresse vers le périphérique série` Ici renseignez le path de votre périphérique USB testé précédement. Le champ est rempli par default avec la valeur `/dev/ttyUSB0`: Il ne s'agit pas d'une auto détection mais simplement de la valeure la plus probable dans 99% des installations. Il est aussi possible d'utiliser une URL supporté par [pyserial](https://pyserial.readthedocs.io/en/latest/url_handlers.html), ce qui peut s'avérer utile si le port série est connecté sur un appareil distant (support de la rfc2217 par exemple).
* `Mode TIC` Choississez entre `Standard` et `Historique`. Plus de détails sur ces 2 modes en début de ce document.
* `Triphasé` À cocher si votre compteur est un compteur... triphasé. À noter que cette option n'a d'effet que si vous êtes en mode historique (le mode standard gère le mono et le tri de manière indifférente).
- `Chemin/Adresse vers le périphérique série` Ici renseignez le path de votre périphérique USB testé précédement. Le champ est rempli par default avec la valeur `/dev/ttyUSB0`: Il ne s'agit pas d'une auto détection mais simplement de la valeure la plus probable dans 99% des installations. Il est aussi possible d'utiliser une URL supporté par [pyserial](https://pyserial.readthedocs.io/en/latest/url_handlers.html), ce qui peut s'avérer utile si le port série est connecté sur un appareil distant (support de la rfc2217 par exemple).
- `Mode TIC` Choississez entre `Standard` et `Historique`. Plus de détails sur ces 2 modes en début de ce document.
- `Triphasé` À cocher si votre compteur est un compteur... triphasé. À noter que cette option n'a d'effet que si vous êtes en mode historique (le mode standard gère le mono et le tri de manière indifférente).

Validez et patientez pendant le temps du test. Celui-ci va tenter d'ouvrir une connection série sur le périphérique désigné et d'y lire au moins une ligne. En cas d'erreur, celle-ci vous sera retourné à l'écran de configuration. Sinon, votre nouvelle intégration est prête et disponible dans la liste des intégrations de la page où vous vous trouvez.

Expand Down
26 changes: 18 additions & 8 deletions custom_components/linkytic/__init__.py
Original file line number Diff line number Diff line change
@@ -1,24 +1,25 @@
"""The linkytic integration."""

from __future__ import annotations
import asyncio

import asyncio
import logging

from homeassistant.config_entries import ConfigEntry, ConfigEntryNotReady
from homeassistant.components import usb
from homeassistant.config_entries import ConfigEntry
from homeassistant.const import EVENT_HOMEASSISTANT_STOP, Platform
from homeassistant.core import HomeAssistant
from homeassistant.components import usb
from homeassistant.exceptions import ConfigEntryNotReady

from .const import (
DOMAIN,
LINKY_IO_ERRORS,
OPTIONS_REALTIME,
SETUP_PRODUCER,
SETUP_SERIAL,
SETUP_THREEPHASE,
SETUP_TICMODE,
SETUP_PRODUCER,
TICMODE_STANDARD,
LINKY_IO_ERRORS,
)
from .serial_reader import LinkyTICReader

Expand All @@ -45,6 +46,9 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
async def read_serial_number(serial: LinkyTICReader):
while serial.serial_number is None:
await asyncio.sleep(1)
# Check for any serial error that occurred in the serial thread context
if serial.setup_error:
raise serial.setup_error
return serial.serial_number

s_n = await asyncio.wait_for(read_serial_number(serial_reader), timeout=5)
Expand Down Expand Up @@ -103,14 +107,18 @@ async def update_listener(hass: HomeAssistant, entry: ConfigEntry):

async def async_migrate_entry(hass: HomeAssistant, config_entry: ConfigEntry):
"""Migrate old entry."""
_LOGGER.info("Migrating from version %d.%d", config_entry.version, config_entry.minor_version)
_LOGGER.info(
"Migrating from version %d.%d", config_entry.version, config_entry.minor_version
)

if config_entry.version == 1:
new = {**config_entry.data}

if config_entry.minor_version < 2:
# Migrate to serial by-id.
serial_by_id = await hass.async_add_executor_job(usb.get_serial_by_id, new[SETUP_SERIAL])
serial_by_id = await hass.async_add_executor_job(
usb.get_serial_by_id, new[SETUP_SERIAL]
)
if serial_by_id == new[SETUP_SERIAL]:
_LOGGER.warning(
f"Couldn't find a persistent /dev/serial/by-id alias for {serial_by_id}. "
Expand All @@ -120,7 +128,9 @@ async def async_migrate_entry(hass: HomeAssistant, config_entry: ConfigEntry):
new[SETUP_SERIAL] = serial_by_id

# config_entry.minor_version = 2
hass.config_entries.async_update_entry(config_entry, data=new, minor_version=2, version=1) # type: ignore
hass.config_entries.async_update_entry(
config_entry, data=new, minor_version=2, version=1
) # type: ignore

_LOGGER.info(
"Migration to version %d.%d successful",
Expand Down
Loading
Loading