From 9a377523dc4a04e083407c8acdbd6ec38983b37f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jacek=20Zi=C3=B3=C5=82kowski?= Date: Fri, 13 Sep 2024 02:43:16 +0200 Subject: [PATCH] enable status response tests (#269) --- pyproject.toml | 2 +- tdmgr/GUI/dialogs/main.py | 2 +- tdmgr/schemas/common.py | 13 + tdmgr/schemas/status.py | 245 +++++++++++------- .../jsonfiles/12.2.0.2/STATUS.json | 36 ++- .../jsonfiles/12.2.0.2/STATUS1.json | 18 +- .../jsonfiles/12.2.0.2/STATUS2.json | 13 +- .../jsonfiles/14.2.0.4/STATUS5.1.json | 28 ++ .../jsonfiles/14.2.0.4/STATUS5.json | 28 ++ .../jsonfiles/6.3.0.12/STATE.json | 14 +- .../jsonfiles/6.3.0.12/STATUS.json | 31 ++- .../jsonfiles/6.3.0.12/STATUS1.json | 15 +- .../jsonfiles/6.3.0.12/STATUS10.json | 11 +- .../jsonfiles/6.3.0.12/STATUS11.json | 16 +- .../jsonfiles/6.3.0.12/STATUS2.json | 10 +- .../jsonfiles/6.3.0.12/STATUS3.json | 20 +- .../jsonfiles/6.3.0.12/STATUS4.json | 19 +- .../jsonfiles/6.3.0.12/STATUS5.json | 13 +- .../jsonfiles/6.3.0.12/STATUS6.json | 13 +- .../jsonfiles/6.3.0.12/STATUS7.json | 12 +- .../jsonfiles/7.0.0.4/STATE.json | 20 +- tests/status_parsing/test_status_schemas.py | 10 +- 22 files changed, 470 insertions(+), 119 deletions(-) create mode 100644 tests/status_parsing/jsonfiles/14.2.0.4/STATUS5.1.json create mode 100644 tests/status_parsing/jsonfiles/14.2.0.4/STATUS5.json diff --git a/pyproject.toml b/pyproject.toml index 141127c..1d6e1ae 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -19,7 +19,7 @@ classifiers = [ "Development Status :: 4 - Beta", ] dependencies = [ - "paho_mqtt>=1.4", + "paho_mqtt>=1.4,<2", "PyQt5>=5.14.2,<6" ] requires-python = ">=3.8" diff --git a/tdmgr/GUI/dialogs/main.py b/tdmgr/GUI/dialogs/main.py index 4919c33..f4b9309 100644 --- a/tdmgr/GUI/dialogs/main.py +++ b/tdmgr/GUI/dialogs/main.py @@ -560,7 +560,7 @@ def openTelemetry(self): if self.device: tele_widget = TelemetryWidget(self.device) self.addDockWidget(Qt.RightDockWidgetArea, tele_widget) - self.mqtt_publish(self.device.cmnd_topic("STATUS"), "10") + self.mqtt_publish(self.device.cmnd_topic("STATUS"), "8") self.tele_docks.append(tele_widget) self.resizeDocks( self.tele_docks, [100 // len(self.tele_docks) for _ in self.tele_docks], Qt.Vertical diff --git a/tdmgr/schemas/common.py b/tdmgr/schemas/common.py index 6c0d3a1..83c0427 100644 --- a/tdmgr/schemas/common.py +++ b/tdmgr/schemas/common.py @@ -1,6 +1,19 @@ +import logging from enum import Enum +from pydantic import BaseModel, ConfigDict, model_validator + class OnOffEnum(str, Enum): ON = "ON" OFF = "OFF" + + +class TDMBaseModel(BaseModel): + model_config = ConfigDict(extra="allow") + + @model_validator(mode="after") + def log_extra_fields(cls, values): + if cls.__name__ != "StatusSNSSchema" and values.model_extra: + logging.warning("%s has extra fields: %s", cls.__name__, values.model_extra) + return values diff --git a/tdmgr/schemas/status.py b/tdmgr/schemas/status.py index eca9d65..6bbffa4 100644 --- a/tdmgr/schemas/status.py +++ b/tdmgr/schemas/status.py @@ -1,166 +1,206 @@ from typing import List, Optional, Union -from pydantic import BaseModel, create_model +from pydantic import create_model +from tdmgr.schemas.common import TDMBaseModel -class StatusSchema(BaseModel): - Module: int + +class StatusSchema(TDMBaseModel): + ButtonRetain: int + ButtonTopic: str DeviceName: Optional[str] = None FriendlyName: List[str] - Topic: str - ButtonTopic: str + InfoRetain: Optional[int] = None + LedMask: Optional[str] = None + LedState: int + Module: int Power: int + PowerLock: Optional[str] = None PowerOnState: int - LedState: int - LedMask: Optional[str] = None + PowerRetain: int SaveData: int SaveState: int - SwitchTopic: str + SensorRetain: int + StateRetain: Optional[int] = None + StatusRetain: Optional[int] = None SwitchMode: List[int] - ButtonRetain: int SwitchRetain: int - SensorRetain: int - PowerRetain: int + SwitchTopic: str + Topic: str -class StatusPRMSchema(BaseModel): +class StatusPRMSchema(TDMBaseModel): + BCResetTime: Optional[str] = None Baudrate: int + BootCount: int + CfgHolder: Optional[int] = None GroupTopic: str OtaUrl: str RestartReason: str - Uptime: str - StartupUTC: str - Sleep: int - CfgHolder: Optional[int] = None - BootCount: int - SaveCount: int SaveAddress: Optional[str] = None + SaveCount: int + SerialConfig: Optional[str] = None + Sleep: int + StartupUTC: str + Uptime: str -class StatusFWRSchema(BaseModel): - Version: str - BuildDateTime: str +class StatusFWRSchema(TDMBaseModel): Boot: Optional[int] = None + BuildDateTime: str + CR: Optional[str] = None Core: Optional[str] = None - SDK: str + CpuFrequency: Optional[int] = None Hardware: Optional[str] = None + SDK: str + Version: str -class StatusLOGSchema(BaseModel): - SerialLog: int - WebLog: int - MqttLog: int - SysLog: int +class StatusLOGSchema(TDMBaseModel): LogHost: str LogPort: int + MqttLog: Optional[int] = None + Resolution: Optional[str] = None SSId: List[str] - TelePeriod: int - Resolution: str + SerialLog: int SetOption: List[str] + SysLog: int + TelePeriod: int + WebLog: int -class StatusMEMSchema(BaseModel): - ProgramSize: int +class StatusMEMSchema(TDMBaseModel): + Drivers: Optional[str] = None + Features: List[str] + FlashChipId: str + FlashFrequency: Optional[int] = None + FlashMode: Optional[Union[int, str]] = None + FlashSize: int Free: int Heap: int + I2CDriver: Optional[str] = None ProgramFlashSize: int - FlashSize: int - FlashChipId: str - FlashMode: Optional[Union[int, str]] = None - Features: List[str] - Drivers: str - Sensors: str + ProgramSize: int + PsrFree: Optional[int] = None + PsrMax: Optional[int] = None + Sensors: Optional[str] = None + StackLowMark: Optional[int] = None -class StatusNETSchema(BaseModel): +class BaseNETSchema(TDMBaseModel): + DNSServer1: Optional[str] = None + DNSServer2: Optional[str] = None + DNSServer: Optional[str] = None + Gateway: str + HTTP_API: Optional[int] = None Hostname: str + IP6Global: Optional[str] = None + IP6Local: Optional[str] = None IPAddress: str - Gateway: str - Subnetmask: str - DNSServer: Optional[str] = None Mac: str + Subnetmask: str + + +class StatusNETSchema(BaseNETSchema): + Ethernet: Optional[BaseNETSchema] = None Webserver: int WifiConfig: int + WifiPower: Optional[int] = None -class StatusMQTSchema(BaseModel): +class StatusMQTSchema(TDMBaseModel): + KEEPALIVE: int + MAX_PACKET_SIZE: int + MqttClient: str + MqttClientMask: str + MqttCount: Optional[int] = None MqttHost: str MqttPort: int - MqttClientMask: str - MqttClient: str + MqttType: Optional[int] = None MqttUser: str - MqttCount: int - MAX_PACKET_SIZE: int - KEEPALIVE: int + SOCKET_TIMEOUT: Optional[int] = None -class StatusPTHSchema(BaseModel): +class StatusPTHSchema(TDMBaseModel): + CurrentHigh: Union[int, List[int]] + CurrentLow: Union[int, List[int]] + MaxEnergy: Optional[int] = None + MaxEnergyStart: Optional[int] = None + MaxPower: Optional[int] = None + MaxPowerHold: Optional[int] = None + MaxPowerWindow: Optional[int] = None PowerDelta: Union[int, List[int]] - PowerLow: Union[int, List[int]] PowerHigh: Union[int, List[int]] + PowerLow: Union[int, List[int]] + VoltageHigh: Optional[int] = None VoltageLow: Union[int, List[int]] - CurrentLow: Union[int, List[int]] - CurrentHigh: Union[int, List[int]] -class StatusSTKSchema(BaseModel): - Exception: int - Reason: str +class StatusSTKSchema(TDMBaseModel): + CallChain: List[str] + DEPC: str EPC: List[str] EXCVADDR: str - DEPC: str - CallChain: List[str] + Exception: int + Reason: str -class StatusTIMSchema(BaseModel): - UTC: str +class StatusSNSSchema(TDMBaseModel): + TempUnit: Optional[str] = None + Time: str + + +class StatusTIMSchema(TDMBaseModel): + EndDST: str Local: str StartDST: str - EndDST: str - Timezone: Union[str, int] Sunrise: Optional[str] = None Sunset: Optional[str] = None + Timezone: Union[str, int] + UTC: str -class WifiSchema(BaseModel): +class WifiSchema(TDMBaseModel): AP: int - SSId: str BSSId: str Channel: Union[int, List[int]] + Downtime: Optional[str] = None + LinkCount: Optional[int] = None + Mode: Optional[str] = None RSSI: int + SSId: str Signal: Optional[int] = None - LinkCount: int - Downtime: str -class BerrySchema(BaseModel): +class BerrySchema(TDMBaseModel): HeapUsed: int Objects: int -class StateSTSBaseSchema(BaseModel): +class StateSTSBaseSchema(TDMBaseModel): + Berry: Optional[BerrySchema] = None + Channel: Optional[List[int]] = None + Color: Optional[str] = None + Fade: Optional[str] = None + HSBColor: Optional[str] = None + Heap: Optional[int] = None + LedTable: Optional[str] = None + LoadAvg: Optional[int] = None + MqttCount: Optional[int] = None + Scheme: Optional[int] = None + Sleep: Optional[int] = None + SleepMode: Optional[str] = None + Speed: Optional[int] = None Time: str Uptime: str - UptimeSec: int - Heap: int - SleepMode: str - Sleep: int - LoadAvg: int - MqttCount: int + UptimeSec: Optional[int] = None + Vcc: Optional[float] = None + White: Optional[int] = None Wifi: WifiSchema class StateBaseSchema(StateSTSBaseSchema): - Vcc: Optional[float] = None Dimmer: Optional[int] = None - Color: Optional[str] = None - HSBColor: Optional[str] = None - Channel: Optional[Union[int, List[int]]] = None - Scheme: Optional[int] = None - Fade: Optional[str] = None - Speed: Optional[int] = None - LedTable: Optional[str] = None - Berry: Optional[BerrySchema] = None StateSchema = create_model( @@ -169,69 +209,77 @@ class StateBaseSchema(StateSTSBaseSchema): **{f"POWER{idx}": (Optional[str], None) for idx in list(map(str, range(1, 33))) + [""]}, ) +_power_dict = {f"POWER{idx}": (Optional[str], None) for idx in list(map(str, range(1, 33))) + [""]} +_dimmer_dict = {f"Dimmer{idx}": (Optional[int], None) for idx in list(map(str, range(1, 6))) + [""]} +_channel_dict = {f"Channel{idx}": (Optional[int], None) for idx in list(map(str, range(1, 6)))} + StatusSTSSchema = create_model( 'StatusSTSSchema', __base__=StateSTSBaseSchema, - **{f"POWER{idx}": (Optional[str], None) for idx in list(map(str, range(1, 33))) + [""]}, + **{**_power_dict, **_dimmer_dict, **_channel_dict}, ) -class StatusResponseSchema(BaseModel): +class StatusResponseSchema(TDMBaseModel): Status: StatusSchema -class Status1ResponseSchema(BaseModel): +class Status1ResponseSchema(TDMBaseModel): StatusPRM: StatusPRMSchema -class Status2ResponseSchema(BaseModel): +class Status2ResponseSchema(TDMBaseModel): StatusFWR: StatusFWRSchema -class Status3ResponseSchema(BaseModel): +class Status3ResponseSchema(TDMBaseModel): StatusLOG: StatusLOGSchema -class Status4ResponseSchema(BaseModel): +class Status4ResponseSchema(TDMBaseModel): StatusMEM: StatusMEMSchema -class Status5ResponseSchema(BaseModel): +class Status5ResponseSchema(TDMBaseModel): StatusNET: StatusNETSchema -class Status6ResponseSchema(BaseModel): +class Status6ResponseSchema(TDMBaseModel): StatusMQT: StatusMQTSchema -class Status7ResponseSchema(BaseModel): +class Status7ResponseSchema(TDMBaseModel): StatusTIM: StatusTIMSchema -class Status9ResponseSchema(BaseModel): +class Status9ResponseSchema(TDMBaseModel): StatusPTH: StatusPTHSchema -class Status11ResponseSchema(BaseModel): +class Status10ResponseSchema(TDMBaseModel): + StatusSNS: StatusSNSSchema + + +class Status11ResponseSchema(TDMBaseModel): StatusSTS: StatusSTSSchema -class Status12ResponseSchema(BaseModel): +class Status12ResponseSchema(TDMBaseModel): StatusSTK: StatusSTKSchema class Status0ResponseSchema(StatusResponseSchema): - StatusPRM: StatusPRMSchema + # StatusSTS: Optional[Json] StatusFWR: StatusFWRSchema StatusLOG: StatusLOGSchema StatusMEM: StatusMEMSchema - StatusNET: StatusNETSchema StatusMQT: Optional[StatusMQTSchema] - # StatusSNS: Optional[Status10ResponseSchema] - # StatusSTS: Optional[Json] + StatusNET: StatusNETSchema + StatusPRM: StatusPRMSchema + StatusSNS: Optional[Status10ResponseSchema] -STATUS_SCHEMA_MAP: [str, BaseModel] = { +STATUS_SCHEMA_MAP: [str, TDMBaseModel] = { 'STATE': StateSchema, 'STATUS': StatusResponseSchema, 'STATUS0': Status0ResponseSchema, @@ -243,6 +291,7 @@ class Status0ResponseSchema(StatusResponseSchema): 'STATUS6': Status6ResponseSchema, 'STATUS7': Status7ResponseSchema, 'STATUS9': Status9ResponseSchema, + 'STATUS10': Status10ResponseSchema, 'STATUS11': Status11ResponseSchema, 'STATUS12': Status12ResponseSchema, } diff --git a/tests/status_parsing/jsonfiles/12.2.0.2/STATUS.json b/tests/status_parsing/jsonfiles/12.2.0.2/STATUS.json index ce8cfa6..4280368 100644 --- a/tests/status_parsing/jsonfiles/12.2.0.2/STATUS.json +++ b/tests/status_parsing/jsonfiles/12.2.0.2/STATUS.json @@ -1 +1,35 @@ -{"Status":{"Module":6,"DeviceName":"Tasmota","FriendlyName":["Tasmota"],"Topic":"tasmota_1A704F","ButtonTopic":"0","Power":1,"PowerOnState":3,"LedState":1,"LedMask":"FFFF","SaveData":1,"SaveState":1,"SwitchTopic":"0","SwitchMode":[0,0,0,0,0,0,0,0],"ButtonRetain":0,"SwitchRetain":0,"SensorRetain":0,"PowerRetain":0,"InfoRetain":0,"StateRetain":0,"StatusRetain":0}} \ No newline at end of file +{ + "Status": { + "Module": 6, + "DeviceName": "Tasmota", + "FriendlyName": [ + "Tasmota" + ], + "Topic": "tasmota_1A704F", + "ButtonTopic": "0", + "Power": 1, + "PowerOnState": 3, + "LedState": 1, + "LedMask": "FFFF", + "SaveData": 1, + "SaveState": 1, + "SwitchTopic": "0", + "SwitchMode": [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "ButtonRetain": 0, + "SwitchRetain": 0, + "SensorRetain": 0, + "PowerRetain": 0, + "InfoRetain": 0, + "StateRetain": 0, + "StatusRetain": 0 + } +} \ No newline at end of file diff --git a/tests/status_parsing/jsonfiles/12.2.0.2/STATUS1.json b/tests/status_parsing/jsonfiles/12.2.0.2/STATUS1.json index a7c6a6c..062e9ee 100644 --- a/tests/status_parsing/jsonfiles/12.2.0.2/STATUS1.json +++ b/tests/status_parsing/jsonfiles/12.2.0.2/STATUS1.json @@ -1 +1,17 @@ -{"StatusPRM":{"Baudrate":115200,"SerialConfig":"8N1","GroupTopic":"tasmotas","OtaUrl":"http://ota.tasmota.com/tasmota/release/tasmota.bin.gz","RestartReason":"Power On","Uptime":"94T04:19:39","StartupUTC":"2023-10-09T15:15:19","Sleep":50,"CfgHolder":4617,"BootCount":12,"BCResetTime":"2022-11-05T18:47:52","SaveCount":896,"SaveAddress":"FB000"}} +{ + "StatusPRM": { + "Baudrate": 115200, + "SerialConfig": "8N1", + "GroupTopic": "tasmotas", + "OtaUrl": "http://ota.tasmota.com/tasmota/release/tasmota.bin.gz", + "RestartReason": "Power On", + "Uptime": "94T04:19:39", + "StartupUTC": "2023-10-09T15:15:19", + "Sleep": 50, + "CfgHolder": 4617, + "BootCount": 12, + "BCResetTime": "2022-11-05T18:47:52", + "SaveCount": 896, + "SaveAddress": "FB000" + } +} diff --git a/tests/status_parsing/jsonfiles/12.2.0.2/STATUS2.json b/tests/status_parsing/jsonfiles/12.2.0.2/STATUS2.json index 6aa5d7f..20c20d8 100644 --- a/tests/status_parsing/jsonfiles/12.2.0.2/STATUS2.json +++ b/tests/status_parsing/jsonfiles/12.2.0.2/STATUS2.json @@ -1 +1,12 @@ -{"StatusFWR":{"Version":"12.2.0.2(tasmota)","BuildDateTime":"2022-11-03T16:54:39","Boot":31,"Core":"2_7_4_9","SDK":"2.2.2-dev(38a443e)","CpuFrequency":80,"Hardware":"ESP8266EX","CR":"369/699"}} +{ + "StatusFWR": { + "Version": "12.2.0.2(tasmota)", + "BuildDateTime": "2022-11-03T16:54:39", + "Boot": 31, + "Core": "2_7_4_9", + "SDK": "2.2.2-dev(38a443e)", + "CpuFrequency": 80, + "Hardware": "ESP8266EX", + "CR": "369/699" + } +} diff --git a/tests/status_parsing/jsonfiles/14.2.0.4/STATUS5.1.json b/tests/status_parsing/jsonfiles/14.2.0.4/STATUS5.1.json new file mode 100644 index 0000000..3a82b2a --- /dev/null +++ b/tests/status_parsing/jsonfiles/14.2.0.4/STATUS5.1.json @@ -0,0 +1,28 @@ +{ + "StatusNET": { + "Hostname": "tasmota-68FF94-8084", + "IPAddress": "0.0.0.0", + "Gateway": "192.168.7.1", + "Subnetmask": "255.255.255.0", + "DNSServer1": "192.168.7.1", + "DNSServer2": "0.0.0.0", + "Mac": "34:98:7A:68:FF:94", + "IP6Global": "", + "IP6Local": "", + "Ethernet": { + "Hostname": "tasmota-68FF94-8084eth", + "IPAddress": "192.168.7.187", + "Gateway": "192.168.7.1", + "Subnetmask": "255.255.255.0", + "DNSServer1": "192.168.7.1", + "DNSServer2": "0.0.0.0", + "Mac": "34:98:7A:68:FF:97", + "IP6Global": "", + "IP6Local": "fe80::3698:7aff:fe68:ff97%en1" + }, + "Webserver": 2, + "HTTP_API": 1, + "WifiConfig": 0, + "WifiPower": 17.0 + } +} \ No newline at end of file diff --git a/tests/status_parsing/jsonfiles/14.2.0.4/STATUS5.json b/tests/status_parsing/jsonfiles/14.2.0.4/STATUS5.json new file mode 100644 index 0000000..73c6a4e --- /dev/null +++ b/tests/status_parsing/jsonfiles/14.2.0.4/STATUS5.json @@ -0,0 +1,28 @@ +{ + "StatusNET": { + "Hostname": "xxxxxxxx", + "IPAddress": "192.168.0.1", + "Gateway": "192.168.0.99", + "Subnetmask": "255.255.254.0", + "DNSServer1": "192.168.0.99", + "DNSServer2": "0.0.0.0", + "Mac": "xx:xx:xx:xx:xx:xx", + "IP6Global": "xxxx:::::::xxxx", + "IP6Local": "fe80::xxxx:xxxx:xxxx:xxxx%st3", + "Ethernet": { + "Hostname": "xxxxxxxx-eth", + "IPAddress": "192.168.0.2", + "Gateway": "192.168.0.99", + "Subnetmask": "255.255.254.0", + "DNSServer1": "192.168.0.99", + "DNSServer2": "0.0.0.0", + "Mac": "xx:xx:xx:xx:xx:xx", + "IP6Global": "xxxx:::::::xxxx", + "IP6Local": "fe80::xxxx:xxxx:xxxx:xxxx%en1" + }, + "Webserver": 2, + "HTTP_API": 1, + "WifiConfig": 4, + "WifiPower": 0.0 + } +} \ No newline at end of file diff --git a/tests/status_parsing/jsonfiles/6.3.0.12/STATE.json b/tests/status_parsing/jsonfiles/6.3.0.12/STATE.json index 95cee06..5daa964 100644 --- a/tests/status_parsing/jsonfiles/6.3.0.12/STATE.json +++ b/tests/status_parsing/jsonfiles/6.3.0.12/STATE.json @@ -1 +1,13 @@ -{"Time":"2024-01-12T06:29:01","Uptime":"2T05:25:48","Vcc":3.258,"POWER1":"OFF","Wifi":{"AP":1,"SSId":"xxx","BSSId":"F0:9F:C2:03:CD:73","Channel":6,"RSSI":100}} +{ + "Time": "2024-01-12T06:29:01", + "Uptime": "2T05:25:48", + "Vcc": 3.258, + "POWER1": "OFF", + "Wifi": { + "AP": 1, + "SSId": "xxx", + "BSSId": "F0:9F:C2:03:CD:73", + "Channel": 6, + "RSSI": 100 + } +} diff --git a/tests/status_parsing/jsonfiles/6.3.0.12/STATUS.json b/tests/status_parsing/jsonfiles/6.3.0.12/STATUS.json index 70f2201..826b85a 100644 --- a/tests/status_parsing/jsonfiles/6.3.0.12/STATUS.json +++ b/tests/status_parsing/jsonfiles/6.3.0.12/STATUS.json @@ -1 +1,30 @@ -{"Status":{"Module":1,"FriendlyName":["Sonoff_1"],"Topic":"sonoff_1","ButtonTopic":"0","Power":1,"PowerOnState":3,"LedState":1,"SaveData":1,"SaveState":1,"SwitchTopic":"0","SwitchMode":[0,0,0,0,0,0,0,0],"ButtonRetain":0,"SwitchRetain":0,"SensorRetain":0,"PowerRetain":0}} \ No newline at end of file +{ + "Status": { + "Module": 1, + "FriendlyName": [ + "Sonoff_1" + ], + "Topic": "sonoff_1", + "ButtonTopic": "0", + "Power": 1, + "PowerOnState": 3, + "LedState": 1, + "SaveData": 1, + "SaveState": 1, + "SwitchTopic": "0", + "SwitchMode": [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "ButtonRetain": 0, + "SwitchRetain": 0, + "SensorRetain": 0, + "PowerRetain": 0 + } +} \ No newline at end of file diff --git a/tests/status_parsing/jsonfiles/6.3.0.12/STATUS1.json b/tests/status_parsing/jsonfiles/6.3.0.12/STATUS1.json index 955c8f1..4d865f2 100644 --- a/tests/status_parsing/jsonfiles/6.3.0.12/STATUS1.json +++ b/tests/status_parsing/jsonfiles/6.3.0.12/STATUS1.json @@ -1 +1,14 @@ -{"StatusPRM":{"Baudrate":115200,"GroupTopic":"sonoffs","OtaUrl":"http://sonoff.maddox.co.uk/tasmota/sonoff.ino.bin","RestartReason":"Hardware Watchdog","Uptime":"1T19:36:45","StartupUTC":"2024-01-10T00:03:13","Sleep":0,"BootCount":420,"SaveCount":10693,"SaveAddress":"F6000"}} +{ + "StatusPRM": { + "Baudrate": 115200, + "GroupTopic": "sonoffs", + "OtaUrl": "http://sonoff.maddox.co.uk/tasmota/sonoff.ino.bin", + "RestartReason": "Hardware Watchdog", + "Uptime": "1T19:36:45", + "StartupUTC": "2024-01-10T00:03:13", + "Sleep": 0, + "BootCount": 420, + "SaveCount": 10693, + "SaveAddress": "F6000" + } +} diff --git a/tests/status_parsing/jsonfiles/6.3.0.12/STATUS10.json b/tests/status_parsing/jsonfiles/6.3.0.12/STATUS10.json index 91cf7a4..3731aee 100644 --- a/tests/status_parsing/jsonfiles/6.3.0.12/STATUS10.json +++ b/tests/status_parsing/jsonfiles/6.3.0.12/STATUS10.json @@ -1 +1,10 @@ -{"StatusSNS":{"Time":"2024-01-11T20:39:58","AM2301":{"Temperature":23.9,"Humidity":24.4},"TempUnit":"C"}} +{ + "StatusSNS": { + "Time": "2024-01-11T20:39:58", + "AM2301": { + "Temperature": 23.9, + "Humidity": 24.4 + }, + "TempUnit": "C" + } +} diff --git a/tests/status_parsing/jsonfiles/6.3.0.12/STATUS11.json b/tests/status_parsing/jsonfiles/6.3.0.12/STATUS11.json index 1a9cf4d..a530494 100644 --- a/tests/status_parsing/jsonfiles/6.3.0.12/STATUS11.json +++ b/tests/status_parsing/jsonfiles/6.3.0.12/STATUS11.json @@ -1 +1,15 @@ -{"StatusSTS":{"Time":"2024-01-11T20:39:58","Uptime":"1T19:36:45","Vcc":3.231,"POWER1":"ON","Wifi":{"AP":1,"SSId":"xxx","BSSId":"F0:9F:C2:03:CD:73","Channel":6,"RSSI":100}}} +{ + "StatusSTS": { + "Time": "2024-01-11T20:39:58", + "Uptime": "1T19:36:45", + "Vcc": 3.231, + "POWER1": "ON", + "Wifi": { + "AP": 1, + "SSId": "xxx", + "BSSId": "F0:9F:C2:03:CD:73", + "Channel": 6, + "RSSI": 100 + } + } +} diff --git a/tests/status_parsing/jsonfiles/6.3.0.12/STATUS2.json b/tests/status_parsing/jsonfiles/6.3.0.12/STATUS2.json index 6c2039c..96a18cc 100644 --- a/tests/status_parsing/jsonfiles/6.3.0.12/STATUS2.json +++ b/tests/status_parsing/jsonfiles/6.3.0.12/STATUS2.json @@ -1 +1,9 @@ -{"StatusFWR":{"Version":"6.3.0.12(sonoff)","BuildDateTime":"2018-11-23T14:07:50","Boot":4,"Core":"2_3_0","SDK":"1.5.3(aec24ac9)"}} +{ + "StatusFWR": { + "Version": "6.3.0.12(sonoff)", + "BuildDateTime": "2018-11-23T14:07:50", + "Boot": 4, + "Core": "2_3_0", + "SDK": "1.5.3(aec24ac9)" + } +} diff --git a/tests/status_parsing/jsonfiles/6.3.0.12/STATUS3.json b/tests/status_parsing/jsonfiles/6.3.0.12/STATUS3.json index 52e4b0f..d14ac9d 100644 --- a/tests/status_parsing/jsonfiles/6.3.0.12/STATUS3.json +++ b/tests/status_parsing/jsonfiles/6.3.0.12/STATUS3.json @@ -1 +1,19 @@ -{"StatusLOG":{"SerialLog":2,"WebLog":2,"SysLog":0,"LogHost":"192.168.0.130","LogPort":514,"SSId":["xxx","xxx-2"],"TelePeriod":300,"SetOption":["54000009","55818000","00000001"]}} +{ + "StatusLOG": { + "SerialLog": 2, + "WebLog": 2, + "SysLog": 0, + "LogHost": "192.168.0.130", + "LogPort": 514, + "SSId": [ + "xxx", + "xxx-2" + ], + "TelePeriod": 300, + "SetOption": [ + "54000009", + "55818000", + "00000001" + ] + } +} diff --git a/tests/status_parsing/jsonfiles/6.3.0.12/STATUS4.json b/tests/status_parsing/jsonfiles/6.3.0.12/STATUS4.json index 4e16b31..62b4b48 100644 --- a/tests/status_parsing/jsonfiles/6.3.0.12/STATUS4.json +++ b/tests/status_parsing/jsonfiles/6.3.0.12/STATUS4.json @@ -1 +1,18 @@ -{"StatusMEM":{"ProgramSize":498,"Free":504,"Heap":18,"ProgramFlashSize":1024,"FlashSize":1024,"FlashChipId":"1440E0","FlashMode":3,"Features":["00000809","0FDAE794","240383A0","23B617CE","00003BC0"]}} +{ + "StatusMEM": { + "ProgramSize": 498, + "Free": 504, + "Heap": 18, + "ProgramFlashSize": 1024, + "FlashSize": 1024, + "FlashChipId": "1440E0", + "FlashMode": 3, + "Features": [ + "00000809", + "0FDAE794", + "240383A0", + "23B617CE", + "00003BC0" + ] + } +} diff --git a/tests/status_parsing/jsonfiles/6.3.0.12/STATUS5.json b/tests/status_parsing/jsonfiles/6.3.0.12/STATUS5.json index c3e5d28..46b6ff7 100644 --- a/tests/status_parsing/jsonfiles/6.3.0.12/STATUS5.json +++ b/tests/status_parsing/jsonfiles/6.3.0.12/STATUS5.json @@ -1 +1,12 @@ -{"StatusNET":{"Hostname":"sonoff_1-3937","IPAddress":"192.168.1.200","Gateway":"192.168.1.1","Subnetmask":"255.255.255.0","DNSServer":"192.168.1.130","Mac":"5C:CF:7F:E7:4F:61","Webserver":2,"WifiConfig":3}} +{ + "StatusNET": { + "Hostname": "sonoff_1-3937", + "IPAddress": "192.168.1.200", + "Gateway": "192.168.1.1", + "Subnetmask": "255.255.255.0", + "DNSServer": "192.168.1.130", + "Mac": "5C:CF:7F:E7:4F:61", + "Webserver": 2, + "WifiConfig": 3 + } +} diff --git a/tests/status_parsing/jsonfiles/6.3.0.12/STATUS6.json b/tests/status_parsing/jsonfiles/6.3.0.12/STATUS6.json index 65eac83..57f4930 100644 --- a/tests/status_parsing/jsonfiles/6.3.0.12/STATUS6.json +++ b/tests/status_parsing/jsonfiles/6.3.0.12/STATUS6.json @@ -1 +1,12 @@ -{"StatusMQT":{"MqttHost":"192.168.1.130","MqttPort":1883,"MqttClientMask":"DVES_%06X","MqttClient":"DVES_E74F61","MqttUser":"DVES_USER","MqttType":1,"MAX_PACKET_SIZE":1000,"KEEPALIVE":15}} +{ + "StatusMQT": { + "MqttHost": "192.168.1.130", + "MqttPort": 1883, + "MqttClientMask": "DVES_%06X", + "MqttClient": "DVES_E74F61", + "MqttUser": "DVES_USER", + "MqttType": 1, + "MAX_PACKET_SIZE": 1000, + "KEEPALIVE": 15 + } +} diff --git a/tests/status_parsing/jsonfiles/6.3.0.12/STATUS7.json b/tests/status_parsing/jsonfiles/6.3.0.12/STATUS7.json index a36d56b..c4d0be8 100644 --- a/tests/status_parsing/jsonfiles/6.3.0.12/STATUS7.json +++ b/tests/status_parsing/jsonfiles/6.3.0.12/STATUS7.json @@ -1 +1,11 @@ -{"StatusTIM":{"UTC":"Thu Jan 11 19:39:58 2024","Local":"Thu Jan 11 20:39:58 2024","StartDST":"Sun Mar 31 02:00:00 2024","EndDST":"Sun Oct 27 03:00:00 2024","Timezone":"+01:00","Sunrise":"08:41","Sunset":"17:14"}} +{ + "StatusTIM": { + "UTC": "Thu Jan 11 19:39:58 2024", + "Local": "Thu Jan 11 20:39:58 2024", + "StartDST": "Sun Mar 31 02:00:00 2024", + "EndDST": "Sun Oct 27 03:00:00 2024", + "Timezone": "+01:00", + "Sunrise": "08:41", + "Sunset": "17:14" + } +} diff --git a/tests/status_parsing/jsonfiles/7.0.0.4/STATE.json b/tests/status_parsing/jsonfiles/7.0.0.4/STATE.json index 27e500d..b2fecef 100644 --- a/tests/status_parsing/jsonfiles/7.0.0.4/STATE.json +++ b/tests/status_parsing/jsonfiles/7.0.0.4/STATE.json @@ -1 +1,19 @@ -{"Time":"2024-01-11T11:42:21","Uptime":"44T15:13:31","UptimeSec":3856411,"Heap":26,"SleepMode":"Dynamic","Sleep":50,"LoadAvg":19,"MqttCount":12,"Wifi":{"AP":1,"SSId":"asdqwe","BSSId":"AA:BB:CC:DD:EE:FF","Channel":6,"RSSI":66,"LinkCount":19,"Downtime":"0T02:15:08"}} \ No newline at end of file +{ + "Time": "2024-01-11T11:42:21", + "Uptime": "44T15:13:31", + "UptimeSec": 3856411, + "Heap": 26, + "SleepMode": "Dynamic", + "Sleep": 50, + "LoadAvg": 19, + "MqttCount": 12, + "Wifi": { + "AP": 1, + "SSId": "asdqwe", + "BSSId": "AA:BB:CC:DD:EE:FF", + "Channel": 6, + "RSSI": 66, + "LinkCount": 19, + "Downtime": "0T02:15:08" + } +} \ No newline at end of file diff --git a/tests/status_parsing/test_status_schemas.py b/tests/status_parsing/test_status_schemas.py index 86995b5..76f2fbd 100644 --- a/tests/status_parsing/test_status_schemas.py +++ b/tests/status_parsing/test_status_schemas.py @@ -1,3 +1,4 @@ +import logging import os import pytest @@ -5,7 +6,7 @@ from tdmgr.schemas.status import STATUS_SCHEMA_MAP -PATH = os.path.join('status_parsing', 'jsonfiles') +PATH = os.path.join(os.getcwd(), 'jsonfiles') def get_status_jsonfiles(): @@ -18,14 +19,15 @@ def get_status_jsonfiles(): return _files -@pytest.mark.skip(reason="WIP") @pytest.mark.parametrize("jsonfile", get_status_jsonfiles()) -def test_status_parsing(jsonfile): +def test_status_parsing(caplog, jsonfile): status_type = jsonfile.split(os.path.sep)[-1].split('.')[0] schema = STATUS_SCHEMA_MAP.get(status_type) with open(jsonfile, "r") as payload: try: - schema.model_validate_json(payload.read()) + with caplog.at_level(logging.DEBUG): + schema.model_validate_json(payload.read()) + assert "Schema has extra fields" not in caplog.text except ValidationError as e: pytest.fail(str(e))