def execute(self, handler, cmd, source): """ Execute an arbitrary command :param handler: CLIHandler to use for reply :param cmd: Received command :param source: Call source :return: TRUE: Command found and handled, FALSE: Unknown command, nothing done """ if self.plugin and getattr(self.plugin, 'alive', False): if self.logics is None: self.logics = Logics.get_instance() for command, data in self._commands.items(): if cmd == command or cmd.startswith(command + " "): self.logger.debug( "try to dispatch command '{}'".format(cmd)) try: data['function'](handler, cmd.lstrip(command).strip(), source) except Exception as e: self.logger.exception(e) handler.push( "Exception \"{0}\" occured when executing command \"{1}\".\n" .format(e, command)) handler.push("See smarthomeNG log for details\n") return True return False
def __init__(self, smarthome, dispatcher, sock, addr, items, visu_logics, proto, querydef): lib.connection.Stream.__init__(self, sock, addr) self.terminator = b"\r\n\r\n" self.logger = logging.getLogger(__name__) self._sh = smarthome self.shtime = dispatcher.shtime self._dp = dispatcher self.found_terminator = self.parse_header self.addr = addr self.header = {} self.monitor = {'item': [], 'rrd': [], 'log': []} self.monitor_id = {'item': 'item', 'rrd': 'item', 'log': 'name'} self._update_series = {} self.items = items self.rrd = False self.log = False self.logs = self._sh.return_logs() self._series_lock = threading.Lock() self.visu_logics = visu_logics self.proto = proto self.querydef = querydef self.logger.info( "VISU: Websocket handler uses protocol version {0}".format( self.proto)) self.sw = '' self.swversion = '' self.hostname = '' self.browser = '' self.browserversion = '' # get access to the logics api from lib.logic import Logics self.logics = Logics.get_instance() return
def logics_initialize(self): """ Initialize access to logics API and test if Blockly plugin is loaded This can't be done during __init__, since not all components are loaded/initialized at that time. """ if self.logics is not None: return self.logics = Logics.get_instance() self.yaml_updates = (self.logics.return_config_type() == '.yaml') # find out if blockly plugin is loaded if self.blockly_plugin_loaded == None: self.blockly_plugin_loaded = False # for x in self._sh._plugins: # for x in self._sh.return_plugins(): for x in self.plugins.return_plugins(): try: if x.get_shortname() == 'blockly': self.blockly_plugin_loaded = True except: pass return
def run(self): """ This is called when the plugins thread is about to run """ self.alive = True self.logics = Logics.get_instance() # Returns the instance of the Logics class, to be used to access the logics-api q = self._updater.start_polling(timeout=self._long_polling_timeout) # (poll_interval=0.0, timeout=10, network_delay=None, clean=False, bootstrap_retries=0, read_latency=2.0, allowed_updates=None) if self._pretty_thread_names: self.logger.debug("Changing Telegrams thread names to pretty thread names") try: for t in self._updater._Updater__threads: if 'dispatcher' in t.name: t.name = 'Telegram Dispatcher' if 'updater' in t.name: t.name = 'Telegram Updater' for t in self._updater.dispatcher._Dispatcher__async_threads: *_, num = t.name.split('_') t.name = 'Telegram Worker {}'.format(num) if num.isnumeric() else num except: self.logger.warning("Could not assign pretty names to Telegrams threads, maybe object model of python-telegram-bot module has changed? Please inform the author of plugin!") self.logger.debug("started polling the updater, Queue is {}".format(q)) self.msg_broadcast(self._welcome_msg) self.logger.debug("sent welcome message {}")
def run(self): self.alive = True self.logics = Logics.get_instance( ) # Returns the instance of the Logics class, to be used to access the logics-api self._updater.start_polling( ) # (poll_interval=0.0, timeout=10, network_delay=None, clean=False, bootstrap_retries=0, read_latency=2.0, allowed_updates=None)
def __init__(self): # !! Cannot initialze self.logics here, because at startup logics are initialized after plugins !! self.logics = Logics.get_instance() self.logger.info("BackendLogics __init__ self.logics = {}".format(self.logics)) self.plugins = Plugins.get_instance() self.logger.info("BackendLogics __init__ self.plugins = {}".format(str(self.plugins))) self.scheduler = Scheduler.get_instance() self.logger.info("BackendLogics __init__ self.scheduler = {}".format(self.scheduler))
def index(self, reload=None): """ Build index.html for cherrypy Display a list of all connected visu clients Render the template and return the html file to be delivered to the browser :return: contents of the template after beeing rendered """ # get API handles that were unavailable during __init__ if self.items is None: self.items = Items.get_instance() if self.logics is None: self.logics = Logics.get_instance() clients = [] for clientinfo in self.plugin.return_clients(): c = clientinfo.get('addr', '') client = dict() client['ip'] = clientinfo.get('ip', '') client['port'] = clientinfo.get('port', '') try: client['name'] = socket.gethostbyaddr(client['ip'])[0] except: client['name'] = client['ip'] client['sw'] = clientinfo.get('sw', '') client['swversion'] = clientinfo.get('swversion', '') client['protocol'] = clientinfo.get('protocol', '') client['hostname'] = clientinfo.get('hostname', '') client['browser'] = clientinfo.get('browser', '') client['browserversion'] = clientinfo.get('browserversion', '') clients.append(client) clients_sorted = sorted(clients, key=lambda k: k['name']) plgitems = [] for item in self.items.return_items(): if ('visu_acl' in item.conf): plgitems.append(item) plglogics = [] for logic in self.logics.return_logics(): plglogics.append(self.logics.get_logic_info(logic)) tmpl = self.tplenv.get_template('index.html') return tmpl.render(p=self.plugin, items=sorted(plgitems, key=lambda k: str.lower(k['_path'])), logics=sorted(plglogics, key=lambda k: str.lower(k['name'])), clients=clients_sorted, client_count=len(clients_sorted))
def index_html(self, cmd='', filename='', logicname='', v=0): self.logger.info( "index_html: cmd = '{}', filename = '{}', logicname = '{}'".format( cmd, filename, logicname)) if self.edit_redirect != '': self.edit_html(cmd='edit', logicname=self.edit_redirect) if self.logics is None: self.logics = Logics.get_instance() cherrypy.lib.caching.expires(0) if cmd == '' and filename == '' and logicname == '': cmd = self.cmd if cmd == '': cmd = 'new' self.cmd = cmd.lower() self.logger.info( "index_html: cmd = {}, filename = {}, logicname = {}".format( cmd, filename, logicname)) if self.cmd == '': # self.logic_filename = '' self.logicname = '' elif self.cmd == 'new': self.logic_filename = 'new' self.logicname = '' elif self.cmd == 'edit' and filename != '': self.logic_filename = filename self.logicname = logicname self.logger.info( "index_html: self.logicname = '{}', self.logic_filename = '{}'". format(self.logicname, self.logic_filename)) language = self._sh.get_defaultlanguage() if language != get_translation_lang(): self.logger.debug( "index_html: Language = '{}' get_translation_lang() = '{}'". format(language, get_translation_lang())) if not load_translation(language): self.logger.warning( "index_html: Language '{}' not found, using standard language instead" .format(language)) tmpl = self.tplenv.get_template('blockly.html') return tmpl.render(smarthome=self._sh, dyn_sh_toolbox=self._DynToolbox(self._sh), cmd=self.cmd, logicname=logicname, timestamp=str(time.time()), lang=translation_lang)
async def get_shng_class_instances(self): """ Ensure that the instance vars for items and logics are initialized """ while self.items is None: self.items = Items.get_instance() if self.items is None: await asyncio.sleep(1) while self.logics is None: self.logics = Logics.get_instance() if self.logics is None: await asyncio.sleep(1) return
def __init__(self, module): self._sh = module._sh self.module = module self.base_dir = self._sh.get_basedir() self.logger = logging.getLogger(__name__) self.etc_dir = self._sh._etc_dir self.logics_dir = os.path.join(self.base_dir, 'logics') self.logics = Logics.get_instance() self.logger.info("__init__ self.logics = {}".format(self.logics)) self.plugins = Plugins.get_instance() self.logger.info("__init__ self.plugins = {}".format(str( self.plugins))) self.scheduler = Scheduler.get_instance() self.logger.info("__init__ self.scheduler = {}".format(self.scheduler)) self.blockly_plugin_loaded = None self.logics_data = {} self.logics = Logics.get_instance() return
def run(self): """ This is called when the plugins thread is about to run """ self.alive = True self.logics = Logics.get_instance( ) # Returns the instance of the Logics class, to be used to access the logics-api q = self._updater.start_polling( timeout=self._long_polling_timeout ) # (poll_interval=0.0, timeout=10, network_delay=None, clean=False, bootstrap_retries=0, read_latency=2.0, allowed_updates=None) self.logger.debug("started polling the updater, Queue is {}".format(q)) self._msg_broadcast(self._welcome_msg) self.logger.debug("sent welcome message {}")
def _add_scene_entry(self, item, state, ditemname, value, learn=False, name=''): """ Adds a single assignement entry to the loaded scenes :param item: item defing the scene (type: scene) :param row: list of: state number, item to assign to, value to assign to item :param name: name of the scene state :type item: item object :type row: list (with 3 entries) :type name: str """ logger.debug( "_add_scene_entry: item = {}, state = {}, ditem = {}, value = {}, learn = {}, name = {}" .format(item.id(), state, ditemname, value, learn, name)) value = item.get_stringwithabsolutepathes(value, 'sh.', '(', 'scene') # ditem = self._sh.return_item(item.get_absolutepath(ditemname, attribute='scene')) ditem = self.items.return_item( item.get_absolutepath(ditemname, attribute='scene')) if learn: rvalue = self._eval(value) if str(rvalue) != value: logger.warning( "_add_scene_entry - Learn set to 'False', because '{}' != '{}'" .format(rvalue, value)) learn = False if ditem is None: ditem = Logics.return_logic(ditemname) if ditem is None: logger.warning( "Could not find item or logic '{}' specified in {}".format( ditemname, scene_file)) return if item.id() in self._scenes: if state in self._scenes[item.id()]: self._scenes[item.id()][state].append( [ditem, value, name, learn]) else: self._scenes[item.id()][state] = [[ditem, value, name, learn]] else: self._scenes[item.id()] = {state: [[ditem, value, name, learn]]} return
def __init__(self, smarthome): self._sh = smarthome global _scenes_instance if _scenes_instance is not None: import inspect curframe = inspect.currentframe() calframe = inspect.getouterframes(curframe, 2) logger.critical(translate("A second 'scenes' object has been created. There should only be ONE instance of class 'Scenes'!!! Called from: {frame1} ({frame2})", {'frame1': calframe[1][1], 'frame2': calframe[1][3]})) _scenes_instance = self self.items = Items.get_instance() self.logics = Logics.get_instance() self._load_scenes() return
def run(self): """ This is called when the plugins thread is about to run """ self.alive = True self.logics = Logics.get_instance( ) # Returns the instance of the Logics class, to be used to access the logics-api q = self._updater.start_polling( timeout=self._long_polling_timeout ) # (poll_interval=0.0, timeout=10, network_delay=None, clean=False, bootstrap_retries=0, read_latency=2.0, allowed_updates=None) if self._pretty_thread_names: if self.logger.isEnabledFor(logging.DEBUG): self.logger.debug( "Changing Telegrams thread names to pretty thread names") try: for t in self._updater._Updater__threads: if 'dispatcher' in t.name: t.name = 'Telegram Dispatcher' if 'updater' in t.name: t.name = 'Telegram Updater' for t in self._updater.dispatcher._Dispatcher__async_threads: *_, num = t.name.split('_') t.name = f'Telegram Worker {num}' if num.isnumeric( ) else num # from telegram.jobqueue.py @ line 301 thread is named # name=f"Bot:{self._dispatcher.bot.id}:job_queue" if hasattr(self._updater.job_queue, '_JobQueue__thread'): t = self._updater.job_queue._JobQueue__thread if t.name.startswith('Bot'): _, id, _ = t.name.split(':') self._updater.job_queue._JobQueue__thread.name = f"Telegram JobQueue for id {id}" else: # model in telegram.ext.jobqueue.py might be changed now pass except Exception as e: self.logger.warning( f"Error '{e}' occurred. Could not assign pretty names to Telegrams threads, maybe object model of python-telegram-bot module has changed? Please inform the author of plugin!" ) if self.logger.isEnabledFor(logging.DEBUG): self.logger.debug(f"started polling the updater, Queue is {q}") if self._welcome_msg: self.msg_broadcast(self._welcome_msg) if self.logger.isEnabledFor(logging.DEBUG): self.logger.debug(f"sent welcome message {self._welcome_msg}")
def __init__(self, webif_dir, plugin): """ Initialization of instance of class WebInterface :param webif_dir: directory where the webinterface of the plugin resides :param plugin: instance of the plugin :type webif_dir: str :type plugin: object """ self.logger = logging.getLogger(__name__) self.webif_dir = webif_dir self.plugin = plugin self.tplenv = self.init_template_environment() # try to get API handles self.items = Items.get_instance() self.logics = Logics.get_instance()
def _add_scene_entry(self, item, state, ditemname, value, learn=False, name=''): """ Adds a single assignement entry to the loaded scenes :param item: item defing the scene (type: scene) :param row: list of: state number, item to assign to, value to assign to item :param name: name of the scene state :type item: item object :type row: list (with 3 entries) :type name: str """ logger.debug("_add_scene_entry: item = {}, state = {}, ditem = {}, value = {}, learn = {}, name = {}".format(item.id(), state, ditemname, value, learn, name)) value = item.get_stringwithabsolutepathes(value, 'sh.', '(', 'scene') # ditem = self._sh.return_item(item.get_absolutepath(ditemname, attribute='scene')) ditem = self.items.return_item(item.get_absolutepath(ditemname, attribute='scene')) if learn: rvalue = self._eval(value) if str(rvalue) != value: logger.warning("_add_scene_entry - Learn set to 'False', because '{}' != '{}'".format(rvalue, value)) learn = False if ditem is None: ditem = Logics.return_logic(ditemname) if ditem is None: logger.warning("Could not find item or logic '{}' specified in {}".format(ditemname, scene_file)) return if item.id() in self._scenes: if state in self._scenes[item.id()]: self._scenes[item.id()][state].append([ditem, value, name, learn]) else: self._scenes[item.id()][state] = [[ditem, value, name, learn]] else: self._scenes[item.id()] = {state: [[ditem, value, name, learn]]} return
def __init__(self, sh, testparam=''): """ Initialization Routine for the module """ # TO DO: Shortname anders setzen (oder warten bis der Plugin Loader es beim Laden setzt self._shortname = self.__class__.__name__ self._shortname = self._shortname.lower() self.logger = logging.getLogger(__name__) self._sh = sh self.etc_dir = sh._etc_dir self.shtime = Shtime.get_instance() self.logger.debug("Module '{}': Initializing".format(self._shortname)) # get the parameters for the module (as defined in metadata module.yaml): self.logger.debug("Module '{}': Parameters = '{}'".format(self._shortname, dict(self._parameters))) self.ip = self.get_parameter_value('ip') #if self.ip == '0.0.0.0': # self.ip = Utils.get_local_ipv4_address() self.port = self.get_parameter_value('port') self.tls_port = self.get_parameter_value('tls_port') self.use_tls = self.get_parameter_value('use_tls') self.tls_cert = self.get_parameter_value('tls_cert') self.tls_key = self.get_parameter_value('tls_key') # parameters for smartVISU handling are initialized by the smartvisu plugin #self.sv_enabled = self.get_parameter_value('sv_enabled') #self.sv_acl = self.get_parameter_value('default_acl') #self.sv_querydef = self.get_parameter_value('sv_querydef') #self.sv_ser_upd_cycle = self.get_parameter_value('sv_ser_upd_cycle') self.sv_enabled = False self.sv_acl = 'deny' self.sv_querydef = False self.sv_ser_upd_cycle = 0 self.ssl_context = None if self.use_tls: self.ssl_context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER) pem_file = os.path.join(self.etc_dir, self.tls_cert) key_file = os.path.join(self.etc_dir, self.tls_key) try: self.ssl_context.load_cert_chain(pem_file, key_file) except Exception as e: self.logger.error("Secure websocket port not opened because the following error ocured while initilizing tls: {}".format(e)) self.ssl_context = None self.use_tls = False if self.use_tls and self.port == self.tls_port: self.logger.error("Secure websocket port not opened because it cannnot be the same port as the ws:// port:") self.ssl_context = None self.use_tls = False self.logger.info("ip : {}".format(self.ip)) self.logger.info("port : {}".format(self.port)) self.logger.info("tls_port : {}".format(self.tls_port)) self.logger.info("use_tls : {}".format(self.use_tls)) self.logger.info("tls_cert : {}".format(self.tls_cert)) self.logger.info("tls_key : {}".format(self.tls_key)) # try to get API handles self.items = Items.get_instance() self.logics = Logics.get_instance() self.loop = None # Var to hold the event loop for asyncio # For Release 1.8 only: Enable smartVISU protocol support even if smartvisu plugin is not loaded self.set_smartvisu_support(protocol_enabled=True)
def __init__(self): self.logics = Logics.get_instance() self.logger.warning("BackendLogics __init__ self.logics = {}".format( str(self.logics)))
def __init__(self, smarthome): self._sh = smarthome global _scenes_instance if _scenes_instance is not None: import inspect curframe = inspect.currentframe() calframe = inspect.getouterframes(curframe, 2) logger.critical( "A second 'scenes' object has been created. There should only be ONE instance of class 'Scenes'!!! Called from: {} ({})" .format(calframe[1][1], calframe[1][3])) _scenes_instance = self self.items = Items.get_instance() self.logics = Logics.get_instance() self._scenes = {} self._learned_values = {} self._scenes_dir = smarthome._scenes_dir if not os.path.isdir(self._scenes_dir): logger.warning( "Directory scenes not found. Ignoring scenes.".format( self._scenes_dir)) return self._learned_values = {} # for item in smarthome.return_items(): for item in self.items.return_items(): if item.type() == 'scene': self.scene_file = os.path.join(self._scenes_dir, item.id()) scene_file_yaml = yaml.yaml_load(self.scene_file + '.yaml', ordered=False, ignore_notfound=True) if scene_file_yaml is not None: # Reading yaml file with scene definition for state in scene_file_yaml: actions = scene_file_yaml[state].get('actions', None) if actions is not None: if isinstance(actions, dict): actions = [actions] if isinstance(actions, list): for action in actions: if isinstance(action, dict): self._add_scene_entry( item, str(state), action.get('item', ''), str(action.get('value', '')), action.get('learn', ''), scene_file_yaml[state].get( 'name', '')) else: logger.warning( "Scene {}, state {}: action '{}' is not a dict" .format(item, state, action)) else: logger.warning( "Scene {}, state {}: actions are not a list" .format(item, state)) self._load_learned_values(str(item.id())) else: # Trying to read conf file with scene definition scene_conf_file = self.scene_file + '.conf' try: with open(scene_conf_file, 'r', encoding='UTF-8') as f: reader = csv.reader(f, delimiter=' ') for row in reader: if row == []: # ignore empty lines continue if row[0][0] == '#': # ignore comments continue self._add_scene_entry(item, row[0], row[1], row[2]) except Exception as e: logger.warning( "Problem reading scene file {0}: No .yaml or .conf file found with this name" .format(self.scene_file)) continue item.add_method_trigger(self._trigger)
def run(self): self.alive = True self.logics = Logics.get_instance( ) # Returns the instance of the Logics class, to be used to access the logics-api
def setUp(self): logger.warning('') self.sh = MockSmartHome() self._logics = Logics(self.sh, self.sh._logic_conf_basename, self.sh._env_logic_conf_basename) self.logics = Logics.get_instance()