Beispiel #1
0
    def go(self) -> tuple:
        mapping = {
            'device\\..*': self._device,
            'group\\.(input|output|connection)': self._device,
        }

        if self.path_main == PATH_CORE:
            check = f'{self.path_type}.{self.path_subtype}'
            matched = False

            for match, goto in mapping.items():
                if regex_match(match, check) is not None:
                    matched = True
                    goto()
                    break

            if matched:
                return self.result

            else:
                log('No route matched!', level=5)

        else:
            log(f"Wrong api root-path supplied => should be '{PATH_CORE}'",
                level=4)

        return self.status
Beispiel #2
0
    def get(self) -> dict:
        # {
        #     object_condition_match: [instance_list],
        #     object_condition_specialmatch: [instance_list],
        #     object_condition_link: [instance_list],
        #     group_condition: [instance_list]
        # }

        log(f'Building condition objects (all)', level=8)

        output = {}

        _config = {
            config.KEY_OBJECT_CONDITION_MATCH: ConditionMatch,
            config.KEY_OBJECT_CONDITION_MATCH_SPECIAL: ConditionMatchSpecial,
            config.KEY_OBJECT_CONDITION_LINK: ConditionLink,
            config.KEY_GROUP_CONDITION: ConditionGroup,
        }

        for key, factory in _config.items():
            output[key] = factory(
                blueprint=blueprint_dict[key],
                supply_data=self.supply_data[key],
            ).get()

        return output
Beispiel #3
0
def get(config_dict: dict, system_tasks: bool = True) -> list:
    if system_tasks:
        timer_list = get_tasks()

    else:
        timer_list = []

    for category, obj_data in config_dict.items():
        for obj in obj_data:
            if isinstance(obj, TIMER_OBJECTS):
                if obj.enabled == 1:

                    if isinstance(obj, GaInputDevice):
                        if obj.timer is not None and obj.timer != obj.parent_instance.timer:
                            timer_list.append(obj)

                    elif isinstance(obj, (GaInputModel, GaConditionGroup)):
                        timer_list.append(obj)

                else:
                    log(f"Is disabled: \"{obj}\"", level=6)

            else:
                log(f"Is not allowed: \"{obj}\"", level=7)

    return timer_list
Beispiel #4
0
    def get(self) -> list:
        # {
        #     [instance_list]
        # }

        area_group_list = []
        log(f'Building area objects', level=8)

        for data_dict in self.supply_data.values():
            instance = self.blueprint(
                connection_group_list=data_dict[self.key_member][
                    config.SUPPLY_AR_KEY_MEMBER_CG],
                connection_obj_list=data_dict[self.key_member][
                    config.SUPPLY_AR_KEY_MEMBER_CO],
                input_group_list=data_dict[self.key_member][
                    config.SUPPLY_AR_KEY_MEMBER_IG],
                input_obj_list=data_dict[self.key_member][
                    config.SUPPLY_AR_KEY_MEMBER_IO],
                output_group_list=data_dict[self.key_member][
                    config.SUPPLY_AR_KEY_MEMBER_OG],
                output_obj_list=data_dict[self.key_member][
                    config.SUPPLY_AR_KEY_MEMBER_OO],
                nested_list=data_dict[self.key_member][
                    config.SUPPLY_GENERIC_KEY_MEMBER_NESTED],
                object_id=data_dict[config.DB_ALL_KEY_ID],
                name=data_dict[config.DB_ALL_KEY_NAME],
                description=data_dict[config.DB_ALL_KEY_DESCRIPTION],
            )

            area_group_list.append(instance)

        return area_group_list
Beispiel #5
0
    def get_device(self):
        output_list = []

        log(f'Building device objects', level=8)

        for data_dict in self.supply_data.values():
            if self.downlink_attribute in data_dict:
                instance = self.blueprint(
                    setting_dict=data_dict[self.key_setting],
                    object_id=data_dict[self.key_id],
                    name=data_dict[self.key_name],
                    description=data_dict[self.key_desc],
                    downlink=data_dict[self.downlink_attribute],
                )

            else:
                instance = self.blueprint(
                    setting_dict=data_dict[self.key_setting],
                    object_id=data_dict[self.key_id],
                    name=data_dict[self.key_name],
                    description=data_dict[self.key_desc],
                )

            output_list.append(instance)

        return output_list
Beispiel #6
0
    def get(self, query: [str, list]) -> list:
        if type(query) == str:
            query_list = [query]

        else:
            query_list = query

        log(f"Query to execute: \"{query_list}\"", level=7)
        data_list = []

        try:
            for q in query_list:
                data = self._read_cache(q)

                if len(query_list) > 1:
                    if type(data) is not None:
                        data_list.append(data)

                else:
                    data_list = data

        except self.SQL_EXCEPTION_TUPLE as error_msg:
            self._error(error_msg)

        log(f"Query output: \"{data_list}\"", level=7)
        return data_list  # list of dicts
Beispiel #7
0
    def stop(self) -> bool:
        log('Stopping all threads', level=6)

        for job in self.jobs:
            job.stop()

        log('All threads stopped. Exiting loop', level=3)
        return True
Beispiel #8
0
 def stop_thread(self, description: str):
     log(f"Stopping thread for \"{description}\"", level=6)
     for job in self.jobs:
         if job.description == description:
             job.stop()
             self.jobs.remove(job)
             log(f"Thread {job.description} stopped.", level=4)
             del job
             break
Beispiel #9
0
    def get(self) -> dict:
        # {
        #     object_connection: [instance_list],
        #     object_input: [instance_list],
        #     group_connection: [instance_list],
        #     object_output: [instance_list],
        #     group_input: [instance_list],
        #     group_output: [instance_list],
        # }

        log('Building device objects (all)', level=8)

        output_dict = {}

        device_config_list = [
            {'bp': GenericDeviceFactory, 'ok': config.KEY_OBJECT_CONNECTION, 'gk': config.KEY_GROUP_CONNECTION},
            {'bp': GenericDeviceFactory, 'ok': config.KEY_OBJECT_INPUT, 'gk': config.KEY_GROUP_INPUT},
            {'bp': GenericDeviceFactory, 'ok': config.KEY_OBJECT_OUTPUT, 'gk': config.KEY_GROUP_OUTPUT},
        ]

        update_states = {
            config.KEY_OBJECT_OUTPUT: {'attribute': 'state', 'query': DEVICE_TMPL['output']['state']['get'], 'value': 1, 'set_to': True},
        }

        for device_config in device_config_list:
            output_dict[device_config['gk']] = device_config['bp'](
                blueprint=blueprint_dict[device_config['gk']],
                supply_data=self.supply_data[device_config['gk']],
            ).get_model()

            output_dict[device_config['ok']] = device_config['bp'](
                blueprint=blueprint_dict[device_config['ok']],
                supply_data=self.supply_data[device_config['ok']],
            ).get_device()

            if device_config['ok'] in update_states:
                update = update_states[device_config['ok']]
                attribute = update['attribute']

                for device in output_dict[device_config['ok']]:
                    result = self.database.get(update['query'] % device.object_id)

                    if result is not None and len(result) > 0:
                        db_value = result[0]['active']

                        if db_value == update['value']:
                            log(f"Setting {attribute} of device {device.name} to value from db!", level=5)

                            if 'set_to' in update:
                                setattr(device, attribute, update['set_to'])

                            else:
                                setattr(device, attribute, db_value)

        del self.database
        return output_dict
Beispiel #10
0
 def reload_thread(self, sleep_time: int, thread_data,
                   description: str) -> None:
     log(f"Reloading thread for \"{description}\"", level=6)
     self.stop_thread(description=description)
     self.add_thread(
         sleep_time=sleep_time,
         thread_data=thread_data,
         description=description,
     )
     self.start_thread(description=description)
Beispiel #11
0
    def _error(self, msg: str):
        log(f"SQL connection error: \"{msg}\"", level=3)

        try:
            self.connection.rollback()

        except (UnboundLocalError, AttributeError):
            pass

        raise ConnectionError(censor(msg))
Beispiel #12
0
    def _connect(self) -> bool:
        try:
            if self.connection_data_dict['server'] in ['127.0.0.1', 'localhost']:
                if self.connection_data_dict['user'] == 'root':
                    try:
                        # local logon as root
                        # will only work if it is run with root privileges
                        # should only be used in the setup and update
                        _connection = mysql.connector.connect(
                            unix_socket=self._unix_sock(),
                            user=self.connection_data_dict['user'],
                        )
                        log('Initiated sql connection via socket as root without password', level=8)

                    except self.SQL_EXCEPTION_TUPLE:
                        # if failed without password, try again with it
                        _connection = mysql.connector.connect(
                            unix_socket=self._unix_sock(),
                            user=self.connection_data_dict['user'],
                            passwd=self.connection_data_dict['secret']
                        )
                        log('Initiated sql connection via socket as root', level=8)

                else:
                    # local logon for default users
                    _connection = mysql.connector.connect(
                        unix_socket=self._unix_sock(),
                        user=self.connection_data_dict['user'],
                        passwd=self.connection_data_dict['secret'],
                        database=self.connection_data_dict['database']
                    )
                    log('Initiated sql connection to localhost', level=8)

            else:
                # remote logon
                _connection = mysql.connector.connect(
                    host=self.connection_data_dict['server'],
                    port=self.connection_data_dict['port'],
                    user=self.connection_data_dict['user'],
                    passwd=self.connection_data_dict['secret'],
                    database=self.connection_data_dict['database']
                )
                log('Initiated sql connection to remote server', level=8)

        except self.SQL_EXCEPTION_TUPLE as error_msg:
            self._error(error_msg)

        try:
            self.connection = _connection
            self.cursor = _connection.cursor(buffered=True, dictionary=True)
            return True

        except UnboundLocalError:
            log('Connection instance could not be created.')
            raise ConnectionError('Connection instance not created')
Beispiel #13
0
    def __init__(self, parsed: dict):
        self.path = parsed['path'].split(PACKAGE_PATH_SEPARATOR)[0].split('.')
        self.data = parsed['data']
        self.result = None
        try:
            self.path_main = f'{self.path[0]}.{self.path[1]}'
            self.path_type = self.path[2]
            self.path_subtype = self.path[3]
            self.path_id = int(self.path[4])

        except (TypeError, IndexError):
            log(f'Router did not get all expected arguments!', level=3)
            raise IndexError
Beispiel #14
0
    def _check(self, attribute: str, instance) -> None:
        """
        Will check if the link was successfully created.
        Else it will log an error.

        :param attribute: Instance attribute that should be checked
        :param instance: Instance to check
        :return: None
        """
        to_check = getattr(instance, attribute)
        if not isinstance(to_check, self.LINK_TARGET_TYPES):
            log(f'Failed to create \"{attribute}\" link for object \"{instance}\"',
                level=4)
Beispiel #15
0
    def __del__(self):
        try:
            self.cursor.close()

        except (UnboundLocalError, AttributeError, ReferenceError):
            pass

        try:
            self.connection.close()
            log('SQL connection closed', level=8)

        except (UnboundLocalError, AttributeError, ReferenceError):
            pass
Beispiel #16
0
    def get(self):
        output_list = []
        log(f'Building condition special-match objects', level=8)

        for data_dict in self.supply_data.values():
            instance = self.blueprint(
                object_id=data_dict[config.DB_ALL_KEY_ID],
                name=data_dict[config.DB_ALL_KEY_NAME],
                description=data_dict[config.DB_ALL_KEY_DESCRIPTION],
            )

            output_list.append(instance)

        return output_list
Beispiel #17
0
    def get(self):
        output_list = []
        log(f'Building task objects', level=8)

        for data_dict in self.supply_data.values():
            instance = self.blueprint(
                setting_dict=data_dict[config.SUPPLY_KEY_SETTING_DICT],
                object_id=data_dict[config.DB_ALL_KEY_ID],
                name=data_dict[config.DB_ALL_KEY_NAME],
                description=data_dict[config.DB_ALL_KEY_DESCRIPTION],
            )

            output_list.append(instance)

        return output_list
Beispiel #18
0
    def get(self):
        output_list = []
        log(f'Building condition link objects', level=8)

        for data_dict in self.supply_data.values():
            instance = self.blueprint(
                condition_match_dict=data_dict[self.key_member][config.SUPPLY_CL_KEY_MEMBER_CM],
                condition_group_dict=data_dict[self.key_member][config.SUPPLY_CL_KEY_MEMBER_CG],
                setting_dict=data_dict[config.SUPPLY_KEY_SETTING_DICT],
                object_id=data_dict[config.DB_ALL_KEY_ID],
                name=data_dict[config.DB_ALL_KEY_NAME],
            )

            output_list.append(instance)

        return output_list
Beispiel #19
0
    def get(self) -> dict:
        # {
        #     area_group: [instance_list],
        # }

        log(f'Building group objects (all)', level=8)

        output_dict = {
            self.key_area_group:
            AreaGroup(
                supply_data=self.supply_data[self.key_area_group],
                factory_dict=self.factory_data,
                blueprint=blueprint_dict[self.key_area_group],
            ).get()
        }

        return output_dict
Beispiel #20
0
    def _log(self, output, level: int = 1):
        try:
            from core.utils.debug import fns_log, log

            if len(self.log_cache) > 0:
                for msg in self.log_cache:
                    log(output=msg['output'], level=msg['level'])

                self.log_cache = []

            fns_log(output=output, level=level)

        except Exception:
            self.log_cache.append({'level': level, 'output': output})

            if level == 1:
                journal.send(output)
Beispiel #21
0
    def get_model(self):
        output_list = []

        log(f'Building device model objects', level=8)

        for data_dict in self.supply_data.values():
            instance = self.blueprint(
                setting_dict=data_dict[self.key_setting],
                member_list=data_dict[config.SUPPLY_KEY_MEMBER_DICT][
                    config.SUPPLY_GENERIC_KEY_MEMBER],
                object_id=data_dict[self.key_id],
                name=data_dict[self.key_name],
                description=data_dict[self.key_desc],
            )

            output_list.append(instance)

        return output_list
Beispiel #22
0
    def put(self, command: [str, list]) -> bool:
        if type(command) == str:
            command_list = [command]

        else:
            command_list = command

        log(f"Query to execute: \"{command_list}\"", level=7)

        try:
            for cmd in command_list:
                self.cursor.execute(cmd)

            self.connection.commit()

        except self.SQL_EXCEPTION_TUPLE as error_msg:
            self._error(error_msg)

        return True
Beispiel #23
0
    def _one_to_one_options(self, instances: list, oto_config: dict,
                            type_key: str) -> None:
        """
        Links two object instances if there is the option to choose one of X target types.
        Will check which target type is configured, find and link it [only object_id linking supported]

        Example:
        - condition match can be linked to one of [input object, input model, special match]
        - one will/must be linked

        :param instances: The currently processed object instances - only one type at a time
        :param oto_config: Link config sub-dict as configured in factory config file
        :param type_key: The type that is currently processed - needed to get the correct raw data from the supply data
        :return: None
        """

        for instance in instances:
            _id = getattr(instance, config.CORE_ID_ATTRIBUTE)
            raw_instance_data = [
                data_dict for data_dict in self.supply_data[type_key].values()
                if int(data_dict['id']) == _id
            ][0]

            for set_attr, options in oto_config.items():
                for option in options:
                    search_attr = option[config.LINK_KEY_SEARCH_ATTR]
                    query_attr = config.CORE_ID_ATTRIBUTE
                    search_key = option[config.LINK_KEY_SEARCH_KEY]

                    if raw_instance_data[search_attr] is not None:
                        to_compare = int(raw_instance_data[search_attr])

                        for target_instance in self.factory_data[search_key]:
                            if getattr(target_instance,
                                       query_attr) == to_compare:
                                setattr(instance, set_attr, target_instance)
                                log(f'Object \"{instance}\" has the following link target for attribute \"{set_attr}\": \"{target_instance}\"',
                                    level=8)
                                break

                        break

                self._check(attribute=set_attr, instance=instance)
Beispiel #24
0
    def stop(self) -> bool:
        log(f"Thread stopping {self.log_name}", level=6)
        self.state_stop.set()

        try:
            self.join(config.THREAD_JOIN_TIMEOUT)
            if self.is_alive():
                log(f"Unable to join thread {self.log_name}", level=5)

        except RuntimeError:
            log(f"Got error stopping thread {self.log_name}", level=5)

        log(f"Stopped thread {self.log_name}", level=4)
        return True
Beispiel #25
0
def start(instance, settings: dict = None):
    if settings is None:
        settings = {}

    if isinstance(instance, (GaInputDevice, GaInputModel)):
        from core.device.input.main import Go
        Go(instance=instance, **settings).start()

    elif isinstance(instance, GaConditionGroup):
        from core.device.output.main import Go
        Go(instance=instance, **settings).start()

    elif isinstance(instance, GaTaskDevice):
        log('Core timers are not yet implemented', level=3)
        pass

    elif isinstance(instance, SystemTask):
        instance.execute(**settings)

    else:
        log(f"Service could not find a matching decision for instance: '{instance}'",
            level=5)
Beispiel #26
0
    def add_thread(self,
                   sleep_time: int,
                   thread_data,
                   description: str,
                   once: bool = False,
                   daemon: bool = True):
        log(f"Adding thread for \"{description}\" with interval \"{sleep_time}\"",
            level=7)
        self.thread_nr += 1

        def decorator(function):
            if sleep_time == 0:
                sleep_time_new = config.THREAD_DEFAULT_SLEEP_TIME
                self.jobs.add(
                    Workload(
                        sleep=timedelta(seconds=sleep_time_new),
                        execute=function,
                        data=thread_data,
                        loop_instance=self,
                        once=True,
                        description=description,
                        daemon=daemon,
                        name=f"Thread #{self.thread_nr}",
                    ))
            else:
                self.jobs.add(
                    Workload(
                        sleep=timedelta(seconds=sleep_time),
                        execute=function,
                        data=thread_data,
                        loop_instance=self,
                        once=once,
                        description=description,
                        daemon=daemon,
                        name=f"Thread #{self.thread_nr}",
                    ))
            return function

        return decorator
Beispiel #27
0
    def __init__(self):
        try:
            self.connection_data_dict = {
                'server': config.AGENT.sql_server,
                'port': config.AGENT.sql_port,
                'user': config.AGENT.sql_user,
                'secret': config.AGENT.sql_secret,
                'database': config.AGENT.sql_database
            }

            log(
                f"DB connection config: "
                f"server => \"{self.connection_data_dict['server']}\" "
                f"port => \"{self.connection_data_dict['port']}\" "
                f"user => \"{self.connection_data_dict['user']}\" "
                f"database => \"{self.connection_data_dict['database']}\"",
                level=7)

        except IndexError as error_msg:
            self._error(msg=error_msg)

        self.link = None
        self._link()
Beispiel #28
0
    def get(self):
        output_list = []
        log(f'Building condition group objects', level=8)

        for data_dict in self.supply_data.values():

            instance = self.blueprint(
                member_list=data_dict[self.key_member][
                    config.SUPPLY_CG_KEY_MEMBER_CL],
                output_object_list=data_dict[self.key_member][
                    config.SUPPLY_CG_KEY_MEMBER_OO],
                output_group_list=data_dict[self.key_member][
                    config.SUPPLY_CG_KEY_MEMBER_OG],
                area_group_list=data_dict[self.key_member][
                    config.SUPPLY_CG_KEY_MEMBER_AG],
                setting_dict=data_dict[config.SUPPLY_KEY_SETTING_DICT],
                object_id=data_dict[config.DB_ALL_KEY_ID],
                name=data_dict[config.DB_ALL_KEY_NAME],
                description=data_dict[config.DB_ALL_KEY_DESCRIPTION],
            )

            output_list.append(instance)

        return output_list
Beispiel #29
0
    def _one_to_one(self, instances: list, oto_config: dict) -> None:
        """
        Links two object instances.
        Either links them via object_id [config=simple key:value pair] or some custom mapping [config=dict]

        :param instances: The currently processed object instances - only one type at a time
        :param oto_config: Link config sub-dict as configured in factory config file
        :return: None
        """

        for key, link_config in oto_config.items():
            if type(link_config) == dict:
                # this instance is a member of the targets member list
                search_key = link_config[config.LINK_KEY_SEARCH_KEY]
                search_attr = link_config[config.LINK_KEY_SEARCH_ATTR]
                set_attr = link_config[config.LINK_KEY_SET_ATTR]

                for instance in instances:
                    for target_instance in self.factory_data[search_key]:
                        if instance in getattr(target_instance, search_attr):
                            log(f'Object \"{instance}\" has the following link target for attribute \"{set_attr}\": \"{target_instance}\"',
                                level=8)
                            setattr(instance, set_attr, target_instance)
                            break

                    self._check(attribute=set_attr, instance=instance)

            else:
                # simple id to id link
                search_key = link_config
                search_attr = config.CORE_ID_ATTRIBUTE
                set_attr = key

                for instance in instances:
                    try:
                        # get the raw id of the target object
                        to_compare = int(getattr(instance, set_attr))

                    except TypeError:
                        if set_attr != 'downlink':
                            log(f'Unable to get value for attribute \"{set_attr}\" from object \"{instance}\"',
                                level=5)

                        continue

                    for target_instance in self.factory_data[search_key]:
                        if getattr(target_instance, search_attr) == to_compare:
                            log(f'Object \"{instance}\" has the following link target for attribute \"{set_attr}\": \"{target_instance}\"',
                                level=8)
                            setattr(instance, set_attr, target_instance)
                            break

                    self._check(attribute=set_attr, instance=instance)
Beispiel #30
0
    def _one_to_many(self, instances: list, otm_config: dict) -> None:
        """
        Builds a member-list/dict to link to the current instance.
        It supports lists and numbered dicts (key=number,value=member)

        :param instances: The currently processed object instances - only one type at a time
        :param otm_config: Link config sub-dict as configured in factory config file
        :return: None
        """

        for instance in instances:
            for member_attr, search_key in otm_config.items():
                raw_member_data = getattr(instance, member_attr)
                possible_members = self.factory_data[search_key]

                if type(raw_member_data) == list:
                    log(f'Building member list for instance \"{instance}\"',
                        level=8)
                    members = []
                    for member in raw_member_data:
                        for possible_member in possible_members:
                            if possible_member.object_id == member:
                                members.append(possible_member)
                                break

                else:
                    # numbered members -> p.e. condition link
                    log(f'Building numbered member dict for instance \"{instance}\"',
                        level=8)

                    members = {}
                    for numbered_data, member in raw_member_data.items():
                        for possible_member in possible_members:
                            if possible_member.object_id == member:
                                members[numbered_data] = possible_member
                                break

                log(f'Object \"{instance}\" has the following members for attribute \"{member_attr}\": \"{members}\"',
                    level=8)
                setattr(instance, member_attr, members)