Rademacher DuoFern USB-Stick Integration (HACS)

Hi everyone! :wave:

I’d like to share a custom integration I’ve built for Rademacher DuoFern roller shutters, controlled locally through the DuoFern USB stick (model 7000 00 93).

What it does

This integration communicates directly with the DuoFern USB stick using the native serial protocol — no cloud, no additional gateway, fully local.

Features:

  • Open / Close / Stop / Set Position for roller shutters
  • Real-time position reporting (push-based, no polling)
  • USB auto-discovery
  • Config flow with 2-step setup (connection + device registration)
  • Options flow for adding/removing devices after initial setup
  • Standalone CLI tools for testing and device pairing (no FHEM needed)

Supported Devices

Primarily RolloTron roller shutter actuators (types 0x40–0x70), including RolloTron Standard, Comfort, and Pro models.

Why I built this

I was running FHEM for years just to control my DuoFern shutters, but wanted to move everything into Home Assistant natively. Since there was no existing HA integration for DuoFern USB stick control, I implemented the serial protocol from scratch (based on analysis of the FHEM Perl modules) as a proper HA custom component with config flow, push-based updates, and full HACS support.

Installation (via HACS)

  1. Open HACS → three dots menu → Custom repositories
  2. Add https://github.com/MSchenkl/homeassistant-duofern with category Integration
  3. Search for “Rademacher DuoFern” and install
  4. Restart Home Assistant
  5. Go to Settings → Devices & Services → Add Integration → DuoFern

Links

If you’re using Rademacher DuoFern shutters with the USB stick, give it a try! Feedback, bug reports, and contributions are very welcome. :slightly_smiling_face:

1 Like

Hi Mark,

Thanks for your new Duofern USB stick HA integration, I’m very curious to test it out :slight_smile:
did you know there was already a Duofern HA HACS integration for HA called PyDuofernHacs ?

it’s derived from GitHub - gluap/pyduofern which on it’s turn is derived with
reverse engineering on the original FHEM Duofern Perl code.

Why did you write your own version ? Has your integration advantages over PyDuofern ?
Will you be added Sun sensors also ?
Binary sensors & devices were all documentated in the FHEM source code.
It’s even in the PyDuofern code, so maybe you could check there.

I think PyDuofern is polling based while your’s is push based according to your documentation.
I’ve been using PyDuofern ever since I also switches from FHEM to HA years ago. It has been working great with some up- & downsides. Sometimes Roller Shutters did not react or were not in sync, also on HA reboot status was not correct and you had to add extra HA reboot automations that triggered: duofern.set_update_interval (0) action.

Since last years there were some extra features added like sun mode and other “mode” toggle buttons for each Roller Shutter. Also Sun sensors (binary state sensors) were addon.
They worked on my Solar powered Sun sensor Rademacher: “DuoFern Sonnensensor 9478” :


it’s not visible anymore on: Übersicht Sensoren Rollladen und Sonnenschutz - Rademacher because it’s replaced by a battery powered sun sensor.

I installed your new integration (added it in HACS and rebooted HA).
I did not add the new integration yet in “Devices”, what I already noticed was that my existing running PyDuofern integration stopped working.
I removed my PyDuofern integration, rebooted and added under devices your integration.
After adding the network key code, USB serial port path and added comma spaced Duofern device ID’s, your integration worked immediatly. I can control my shutters (open/close, position).
At first glance it seems snappier than PyDuofern, so I’ll be using/testing it further.
I also like the fact your integration does not rely on seperate python libraries like PyDuofernHACS does on PyDuofern.

Since the Rademacher Duofern USB stick is obsolete (you can’t find or buy it anymore) I was looking in other “backup” solutions into controlling my Duofern roller shutters for when my USB stick dies.

I’ve been develloping my own ESP32 chip based control for it using a NRF905 transceiver:


This sends complete Duofern packages into the air (parallel next to my HA USB stick).
At the moment the ESP32 chip used an internal on-board website for control & testing, but in the end it will be fully HA controllable over MQTT or WebAPI.

There are indeed some “quirks” in the whole handshake procedure. I notice when I send Duofern messages by ESP32 my existing PyDuofern integration lost it’s handshake and had to rehandshake.
My ESP32 also does some handshaking & resending when receiving not ACKED telegrams & get’s ACKED after some extra telegrams.

Hi Monty,

Thanks for your message and for trying out the integration — great to hear it’s working well for you!

Yes, I was aware of PyDuofern and PyDuofernHACS. In fact, I studied both the PyDuofern code and the original FHEM Perl source (10_DUOFERN.pm and 10_DUOFERNSTICK.pm) extensively during development. I decided to write a new integration from scratch for several reasons:

Why not PyDuofern?

  1. Abandoned project — PyDuofern’s last PyPI release was in 2020 and the library has had no meaningful maintenance since. It doesn’t support Python 3.12+ cleanly and triggers deprecation warnings with current asyncio APIs.
  2. Threading-based architecture — PyDuofern uses background threads for serial communication and then bridges into asyncio with call_soon_threadsafe. Home Assistant’s architecture is fully async, and mixing threads with HA’s event loop creates subtle race conditions, especially during startup and shutdown.
  3. Ghost device bug — PyDuofern persists device state to JSON files. After removing or re-pairing a device, the old state can reappear after a restart because the JSON cache isn’t properly invalidated. This also explains the stale status you described after HA reboots.
  4. No support for 10-digit device codes — Newer DuoFern firmware uses extended 10-digit device identifiers. PyDuofern only handles the classic 6-digit format.
  5. Silent command failures — PyDuofern doesn’t verify whether commands were actually acknowledged by the stick. Commands can silently fail without any feedback to the user or HA, which is likely what caused your “roller shutters did not react” issues.
  6. Separate library dependency — PyDuofernHACS depends on the PyDuofern library as a separate package, adding another layer of indirection and potential version conflicts.

Advantages of this integration:

  • Pure async — Direct asyncio.Protocol for serial communication, no threads. This integrates cleanly with HA’s event loop and makes it genuinely push-based (as you noticed).
  • Push-based status — No polling interval needed. The stick sends status frames whenever a device changes state (after commands, after movement completes, etc.). The only “poll” is a single status broadcast during initialization to get the current state of all devices.
  • Optimistic updates — When you send a command, the UI updates immediately without waiting for the device to confirm, which is why it feels snappier.
  • Type-safe protocol layer — All DuoFern frames are parsed into typed Python dataclasses with proper validation, not raw byte arrays with magic offsets.
  • Self-contained — No external library dependency beyond pyserial. All protocol logic is built into the integration itself, so there’s no version mismatch risk.
  • Coordinator pattern — Uses HA’s DataUpdateCoordinator properly, which ensures clean startup/shutdown and correct entity lifecycle management.

Sun sensors:

Good question! The protocol layer already decodes sun-related status fields from cover status frames (sun_automatic, sun_mode, sun_position, dawn_automatic, dusk_automatic). And the device type registry already recognizes sun sensor types (0xA5, 0xA9, 0xAF). However, no HA entities surface this data yet — right now only cover entities are implemented.

Adding binary sensors for sun mode states and sensor entities for sun position is definitely on the roadmap. If you have a DuoFern sun sensor (like your 9478) and would be willing to help test, that would be very helpful! I’d need to see what status frames the sun sensor sends to make sure the parsing is correct.

Regarding the USB stick conflict:

That’s expected behavior — both integrations try to open the same serial port exclusively. Only one integration can control the stick at a time. Glad to hear removing PyDuofern and adding this one went smoothly.

Regarding backup solutions:

Since you mentioned looking for alternatives in case your USB stick dies — I’m in the same situation. The DuoFern USB stick (both model 7000 and 9000) is discontinued. If you find any interesting alternatives, I’d love to hear about them.

Thanks again for the detailed feedback — it’s really helpful to hear from someone who has used PyDuofern for years and can compare directly!

Best regards,
Mark

Hi Mark,

I really like your new Duofern integration :slight_smile:
it’s more neatly and self contained (not dependant on external python libraries like PyDuofern) like you wrote.
Also I like the push based status instead of polling and the Async communication instead of thread based stuff like PyDuofern.

Sure i’m willing to provide Duofern logs for Sun sensors. (I only have 2 9478’s)
and willing to help test it out.

Below is my “bare” Duofern log my ESP32 Duofern application captures when the solar sensor trips to Sun state or No Sun state.

6F1234 is my network key and A524A8 is my 9478 Sun sensor (solar powered).

“6F1234 A524A8 00 0015BF 142011 FF070801FF0100000000000000 1B525687BA0B”,
“6F1234 A524A8 00 0015BF 242011 FF070801FF0100000000000000 7E219F834A7F”,
“6F1234 A524A8 00 0015C0 042011 FF070801FF0100000000000000 CD4327D50969”,
“6F1234 A524A8 00 0015C0 142011 FF070801FF0100000000000000 C2176BEE7D68”,
“6F1234 A524A8 00 0015C1 042011 FF070801FF0100000000000000 B3E8B84ECBFA”,
“A524A8 6F1234 02 0015C2 042011 FF070801FF0100000000000000 908BA4DB4A47”,
“A524A8 6F1234 03 0015C0 032011 FF070801FF0100000000000000 136FF60E7E33”,
“6F1234 A524A8 00 0015C3 042011 FF070801FF0100000000000000 E9F1F2A31D7C”,
“A524A8 6F1234 02 0015C4 032011 FF070801FF0100000000000000 2103666E0A08”,
“6F1234 A524A8 00 0015C5 042011 FF070A01000100000000000000 234444292FD8”,
“A524A8 6F1234 02 0015C6 032011 FF070A01000100000000000000 5B56B8F41C64”,
“6F1234 A524A8 00 0015C7 042011 FF070801FF0100000000000000 75C65684BA4C”,
“6F1234 A524A8 00 0015C7 142011 FF070801FF0100000000000000 9C6E977D65B8”,
“A524A8 6F1234 02 0015C8 032011 FF070801FF0100000000000000 ADD8CA4FA7D8”,
“6F1234 A524A8 00 0015C9 042011 FF070A01000100000000000000 8721E1FDCDFA”,
“A524A8 6F1234 02 0015CA 042011 FF070A01000100000000000000 C9B449E749EE”,
“A524A8 6F1234 02 0015CA 032011 FF070A01000100000000000000 BF3355C8BA86”,

For comparison 407F0E is my one Rollotron attached at the moment. (think it’s a 1200 model, not sure)
You will recogize the different Duofern status stuff in the 6’th string part.
In the 4’th string part you see the incrementing counter.

I can also see “unhandled” duofern messages in your Duofern logs like:
Unhandled message type 0x0F: 0FFF070A0100010000000000000001A524A86F123400

2026-02-26 08:44:53.832 WARNING (SyncWorker_0) [homeassistant.loader] We found a custom integration duofern which has not been tested by Home Assistant. This component might cause stability problems, be sure to disable it if you experience issues with Home Assistant
2026-02-26 08:45:14.096 INFO (MainThread) [custom_components.duofern] Setting up DuoFern integration: port=/dev/ttyUSB5, system_code=6F1234, devices=2
2026-02-26 08:45:14.104 INFO (MainThread) [custom_components.duofern.stick] Connecting to DuoFern stick on /dev/ttyUSB5 (system code: 6F1234)
2026-02-26 08:45:14.113 DEBUG (MainThread) [custom_components.duofern.stick] Serial port opened: /dev/ttyUSB5
2026-02-26 08:45:14.113 DEBUG (MainThread) [custom_components.duofern.stick] Init attempt 1/4
2026-02-26 08:45:14.113 DEBUG (MainThread) [custom_components.duofern.stick] TX: 01000000000000000000000000000000000000000000
2026-02-26 08:45:14.114 DEBUG (MainThread) [custom_components.duofern.stick] Serial connection established
2026-02-26 08:45:14.128 DEBUG (MainThread) [custom_components.duofern.stick] TX: 0E000000000000000000000000000000000000000000
2026-02-26 08:45:14.144 DEBUG (MainThread) [custom_components.duofern.stick] TX: 0A6F1234000100000000000000000000000000000000
2026-02-26 08:45:14.176 DEBUG (MainThread) [custom_components.duofern.stick] TX: 81000000000000000000000000000000000000000000
2026-02-26 08:45:14.176 DEBUG (MainThread) [custom_components.duofern.stick] TX: 14140000000000000000000000000000000000000000
2026-02-26 08:45:14.207 DEBUG (MainThread) [custom_components.duofern.stick] TX: 81000000000000000000000000000000000000000000
2026-02-26 08:45:14.213 DEBUG (MainThread) [custom_components.duofern.stick] TX: 0300407F0E0000000000000000000000000000000000
2026-02-26 08:45:14.231 DEBUG (MainThread) [custom_components.duofern.stick] TX: 81000000000000000000000000000000000000000000
2026-02-26 08:45:14.231 DEBUG (MainThread) [custom_components.duofern.stick] TX: 0301A524A80000000000000000000000000000000000
2026-02-26 08:45:14.270 DEBUG (MainThread) [custom_components.duofern.stick] TX: 81000000000000000000000000000000000000000000
2026-02-26 08:45:14.270 DEBUG (MainThread) [custom_components.duofern.stick] TX: 10010000000000000000000000000000000000000000
2026-02-26 08:45:14.294 DEBUG (MainThread) [custom_components.duofern.stick] TX: 81000000000000000000000000000000000000000000
2026-02-26 08:45:14.300 DEBUG (MainThread) [custom_components.duofern.stick] TX: 0DFF0F400000000000000000000000000000FFFFFF01
2026-02-26 08:45:14.340 DEBUG (MainThread) [custom_components.duofern.stick] TX: 81000000000000000000000000000000000000000000
2026-02-26 08:45:14.346 INFO (MainThread) [custom_components.duofern.stick] DuoFern stick init complete (attempt 1)
2026-02-26 08:45:14.350 INFO (MainThread) [custom_components.duofern.stick] DuoFern stick initialized successfully
2026-02-26 08:45:14.351 INFO (MainThread) [custom_components.duofern.coordinator] DuoFern coordinator connected
2026-02-26 08:45:15.022 DEBUG (MainThread) [custom_components.duofern.stick] RX: 0FFF0F210000640000004100120000407F0E6F123401
2026-02-26 08:45:15.029 DEBUG (MainThread) [custom_components.duofern.stick] TX: 81000000000000000000000000000000000000000000
2026-02-26 08:45:15.034 DEBUG (MainThread) [custom_components.duofern.coordinator] Status update for 407F0E: position=0, moving=stop
2026-02-26 08:45:15.034 DEBUG (MainThread) [custom_components.duofern.coordinator] Manually updated duofern data
2026-02-26 08:45:27.678 DEBUG (MainThread) [custom_components.duofern.cover] Adding cover entity for device 407F0E
2026-02-26 08:45:27.700 WARNING (MainThread) [homeassistant.helpers.frame] Detected that custom integration 'duofern' calls `device_registry.async_get_or_create` referencing a non existing `via_device` ('duofern', '6F1234'), with device info: {'identifiers': {('duofern', '407F0E')}, 'manufacturer': 'Rademacher', 'model': 'RolloTron Standard', 'name': 'DuoFern RolloTron Standard (407F0E)', 'sw_version': None, 'via_device': ('duofern', '6F1234')} at custom_components/duofern/cover.py, line 59: async_add_entities(entities). This will stop working in Home Assistant 2025.12.0, please create a bug report at https://github.com/MSchenkl/homeassistant-duofern/issues
2026-02-26 08:45:27.701 INFO (MainThread) [custom_components.duofern.cover] Added 1 DuoFern cover entities
2026-02-26 09:36:36.353 DEBUG (MainThread) [custom_components.duofern.stick] RX: 0FFF070801FF010000000000000001A524A86F123400
2026-02-26 09:36:36.353 DEBUG (MainThread) [custom_components.duofern.stick] TX: 81000000000000000000000000000000000000000000
2026-02-26 09:36:36.354 DEBUG (MainThread) [custom_components.duofern.coordinator] Unhandled message type 0x0F: 0FFF070801FF010000000000000001A524A86F123400
2026-02-26 17:51:31.190 DEBUG (MainThread) [custom_components.duofern.stick] RX: 0FFF070A0100010000000000000001A524A86F123400
2026-02-26 17:51:31.190 DEBUG (MainThread) [custom_components.duofern.stick] TX: 81000000000000000000000000000000000000000000
2026-02-26 17:51:31.191 DEBUG (MainThread) [custom_components.duofern.coordinator] Unhandled message type 0x0F: 0FFF070A0100010000000000000001A524A86F123400
2026-02-26 19:00:27.937 DEBUG (MainThread) [custom_components.duofern.stick] Command queued: 0D01070300000000000000000000006F1234407F0E00 (queue size: 1)
2026-02-26 19:00:27.937 DEBUG (MainThread) [custom_components.duofern.coordinator] Manually updated duofern data
2026-02-26 19:00:27.939 DEBUG (MainThread) [custom_components.duofern.stick] TX: 0D01070300000000000000000000006F1234407F0E00
2026-02-26 19:00:27.939 DEBUG (MainThread) [custom_components.duofern.stick] Command sent: 0D01070300000000000000000000006F1234407F0E00
2026-02-26 19:00:30.265 DEBUG (MainThread) [custom_components.duofern.stick] RX: 810100BB00000000000000000000006F1234407F0E00
2026-02-26 19:00:30.266 DEBUG (MainThread) [custom_components.duofern.stick] ACK received for command
2026-02-26 19:00:57.883 DEBUG (MainThread) [custom_components.duofern.stick] RX: 0FFF0F210000640000004164120000407F0EFFFFFF01
2026-02-26 19:00:57.883 DEBUG (MainThread) [custom_components.duofern.stick] TX: 81000000000000000000000000000000000000000000
2026-02-26 19:00:57.884 DEBUG (MainThread) [custom_components.duofern.coordinator] Status update for 407F0E: position=100, moving=stop
2026-02-26 19:00:57.884 DEBUG (MainThread) [custom_components.duofern.coordinator] Manually updated duofern data
2026-02-27 07:02:05.887 DEBUG (MainThread) [custom_components.duofern.stick] Command queued: 0D01070100000000000000000000006F1234407F0E00 (queue size: 1)
2026-02-27 07:02:05.887 DEBUG (MainThread) [custom_components.duofern.coordinator] Manually updated duofern data
2026-02-27 07:02:05.888 DEBUG (MainThread) [custom_components.duofern.stick] TX: 0D01070100000000000000000000006F1234407F0E00
2026-02-27 07:02:05.888 DEBUG (MainThread) [custom_components.duofern.stick] Command sent: 0D01070100000000000000000000006F1234407F0E00
2026-02-27 07:02:08.213 DEBUG (MainThread) [custom_components.duofern.stick] RX: 810100BB00000000000000000000006F1234407F0E00
2026-02-27 07:02:08.213 DEBUG (MainThread) [custom_components.duofern.stick] ACK received for command
2026-02-27 07:02:41.768 DEBUG (MainThread) [custom_components.duofern.stick] RX: 0FFF0F210000640000004100120000407F0EFFFFFF01
2026-02-27 07:02:41.769 DEBUG (MainThread) [custom_components.duofern.stick] TX: 81000000000000000000000000000000000000000000
2026-02-27 07:02:41.769 DEBUG (MainThread) [custom_components.duofern.coordinator] Status update for 407F0E: position=0, moving=stop
2026-02-27 07:02:41.769 DEBUG (MainThread) [custom_components.duofern.coordinator] Manually updated duofern data
2026-02-27 07:41:22.043 DEBUG (MainThread) [custom_components.duofern.stick] Command queued: 0D01070100000000000000000000006F1234407F0E00 (queue size: 1)
2026-02-27 07:41:22.043 DEBUG (MainThread) [custom_components.duofern.coordinator] Manually updated duofern data
2026-02-27 07:41:22.045 DEBUG (MainThread) [custom_components.duofern.stick] TX: 0D01070100000000000000000000006F1234407F0E00
2026-02-27 07:41:22.045 DEBUG (MainThread) [custom_components.duofern.stick] Command sent: 0D01070100000000000000000000006F1234407F0E00
2026-02-27 07:41:22.138 DEBUG (MainThread) [custom_components.duofern.stick] RX: 810003CC00000000000000000000006F1234407F0E00
2026-02-27 07:41:22.138 DEBUG (MainThread) [custom_components.duofern.stick] ACK received for command
2026-02-27 09:39:32.427 DEBUG (MainThread) [custom_components.duofern.stick] RX: 0FFF070801FF010000000000000001A524A86F123400
2026-02-27 09:39:32.427 DEBUG (MainThread) [custom_components.duofern.stick] TX: 81000000000000000000000000000000000000000000
2026-02-27 09:39:32.427 DEBUG (MainThread) [custom_components.duofern.coordinator] Unhandled message type 0x0F: 0FFF070801FF010000000000000001A524A86F123400
2026-02-27 09:49:40.238 DEBUG (MainThread) [custom_components.duofern.stick] RX: 0FFF070801FF010000000000000001A524A86F123400
2026-02-27 09:49:40.239 DEBUG (MainThread) [custom_components.duofern.stick] TX: 81000000000000000000000000000000000000000000
2026-02-27 09:49:40.239 DEBUG (MainThread) [custom_components.duofern.coordinator] Unhandled message type 0x0F: 0FFF070801FF010000000000000001A524A86F123400
2026-02-27 12:49:36.582 DEBUG (MainThread) [custom_components.duofern.stick] RX: 0FFF070A0100010000000000000001A524A86F123400
2026-02-27 12:49:36.582 DEBUG (MainThread) [custom_components.duofern.stick] TX: 81000000000000000000000000000000000000000000
2026-02-27 12:49:36.583 DEBUG (MainThread) [custom_components.duofern.coordinator] Unhandled message type 0x0F: 0FFF070A0100010000000000000001A524A86F123400
2026-02-27 13:06:56.082 DEBUG (MainThread) [custom_components.duofern.stick] RX: 0FFF070801FF010000000000000001A524A86F123400
2026-02-27 13:06:56.082 DEBUG (MainThread) [custom_components.duofern.stick] TX: 81000000000000000000000000000000000000000000
2026-02-27 13:06:56.083 DEBUG (MainThread) [custom_components.duofern.coordinator] Unhandled message type 0x0F: 0FFF070801FF010000000000000001A524A86F123400
2026-02-27 13:32:39.288 DEBUG (MainThread) [custom_components.duofern.stick] RX: 0FFF070A0100010000000000000001A524A86F123400
2026-02-27 13:32:39.288 DEBUG (MainThread) [custom_components.duofern.stick] TX: 81000000000000000000000000000000000000000000
2026-02-27 13:32:39.289 DEBUG (MainThread) [custom_components.duofern.coordinator] Unhandled message type 0x0F: 0FFF070A0100010000000000000001A524A86F123400
2026-02-27 19:02:09.244 DEBUG (MainThread) [custom_components.duofern.stick] Command queued: 0D01070300000000000000000000006F1234407F0E00 (queue size: 1)
2026-02-27 19:02:09.245 DEBUG (MainThread) [custom_components.duofern.coordinator] Manually updated duofern data
2026-02-27 19:02:09.246 DEBUG (MainThread) [custom_components.duofern.stick] TX: 0D01070300000000000000000000006F1234407F0E00
2026-02-27 19:02:09.247 DEBUG (MainThread) [custom_components.duofern.stick] Command sent: 0D01070300000000000000000000006F1234407F0E00
2026-02-27 19:02:09.372 DEBUG (MainThread) [custom_components.duofern.stick] RX: 810003CC00000000000000000000006F1234407F0E00
2026-02-27 19:02:09.372 DEBUG (MainThread) [custom_components.duofern.stick] ACK received for command
2026-02-27 19:02:38.809 DEBUG (MainThread) [custom_components.duofern.stick] RX: 0FFF0F210000640000004164120000407F0EFFFFFF01
2026-02-27 19:02:38.809 DEBUG (MainThread) [custom_components.duofern.stick] TX: 81000000000000000000000000000000000000000000
2026-02-27 19:02:38.809 DEBUG (MainThread) [custom_components.duofern.coordinator] Status update for 407F0E: position=100, moving=stop
2026-02-27 19:02:38.809 DEBUG (MainThread) [custom_components.duofern.coordinator] Manually updated duofern data
2026-02-27 19:21:30.797 WARNING (SyncWorker_7) [homeassistant.loader] We found a custom integration duofern which has not been tested by Home Assistant. This component might cause stability problems, be sure to disable it if you experience issues with Home Assistant

A524A8 my Sun sensor is visible there :slight_smile:

As for backup solution instead of the USB stick, i’m develloping my own bare metal Duofern solution based on ESP32 chip & NRF905 wireless transceiver.
But this is a long work in progress since I do this in my spare time.
At the moment it’s just experimental code just to test out from a webpage on the ESP32: (marked below is the same sun sensor messages from today)

I’m just starting to learn all different Duofern packets also with the help of FHEM & PyDuofern code. Also how to send & receive since you have to retry or send some packets multiple times, include incrementing ID’s and since NRF905 sends our bare wireless also add some magic Duofern secret hash codes.

Hardware is based on a design by Joost who did an ESP32 to NRF905 board to control Zehnder air units. (discussed here: Zehnder comfofan s aansturen via RPi, Arduino - Modding, mechanica en elektronica - GoT)

You can find his ESP32/NRF905 PCB here:
Zehnder ComfoAir Home Assistant controller from JoooostB on Tindie

And his fitting 3D print case here:
Zehnder ComfoAir ESP32 nRF905 PCB Case - Free 3D Print Model - MakerWorld

It looks like this then: (my Duofern backup solution when my original Rademacher USB stick will fail):

Zehnder uses other Frequency, but you can change the NRF905 frequency to fit Duofern’s 434.5 MHz.
Other solution would be to use NRF905 ESPHOME.

for those interested in a fork/further development of Mark’s Duofern integration (including all missing other Duofern devices like Sun sensors, …) can check out Irstmon’s fork here: irstmon/homeassistant-duofern: Rademacher DuoFern custom integration for Home Assistant - control DuoFern devices via DuoFern USB stick directly from Home Assistant.
He seems to have added all the missing other FHEM duofern device stuff.
My solar sensor is recognized but I think inverted detection signal (have to check further when the sun shines today :sunglasses: )
But I can’t seem to add “Issues” or “comments” to Irstman’s github.
Further you can tick off tested: DuoFern RolloTron Standard (40xxxx) works also great.
So if you’re reading Irstman, thanks a lot for completing the missing Duofern FHEM code into this native HA one. :+1:

Well first of all - thanks fo Mark’s integration which was what got me going in the first place! I didn’t want to steal it or something, I was just missing the dawn / dusk part and then it escalated rather quickly that with the help of Claude I was able to integrate more and more of the missing features (as I’ve never used python before) and started adding something more (auto-discovery of paired devices if opt-in enabled).

Second… well, I don’t know why but github didn’t enable issues on the forked Repo. I’ve enabled it now.

And maybe the invertion is based on how HA handles 0 / 100 % which is just the other way round from FHEM. I will try to take a look, can you send some raw frames from the debug log via an issue (which is now possible :slight_smile: )?