* Initial implementation of hardware update model
* Fixes
* WIP: change the `homeassistant_sky_connect` integration type
* More fixes
* WIP
* Display firmware info in the device page
* Make progress more responsive
* WIP: Yellow
* Abstract the bootloader reset type
* Clean up comments
* Make the Yellow integration non-hardware
* Use the correct radio device for Yellow
* Avoid hardcoding strings
* Use `FIRMWARE_VERSION` within config flows
* Fix up unit tests
* Revert integration type changes
* Rewrite hardware ownership context manager name, for clarity
* Move manifest parsing logic into a new package
Pass the correct type to the firmware API library
* Create and delete entities instead of mutating the entity description
* Move entity replacement into a `async_setup_entry` callback
* Change update entity category from "diagnostic" to "config"
* Have the client library handle firmware fetching
* Switch from dispatcher to `async_on_state_change`
* Remove unnecessary type annotation on base update entity
* Simplify state recomputation
* Remove device registry code, since the devices will not be visible
* Further simplify state computation
* Give the device-less update entity a more descriptive name
* Limit state changes to integer increments when sending firmware update progress
* Re-raise `HomeAssistantError` if there is a problem during flashing
* Remove unnecessary state write during entity creation
* Rename `_maybe_recompute_state` to `_update_attributes`
* Bump the flasher to 0.0.30
* Add some tests
* Ensure the update entity has a sensible name
* Initial ZBT-1 unit tests
* Replace `_update_config_entry_after_install` with a more explicit `_firmware_info_callback` override
* Write the firmware version to the config entry as well
* Test the hardware update platform independently
* Add unit tests to the Yellow and ZBT-1 integrations
* Load firmware info from the config entry when creating the update entity
* Test entity state restoration
* Test the reloading of integrations marked as "owning"
* Test installation failure cases
* Test firmware type change callback failure case
* Address review comments
* Migrate `self._probed_firmware_type` to `self._probed_firmware_info`
* Migrate from `firmware_type` to the full `firmware_info`
* Implement `probe_silabs_firmware_type` via `probe_silabs_firmware_info`
* Fix unit tests
* Increase coverage
* Bring test coverage to 100%
* Simplify test per review comment
* Implement `async_register_firmware_info_provider` for OTBR
* Keep track of the current device for OTBR
Keep track of the current device, part 2
* Fix unit tests
* Revert keeping track of the current device
* Fix existing unit tests
* Increase test coverage
* Remove unused code from tests
* Reload OTBR when the addon reloads
* Only reload if the current entry is running
* Runtime test
* Add a unit test for the reloading
* Clarify the purpose of `ConfigEntryState.SETUP_IN_PROGRESS`
* Simplify typing
* Replace `FirmwareGuess` with `FirmwareInfo` with owner tracking
* Fix up config flow
* Account for OTBR addon existing independent of integration
* Fix remaining unit tests
* Add some tests for ownership
* Unit test `get_zha_firmware_info`
* ZHA `homeassistant_hardware` platform
* OTBR `homeassistant_hardware` platform
* Rework imports
* Fix unit tests
* Add OTBR unit tests
* Add hassfest exemption for `homeassistant_hardware` and `otbr`
* Invert registration to decouple the hardware integration
* Revert "Add hassfest exemption for `homeassistant_hardware` and `otbr`"
This reverts commit c8c6e7044f.
* Fix circular imports
* Fix unit tests
* Address review comments
* Simplify API a little
* Fix `| None` mypy issues
* Remove the `unregister_firmware_info_provider` API
* 100% coverage
* Add `HardwareInfoDispatcher.register_firmware_info_callback`
* Unit test `register_firmware_info_callback` (zha)
* Unit test `register_firmware_info_callback` (otbr)
* Update existing hardware helper tests to use the new function
* Add `async_` prefix to helper function names
* Move OTBR implementation to a separate PR
* Update ZHA diagnostics snapshot
* Switch from `dict.setdefault` to `defaultdict`
* Add some error handling to `iter_firmware_info` and increase test coverage
* Oops