1 """Config Flow for PlayStation 4."""
3 from collections
import OrderedDict
6 from pyps4_2ndscreen.errors
import CredentialTimeout
7 from pyps4_2ndscreen.helpers
import Helper
8 from pyps4_2ndscreen.media_art
import COUNTRIES
9 import voluptuous
as vol
31 CONF_MODE =
"Config Mode"
32 CONF_AUTO =
"Auto Discover"
33 CONF_MANUAL =
"Manual Entry"
38 PORT_MSG = {UDP_PORT:
"port_987_bind_error", TCP_PORT:
"port_997_bind_error"}
44 """Handle a PlayStation 4 config flow."""
46 VERSION = CONFIG_ENTRY_VERSION
49 """Initialize the config flow."""
51 self.
credscreds: str |
None =
None
55 self.
pinpin: str |
None =
None
57 self.
locationlocation: location.LocationInfo |
None =
None
61 self, user_input: dict[str, Any] |
None =
None
62 ) -> ConfigFlowResult:
63 """Handle a user config flow."""
65 ports = PORT_MSG.keys()
66 failed = await self.hass.async_add_executor_job(self.
helperhelper.port_bind, ports)
68 reason = PORT_MSG[failed]
73 self, user_input: dict[str, Any] |
None =
None
74 ) -> ConfigFlowResult:
75 """Return PS4 credentials from 2nd Screen App."""
77 if user_input
is not None:
79 self.
credscreds = await self.hass.async_add_executor_job(
80 self.
helperhelper.get_creds, DEFAULT_ALIAS
82 if self.
credscreds
is not None:
85 except CredentialTimeout:
86 errors[
"base"] =
"credential_timeout"
91 self, user_input: dict[str, Any] |
None =
None
92 ) -> ConfigFlowResult:
93 """Prompt for mode."""
95 mode = [CONF_AUTO, CONF_MANUAL]
97 if user_input
is not None:
98 if user_input[CONF_MODE] == CONF_MANUAL:
100 if device := user_input[CONF_IP_ADDRESS]:
103 errors[CONF_IP_ADDRESS] =
"no_ipaddress"
107 mode_schema = OrderedDict[vol.Marker, Any]()
108 mode_schema[vol.Required(CONF_MODE, default=CONF_AUTO)] = vol.In(
list(mode))
109 mode_schema[vol.Optional(CONF_IP_ADDRESS)] = str
112 step_id=
"mode", data_schema=vol.Schema(mode_schema), errors=errors
116 self, user_input: dict[str, Any] |
None =
None
117 ) -> ConfigFlowResult:
118 """Prompt user input. Create or edit entry."""
119 regions = sorted(COUNTRIES.keys())
120 default_region =
None
123 if user_input
is None:
126 devices = await self.hass.async_add_executor_job(
127 self.
helperhelper.has_devices, self.
m_devicem_device, LOCAL_UDP_PORT
134 self.
device_listdevice_list = [device[
"host-ip"]
for device
in devices]
143 if self.
credscreds == entry.data[CONF_TOKEN]
144 for device
in entry.data[
"devices"]
148 for c_device
in conf_devices:
149 if c_device[
"host"]
in self.
device_listdevice_list:
158 if user_input
is not None:
159 self.
regionregion = user_input[CONF_REGION]
160 self.
namename = user_input[CONF_NAME]
162 self.
pinpin =
str(user_input[CONF_CODE]).zfill(PIN_LENGTH)
163 self.
hosthost = user_input[CONF_IP_ADDRESS]
165 is_ready, is_login = await self.hass.async_add_executor_job(
174 if is_ready
is False:
175 errors[
"base"] =
"cannot_connect"
176 elif is_login
is False:
177 errors[
"base"] =
"login_failed"
180 CONF_HOST: self.
hosthost,
181 CONF_NAME: self.
namename,
182 CONF_REGION: self.
regionregion,
187 title=
"PlayStation 4",
188 data={CONF_TOKEN: self.
credscreds,
"devices": [device]},
193 self.
locationlocation = await location.async_detect_location_info(
197 country = COUNTRYCODE_NAMES.get(self.
locationlocation.country_code)
198 if country
in COUNTRIES:
199 default_region = country
202 link_schema = OrderedDict[vol.Marker, Any]()
203 link_schema[vol.Required(CONF_IP_ADDRESS)] = vol.In(
list(self.
device_listdevice_list))
204 link_schema[vol.Required(CONF_REGION, default=default_region)] = vol.In(
207 link_schema[vol.Required(CONF_CODE)] = vol.All(
208 vol.Strip, vol.Length(max=PIN_LENGTH), vol.Coerce(int)
210 link_schema[vol.Required(CONF_NAME, default=DEFAULT_NAME)] = str
213 step_id=
"link", data_schema=vol.Schema(link_schema), errors=errors
ConfigFlowResult async_step_mode(self, dict[str, Any]|None user_input=None)
ConfigFlowResult async_step_user(self, dict[str, Any]|None user_input=None)
ConfigFlowResult async_step_creds(self, dict[str, Any]|None user_input=None)
ConfigFlowResult async_step_link(self, dict[str, Any]|None user_input=None)
ConfigFlowResult async_create_entry(self, *str title, Mapping[str, Any] data, str|None description=None, Mapping[str, str]|None description_placeholders=None, Mapping[str, Any]|None options=None)
list[ConfigEntry] _async_current_entries(self, bool|None include_ignore=None)
ConfigFlowResult async_abort(self, *str reason, Mapping[str, str]|None description_placeholders=None)
ConfigFlowResult async_show_form(self, *str|None step_id=None, vol.Schema|None data_schema=None, dict[str, str]|None errors=None, Mapping[str, str]|None description_placeholders=None, bool|None last_step=None, str|None preview=None)
_FlowResultT async_show_form(self, *str|None step_id=None, vol.Schema|None data_schema=None, dict[str, str]|None errors=None, Mapping[str, str]|None description_placeholders=None, bool|None last_step=None, str|None preview=None)
_FlowResultT async_create_entry(self, *str|None title=None, Mapping[str, Any] data, str|None description=None, Mapping[str, str]|None description_placeholders=None)
_FlowResultT async_abort(self, *str reason, Mapping[str, str]|None description_placeholders=None)
bool remove(self, _T matcher)
aiohttp.ClientSession async_get_clientsession(HomeAssistant hass, bool verify_ssl=True, socket.AddressFamily family=socket.AF_UNSPEC, ssl_util.SSLCipherList ssl_cipher=ssl_util.SSLCipherList.PYTHON_DEFAULT)