An Asterisk-based alarm clock service

I've created an alarm clock facility and added it to the dialplan of my Asterisk server, but I use it so seldom that I can never remember how to use it when I want to.

  • Dial 0 to review all currently-set alarm times
  • Dial 1-9 alone to cancel (delete) that alarm
  • Dial 1-9 followed by 0 to disable (without cancelling completely) the alarm
  • Dial 1-9 followed by 1 to re-enable the alarm
  • Dial 1-9 followed by HHMM to set the alarm for the specified time (and enable it)

TODO: Add a facility to set just a one-off alarm (the above, once set, go off every day until disabled).
TODO: Get the system to notice which extension the alarm was set from, and only ring that extension for the alarm itself.

To make this work on your own Asterisk server, you need to do four things:

  1. Add the following dialplan code to whatever context your SIP phones are registered to:
    dialplan.txt
    exten => _ZXXXX,1,NoOp(Setting alarm ${EXTEN:0:1} to ${EXTEN:1})
    same => n,GotoIf($["${EXTEN:1:2}">"23"]?inval)
    same => n,GotoIf($["${EXTEN:3:2}">"59"]?inval)
    same => n,Set(CHANNEL(language)=al)
    same => n,System(/etc/asterisk/alarm/do.sh set ${EXTEN:0:1} ${EXTEN:1})
    same => n,Playback(silence/1)
    same => n,Playback(alarm)
    same => n,Playback(digits/${EXTEN:0:1})
    same => n,Playback(is-set-to)
    same => n,SayUnixTime(${STRPTIME(2000-01-01 ${EXTEN:1:2}:${EXTEN:3:2}:00,,%Y-%m-%d %H:%M:%S)},,HM)
    same => n,Playback(silence/1)
    same => n,Hangup()
    same => n(inval),Playback(im-sorry&please-try&another-time)
    same => n,Hangup()
    
    exten => _Z0,1,NoOp(Disabling alarm ${EXTEN:0:1})
    same => n,System(/etc/asterisk/alarm/do.sh disable ${EXTEN:0:1})
    same => n,Set(CHANNEL(language)=al)
    same => n,Playback(silence/1)
    same => n,Playback(alarm)
    same => n,Playback(digits/${EXTEN:0:1})
    same => n,Playback(off)
    same => n,Playback(silence/1)
    same => n,Hangup()
    
    exten => _Z1,1,NoOp(Enabling alarm ${EXTEN:0:1})
    same => n,System(/etc/asterisk/alarm/do.sh enable ${EXTEN:0:1})
    same => n,Set(CHANNEL(language)=al)
    same => n,Playback(silence/1)
    same => n,Playback(alarm)
    same => n,Playback(digits/${EXTEN:0:1})
    same => n,Playback(on)
    same => n,Playback(silence/1)
    same => n,Hangup()
    
    exten => 0,1,NoOp(Reviewing all alarm times)
    same => n,Set(CHANNEL(language)=al)
    same => n,Playback(silence/1)
    same => n,Playback(current-time-is)
    same => n,SayUnixTime(,,HM)
    same => n,Playback(silence/1)
    same => n,Set(n=1)
    same => n,While($[${n}<10])
    same => n,Set(t=${FILE(/etc/asterisk/alarm/alarm.${n}.txt)})
    same => n,GotoIf($["x${t}"="x"]?none)
    same => n,Playback(alarm)
    same => n,Playback(digits/${n})
    same => n,Playback(is-set-to)
    same => n,GotoIf($["${t:0:1}"="#"]?hash)
    same => n,SayUnixTime(${STRPTIME(2000-01-01 ${t:0:2}:${t:2:2}:00,,%Y-%m-%d %H:%M:%S)},,HM)
    same => n,Playback(silence/1)
    same => n,Goto(none)
    same => n(hash),SayUnixTime(${STRPTIME(2000-01-01 ${t:1:2}:${t:3:2}:00,,%Y-%m-%d %H:%M:%S)},,HM)
    same => n,Playback(off)
    same => n,Playback(silence/1)
    same => n(none),Set(n=$[${n}+1])
    same => n,EndWhile
    same => n,Hangup()
    
    exten => _Z,1,NoOp(Cancelling alarm ${EXTEN})
    same => n,System(/etc/asterisk/alarm/do.sh cancel ${EXTEN})
    same => n,Set(CHANNEL(language)=al)
    same => n,Playback(silence/1)
    same => n,Playback(alarm)
    same => n,Playback(digits/${EXTEN:0:1})
    same => n,Playback(has-been-cleared)
    same => n,Playback(silence/1)
    same => n,Hangup()
  2. Add the following additional context for the alarm script to use:
    wakeywakey.txt
    [WakeyWakey]
    exten => Call,1,NoOp(Call)
    same => n,Set(CHANNEL(language)=al)
    same => n,Dial(SIP/KSnom870)
    same => n,Hangup()
    
    exten => Alarm,1,NoOp(Alarm)
    same => n,Set(CHANNEL(language)=al)
    same => n,Playback(silence/1)
    same => n,Playback(this-is-yr-wakeup-call)
    same => n,Playback(silence/1)
    same => n,Playback(current-time-is)
    same => n,SayUnixTime(,,HM)
    same => n,Hangup()

    Note: adjust the above extension name "KSnom870" to whichever phone/s you wish the ring when the alarm goes off.

  3. Add the following bash script to call the alarm context at the appropriate time:
    do.sh
    #!/bin/bash
    
    # Process various alarm functions
    
    if [ "$1" = "set" ]
    then
    # Set alarm $2 to time $3
    
      echo "$3" >/etc/asterisk/alarm/alarm.$2.txt
    
      sed -i "/ringnow $2/d" /etc/asterisk/alarm/crontab
      echo "${3:2:2} ${3:0:2} * * * /etc/asterisk/alarm/do.sh ringnow $2 $3" >>/etc/asterisk/alarm/crontab
      crontab /etc/asterisk/alarm/crontab
    fi
    
    if [ "$1" ] "cancel" ]
    then
    # Cancel alarm $2
    
      rm -f /etc/asterisk/alarm/alarm.$2.txt
      sed -i "/ringnow $2/d" /etc/asterisk/alarm/crontab
      crontab /etc/asterisk/alarm/crontab
    fi
    
    if [ "$1" = "enable" ]
    then
    # Enable alarm $2
    
      if grep -q "^#" /etc/asterisk/alarm/alarm.$2.txt
      then
        sed -i "s/^#\+//" /etc/asterisk/alarm/alarm.$2.txt
        sed -i "s/#\+\(.*ringnow $2 .*\)/\1/" /etc/asterisk/alarm/crontab
        crontab /etc/asterisk/alarm/crontab
      fi
    fi
    
    if [ "$1" = "disable" ]
    then
    # Disable alarm $2
    
      if ! grep -q "^#" /etc/asterisk/alarm/alarm.$2.txt
      then
        sed -i "s/^/#/" /etc/asterisk/alarm/alarm.$2.txt
        sed -i "s/\(.*ringnow $2 .*\)/#\1/" /etc/asterisk/alarm/crontab
        crontab /etc/asterisk/alarm/crontab
      fi
    fi
    
    if [ "$1" = "ringnow" ]
    then
    # Copy the callfile to place the call
    
      cd /etc/asterisk/alarm
      rsync -aq callfile /var/spool/asterisk/outgoing
    fi
  4. Add the following callfile so that it can be copied by the bash script:
    callfile
    Channel: Local/Call@WakeyWakey
    Context: WakeyWakey
    Extension: Alarm
    Priority: 1

Go up
Return to main index.