def get_special_placeholder(): from platform import system return { 'DAEMON_SOURCE_FILENAME': DOORPI.parse_string(DOORPI.CONST.DAEMON_FILE['source']), 'DAEMON_TARGET_FILENAME': DOORPI.parse_string(DOORPI.CONST.DAEMON_FILE['target']), 'DAEMON_INSTALL_COMMAND': DOORPI.parse_string(DOORPI.CONST.DAEMON_FILE['install_command']), 'DAEMON_UNINSTALL_COMMAND': DOORPI.parse_string(DOORPI.CONST.DAEMON_FILE['uninstall_command']), 'DAEMON_STDIN_PATH': DOORPI.CONST.DAEMON_STDIN_PATH, 'DAEMON_STDOUT_PATH': DOORPI.CONST.DAEMON_STDOUT_PATH, 'DAEMON_STDERR_PATH': DOORPI.CONST.DAEMON_STDERR_PATH, 'DAEMON_PIDFILE': DOORPI.CONST.DAEMON_PIDFILE, 'DAEMON_PIDFILE_TIMEOUT': DOORPI.CONST.DAEMON_PIDFILE_TIMEOUT, 'PROJECT': DOORPI.CONST.META.prog, 'PROJECT_VERSION': DOORPI.CONST.META.version, 'PROJECT_DESCRIPTION': DOORPI.CONST.META.description, 'DAEMON_DEFAULT_ARGUMENTS': DOORPI.CONST.DAEMON_DEFAULT_ARGUMENTS }
def start(self): logger.debug("start ConfigHandler with configfile %s", DOORPI.arguments.config_file) DOORPI.register_module(__name__, self.start, self.stop) self._config_object = self.load_config_from_configfile( DOORPI.arguments.config_file) return self
def _fire_events_for_input_id(self, event_names, input_id): if input_id not in self.inputs: return False for event_variation in self._create_event_variations( self.inputs[input_id].technical_name, event_names): DOORPI.events(self._id, event_variation, kwargs=self.inputs[input_id].__dict__.update( self.interface_info)) for event_variation in self._create_event_variations( self.inputs[input_id].name, event_names): DOORPI.events(self._id, event_variation, kwargs=self.inputs[input_id].__dict__.update( self.interface_info)) return True
def write_parsed_daemon_file(): from os import stat as get_file_attributes, chmod from stat import S_IEXEC as ExecutableBit special_placeholder = get_special_placeholder() source_file = open(special_placeholder['DAEMON_SOURCE_FILENAME'], 'r') target_file = open(special_placeholder['DAEMON_TARGET_FILENAME'], 'w') logger.info( "write example daemonfile from %s to %s and replace the placeholder inside the examplefile", special_placeholder['DAEMON_SOURCE_FILENAME'], special_placeholder['DAEMON_TARGET_FILENAME']) for single_line in source_file.readlines(): target_file.write(DOORPI.parse_string(single_line, special_placeholder)) source_file.close() target_file.close() logger.info("make the daemonfile %s executable", special_placeholder['DAEMON_TARGET_FILENAME']) chmod( special_placeholder['DAEMON_TARGET_FILENAME'], get_file_attributes( special_placeholder['DAEMON_TARGET_FILENAME']).st_mode | ExecutableBit) return special_placeholder['DAEMON_TARGET_FILENAME']
def __init__(self, callback, id=None, **kwargs): self._id = id or DOORPI.generate_id(prefix='Action_') self._callback = callback self._kwargs = kwargs if len(self.__class__.__bases__) is 0: self.action_name = str(callback) else: self.action_name = self.__class__.__name__
def _fire_output_event(self, technical_name, event_names): for output_id in self.outputs: if self.outputs[output_id].technical_name != technical_name: continue for event_variation in self._create_event_variations( self.outputs[output_id].technical_name, event_names): DOORPI.events(self._id, event_variation, kwargs=self.inputs[input_id].__dict__.update( self.interface_info)) for event_variation in self._create_event_variations( self.outputs[output_id].name, event_names): DOORPI.events(self._id, event_variation, kwargs=self.inputs[input_id].__dict__.update( self.interface_info)) return True return False
def load_interface(self, config_path, interface_name): try: module_type = DOORPI.config(config_path + interface_name + '/type', None) if not module_type: raise MissingInterfaceTypException() interface_object = importlib.import_module(DOORPI.CONST.INTERFACES_BASE_IMPORT_PATH + module_type).__interface__( name = interface_name, config_path = config_path + interface_name ) if interface_name in self._interfaces: raise InterfaceNameAlreadyExistsException(interface_name) else: self._interfaces[interface_name] = interface_object.start() except Exception as exp: logger.exception('failed to load interface with error %s', exp)
def start(self): super(GPIOBasedInterface, self).start() GPIO.setwarnings(DOORPI.config(self._conf + '/setwarnings', False)) GPIO.setmode(DOORPI.config(self._conf + '/mode', GPIO.BOARD)) logger.debug('use GPIO %s - %s', GPIO.VERSION, GPIO.RPI_INFO) self._register_channels() DOORPI.events.register_events(self.module_name, *self.channel_events) default_edge = DOORPI.config('%s/event_edge' % self._conf, GPIO.BOTH) default_bouncetime = DOORPI.config('%s/event_bouncetime' % self._conf, 40) default_pull_up_down = DOORPI.config('%s/pull_up_down' % self._conf, GPIO.PUD_OFF) for input_id in self.inputs: GPIO.setup(channel=self.inputs[input_id].technical_name, direction=GPIO.IN, pull_up_down=DOORPI.config( '%s/outputs/%s/pull_up_down' % (self._conf, self.inputs[input_id].name), default_pull_up_down)) GPIO.add_event_detect(gpio=self.inputs[input_id].technical_name, edge=DOORPI.config( '%s/outputs/%s/event_edge' % (self._conf, self.inputs[input_id].name), default_edge), callback=self.event_detect, bouncetime=DOORPI.config( '%s/outputs/%s/event_bouncetime' % (self._conf, self.inputs[input_id].name), default_bouncetime)) for output_id in self.outputs: GPIO.setup(channel=self.outputs[output_id].technical_name, direction=GPIO.OUT, initial=self.outputs[output_id].value) self.set_output(output_id, self.outputs[output_id].value, log=False) self._register_outputs_actions()
def load_config_from_configfile(config_file=None): with open(DOORPI.parse_string(config_file)) as data_file: config_object = json.load(data_file) return config_object
def __init__(self): DOORPI.register_module(__name__, self.start, self.stop, False)
def start(self): logger.debug("start InterfaceHandler") for interface_name in DOORPI.config('/interfaces', default = [], function = 'keys'): self.load_interface('/interfaces/', interface_name) logger.debug('loaded %s interfaces', len(self._interfaces))
class InterfaceBaseClass(object): _id = DOORPI.generate_id(prefix='Interface_') _conf = None _name = '' _destroyed = False @property def id(self): return self._id @property def is_destroyed(self): return self._destroyed @property def fullname(self): return "[%s] %s (%s.%s)" % (self._id, self._name, self.module_name, self.class_name) @property def name(self): return self._name @property def module_name(self): return self.__class__.__module__ @property def class_name(self): return self.__class__.__name__ @property def interface_info(self): return { 'class_name': self.class_name, 'module_name': self.module_name, 'interface_name': self.name, 'interface_id': self.id #'channel' : self.last_key } def interface_name_variations(self, prefix='', postfix=''): return [ "", "%s%s%s" % (prefix, self.name, postfix), "%s%s%s" % (prefix, self.module_name, postfix), "%s%s.%s%s" % (prefix, self.module_name, self.name, postfix) ] def __init__(self, name, config_path): self._name = name self._conf = config_path self._register_destroy_action() def start(self): logger.debug('%s starting', self.fullname) def stop(self): logger.debug('%s stopping', self.fullname) DOORPI.events.unregister_source(self._id) def _register_destroy_action(self, stop_function=None): if stop_function is None: stop_function = self.stop return DOORPI.events.register_action( InterfaceStopAction(stop_function), 'OnShutdown')
def start(self): super(HardwareInterfaceBaseClass, self).start() if DOORPI.config(self._conf + '/reverse_polarity', False): self._high_level = DOORPI.CONST.LOW_LEVEL self._low_level = DOORPI.CONST.HIGH_LEVEL
def _register_channels(self): inputs = DOORPI.config(self._conf + '/inputs', [], function='keys') logger.info('%s has %s inputs', self.fullname, len(inputs)) for input_name in inputs: if input_name in self._inputs: raise InputNameAlreadyExistsException() input_id = DOORPI.generate_id(prefix='Input_') self._inputs[input_id] = SingleChannel( id=input_id, name=input_name, technical_name=DOORPI.config( '%s/inputs/%s/technical_name' % (self._conf, input_name), input_name), initial_value=DOORPI.config( '%s/inputs/%s/initial_value' % (self._conf, input_name), False), log=DOORPI.config( '%s/inputs/%s/log' % (self._conf, input_name), True), ) outputs = DOORPI.config(self._conf + '/outputs', [], function='keys') logger.info('%s has %s outputs', self.fullname, len(inputs)) for output_name in outputs: if output_name in self._outputs: raise OutputNameAlreadyExistsException() output_id = DOORPI.generate_id(prefix='Output_') self._outputs[output_id] = SingleChannel( id=output_id, name=output_name, technical_name=DOORPI.config( '%s/outputs/%s/technical_name' % (self._conf, output_name), output_name), initial_value=DOORPI.config( '%s/outputs/%s/initial_value' % (self._conf, output_name), False), log=DOORPI.config( '%s/outputs/%s/log' % (self._conf, output_name), True), high_level=DOORPI.config( '%s/outputs/%s/high_level' % (self._conf, output_name), True), low_level=DOORPI.config( '%s/outputs/%s/low_level' % (self._conf, output_name), False), high_by_event=DOORPI.config( '%s/outputs/%s/high_by_event' % (self._conf, output_name), None), low_by_event=DOORPI.config( '%s/outputs/%s/low_by_event' % (self._conf, output_name), None), )
def do_tick_tack(self, time_for_this_tick=0.2): timestamp_now = time.time() timestamp_past = self.last_time_tick datetime_now = datetime.datetime.fromtimestamp(timestamp_now) datetime_past = datetime.datetime.fromtimestamp(timestamp_past) if datetime_now.year != datetime_past.year: DOORPI.events('OnTimeYear', __name__) if datetime_now.year % 2 is 0: DOORPI.events('OnTimeYearEvenNumber', __name__) else: DOORPI.events('OnTimeYearUnevenNumber', __name__) if datetime_now.month != datetime_past.month: DOORPI.events('OnTimeMonth', __name__) if datetime_now.month % 2 is 0: DOORPI.events('OnTimeMonthEvenNumber', __name__) else: DOORPI.events('OnTimeMonthUnevenNumber', __name__) if datetime_now.day != datetime_past.day: DOORPI.events('OnTimeDay', __name__) if datetime_now.day % 2 is 0: DOORPI.events('OnTimeDayEvenNumber', __name__) else: DOORPI.events('OnTimeDayUnevenNumber', __name__) if datetime_now.hour != datetime_past.hour: DOORPI.events('OnTimeHour', __name__) if datetime_now.hour % 2 is 0: DOORPI.events('OnTimeHourEvenNumber', __name__) else: DOORPI.events('OnTimeHourUnevenNumber', __name__) for hour in DOORPI.CONST.HOUR_RANGE: if hour is datetime_now.hour: DOORPI.events('OnTimeHour%s' % hour, __name__) if datetime_now.minute != datetime_past.minute: DOORPI.events('OnTimeMinute', __name__) if datetime_now.minute % 2 is 0: DOORPI.events('OnTimeMinuteEvenNumber', __name__) else: DOORPI.events('OnTimeMinuteUnevenNumber', __name__) for minute in DOORPI.CONST.MINUTE_RANGE: if minute is datetime_now.minute: DOORPI.events('OnTimeMinute%s' % minute, __name__) if datetime_now.minute % 5 is 0: DOORPI.events('OnTimeMinuteEvery5', __name__) if datetime_now.second != datetime_past.second: DOORPI.events('OnTimeSecond', __name__) if datetime_now.second % 2 is 0: DOORPI.events('OnTimeSecondEvenNumber', __name__) else: DOORPI.events('OnTimeSecondUnevenNumber', __name__) microsecond = datetime_now.microsecond / 100000 if (microsecond % 2 is 0 or microsecond is 0 ) and microsecond is not self.last_realtime_event: self.last_realtime_event = microsecond DOORPI.events('OnTimeTick', __name__) self.last_time_tick = timestamp_now sleep_time = time_for_this_tick - (timestamp_now - time.time()) if sleep_time > 0: time.sleep(sleep_time) return True
def heart_beat(self): timestamp_now = time.time() timestamp_past = self._last_time_tick datetime_now = datetime.datetime.fromtimestamp(timestamp_now) datetime_past = datetime.datetime.fromtimestamp(timestamp_past) if datetime_now.year != datetime_past.year: DOORPI.events('OnTimeYear', __name__) if datetime_now.year % 2 is 0: self('OnTimeYearEvenNumber', __name__) else: self('OnTimeYearUnevenNumber', __name__) if datetime_now.month != datetime_past.month: DOORPI.events('OnTimeMonth', __name__) if datetime_now.month % 2 is 0: self('OnTimeMonthEvenNumber', __name__) else: self('OnTimeMonthUnevenNumber', __name__) if datetime_now.day != datetime_past.day: DOORPI.events('OnTimeDay', __name__) if datetime_now.day % 2 is 0: self('OnTimeDayEvenNumber', __name__) else: self('OnTimeDayUnevenNumber', __name__) if datetime_now.hour != datetime_past.hour: DOORPI.events('OnTimeHour', __name__) if datetime_now.hour % 2 is 0: self('OnTimeHourEvenNumber', __name__) else: self('OnTimeHourUnevenNumber', __name__) for hour in DOORPI.CONST.HOUR_RANGE: if hour is datetime_now.hour: self('OnTimeHour%s' % hour, __name__) if datetime_now.minute != datetime_past.minute: DOORPI.events('OnTimeMinute', __name__) if datetime_now.minute % 2 is 0: self('OnTimeMinuteEvenNumber', __name__) else: self('OnTimeMinuteUnevenNumber', __name__) for minute in DOORPI.CONST.MINUTE_RANGE: if minute is datetime_now.minute: self('OnTimeMinute%s' % minute, __name__) if datetime_now.minute % 5 is 0: self('OnTimeMinuteEvery5', __name__) if datetime_now.second != datetime_past.second: DOORPI.events('OnTimeSecond', __name__) if datetime_now.second % 2 is 0: self('OnTimeSecondEvenNumber', __name__) else: self('OnTimeSecondUnevenNumber', __name__) microsecond = datetime_now.microsecond / 100000 if (microsecond % 2 is 0 or microsecond is 0 ) and microsecond is not self._last_realtime_event: self._last_realtime_event = microsecond DOORPI.events('OnTimeTick', __name__) sleep_time = (self._last_heart_beat * 0.5 + DOORPI.CONST.HEART_BEAT_BASE_VALUE) - (timestamp_now - time.time()) if sleep_time > 0: time.sleep(sleep_time) self._last_time_tick = timestamp_now self._last_heart_beat = time.time() - timestamp_now return not self._destroy
def start(self, db_type, connection_string): connection_string = DOORPI.parse_string(connection_string) logger.info('open %s db for event history with connection string "%s"', db_type, connection_string) return self
def fire_event_synchron(self, event_source, event_name, kwargs=None): if self._destroy and event_source != __name__: return False log = self.log_for_event(event_name) event_fire_id = DOORPI.generate_id(prefix='Event_') if kwargs is None: kwargs = {} kwargs.update({ 'last_fired': time.time(), 'last_fired_from': event_source, 'event_fire_id': event_fire_id }) message = '' if event_name not in self._events.keys(): message = 'unknown event' elif event_source not in self._events[event_name].sources: message = 'unknown source for this event' elif len(self._events[event_name].actions) == 0: message = 'no actions for this event' if message != '': message = '[%s] %s - skip fire event %s from %s' % ( event_fire_id, message, event_name, event_source) if log: logger.info(message) return message if log: logger.debug( "[%s] fire for event %s from %s this actions %s with kwargs %s", event_fire_id, event_name, event_source, self._events[event_name].actions, kwargs) for action_id in self._events[event_name].actions: if action_id not in self._actions.keys(): logger.error( '[%s] missing action reference for action_id %s by event %s', event_fire_id, action_id, event_name) continue if log: logger.debug("[%s] try to fire action %s", event_fire_id, self._actions[action_id]) try: result = self._actions[action_id].run(**kwargs) if not result and log: logger.warning('[%s] action %s returns %s', event_fire_id, self._actions[action_id], result) if self._actions[action_id].single_fire_action is True: self.unregister_action(action_id) except SystemExit as exp: logger.info( '[%s] Detected SystemExit and shutdown DoorPi (Message: %s)', event_fire_id, exp) DOORPI.stop() except KeyboardInterrupt as exp: logger.info( "[%s] Detected KeyboardInterrupt and shutdown DoorPi (Message: %s)", event_fire_id, exp) DOORPI.stop() except: logger.exception( "[%s] error while fire action %s for event_name %s", event_fire_id, self._actions[action_id], event_name) if log: logger.debug("[%s] finished fire_event for event %s from %s", event_fire_id, event_name, event_source) return True
# -*- coding: utf-8 -*- from main import DOORPI logger = DOORPI.register_module(__name__, return_new_logger=True) from plugins.interfaces.hardware import HardwareInterfaceBaseClass class FileSystemBasedInterface(HardwareInterfaceBaseClass): def __init__(self): pass def start(self, interface_id, config): logger.debug('[%s] start interface %s (type: %s)', interface_id, config['name'], config['type']) def stop(self): pass __interface__ = FileSystemBasedInterface()
# -*- coding: utf-8 -*- from main import DOORPI logger = DOORPI.register_modul(__name__) class EventHandlerConfig: typ = { 'type': 'string', 'default': DOORPI.CONSTEVENTHANDLER_DB_TYP, 'description': 'EventHandlerConfig_key_typ' } connection_string = DOORPI.EVENTHANDLER_DB_CONNECTIONSTRING