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)
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']
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))
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
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
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)
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()
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']
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 = {}
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)
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']
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')
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())
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()
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)
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)
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)
def start(self): """ Start component """ Log.info('Daemon ' + self.get_code() + ' started')
def start(cls): cls.load_variables() cls.load_components() cls.start_components() Log.info("Engine started")
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()
def _on_learn_end(self): Log.info("Exiting learning mode") self._learning_signal = None self._learn_timeout.cancel() return Reply(Reply.INTERCOM_STATUS_SUCCESS)