Skip to content

1.5.2

Choose a tag to compare

@github-actions github-actions released this 06 Apr 13:58
50c793c

E-bloc România v1.5.2

Data: 2026-04-06
Versiune: v1.5.2
Tip: Bug fix + Refactorizare arhitectură


Problema

Toate entitățile (senzori, selectori, butoane) din toate asociațiile erau grupate sub un singur dispozitiv E-bloc România (10001) în Home Assistant. Un utilizator cu 3 asociații (50100, 50200, 50300) vedea totul la grămadă, fără separare logică.

În plus, entitățile din asociații diferite aveau coliziuni de entity_id — de exemplu sensor.ebloc_10001_factura_restanta exista o singură dată, deși ar fi trebuit să existe câte una per asociație.


Cauza rădăcină

DeviceInfo.identifiers folosea doar id_user ca identificator unic:

identifiers={(DOMAIN, str(id_user))}

Toate entitățile, indiferent de asociație, raportau același device. Home Assistant grupează entitățile după identifiers — dacă toate au aceeași valoare, toate ajung sub același dispozitiv.

Același lucru și la entity_id și unique_id — lipsea id_asoc, ceea ce cauza coliziuni între asociații.


Soluția aplicată

1. Dispozitive separate per asociație

Funcția _global_device(id_user) a fost eliminată complet. Înlocuită cu _association_device(id_user, id_asoc):

def _association_device(id_user: int, id_asoc) -> DeviceInfo:
    return DeviceInfo(
        identifiers={(DOMAIN, f"{id_user}_{id_asoc}")},
        name=f"E-bloc România ({id_asoc})",
        manufacturer="Ciprian Nicolae (cnecrea)",
        model="E-bloc România",
        entry_type=DeviceEntryType.SERVICE,
    )

Rezultat: fiecare asociație are propriul dispozitiv în HA.

2. Entități globale (Cont utilizator, Carduri salvate)

Aceste entități nu aparțin unei asociații specifice, dar nu mai avem dispozitiv global. Soluția: sunt atribuite primei asociații din coordinator data, prin funcția _first_association_id().

3. id_asoc inclus în toate identificatoarele per-asociație

Fișiere modificate: sensor.py, button.py, number.py

sensor.py — Senzori per asociație

Entitate unique_id (înainte) unique_id (după)
AsociatieSensor {DOMAIN}_{id_user}_asociatie {DOMAIN}_{id_user}_{id_asoc}_asociatie
IndexContorSensor {DOMAIN}_{id_user}_{id_contor} {DOMAIN}_{id_user}_{id_asoc}_{id_contor}
FacturaRestantaSensor {DOMAIN}_{id_user}_{id_ap}_factura_restanta {DOMAIN}_{id_user}_{id_asoc}_{id_ap}_factura_restanta
ArhivaPlatiSensor {DOMAIN}_{id_user}_{id_ap}_plati {DOMAIN}_{id_user}_{id_asoc}_{id_ap}_plati
NrPersoaneSensor {DOMAIN}_{id_user}_{id_ap}_nr_pers {DOMAIN}_{id_user}_{id_asoc}_{id_ap}_nr_pers
TicheteSensor {DOMAIN}_{id_user}_{id_ap}_tichete {DOMAIN}_{id_user}_{id_asoc}_{id_ap}_tichete
CitirePermisaSensor {DOMAIN}_{id_user}_{id_ap}_citire_permisa {DOMAIN}_{id_user}_{id_asoc}_{id_ap}_citire_permisa

Toate _custom_entity_id au fost actualizate cu același pattern (ex: sensor.ebloc_10001_50100_factura_restanta).

button.py — Butoane per asociație

Entitate unique_id (după) entity_id (după)
TrimiteIndexButton {DOMAIN}_{id_user}_{id_asoc}_{id_contor}_trimite_index button.{DOMAIN}_{id_user}_{id_asoc}_trimite_index_{titlu_slug}
TrimiteNrPersButton {DOMAIN}_{id_user}_{id_asoc}_{id_ap}_trimite_nr_pers button.{DOMAIN}_{id_user}_{id_asoc}_trimite_nr_persoane

number.py — Selectori per asociație

Entitate unique_id (după) entity_id (după)
NrPersoaneNumber {DOMAIN}_{id_user}_{id_asoc}_{id_ap}_nr_pers number.{DOMAIN}_{id_user}_{id_asoc}_nr_persoane_selector
IndexContorNumber {DOMAIN}_{id_user}_{id_asoc}_{id_contor}_index number.{DOMAIN}_{id_user}_{id_asoc}_index_{titlu_slug}_selector

4. Consistență cross-file (button ↔ number)

Verificat și confirmat:

  • TrimiteIndexButton._number_uid = IndexContorNumber._attr_unique_id = {DOMAIN}_{id_user}_{id_asoc}_{id_contor}_index
  • TrimiteNrPersButton._number_uid = NrPersoaneNumber._attr_unique_id = {DOMAIN}_{id_user}_{id_asoc}_{id_ap}_nr_pers

5. Bug critic reparat: cod mort în number.py

Inițializarea self._value (fallback cu ultimul index/nr. persoane din API) era plasată după return în proprietatea device_info — nu se executa niciodată. La runtime ar fi cauzat AttributeError pe native_value.

Reparat în ambele clase: NrPersoaneNumber și IndexContorNumber.

6. Coordinator: gestionare nologin pe ContoareGetIndexLuni

AppContoareGetIndexLuni.php returnează nologin selectiv pe unele asociații. Codul anterior nu detecta acest caz — nu era excepție, ci un răspuns valid cu aLuni: [].

Reparat:

  • Detecție explicită result == "nologin" cu marcare pentru retry
  • Re-autentificare automată (async_ensure_authenticated()) + retry doar pentru asociațiile afectate
  • Fallback robust: luna or datetime.now().strftime("%Y-%m") în loc de string gol
  • Logging la nivel INFO pentru fiecare asociație (sursă luna: GetIndexLuni sau fallback)

Clasele de bază actualizate

EblocEntity.device_info, EblocNumber.device_info și EblocButton.device_info — toate folosesc acum {id_user}_{id_asoc} ca pattern de identificare. Nu mai există nicio referință la _global_device sau la str(id_user) singur ca identifier.


Impact la upgrade

ATENȚIE: Această modificare schimbă unique_id și entity_id pentru toate entitățile per-asociație. La upgrade:

  • Entitățile vechi vor fi șterse automat din registry (unique_id diferit)
  • Entitățile noi vor fi create cu noile ID-uri
  • Automatizările, dashboard-urile și scripturile care referențiază entity_id-urile vechi trebuie actualizate manual
  • Dispozitivul global anterior (ex: E-bloc România (10001)) va rămâne orfan și poate fi șters manual din Setări → Dispozitive

📈 Integrarea în cifre

⭐ Stars 📥 Instalări 🔄 Clone (14z)
17 643 369

Dacă integrarea E-bloc România îți este utilă, lasă un ⭐ pe repository — îi ajută și pe alți utilizatori să o descopere.


💛 Dezvoltarea consumă timp și resurse. Dacă vrei să susții proiectul:
Buy Me a Coffee · 💰 GitHub Sponsors