How to make ordinary push button lighting smart with openhab

This is a tutorial to control ordinary push button lighting with openhab and google assistant.
In this way, the lighting can always be controlled via the push buttons, even when openhab is offline.
With this set of rules and items you can tell google assistant to turn the lights on or off.

The idea is that we use a dummy item and the lighting status to also see the status of the lighting at google assistant, so we can also say to google assistant switch the lighting on or off.This is necessary because we work with pulse relays otherwise google assistant thinks that we always switch off the lights immediately after 250ms.

You do need electrical knowledge. If you don’t have this, don’t try it yourself but ask a trained electrician.

My electrical cabinet contains double-pole pulse relays.
It is important that they are double pole because we will use 1 pole to switch the lighting and 1 pole to indicate the status of the lighting.

My pulse relays first worked on 24V ac but because the modbus modules work on DC I placed a 12V DC transformer because my puls’s relays also worked on 12V DC.
But you can use a voltage between 9V DC and 30V DC.


I use cheap modbus modules that I bought on aliexpress for this.

You need the following parts:
1xModbus module relay output: https://nl.aliexpress.com/item/32738571820.html?gps-id=pcStoreLeaderboard&scm=1007.22922.122102.0&scm_id=1007.22922.122102.0&scm-url=1007.22922.122102.0&pvid=aa7c888e-64ea-4ca9-81dd-48d1050b136b&spm=a2g0o.store_home.smartLeaderboard_136449541.32738571820

1xModbus module digital input:https://nl.aliexpress.com/item/32735641541.html?spm=a2g0o.detail.100009.2.103372a61KEG0k&gps-id=pcDetailLeftTopSell&scm=1007.13482.95643.0&scm_id=1007.13482.95643.0&scm-url=1007.13482.95643.0&pvid=994b05be-af4c-4eb4-9ad0-d9a94daa0ce7&_t=gps-id:pcDetailLeftTopSell,scm-url:1007.13482.95643.0,pvid:994b05be-af4c-4eb4-9ad0-d9a94daa0ce7,tpp_buckets:668%230%23170098%233_668%23808%237756%23612_668%23888%233325%2314_668%232846%238112%23586_668%232717%237564%23604

1x Usb to RS485 converter

I’m not going to say too much about the wiring because I assume that you have electrical knowledge.

The relay output module must be placed in parallel over the push buttons so that they can respond like a push button. We use a rule to make the relay output module switch off after 250ms so that it simulates a push of a button.

The digital input module must be connected in such a way that when the pulse relay contact is closed(light on)the input is on.This way, openhab also knows when a push button is pressed.

You have to install the modbus binding because the wellpro modules communicate with openhab via modbus.

More info about the modbus binding can you find here:

For more info on how to set google assistant:

The configuration is entirely textual.
The items and rules are for 3 lights.
You can copy and rename for the other lights.
Create the following folders:

Lighting.items

Switch keuken1    "keuken1"         { channel="modbus:data:slave1:slave1coils:do00:switch" }
Switch keuken2    "keuken2"         { channel="modbus:data:slave1:slave1coils:do01:switch" } 
Switch keuken3    "keuken3"         { channel="modbus:data:slave1:slave1coils:do02:switch" }

Group:Number:SUM   gVerlichtingsinput  "Verlichting aan [%d] "


Contact verlichting1 "[MAP(en.map):%s]"  (gVerlichtingsinput) { channel="modbus:data:slave10:slave10Inputs:di00:contact" }
Contact verlichting2 "[MAP(en.map):%s]"  (gVerlichtingsinput) { channel="modbus:data:slave10:slave10Inputs:di01:contact" }
Contact verlichting3 "[MAP(en.map):%s]"  (gVerlichtingsinput) { channel="modbus:data:slave10:slave10Inputs:di02:contact" }

Group  gVerlichting  

Switch dummy1 "keuken1"       (gVerlichting)    { ga="Light" }
Switch dummy2 "keuken2"       (gVerlichting)    { ga="Light" }
Switch dummy3 "keuken3"       (gVerlichting)    { ga="Light" }

Lighting-pulse.rules


rule "keuken1 is a switch ON "
       when
         Item dummy1 received command ON
          then
           if(verlichting1.state == CLOSED)
               sendCommand(keuken1 ,ON)
              createTimer(now.plusMillis(250))[
               sendCommand(keuken1 ,OFF)]
            end

rule "keuken1 is a switch OFF"
       when
         Item dummy1 received command OFF
          then
           if(verlichting1.state == OPEN)
               sendCommand(keuken1 ,ON)
              createTimer(now.plusMillis(250))[
               sendCommand(keuken1 ,OFF)]
            end
 rule "keuken2 is a switch ON "
       when
         Item dummy2 received command ON
          then
           if(verlichting2.state == CLOSED)
               sendCommand(keuken2 ,ON)
              createTimer(now.plusMillis(250))[
               sendCommand(keuken2 ,OFF)]
            end

rule "keuken2 is a switch OFF"
       when
         Item dummy2 received command OFF
          then
           if(verlichting2.state == OPEN)
               sendCommand(keuken2 ,ON)
              createTimer(now.plusMillis(250))[
               sendCommand(keuken2 ,OFF)]
            end
            
rule "keuken3 is a switch ON "
       when
         Item dummy3 received command ON
          then
           if(verlichting3.state == CLOSED)
               sendCommand(keuken3 ,ON)
              createTimer(now.plusMillis(250))[
               sendCommand(keuken3 ,OFF)]
            end

rule "keuken3 is a switch OFF"
       when
         Item dummy3 received command OFF
          then
           if(verlichting3.state == OPEN)
               sendCommand(keuken3 ,ON)
              createTimer(now.plusMillis(250))[
               sendCommand(keuken3 ,OFF)]
            end


Lighting-status.rules

rule "status keuken1 update "
       when
         Item verlichting1 changed 
          then
          if(verlichting1.state == OPEN){
            dummy1.postUpdate(ON)
      } else {
          if(verlichting1.state == CLOSED)
            dummy1.postUpdate(OFF)}
end

rule "status keuken2 update "
       when
         Item verlichting2 changed 
          then
          if(verlichting2.state == OPEN){
            dummy2.postUpdate(ON)
      } else {
          if(verlichting2.state == CLOSED)
            dummy2.postUpdate(OFF)}
end

rule "status keuken3 update "
       when
         Item verlichting3 changed 
          then
          if(verlichting3.state == OPEN){
            dummy3.postUpdate(ON)
      } else {
          if(verlichting3.state == CLOSED)
            dummy3.postUpdate(OFF)}
end

Make sure you enter the correct usb port in the configuration at port = “/ dev / ttyUSB-RS485”

BridgeModbus.things

your coBridge modbus:serial:slave1 [ port="/dev/ttyUSB-RS485" ,id=1 , baud=9600, stopBits="1", parity="none",timeBetweenTransactionsMillis=35,dataBits=8, encoding="rtu" ]{

Bridge poller slave1coils [ start=0, length=8, refresh=0, type="coil" ]{
    
        Thing data do00 [ readStart="0", readValueType="bit", writeStart="0", writeValueType="bit", writeType="coil",updateUnchangedValuesEveryMillis="5000000" ]
        Thing data do01 [ readStart="1", readValueType="bit", writeStart="1", writeValueType="bit", writeType="coil",updateUnchangedValuesEveryMillis="5000000" ]
        Thing data do02 [ readStart="2", readValueType="bit", writeStart="2", writeValueType="bit", writeType="coil",updateUnchangedValuesEveryMillis="5000000" ]
        Thing data do03 [ readStart="3", readValueType="bit", writeStart="3", writeValueType="bit", writeType="coil",updateUnchangedValuesEveryMillis="5000000" ]
        Thing data do04 [ readStart="4", readValueType="bit", writeStart="4", writeValueType="bit", writeType="coil",updateUnchangedValuesEveryMillis="5000000" ]
        Thing data do05 [ readStart="5", readValueType="bit", writeStart="5", writeValueType="bit", writeType="coil",updateUnchangedValuesEveryMillis="5000000" ]
        Thing data do06 [ readStart="6", readValueType="bit", writeStart="6", writeValueType="bit", writeType="coil",updateUnchangedValuesEveryMillis="5000000" ]
        Thing data do07 [ readStart="7", readValueType="bit", writeStart="7", writeValueType="bit", writeType="coil",updateUnchangedValuesEveryMillis="5000000" ]

    } 
}     

Bridge modbus:serial:slave10 [ port="/dev/ttyUSB-RS485" ,id=10 , baud=9600, stopBits="1", parity="none",timeBetweenTransactionsMillis=35,dataBits=8, encoding="rtu" ]{ 
   
Bridge poller slave10Inputs [ start=0, length=16, refresh=1000, type="discrete" ]{ 
    
       Thing data di00 [ readStart="0", readValueType="bit",updateUnchangedValuesEveryMillis="5000000" ]
       Thing data di01 [ readStart="1", readValueType="bit",updateUnchangedValuesEveryMillis="5000000" ]
       Thing data di02 [ readStart="2", readValueType="bit",updateUnchangedValuesEveryMillis="5000000" ]
       Thing data di03 [ readStart="3", readValueType="bit",updateUnchangedValuesEveryMillis="5000000" ]
       Thing data di04 [ readStart="4", readValueType="bit",updateUnchangedValuesEveryMillis="5000000" ]
       Thing data di05 [ readStart="5", readValueType="bit",updateUnchangedValuesEveryMillis="5000000" ]
       Thing data di06 [ readStart="6", readValueType="bit",updateUnchangedValuesEveryMillis="5000000" ]
       Thing data di07 [ readStart="7", readValueType="bit",updateUnchangedValuesEveryMillis="5000000" ]
       Thing data di08 [ readStart="8", readValueType="bit",updateUnchangedValuesEveryMillis="5000000" ]
       Thing data di09 [ readStart="9", readValueType="bit",updateUnchangedValuesEveryMillis="5000000" ]
       Thing data di10 [ readStart="10", readValueType="bit",updateUnchangedValuesEveryMillis="5000000" ]
       Thing data di11 [ readStart="11", readValueType="bit",updateUnchangedValuesEveryMillis="5000000" ]
       Thing data di12 [ readStart="12", readValueType="bit",updateUnchangedValuesEveryMillis="5000000" ]
       Thing data di13 [ readStart="13", readValueType="bit",updateUnchangedValuesEveryMillis="5000000" ]
       Thing data di14 [ readStart="14", readValueType="bit",updateUnchangedValuesEveryMillis="5000000" ]
       Thing data di15 [ readStart="15", readValueType="bit",updateUnchangedValuesEveryMillis="5000000" ]
          
    }
}   

Transform map

en.map

CLOSED=UIT
OPEN=AAN
NULL=unknown


Lighting.sitemap

Frame label="keuken" {
       
        Switch item=dummy1 mappings=[ON="AAN",OFF="UIT"]
        Text item=verlichting1 icon="light" 
        Switch item=dummy2 mappings=[ON="AAN",OFF="UIT"]
        Text item=verlichting2 icon="light"
        Switch item=dummy3 mappings=[ON="AAN",OFF="UIT"]
        Text item=verlichting3 icon="light" }

And if you use habpanel matrix theme

Lighting.widget.json (12.9 KB)

2 Likes

Looks great and interesting. Thanks for sharing.

Thanks for posting. Your rules could be collapsed into two. The easiest would be to put the dummy and verlichting Items into Groups.


rule "keuken is a switch commanded"
when
    Member of dummy received command
then
    val cmd = receivedCommand
    val num = triggeringItem.name.repalce("dummy", "")
    val verlichting = verlichting.members.findFirst(i | i.name == "verlichting"+num)).state

    if(cmd == ON && verlichting == CLOSED) sendCommand("keuken"+num, "ON")
    else if(cmd == OFF && verlichting == OPEN) sendCommand("keuken"+num, "ON")

    createTimer(now.plusMillis(250), [ | sendCommand("keuken"+num, "OFF") ])
end

rule "status keulken update"
when
    Member of verlichting changed
then
    postUpdate(triggeringItem.name.replace("verlichting", "dummy"), if(triggeringItem.state == OPEN), ON else OFF)
end
2 Likes

This topic was automatically closed 41 days after the last reply. New replies are no longer allowed.