def _gadget_needs_update(local_gadget: Gadget, fetched_gadget: Gadget): """ Checks if the gadget on the remote storage needs an update by comparing the gadgets characteristics boundaries :param local_gadget: The local gadget (master) :param fetched_gadget: The fetched gadget to compare it with :return: Whether the fetched gadget needs to be updated """ needs_update = local_gadget.get_characteristics( ) != fetched_gadget.get_characteristics() return needs_update
def merge_gadgets(self, old_gadget: Gadget, new_gadget: Gadget) -> Gadget: """ Merges two gadgets (typically one 'original' and a new one with update information) into a new gadget containing with name, client and class of the old and characteristics of the new one. :param old_gadget: Original gadget to base merged gadget on :param new_gadget: Gadget wth update information :return: The emrged gadget :raise GadgetMergeError: If anything goes wrong during merges """ encoder = ApiEncoder() if not isinstance( new_gadget, AnyGadget) and old_gadget.__class__ != new_gadget.__class__: raise GadgetMergeError( f"Cannot merge gadgets with different classes {old_gadget.__class__.__name__} " f"and {new_gadget.__class__.__name__}") try: gadget_type = encoder.encode_gadget_identifier(old_gadget) except IdentifierEncodeError as err: raise GadgetMergeError(err.args[0]) try: merged_gadget = self.create_gadget( gadget_type, old_gadget.get_name(), old_gadget.get_host_client(), new_gadget.get_characteristics()) except GadgetCreationError as err: raise GadgetMergeError(err.args[0]) return merged_gadget
def encode_gadget(self, gadget: Gadget) -> dict: """ Serializes a gadget according to api specification :param gadget: The gadget to serialize :return: The serialized version of the gadget as dict :raises GadgetEncodeError: If anything goes wrong during the serialization process """ try: identifier = self.encode_gadget_identifier(gadget) except IdentifierEncodeError as err: self._logger.error(err.args[0]) raise GadgetEncodeError(gadget.__class__.__name__, gadget.get_name()) characteristics_json = [self.encode_characteristic(x) for x in gadget.get_characteristics()] mapping_json = {} for mapping in gadget.get_event_mapping(): if mapping.get_id() in mapping_json: self._logger.error(f"found double mapping for {mapping.get_id()}") continue mapping_json[mapping.get_id()] = mapping.get_list() gadget_json = {"type": int(identifier), "id": gadget.get_name(), "characteristics": characteristics_json, "event_map": mapping_json} return gadget_json
def receive_gadget(self, gadget: Gadget): if self._last_published_gadget is not None and self._last_published_gadget == gadget.get_name( ): return fetched_gadget = self._fetch_gadget_data(gadget.get_name()) if fetched_gadget is None: # Gadget with given name does not exist on the remote system, or is broken somehow try: self.create_gadget(gadget) except GadgetCreationError as err: self._logger.error(err.args[0]) raise GadgetUpdateError(gadget.get_name()) else: if self._gadget_needs_update(gadget, fetched_gadget): # Gadget needs to be recreated due to characteristic boundaries changes try: self.remove_gadget(gadget.get_name()) except GadgetDeletionError as err: self._logger.error(err.args[0]) try: self.create_gadget(gadget) except GadgetCreationError as err: self._logger.error(err.args[0]) raise GadgetUpdateError(gadget.get_name()) else: # Gadget does not need to be re-created, only updated for characteristic in gadget.get_characteristics(): fetched_characteristic = fetched_gadget.get_characteristic( characteristic.get_type()) if fetched_characteristic.get_true_value( ) != characteristic.get_true_value(): self._update_characteristic(gadget, characteristic.get_type())
def create_gadget(self, gadget: Gadget): self._logger.info( f"Creating gadget '{gadget.get_name()}' on external source") adding_successful = self._network_connector.add_gadget(gadget) if not adding_successful: raise GadgetCreationError(gadget.get_name()) for characteristic in gadget.get_characteristics(): self._update_characteristic(gadget, characteristic.get_type())
def encode_gadget_update(self, gadget: Gadget) -> dict: """ Serializes gadget update information according to api specification :param gadget: The gadget to serialize :return: The serialized version of the changeable gadget information as dict :raises GadgetEncodeError: If anything goes wrong during the serialization process """ characteristics_json = [self.encode_characteristic_update(x) for x in gadget.get_characteristics()] gadget_json = {"id": gadget.get_name(), "characteristics": characteristics_json} return gadget_json
def receive_gadget_update(self, gadget: Gadget): for identifier in [x.get_type() for x in gadget.get_characteristics()]: try: self._update_characteristic(gadget, identifier) except CharacteristicParsingError as err: self._logger.info(err.args[0])