Custom Device State

Submitted by russell on 11 March 2007 - 12:59am.
Presence

"Presence" is a nice buzz word that gets thrown around a lot. For example, if you have a SIPi phone, you may configure your phone to subscibe to the state of certain extensions. That way, you can see if someone within your company is on the phone before you even try to call them.

When you set this up in Asterisk, you map an extension to a real device. For example, when someone subscribes to the state of extension 1234, Asterisk knows to give them the state of the SIP phone SIP/myphone.

exten => 1234,hint,SIP/myphone
Mapping extensions to things other than phones

The really cool thing about doing this in Asterisk is that the extension doesn't have to be mapped to a real device. There are other things in Asterisk that you can subscribe to the state of.

Subscribe to extension 1235 to see when MeetMe conference number 555 is in use:

exten => 1235,hint,Meetme:555

In an SLA (Shared Line Appearances) setup, a phone subscribes to the state of a trunk:

exten => station1_line1,hint,SLA:station1_line1

Note that the colon after Meetme and SLA indicates to Asterisk that this is a virtual device and not a standard Asterisk device, denoted with a forward slash.

Custom Device State

A couple of weeks ago, I woke up in the middle of the night and couldn't go back to sleep. I popped into IRC and talking to someone there gave me the idea to write a new module, func_devstate, which adds a new dialplan function, DEVSTATE.

DEVSTATE has two different ways it can be used. First, you can retrieve the state of any device in the dialplan. This is useful if you would like to make decisions in the dialplan based on the current state of a device.

exten => s,1,NoOp(My phone state is currently ${DEVSTATE(SIP/myphone)})

The second way that DEVSTATE can be used is to create custom device state.

exten => s,1,Set(DEVSTATE(Custom:mycustomstate)=INUSE)

Then, of course, you could retrieve this state in the dialplan as well.

exten => s,1,NoOp(My custom device state is ${DEVSTATE(Custom:mycustomstate)})

That may not seem terribly useful, yet, but let me illustate a practical example. Let's say you use Asterisk to control the lights in your home. To keep the example simple, to turn a light on you run an application called "lighton 1" to turn light number 1 on, and "lightoff 1" to turn light number 1 off.

Let's say you configure your SIP phone to subscribe to the state of 1236 to control light number 1. Also, when you press its button, the phone will call 1236 to turn the light on or off, depending on its current state.

exten => 1236,hint,Custom:light1

exten => 1236,1,Goto(1236-${DEVSTATE(Custom:light1)}|1)

exten => 1236-UNKNOWN,1,Goto(1236-NOT_INUSE|1)

exten => 1236-NOT_INUSE,1,System(lighton 1)
exten => 1236-NOT_INUSE,n,Set(DEVSTATE(Custom:light1)=INUSE)

exten => 1236-INUSE,1,System(lightoff 1)
exten => 1236-INUSE,n,Set(DEVSTATE(Custom:light1)=NOT_INUSE)

Note that the handling of the UNKNOWN state is needed for the first time you press the button, because the state has not yet been set to either NOT_INUSE or INUSE.

With this example, you now have a button and an LED on your SIP phone that tells you whether a light is on or off, and lets you control it. If you come up with a really cool way to use this, I would love to hear about it. Feel free to email me at russell@digium.com.