KNX shutters control without shutter actuator (relay-controlled shutters)

Gentlemen,

Home-grown automation enthusiast here.
I’m running Home Assistant for the very first time and I’m really amazed.
Unfortunately, every great piece of software finally ends up crashing on some cost-saving user’s head.

My problem is that I had no money for KNX shutter actors, so I bought H8I8O modules from China, connected them with some relays and this is how I control the “move up/move down” commands. I have two different group addresses assigned for every shutter and if I send binary “1” to this group address it starts to move up as long as I don’t send “0” to this address. The movement downwards is solved in the same way.

This is working fine, because my shutters motors are IC-equipped, so even if I short circuit the move up and move down relays they go into so called “reset mode” and not get damaged.

But the problem is that cover implementation defined for shutters available in Home Assistant is not sufficient for me as it only allows for definition of long movement group address and short movement group address.

So this is where I come and ask for you kind support:

  1. how to deal with such configuration like mine, but without the need to buy shutter actuators?
  2. I was even thinking about writing some software in C++ (using eibd library) or Python (using xknx) to create some kind of “shutter manager”. I would assign different group addresses to this piece of software that would behave the same way as hardware shutter actuator, so for example there would be address for long movement with binary “1” for down movement and binary “0” for up movement, but when received by the software it would “resend” to KNX bus the command for H8I8O relay actuator address group for specific movement direction AND a timeout as a result. The question is: maybe you are aware of an already existing software or rule engine that I could use for this?

EDIT:
The software I’m thinking of should work as the followig C++ snippet:

   if(address_group == "0/1/20") //virtual address group for a single shutter
      if(received_value == 1){ //virtual shutter move down
         knx.send_command("0/1/2", 1); //then turn on the relay responsible for down movement...
         sleep(30000); //wait for the shutter to fully close
         knx.send_command("0/1/2", 0); //open the relay
      }

I’d not write a C++ program - you can just as well do that in a HA automation :wink:
Id even consider not using the sleep at all but let the Relais sit in position and only reset the other one just before the next movement - or set both to OFF on a stop command.

Other than that you can use a template cover using knx.send services. Template Cover - Home Assistant

The benefit of the automation approach would be getting the inferred position support provided by xknx (when you set the travel times in HA KNX configuration). So you could travel directly to eg. 60% from HA and xknx sends the stop signal automatically after 60% of the configured time.
The trick part is to keep it synchronized when you triggering from outside of HA.

1 Like

Thank you, @farmio for the ideas.
I also think that automation approach will be better in that case, because with that solution I will be able not only to make Home Assistant cope with the shutters, but the shutters will respond to physical buttons as well (meaning that I can close the shutter from both smartphone, automated scripts in HA and physical buttons on the wall addressing the “virtual” shutter group address).

I’ve made some quick research and this is the automation script that I’ve crafted:

automation:
  - trigger:
    - platform: event
      event_type: knx_event
    condition:
      condition: template
      # „31/1/1” is the address of „virtual shutter”
      value_template: "{{ trigger.event.data.address == '31/1/1' and trigger.event.data.data[0] == 1 }}"
    action:
      - service: knx.write
        data:
          # The actual group address of a shutter is 1/1/4 for upward movement
          address: "1/1/4"
          payload: 1
          type: binary
      - delay: 0:0:10
      - service: knx.write
        data:
          address: "1/1/4"
          payload: 0
          type: binary

It should define a new group address “31/1/1” where, if I send binary “1” the shutter relay will move the shutter for 10 seconds and then release the relay.

The script however is not working :slight_smile: . Would you be so kind and advice me what I’ve done wrong?

There is no trigger.event.data.address - it is called destination.
You can apply this directly to the trigger key instead of using a condition if you prefer.
like

trigger:
  - platform: event
    event_type: knx_event
    event_data:
      destination: "31/1/1"
      telegramtype: GroupValueWrite

You may also use multiple of these triggers and assign trigger ids or branch out the action with choose: to individually process different payloads.

And binary is not a valid sensor type. Just omit the type key to send a raw payload - which when given an integer (instead of a list) is interpreted as binary value.

And the service is called knx.send, not “knx.write”.

Additionally the data object is not a list when the received telegram is DPT 1/2/3 - so trigger.event.data.data == 1 would be correct.

You can find most of these details in the KNX integration documentation under the “Events” and “Services” paragraphs. KNX Events

Additionally you can use HA directly to inspect incoming events Open your Home Assistant instance and show your event developer tools.
and try out services before you create automations Open your Home Assistant instance and show your service developer tools.

1 Like

@farmio, thank you so much! This is literally insane!
Here’s the script I have created and it’s working:

automation:
  - trigger:
    - platform: event
      event_type: knx_event
    condition:
      condition: template
      value_template: "{{ trigger.event.data.destination == '31/0/1' and trigger.event.data.data == 1 }}"
    action:
      - service: knx.send
        data:
          address: "1/0/3"
          payload: 0
      - service: knx.send
        data:
          address: "1/0/4"
          payload: 1
      - delay: 0:0:35
      - service: knx.send
        data:
          address: "1/0/4"
          payload: 0

When I moved the condition directly to trigger section it was hard for me to access its data, so I decided to stick with the value_template.

Also, I had to register the event at the end of automation file with:

# Register the events to make HA aware of new address groups
  - trigger:
      - platform: homeassistant
        event: start
    action:
      # Register the group address to trigger a knx_event
      - service: knx.event_register
        data:
          # Roleta kuchnia (HA managed)
          address: "31/0/1"

Without it Home Assistant didn’t respond to the bus telegram sent to 31/0/1 with any value. I don’t know why is that, but after some trial and error I found it out. It’s probably because the event was not registered as a “watch list” in Home Assistant.

Now it seems that I need to create the same script for every shutter that I have. Or, do you maybe have an idea how to do it in more convenient way?

Enter the world of Blueprints :wink:

You should add listeners for automation_reloaded and service_registered for some knx service - in case you reload the KNX integration. See KNX - relative dimming for lights blueprint · GitHub for an example.

An easier way is to statically define the GAs you want events for in your configuration.yaml - see the KNX integration documentation “Events” paragraph I linked earlier.

So let it be a shutter control blueprint! :slight_smile: ! This will be my next step, but for now I need to implement the listeners for automation_reloaded and service_registered according to your example, but I fail miserably. I don’t have an idea why the following snippet doesn’t work:

# Register the events to make HA aware of new address groups
  - trigger:
    - platform: homeassistant
      event: start
      id: "initialize"
    - platform: event
      event_type: automation_reloaded
      id: "initialize"
    # when KNX integration was reloaded
    - platform: event
      event_type: service_registered
      event_data:
        domain: knx
        service: event_register
      id: "initialize"
    
  # INITIALIZE
  - conditions:
      condition: trigger
      id: "initialize"
    sequence:
    - service: knx.event_register
      data:
        address: "31/0/1"

Do you have an idea? I think I have done it exactly like in your script, but the effect is that “31/0/1” is not being setup as listener neither after HA restart nor after automations reload.

I use actions: choose: instead of conditions: directly, but not sure if it can work your way too.

I have used the system_log.write service for quick debugging - maybe it helps you too. It just writes to HAs log so you can print variables. But nowadays there is automation debugging so that may be more efficient.

As I said, you may just configure the GAs in your knx: event: config and skip the initialization completely.

I understand. Will try to debug the script. I wanted to keep group addresses listeners configuration in the automation section to move it further to the blueprint so nothing additional is needed to configure when applying the blueprint. Without it one will still need to configure the knx: event: config, so I’ll try to figure it out myself.

1 Like

:+1: that’s the spirit! This is exactly what the event_register service was intended for :smiley:

OK, so just as a reference point for everyone else who may face the same issue I want to share my KNX shutter relay control blueprint available at Github: https://github.com/kjakobczyk/Home-Assistant-blueprints/blob/f93547c21369a50abc4e01824f888db0e5b437f1/KNX_shutter_relay_control/KNX_shutter_relay_control.yaml

The issue is solved way above my expectations. Once again thank you @farmio!

2 Likes

Very cool :+1:!

One minor tweak I’d make is for the stop action: The 500ms delay is not needed when stopping.
You can use multiple addresses in knx.send. Just pass a list of both and it will send to both consecutive.

Same for knx.event_register - you can pass a list there too.