feat(config_flow): digit-delay (0.05–1.0 s, invalid input error) + optional send-enter options UI consumed by the §7 channel path; strings/README updated (P5-2.1)
This commit is contained in:
1 parent
4661e52041
commit
3d026ae60e
4 files changed
+45
-6
No files matched your search
@@ -84,6 +84,14 @@ TV Remote entity, the Nvidia Remote Protocol (PIN pairing), or ADB
|
|||||||
media-session mode (ADB enabled + host). The `no_state_source` form error
|
media-session mode (ADB enabled + host). The `no_state_source` form error
|
||||||
fires only when none of the three is present; ADB-only setups are valid.
|
fires only when none of the three is present; ADB-only setups are valid.
|
||||||
|
|
||||||
|
### Channel entry options
|
||||||
|
|
||||||
|
The options flow exposes the §7 channel behavior the integration replicates:
|
||||||
|
the inter-digit **delay** (0.05–1.0 s, default 0.1) and the optional
|
||||||
|
**ENTER press** after the digits (off by default — TiviMate's validated
|
||||||
|
behavior). Both are consumed by `play_media` with
|
||||||
|
`media_content_type: channel`.
|
||||||
|
|
||||||
### Raw `adb_command` service (opt-in)
|
### Raw `adb_command` service (opt-in)
|
||||||
|
|
||||||
When enabled in the integration's options (`adb_command_enabled`, **default
|
When enabled in the integration's options (`adb_command_enabled`, **default
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ from .adb_session import ensure_adb_key
|
|||||||
from .connection import ShieldConnectionManager
|
from .connection import ShieldConnectionManager
|
||||||
from .const import (
|
from .const import (
|
||||||
ATTR_MEDIA_DAG_INPUT_MAP,
|
ATTR_MEDIA_DAG_INPUT_MAP,
|
||||||
|
CHANNEL_DIGIT_DELAY,
|
||||||
CONF_ADB_COMMAND_ENABLED,
|
CONF_ADB_COMMAND_ENABLED,
|
||||||
CONF_ADB_ENABLED,
|
CONF_ADB_ENABLED,
|
||||||
CONF_ADB_HOST,
|
CONF_ADB_HOST,
|
||||||
@@ -20,6 +21,8 @@ from .const import (
|
|||||||
CONF_ADB_STORE_APP_INFO,
|
CONF_ADB_STORE_APP_INFO,
|
||||||
CONF_ANDROIDTV_ENTITY,
|
CONF_ANDROIDTV_ENTITY,
|
||||||
CONF_APP_NAME_MAP,
|
CONF_APP_NAME_MAP,
|
||||||
|
CONF_CHANNEL_DIGIT_DELAY,
|
||||||
|
CONF_CHANNEL_SEND_ENTER,
|
||||||
CONF_JELLYFIN_ENTITY,
|
CONF_JELLYFIN_ENTITY,
|
||||||
CONF_PAIRING_CODE,
|
CONF_PAIRING_CODE,
|
||||||
CONF_POWER_ENTITY,
|
CONF_POWER_ENTITY,
|
||||||
@@ -497,6 +500,16 @@ class NvidiaShieldOptionsFlow(config_entries.OptionsFlow):
|
|||||||
"""Single-page options."""
|
"""Single-page options."""
|
||||||
errors = {}
|
errors = {}
|
||||||
if user_input is not None:
|
if user_input is not None:
|
||||||
|
# P5-2: validate the digit delay (0.05–1.0 s, §7 window)
|
||||||
|
delay = user_input.pop(CONF_CHANNEL_DIGIT_DELAY, None)
|
||||||
|
if delay is not None:
|
||||||
|
try:
|
||||||
|
delay = float(delay)
|
||||||
|
except (TypeError, ValueError):
|
||||||
|
errors["base"] = "invalid_digit_delay"
|
||||||
|
delay = None
|
||||||
|
if delay is not None and not (0.05 <= delay <= 1.0):
|
||||||
|
errors["base"] = "invalid_digit_delay"
|
||||||
app_map_text = user_input.pop(CONF_APP_NAME_MAP, None)
|
app_map_text = user_input.pop(CONF_APP_NAME_MAP, None)
|
||||||
if app_map_text is None:
|
if app_map_text is None:
|
||||||
app_map = self._options.get(CONF_APP_NAME_MAP, {})
|
app_map = self._options.get(CONF_APP_NAME_MAP, {})
|
||||||
@@ -507,6 +520,8 @@ class NvidiaShieldOptionsFlow(config_entries.OptionsFlow):
|
|||||||
if app_map is None:
|
if app_map is None:
|
||||||
errors["base"] = "invalid_app_map"
|
errors["base"] = "invalid_app_map"
|
||||||
if not errors:
|
if not errors:
|
||||||
|
if delay is not None:
|
||||||
|
self._options[CONF_CHANNEL_DIGIT_DELAY] = delay
|
||||||
self._options.update(user_input)
|
self._options.update(user_input)
|
||||||
self._options[CONF_APP_NAME_MAP] = app_map
|
self._options[CONF_APP_NAME_MAP] = app_map
|
||||||
return self.async_create_entry(title="", data=self._options)
|
return self.async_create_entry(title="", data=self._options)
|
||||||
@@ -537,6 +552,12 @@ class NvidiaShieldOptionsFlow(config_entries.OptionsFlow):
|
|||||||
recv_key = vol.Optional(CONF_RECEIVER_ENTITY, default=recv)
|
recv_key = vol.Optional(CONF_RECEIVER_ENTITY, default=recv)
|
||||||
schema_dict[recv_key] = sel["receiver"]
|
schema_dict[recv_key] = sel["receiver"]
|
||||||
|
|
||||||
|
# P5-2: channel digit behavior (the user-validated §7 flow)
|
||||||
|
current_delay = self._options.get(CONF_CHANNEL_DIGIT_DELAY, CHANNEL_DIGIT_DELAY)
|
||||||
|
schema_dict[vol.Optional(CONF_CHANNEL_DIGIT_DELAY, default=current_delay)] = str
|
||||||
|
current_enter = self._options.get(CONF_CHANNEL_SEND_ENTER, False)
|
||||||
|
schema_dict[vol.Optional(CONF_CHANNEL_SEND_ENTER, default=current_enter)] = bool
|
||||||
|
|
||||||
# P4-2a: the raw adb_command service is opt-in (default off)
|
# P4-2a: the raw adb_command service is opt-in (default off)
|
||||||
current_flag = self._options.get(CONF_ADB_COMMAND_ENABLED, False)
|
current_flag = self._options.get(CONF_ADB_COMMAND_ENABLED, False)
|
||||||
schema_dict[vol.Optional(CONF_ADB_COMMAND_ENABLED, default=current_flag)] = bool
|
schema_dict[vol.Optional(CONF_ADB_COMMAND_ENABLED, default=current_flag)] = bool
|
||||||
|
|||||||
@@ -55,7 +55,8 @@
|
|||||||
"protocol_invalid_code": "Pairing has not started or the code is empty. Click Submit to retry.",
|
"protocol_invalid_code": "Pairing has not started or the code is empty. Click Submit to retry.",
|
||||||
"protocol_pair_failed": "The Shield rejected that pairing code. Click Submit to try again.",
|
"protocol_pair_failed": "The Shield rejected that pairing code. Click Submit to try again.",
|
||||||
"no_state_source": "No state source selected. Provide at least one of: the Android TV Remote entity, the Nvidia Remote Protocol pairing, or ADB media-session mode (enable ADB and set the ADB Host).",
|
"no_state_source": "No state source selected. Provide at least one of: the Android TV Remote entity, the Nvidia Remote Protocol pairing, or ADB media-session mode (enable ADB and set the ADB Host).",
|
||||||
"invalid_app_map": "Each line must be package=name with a non-empty package (no spaces) and a non-empty name \u2014 e.g. ar.tvplayer.tv=TiviMate."
|
"invalid_app_map": "Each line must be package=name with a non-empty package (no spaces) and a non-empty name \u2014 e.g. ar.tvplayer.tv=TiviMate.",
|
||||||
|
"invalid_digit_delay": "The digit delay must be between 0.05 and 1.0 seconds."
|
||||||
},
|
},
|
||||||
"abort": {
|
"abort": {
|
||||||
"already_configured": "This Shield entity is already configured.",
|
"already_configured": "This Shield entity is already configured.",
|
||||||
@@ -79,7 +80,9 @@
|
|||||||
"adb_host": "ADB Host",
|
"adb_host": "ADB Host",
|
||||||
"adb_port": "ADB Port",
|
"adb_port": "ADB Port",
|
||||||
"app_name_map": "Apps name/icon map",
|
"app_name_map": "Apps name/icon map",
|
||||||
"adb_command_enabled": "Enable raw ADB shell service"
|
"adb_command_enabled": "Enable raw ADB shell service",
|
||||||
|
"channel_digit_delay": "Channel digit delay (seconds)",
|
||||||
|
"channel_send_enter": "Send ENTER after channel digits"
|
||||||
},
|
},
|
||||||
"data_description": {
|
"data_description": {
|
||||||
"jellyfin_entity": "The Jellyfin media_player for this device. Session stream info is read from the HA Jellyfin integration's existing coordinator \u2014 no extra config needed.",
|
"jellyfin_entity": "The Jellyfin media_player for this device. Session stream info is read from the HA Jellyfin integration's existing coordinator \u2014 no extra config needed.",
|
||||||
@@ -91,7 +94,9 @@
|
|||||||
"adb_host": "IP address for ADB connection. Leave blank to auto-detect from the Android TV Remote integration.",
|
"adb_host": "IP address for ADB connection. Leave blank to auto-detect from the Android TV Remote integration.",
|
||||||
"adb_port": "ADB port (default 5555).",
|
"adb_port": "ADB port (default 5555).",
|
||||||
"app_name_map": "One entry per line, package=name (e.g. ar.tvplayer.tv=TiviMate). The friendly name resolves after the Android TV Remote entity and the protocol push; icons follow the media image lookup by name. Leave blank to clear.",
|
"app_name_map": "One entry per line, package=name (e.g. ar.tvplayer.tv=TiviMate). The friendly name resolves after the Android TV Remote entity and the protocol push; icons follow the media image lookup by name. Leave blank to clear.",
|
||||||
"adb_command_enabled": "Adds the nvidia_shield.adb_command service (raw ADB shell over the persistent connection). Security-relevant: leave off unless you need it \u2014 it is the same opt-in posture as the core androidtv integration."
|
"adb_command_enabled": "Adds the nvidia_shield.adb_command service (raw ADB shell over the persistent connection). Security-relevant: leave off unless you need it \u2014 it is the same opt-in posture as the core androidtv integration.",
|
||||||
|
"channel_digit_delay": "Pause between the channel digits entered via play_media(channel) \u2014 0.05 to 1.0 seconds (default 0.1, matching the validated behavior).",
|
||||||
|
"channel_send_enter": "Optionally presses ENTER after the last digit (protocol key, then the ADB keyevent fallback). Off by default \u2014 matches TiviMate's validated behavior."
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -55,7 +55,8 @@
|
|||||||
"protocol_invalid_code": "Pairing has not started or the code is empty. Click Submit to retry.",
|
"protocol_invalid_code": "Pairing has not started or the code is empty. Click Submit to retry.",
|
||||||
"protocol_pair_failed": "The Shield rejected that pairing code. Click Submit to try again.",
|
"protocol_pair_failed": "The Shield rejected that pairing code. Click Submit to try again.",
|
||||||
"no_state_source": "No state source selected. Provide at least one of: the Android TV Remote entity, the Nvidia Remote Protocol pairing, or ADB media-session mode (enable ADB and set the ADB Host).",
|
"no_state_source": "No state source selected. Provide at least one of: the Android TV Remote entity, the Nvidia Remote Protocol pairing, or ADB media-session mode (enable ADB and set the ADB Host).",
|
||||||
"invalid_app_map": "Each line must be package=name with a non-empty package (no spaces) and a non-empty name \u2014 e.g. ar.tvplayer.tv=TiviMate."
|
"invalid_app_map": "Each line must be package=name with a non-empty package (no spaces) and a non-empty name \u2014 e.g. ar.tvplayer.tv=TiviMate.",
|
||||||
|
"invalid_digit_delay": "The digit delay must be between 0.05 and 1.0 seconds."
|
||||||
},
|
},
|
||||||
"abort": {
|
"abort": {
|
||||||
"already_configured": "This Shield entity is already configured.",
|
"already_configured": "This Shield entity is already configured.",
|
||||||
@@ -79,7 +80,9 @@
|
|||||||
"adb_host": "ADB Host",
|
"adb_host": "ADB Host",
|
||||||
"adb_port": "ADB Port",
|
"adb_port": "ADB Port",
|
||||||
"app_name_map": "Apps name/icon map",
|
"app_name_map": "Apps name/icon map",
|
||||||
"adb_command_enabled": "Enable raw ADB shell service"
|
"adb_command_enabled": "Enable raw ADB shell service",
|
||||||
|
"channel_digit_delay": "Channel digit delay (seconds)",
|
||||||
|
"channel_send_enter": "Send ENTER after channel digits"
|
||||||
},
|
},
|
||||||
"data_description": {
|
"data_description": {
|
||||||
"jellyfin_entity": "The Jellyfin media_player for this device. Session stream info is read from the HA Jellyfin integration's existing coordinator \u2014 no extra config needed.",
|
"jellyfin_entity": "The Jellyfin media_player for this device. Session stream info is read from the HA Jellyfin integration's existing coordinator \u2014 no extra config needed.",
|
||||||
@@ -91,7 +94,9 @@
|
|||||||
"adb_host": "IP address for ADB connection. Leave blank to auto-detect from the Android TV Remote integration.",
|
"adb_host": "IP address for ADB connection. Leave blank to auto-detect from the Android TV Remote integration.",
|
||||||
"adb_port": "ADB port (default 5555).",
|
"adb_port": "ADB port (default 5555).",
|
||||||
"app_name_map": "One entry per line, package=name (e.g. ar.tvplayer.tv=TiviMate). The friendly name resolves after the Android TV Remote entity and the protocol push; icons follow the media image lookup by name. Leave blank to clear.",
|
"app_name_map": "One entry per line, package=name (e.g. ar.tvplayer.tv=TiviMate). The friendly name resolves after the Android TV Remote entity and the protocol push; icons follow the media image lookup by name. Leave blank to clear.",
|
||||||
"adb_command_enabled": "Adds the nvidia_shield.adb_command service (raw ADB shell over the persistent connection). Security-relevant: leave off unless you need it \u2014 it is the same opt-in posture as the core androidtv integration."
|
"adb_command_enabled": "Adds the nvidia_shield.adb_command service (raw ADB shell over the persistent connection). Security-relevant: leave off unless you need it \u2014 it is the same opt-in posture as the core androidtv integration.",
|
||||||
|
"channel_digit_delay": "Pause between the channel digits entered via play_media(channel) \u2014 0.05 to 1.0 seconds (default 0.1, matching the validated behavior).",
|
||||||
|
"channel_send_enter": "Optionally presses ENTER after the last digit (protocol key, then the ADB keyevent fallback). Off by default \u2014 matches TiviMate's validated behavior."
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in new issue
Block a user