Data Entry Flow is a data entry framework that is part of Home Assistant. Data entry is done via data entry flows. A flow can represent a simple login form or a multi-step setup wizard for a component. A Flow Manager manages all flows that are in progress and handles creation of new flows.
Data Entry Flow is used in Home Assistant to create config entries.
This is the class that manages the flows that are in progress. When instantiating one, you pass in two async callbacks:
The manager delegates instantiating of config flow handlers to this async callback. This allows the parent of the manager to define their own way of finding handlers and preparing a handler for instantiation. For example, in the case of the config entry manager, it will make sure that the dependencies and requirements are setup.
This async callback is called when a flow is finished or aborted. i.e.
result['type'] in [RESULT_TYPE_CREATE_ENTRY, RESULT_TYPE_ABORT]. The callback function can modify result and return it back, if the result type changed to
RESULT_TYPE_FORM, the flow will continue running, display another form.
If the result type is
RESULT_TYPE_FORM, the result should look like:
If the result type is
RESULT_TYPE_CREATE_ENTRY, the result should look like:
If the result type is
RESULT_TYPE_ABORT, the result should look like:
Flow handlers will handle a single flow. A flow contains one or more steps. When a flow is instantiated, the
FlowHandler.init_step step will be called. Each step has three different possible results: "Show Form", "Abort" and "Create Entry".
At a minimum, each flow handler will have to define a version number and a step. This doesn't have to be
async_create_flow can assign
init_step dependent on the current workflow, for example in configuration,
context.source will be used as
The bare minimum config flow:
This result type will show a form to the user to fill in. You define the current step, the schema of the data (using voluptuous) and optionally a dictionary of errors. Title and description of the step will be provided via the translation file. Where this is defined depends on the context of the data entry flow.
After the user has filled in the form, the step method will be called again and the user input is passed in. Your step will only be called if the user input passes your data schema. When the user passes in data, you will have to do extra validation of the data. For example, you can verify that the passed in username and password are valid.
If something is wrong, you can return a dictionary with errors. Each key in the error dictionary refers to a field name that contains the error. Use the key
base if you want to show an error unrelated to a specific field. The specified errors need to refer to a key in a translation file.
If the user input passes validation, you can again return one of the three return values. If you want to navigate the user to the next step, return the return value of that step:
When the result is "Create Entry", an entry will be created and passed to the parent of the flow manager. A success message is shown to the user and the flow is finished. You create an entry by passing a title and data. The title can be used in the UI to indicate to the user which entry it is. Data can be any data type, as long as it is JSON serializable.
When a flow cannot be finished, you need to abort it. This will finish the flow and inform the user that the flow has finished. Reasons for a flow to not be able to finish can be that a device is already configured or not compatible with Home Assistant.
External Step & External Step Done
It is possible that a user needs to finish a config flow by doing actions on an external website. For example, setting up an integration by being redirected to an external webpage. This is commonly used by integrations that use OAuth2 to authorize a user.
The example is about config entries, but works with other parts that use data entry flows too.
The flow works as follows:
User starts config flow in Home Assistant
Config flow prompts user to finish the flow on an external website
User opens the external website
Upon completion of the external step, the user's browser will be redirected to a Home Assistant endpoint to deliver the response.
To be able to route the result of the external step to the Home Assistant endpoint, you will need to make sure the config flow ID is included. If your external step is an OAuth2 flow, you can leverage the oauth2 state for this. This is a variable that is not interpreted by the authorization page but is passed as-is to the Home Assistant endpoint.
The window closes and the Home Assistant user interface with the config flow will be visible to the user again.
The config flow has automatically advanced to the next step when the external step was marked as done. The user is prompted with the next step.
Example configuration flow that includes an external step.
Avoid doing work based on the external step data before you return an
async_mark_external_step_done. Instead, do the work in the step that you refer to as
next_step_id when marking the external step done. This will give the user a better user experience by showing a spinner in the UI while the work is done.
If you do the work inside the authorize callback, the user will stare at a blank screen until that all of a sudden closes because the data has forwarded. If you do the work before marking the external step as done, the user will still see the form with the "Open external website" button while the background work is being done. That too is undesirable.
Example code to mark an external step as done:
Data entry flows depend on translations for showing the text in the forms. It depends on the parent of a data entry flow manager where this is stored.
Initializing a config flow from an external source
You might want to initialize a config flow programmatically. For example, if we discover a device on the network that requires user interaction to finish setup. To do so, pass a source parameter and optional user input when initializing a flow:
The config flow handler will not start with the
init step. Instead, it will be instantiated with a step name equal to the source. The step should follow the same return values as a normal step.