7

I have a ZWave light bulb and a ZWave 4-button wall switch, both connected to Domoticz installed on a Raspberry Pi.

I'd like the following scenarios :

  • Button 1 : lamp on for 30 minutes
  • Button 2 : lamp off
  • Button 3 : lamp always on
  • Button 4 : summon Cthulhu

Each buttons overrides the previous action (Button 3 -> Button 1 = on for 30 minutes)

Wiring and programming the buttons is easy, but now, how about the timer ? I'd like to avoid creating a homemade service because I'm afraid of messing with init.d.

I have 3 possibilities :


Domoticz dummy switch

Domoticz allows to create a dummy switch which can change states after some time given in an interface :

domoticz dummy switch

Pros

  • off-the-shelf timer!
  • I can interact quite quickly between my wall switch and the lamp

Cons

  • although Domoticz handles MQTT, there will be a lot of LUA script and "blocky" to interconnect devices
  • time might not be easily configurable...

at and atq

at is a linux command to plan an action in time, as simple as

at [when] < [what]

Pros

  • multi-timer service
  • easy to use and call

Cons

  • at only gives an unique ID, unless parsing the planned command I can't give a name to the job (unless with a magic linux command...)
  • therefore I need to code/implement a job matcher using a database

Crontab

Crontab is a linux service to plan repetitive tasks. In my case it will be a simple

# check every minute
* * * * * /path/checktimer.sh

Pros

  • Reliable time trigger

Cons

  • Cannot manage seconds...
  • Still forced to maintain somewhere a job matcher

To my question :

  • Did you have to manage timers like this kind?
  • Did I miss other more reliable/configurable solutions?
  • Do you have a preference with on the solutions above?
2
  • 1
    Just use sleep or usleep to trigger the off? Its the underlying function under at, and you can the use jobs to handle background jobs (mainly to cancel a planned off if I understood properly)
    – Tensibai
    Commented Apr 19, 2017 at 21:45
  • sleep looks worse : you only pass a time and it returns nothing. Can you answer and give an example using jobs?
    – Goufalite
    Commented Apr 20, 2017 at 14:39

3 Answers 3

5

Per request I'll try to give an example on how I would tackle it (with bash shell jobs handling):

Button 1:
When turning on a lamp X for 30 seconds and lamp Y for 5 minutes:

echo "Switch on lamp_x" && sleep 30s && echo "Switch off lamp_x" &
echo "Switch on lamp_y" && sleep 5m && echo "Switch off lamp_y" &

Due to process limitations, this has to be on two separate lines, the echo above should be replaced by actual commands obviously.

button 3:
You can then kill sleep to stop it and keep the light on by getting a job pid and killing it:

kill $(jobs -p %?lamp_y)
echo "Switch on lamp_y"

The fact the commands are chained by && will prevent the command after sleep to run as sleep didn't exit properly.
This doesn't handle non existing job, which may cause kill to return an error, nothing bad should happen here.

Button 2: Using the same method as button 3, but using the stop command and killing the jobs if any.

Button 4:

echo "Ph'nglui mglw'nafh Cthulhu R'lyeh wgah'nagl fhtagn"

(sorry I've no idea what you wish here, set for completeness)


Details of implementations about jobs:

jobs -p %?lamp_y return the current pid -p of a job matching the jobspec %?lamp_y which means lamp_y may appear anywhere in the command line, choose carefully what to use here (but I bet you have a unique identifier for things or group of things you wish to control).

3
  • 3
    I'm not volunteering to test your implementation of button 4. Commented Apr 21, 2017 at 9:13
  • 2
    One liner killing job is perfect! Thank you! I BTW I tried your button 4 implementation and now all my lights are flashing and there is a creepy sound everywhere, great for a Halloween party!
    – Goufalite
    Commented Apr 24, 2017 at 12:03
  • Protip : start the command with true taskid && so you can track easily your job ! Unfortunatly this doesn't work if PHP or another program calls the command because it will be launched as a subshell...
    – Goufalite
    Commented Feb 16, 2018 at 9:58
3

If you want to use an online service for this, you should be able to use https://www.stringify.com They support sequences and variables (and timers). I've not used their service in anger, but it looks like you should be able to use a timer to decrement a variable (which determines the remaining on time), and the various trigger events can force the variable to a new value.

They support IFTTT integration, so pretty much any endpoint can be linked in some way.

3

I've found another way quite expensive yet working with external processes such as PHP's system : screen

First, install it :

sudo apt-get install screen

Then call your function

screen -dm -S taskid bash -c 'sleep 20 && command'
    -dm : detach process
    -S  : identify screen by name

To list your tasks

ls /var/run/screen/S-www-data (or S-anotheruser, warning it is user bound, or sudo it)

To kill it

screen -S taskid -X kill
    -S : identify screen by name
    -X : access the screen and perform this command

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.