Example #1
0
    def load_components(cls):
        Log.info("Loading components")
        cls.components = ComponentCollection()

        for k in cls.config['components'].keys():
            component_info = cls.config['components'][k]

            module_name, class_name = component_info['class'].split('/', 2)

            module = importlib.import_module(module_name)
            component_class = getattr(module, class_name)

            component_name = component_info['name']
            if 'params' in component_info:
                component_params = component_info['params']
            else:
                component_params = {}

            component = component_class(k, component_name, component_params)
            component_class.set_instance_code(k)

            cls.components.add(k, component, component.COMPONENT_TYPE)

        cls.allowed_paths = []
        if 'allowed_paths' in cls.config:
            cls.allowed_paths = cls.config['allowed_paths']
Example #2
0
    def send_mjpeg(self, cam: Cam):
        self.send_response(200)
        self.send_header('Content-type', 'multipart/x-mixed-replace; boundary=--jpgboundary')
        self.end_headers()

        while True:
            img = cam.image
            if img is None:
                time.sleep(5)
                continue

            try:
                imgRGB = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
                jpg = Image.fromarray(imgRGB)
                tmpFile = io.BytesIO()

                jpg.save(tmpFile, 'JPEG')
                self.wfile.write(bytes("--jpgboundary", 'utf-8'))
                self.send_header('Content-type', 'image/jpeg')
                # self.send_header('Content-length', str(tmpFile.len))
                self.end_headers()
                jpg.save(self.wfile, 'JPEG')
            except:
                Log.info("Closing camera stream for " + cam.code)
                break
Example #3
0
    def _on_learn_timeout(self):
        if self._learning_signal is not None:
            Log.info("Learning signal timeout")

            self.send_intercom_message(self.INTERCOM_MESSAGE_EVENT_LEARN_FAIL,
                                       self._learning_signal.to_dict())
            self._learning_signal = None
Example #4
0
    def load(cls):
        """
        Load YML signals file
        """

        cls._signals = []

        signals_file = cls._get_signals_file()
        try:
            signals = yaml.load(open(signals_file, 'r'))
            Log.info("Loading signals information from " + signals_file)
        except:
            Log.error("Loading signals information failed from " +
                      signals_file)
            return

        if signals is not None:
            for device_code, device_info in signals.items():
                for sub_code, sub_info in device_info['subs'].items():
                    signal = Signal(
                        manager=App.components.get(sub_info['manager']),
                        code=sub_info['code'],
                        dump=sub_info['dump'],
                        device_code=device_code,
                        device_name=device_info['name'],
                        sub_code=sub_code,
                        sub_name=sub_info['name'],
                    )

                    cls._signals.append(signal)
Example #5
0
    def handle(self):
        line = ''

        (host, port) = self.client_address

        Log.info("TCP socket client connected from " + host + ':' + str(port))
        TCPSocketManager.get_instance().handlers[threading.current_thread()] = self

        while True:
            try:
                b = self.request.recv(1)
            except Exception:
                break

            if b == b'':
                break

            c = b.decode('utf-8')
            if c in ['\n', '\r']:
                self._on_line(line.strip())
                line = ''

            else:
                line += c

        del TCPSocketManager.get_instance().handlers[threading.current_thread()]
        Log.info("TCP socket client disconnected from " + host + ':' + str(port))
Example #6
0
    def _fire_delayed(self, signal: Signal):
        Log.info('Queuing signal: ' + str(signal))
        while not self._can_send_message():
            time.sleep(self.SIGNAL_RELAX_TIME)

        Log.info('Firing signal: ' + str(signal))
        self._delay_signal()
        self._fire(signal)
Example #7
0
    def send_message(self, text, recipients=None):
        if recipients is None:
            recipients = self._allowed_users

        for recipient in recipients:
            chat_id = self.get_chat_id(recipient)
            if chat_id is not None:
                self.get_bot().sendMessage(chat_id, text)
            else:
                Log.error('Unknown chat ID for user ' + recipient +
                          ', please send a message to this bot')
Example #8
0
    def _fire(self, variables, delay=0):
        time.sleep(delay)
        message_to_send = self.copy()

        payload = message_to_send.message_payload
        new_payload = Utils.replace_variables_dict(payload, variables)

        message_to_send.message_payload = new_payload
        Log.info('Firing action "' + self.message_type + '" ')

        return message_to_send.send()
Example #9
0
    def load_variables(cls):
        variable_file = cls.get_settings_path() + '/variables.yml'

        cls.variables = {}
        try:
            cls.variables = yaml.load(open(variable_file, 'r'))
            Log.info('Variables loaded from ' + variable_file)
        except:
            pass

        if cls.variables is None:
            cls.variables = {}
Example #10
0
    def _load_runtime(self):
        self._chat_ids = {}

        runtime_file = self._get_runtime_file()
        try:
            runtime = yaml.load(open(runtime_file, 'r'))
            Log.info("Loading runtime from " + runtime_file)
        except:
            Log.error("Loading runtime failed from " + runtime_file)
            return

        self._chat_ids = runtime['chat_ids']
Example #11
0
    def _learn_signal(self, signal: Signal):
        Log.info("Learning signal " + str(signal))

        self._learning_signal.set_manager(signal.get_manager())
        self._learning_signal.set_code(signal.get_code())
        self._learning_signal.set_dump(signal.get_dump())

        SignalRepo.add(self._learning_signal)

        self.send_intercom_message(
            self.INTERCOM_MESSAGE_EVENT_LEARN_NEW_SIGNAL, signal.to_dict())
        self.send_intercom_message(self.INTERCOM_MESSAGE_EVENT_LEARN_END)
Example #12
0
    def handle_intercom_message(self, message: Message) -> Reply:
        """
        Handle an incoming message from another component

        :param message: Message to be sent
        :return: Message reply
        """
        try:
            return self._on_intercom_message(message)
        except Exception as e:
            Log.error(
                "Intercom message " + message.message_type + " failed:" + traceback.format_exc())
            return Reply(Reply.INTERCOM_STATUS_FAILURE, {'message': str(e)})
Example #13
0
    def load_settings(self):
        self._allowed_users = []

        settings_file = self._get_settings_file()
        try:
            settings = yaml.load(open(settings_file, 'r'))
            Log.info("Loading settings from " + settings_file)
        except:
            Log.error("Loading settings failed from " + settings_file)
            return

        self._token = settings['token']
        self._allowed_users = settings['users']
Example #14
0
    def __init__(self, code, name, params=None):
        if params is None:
            params = {}

        if self.COMPONENT_SINGLETON:
            if self.__class__.get_instance() is not None:
                Log.error(self.__class__.__name__ + ' cannot be allocated more than once')
                raise Exception(self.__class__.__name__ + ' cannot be allocated more than once')

        self._code = code
        self._name = name
        self._params = params

        Log.info('Daemon ' + self.get_code() + ' loaded')
Example #15
0
    def _on_signal(self, signal: Signal):
        Log.info("Received signal: " + str(signal))

        self._delay_signal()

        if self.is_learning():
            self._learn_signal(signal)

        else:
            self.send_intercom_message(
                SignalManager.INTERCOM_MESSAGE_EVENT_SIGNAL_RECEIVED,
                signal.to_dict())

            recognized_signal = SignalRepo.get_by_signal(signal)
            if recognized_signal is not None:
                Log.info("Recognized signal: " + str(recognized_signal))
                self.send_intercom_message(
                    SignalManager.INTERCOM_MESSAGE_EVENT_SIGNAL_RECOGNIZED,
                    recognized_signal.to_dict())
Example #16
0
    def do_GET(self):
        m = re.search(r'^/(?P<cam>[\w+\-_]+)\.(?P<mode>mjpg|html)$', self.path)

        if m:
            cam = m.group('cam')
            mode = m.group('mode')

            Log.info('Cam HTTP request for "' + cam + '" (mode ' + mode + ')')

            cam_instance = CamRepo.get_by_code(cam)

            if cam_instance is not None:
                if mode == 'mjpg':
                    self.send_mjpeg(cam_instance)
                    return
                elif mode == 'html':
                    self.send_html(cam_instance)
                    return

        self.send404()
Example #17
0
    def send_picture(self, file_name, caption=None, recipients=None):
        if file_name is None:
            return

        try:
            if recipients is None:
                recipients = self._allowed_users

            for recipient in recipients:
                chat_id = self.get_chat_id(recipient)
                if chat_id is not None:
                    self.get_bot().sendPhoto(chat_id=chat_id,
                                             photo=open(file_name, 'rb'),
                                             caption=caption)
                else:
                    Log.error('Unknown chat ID for user ' + recipient +
                              ', please send a message to this bot')
        except telegram.error.BadRequest:
            pass

        except FileNotFoundError:
            Log.error('File ' + file_name + ' not found')
Example #18
0
    def _on_intercom_message(self, message: Message) -> Reply:
        event = Event.create_from_message(message)

        all_rules = RuleRepo.get_rules()
        for rule in all_rules:
            res = rule.match_event(event)
            if res is not False:
                Log.info('Triggering rule: ' + rule.code)

                variables = copy.deepcopy(message.message_payload)
                variables.update(res)

                threading.Thread(target=rule.fire_actions, kwargs={
                    'variables': variables
                }).start()

                threading.Thread(target=self._trigger_rule_event, kwargs={
                    'rule': rule,
                    'message': message
                }).start()

        return Component._on_intercom_message(self, message)
Example #19
0
    def _on_learn_start(self, message: Message) -> Reply:
        payload = message.message_payload

        self._last_learning_signal = None
        self._learning_signal = Signal(
            code='',
            manager=None,
            device_name=payload['device'],
            sub_name=payload['sub'],
        )

        if self._learn_timeout is not None:
            self._learn_timeout.cancel()

        self._learn_timeout = threading.Timer(interval=self.LEARN_TIMEOUT,
                                              function=self._on_learn_timeout)
        self._learn_timeout.start()

        Log.info("Learning start: " + str(self._learning_signal))
        self.send_intercom_message(self.INTERCOM_MESSAGE_EVENT_LEARN_START,
                                   self._learning_signal.to_dict())

        return Reply(Reply.INTERCOM_STATUS_SUCCESS)
Example #20
0
    def send(self) -> Reply:
        """
        Send a message to intercom channel
        :return: Message reply
        """
        from survy.core.app import App

        found = False
        res = {}
        status = Reply.INTERCOM_STATUS_SUCCESS

        recipients = self.get_recipients()
        for component in recipients:
            component_instance = App.components.get(component)

            if component_instance is not None:
                reply = component_instance.handle_intercom_message(self)

                if reply is not None:
                    if reply != Reply.INTERCOM_STATUS_NOT_FOUND:
                        # At least one component can handle our message
                        found = True

                        if reply == Reply.INTERCOM_STATUS_FAILURE:
                            # Set failure when at least one component replies with failure
                            status = Reply.INTERCOM_STATUS_FAILURE

                        res[component] = reply.to_dict()

            else:
                Log.error('Unknown component: ' + component)

        if not found:
            return Reply(Reply.INTERCOM_STATUS_NOT_FOUND)

        return Reply(status, res)
Example #21
0
    def load(cls):
        """
        Load YML rules file
        """
        cls._rules = []

        rules_file = cls._get_rules_file()
        try:
            rules = yaml.load(open(rules_file, 'r'))
            Log.info("Loading rules information from " + rules_file)
        except:
            Log.error("Loading rules information failed from " + rules_file)
            return

        for rule_code, rule_info in rules.items():

            event_instances = []
            action_instances = []
            condition_instances = []

            for event in rule_info['events']:
                if 'type' not in event:
                    Log.error('Missing "type" for event on rule "' + rule_code + '"')
                    continue

                payload = {}
                if 'payload' in event:
                    payload = event['payload']

                component = None
                if 'component_from' in event:
                    component = event['component_from']

                event_instances.append(Event(
                    message_from=component,
                    message_to='',
                    message_type=event['type'],
                    message_payload=payload
                ))

            for action in rule_info['actions']:
                if 'type' not in action:
                    Log.error('Missing "type" for action on rule "' + rule_code + '"')
                    continue

                payload = {}
                if 'payload' in action:
                    payload = action['payload']

                component = '_all'
                if 'component_to' in action:
                    component = action['component_to']

                async = False
                if 'async' in action:
                    async = action['async']

                delay = False
                if 'delay' in action:
                    delay = action['delay']

                action_instances.append(Action(
                    message_to=component,
                    message_from=RuleManager.get_instance().get_code(),
                    message_type=action['type'],
                    message_payload=payload,
                    action_async=async,
                    action_delay=delay
                ))

            if 'conditions' in rule_info:
                for condition in rule_info['conditions']:
                    if 'payload' in condition:
                        payload = condition['payload']
                        condition_instance = Condition(
                            condition_payload=payload
                        )
                        condition_instances.append(condition_instance)

            if 'name' not in rule_info:
                rule_info['name'] = rule_code

            rule = Rule(
                code=rule_code,
                name=rule_info['name'],
                events=event_instances,
                actions=action_instances,
                conditions=condition_instances
            )

            cls._rules.append(rule)
Example #22
0
    def start(cls):
        cls.load_variables()
        cls.load_components()
        cls.start_components()

        Log.info("Engine started")
Example #23
0
 def start_components(cls):
     Log.info("Starting components")
     components_list = cls.components.get_list()
     for code in components_list:
         threading.Thread(target=cls.components.get(code).start).start()
Example #24
0
 def start(self):
     """
     Start component
     """
     Log.info('Daemon ' + self.get_code() + ' started')
Example #25
0
    def _on_learn_end(self):
        Log.info("Exiting learning mode")

        self._learning_signal = None
        self._learn_timeout.cancel()
        return Reply(Reply.INTERCOM_STATUS_SUCCESS)