diff --git a/custom_components/linkytic/status_register.py b/custom_components/linkytic/status_register.py index 30b4f65..df8677e 100644 --- a/custom_components/linkytic/status_register.py +++ b/custom_components/linkytic/status_register.py @@ -20,7 +20,7 @@ def get_status(self, register: str) -> str | bool: int_register = int(register, base=16) except TypeError: return False - val = (int_register >> self.lsb) & (1 << (self.len - 1)) + val = (int_register >> self.lsb) & ((1 << self.len) - 1) if self.options is None: return bool(val) @@ -43,10 +43,16 @@ def get_status(self, register: str) -> str | bool: etat_euridis = { 0: "Désactivée", 1: "Activée sans sécurité", - 2: "Activée avec sécurité", + 2: "Valeur non valide", # codespell:ignore + 3: "Activée avec sécurité", } -statut_cpl = {0: "New/Unlock", 1: "New/Lock", 2: "Registered"} +statut_cpl = { + 0: "New/Unlock", + 1: "New/Lock", + 2: "Registered", + 3: "Valeur non valide", # codespell:ignore +} tempo_color = { 0: "Pas d'annonce", @@ -77,19 +83,21 @@ class StatusRegister(Enum): CONTACT_SEC = StatusRegisterEnumValueType(0) ORGANE_DE_COUPURE = StatusRegisterEnumValueType(1, 3, organe_coupure) - ETAT_DU_CACHE_BORNE_DISTRIBUTEUR = StatusRegisterEnumValueType(3) - SURTENSION_SUR_UNE_DES_PHASES = StatusRegisterEnumValueType(5) - DEPASSEMENT_PUISSANCE_REFERENCE = StatusRegisterEnumValueType(6) - PRODUCTEUR_CONSOMMATEUR = StatusRegisterEnumValueType(7) - SENS_ENERGIE_ACTIVE = StatusRegisterEnumValueType(8) - TARIF_CONTRAT_FOURNITURE = StatusRegisterEnumValueType(9, 3, tarif_en_cours) - TARIF_CONTRAT_DISTRIBUTEUR = StatusRegisterEnumValueType(13, 2, tarif_en_cours) - MODE_DEGRADE_HORLOGE = StatusRegisterEnumValueType(15) - MODE_TIC = StatusRegisterEnumValueType(16) - ETAT_SORTIE_COMMUNICATION_EURIDIS = StatusRegisterEnumValueType(18, 2, etat_euridis) - STATUS_CPL = StatusRegisterEnumValueType(20, 2, statut_cpl) - SYNCHRO_CPL = StatusRegisterEnumValueType(22) - COULEUR_JOUR_CONTRAT_TEMPO = StatusRegisterEnumValueType(23, 2, tempo_color) - COULEUR_LENDEMAIN_CONTRAT_TEMPO = StatusRegisterEnumValueType(25, 2, tempo_color) - PREAVIS_POINTES_MOBILES = StatusRegisterEnumValueType(27, 2, preavis_pm) - POINTE_MOBILE = StatusRegisterEnumValueType(29, 2, pointe_mobile) + ETAT_DU_CACHE_BORNE_DISTRIBUTEUR = StatusRegisterEnumValueType(4) + # bit 5 is reserved + SURTENSION_SUR_UNE_DES_PHASES = StatusRegisterEnumValueType(6) + DEPASSEMENT_PUISSANCE_REFERENCE = StatusRegisterEnumValueType(7) + PRODUCTEUR_CONSOMMATEUR = StatusRegisterEnumValueType(8) + SENS_ENERGIE_ACTIVE = StatusRegisterEnumValueType(9) + TARIF_CONTRAT_FOURNITURE = StatusRegisterEnumValueType(10, 4, tarif_en_cours) + TARIF_CONTRAT_DISTRIBUTEUR = StatusRegisterEnumValueType(14, 2, tarif_en_cours) + MODE_DEGRADE_HORLOGE = StatusRegisterEnumValueType(16) + MODE_TIC = StatusRegisterEnumValueType(17) + # bit 18 is reserved + ETAT_SORTIE_COMMUNICATION_EURIDIS = StatusRegisterEnumValueType(19, 2, etat_euridis) + STATUS_CPL = StatusRegisterEnumValueType(21, 2, statut_cpl) + SYNCHRO_CPL = StatusRegisterEnumValueType(23) + COULEUR_JOUR_CONTRAT_TEMPO = StatusRegisterEnumValueType(24, 2, tempo_color) + COULEUR_LENDEMAIN_CONTRAT_TEMPO = StatusRegisterEnumValueType(26, 2, tempo_color) + PREAVIS_POINTES_MOBILES = StatusRegisterEnumValueType(28, 2, preavis_pm) + POINTE_MOBILE = StatusRegisterEnumValueType(30, 2, pointe_mobile) diff --git a/tests/__init__.py b/tests/__init__.py new file mode 100644 index 0000000..ce367ce --- /dev/null +++ b/tests/__init__.py @@ -0,0 +1 @@ +"""Tests for the linkytic custom component.""" diff --git a/tests/test_status_register.py b/tests/test_status_register.py new file mode 100644 index 0000000..600ee43 --- /dev/null +++ b/tests/test_status_register.py @@ -0,0 +1,104 @@ +"""Test the status register decoding.""" + +from custom_components.linkytic.status_register import ( + StatusRegister, + etat_euridis, + organe_coupure, + pointe_mobile, + preavis_pm, + statut_cpl, + tarif_en_cours, + tempo_color, +) + + +def test_parse(): + STGE = "013AC501" + + EXPECTED = { + StatusRegister.CONTACT_SEC: 1, + StatusRegister.ORGANE_DE_COUPURE: organe_coupure[0], + StatusRegister.ETAT_DU_CACHE_BORNE_DISTRIBUTEUR: 0, + StatusRegister.SURTENSION_SUR_UNE_DES_PHASES: 0, + StatusRegister.DEPASSEMENT_PUISSANCE_REFERENCE: 0, + StatusRegister.PRODUCTEUR_CONSOMMATEUR: 1, + StatusRegister.SENS_ENERGIE_ACTIVE: 0, + StatusRegister.TARIF_CONTRAT_FOURNITURE: tarif_en_cours[1], + StatusRegister.TARIF_CONTRAT_DISTRIBUTEUR: tarif_en_cours[3], + StatusRegister.MODE_DEGRADE_HORLOGE: 0, + StatusRegister.MODE_TIC: 1, + StatusRegister.ETAT_SORTIE_COMMUNICATION_EURIDIS: etat_euridis[3], + StatusRegister.STATUS_CPL: statut_cpl[1], + StatusRegister.SYNCHRO_CPL: 0, + StatusRegister.COULEUR_JOUR_CONTRAT_TEMPO: tempo_color[1], + StatusRegister.COULEUR_LENDEMAIN_CONTRAT_TEMPO: tempo_color[0], + StatusRegister.PREAVIS_POINTES_MOBILES: preavis_pm[0], + StatusRegister.POINTE_MOBILE: pointe_mobile[0], + } + + for element in StatusRegister: + assert EXPECTED[element] == element.value.get_status(STGE) + + STGE = "003AC000" + + EXPECTED = { + StatusRegister.CONTACT_SEC: 0, + StatusRegister.ORGANE_DE_COUPURE: organe_coupure[0], + StatusRegister.ETAT_DU_CACHE_BORNE_DISTRIBUTEUR: 0, + StatusRegister.SURTENSION_SUR_UNE_DES_PHASES: 0, + StatusRegister.DEPASSEMENT_PUISSANCE_REFERENCE: 0, + StatusRegister.PRODUCTEUR_CONSOMMATEUR: 0, + StatusRegister.SENS_ENERGIE_ACTIVE: 0, + StatusRegister.TARIF_CONTRAT_FOURNITURE: tarif_en_cours[0], + StatusRegister.TARIF_CONTRAT_DISTRIBUTEUR: tarif_en_cours[3], + StatusRegister.MODE_DEGRADE_HORLOGE: 0, + StatusRegister.MODE_TIC: 1, + StatusRegister.ETAT_SORTIE_COMMUNICATION_EURIDIS: etat_euridis[3], + StatusRegister.STATUS_CPL: statut_cpl[1], + StatusRegister.SYNCHRO_CPL: 0, + StatusRegister.COULEUR_JOUR_CONTRAT_TEMPO: tempo_color[0], + StatusRegister.COULEUR_LENDEMAIN_CONTRAT_TEMPO: tempo_color[0], + StatusRegister.PREAVIS_POINTES_MOBILES: preavis_pm[0], + StatusRegister.POINTE_MOBILE: pointe_mobile[0], + } + + for element in StatusRegister: + assert EXPECTED[element] == element.value.get_status(STGE) + + STGE = "FFDFE7FD" + + EXPECTED = { + StatusRegister.CONTACT_SEC: 1, + StatusRegister.ORGANE_DE_COUPURE: organe_coupure[6], + StatusRegister.ETAT_DU_CACHE_BORNE_DISTRIBUTEUR: 1, + StatusRegister.SURTENSION_SUR_UNE_DES_PHASES: 1, + StatusRegister.DEPASSEMENT_PUISSANCE_REFERENCE: 1, + StatusRegister.PRODUCTEUR_CONSOMMATEUR: 1, + StatusRegister.SENS_ENERGIE_ACTIVE: 1, + StatusRegister.TARIF_CONTRAT_FOURNITURE: tarif_en_cours[9], + StatusRegister.TARIF_CONTRAT_DISTRIBUTEUR: tarif_en_cours[3], + StatusRegister.MODE_DEGRADE_HORLOGE: 1, + StatusRegister.MODE_TIC: 1, + StatusRegister.ETAT_SORTIE_COMMUNICATION_EURIDIS: etat_euridis[3], + StatusRegister.STATUS_CPL: statut_cpl[2], + StatusRegister.SYNCHRO_CPL: 1, + StatusRegister.COULEUR_JOUR_CONTRAT_TEMPO: tempo_color[3], + StatusRegister.COULEUR_LENDEMAIN_CONTRAT_TEMPO: tempo_color[3], + StatusRegister.PREAVIS_POINTES_MOBILES: preavis_pm[3], + StatusRegister.POINTE_MOBILE: pointe_mobile[3], + } + + for element in StatusRegister: + assert EXPECTED[element] == element.value.get_status(STGE) + +def parse_stge(stge: str): + for element in StatusRegister: + print(element.name, element.value.get_status(stge)) + +if __name__ == "__main__": + # Parse STGE, call this file as a module (python -m tests.test_status_register ) + import sys + if len(sys.argv) <= 1: + print("No stge to parse.") + sys.exit(1) + parse_stge(sys.argv[1]) \ No newline at end of file