Trash calendar with Exec binding and simple shell script

Hi all,

this thread here reminded me posting my trash calendar solution for openHAB.

Back in the OH1.x days I wrote a simple shell script the get trash dates into openHAB from plain text files.
The original version is published at the German forum.

I just updated it to OH2 and the Exec2-Binding what makes it a little bit easier in my opinion.

1. Text files

Just put all your dates of one kind of trash into a text file, e.g. trash_yellow.txt (yellow means the German “Gelber Sack” recycling system). You can use multiple files for different kinds of trash.

2018-01-11
2018-01-25
2018-02-08
2018-02-22
2018-03-08
2018-03-22

2. Shell script

Place following script and the created plain text files in your conf folder. I created a subfolder called shellscripts for this and use a manual OH installation. If you use apt installation you have to adjust the path for trash_file in the script.

trash.sh

#!/bin/bash

#Current date
datum=$(date +%s)

#1st argument defines kind of trash
trash_kind=$1

#use respective trash text file
trash_file="/opt/openhab/openhab2/conf/shellscripts/trash_$trash_kind.txt"

#loop searching the text file to find the first date > today
#time read from text file is always 00:00:00h -> #86399sec = 23:59:59h to include current day
while read datum_line
do
	datum_line_sec=$(date -d $datum_line +%s)
	let datum_diff=$datum-$datum_line_sec
	if [ $datum_diff -lt 86399 ]
	then
		echo $datum_line
		exit 0
	fi
done < $trash_file

echo "Error"
exit 1;

3. openHAB

As mentioned I use the Exec2 binding to get the data into openHAB. Again check if the path to the script matches your installation or adjust it.

*.things

Thing exec:command:trash "Muellabfuhr" [ command="/opt/openhab/openhab2/conf/shellscripts/trash.sh %2$s", interval=0, autorun=true ]

*.items

// items for exec-binding
String iTrashRaw "Script Ergebnis [%s]"  { channel="exec:command:trash:output" }
String iTrashRaw_Trigger "Trigger für Mülltermin [%s]" { channel="exec:command:trash:input" }
Number iTrashRaw_Result "Script Rückgabewert [%d]"  { channel="exec:command:trash:exit" }
// items for rule
DateTime iTrashBrown "Restmüll [%1$td.%1$tm.%1$tY]" 
DateTime iTrashYellow "Gelbe Tüte [%1$td.%1$tm.%1$tY]"
Switch vTrashRead "Mülltermine aktualisieren"

*.rules

rule "Mülltermine"
when
  Item vTrashRead changed to ON  
then  
  iTrashRaw_Trigger.sendCommand("brown")
  Thread::sleep(5000)
  if (iTrashRaw_Result.state == 0) {
    iTrashBrown.sendCommand(new DateTimeType(iTrashRaw.state.toString+"T00:00:00"))
  }
  Thread::sleep(1000)
  iTrashRaw_Trigger.sendCommand("yellow")
  Thread::sleep(5000)
  if (iTrashRaw_Result.state == 0) {
    iTrashYellow.sendCommand(new DateTimeType(iTrashRaw.state.toString+"T00:00:00"))
  }
  vTrashRead.postUpdate(OFF)
end

After doing this you get a DateTimeItem for each kind of trash representing the date for the next trash disposal of this kind. Now you can show these items on your Sitemap, HabPanel, process them in further rules or whatever.

If you find this useful, just give it a like :wink:
If you have any questions, please ask…

Cheers
Sebastian

4 Likes

I will definitely give it a try. Looks plain and easy.
Thank you very much.

Those are some really long sleeps which, if you have other rules with sleeps or blocking actions (e.g. executCommandLine on a long-running script) it could cause problems.

This should do the same thing without the sleeps.

rule "Mülltermine"
when
  Item vTrashRead changed to ON  
then  
  iTrashRaw_Trigger.sendCommand("brown")
  createTimer(now.plusSeconds(5), [|
    if (iTrashRaw_Result.state == 0) {
      iTrashBrown.sendCommand(new DateTimeType(iTrashRaw.state.toString+"T00:00:00"))
    }
  ])
  createTimer(now.plusSeconds(6), [|
    iTrashRaw_Trigger.sendCommand("yellow")
  ])
  createTimer(now.plusSeconds(11), [|
    if (iTrashRaw_Result.state == 0) {
      iTrashYellow.sendCommand(new DateTimeType(iTrashRaw.state.toString+"T00:00:00"))
    }
    vTrashRead.postUpdate(OFF)
  ])
end

The code above will allow the rule to return immediately but still space out the commands over the seconds.

Thanks for posting! It’s a great example.

Thanks for your hints @rlkoshak.
I had no issues with it since the rule runs only once a day at 2am, but you are right. Using timers is the better solution.

Hi,
after long abstinence due to bad accident I am trying to restore my openhab configuration.

One of many glitches is my garbage rule which is now giving me the following error.

2020-01-19 11:20:11.986 [nt.ItemStatePredictedEvent] - Garbage_ExecTrigger predicted to become paper

2020-01-19 11:20:11.990 [vent.ItemStateChangedEvent] - Garbage_ExecTrigger changed from trash to paper

2020-01-19 11:20:12.082 [vent.ItemStateChangedEvent] - Garbage_Exec changed from Current date

Error

/etc/openhab2/rules/scripts/shellscripts/trash.sh: Zeile 24: /etc/openhab2/scripts/shellscripts/trash_trash.txt: Datei oder Verzeichnis nicht gefunden

/etc/openhab2/rules/scripts/shellscripts/trash.sh: Zeile 24: /etc/openhab2/scripts/shellscripts/trash_trash.txt: Datei oder Verzeichnis nicht gefunden to Current date

Error

sorry for the bad typing. My left hand does not do what it is supposed to.

Hi,
I used your script for trash calendar but I receive this error, can help me?

   ==> /var/log/openhab2/openhab.log <==
2020-11-08 19:08:54.273 [DEBUG] [ng.exec.internal.handler.ExecHandler] - Passing to shell for parsing command.
2020-11-08 19:08:54.274 [DEBUG] [ng.exec.internal.handler.ExecHandler] - OS: *NIX (Linux)
2020-11-08 19:08:54.285 [DEBUG] [ng.exec.internal.handler.ExecHandler] - Exec [ERROR]: 'sh: 1: /etc/openhab2/script/trash.sh: not found'
2020-11-08 19:08:54.303 [DEBUG] [ng.exec.internal.handler.ExecHandler] - Transformed response is 'sh: 1: /etc/openhab2/script/trash.sh: not found
sh: 1: /etc/openhab2/script/trash.sh: not found'

Basically openhab don’t find the script, but there is in the folder…
Thanks

A little bit more information would be helpful…
Which oh version? Which OS? What kind of installation? What’s about your config? …

1 Like

Right, sorry.
I have installed openhabian with openhab 2.5.10-1 on Raspberry Pi 4 Model B
My config is:

.things
Thing exec:command:trash "Raccolta_rifiuti" [ command="/etc/openhab2/scripts/trash.sh %2$s", interval=0, autorun=true ]

.items

// items for exec-binding
String iTrashRaw "Risultato script output [%s]"  { channel="exec:command:trash:output" }
String iTrashRaw_Trigger "Trigger per scadenza [%s]" { channel="exec:command:trash:input" } //prima era String , nell esempio	
Number iTrashRaw_Result "Script valore di ritorno [%d]"  { channel="exec:command:trash:exit" }
// items for rule
DateTime iTrashUmido "Umido [%1$td.%1$tm.%1$tY]" 
DateTime iTrashSecco "Secco [%1$td.%1$tm.%1$tY]"
DateTime iTrashPlastica "Plastica [%1$td.%1$tm.%1$tY]"
DateTime iTrashVetro "Vetro [%1$td.%1$tm.%1$tY]"
DateTime iTrashCarta "Carta [%1$td.%1$tm.%1$tY]"
Switch vTrashRead "Aggiornamento date dei rifiuti"

Trash.sh
I have only modified:
trash_file="/etc/openhab2/scripts/shellscripts/trash_$trash_kind.txt"

.rules
rule “Raccolta rifiuti”
when
Item vTrashRead changed to ON
then
iTrashRaw_Trigger.sendCommand(“secco”)
createTimer(now.plusSeconds(5), [|
if (iTrashRaw_Result.state == 0) {
iTrashSecco.sendCommand(new DateTimeType(iTrashRaw.state.toString+“T00:00:00”))
}
])
createTimer(now.plusSeconds(6), [|
iTrashRaw_Trigger.sendCommand(“vetro”)
])
createTimer(now.plusSeconds(11), [|
if (iTrashRaw_Result.state == 0) {
iTrashVetro.sendCommand(new DateTimeType(iTrashRaw.state.toString+“T00:00:00”))
}

      ])

      createTimer(now.plusSeconds(12), [|
        iTrashRaw_Trigger.sendCommand("umido")
      ])
      createTimer(now.plusSeconds(17), [|
        if (iTrashRaw_Result.state == 0) {
          iTrashUmido.sendCommand(new DateTimeType(iTrashRaw.state.toString+"T00:00:00"))
    }
    
  ])

  createTimer(now.plusSeconds(18), [|
    iTrashRaw_Trigger.sendCommand("carta")
  ])
  createTimer(now.plusSeconds(23), [|
    if (iTrashRaw_Result.state == 0) {
      iTrashCarta.sendCommand(new DateTimeType(iTrashRaw.state.toString+"T00:00:00"))
    }
    
  ])

  createTimer(now.plusSeconds(24), [|
    iTrashRaw_Trigger.sendCommand("plastica")
  ])
  createTimer(now.plusSeconds(29), [|
    if (iTrashRaw_Result.state == 0) {
      iTrashPlastica.sendCommand(new DateTimeType(iTrashRaw.state.toString+"T00:00:00"))
    }
  vTrashRead.postUpdate(OFF)
    
  ])
end

Have you seen the note in the Exec binding docs, refirring to use of input channel with autorun -

Note that sending the same command a second time will not trigger execution.

The paths in the Thing configuration and in the Shell script don’t match. Please double-check your path configuration.

I don’t think they must necessarily coincide but I have tested with the same paths and the result is the same:

2020-11-09 19:28:55.781 [DEBUG] [ng.exec.internal.handler.ExecHandler] - Exec [ERROR]: 'sh: 1: /etc/openhab2/scripts/shellscripts/trash.sh: not found'
2020-11-09 19:28:55.785 [DEBUG] [ng.exec.internal.handler.ExecHandler] - Transformed response is 'sh: 1: /etc/openhab2/scripts/shellscripts/trash.sh: not found
sh: 1: /etc/openhab2/scripts/shellscripts/trash.sh: not found'

Mh :thinking:
The debug messages says that the script can’t be found. If the path is correct then this might be a permission issue. Have you read about the newly introduced whitelist feature for the exec binding? Maybe this is somehow related. Or it might be a problem with file permissions…

No other ideas at the moment… Config looks good

Yes, I think it is a permissions problem because if I change with command chown the owner of trash.sh with “openhab” and the exec log says “Permission denied”.
If I set “openhabian” like owner return the message “Not found”.
I don’t undestand how change the permissions