Skip to content

Commit 78736ef

Browse files
authored
Merge pull request #54 from tomleglaunec/stge_fix
Fix status register decoding
2 parents 0523b14 + f2ce2f4 commit 78736ef

File tree

3 files changed

+132
-19
lines changed

3 files changed

+132
-19
lines changed

custom_components/linkytic/status_register.py

Lines changed: 27 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ def get_status(self, register: str) -> str | bool:
2020
int_register = int(register, base=16)
2121
except TypeError:
2222
return False
23-
val = (int_register >> self.lsb) & (1 << (self.len - 1))
23+
val = (int_register >> self.lsb) & ((1 << self.len) - 1)
2424

2525
if self.options is None:
2626
return bool(val)
@@ -43,10 +43,16 @@ def get_status(self, register: str) -> str | bool:
4343
etat_euridis = {
4444
0: "Désactivée",
4545
1: "Activée sans sécurité",
46-
2: "Activée avec sécurité",
46+
2: "Valeur non valide", # codespell:ignore
47+
3: "Activée avec sécurité",
4748
}
4849

49-
statut_cpl = {0: "New/Unlock", 1: "New/Lock", 2: "Registered"}
50+
statut_cpl = {
51+
0: "New/Unlock",
52+
1: "New/Lock",
53+
2: "Registered",
54+
3: "Valeur non valide", # codespell:ignore
55+
}
5056

5157
tempo_color = {
5258
0: "Pas d'annonce",
@@ -77,19 +83,21 @@ class StatusRegister(Enum):
7783

7884
CONTACT_SEC = StatusRegisterEnumValueType(0)
7985
ORGANE_DE_COUPURE = StatusRegisterEnumValueType(1, 3, organe_coupure)
80-
ETAT_DU_CACHE_BORNE_DISTRIBUTEUR = StatusRegisterEnumValueType(3)
81-
SURTENSION_SUR_UNE_DES_PHASES = StatusRegisterEnumValueType(5)
82-
DEPASSEMENT_PUISSANCE_REFERENCE = StatusRegisterEnumValueType(6)
83-
PRODUCTEUR_CONSOMMATEUR = StatusRegisterEnumValueType(7)
84-
SENS_ENERGIE_ACTIVE = StatusRegisterEnumValueType(8)
85-
TARIF_CONTRAT_FOURNITURE = StatusRegisterEnumValueType(9, 3, tarif_en_cours)
86-
TARIF_CONTRAT_DISTRIBUTEUR = StatusRegisterEnumValueType(13, 2, tarif_en_cours)
87-
MODE_DEGRADE_HORLOGE = StatusRegisterEnumValueType(15)
88-
MODE_TIC = StatusRegisterEnumValueType(16)
89-
ETAT_SORTIE_COMMUNICATION_EURIDIS = StatusRegisterEnumValueType(18, 2, etat_euridis)
90-
STATUS_CPL = StatusRegisterEnumValueType(20, 2, statut_cpl)
91-
SYNCHRO_CPL = StatusRegisterEnumValueType(22)
92-
COULEUR_JOUR_CONTRAT_TEMPO = StatusRegisterEnumValueType(23, 2, tempo_color)
93-
COULEUR_LENDEMAIN_CONTRAT_TEMPO = StatusRegisterEnumValueType(25, 2, tempo_color)
94-
PREAVIS_POINTES_MOBILES = StatusRegisterEnumValueType(27, 2, preavis_pm)
95-
POINTE_MOBILE = StatusRegisterEnumValueType(29, 2, pointe_mobile)
86+
ETAT_DU_CACHE_BORNE_DISTRIBUTEUR = StatusRegisterEnumValueType(4)
87+
# bit 5 is reserved
88+
SURTENSION_SUR_UNE_DES_PHASES = StatusRegisterEnumValueType(6)
89+
DEPASSEMENT_PUISSANCE_REFERENCE = StatusRegisterEnumValueType(7)
90+
PRODUCTEUR_CONSOMMATEUR = StatusRegisterEnumValueType(8)
91+
SENS_ENERGIE_ACTIVE = StatusRegisterEnumValueType(9)
92+
TARIF_CONTRAT_FOURNITURE = StatusRegisterEnumValueType(10, 4, tarif_en_cours)
93+
TARIF_CONTRAT_DISTRIBUTEUR = StatusRegisterEnumValueType(14, 2, tarif_en_cours)
94+
MODE_DEGRADE_HORLOGE = StatusRegisterEnumValueType(16)
95+
MODE_TIC = StatusRegisterEnumValueType(17)
96+
# bit 18 is reserved
97+
ETAT_SORTIE_COMMUNICATION_EURIDIS = StatusRegisterEnumValueType(19, 2, etat_euridis)
98+
STATUS_CPL = StatusRegisterEnumValueType(21, 2, statut_cpl)
99+
SYNCHRO_CPL = StatusRegisterEnumValueType(23)
100+
COULEUR_JOUR_CONTRAT_TEMPO = StatusRegisterEnumValueType(24, 2, tempo_color)
101+
COULEUR_LENDEMAIN_CONTRAT_TEMPO = StatusRegisterEnumValueType(26, 2, tempo_color)
102+
PREAVIS_POINTES_MOBILES = StatusRegisterEnumValueType(28, 2, preavis_pm)
103+
POINTE_MOBILE = StatusRegisterEnumValueType(30, 2, pointe_mobile)

tests/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
"""Tests for the linkytic custom component."""

tests/test_status_register.py

Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
"""Test the status register decoding."""
2+
3+
from custom_components.linkytic.status_register import (
4+
StatusRegister,
5+
etat_euridis,
6+
organe_coupure,
7+
pointe_mobile,
8+
preavis_pm,
9+
statut_cpl,
10+
tarif_en_cours,
11+
tempo_color,
12+
)
13+
14+
15+
def test_parse():
16+
STGE = "013AC501"
17+
18+
EXPECTED = {
19+
StatusRegister.CONTACT_SEC: 1,
20+
StatusRegister.ORGANE_DE_COUPURE: organe_coupure[0],
21+
StatusRegister.ETAT_DU_CACHE_BORNE_DISTRIBUTEUR: 0,
22+
StatusRegister.SURTENSION_SUR_UNE_DES_PHASES: 0,
23+
StatusRegister.DEPASSEMENT_PUISSANCE_REFERENCE: 0,
24+
StatusRegister.PRODUCTEUR_CONSOMMATEUR: 1,
25+
StatusRegister.SENS_ENERGIE_ACTIVE: 0,
26+
StatusRegister.TARIF_CONTRAT_FOURNITURE: tarif_en_cours[1],
27+
StatusRegister.TARIF_CONTRAT_DISTRIBUTEUR: tarif_en_cours[3],
28+
StatusRegister.MODE_DEGRADE_HORLOGE: 0,
29+
StatusRegister.MODE_TIC: 1,
30+
StatusRegister.ETAT_SORTIE_COMMUNICATION_EURIDIS: etat_euridis[3],
31+
StatusRegister.STATUS_CPL: statut_cpl[1],
32+
StatusRegister.SYNCHRO_CPL: 0,
33+
StatusRegister.COULEUR_JOUR_CONTRAT_TEMPO: tempo_color[1],
34+
StatusRegister.COULEUR_LENDEMAIN_CONTRAT_TEMPO: tempo_color[0],
35+
StatusRegister.PREAVIS_POINTES_MOBILES: preavis_pm[0],
36+
StatusRegister.POINTE_MOBILE: pointe_mobile[0],
37+
}
38+
39+
for element in StatusRegister:
40+
assert EXPECTED[element] == element.value.get_status(STGE)
41+
42+
STGE = "003AC000"
43+
44+
EXPECTED = {
45+
StatusRegister.CONTACT_SEC: 0,
46+
StatusRegister.ORGANE_DE_COUPURE: organe_coupure[0],
47+
StatusRegister.ETAT_DU_CACHE_BORNE_DISTRIBUTEUR: 0,
48+
StatusRegister.SURTENSION_SUR_UNE_DES_PHASES: 0,
49+
StatusRegister.DEPASSEMENT_PUISSANCE_REFERENCE: 0,
50+
StatusRegister.PRODUCTEUR_CONSOMMATEUR: 0,
51+
StatusRegister.SENS_ENERGIE_ACTIVE: 0,
52+
StatusRegister.TARIF_CONTRAT_FOURNITURE: tarif_en_cours[0],
53+
StatusRegister.TARIF_CONTRAT_DISTRIBUTEUR: tarif_en_cours[3],
54+
StatusRegister.MODE_DEGRADE_HORLOGE: 0,
55+
StatusRegister.MODE_TIC: 1,
56+
StatusRegister.ETAT_SORTIE_COMMUNICATION_EURIDIS: etat_euridis[3],
57+
StatusRegister.STATUS_CPL: statut_cpl[1],
58+
StatusRegister.SYNCHRO_CPL: 0,
59+
StatusRegister.COULEUR_JOUR_CONTRAT_TEMPO: tempo_color[0],
60+
StatusRegister.COULEUR_LENDEMAIN_CONTRAT_TEMPO: tempo_color[0],
61+
StatusRegister.PREAVIS_POINTES_MOBILES: preavis_pm[0],
62+
StatusRegister.POINTE_MOBILE: pointe_mobile[0],
63+
}
64+
65+
for element in StatusRegister:
66+
assert EXPECTED[element] == element.value.get_status(STGE)
67+
68+
STGE = "FFDFE7FD"
69+
70+
EXPECTED = {
71+
StatusRegister.CONTACT_SEC: 1,
72+
StatusRegister.ORGANE_DE_COUPURE: organe_coupure[6],
73+
StatusRegister.ETAT_DU_CACHE_BORNE_DISTRIBUTEUR: 1,
74+
StatusRegister.SURTENSION_SUR_UNE_DES_PHASES: 1,
75+
StatusRegister.DEPASSEMENT_PUISSANCE_REFERENCE: 1,
76+
StatusRegister.PRODUCTEUR_CONSOMMATEUR: 1,
77+
StatusRegister.SENS_ENERGIE_ACTIVE: 1,
78+
StatusRegister.TARIF_CONTRAT_FOURNITURE: tarif_en_cours[9],
79+
StatusRegister.TARIF_CONTRAT_DISTRIBUTEUR: tarif_en_cours[3],
80+
StatusRegister.MODE_DEGRADE_HORLOGE: 1,
81+
StatusRegister.MODE_TIC: 1,
82+
StatusRegister.ETAT_SORTIE_COMMUNICATION_EURIDIS: etat_euridis[3],
83+
StatusRegister.STATUS_CPL: statut_cpl[2],
84+
StatusRegister.SYNCHRO_CPL: 1,
85+
StatusRegister.COULEUR_JOUR_CONTRAT_TEMPO: tempo_color[3],
86+
StatusRegister.COULEUR_LENDEMAIN_CONTRAT_TEMPO: tempo_color[3],
87+
StatusRegister.PREAVIS_POINTES_MOBILES: preavis_pm[3],
88+
StatusRegister.POINTE_MOBILE: pointe_mobile[3],
89+
}
90+
91+
for element in StatusRegister:
92+
assert EXPECTED[element] == element.value.get_status(STGE)
93+
94+
def parse_stge(stge: str):
95+
for element in StatusRegister:
96+
print(element.name, element.value.get_status(stge))
97+
98+
if __name__ == "__main__":
99+
# Parse STGE, call this file as a module (python -m tests.test_status_register <STGE>)
100+
import sys
101+
if len(sys.argv) <= 1:
102+
print("No stge to parse.")
103+
sys.exit(1)
104+
parse_stge(sys.argv[1])

0 commit comments

Comments
 (0)