def _env_var_yaml(loader, node): """Load environment variables and embed it into the configuration YAML.""" if node.value in os.environ: return os.environ[node.value] else: _LOGGER.error("Environment variable %s not defined.", node.value) raise BluMateError(node.value)
def load_yaml(fname): """Load a YAML file.""" try: with open(fname, encoding='utf-8') as conf_file: # If configuration file is empty YAML returns None # We convert that to an empty dict return yaml.load(conf_file, Loader=SafeLineLoader) or {} except yaml.YAMLError as exc: _LOGGER.error(exc) raise BluMateError(exc)
def load_yaml_config_file(config_path): """Parse a YAML configuration file.""" conf_dict = load_yaml(config_path) if not isinstance(conf_dict, dict): _LOGGER.error( 'The configuration file %s does not contain a dictionary', os.path.basename(config_path)) raise BluMateError() return conf_dict
def from_config(config, config_validation=True): """Turn a condition configuration into a method.""" factory = getattr(sys.modules[__name__], FROM_CONFIG_FORMAT.format(config.get(CONF_CONDITION)), None) if factory is None: raise BluMateError('Invalid condition "{}" specified {}'.format( config.get(CONF_CONDITION), config)) return factory(config, config_validation)
def __call__(self, method, path, data=None): """Make a call to the Home Assistant API.""" if data is not None: data = json.dumps(data, cls=JSONEncoder) url = urllib.parse.urljoin(self.base_url, path) try: if method == METHOD_GET: return requests.get( url, params=data, timeout=5, headers=self._headers) else: return requests.request( method, url, data=data, timeout=5, headers=self._headers) except requests.exceptions.ConnectionError: _LOGGER.exception("Error connecting to server") raise BluMateError("Error connecting to server") except requests.exceptions.Timeout: error = "Timeout when talking to {}".format(self.host) _LOGGER.exception(error) raise BluMateError(error)
def start(self): """Start the instance.""" # Ensure a local API exists to connect with remote if 'api' not in self.config.components: if not bootstrap.setup_component(self, 'api'): raise BluMateError( 'Unable to setup local API to receive events') bm.create_timer(self) self.bus.fire(bm.EVENT_BLUMATE_START, origin=bm.EventOrigin.remote) # Give eventlet time to startup import eventlet eventlet.sleep(0.1) # Setup that events from remote_api get forwarded to local_api # Do this after we fire START, otherwise HTTP is not started if not connect_remote_events(self.remote_api, self.config.api): raise BluMateError(( 'Could not setup event forwarding from api {} to ' 'local api {}').format(self.remote_api, self.config.api))
def see(self, mac=None, dev_id=None, host_name=None, location_name=None, gps=None, gps_accuracy=None, battery=None): """Notify the device tracker that you see a device.""" with self.lock: if mac is None and dev_id is None: raise BluMateError('Neither mac or device id passed in') elif mac is not None: mac = mac.upper() device = self.mac_to_dev.get(mac) if not device: dev_id = util.slugify(host_name or '') or util.slugify(mac) else: dev_id = cv.slug(str(dev_id).lower()) device = self.devices.get(dev_id) if device: device.seen(host_name, location_name, gps, gps_accuracy, battery) if device.track: device.update_ha_state() return # If no device can be found, create it dev_id = util.ensure_unique_string(dev_id, self.devices.keys()) device = Device(self.hass, self.consider_home, self.home_range, self.track_new, dev_id, mac, (host_name or dev_id).replace('_', ' ')) self.devices[dev_id] = device if mac is not None: self.mac_to_dev[mac] = device device.seen(host_name, location_name, gps, gps_accuracy, battery) if device.track: device.update_ha_state() # During init, we ignore the group if self.group is not None: self.group.update_tracked_entity_ids( list(self.group.tracking) + [device.entity_id]) update_config(self.hass.config.path(YAML_DEVICES), dev_id, device)
def __init__(self, remote_api, local_api=None): """Initalize the forward instance.""" if not remote_api.validate_api(): raise BluMateError( "Remote API at {}:{} not valid: {}".format( remote_api.host, remote_api.port, remote_api.status)) self.remote_api = remote_api self.pool = pool = bm.create_worker_pool() self.bus = EventBus(remote_api, pool) self.services = bm.ServiceRegistry(self.bus, pool) self.states = StateMachine(self.bus, self.remote_api) self.config = bm.Config() self.config.api = local_api
def fire(self, event_type, event_data=None, origin=EventOrigin.local): """Fire an event.""" if not self._pool.running: raise BluMateError('BluMate has shut down.') with self._lock: # Copy the list of the current listeners because some listeners # remove themselves as a listener while being executed which # causes the iterator to be confused. get = self._listeners.get listeners = get(MATCH_ALL, []) + get(event_type, []) event = Event(event_type, event_data, origin) if event_type != EVENT_TIME_CHANGED: _LOGGER.info("Bus:Handling %s", event) if not listeners: return job_priority = JobPriority.from_event_type(event_type) for func in listeners: self._pool.add_job(job_priority, (func, event))
def _raise_on_error(result): """Raise error if error result.""" if result != 0: raise BluMateError('Error talking to MQTT: {}'.format(result))