def process_ws_packet( self, packet: WSPacket, models: Optional[Set[ModelType]] = None, ignore_stats: bool = False) -> Optional[WSSubscriptionMessage]: if models is None: models = set() if not isinstance(packet.action_frame, WSJSONPacketFrame): _LOGGER.debug("Unexpected action frame format: %s", packet.action_frame.payload_format) if not isinstance(packet.data_frame, WSJSONPacketFrame): _LOGGER.debug("Unexpected data frame format: %s", packet.data_frame.payload_format) action, data = self._get_frame_data(packet) if action["newUpdateId"] is not None: self.last_update_id = UUID(action["newUpdateId"]) if action["modelKey"] not in ModelType.values(): _LOGGER.debug("Unknown model type: %s", action["modelKey"]) self._create_stat(packet, [], True) return None if len(models) > 0 and ModelType( action["modelKey"]) not in models or len(data) == 0: self._create_stat(packet, [], True) return None if action["action"] == "add": return self._process_add_packet(packet, data) if action["action"] == "update": if action["modelKey"] == ModelType.NVR.value: return self._process_nvr_update(packet, data, ignore_stats) if action["modelKey"] in ModelType.bootstrap_models( ) or action["modelKey"] == ModelType.EVENT.value: return self._process_device_update(packet, action, data, ignore_stats) _LOGGER.debug("Unexpected bootstrap model type for update: %s", action["modelKey"]) self._create_stat(packet, [], True) return None
def unifi_dict_to_dict(cls, data: Dict[str, Any]) -> Dict[str, Any]: for model_type in ModelType.bootstrap_models(): key = model_type + "s" items: Dict[str, ProtectModel] = {} for item in data[key]: items[item["id"]] = item data[key] = items return super().unifi_dict_to_dict(data)
def unifi_dict(self, data: Optional[Dict[str, Any]] = None, exclude: Optional[Set[str]] = None) -> Dict[str, Any]: data = super().unifi_dict(data=data, exclude=exclude) if "events" in data: del data["events"] for model_type in ModelType.bootstrap_models(): attr = model_type + "s" if attr in data and isinstance(data[attr], dict): data[attr] = list(data[attr].values()) return data
def unifi_dict_to_dict(cls, data: Dict[str, Any]) -> Dict[str, Any]: api = cls._get_api(data.get("api")) for model_type in ModelType.bootstrap_models(): key = model_type + "s" items: Dict[str, ProtectModel] = {} for item in data[key]: if api is not None and api.ignore_unadopted and not item.get( "isAdopted", True): continue items[item["id"]] = item data[key] = items return super().unifi_dict_to_dict(data)
def get_klass_from_dict(data: Dict[str, Any]) -> Type[ProtectModel]: """ Helper method to read the `modelKey` from a UFP JSON dict and get the correct Python class for conversion. Will raise `DataDecodeError` if the `modelKey` is for an unknown object. """ if "modelKey" not in data: raise DataDecodeError("No modelKey") model = ModelType(data["modelKey"]) klass = MODEL_TO_CLASS.get(model) if klass is None: raise DataDecodeError("Unknown modelKey") return klass
def _process_add_packet( self, packet: WSPacket, data: Dict[str, Any]) -> Optional[WSSubscriptionMessage]: obj = create_from_unifi_dict(data, api=self._api) if isinstance(obj, Event): self.process_event(obj) elif isinstance(obj, NVR): self.nvr = obj elif (isinstance(obj, ProtectModelWithId) and obj.model is not None and obj.model.value in ModelType.bootstrap_models()): key = obj.model.value + "s" getattr(self, key)[obj.id] = obj else: _LOGGER.debug("Unexpected bootstrap model type for add: %s", obj.model) return None updated = obj.dict() self._create_stat(packet, list(updated.keys()), False) return WSSubscriptionMessage(action=WSAction.ADD, new_update_id=self.last_update_id, changed_data=updated, new_obj=obj)
def process_ws_packet(self, packet: WSPacket) -> Optional[WSSubscriptionMessage]: if not isinstance(packet.action_frame, WSJSONPacketFrame): _LOGGER.debug("Unexpected action frame format: %s", packet.action_frame.payload_format) if not isinstance(packet.data_frame, WSJSONPacketFrame): _LOGGER.debug("Unexpected data frame format: %s", packet.data_frame.payload_format) action: dict = packet.action_frame.data # type: ignore data: dict = packet.data_frame.data # type: ignore if action["newUpdateId"] is not None: self.last_update_id = UUID(action["newUpdateId"]) if action["modelKey"] not in ModelType.values(): _LOGGER.debug("Unknown model type: %s", action["modelKey"]) return None if action["action"] == "add": obj = create_from_unifi_dict(data, api=self._api) if isinstance(obj, Event): self.process_event(obj) elif isinstance(obj, NVR): self.nvr = obj elif ( isinstance(obj, ProtectModelWithId) and obj.model is not None and obj.model.value in ModelType.bootstrap_models() ): key = obj.model.value + "s" getattr(self, key)[obj.id] = obj else: _LOGGER.debug("Unexpected bootstrap model type for add: %s", obj.model) return WSSubscriptionMessage( action=WSAction.ADD, new_update_id=self.last_update_id, changed_data=obj.dict(), new_obj=obj ) if action["action"] == "update": model_type = action["modelKey"] if model_type == ModelType.NVR.value: data = self.nvr.unifi_dict_to_dict(data) old_nvr = self.nvr.copy() self.nvr = self.nvr.update_from_dict(deepcopy(data)) return WSSubscriptionMessage( action=WSAction.UPDATE, new_update_id=self.last_update_id, changed_data=data, new_obj=self.nvr, old_obj=old_nvr, ) if model_type in ModelType.bootstrap_models() or model_type == ModelType.EVENT.value: key = model_type + "s" devices = getattr(self, key) if action["id"] in devices: obj: ProtectModel = devices[action["id"]] data = obj.unifi_dict_to_dict(data) old_obj = obj.copy() obj = obj.update_from_dict(deepcopy(data)) if isinstance(obj, Event): self.process_event(obj) devices[action["id"]] = obj return WSSubscriptionMessage( action=WSAction.UPDATE, new_update_id=self.last_update_id, changed_data=data, new_obj=obj, old_obj=old_obj, ) # ignore updates to events that phase out if model_type != ModelType.EVENT.value: _LOGGER.debug("Unexpected %s: %s", key, action["id"]) else: _LOGGER.debug("Unexpected bootstrap model type for update: %s", model_type) return None