Ha_openems: Fenecon FEMS and OpenEMS integration

Thanks for the quick reply @Scritch & @romal! I did what you suggested, updated to the latest release and updated the config entries as suggested in the documentation. I saw a new device “ctrlIoHeatingElement0”. After activating the 2 entities, 15 more showed up (16 sensors & 1 switch):

So far so good! Now, what I’m actually trying to do is manually activating the heating rod in the early morning if the SOC of the battery is above a certain value. For that I need to be able to activate the manual mode and the desired level of heating (1-3) like in the FEMS UI:

Please let me know what kind of information you need from my side to add switch and select entities to your integration.

Thank you & best regards!

Idea:

  1. You: Operate the FEMS WebUI, try all options. In parallel, record the WebSocket communication and send it to to me
  2. Me: Analyze the communication, adjust integration entity mappings, create preview version for you
  3. You: Test the preview, share feedback.

We might need a few iterations to have it fully working :slight_smile:

Regarding the first step, please do this in chrome (as only chrome allows to properly export the communication in a later step). If you never use the chrome dev tools before, I found the following extensive howto: https://developer.chrome.com/docs/devtools/network. In short: Open Inspector view, select the network tab, filter for WebSocket communication.
Then, open the FEMS WebUI and change the heating rod configuration for all options which are supported by the UI. When done, export the communication as an HAR file. Then share the file with me.

I recommend we continue in a github issue to avoid spamming the thread here. If you don’t have a github account and you don’t want to create one, we can also use personal messages of this community.

Ok, I have created an issue on github (Link) and uploaded the .har file there.

Hi,

today I tried to migrate my Fenecon2mqtt installation to the HA_openems addon, but I’m getting an error: “Cannot read edge components” when adding a new device with the IP of my FEMS:

In the FEMS log, the following error message appears when I try to connect:

[ctrlApiWebsocket0] User [User [id=guest, name=Guest]] closed websocket connection.
4.8.2025, 17:25:30
WARN
io.openems.common.websocket.OnMessageHandler
[ctrlApiWebsocket0] JSON-RPC Error "Unable to find OpenEMS Component with ID [ctrlFixActivePower0]" for Request {"method":"edgeRpc","params":{"edgeId":"0","payload":{"method":"componentJsonApi","params":{"componentId":"_componentManager","payload":{"method":"getChannelsOfComponent","params":{"componentId":"c...
4.8.2025, 17:25:30
ERROR
io.openems.edge.common.jsonapi.JsonApiBuilder
Unable to find OpenEMS Component with ID [ctrlFixActivePower0]
4.8.2025, 17:25:29
INFO
io.openems.edge.controller.api.websocket.handler.AuthenticationRequestHandler
User [guest:Guest] connected.
4.8.2025, 17:25:29
INFO
io.openems.edge.core.user.UserServiceImpl

I also tried the local monitoring connection option with the same result.

Any idea what the problem could be?

A bit of a shot into the dark, but it is worth a try: Can you test the initialization with v1.0.4 and check if this version (prerelease) is able to handle the problem gracefully?

Unfortunately not — I’m now getting the error “unknown error occurred”, but the same log entry in the FEMS log as before:

7.8.2025, 00:13:12
WARN
io.openems.common.websocket.OnMessageHandler
[ctrlApiWebsocket0] JSON-RPC Error "Unable to find OpenEMS Component with ID [ctrlFixActivePower0]" for Request {"method":"edgeRpc","params":{"edgeId":"0","payload":{"method":"componentJsonApi","params":{"componentId":"_componentManager","payload":{"method":"getChannelsOfComponent","params":{"componentId":"c...
7.8.2025, 00:13:11
ERROR
io.openems.edge.common.jsonapi.JsonApiBuilder
Unable to find OpenEMS Component with ID [ctrlFixActivePower0]
7.8.2025, 00:13:11
INFO
io.openems.edge.controller.api.websocket.handler.AuthenticationRequestHandler

It might be worth mentioning that the Fenecon system in question is not the Home version, but rather its predecessor, with a Kaco inverter and BYD storage (Pro Hybrid 10 series).

Please enable the integrations debug logging in home assistant and share the output with me.

Is this the log you are looking for?

2025-08-07 21:49:27.752 DEBUG (MainThread) [custom_components.openems.openems] SubscriptionUpdater start
2025-08-07 21:49:28.336 ERROR (MainThread) [aiohttp.server] Error handling request from ........
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 83, 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/ban.py", line 86, in ban_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 227, 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 487, in _async_handle_step
    result: _FlowResultT = await getattr(flow, method)(user_input)
                           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/config/custom_components/openems/config_flow.py", line 224, in async_step_user
    return await self._create_or_update_entry(backend)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/config/custom_components/openems/config_flow.py", line 246, in _create_or_update_entry
    components = await asyncio.wait_for(
                 ^^^^^^^^^^^^^^^^^^^^^^^
    ...<2 lines>...
    )
    ^
  File "/usr/local/lib/python3.13/asyncio/tasks.py", line 507, in wait_for
    return await fut
           ^^^^^^^^^
  File "/config/custom_components/openems/openems.py", line 910, in read_edge_components
    return await self.the_edge.read_components()
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/config/custom_components/openems/openems.py", line 573, in read_components
    await self._read_edge_channels(components)
  File "/config/custom_components/openems/openems.py", line 583, in _read_edge_channels
    for componentId in components:
                       ^^^^^^^^^^
RuntimeError: dictionary changed size during iteration
2025-08-07 21:49:28.341 DEBUG (MainThread) [custom_components.openems.openems] SubscriptionUpdater end

Yes, exactly.

I made a relatively easy mistake, but it just happens when you have no means to test new code :slight_smile:

I have fixed and create v1.0.4a. Please try again. If it still fails, please post the updated log.

With the new version v1.0.4a, all devices configured in FEMS have been added, and at first glance, all data is there :slight_smile:
Many thanks for the quick support!
Next, I’ll start configuring all automations etc. to use the new entities, and then I’ll look into how to edit the statistics with the old data.

I recently upgraded my Hardy Barth Wallbox to support dynamic phase switching and was positively surprised when I noticed that it is fully supported by FEMS / OpenEMS.

However, the integration did not yet properly recognize and process the resulting dynamic entity config changes.

I have added the required feature with version v1.1.0 and uploaded the new pre-release some minutes ago.

Does the integration fallsback to local monitoring if the fenecon API is not available? (for example if the internet connection is down)

It always uses the local connection to the websocket if you set it up with the local IP.
For user you can use x and for password user or owner (if you also want to have write access)

1 Like

OHH I did not knew about the owner one, thanks!

1 Like

Just as an idea: try reading the manual. :wink:

Yes sorry, I understood the " For local monitoring, common values are user or owner" as “Sometimes it is user and sometimes it is owner

Okay, thx for the feedback. I will improve it and make it clear.

Hi! Is there a way to control the heating rod with OpenEMS?

There was an initial attempt to get the heating rod config working. However, since I don’t have a test environment, I rely on feedback from tester.

I have rebased the related config changes to the most recent version of the integration: Release heating_rod · Lamarqe/ha_openems · GitHub

If this works correctly, I can merge the changes to the main branch.

1 Like

Thanks! I will do my best to test it :slight_smile: