Device Tools: Create, Modify and Merge Devices

@tim.plas

There’s 3 things you have to do:

  1. First you have to enable a Battery Notes feature that’s not enabled by default. This isn’t super obvious but Battery Notes ONLY displays supported devices by default, not all devices, which is needed to add Battery Notes configs to. The only way to show all devices in Battery Notes is to add it into the HA configuration.yaml. My excerpt for this is below:
# Battery Notes
battery_notes:
  enable_autodiscovery: true
  show_all_devices: true
  enable_replaced: true
  default_battery_low_threshold: 20

Once you’ve got the above setup you just need the following:

  1. Create a device in the Device Tools integration. This you do by going into the integration, clicking “Add Device” and only adding a modification name (leaving the bottom item blank) and at the next prompt name the device. These 2 pieces is what gets you a device to configure a battery for.
  2. Once you have your device, go into Battery Notes and add a new Device there, selecting your newly created Device Tools device from the dropdown. Then you just configure as you would any normally auto detected device
1 Like

Wonderful; thanks so much!

I’m struggling a bit to use this. It must be something obvious I just can’t find. It’s installed. I’ve got the first device created, and see it under the integration entries. I can’t seem to find any button or link to get an entity picker to show up. I’ve clicked everything and can’t find the configure device entities. I do not see anything labeled configure anywhere.

The only link that doesn’t seem right, is the cog wheel gives this error “Config flow could not be loaded: 500 Internal Server Error Server got itself in trouble”

@joer293 - I’m afraid the Device Tools integration got broken in HA OS 2025.12 , by something that it used which got deprecated & removed as of 2025.12. The 500 error on the gear icon is exactly the symptom.

We’re waiting for the code owner to update it. Meanwhile, in the discussion on the GitHub repository, someone suggested a temporary work-around by commenting out one line of code. That didn’t work for me, but maybe I missed something.

I have certainly found the integration useful. I’ve been using it to add “dumb” devices to HA, so that I can use the Battery Notes HACS integration to keep track of devices’ battery type & usage.

@uSlackr postet this an hour ago

1 Like

That’s right. I took some time the last few days to finally finish up the migration code and fix a few bugs that newly got introduced. I hope the new version works for everyone! These are the release notes:

This update represents a major architectural overhaul of the device-tools Home Assistant custom component, transitioning from a polling-based modification system to an event-driven listener architecture. The changes significantly refactor how device and entity modifications are managed, introducing new abstractions and improving the configuration flow.

Key Changes:

  • Replaced polling-based modification system with event-driven listeners (DeviceListener, EntityListener)
  • Introduced new modification class hierarchy (Modification, EntryModification, DeviceModification, EntityModification, MergeModification)
  • Completely rewrote config flow with support for device, entity, and merge modification types
  • Added migration logic from v1 to v2 configuration format
  • Updated Python requirements to 3.13+ and HomeAssistant to 2025.12+
4 Likes

Thank you for the update.
Not sure you prefer some pre-reporting over here, or should I jump stright into github.

I’ve had my Wattsonic entities (dozens) integrated into a single device. After update to 2.0.1, it ended with Wattsonic device remained, but:

  1. Device Tools is not linked to it anymore
  2. Some entities are definitively missing.
  3. DeviceTools reports 35 entries, while there was only one Wattsonic only (see the second screenshot). All behave the same when opening its options

It’s OK with me to fix it on my own (eventually remove all and recreate the device). But if you like to take the opportunity to debug the migration, I can provide some data.

No info in logs (warning level) found.

BTW see the Version 0.0.0 on my screenshot. Maybe worth updating.

Im getting an error with 2.0.0-alpha whenever I try to create a new device. I leave the device selector empty, and enter a modification_entry_name and I get “Unknown error occurred” with the following in the logs:

2026-03-03 13:31:54.256 ERROR (MainThread) [aiohttp.server] Error handling request from 192.168.1.233
Traceback (most recent call last):
  File "/usr/local/lib/python3.13/site-packages/aiohttp/web_protocol.py", line 510, in _handle_request
    resp = await request_handler(request)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.13/site-packages/aiohttp/web_app.py", line 569, in _handle
    return await handler(request)
           ^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.13/site-packages/aiohttp/web_middlewares.py", line 117, in impl
    return await handler(request)
           ^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/src/homeassistant/homeassistant/components/http/security_filter.py", line 92, in security_filter_middleware
    return await handler(request)
           ^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/src/homeassistant/homeassistant/components/http/forwarded.py", line 87, in forwarded_middleware
    return await handler(request)
           ^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/src/homeassistant/homeassistant/components/http/request_context.py", line 26, in request_context_middleware
    return await handler(request)
           ^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/src/homeassistant/homeassistant/components/http/auth.py", line 242, in auth_middleware
    return await handler(request)
           ^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/src/homeassistant/homeassistant/components/http/headers.py", line 41, in headers_middleware
    response = await handler(request)
               ^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/src/homeassistant/homeassistant/helpers/http.py", line 73, in handle
    result = await handler(request, **request.match_info)
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/src/homeassistant/homeassistant/components/http/decorators.py", line 83, in with_admin
    return await func(self, request, *args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/src/homeassistant/homeassistant/components/config/config_entries.py", line 234, in post
    return await super().post(request, flow_id)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/src/homeassistant/homeassistant/components/http/data_validator.py", line 74, in wrapper
    return await method(view, request, data, *args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/src/homeassistant/homeassistant/helpers/data_entry_flow.py", line 121, in post
    result = await self._flow_mgr.async_configure(flow_id, data)
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/src/homeassistant/homeassistant/data_entry_flow.py", line 336, in async_configure
    result = await self._async_configure(flow_id, user_input)
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/src/homeassistant/homeassistant/data_entry_flow.py", line 383, in _async_configure
    result = await self._async_handle_step(
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
        flow, cur_step["step_id"], user_input
        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    )
    ^
  File "/usr/src/homeassistant/homeassistant/data_entry_flow.py", line 483, in _async_handle_step
    result: _FlowResultT = await getattr(flow, method)(user_input)
                           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/config/custom_components/device_tools/config_flow.py", line 346, in async_step_create_entry
    return await self.async_step_modify_entry()
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/config/custom_components/device_tools/config_flow.py", line 435, in async_step_modify_entry
    for k, v in modification_original_data.items()
                ^^^^^^^^^^^^^^^^^^^^^^^^^^
UnboundLocalError: cannot access local variable 'modification_original_data' where it is not associated with a value