def __init__(self, hass, name, pca_path, knn_path): """Initialize the MlSensor.""" with open(get_default_config_dir() + pca_path, 'rb') as handle: self._pca = pickle.load(handle) with open(get_default_config_dir() + knn_path, 'rb') as handle: self._knn = pickle.load(handle) self._name = name self._state = None self._running = False self._hass = hass hass.services.register(DOMAIN, "check_state", self.poll_status)
def run(args): """Handle Home Assistant auth provider script.""" parser = argparse.ArgumentParser( description=("Manage Home Assistant users")) parser.add_argument( '--script', choices=['auth']) parser.add_argument( '-c', '--config', default=get_default_config_dir(), help="Directory that contains the Home Assistant configuration") subparsers = parser.add_subparsers() parser_list = subparsers.add_parser('list') parser_list.set_defaults(func=list_users) parser_add = subparsers.add_parser('add') parser_add.add_argument('username', type=str) parser_add.add_argument('password', type=str) parser_add.set_defaults(func=add_user) parser_validate_login = subparsers.add_parser('validate') parser_validate_login.add_argument('username', type=str) parser_validate_login.add_argument('password', type=str) parser_validate_login.set_defaults(func=validate_login) parser_change_pw = subparsers.add_parser('change_password') parser_change_pw.add_argument('username', type=str) parser_change_pw.add_argument('new_password', type=str) parser_change_pw.set_defaults(func=change_password) args = parser.parse_args(args) path = os.path.join(os.getcwd(), args.config, hass_auth.PATH_DATA) args.func(hass_auth.load_data(path), args)
def ensure_config_path(config_dir): """Validate the configuration directory.""" lib_dir = os.path.join(config_dir, 'lib') # Test if configuration directory exists if not os.path.isdir(config_dir): if config_dir != config_util.get_default_config_dir(): print(('Fatal Error: Specified configuration directory does ' 'not exist {} ').format(config_dir)) sys.exit(1) try: os.mkdir(config_dir) except OSError: print(('Fatal Error: Unable to create default configuration ' 'directory {} ').format(config_dir)) sys.exit(1) # Test if library directory exists if not os.path.isdir(lib_dir): try: os.mkdir(lib_dir) except OSError: print(('Fatal Error: Unable to create library ' 'directory {} ').format(lib_dir)) sys.exit(1)
def ensure_config_path(config_dir: str) -> None: """Validate the configuration directory.""" import homeassistant.config as config_util lib_dir = os.path.join(config_dir, 'deps') # Test if configuration directory exists if not os.path.isdir(config_dir): if config_dir != config_util.get_default_config_dir(): print(('Fatal Error: Specified configuration directory does ' 'not exist {} ').format(config_dir)) sys.exit(1) try: os.mkdir(config_dir) except OSError: print(('Fatal Error: Unable to create default configuration ' 'directory {} ').format(config_dir)) sys.exit(1) # Test if library directory exists if not os.path.isdir(lib_dir): try: os.mkdir(lib_dir) except OSError: print(('Fatal Error: Unable to create library ' 'directory {} ').format(lib_dir)) sys.exit(1)
def load_token(self): try: persist_token = os.path.join(get_default_config_dir(), self._token_persist_filename) try: with open(persist_token) as f: try: dict_token = json.load(f) except ValueError: return ERROR_VALUE except FileNotFoundError: with open(self._token_persist_filename) as f: try: dict_token = json.load(f) except ValueError: return ERROR_VALUE self._token.set_token(dict_token['_token']) self._token.set_vaild_until(dict_token['_valid_until']) self._token.set_hash_alg(dict_token['_hash_alg']) _LOGGER.debug("load_token successfully...") return True except IOError: _LOGGER.debug("error load_token...") return ERROR_VALUE
def get_arguments() -> argparse.Namespace: """Get parsed passed in arguments.""" import homeassistant.config as config_util parser = argparse.ArgumentParser( description="Home Assistant: Observe, Control, Automate.") parser.add_argument('--version', action='version', version=__version__) parser.add_argument( '-c', '--config', metavar='path_to_config_dir', default=config_util.get_default_config_dir(), help="Directory that contains the Home Assistant configuration") parser.add_argument( '--demo-mode', action='store_true', help='Start Home Assistant in demo mode') parser.add_argument( '--debug', action='store_true', help='Start Home Assistant in debug mode') parser.add_argument( '--open-ui', action='store_true', help='Open the webinterface in a browser') parser.add_argument( '--skip-pip', action='store_true', help='Skips pip install of required packages on startup') parser.add_argument( '-v', '--verbose', action='store_true', help="Enable verbose logging to file.") parser.add_argument( '--pid-file', metavar='path_to_pid_file', default=None, help='Path to PID file useful for running as daemon') parser.add_argument( '--log-rotate-days', type=int, default=None, help='Enables daily log rotation and keeps up to the specified days') parser.add_argument( '--runner', action='store_true', help='On restart exit with code {}'.format(RESTART_EXIT_CODE)) parser.add_argument( '--script', nargs=argparse.REMAINDER, help='Run one of the embedded scripts') if os.name == "posix": parser.add_argument( '--daemon', action='store_true', help='Run Home Assistant as daemon') arguments = parser.parse_args() if os.name != "posix" or arguments.debug or arguments.runner: setattr(arguments, 'daemon', False) return arguments
def run(args): """Handle ensure config commandline script.""" parser = argparse.ArgumentParser( description=("Ensure a Home Assistant config exists, " "creates one if necessary.")) parser.add_argument( '-c', '--config', metavar='path_to_config_dir', default=config_util.get_default_config_dir(), help="Directory that contains the Home Assistant configuration") parser.add_argument('--script', choices=['ensure_config']) args = parser.parse_args() config_dir = os.path.join(os.getcwd(), args.config) # Test if configuration directory exists if not os.path.isdir(config_dir): print(('Creating directory', config_dir)) os.makedirs(config_dir) config_path = config_util.ensure_config_exists(config_dir) print(('Configuration file:', config_path)) return 0
def run(args): """Handle ensure config commandline script.""" parser = argparse.ArgumentParser( description=("Ensure a Home Assistant config exists, " "creates one if necessary.")) parser.add_argument( '-c', '--config', metavar='path_to_config_dir', default=config_util.get_default_config_dir(), help="Directory that contains the Home Assistant configuration") parser.add_argument( '--script', choices=['ensure_config']) args = parser.parse_args() config_dir = os.path.join(os.getcwd(), args.config) # Test if configuration directory exists if not os.path.isdir(config_dir): print('Creating directory', config_dir) os.makedirs(config_dir) config_path = config_util.ensure_config_exists(config_dir) print('Configuration file:', config_path) return 0
def extract_config_dir(args=None) -> str: """Extract the config dir from the arguments or get the default.""" parser = argparse.ArgumentParser(add_help=False) parser.add_argument('-c', '--config', default=None) args = parser.parse_known_args(args)[0] return (os.path.join(os.getcwd(), args.config) if args.config else get_default_config_dir())
def extract_config_dir(args: Optional[Sequence[Text]] = None) -> str: """Extract the config dir from the arguments or get the default.""" parser = argparse.ArgumentParser(add_help=False) parser.add_argument("-c", "--config", default=None) parsed_args = parser.parse_known_args(args)[0] return (os.path.join(os.getcwd(), parsed_args.config) if parsed_args.config else get_default_config_dir())
def ensure_config_path(config_dir: str) -> None: """Validate the configuration directory.""" # pylint: disable=import-outside-toplevel import homeassistant.config as config_util lib_dir = os.path.join(config_dir, "deps") # Test if configuration directory exists if not os.path.isdir(config_dir): if config_dir != config_util.get_default_config_dir(): print( f"Fatal Error: Specified configuration directory {config_dir} " "does not exist") sys.exit(1) try: os.mkdir(config_dir) except OSError: print("Fatal Error: Unable to create default configuration " f"directory {config_dir}") sys.exit(1) # Test if library directory exists if not os.path.isdir(lib_dir): try: os.mkdir(lib_dir) except OSError: print(f"Fatal Error: Unable to create library directory {lib_dir}") sys.exit(1)
def __init__(self, hass, config): self.hass = hass authtoken_path = get_default_config_dir() + "gmusic_authtoken" if os.path.isfile(authtoken_path): with open(authtoken_path, 'rb') as handle: authtoken = pickle.load(handle) else: authtoken = None self._api = GMusic() logged_in = self._api.login(config.get('user'), config.get('password'), config.get('device_id'), authtoken) if not logged_in: _LOGGER.error("Failed to log in, check http://unofficial-google-music-api.readthedocs.io/en/latest/reference/mobileclient.html#gmusicapi.clients.Mobileclient.login") return False with open(authtoken_path, 'wb') as f: pickle.dump(self._api.session._authtoken, f) self._playlist = "input_select." + config.get("playlist","") self._media_player = "input_select." + config.get("media_player","") self._entity_ids = [] self._playing = False self._playlists = [] self._tracks = [] self._next_track_no = 0 self._playlist_to_index = {} self._unsub_tracker = None self._name = "Google music" track_time_change(hass, self._update_playlist, hour=[15, 6], minute=46, second=46) hass.bus.listen_once(EVENT_HOMEASSISTANT_START, self._update_playlist)
def run(args): """Handle ensure config commandline script.""" parser = argparse.ArgumentParser(description=( "Ensure a Home Assistant config exists, creates one if necessary.")) parser.add_argument( "-c", "--config", metavar="path_to_config_dir", default=config_util.get_default_config_dir(), help="Directory that contains the Home Assistant configuration", ) parser.add_argument("--script", choices=["ensure_config"]) args = parser.parse_args() config_dir = os.path.join(os.getcwd(), args.config) # Test if configuration directory exists if not os.path.isdir(config_dir): print("Creating directory", config_dir) os.makedirs(config_dir) hass = HomeAssistant() config_path = hass.loop.run_until_complete(async_run(hass, config_dir)) print("Configuration file:", config_path) return 0
def run(args): """Handle Safegate Pro auth provider script.""" parser = argparse.ArgumentParser(description="Manage Safegate Pro users") parser.add_argument("--script", choices=["auth"]) parser.add_argument( "-c", "--config", default=get_default_config_dir(), help="Directory that contains the Safegate Pro configuration", ) subparsers = parser.add_subparsers(dest="func") subparsers.required = True parser_list = subparsers.add_parser("list") parser_list.set_defaults(func=list_users) parser_add = subparsers.add_parser("add") parser_add.add_argument("username", type=str) parser_add.add_argument("password", type=str) parser_add.set_defaults(func=add_user) parser_validate_login = subparsers.add_parser("validate") parser_validate_login.add_argument("username", type=str) parser_validate_login.add_argument("password", type=str) parser_validate_login.set_defaults(func=validate_login) parser_change_pw = subparsers.add_parser("change_password") parser_change_pw.add_argument("username", type=str) parser_change_pw.add_argument("new_password", type=str) parser_change_pw.set_defaults(func=change_password) asyncio.set_event_loop_policy(runner.HassEventLoopPolicy(False)) asyncio.run(run_command(parser.parse_args(args)))
def get_arguments(): """Get parsed passed in arguments.""" import homeassistant.config as config_util parser = argparse.ArgumentParser( description="Home Assistant: Observe, Control, Automate.") parser.add_argument('--version', action='version', version=__version__) parser.add_argument( '-c', '--config', metavar='path_to_config_dir', default=config_util.get_default_config_dir(), help="Directory that contains the Home Assistant configuration") parser.add_argument('--demo-mode', action='store_true', help='Start Home Assistant in demo mode') parser.add_argument( '--debug', action='store_true', help='Start Home Assistant in debug mode. Runs in single process to ' 'enable use of interactive debuggers.') parser.add_argument('--open-ui', action='store_true', help='Open the webinterface in a browser') parser.add_argument( '--skip-pip', action='store_true', help='Skips pip install of required packages on startup') parser.add_argument('-v', '--verbose', action='store_true', help="Enable verbose logging to file.") parser.add_argument('--pid-file', metavar='path_to_pid_file', default=None, help='Path to PID file useful for running as daemon') parser.add_argument( '--log-rotate-days', type=int, default=None, help='Enables daily log rotation and keeps up to the specified days') parser.add_argument( '--install-osx', action='store_true', help='Installs as a service on OS X and loads on boot.') parser.add_argument('--uninstall-osx', action='store_true', help='Uninstalls from OS X.') parser.add_argument('--restart-osx', action='store_true', help='Restarts on OS X.') if os.name != "nt": parser.add_argument('--daemon', action='store_true', help='Run Home Assistant as daemon') arguments = parser.parse_args() if os.name == "nt": arguments.daemon = False return arguments
def __init__(self, hass, config): from gmusicapi import Mobileclient # https://github.com/simon-weber/gmusicapi/issues/424 class GMusic(Mobileclient): def login(self, username, password, device_id, authtoken=None): if authtoken: self.android_id = device_id self.session._authtoken = authtoken self.session.is_authenticated = True try: # Send a test request to ensure our authtoken is still valide and working self.get_registered_devices() return True except: # Faild with the test-request so we set "is_authenticated=False" # and go through the login-process again to get a new "authtoken" self.session.is_authenticated = False if device_id: if super(GMusic, self).login(username, password, device_id): return True # Prevent further execution in case we failed with the login-process raise SystemExit self.hass = hass authtoken_path = get_default_config_dir() + "gmusic_authtoken" if os.path.isfile(authtoken_path): with open(authtoken_path, 'rb') as handle: authtoken = pickle.load(handle) else: authtoken = None self._api = GMusic() logged_in = self._api.login(config.get('user'), config.get('password'), config.get('device_id'), authtoken) if not logged_in: _LOGGER.error("Failed to log in, check http://unofficial-google-music-api.readthedocs.io/en/latest/reference/mobileclient.html#gmusicapi.clients.Mobileclient.login") return False with open(authtoken_path, 'wb') as f: pickle.dump(self._api.session._authtoken, f) self._playlist = "input_select." + config.get("playlist","") self._media_player = "input_select." + config.get("media_player","") self._entity_ids = [] self._playing = False self._playlists = [] self._tracks = [] self._next_track_no = 0 self._playlist_to_index = {} self._unsub_tracker = None self._name = "Google music" track_time_change(hass, self._update_playlist, hour=[15, 6], minute=46, second=46) hass.bus.listen_once(EVENT_HOMEASSISTANT_START, self._update_playlist)
def _handle_get_local(handler, path_match, data): """ Returns a static file from the hass.config.path/www for the frontend. """ req_file = util.sanitize_path(path_match.group('file')) path = os.path.join(get_default_config_dir(), 'www', req_file) if not os.path.isfile(path): return False handler.write_file(path)
def delete_token(self): try: persist_token = os.path.join(get_default_config_dir(), self._token_persist_filename) try: os.remove(persist_token) except FileNotFoundError: os.remove(self._token_persist_filename) except IOError: _LOGGER.debug("error deleting token...") return ERROR_VALUE
async def get_token_from_file(self): try: persist_token = os.path.join(get_default_config_dir(), self._token_persist_filename) if os.path.exists(persist_token): if self.load_token(): _LOGGER.debug( "token successfully loaded from file: {}".format( persist_token)) except FileExistsError: _LOGGER.debug("error loading token {}".format(persist_token)) _LOGGER.debug("{}".format(traceback.print_exc()))
def __init__(self): self.latitude = None self.longitude = None self.temperature_unit = None self.location_name = None self.time_zone = None # List of loaded components self.components = [] # Remote.API object pointing at local API self.api = None # Directory that holds the configuration self.config_dir = get_default_config_dir()
def get_arguments(): """ Get parsed passed in arguments. """ parser = argparse.ArgumentParser( description="Home Assistant: Observe, Control, Automate.") parser.add_argument('--version', action='version', version=__version__) parser.add_argument( '-c', '--config', metavar='path_to_config_dir', default=config_util.get_default_config_dir(), help="Directory that contains the Home Assistant configuration") parser.add_argument( '--demo-mode', action='store_true', help='Start Home Assistant in demo mode') parser.add_argument( '--open-ui', action='store_true', help='Open the webinterface in a browser') parser.add_argument( '--skip-pip', action='store_true', help='Skips pip install of required packages on startup') parser.add_argument( '-v', '--verbose', action='store_true', help="Enable verbose logging to file.") parser.add_argument( '--pid-file', metavar='path_to_pid_file', default=None, help='Path to PID file useful for running as daemon') parser.add_argument( '--log-rotate-days', type=int, default=None, help='Enables daily log rotation and keeps up to the specified days') if os.name != "nt": parser.add_argument( '--daemon', action='store_true', help='Run Home Assistant as daemon') arguments = parser.parse_args() if os.name == "nt": arguments.daemon = False return arguments
def __init__(self): self.latitude = None self.longitude = None self.temperature_unit = None self.location_name = None self.time_zone = None # If True, pip install is skipped for requirements on startup self.skip_pip = False # List of loaded components self.components = [] # Remote.API object pointing at local API self.api = None # Directory that holds the configuration self.config_dir = get_default_config_dir()
def get_arguments(): """ Get parsed passed in arguments. """ parser = argparse.ArgumentParser( description="Home Assistant: Observe, Control, Automate.") parser.add_argument( '-c', '--config', metavar='path_to_config_dir', default=config_util.get_default_config_dir(), help="Directory that contains the Home Assistant configuration") parser.add_argument( '--demo-mode', action='store_true', help='Start Home Assistant in demo mode') parser.add_argument( '--open-ui', action='store_true', help='Open the webinterface in a browser') return parser.parse_args()
def save_token(self): try: persist_token = os.path.join(get_default_config_dir(), self._token_persist_filename) dict_token = {"_token": self._token.token, "_valid_until": self._token.vaild_until} try: with open(persist_token, "w") as write_file: json.dump(dict_token, write_file) except FileNotFoundError: with open(self._token_persist_filename, "w") as write_file: json.dump(dict_token, write_file) _LOGGER.debug("save_token successfully...") return True except IOError: _LOGGER.debug("error save_token...") _LOGGER.debug("tokenpath: {}".format(persist_token)) return ERROR_VALUE
def run(args): """Handle Home Assistant auth provider script.""" parser = argparse.ArgumentParser( description="Manage Home Assistant users") parser.add_argument( '--script', choices=['auth']) parser.add_argument( '-c', '--config', default=get_default_config_dir(), help="Directory that contains the Home Assistant configuration") subparsers = parser.add_subparsers(dest='func') subparsers.required = True parser_list = subparsers.add_parser('list') parser_list.set_defaults(func=list_users) parser_add = subparsers.add_parser('add') parser_add.add_argument('username', type=str) parser_add.add_argument('password', type=str) parser_add.set_defaults(func=add_user) parser_validate_login = subparsers.add_parser('validate') parser_validate_login.add_argument('username', type=str) parser_validate_login.add_argument('password', type=str) parser_validate_login.set_defaults(func=validate_login) parser_change_pw = subparsers.add_parser('change_password') parser_change_pw.add_argument('username', type=str) parser_change_pw.add_argument('new_password', type=str) parser_change_pw.set_defaults(func=change_password) args = parser.parse_args(args) loop = asyncio.get_event_loop() hass = HomeAssistant(loop=loop) loop.run_until_complete(run_command(hass, args)) # Triggers save on used storage helpers with delay (core auth) logging.getLogger('homeassistant.core').setLevel(logging.WARNING) loop.run_until_complete(hass.async_stop())
def run(args): """Handle Home Assistant auth provider script.""" parser = argparse.ArgumentParser( description=("Manage Home Assistant users")) parser.add_argument('--script', choices=['auth']) parser.add_argument( '-c', '--config', default=get_default_config_dir(), help="Directory that contains the Home Assistant configuration") subparsers = parser.add_subparsers(dest='func') subparsers.required = True parser_list = subparsers.add_parser('list') parser_list.set_defaults(func=list_users) parser_add = subparsers.add_parser('add') parser_add.add_argument('username', type=str) parser_add.add_argument('password', type=str) parser_add.set_defaults(func=add_user) parser_validate_login = subparsers.add_parser('validate') parser_validate_login.add_argument('username', type=str) parser_validate_login.add_argument('password', type=str) parser_validate_login.set_defaults(func=validate_login) parser_change_pw = subparsers.add_parser('change_password') parser_change_pw.add_argument('username', type=str) parser_change_pw.add_argument('new_password', type=str) parser_change_pw.set_defaults(func=change_password) args = parser.parse_args(args) loop = asyncio.get_event_loop() hass = HomeAssistant(loop=loop) hass.config.config_dir = os.path.join(os.getcwd(), args.config) data = hass_auth.Data(hass) loop.run_until_complete(data.async_load()) loop.run_until_complete(args.func(data, args))
def run(args): """Handle Home Assistant auth provider script.""" parser = argparse.ArgumentParser( description=("Manage Home Assistant users")) parser.add_argument( '--script', choices=['auth']) parser.add_argument( '-c', '--config', default=get_default_config_dir(), help="Directory that contains the Home Assistant configuration") subparsers = parser.add_subparsers(dest='func') subparsers.required = True parser_list = subparsers.add_parser('list') parser_list.set_defaults(func=list_users) parser_add = subparsers.add_parser('add') parser_add.add_argument('username', type=str) parser_add.add_argument('password', type=str) parser_add.set_defaults(func=add_user) parser_validate_login = subparsers.add_parser('validate') parser_validate_login.add_argument('username', type=str) parser_validate_login.add_argument('password', type=str) parser_validate_login.set_defaults(func=validate_login) parser_change_pw = subparsers.add_parser('change_password') parser_change_pw.add_argument('username', type=str) parser_change_pw.add_argument('new_password', type=str) parser_change_pw.set_defaults(func=change_password) args = parser.parse_args(args) loop = asyncio.get_event_loop() hass = HomeAssistant(loop=loop) hass.config.config_dir = os.path.join(os.getcwd(), args.config) data = hass_auth.Data(hass) loop.run_until_complete(data.async_load()) loop.run_until_complete(args.func(data, args))
def get_arguments() -> argparse.Namespace: """Get parsed passed in arguments.""" import homeassistant.config as config_util parser = argparse.ArgumentParser( description="Home Assistant: Observe, Control, Automate.") parser.add_argument("--version", action="version", version=__version__) parser.add_argument( "-c", "--config", metavar="path_to_config_dir", default=config_util.get_default_config_dir(), help="Directory that contains the Home Assistant configuration", ) parser.add_argument("--demo-mode", action="store_true", help="Start Home Assistant in demo mode") parser.add_argument("--debug", action="store_true", help="Start Home Assistant in debug mode") parser.add_argument("--open-ui", action="store_true", help="Open the webinterface in a browser") parser.add_argument( "--skip-pip", action="store_true", help="Skips pip install of required packages on startup", ) parser.add_argument("-v", "--verbose", action="store_true", help="Enable verbose logging to file.") parser.add_argument( "--pid-file", metavar="path_to_pid_file", default=None, help="Path to PID file useful for running as daemon", ) parser.add_argument( "--log-rotate-days", type=int, default=None, help="Enables daily log rotation and keeps up to the specified days", ) parser.add_argument( "--log-file", type=str, default=None, help="Log file to write to. If not set, CONFIG/home-assistant.log " "is used", ) parser.add_argument("--log-no-color", action="store_true", help="Disable color logs") parser.add_argument( "--runner", action="store_true", help=f"On restart exit with code {RESTART_EXIT_CODE}", ) parser.add_argument("--script", nargs=argparse.REMAINDER, help="Run one of the embedded scripts") if os.name == "posix": parser.add_argument("--daemon", action="store_true", help="Run Home Assistant as daemon") arguments = parser.parse_args() if os.name != "posix" or arguments.debug or arguments.runner: setattr(arguments, "daemon", False) return arguments
CONF_MAX_RESULTS = "max_results" CONF_CAL_ID = "cal_id" CONF_ENTITIES = "entities" CONF_HAS_ATTACHMENT = "has_attachment" CONF_HOURS_BACKWARD_TO_GET = "start_offset" CONF_HOURS_FORWARD_TO_GET = "end_offset" CONF_IS_UNREAD = "is_unread" CONF_MAIL_FOLDER = "folder" CONF_MAIL_FROM = "from" CONF_MAX_ITEMS = "max_items" CONF_QUERY_SENSORS = "query_sensors" CONF_SUBJECT_CONTAINS = "subject_contains" CONF_SUBJECT_IS = "subject_is" CONF_TRACK_NEW = "track_new_calendar" CONFIG_BASE_DIR = get_default_config_dir() CONFIGURATOR_DESCRIPTION = ( "To link your O365 account, click the link, login, and authorize:") CONFIGURATOR_LINK_NAME = "Link O365 account" CONFIGURATOR_SUBMIT_CAPTION = "I authorized successfully" DATETIME_FORMAT = "%Y-%m-%dT%H:%M:%S%z" DEFAULT_CACHE_PATH = ".O365-token-cache" DEFAULT_HOURS_BACKWARD_TO_GET = 0 DEFAULT_HOURS_FORWARD_TO_GET = 24 DEFAULT_NAME = "O365" DOMAIN = "o365" ICON = "mdi:office" MIN_TIME_BETWEEN_UPDATES = timedelta(minutes=15) DEFAULT_OFFSET = "!!" SCOPE = [ "offline_access",
def run(script_args: List) -> int: """Handle check config commandline script.""" parser = argparse.ArgumentParser( description="Check Home Assistant configuration.") parser.add_argument("--script", choices=["check_config"]) parser.add_argument( "-c", "--config", default=get_default_config_dir(), help="Directory that contains the Home Assistant configuration", ) parser.add_argument( "-i", "--info", nargs="?", default=None, const="all", help="Show a portion of the config", ) parser.add_argument("-f", "--files", action="store_true", help="Show used configuration files") parser.add_argument("-s", "--secrets", action="store_true", help="Show secret information") args, unknown = parser.parse_known_args() if unknown: print(color("red", "Unknown arguments:", ", ".join(unknown))) config_dir = os.path.join(os.getcwd(), args.config) print(color("bold", "Testing configuration at", config_dir)) res = check(config_dir, args.secrets) domain_info: List[str] = [] if args.info: domain_info = args.info.split(",") if args.files: print(color(C_HEAD, "yaml files"), "(used /", color("red", "not used") + ")") deps = os.path.join(config_dir, "deps") yaml_files = [ f for f in glob(os.path.join(config_dir, "**/*.yaml"), recursive=True) if not f.startswith(deps) ] for yfn in sorted(yaml_files): the_color = "" if yfn in res["yaml_files"] else "red" print(color(the_color, "-", yfn)) if res["except"]: print(color("bold_white", "Failed config")) for domain, config in res["except"].items(): domain_info.append(domain) print(" ", color("bold_red", domain + ":"), color("red", "", reset="red")) dump_dict(config, reset="red") print(color("reset")) if domain_info: if "all" in domain_info: print(color("bold_white", "Successful config (all)")) for domain, config in res["components"].items(): print(" ", color(C_HEAD, domain + ":")) dump_dict(config) else: print(color("bold_white", "Successful config (partial)")) for domain in domain_info: if domain == ERROR_STR: continue print(" ", color(C_HEAD, domain + ":")) dump_dict(res["components"].get(domain)) if args.secrets: flatsecret: Dict[str, str] = {} for sfn, sdict in res["secret_cache"].items(): sss = [] for skey in sdict: if skey in flatsecret: _LOGGER.error("Duplicated secrets in files %s and %s", flatsecret[skey], sfn) flatsecret[skey] = sfn sss.append( color("green", skey) if skey in res["secrets"] else skey) print(color(C_HEAD, "Secrets from", sfn + ":"), ", ".join(sss)) print(color(C_HEAD, "Used Secrets:")) for skey, sval in res["secrets"].items(): if sval is None: print(" -", skey + ":", color("red", "not found")) continue print( " -", skey + ":", sval, color("cyan", "[from:", flatsecret.get(skey, "keyring") + "]"), ) return len(res["except"])
def run(script_args: List) -> int: """Handle ensure config commandline script.""" parser = argparse.ArgumentParser( description=("Check Home Assistant configuration.")) parser.add_argument( '--script', choices=['check_config']) parser.add_argument( '-c', '--config', default=config_util.get_default_config_dir(), help="Directory that contains the Home Assistant configuration") parser.add_argument( '-i', '--info', default=None, help="Show a portion of the config") parser.add_argument( '-f', '--files', action='store_true', help="Show used configuration files") parser.add_argument( '-s', '--secrets', action='store_true', help="Show secret information") args = parser.parse_args() config_dir = os.path.join(os.getcwd(), args.config) config_path = os.path.join(config_dir, 'configuration.yaml') if not os.path.isfile(config_path): print('Config does not exist:', config_path) return 1 print(color('bold', "Testing configuration at", config_dir)) domain_info = [] if args.info: domain_info = args.info.split(',') res = check(config_path) if args.files: print(color(C_HEAD, 'yaml files'), '(used /', color('red', 'not used') + ')') # Python 3.5 gets a recursive, but not in 3.4 for yfn in sorted(glob(os.path.join(config_dir, '*.yaml')) + glob(os.path.join(config_dir, '*/*.yaml'))): the_color = '' if yfn in res['yaml_files'] else 'red' print(color(the_color, '-', yfn)) if len(res['except']) > 0: print(color('bold_white', 'Failed config')) for domain, config in res['except'].items(): domain_info.append(domain) print(' ', color('bold_red', domain + ':'), color('red', '', reset='red')) dump_dict(config, reset='red') print(color('reset')) if domain_info: if 'all' in domain_info: print(color('bold_white', 'Successful config (all)')) for domain, config in res['components'].items(): print(' ', color(C_HEAD, domain + ':')) dump_dict(config) else: print(color('bold_white', 'Successful config (partial)')) for domain in domain_info: if domain == ERROR_STR: continue print(' ', color(C_HEAD, domain + ':')) dump_dict(res['components'].get(domain, None)) if args.secrets: flatsecret = {} for sfn, sdict in res['secret_cache'].items(): sss = [] for skey, sval in sdict.items(): if skey in flatsecret: _LOGGER.error('Duplicated secrets in files %s and %s', flatsecret[skey], sfn) flatsecret[skey] = sfn sss.append(color('green', skey) if skey in res['secrets'] else skey) print(color(C_HEAD, 'Secrets from', sfn + ':'), ', '.join(sss)) print(color(C_HEAD, 'Used Secrets:')) for skey, sval in res['secrets'].items(): print(' -', skey + ':', sval, color('cyan', '[from:', flatsecret .get(skey, 'keyring') + ']')) return 0
_RESOURCECURRENT = 'https://api.weather.com/v2/pws/observations/current?stationId={}&format=json&units={}&apiKey={}' _RESOURCEFORECAST = 'https://api.weather.com/v3/wx/forecast/daily/5day?geocode={},{}&units={}&{}&format=json&apiKey={}' _LOGGER = logging.getLogger(__name__) CONF_ATTRIBUTION = "Data provided by the WUnderground weather service" CONF_PWS_ID = 'pws_id' CONF_LANG = 'lang' LENGTH_MILLIMETERS = 'mm' LENGTH_METERS = 'm' DEFAULT_LANG = 'en-US' MIN_TIME_BETWEEN_UPDATES = timedelta(minutes=5) conf_file = config.get_default_config_dir() + '/configuration.yaml' load_config = config.load_yaml_config_file( '/home/homeassistant/configuration.yaml') try: UNIT_SYSTEM = load_config['homeassistant']['unit_system'] except KeyError as err: UNIT_SYSTEM = "metric" if UNIT_SYSTEM == 'imperial': TEMPUNIT = TEMP_FAHRENHEIT LENGTHUNIT = LENGTH_INCHES ALTITUDEUNIT = LENGTH_FEET SPEEDUNIT = 'mph' PRESSUREUNIT = 'inHg' else:
def run(script_args: List) -> int: """Handle ensure config commandline script.""" parser = argparse.ArgumentParser( description="Check Home Assistant configuration.") parser.add_argument('--script', choices=['check_config']) parser.add_argument( '-c', '--config', default=get_default_config_dir(), help="Directory that contains the Home Assistant configuration") parser.add_argument('-i', '--info', nargs='?', default=None, const='all', help="Show a portion of the config") parser.add_argument('-f', '--files', action='store_true', help="Show used configuration files") parser.add_argument('-s', '--secrets', action='store_true', help="Show secret information") args, unknown = parser.parse_known_args() if unknown: print(color('red', "Unknown arguments:", ', '.join(unknown))) config_dir = os.path.join(os.getcwd(), args.config) print(color('bold', "Testing configuration at", config_dir)) res = check(config_dir, args.secrets) domain_info = [] if args.info: domain_info = args.info.split(',') if args.files: print(color(C_HEAD, 'yaml files'), '(used /', color('red', 'not used') + ')') deps = os.path.join(config_dir, 'deps') yaml_files = [ f for f in glob(os.path.join(config_dir, '**/*.yaml'), recursive=True) if not f.startswith(deps) ] for yfn in sorted(yaml_files): the_color = '' if yfn in res['yaml_files'] else 'red' print(color(the_color, '-', yfn)) if res['except']: print(color('bold_white', 'Failed config')) for domain, config in res['except'].items(): domain_info.append(domain) print(' ', color('bold_red', domain + ':'), color('red', '', reset='red')) dump_dict(config, reset='red') print(color('reset')) if domain_info: if 'all' in domain_info: print(color('bold_white', 'Successful config (all)')) for domain, config in res['components'].items(): print(' ', color(C_HEAD, domain + ':')) dump_dict(config) else: print(color('bold_white', 'Successful config (partial)')) for domain in domain_info: if domain == ERROR_STR: continue print(' ', color(C_HEAD, domain + ':')) dump_dict(res['components'].get(domain, None)) if args.secrets: flatsecret = {} for sfn, sdict in res['secret_cache'].items(): sss = [] for skey in sdict: if skey in flatsecret: _LOGGER.error('Duplicated secrets in files %s and %s', flatsecret[skey], sfn) flatsecret[skey] = sfn sss.append( color('green', skey) if skey in res['secrets'] else skey) print(color(C_HEAD, 'Secrets from', sfn + ':'), ', '.join(sss)) print(color(C_HEAD, 'Used Secrets:')) for skey, sval in res['secrets'].items(): if sval is None: print(' -', skey + ':', color('red', "not found")) continue print( ' -', skey + ':', sval, color('cyan', '[from:', flatsecret.get(skey, 'keyring') + ']')) return len(res['except'])
def run(script_args: List) -> int: """Handle ensure config commandline script.""" parser = argparse.ArgumentParser( description="Check Home Assistant configuration.") parser.add_argument( '--script', choices=['check_config']) parser.add_argument( '-c', '--config', default=get_default_config_dir(), help="Directory that contains the Home Assistant configuration") parser.add_argument( '-i', '--info', nargs='?', default=None, const='all', help="Show a portion of the config") parser.add_argument( '-f', '--files', action='store_true', help="Show used configuration files") parser.add_argument( '-s', '--secrets', action='store_true', help="Show secret information") args, unknown = parser.parse_known_args() if unknown: print(color('red', "Unknown arguments:", ', '.join(unknown))) config_dir = os.path.join(os.getcwd(), args.config) print(color('bold', "Testing configuration at", config_dir)) res = check(config_dir, args.secrets) domain_info = [] if args.info: domain_info = args.info.split(',') if args.files: print(color(C_HEAD, 'yaml files'), '(used /', color('red', 'not used') + ')') deps = os.path.join(config_dir, 'deps') yaml_files = [f for f in glob(os.path.join(config_dir, '**/*.yaml'), recursive=True) if not f.startswith(deps)] for yfn in sorted(yaml_files): the_color = '' if yfn in res['yaml_files'] else 'red' print(color(the_color, '-', yfn)) if res['except']: print(color('bold_white', 'Failed config')) for domain, config in res['except'].items(): domain_info.append(domain) print(' ', color('bold_red', domain + ':'), color('red', '', reset='red')) dump_dict(config, reset='red') print(color('reset')) if domain_info: if 'all' in domain_info: print(color('bold_white', 'Successful config (all)')) for domain, config in res['components'].items(): print(' ', color(C_HEAD, domain + ':')) dump_dict(config) else: print(color('bold_white', 'Successful config (partial)')) for domain in domain_info: if domain == ERROR_STR: continue print(' ', color(C_HEAD, domain + ':')) dump_dict(res['components'].get(domain, None)) if args.secrets: flatsecret = {} for sfn, sdict in res['secret_cache'].items(): sss = [] for skey in sdict: if skey in flatsecret: _LOGGER.error('Duplicated secrets in files %s and %s', flatsecret[skey], sfn) flatsecret[skey] = sfn sss.append(color('green', skey) if skey in res['secrets'] else skey) print(color(C_HEAD, 'Secrets from', sfn + ':'), ', '.join(sss)) print(color(C_HEAD, 'Used Secrets:')) for skey, sval in res['secrets'].items(): if sval is None: print(' -', skey + ':', color('red', "not found")) continue print(' -', skey + ':', sval, color('cyan', '[from:', flatsecret .get(skey, 'keyring') + ']')) return len(res['except'])
def run(args): """The actual script body.""" # pylint: disable=too-many-locals,invalid-name,too-many-statements parser = argparse.ArgumentParser( description="Migrate legacy DB to SQLAlchemy format.") parser.add_argument( '-c', '--config', metavar='path_to_config_dir', default=config_util.get_default_config_dir(), help="Directory that contains the Home Assistant configuration") parser.add_argument( '-a', '--append', action='store_true', default=False, help="Append to existing new format SQLite database") parser.add_argument( '--uri', type=str, help="Connect to URI and import (implies --append)" "eg: mysql://localhost/homeassistant") parser.add_argument( '--script', choices=['db_migrator']) args = parser.parse_args() config_dir = os.path.join(os.getcwd(), args.config) # Test if configuration directory exists if not os.path.isdir(config_dir): if config_dir != config_util.get_default_config_dir(): print(('Fatal Error: Specified configuration directory does ' 'not exist {} ').format(config_dir)) return 1 else: config_dir = config_util.get_default_config_dir() src_db = '{}/home-assistant.db'.format(config_dir) dst_db = '{}/home-assistant_v2.db'.format(config_dir) if not os.path.exists(src_db): print("Fatal Error: Old format database '{}' does not exist".format( src_db)) return 1 if not args.uri and (os.path.exists(dst_db) and not args.append): print("Fatal Error: New format database '{}' exists already - " "Remove it or use --append".format(dst_db)) print("Note: --append must maintain an ID mapping and is much slower" "and requires sufficient memory to track all event IDs") return 1 conn = sqlite3.connect(src_db) uri = args.uri or "sqlite:///{}".format(dst_db) engine = create_engine(uri, echo=False) models.Base.metadata.create_all(engine) session_factory = sessionmaker(bind=engine) session = session_factory() append = args.append or args.uri c = conn.cursor() c.execute("SELECT count(*) FROM recorder_runs") num_rows = c.fetchone()[0] print("Converting {} recorder_runs".format(num_rows)) c.close() c = conn.cursor() n = 0 for row in c.execute("SELECT * FROM recorder_runs"): n += 1 session.add(models.RecorderRuns( start=ts_to_dt(row[1]), end=ts_to_dt(row[2]), closed_incorrect=row[3], created=ts_to_dt(row[4]) )) if n % 1000 == 0: session.commit() print_progress(n, num_rows) print_progress(n, num_rows) session.commit() c.close() c = conn.cursor() c.execute("SELECT count(*) FROM events") num_rows = c.fetchone()[0] print("Converting {} events".format(num_rows)) c.close() id_mapping = {} c = conn.cursor() n = 0 for row in c.execute("SELECT * FROM events"): n += 1 o = models.Events( event_type=row[1], event_data=row[2], origin=row[3], created=ts_to_dt(row[4]), time_fired=ts_to_dt(row[5]), ) session.add(o) if append: session.flush() id_mapping[row[0]] = o.event_id if n % 1000 == 0: session.commit() print_progress(n, num_rows) print_progress(n, num_rows) session.commit() c.close() c = conn.cursor() c.execute("SELECT count(*) FROM states") num_rows = c.fetchone()[0] print("Converting {} states".format(num_rows)) c.close() c = conn.cursor() n = 0 for row in c.execute("SELECT * FROM states"): n += 1 session.add(models.States( entity_id=row[1], state=row[2], attributes=row[3], last_changed=ts_to_dt(row[4]), last_updated=ts_to_dt(row[5]), event_id=id_mapping.get(row[6], row[6]), domain=row[7] )) if n % 1000 == 0: session.commit() print_progress(n, num_rows) print_progress(n, num_rows) session.commit() c.close() return 0
def run(script_args: List) -> int: """The actual script body.""" # pylint: disable=invalid-name from sqlalchemy import create_engine from sqlalchemy.orm import sessionmaker from homeassistant.components.recorder import models parser = argparse.ArgumentParser( description="Migrate legacy DB to SQLAlchemy format.") parser.add_argument( '-c', '--config', metavar='path_to_config_dir', default=config_util.get_default_config_dir(), help="Directory that contains the Home Assistant configuration") parser.add_argument( '-a', '--append', action='store_true', default=False, help="Append to existing new format SQLite database") parser.add_argument( '--uri', type=str, help="Connect to URI and import (implies --append)" "eg: mysql://localhost/homeassistant") parser.add_argument( '--script', choices=['db_migrator']) args = parser.parse_args() config_dir = os.path.join(os.getcwd(), args.config) # type: str # Test if configuration directory exists if not os.path.isdir(config_dir): if config_dir != config_util.get_default_config_dir(): print((('Fatal Error: Specified configuration directory does ' 'not exist {} ').format(config_dir))) return 1 src_db = '{}/home-assistant.db'.format(config_dir) dst_db = '{}/home-assistant_v2.db'.format(config_dir) if not os.path.exists(src_db): print(("Fatal Error: Old format database '{}' does not exist".format( src_db))) return 1 if not args.uri and (os.path.exists(dst_db) and not args.append): print(("Fatal Error: New format database '{}' exists already - " "Remove it or use --append".format(dst_db))) print("Note: --append must maintain an ID mapping and is much slower" "and requires sufficient memory to track all event IDs") return 1 conn = sqlite3.connect(src_db) uri = args.uri or "sqlite:///{}".format(dst_db) engine = create_engine(uri, echo=False) models.Base.metadata.create_all(engine) session_factory = sessionmaker(bind=engine) session = session_factory() append = args.append or args.uri c = conn.cursor() c.execute("SELECT count(*) FROM recorder_runs") num_rows = c.fetchone()[0] print(("Converting {} recorder_runs".format(num_rows))) c.close() c = conn.cursor() n = 0 for row in c.execute("SELECT * FROM recorder_runs"): # type: ignore n += 1 session.add(models.RecorderRuns( start=ts_to_dt(row[1]), end=ts_to_dt(row[2]), closed_incorrect=row[3], created=ts_to_dt(row[4]) )) if n % 1000 == 0: session.commit() print_progress(n, num_rows) print_progress(n, num_rows) session.commit() c.close() c = conn.cursor() c.execute("SELECT count(*) FROM events") num_rows = c.fetchone()[0] print(("Converting {} events".format(num_rows))) c.close() id_mapping = {} c = conn.cursor() n = 0 for row in c.execute("SELECT * FROM events"): # type: ignore n += 1 o = models.Events( event_type=row[1], event_data=row[2], origin=row[3], created=ts_to_dt(row[4]), time_fired=ts_to_dt(row[5]), ) session.add(o) if append: session.flush() id_mapping[row[0]] = o.event_id if n % 1000 == 0: session.commit() print_progress(n, num_rows) print_progress(n, num_rows) session.commit() c.close() c = conn.cursor() c.execute("SELECT count(*) FROM states") num_rows = c.fetchone()[0] print(("Converting {} states".format(num_rows))) c.close() c = conn.cursor() n = 0 for row in c.execute("SELECT * FROM states"): # type: ignore n += 1 session.add(models.States( entity_id=row[1], state=row[2], attributes=row[3], last_changed=ts_to_dt(row[4]), last_updated=ts_to_dt(row[5]), event_id=id_mapping.get(row[6], row[6]), domain=row[7] )) if n % 1000 == 0: session.commit() print_progress(n, num_rows) print_progress(n, num_rows) session.commit() c.close() return 0
def run(script_args: List) -> int: """Handle ensure config commandline script.""" parser = argparse.ArgumentParser( description=("Check Home Assistant configuration.")) parser.add_argument('--script', choices=['check_config']) parser.add_argument( '-c', '--config', default=config_util.get_default_config_dir(), help="Directory that contains the Home Assistant configuration") parser.add_argument('-i', '--info', default=None, help="Show a portion of the config") parser.add_argument('-f', '--files', action='store_true', help="Show used configuration files") parser.add_argument('-s', '--secrets', action='store_true', help="Show secret information") args = parser.parse_args() config_dir = os.path.join(os.getcwd(), args.config) config_path = os.path.join(config_dir, 'configuration.yaml') if not os.path.isfile(config_path): print('Config does not exist:', config_path) return 1 print(color('bold', "Testing configuration at", config_dir)) domain_info = [] if args.info: domain_info = args.info.split(',') res = check(config_path) if args.files: print(color(C_HEAD, 'yaml files'), '(used /', color('red', 'not used') + ')') # Python 3.5 gets a recursive, but not in 3.4 for yfn in sorted( glob(os.path.join(config_dir, '*.yaml')) + glob(os.path.join(config_dir, '*/*.yaml'))): the_color = '' if yfn in res['yaml_files'] else 'red' print(color(the_color, '-', yfn)) if len(res['except']) > 0: print(color('bold_white', 'Failed config')) for domain, config in res['except'].items(): domain_info.append(domain) print(' ', color('bold_red', domain + ':'), color('red', '', reset='red')) dump_dict(config, reset='red') print(color('reset')) if domain_info: if 'all' in domain_info: print(color('bold_white', 'Successful config (all)')) for domain, config in res['components'].items(): print(' ', color(C_HEAD, domain + ':')) dump_dict(config) else: print(color('bold_white', 'Successful config (partial)')) for domain in domain_info: if domain == ERROR_STR: continue print(' ', color(C_HEAD, domain + ':')) dump_dict(res['components'].get(domain, None)) if args.secrets: flatsecret = {} for sfn, sdict in res['secret_cache'].items(): sss = [] for skey, sval in sdict.items(): if skey in flatsecret: _LOGGER.error('Duplicated secrets in files %s and %s', flatsecret[skey], sfn) flatsecret[skey] = sfn sss.append( color('green', skey) if skey in res['secrets'] else skey) print(color(C_HEAD, 'Secrets from', sfn + ':'), ', '.join(sss)) print(color(C_HEAD, 'Used Secrets:')) for skey, sval in res['secrets'].items(): print( ' -', skey + ':', sval, color('cyan', '[from:', flatsecret.get(skey, 'keyring') + ']')) return 0
def run(script_args: List) -> int: """Run the actual script.""" from sqlalchemy import create_engine from sqlalchemy import func from sqlalchemy.orm import sessionmaker from influxdb import InfluxDBClient from homeassistant.components.recorder import models from homeassistant.helpers import state as state_helper from homeassistant.core import State from homeassistant.core import HomeAssistantError parser = argparse.ArgumentParser(description="import data to influxDB.") parser.add_argument( '-c', '--config', metavar='path_to_config_dir', default=config_util.get_default_config_dir(), help="Directory that contains the Home Assistant configuration") parser.add_argument( '--uri', type=str, help="Connect to URI and import (if other than default sqlite) " "eg: mysql://localhost/homeassistant") parser.add_argument('-d', '--dbname', metavar='dbname', required=True, help="InfluxDB database name") parser.add_argument('-H', '--host', metavar='host', default='127.0.0.1', help="InfluxDB host address") parser.add_argument('-P', '--port', metavar='port', default=8086, help="InfluxDB host port") parser.add_argument('-u', '--username', metavar='username', default='root', help="InfluxDB username") parser.add_argument('-p', '--password', metavar='password', default='root', help="InfluxDB password") parser.add_argument('-s', '--step', metavar='step', default=1000, help="How many points to import at the same time") parser.add_argument( '-t', '--tags', metavar='tags', default="", help="Comma separated list of tags (key:value) for all points") parser.add_argument('-D', '--default-measurement', metavar='default_measurement', default="", help="Store all your points in the same measurement") parser.add_argument('-o', '--override-measurement', metavar='override_measurement', default="", help="Store all your points in the same measurement") parser.add_argument('-e', '--exclude_entities', metavar='exclude_entities', default="", help="Comma separated list of excluded entities") parser.add_argument('-E', '--exclude_domains', metavar='exclude_domains', default="", help="Comma separated list of excluded domains") parser.add_argument( "-S", "--simulate", default=False, action="store_true", help=("Do not write points but simulate preprocessing and print " "statistics")) parser.add_argument('--script', choices=['influxdb_import']) args = parser.parse_args() simulate = args.simulate client = None if not simulate: client = InfluxDBClient(args.host, args.port, args.username, args.password) client.switch_database(args.dbname) config_dir = os.path.join(os.getcwd(), args.config) # type: str # Test if configuration directory exists if not os.path.isdir(config_dir): if config_dir != config_util.get_default_config_dir(): print(('Fatal Error: Specified configuration directory does ' 'not exist {} ').format(config_dir)) return 1 src_db = '{}/home-assistant_v2.db'.format(config_dir) if not os.path.exists(src_db) and not args.uri: print("Fatal Error: Database '{}' does not exist " "and no URI given".format(src_db)) return 1 uri = args.uri or 'sqlite:///{}'.format(src_db) engine = create_engine(uri, echo=False) session_factory = sessionmaker(bind=engine) session = session_factory() step = int(args.step) step_start = 0 tags = {} if args.tags: tags.update(dict(elem.split(':') for elem in args.tags.split(','))) excl_entities = args.exclude_entities.split(',') excl_domains = args.exclude_domains.split(',') override_measurement = args.override_measurement default_measurement = args.default_measurement # pylint: disable=assignment-from-no-return query = session.query(func.count(models.Events.event_type)).filter( models.Events.event_type == 'state_changed') total_events = query.scalar() prefix_format = '{} of {}' points = [] invalid_points = [] count = 0 from collections import defaultdict entities = defaultdict(int) print_progress(0, total_events, prefix_format.format(0, total_events)) while True: step_stop = step_start + step if step_start > total_events: print_progress(total_events, total_events, prefix_format.format(total_events, total_events)) break query = session.query(models.Events).filter( models.Events.event_type == 'state_changed').order_by( models.Events.time_fired).slice(step_start, step_stop) for event in query: event_data = json.loads(event.event_data) if not ('entity_id' in event_data) or ( excl_entities and event_data['entity_id'] in excl_entities ) or (excl_domains and event_data['entity_id'].split('.')[0] in excl_domains): session.expunge(event) continue try: state = State.from_dict(event_data.get('new_state')) except HomeAssistantError: invalid_points.append(event_data) if not state: invalid_points.append(event_data) continue try: _state = float(state_helper.state_as_number(state)) _state_key = 'value' except ValueError: _state = state.state _state_key = 'state' if override_measurement: measurement = override_measurement else: measurement = state.attributes.get('unit_of_measurement') if measurement in (None, ''): if default_measurement: measurement = default_measurement else: measurement = state.entity_id point = { 'measurement': measurement, 'tags': { 'domain': state.domain, 'entity_id': state.object_id, }, 'time': event.time_fired, 'fields': { _state_key: _state, } } for key, value in state.attributes.items(): if key != 'unit_of_measurement': # If the key is already in fields if key in point['fields']: key = key + '_' # Prevent column data errors in influxDB. # For each value we try to cast it as float # But if we can not do it we store the value # as string add "_str" postfix to the field key try: point['fields'][key] = float(value) except (ValueError, TypeError): new_key = '{}_str'.format(key) point['fields'][new_key] = str(value) entities[state.entity_id] += 1 point['tags'].update(tags) points.append(point) session.expunge(event) if points: if not simulate: client.write_points(points) count += len(points) # This prevents the progress bar from going over 100% when # the last step happens print_progress((step_start + len(points)), total_events, prefix_format.format(step_start, total_events)) else: print_progress((step_start + step), total_events, prefix_format.format(step_start, total_events)) points = [] step_start += step print("\nStatistics:") print("\n".join([ "{:6}: {}".format(v, k) for k, v in sorted(entities.items(), key=lambda x: x[1]) ])) print("\nInvalid Points: {}".format(len(invalid_points))) print("\nImport finished: {} points written".format(count)) return 0
def run(script_args: List) -> int: """Run the actual script.""" from sqlalchemy import create_engine from sqlalchemy import func from sqlalchemy.orm import sessionmaker from influxdb import InfluxDBClient from homeassistant.components.recorder import models from homeassistant.helpers import state as state_helper from homeassistant.core import State from homeassistant.core import HomeAssistantError parser = argparse.ArgumentParser( description="import data to influxDB.") parser.add_argument( '-c', '--config', metavar='path_to_config_dir', default=config_util.get_default_config_dir(), help="Directory that contains the Home Assistant configuration") parser.add_argument( '--uri', type=str, help="Connect to URI and import (if other than default sqlite) " "eg: mysql://localhost/homeassistant") parser.add_argument( '-d', '--dbname', metavar='dbname', required=True, help="InfluxDB database name") parser.add_argument( '-H', '--host', metavar='host', default='127.0.0.1', help="InfluxDB host address") parser.add_argument( '-P', '--port', metavar='port', default=8086, help="InfluxDB host port") parser.add_argument( '-u', '--username', metavar='username', default='root', help="InfluxDB username") parser.add_argument( '-p', '--password', metavar='password', default='root', help="InfluxDB password") parser.add_argument( '-s', '--step', metavar='step', default=1000, help="How many points to import at the same time") parser.add_argument( '-t', '--tags', metavar='tags', default="", help="Comma separated list of tags (key:value) for all points") parser.add_argument( '-D', '--default-measurement', metavar='default_measurement', default="", help="Store all your points in the same measurement") parser.add_argument( '-o', '--override-measurement', metavar='override_measurement', default="", help="Store all your points in the same measurement") parser.add_argument( '-e', '--exclude_entities', metavar='exclude_entities', default="", help="Comma separated list of excluded entities") parser.add_argument( '-E', '--exclude_domains', metavar='exclude_domains', default="", help="Comma separated list of excluded domains") parser.add_argument( "-S", "--simulate", default=False, action="store_true", help=("Do not write points but simulate preprocessing and print " "statistics")) parser.add_argument( '--script', choices=['influxdb_import']) args = parser.parse_args() simulate = args.simulate client = None if not simulate: client = InfluxDBClient( args.host, args.port, args.username, args.password) client.switch_database(args.dbname) config_dir = os.path.join(os.getcwd(), args.config) # type: str # Test if configuration directory exists if not os.path.isdir(config_dir): if config_dir != config_util.get_default_config_dir(): print(('Fatal Error: Specified configuration directory does ' 'not exist {} ').format(config_dir)) return 1 src_db = '{}/home-assistant_v2.db'.format(config_dir) if not os.path.exists(src_db) and not args.uri: print("Fatal Error: Database '{}' does not exist " "and no URI given".format(src_db)) return 1 uri = args.uri or 'sqlite:///{}'.format(src_db) engine = create_engine(uri, echo=False) session_factory = sessionmaker(bind=engine) session = session_factory() step = int(args.step) step_start = 0 tags = {} if args.tags: tags.update(dict(elem.split(':') for elem in args.tags.split(','))) excl_entities = args.exclude_entities.split(',') excl_domains = args.exclude_domains.split(',') override_measurement = args.override_measurement default_measurement = args.default_measurement query = session.query(func.count(models.Events.event_type)).filter( models.Events.event_type == 'state_changed') total_events = query.scalar() prefix_format = '{} of {}' points = [] invalid_points = [] count = 0 from collections import defaultdict entities = defaultdict(int) print_progress(0, total_events, prefix_format.format(0, total_events)) while True: step_stop = step_start + step if step_start > total_events: print_progress(total_events, total_events, prefix_format.format( total_events, total_events)) break query = session.query(models.Events).filter( models.Events.event_type == 'state_changed').order_by( models.Events.time_fired).slice(step_start, step_stop) for event in query: event_data = json.loads(event.event_data) if not ('entity_id' in event_data) or ( excl_entities and event_data[ 'entity_id'] in excl_entities) or ( excl_domains and event_data[ 'entity_id'].split('.')[0] in excl_domains): session.expunge(event) continue try: state = State.from_dict(event_data.get('new_state')) except HomeAssistantError: invalid_points.append(event_data) if not state: invalid_points.append(event_data) continue try: _state = float(state_helper.state_as_number(state)) _state_key = 'value' except ValueError: _state = state.state _state_key = 'state' if override_measurement: measurement = override_measurement else: measurement = state.attributes.get('unit_of_measurement') if measurement in (None, ''): if default_measurement: measurement = default_measurement else: measurement = state.entity_id point = { 'measurement': measurement, 'tags': { 'domain': state.domain, 'entity_id': state.object_id, }, 'time': event.time_fired, 'fields': { _state_key: _state, } } for key, value in state.attributes.items(): if key != 'unit_of_measurement': # If the key is already in fields if key in point['fields']: key = key + '_' # Prevent column data errors in influxDB. # For each value we try to cast it as float # But if we can not do it we store the value # as string add "_str" postfix to the field key try: point['fields'][key] = float(value) except (ValueError, TypeError): new_key = '{}_str'.format(key) point['fields'][new_key] = str(value) entities[state.entity_id] += 1 point['tags'].update(tags) points.append(point) session.expunge(event) if points: if not simulate: client.write_points(points) count += len(points) # This prevents the progress bar from going over 100% when # the last step happens print_progress((step_start + len( points)), total_events, prefix_format.format( step_start, total_events)) else: print_progress( (step_start + step), total_events, prefix_format.format( step_start, total_events)) points = [] step_start += step print("\nStatistics:") print("\n".join(["{:6}: {}".format(v, k) for k, v in sorted(entities.items(), key=lambda x: x[1])])) print("\nInvalid Points: {}".format(len(invalid_points))) print("\nImport finished: {} points written".format(count)) return 0