예제 #1
0
 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)
예제 #2
0
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)
예제 #3
0
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)
예제 #4
0
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)
예제 #5
0
    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
예제 #6
0
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
예제 #7
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
예제 #8
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
예제 #9
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())
예제 #10
0
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())
예제 #11
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())
예제 #12
0
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
예제 #13
0
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)
예제 #14
0
    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)
예제 #15
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)

    hass = HomeAssistant()
    config_path = hass.loop.run_until_complete(async_run(hass, config_dir))
    print("Configuration file:", config_path)
    return 0
예제 #16
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)))
예제 #17
0
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
예제 #18
0
파일: gmusic.py 프로젝트: JIOB/SmartHome-1
    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)
예제 #19
0
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)
예제 #20
0
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)
예제 #21
0
    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
예제 #22
0
파일: __init__.py 프로젝트: somm15/PyLoxone
 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()))
예제 #23
0
    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()
예제 #24
0
    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()
예제 #25
0
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
예제 #26
0
    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()
예제 #27
0
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()
예제 #28
0
파일: __init__.py 프로젝트: somm15/PyLoxone
    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
예제 #29
0
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())
예제 #30
0
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))
예제 #31
0
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))
예제 #32
0
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
예제 #33
0
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",
예제 #34
0
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"])
예제 #35
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
예제 #36
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:
예제 #37
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=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'])
예제 #38
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=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'])
예제 #39
0
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
예제 #40
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
예제 #41
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
예제 #42
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
예제 #43
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