"""Device status for IOmeter bridge and core""" import json from dataclasses import dataclass, field @dataclass class Bridge: """Represents the bridge device status""" rssi: int | None version: str | None @dataclass class Core: """Represents the core device status""" connection_status: str rssi: int | None version: str | None power_status: str | None attachment_status: str | None pin_status: str | None battery_level: int | None @dataclass class Device: """Represents the complete device information""" bridge: Bridge id: str core: Core @dataclass class Meter: """Represents the meter device.""" number: str | None class NullMeter(Meter): """Null Object for Meter to avoid None-attribute errors.""" def __init__(self) -> None: super().__init__(number=None) def __bool__(self) -> bool: return False @dataclass class Status: """Top level class representing the complete device status""" device: Device installation_id: str meter: Meter = field(default_factory=NullMeter) typename: str = "iometer.status.v1" @classmethod def from_json(cls, json_str: str) -> "Status": """Create a Status instance from JSON string""" data = json.loads(json_str) # Create bridge bridge_data = data["device"]["bridge"] bridge = Bridge( rssi=bridge_data.get("rssi"), version=bridge_data.get("version"), ) # Create Core core_data = data["device"]["core"] core = Core( connection_status=core_data["connectionStatus"], rssi=core_data.get("rssi", None), version=core_data.get("version", None), power_status=core_data.get("powerStatus", None), battery_level=core_data.get("batteryLevel", None), attachment_status=core_data.get("attachmentStatus", None), pin_status=core_data.get("pinStatus", None), ) # Create device device = Device(bridge=bridge, id=data["device"]["id"], core=core) # Create meter (use Null Object if missing) meter = ( Meter(number=data["meter"]["number"]) if data.get("meter") else NullMeter() ) # Create full status return cls(device=device, installation_id=data["installationId"], meter=meter) def to_json(self) -> str: """Convert the status to JSON string""" return json.dumps( { "__typename": self.typename, "installationId": self.installation_id, # If meter is a NullMeter, serialize as null "meter": {"number": self.meter.number} if self.meter else None, "device": { "bridge": { "rssi": self.device.bridge.rssi, "version": self.device.bridge.version, }, "id": self.device.id, "core": { "connectionStatus": self.device.core.connection_status, "rssi": self.device.core.rssi, "version": self.device.core.version, "powerStatus": self.device.core.power_status, "batteryLevel": self.device.core.battery_level, "attachmentStatus": self.device.core.attachment_status, "pinStatus": self.device.core.pin_status, }, }, } ) def __str__(self) -> str: return self.to_json()