ControllerX. Bring full functionality to light and media player controllers

You can switch it off in the App-Daemon settings.

After the last update (appdeamon 0.17.3) ControllerX stops working here. i subscribed to github on this issue: [BUG] ControllerX and Appdeamon · Issue #1184 · xaviml/controllerx · GitHub
So maybe this helps other users when the experiencing problems, that they are not alone and there’s work in progress (i’ll hope)

3 Likes

Yep, same here. I restored v 0.16.7 from a backup and now all is well, until the contributor has a chance to fix and update it. Not throwing stones, it’s a great add-on. I think Frenck mentioned that it’s actually due to a change from the Appdaemon coders and not the add-on contributor.

I should know better but I had auto-updates on for all my add-ons (now changed). Much better to give the updates a chance to settle before updating my system.

Thanks, have the same issue.

If it is the same that you mentioned on github, I think you have missed adding exclude_dirs into appdaemon.yaml file.

1 Like

Yes, thanks for that. That appears to the issue. I have made the changes suggested in the GitHub thread.

I added:

appdaemon:
  app_dir: /homeassistant/appdaemon/apps
  exclude_dirs:
    - cx_core

I have the controllerx directory located at /config/appdeamon/apps/controllerx

I take it that is the location of the app_dir entry. That is where HACS is installing the beta update as far as I can see. However, I noticed this in the Appdeamon add-on log:

025-06-09 23:49:40.768905 WARNING AppDaemon: No apps found in /homeassistant/appdaemon/apps. This is probably a mistake

Not sure what the mistake is.

I have to confess that I am confused about the directory structure since we made the change to moving appdaemon to the addon_configs directory. I see that appdaemon.yaml is in the addon_configs directory, and I should make any changes to the configuration there. And I know the a0d7b954_appdaemon/apps/apps.yaml is where I add/edit my devices. Can I now delete the old appdaemon directory under homeassistant? Is that directory just a leftover from the previous install and now unused?

Here’s what I see in my tree:
/
├─ addon_configs/
│ ├─ a0d7b954_appdaemon/
│ │ ├─ appdaemon.yaml
│ │ ├─ apps/
│ │ │ ├─ controllerx/
│ │ │ │ ├─ controllerx.py
│ │ │ │ ├─ cx directories & files/
│ │ │ ├─ hello.py
│ │ │ ├─ apps.yaml
│ │ ├─ compiled/
│ │ ├─ dashboards/
│ │ ├─ namespaces/
│ │ ├─ www/
├─ homeassistant/
│ ├─ appdaemon/
│ │ ├─ apps/
│ │ │ ├─ controllerx/
│ │ │ │ ├─ controllerx.py
│ │ │ │ ├─ cx directories & files

Oh! I think I found my own answer in the thread https://github.com/xaviml/controllerx/discussions/874

My understanding from that thread is that ControllerX has to he in the homeassistant folder in order to be distributed by HACS, but appdaemon is installed directly under config as best practices.

So you do need both directory locations (?)

Here you find the answer to your question:
https://community.home-assistant.io/t/controllerx-bring-full-functionality-to-light-and-media-player-controllers/148855/1499

1 Like

My money is on hello.py:

ModuleNotFoundError: No module named 'hello'
The above exception was the direct cause of the following exception:
Traceback (most recent call last):
  File "/usr/lib/python3.12/site-packages/appdaemon/exceptions.py", line 158, in wrapper
    return await func(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3.12/site-packages/appdaemon/app_management.py", line 1126, in safe_import
    raise ade.FailedImport(module_name, self.AD.app_dir) from e
appdaemon.exceptions.FailedImport: Failed to import 'hello'
Import paths:
  /homeassistant/appdaemon/apps
  /homeassistant/appdaemon/apps/controllerx
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
  File "/usr/lib/python3.12/site-packages/appdaemon/__main__.py", line 157, in run
    loop.run_until_complete(asyncio.gather(*pending))
  File "uvloop/loop.pyx", line 1518, in uvloop.loop.Loop.run_until_complete
  File "/usr/lib/python3.12/site-packages/appdaemon/utility_loop.py", line 148, in loop
    await self.AD.app_management.check_app_updates(mode=UpdateMode.INIT)
  File "/usr/lib/python3.12/site-packages/appdaemon/app_management.py", line 839, in check_app_updates
    await self._import_modules(update_actions)
  File "/usr/lib/python3.12/site-packages/appdaemon/app_management.py", line 1128, in _import_modules
    await safe_import(self)
  File "/usr/lib/python3.12/site-packages/appdaemon/exceptions.py", line 160, in wrapper
    user_exception_block(logger, e, app_dir, header)
  File "/usr/lib/python3.12/site-packages/appdaemon/exceptions.py", line 94, in user_exception_block
    file = Path(frame.filename).relative_to(app_dir.parent)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3.12/pathlib.py", line 682, in relative_to
    raise ValueError(f"{str(self)!r} is not in the subpath of {str(other)!r}")
ValueError: '<frozen importlib._bootstrap>' is not in the subpath of '/homeassistant/appdaemon'
2025-06-30 23:40:55.035664 INFO AppDaemon: Previous message repeated 1 times
[23:40:55] INFO: Service AppDaemon exited with code 0 (by signal 0)
[23:40:56] INFO: Starting AppDaemon...

I have an interesting issue with one controller Ikea Trådfri E2002. I have four of these but for one of them the behavior is not as expected on double pression.

Instead of pressing twice for the second option I have to press three to four times to get the desired result

stue_kntkt_app:
  module: controllerx
  class: E2002LightController
  controller: sensor.sofa_ny_action
  integration: z2m
  light: light.sofagruppe
  multiple_click_delay: 500 # default
  merge_mapping:
    on$2: 
      service: light.turn_on
      data:
         entity_id: light.spisebord
    off$2: 
      service: light.turn_off
      data:
         entity_id: light.spisebord
    arrow_left_click$2: 
      service: switch.toggle
      data:
         entity_id: switch.innr_2
    arrow_right_click$2: 
      service: switch.toggle
      data:
         entity_id: switch.innr_1

Have anyone else had this issue and if so what was the solution.
I have tried replacing the unit - same result, which for me indicates it’s an issue in the code.

A similar setup that works:

iris_standerlampe_app: 
  module: controllerx
  class: E2002LightController
  controller: sensor.iris_kontakt_standerlampe_z2m_action
  integration: z2m
  light: light.iris_standerlampe_z2m
  multiple_click_delay: 500 # default
  merge_mapping:
    on$2: 
      service: light.turn_on
      data:
         entity_id: light.iris_hyggelampe
    off$2: 
      service: light.turn_off
      data:
         entity_id: light.iris_hyggelampe

There is a problem with version 0.17.11 of the AppDaemon add-on; ControlerX does not start. Restore to 0.17.10 and it is OK.

@xaviml and controllerX peoples - I’m seeing something weird which I can’t get my head around, and it’s driving me nuts.

I’ve just switched my set-up from a Conbee II to a ZBT-2 as zigbee adaptor (and from deconz to zha via the procedure here), and so am now reconfiguring my network and ControllerX set-up to match.

Generally it’s working, but one switch is giving me headaches.
My current apps.xml file entry (in /homeassistant/appdaemon/apps/) is as follows:

study_switch:
  module: controllerx
  class: E1743MediaPlayerController
  controller: 84:2e:14:ff:fe:b0:7a:cc
  integration: zha
  media_player: media_player.radiopizero
  merge_mapping:
    on:
      service: script.toggle_rp0
    off:
      service: script.toggle_sonoff
    move_with_on_off_0_83:
      service: script.reset_rp0
    move_1_83_0_0:
      service: script.reset_rp0

And looking in the appdaemon addon log, I see this when short and long pressing 0 and 1 on the switch:

2026-01-10 15:26:30.412267 INFO study_switch: 🎮 Button event triggered: `off`
2026-01-10 15:26:30.429757 INFO study_switch: 🏃 Running `Service (script.toggle_rp0)` now
2026-01-10 15:26:30.437758 INFO study_switch: 
🤖 Service: script.toggle_rp0
2026-01-10 15:26:36.117304 INFO study_switch: 🎮 Button event triggered: `on`
2026-01-10 15:26:36.131528 INFO study_switch: 🏃 Running `Service (script.toggle_sonoff)` now
2026-01-10 15:26:36.137797 INFO study_switch: 
🤖 Service: script.toggle_sonoff
2026-01-10 15:26:40.297760 INFO study_switch: 🎮 Button event triggered: `move_1_83_0_0`
2026-01-10 15:26:40.314016 INFO study_switch: 🏃 Running `Predefined (hold_volume_down)` now
2026-01-10 15:26:40.368806 INFO study_switch: 
🤖 Service: media_player.volume_set
  - entity_id: media_player.radiopizero
  - volume_level: 0.45
2026-01-10 15:26:40.877401 INFO study_switch: 🎮 Button event triggered: `stop_with_on_off`
2026-01-10 15:26:40.890353 INFO study_switch: 🏃 Running `Predefined (release)` now
2026-01-10 15:26:43.275864 INFO study_switch: 🎮 Button event triggered: `move_with_on_off_0_83`
2026-01-10 15:26:43.291662 INFO study_switch: 🏃 Running `Predefined (hold_volume_up)` now
2026-01-10 15:26:43.323634 INFO study_switch: 
🤖 Service: media_player.volume_set
  - entity_id: media_player.radiopizero
  - volume_level: 0.55
2026-01-10 15:26:43.748418 INFO study_switch: 🎮 Button event triggered: `stop_with_on_off`
2026-01-10 15:26:43.764557 INFO study_switch: 🏃 Running `Predefined (release)` now

Two things of note - the “off” and “on” event actions are swapped, and the other two are doing their default mappings and ignoring the remaps in apps.xml. Originally the “off” and “on” actions were set up as per the log, but I swapped them over as a test.

I also see the below lines in the appdaemon log which may or may not have something to do with all this. It appears whenever I change and save apps.xml.

2026-01-10 15:26:22.653217 WARNING AppDaemon: ------------------------------------------------------------
2026-01-10 15:26:22.654147 WARNING AppDaemon: Unexpected error during utility()
2026-01-10 15:26:22.654993 WARNING AppDaemon: ------------------------------------------------------------
2026-01-10 15:26:22.660003 WARNING AppDaemon: Traceback (most recent call last):
  File "/usr/lib/python3.12/site-packages/appdaemon/utility_loop.py", line 246, in _loop_iteration_context
    yield timing
  File "/usr/lib/python3.12/site-packages/appdaemon/utility_loop.py", line 197, in loop
    await self.AD.app_management.check_app_updates()
  File "/usr/lib/python3.12/site-packages/appdaemon/app_management.py", line 898, in check_app_updates
    await self.check_app_config_files(update_actions)
  File "/usr/lib/python3.12/site-packages/appdaemon/app_management.py", line 704, in check_app_config_files
    if not utils.deep_compare(current_app, prev_app):
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3.12/site-packages/appdaemon/utils.py", line 432, in deep_compare
    if deep_compare(v, data[k]):
       ^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3.12/site-packages/appdaemon/utils.py", line 431, in deep_compare
    if isinstance(v, dict) and isinstance(data[k], dict):
                                          ~~~~^^^
KeyError: True
2026-01-10 15:26:22.660897 WARNING AppDaemon: ------------------------------------------------------------

One final point I see in the log is this when I (re)start HA:

2026-01-10 15:22:59.162678 INFO HASS: Connected to Home Assistant 2026.1.0 with aiohttp websocket
2026-01-10 15:22:59.167950 INFO HASS: Authenticated to Home Assistant 2026.1.0
2026-01-10 15:22:59.251939 INFO HASS: Waiting for Home Assistant to start
2026-01-10 15:22:59.543543 INFO HASS: Completed initialization in 441ms
2026-01-10 15:22:59.800870 INFO AppDaemon: Processing restart for plugin namespace 'default'
2026-01-10 15:22:59.804856 INFO AppDaemon: Starting apps: ['kitchen_controller', 'n2_controller', 'study_controller', 'study_switch', 'lounge_switch', 'kitchen_remote', 'breakfast_remote', 'study_remote', 'christmas_switch']
2026-01-10 15:22:59.875032 INFO AppDaemon: Calling initialize() for kitchen_controller
2026-01-10 15:22:59.885695 INFO kitchen_controller: 🎮 ControllerX v5.2.2
2026-01-10 15:23:00.081740 INFO AppDaemon: Calling initialize() for n2_controller
2026-01-10 15:23:00.091215 INFO n2_controller: 🎮 ControllerX v5.2.2
2026-01-10 15:23:00.245947 INFO AppDaemon: Calling initialize() for study_controller
2026-01-10 15:23:00.256606 INFO study_controller: 🎮 ControllerX v5.2.2
2026-01-10 15:23:00.462665 INFO AppDaemon: Calling initialize() for study_switch
2026-01-10 15:23:00.470901 INFO study_switch: 🎮 ControllerX v5.2.2
2026-01-10 15:23:00.577583 INFO AppDaemon: Calling initialize() for lounge_switch
2026-01-10 15:23:00.586077 INFO lounge_switch: 🎮 ControllerX v5.2.2
2026-01-10 15:23:00.650837 INFO AppDaemon: Calling initialize() for kitchen_remote
2026-01-10 15:23:00.660041 INFO kitchen_remote: 🎮 ControllerX v5.2.2
2026-01-10 15:23:00.863812 INFO AppDaemon: Calling initialize() for breakfast_remote
2026-01-10 15:23:00.874129 INFO breakfast_remote: 🎮 ControllerX v5.2.2
2026-01-10 15:23:01.049661 INFO AppDaemon: Calling initialize() for study_remote
2026-01-10 15:23:01.058629 INFO study_remote: 🎮 ControllerX v5.2.2
2026-01-10 15:23:01.246565 INFO AppDaemon: Calling initialize() for christmas_switch
2026-01-10 15:23:01.256296 INFO christmas_switch: 🎮 ControllerX v5.2.2

The point there is that ‘kitchen_controller’, ‘n2_controller’ and ‘study_controller’ are all old names from the previous Conbee II (deconz) network (they are currently kitchen_remote, breakfast_remote and study_remote, which you can see further down) and do not now feature in apps.xml at all (they got renamed to the newer entities listed).

So it looks like perhaps there’s some cached or legacy settings getting mixed in somewhere?
I did find another apps.xml file in /addon_configs/a0d7b954_appdaemon/apps/ , but I’ve removed that (and replaced it with a symlink to the one above) and it’s not helped anything.

Does anyone have any clue what may be going on here and how to restore sanity (HA’s and mine)?

Hello,

I’m not sure if this relates to your issue, but just in case it does and that you haven’t fixed it yet.

I ran into similar error loops in my appdaemon logs. It was ControllerX, which somehow had gotten removed from HACS at some point. I re-downloaded it, but then discovered the config changed a little. ControllerX was downloaded to the /config/appdaemon/apps directory, but appdaemon now wants to be in the /addon_configs/appdaemon/apps directory.

So I copied my apps.yaml file from /addon_configs/appdaemon/apps back to /config/appdaemon/apps (it wasn’t there anymore), and - strangely - added 1 line to the appdaemon.yaml file in addon_config, under the appdaemon: key

appdaemon:
app_dir: /homeassistant/appdaemon/apps

This apparently seems to solve the looping errors in the logs. I haven’t had a chance to test out the controllers yet though, as I’m having trouble re-installing Alexa Media Player.

Don’t quote me on any of this, just offering it up just in case it might help along the way.

Best,
-Kevin

Thanks for that.

In the end, I found that I had a backup appdaemon folder in my config (in parallel with the main one), and it looks like appdaemon was also picking up the apps.yaml file that was in there (it seems to inhale any version of apps.yaml that it can find anywhere).

I did also find the addon_configs one - currently I have a symbolic link in that folder back to the apps.yaml file in the main folder (/homeassistant/appdaemon/apps and /config/appdaemon/apps are actually the same folder it seems from some testing).

Currently things are working OK, except I can’t get long-press to work on the Ikea switch under zha (it used to work under deconz). I’ve got the entries in the apps.yaml file and appdaemon doesn’t throw any errors, but it also seems to just ignore those entries (although on and off on the same switch both remap correctly) and performs the default actions (volume up and down in this case).

I have a issue with E1766 controller. I like to move forward to mqtt configuration. But what ever i do it does not move my blind Kardijl.
the deprectated configuration works fine. Here is the configuration:

Kitchenblind_app:
module: controllerx
class: E1766CoverController
controller: kitchen_blind_controller
integration:
name: z2m
listen_to: mqtt
cover: cover.kitchen_blind
no errors in the log. 22m logs show the commands and also mqttexplorer sees the event. but in appdeamon nothing happens

Thanks for helping