Beispiel #1
0
    def doCommandLine(complexType=True, debug=False, **kw):
        from util import Storage

        if debug:
            SetDebugCallback(None,None,None,None)

        if complexType:
            SetPyclassMetaclass(None,None,None,None,
                                **{'module':'ZSI.generate.pyclass',
                                   'metaclass':'pyclass_type'}
                                )

        options = Storage(
                          file=None,
                          url=None,
                          schema=False,
                          simple_naming=False,
                          clientClassSuffix=None,
                          aname=None,
                          pyclassMapModule=None,
                          address=False,
                          extended=False,
                          types=None,
                          output_directory='.',
                          )

        options.update(kw)

        return options, ()
Beispiel #2
0
    def info(self):
        "Returns a Storage containing the attributes edited by this dialog."

        info = Storage(name=self.name.Value, protocol=self.protocol_name)

        info.protocol, info.name = strip_acct_id(info.protocol, info.name)

        if hasattr(self, "password"):
            info.password_len = len(self.password.Value)
            try:
                info.password = profile.crypt_pw(self.password.Value)
            except UnicodeEncodeError:
                # the database has corrupted the password.
                log.warning("corrupted password")
                info.password = ""
                self.password.Value = ""
                import hub

                hub.get_instance().on_error(
                    "This account's password has been corrupted somehow. Please report it immediately."
                )

        if hasattr(self, "host"):
            info.server = (self.host.Value, int(self.port.Value) if self.port.Value else "")

        if hasattr(self, "remote_alias"):
            info.remote_alias = self.remote_alias.Value

        if hasattr(self, "autologin"):
            info.autologin = bool(self.autologin.Value)

        if hasattr(self, "resource"):
            info.update(
                resource=self.resource.Value,
                priority=try_this(lambda: int(self.priority.Value), DEFAULT_JABBER_PRIORITY),
            )
        #                        ,
        #                        confserver = self.confserver.Value
        if hasattr(self, "dataproxy"):
            info.update(dataproxy=self.dataproxy.Value)

        for d in getattr(self.protocolinfo, "more_details", []):
            attr = d["store"]
            ctrl = getattr(self, attr)
            info[attr] = ctrl.Value

        getattr(self, "info_" + self.formtype, lambda *a: {})(info)

        for info_cb in self.info_callbacks:
            info_cb(info)

        defaults = self.protocolinfo.get("defaults", {})
        for k in defaults:
            if k not in info:
                info[k] = getattr(self.account, k, defaults.get(k))

        return info
Beispiel #3
0
    def info(self):
        'Returns a Storage containing the attributes edited by this dialog.'

        info = Storage(name = self.name.Value,
                       protocol = self.protocol_name)

        info.protocol, info.name = strip_acct_id(info.protocol, info.name)

        if hasattr(self, 'password'):
            info.password_len = len(self.password.Value)
            try:
                info.password = profile.crypt_pw(self.password.Value)
            except UnicodeEncodeError:
                # the database has corrupted the password.
                log.warning('corrupted password')
                info.password = ''
                self.password.Value = ''
                import hub
                hub.get_instance().on_error('This account\'s password has been corrupted somehow. Please report it immediately.')

        if hasattr(self, 'host'):
            info.server = (self.host.Value, int(self.port.Value) if self.port.Value else '')

        if hasattr(self, 'remote_alias'):
            info.remote_alias = self.remote_alias.Value

        if hasattr(self, 'autologin'):
            info.autologin = bool(self.autologin.Value)

        if hasattr(self, 'resource'):
            info.update(resource = self.resource.Value,
                        priority = try_this(lambda: int(self.priority.Value), DEFAULT_JABBER_PRIORITY))
#                        ,
#                        confserver = self.confserver.Value
        if hasattr(self, 'dataproxy'):
            info.update(dataproxy = self.dataproxy.Value)

        for d in getattr(self.protocolinfo, 'more_details', []):
            attr = d['store']
            ctrl = getattr(self, attr)
            info[attr] = ctrl.Value

        getattr(self, 'info_' + self.formtype, lambda *a: {})(info)

        for info_cb in self.info_callbacks:
            info_cb(info)

        defaults = self.protocolinfo.get('defaults', {})
        for k in defaults:
            if k not in info:
                info[k] = getattr(self.account, k, defaults.get(k))

        return info
class Discovery(threading.Thread):
    __devices_table = ("devices", ("id TEXT NOT NULL UNIQUE PRIMARY KEY",
                                   "name TEXT NOT NULL", "model TEXT NOT NULL",
                                   "local_credentials TEXT NOT NULL",
                                   "last_seen TEXT NOT NULL"))

    def __init__(self, mqtt_client: MQTTClient,
                 device_sessions: typing.Dict[str, Session]):
        super().__init__(name="discovery", daemon=True)
        self.__mqtt_client = mqtt_client
        self.__device_sessions = device_sessions
        self.__device_pool: typing.Dict[str, Device] = dict()
        self.__publish_flag = False
        self.__lock = threading.Lock()
        self.__local_storage = Storage(conf.Discovery.db_path, "devices",
                                       (Discovery.__devices_table, ))

    def __handle_new_device(self, device_id: str, data: dict):
        try:
            logger.info("adding '{}'".format(device_id))
            del data["last_seen"]
            device = Device(id=device_id, **data)
            self.__mqtt_client.publish(
                topic=mgw_dc.dm.gen_device_topic(conf.Client.id),
                payload=json.dumps(mgw_dc.dm.gen_set_device_msg(device)),
                qos=1)
            self.__device_pool[device_id] = device
        except Exception as ex:
            logger.error("adding '{}' failed - {}".format(device_id, ex))

    def __handle_missing_device(self, device_id: str):
        try:
            logger.info("removing '{}' ...".format(device_id))
            device = self.__device_pool[device_id]
            self.__mqtt_client.publish(
                topic=mgw_dc.dm.gen_device_topic(conf.Client.id),
                payload=json.dumps(mgw_dc.dm.gen_delete_device_msg(device)),
                qos=1)
            del self.__device_pool[device_id]
        except Exception as ex:
            logger.error("removing '{}' failed - {}".format(device_id, ex))

    def __handle_existing_device(self, device_id: str, data: dict):
        try:
            logger.info("updating '{}' ...".format(device_id))
            device = self.__device_pool[device_id]
            if device.name != data["name"]:
                name_bk = device.name
                device.name = data["name"]
                try:
                    self.__mqtt_client.publish(
                        topic=mgw_dc.dm.gen_device_topic(conf.Client.id),
                        payload=json.dumps(
                            mgw_dc.dm.gen_set_device_msg(device)),
                        qos=1)
                except Exception as ex:
                    device.name = name_bk
                    raise ex
            if device.local_credentials != data["local_credentials"]:
                device.local_credentials = data["local_credentials"]
        except Exception as ex:
            logger.error("updating '{}' failed - {}".format(device_id, ex))

    def __refresh_local_storage(self):
        try:
            logger.info("refreshing local storage ...")
            local_devices = to_dict(
                self.__local_storage.read(Discovery.__devices_table[0]), "id")
            remote_devices = get_cloud_devices(*get_cloud_credentials())
            new_devices, missing_devices, existing_devices = diff(
                local_devices, remote_devices)
            if new_devices:
                for device_id in new_devices:
                    logger.info("adding record for '{}' ...".format(device_id))
                    try:
                        self.__local_storage.create(
                            Discovery.__devices_table[0], {
                                "id": device_id,
                                **remote_devices[device_id]
                            })
                    except Exception as ex:
                        logger.error(
                            "adding record for '{}' failed - {}".format(
                                device_id, ex))
            if missing_devices:
                for device_id in missing_devices:
                    try:
                        device_data = self.__local_storage.read(
                            Discovery.__devices_table[0], id=device_id)
                        now = time.time()
                        age = now - float(device_data[0]["last_seen"])
                        if age > conf.Discovery.grace_period:
                            logger.info(
                                "removing record for '{}' due to exceeded grace period ..."
                                .format(device_id))
                            try:
                                self.__local_storage.delete(
                                    Discovery.__devices_table[0], id=device_id)
                            except Exception as ex:
                                logger.error(
                                    "removing record for '{}' failed - {}".
                                    format(device_id, ex))
                        else:
                            logger.info(
                                "remaining grace period for missing '{}': {}s".
                                format(device_id,
                                       conf.Discovery.grace_period - age))
                    except Exception as ex:
                        logger.error(
                            "can't calculate grace period for missing '{}' - {}"
                            .format(device_id, ex))
            if existing_devices:
                for device_id in existing_devices:
                    logger.info(
                        "updating record for '{}' ...".format(device_id))
                    try:
                        self.__local_storage.update(
                            Discovery.__devices_table[0],
                            remote_devices[device_id],
                            id=device_id)
                    except Exception as ex:
                        logger.error(
                            "updating record for '{}' failed - {}".format(
                                device_id, ex))
        except Exception as ex:
            logger.error("refreshing local storage failed - {}".format(ex))

    def __refresh_devices(self):
        try:
            stored_devices = to_dict(
                self.__local_storage.read(Discovery.__devices_table[0]), "id")
            new_devices, missing_devices, existing_devices = diff(
                self.__device_pool, stored_devices)
            if new_devices:
                for device_id in new_devices:
                    self.__handle_new_device(device_id,
                                             stored_devices[device_id])
            if missing_devices:
                for device_id in missing_devices:
                    self.__handle_missing_device(device_id)
            if existing_devices:
                for device_id in existing_devices:
                    self.__handle_existing_device(device_id,
                                                  stored_devices[device_id])
        except Exception as ex:
            logger.error("refreshing devices failed - {}".format(ex))

    def __start_device_session(self, device: Device, location: tuple):
        logger.info("found '{}' at '{}'".format(device.id, location[0]))
        session = Session(mqtt_client=self.__mqtt_client,
                          device=device,
                          ip=location[0],
                          port=location[1])
        session.start()
        self.__device_sessions[device.id] = session

    def run(self) -> None:
        if not self.__mqtt_client.connected():
            time.sleep(3)
        logger.info("starting {} ...".format(self.name))
        self.__refresh_local_storage()
        last_cloud_check = time.time()
        self.__refresh_devices()
        while True:
            if self.__publish_flag:
                self.__publish_devices(self.__publish_flag)
            if time.time() - last_cloud_check > conf.Discovery.cloud_delay:
                self.__refresh_local_storage()
                last_cloud_check = time.time()
                self.__refresh_devices()
            try:
                positive_hosts = probe_hosts(discover_hosts())
                for device in self.__device_pool.values():
                    if device.id not in self.__device_sessions:
                        for hostname, data in positive_hosts.items():
                            if device.id.replace(
                                    conf.Discovery.device_id_prefix,
                                    "") in hostname:
                                self.__start_device_session(device=device,
                                                            location=data)
                                break
                    else:
                        if not self.__device_sessions[device.id].is_alive():
                            del self.__device_sessions[device.id]
                            for hostname, data in positive_hosts.items():
                                if device.id.replace(
                                        conf.Discovery.device_id_prefix,
                                        "") in hostname:
                                    self.__start_device_session(device=device,
                                                                location=data)
                                    break
            except Exception as ex:
                logger.error("discovery failed - {}".format(ex))
            time.sleep(conf.Discovery.delay)

    def __publish_devices(self, flag: int):
        with self.__lock:
            if self.__publish_flag == flag:
                self.__publish_flag = 0
        for device in self.__device_pool.values():
            try:
                self.__mqtt_client.publish(
                    topic=mgw_dc.dm.gen_device_topic(conf.Client.id),
                    payload=json.dumps(mgw_dc.dm.gen_set_device_msg(device)),
                    qos=1)
            except Exception as ex:
                logger.error("setting device '{}' failed - {}".format(
                    device.id, ex))
            if flag > 1 and device.state == mgw_dc.dm.device_state.online:
                try:
                    self.__mqtt_client.subscribe(
                        topic=mgw_dc.com.gen_command_topic(device.id), qos=1)
                except Exception as ex:
                    logger.error("subscribing device '{}' failed - {}".format(
                        device.id, ex))

    def schedule_publish(self, subscribe: bool = False):
        with self.__lock:
            self.__publish_flag = max(self.__publish_flag, int(subscribe) + 1)