def discover(include_device_type: bool, timeout: int) -> None: devices = VizioAsync.discovery_zeroconf(timeout) data = [] if devices: data = [{ "IP": dev.ip, "Port": dev.port, "Model": dev.model, "Name": dev.name } for dev in devices] else: _LOGGER.info("Couldn't find any devices using zeroconf, trying SSDP") devices = VizioAsync.discovery_ssdp(timeout) if devices: data = [{ "IP": dev.ip, "Model": dev.model, "Name": dev.name } for dev in devices] if devices: if include_device_type: for dev in data: dev["Guessed Device Type"] = guess_device_type( dev["IP"], dev.get("Port")) _LOGGER.info("\n%s", tabulate(data, "keys")) else: _LOGGER.info("No Vizio devices discoverd.")
async def async_step_tv_apps( self, user_input: Dict[str, Any] = None ) -> Dict[str, Any]: """Handle app configuration to complete TV configuration.""" if user_input is not None: if user_input.get(CONF_APPS_TO_INCLUDE_OR_EXCLUDE): # Update stored apps with user entry config keys self._apps[user_input[CONF_INCLUDE_OR_EXCLUDE].lower()] = user_input[ CONF_APPS_TO_INCLUDE_OR_EXCLUDE ].copy() return await self._create_entry_if_unique(self._data) return self.async_show_form( step_id="tv_apps", data_schema=vol.Schema( { vol.Optional( CONF_INCLUDE_OR_EXCLUDE, default=CONF_INCLUDE.title(), ): vol.In([CONF_INCLUDE.title(), CONF_EXCLUDE.title()]), vol.Optional(CONF_APPS_TO_INCLUDE_OR_EXCLUDE): cv.multi_select( VizioAsync.get_apps_list() ), } ), )
def get_apps_list(vizio: VizioAsync, country: str = "all") -> None: apps = vizio.get_apps_list(country) if apps: table = tabulate([{"Name": app} for app in apps], headers="keys") _LOGGER.info("\n%s", table) else: _LOGGER.error("Couldn't get list of apps")
async def async_setup_entry( hass: HomeAssistantType, config_entry: ConfigEntry, async_add_entities: Callable[[List[Entity], bool], None], ) -> None: """Set up a Vizio media player entry.""" host = config_entry.data[CONF_HOST] token = config_entry.data.get(CONF_ACCESS_TOKEN) name = config_entry.data[CONF_NAME] device_class = config_entry.data[CONF_DEVICE_CLASS] # If config entry options not set up, set them up, otherwise assign values managed in options volume_step = config_entry.options.get( CONF_VOLUME_STEP, config_entry.data.get(CONF_VOLUME_STEP, DEFAULT_VOLUME_STEP)) params = {} if not config_entry.options: params["options"] = {CONF_VOLUME_STEP: volume_step} include_or_exclude_key = next( (key for key in config_entry.data.get(CONF_APPS, {}) if key in [CONF_INCLUDE, CONF_EXCLUDE]), None, ) if include_or_exclude_key: params["options"][CONF_APPS] = { include_or_exclude_key: config_entry.data[CONF_APPS][include_or_exclude_key].copy() } if not config_entry.data.get(CONF_VOLUME_STEP): new_data = config_entry.data.copy() new_data.update({CONF_VOLUME_STEP: volume_step}) params["data"] = new_data if params: hass.config_entries.async_update_entry(config_entry, **params) device = VizioAsync( DEVICE_ID, host, name, auth_token=token, device_type=VIZIO_DEVICE_CLASSES[device_class], session=async_get_clientsession(hass, False), timeout=DEFAULT_TIMEOUT, ) if not await device.can_connect_with_auth_check(): _LOGGER.warning("Failed to connect to %s", host) raise PlatformNotReady entity = VizioDevice( config_entry, device, name, device_class, ) async_add_entities([entity], update_before_add=True)
async def async_setup_entry( hass: HomeAssistant, config_entry: ConfigEntry, async_add_entities: AddEntitiesCallback, ) -> None: """Set up a Vizio media player entry.""" host = config_entry.data[CONF_HOST] token = config_entry.data.get(CONF_ACCESS_TOKEN) name = config_entry.data[CONF_NAME] device_class = config_entry.data[CONF_DEVICE_CLASS] # If config entry options not set up, set them up, otherwise assign values managed in options volume_step = config_entry.options.get( CONF_VOLUME_STEP, config_entry.data.get(CONF_VOLUME_STEP, DEFAULT_VOLUME_STEP)) params = {} if not config_entry.options: params["options"] = {CONF_VOLUME_STEP: volume_step} include_or_exclude_key = next( (key for key in config_entry.data.get(CONF_APPS, {}) if key in (CONF_INCLUDE, CONF_EXCLUDE)), None, ) if include_or_exclude_key: params["options"][CONF_APPS] = { include_or_exclude_key: config_entry.data[CONF_APPS][include_or_exclude_key].copy() } if not config_entry.data.get(CONF_VOLUME_STEP): new_data = config_entry.data.copy() new_data.update({CONF_VOLUME_STEP: volume_step}) params["data"] = new_data if params: hass.config_entries.async_update_entry(config_entry, **params) device = VizioAsync( DEVICE_ID, host, name, auth_token=token, device_type=VIZIO_DEVICE_CLASSES[device_class], session=async_get_clientsession(hass, False), timeout=DEFAULT_TIMEOUT, ) apps_coordinator = hass.data[DOMAIN].get(CONF_APPS) entity = VizioDevice(config_entry, device, name, device_class, apps_coordinator) async_add_entities([entity], update_before_add=True) platform = entity_platform.async_get_current_platform() platform.async_register_entity_service(SERVICE_UPDATE_SETTING, UPDATE_SETTING_SCHEMA, "async_update_setting")
async def async_step_init( self, user_input: Dict[str, Any] = None ) -> Dict[str, Any]: """Manage the vizio options.""" if user_input is not None: if user_input.get(CONF_APPS_TO_INCLUDE_OR_EXCLUDE): user_input[CONF_APPS] = { user_input[CONF_INCLUDE_OR_EXCLUDE]: user_input[ CONF_APPS_TO_INCLUDE_OR_EXCLUDE ].copy() } user_input.pop(CONF_INCLUDE_OR_EXCLUDE) user_input.pop(CONF_APPS_TO_INCLUDE_OR_EXCLUDE) return self.async_create_entry(title="", data=user_input) options = { vol.Optional( CONF_VOLUME_STEP, default=self.config_entry.options.get( CONF_VOLUME_STEP, DEFAULT_VOLUME_STEP ), ): vol.All(vol.Coerce(int), vol.Range(min=1, max=10)) } if self.config_entry.data[CONF_DEVICE_CLASS] == DEVICE_CLASS_TV: default_include_or_exclude = ( CONF_EXCLUDE if self.config_entry.options and CONF_EXCLUDE in self.config_entry.options.get(CONF_APPS) else CONF_EXCLUDE ) options.update( { vol.Optional( CONF_INCLUDE_OR_EXCLUDE, default=default_include_or_exclude.title(), ): vol.All( vol.In([CONF_INCLUDE.title(), CONF_EXCLUDE.title()]), vol.Lower ), vol.Optional( CONF_APPS_TO_INCLUDE_OR_EXCLUDE, default=self.config_entry.options.get(CONF_APPS, {}).get( default_include_or_exclude, [] ), ): cv.multi_select(VizioAsync.get_apps_list()), } ) return self.async_show_form(step_id="init", data_schema=vol.Schema(options))
async def async_setup_entry( hass: HomeAssistantType, config_entry: ConfigEntry, async_add_entities: Callable[[List[Entity], bool], None], ) -> None: """Set up a Vizio media player entry.""" host = config_entry.data[CONF_HOST] token = config_entry.data.get(CONF_ACCESS_TOKEN) name = config_entry.data[CONF_NAME] device_class = config_entry.data[CONF_DEVICE_CLASS] # If config entry options not set up, set them up, otherwise assign values managed in options if not config_entry.options: volume_step = config_entry.data.get(CONF_VOLUME_STEP, DEFAULT_VOLUME_STEP) hass.config_entries.async_update_entry( config_entry, options={CONF_VOLUME_STEP: volume_step}) else: volume_step = config_entry.options[CONF_VOLUME_STEP] device = VizioAsync( DEVICE_ID, host, name, auth_token=token, device_type=VIZIO_DEVICE_CLASSES[device_class], session=async_get_clientsession(hass, False), timeout=DEFAULT_TIMEOUT, ) if not await device.can_connect(): fail_auth_msg = "" if token: fail_auth_msg = f"and auth token '{token}' are correct." else: fail_auth_msg = "is correct." _LOGGER.warning( "Failed to connect to Vizio device, please check if host '%s' " "is valid and available. Also check if device class '%s' %s", host, device_class, fail_auth_msg, ) raise PlatformNotReady entity = VizioDevice(config_entry, device, name, volume_step, device_class) async_add_entities([entity], update_before_add=True)
def discover(include_device_type: bool, timeout: int) -> None: devices = VizioAsync.discovery_zeroconf(timeout) if include_device_type: table = tabulate( [[ dev.ip, dev.port, dev.model, dev.name, guess_device_type(dev.ip, dev.port), ] for dev in devices], headers=["IP", "Port", "Model", "Name", "Guessed Device Type"], ) else: table = tabulate( [[dev.ip, dev.port, dev.model, dev.name] for dev in devices], headers=["IP", "Port", "Model", "Name"], ) _LOGGER.info("\n%s", table)
async def async_step_pair_tv( self, user_input: Dict[str, Any] = None ) -> Dict[str, Any]: """Start pairing process and ask user for PIN to complete pairing process.""" errors = {} # Start pairing process if it hasn't already started if not self._ch_type and not self._pairing_token: dev = VizioAsync( DEVICE_ID, self._data[CONF_HOST], self._data[CONF_NAME], None, self._data[CONF_DEVICE_CLASS], session=async_get_clientsession(self.hass, False), ) pair_data = await dev.start_pair() if pair_data: self._ch_type = pair_data.ch_type self._pairing_token = pair_data.token return await self.async_step_pair_tv() return self.async_show_form( step_id="user", data_schema=_get_config_schema(self._data), errors={"base": "cant_connect"}, ) # Complete pairing process if PIN has been provided if user_input and user_input.get(CONF_PIN): dev = VizioAsync( DEVICE_ID, self._data[CONF_HOST], self._data[CONF_NAME], None, self._data[CONF_DEVICE_CLASS], session=async_get_clientsession(self.hass, False), ) pair_data = await dev.pair( self._ch_type, self._pairing_token, user_input[CONF_PIN] ) if pair_data: self._data[CONF_ACCESS_TOKEN] = pair_data.auth_token self._must_show_form = True unique_id = await VizioAsync.get_unique_id( self._data[CONF_HOST], self._data[CONF_ACCESS_TOKEN], self._data[CONF_DEVICE_CLASS], session=async_get_clientsession(self.hass, False), ) # Set unique ID and abort if unique ID is already configured on an entry or a flow # with the unique ID is already in progress await self.async_set_unique_id( unique_id=unique_id, raise_on_progress=True ) self._abort_if_unique_id_configured() # pylint: disable=no-member # https://github.com/PyCQA/pylint/issues/3167 if self.context["source"] == SOURCE_IMPORT: # If user is pairing via config import, show different message return await self.async_step_pairing_complete_import() return await self.async_step_tv_apps() # If no data was retrieved, it's assumed that the pairing attempt was not # successful errors[CONF_PIN] = "complete_pairing_failed" return self.async_show_form( step_id="pair_tv", data_schema=_get_pairing_schema(user_input), errors=errors, )
def cli(ctx, ip: str, auth: str, device_type: str) -> None: logging.basicConfig(level=logging.INFO) ctx.obj = VizioAsync(DEFAULT_DEVICE_ID, ip, DEFAULT_DEVICE_NAME, auth, device_type)
async def get_remote_keys_list(vizio: VizioAsync) -> None: table = tabulate(vizio.get_remote_keys_list(), headers=["App Name"]) _LOGGER.info("\n%s", table)
def get_volume_max(vizio: VizioAsync) -> None: _LOGGER.info("Max volume: %s", vizio.get_max_volume())
async def async_step_pair_tv(self, user_input: dict[str, Any] = None) -> FlowResult: """ Start pairing process for TV. Ask user for PIN to complete pairing process. """ errors = {} # Start pairing process if it hasn't already started if not self._ch_type and not self._pairing_token: dev = VizioAsync( DEVICE_ID, self._data[CONF_HOST], self._data[CONF_NAME], None, self._data[CONF_DEVICE_CLASS], session=async_get_clientsession(self.hass, False), ) pair_data = await dev.start_pair() if pair_data: self._ch_type = pair_data.ch_type self._pairing_token = pair_data.token return await self.async_step_pair_tv() return self.async_show_form( step_id="user", data_schema=_get_config_schema(self._data), errors={"base": "cannot_connect"}, ) # Complete pairing process if PIN has been provided if user_input and user_input.get(CONF_PIN): dev = VizioAsync( DEVICE_ID, self._data[CONF_HOST], self._data[CONF_NAME], None, self._data[CONF_DEVICE_CLASS], session=async_get_clientsession(self.hass, False), ) pair_data = await dev.pair(self._ch_type, self._pairing_token, user_input[CONF_PIN]) if pair_data: self._data[CONF_ACCESS_TOKEN] = pair_data.auth_token self._must_show_form = True if self.context["source"] == SOURCE_IMPORT: # If user is pairing via config import, show different message return await self.async_step_pairing_complete_import() return await self.async_step_pairing_complete() # If no data was retrieved, it's assumed that the pairing attempt was not # successful errors[CONF_PIN] = "complete_pairing_failed" return self.async_show_form( step_id="pair_tv", data_schema=_get_pairing_schema(user_input), errors=errors, )
cv.string, vol.Optional(CONF_ACCESS_TOKEN): cv.string, vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string, vol.Optional(CONF_DEVICE_CLASS, default=DEFAULT_DEVICE_CLASS): vol.All(cv.string, vol.Lower, vol.In([DEVICE_CLASS_TV, DEVICE_CLASS_SPEAKER])), vol.Optional(CONF_VOLUME_STEP, default=DEFAULT_VOLUME_STEP): vol.All(vol.Coerce(int), vol.Range(min=1, max=10)), vol.Optional(CONF_APPS): vol.All( { vol.Exclusive(CONF_INCLUDE, "apps_filter"): vol.All(cv.ensure_list, [vol.All(cv.string, vol.In(VizioAsync.get_apps_list()))]), vol.Exclusive(CONF_EXCLUDE, "apps_filter"): vol.All(cv.ensure_list, [vol.All(cv.string, vol.In(VizioAsync.get_apps_list()))]), vol.Optional(CONF_ADDITIONAL_CONFIGS): vol.All( cv.ensure_list, [ { vol.Required(CONF_NAME): cv.string, vol.Required(CONF_CONFIG): { vol.Required(CONF_APP_ID): cv.string, vol.Required(CONF_NAME_SPACE): vol.Coerce(int), vol.Optional(CONF_MESSAGE, default=None):