Chapter 13. Device States

Out of clutter, find simplicity.

Albert Einstein

It is often useful to be able to determine the state of the devices that are attached to a telephone system. For example, a receptionist might require the ability to see the statuses of everyone in the office in order to determine whether somebody can take a phone call. Asterisk itself needs this same information. As another example, if you were building a call queue, as discussed in Chapter 12, Asterisk needs to know when an agent is available so that another call can be delivered. This chapter discusses device state concepts in Asterisk, as well as how devices and applications use and access this information.

Device States

There are two categories of devices that Asterisk provides state information for: channel devices (such as PJSIP endpoints) and virtual devices (which are built-in services that one might wish to monitor, such as conference rooms).

To reference the state of a channel, you do so in exactly the same way you would with Dial(), for example DEVICE_STATE(PJSIP/000f300B0B02), whereas to reference the state of a virtual device, the format is virtual device type:identifier, for example DEVICE_STATE(ConfBridge:1234).

Virtual devices include things that are inside Asterisk but provide useful state information (see Table 13-1).

Table 13-1. Devices for which Asterisk can provide state information
DeviceDescription
PJSIP/channel nameMany channels can have their state monitored, but the PJSIP channel offers by far the most amount of useful data; thus, monitoring SIP devices is the most common use of DEVICE_STATE.
ConfBridge:conference bridgeThe state of a MeetMe conference bridge. The state will reflect whether or not the conference bridge currently has participants called in. More information on using MeetMe() for call conferencing can be found in Chapter 11.
Custom:custom nameCustom device states. These states have custom names and are modified using the DEVICE_STATE() function. Example usage can be found in “Using Custom Device States”.
Park:exten@contextThe state of a spot in a call parking lot. The state information will reflect whether or not a caller is currently parked at that extension. More information about call parking in Asterisk can be found in “Call Parking”.
Calendar:calendar nameCalendar state. Asterisk will use the contents of the named calendar to set the state to available or busy.

Checking Device States

The DEVICE_STATE() dialplan function reads the current state of a device.

exten => 7012,1,Answer()
 same => n,Set(DeviceIdent=PJSIP/000f300B0B02)
 same => n,Verbose(3,${DeviceIdent} is ${DEVICE_STATE($DeviceIdent})})
 same => n,Hangup()

If we call extension 7012 from the same device that we are checking the state of, the following verbose message comes up on the Asterisk console:

    -- PJSIP/000f300B0B02 is INUSE
Note

Chapter 17 discusses the Asterisk Manager Interface (AMI). The GetVar manager action can be used to retrieve device state values in an external program. You can use it to get the value of a normal variable, or to return a value from a dialplan function such as DEVICE_STATE().

Here is a list of the values that the DEVICE_STATE() function will return (depending, of course, on what was found):

  • UNKNOWN

  • NOT_INUSE

  • INUSE

  • BUSY

  • INVALID

  • UNAVAILABLE

  • RINGING

  • RINGINUSE

  • ONHOLD

This information can then be used in the dialplan for call-flow decisions (for example, a local channel ringing an agent might use this information to determine that an agent phone is on a call on another line, and thus reject the call so it passes back into the queue).

Extension States Using the hint Directive

Extension state is a dialplan mechanism Asterisk uses to allow SIP devices to subscribe to presence information. As an example, a reception phone might have a Busy Lamp Field (BLF) module, containing buttons to be used to show the state of various phones in the office. The phone with the BLF will send subscription requests in order to tell Asterisk which devices it wants to receive presence information from. In the dialplan, we use the hint directive to define the mapping between an extension and one or more devices.

Hints

To define a hint in the dialplan, the keyword hint is used in place of a priority.

[hints]
;exten = <extension>,hint,<device state id>[& <more dev state id],<presence state id>

exten => 100,hint,${UserA_DeskPhone}

exten => 221,hint,ConfBridge:221

Often, you might see hints defined in the same section of the dialplan as the normal extension. This can get a bit visually cluttered, and it also suggests that the hint is somehow associated with the dialable extension, which is not the case.

[sets]

exten => 100,hint,${UserA_DeskPhone}
exten => 100,1,Gosub(subDialUser,${EXTEN},1(${UserA_DeskPhone},${EXTEN},default,22))
exten => 101,hint,${UserA_SoftPhone}
exten => 101,1,Gosub(subDialUser,${EXTEN},1(${UserA_SoftPhone},${EXTEN},default,23))
exten => 102,hint,${UserB_DeskPhone}
exten => 102,1,Gosub(subDialUser,${EXTEN},1(${UserB_DeskPhone},${EXTEN},default,26))
exten => 103,hint,${UserB_SoftPhone}
exten => 103,1,Gosub(subDialUser,${EXTEN},1(${UserB_SoftPhone},${EXTEN},default,24))

exten => 110,1,Dial(${UserA_DeskPhone}&${UserA_SoftPhone}&${UserB_SoftPhone})

In our example we’ve made a direct correlation between the hint’s extension number and the extension number being dialed, although there is no requirement that this be the case.

Checking Extension States

The easiest way to check the current state of the hint extensions is through the Asterisk CLI. The core show hints command will display all currently configured hints:

*CLI> core show hints
    -= Registered Asterisk Dial Plan Hints =-
100@hints : PJSIP/0000f30A0A01   State:Unavailable Presence:not_set Watchers 0
101@hints : PJSIP/SOFTPHONE_A    State:Unavailable Presence:not_set Watchers 0
102@hints : PJSIP/0000f30B0B02   State:Unavailable Presence:not_set Watchers 0
103@hints : PJSIP/SOFTPHONE_B    State:Unavailable Presence:not_set Watchers 0
110@hints : PJSIP/0000f30A0A01&P State:Unavailable Presence:not_set Watchers 0
221@hints : ConfBridge:221       State:Unavailable Presence:not_set Watchers 0
----------------
- 6 hints registered

In addition to showing you the state of each hint, the output of core show hints also provides a count of watchers. A watcher is an entity that has subscribed to receive updates on the state of this extension. If a SIP endpoint subscribes to the state of an extension, the watcher count will be increased.

Extension state can also be retrieved with a dialplan function, EXTENSION_STATE(). This function operates much like the DEVICE_STATE() function described in the preceding section. Add the following example to your /etc/asterisk/extensions.conf file, as a new extension right after 235:

exten => 234,1,NoOp()
  same => n,Set(FEATURE(parkingtime)=60)

exten => 235,1,Noop(The state of 100@hints is ${EXTENSION_STATE(100@hints)} )
  same => n,Hangup()

exten => 321,1,NoOp()

When this extension is called from the endpoint assigned to 100, this is the message that shows up on the Asterisk console:

    -- The state of 100@hints is INUSE

The following list includes the possible values that may be returned from the EXTENSION_STATE() function:

  • UNKNOWN

  • NOT_INUSE

  • INUSE

  • BUSY

  • UNAVAILABLE

  • RINGING

  • RINGINUSE

  • HOLDINUSE

  • ONHOLD

SIP Presence

Asterisk gives devices the capability to subscribe to extension state using the SIP protocol. This functionality is often referred to as BLF (Busy Lamp Field); see Figure 13-1.

Figure 13-1. Busy Lamp Field aka sidecar

The configuration of the module will be slightly (or very) different for each manufacturer; however, the subscription information will—one way or another—need to include the following:

  • The address of the Asterisk server (this might be defined on a per-button basis, or it might apply to the whole phone).

  • The context to subscribe to (in our sample dialplan, it’s named [hints]). This setting is defined in the subscribe_context field of the asterisk.ps_endpoints table.

  • The relevant extension (100, 101, 102, etc.)1

One of the more simple and inexpensive ways we’ve found for testing presence is using the open source Windows softphone, MicroSIP.2 You’ll first need to download MicroSIP and get it registered to your Asterisk system. Then, under the contacts tab of the softphone, you can right-click in the open area to Add a contact. In the Name section you can put whatever you wish, but under the Number section, you will input extension@hints context, which in our case would be one of 100@hints, 101@hints, 102@hints, or 103@hints. If you’ve set everything up in Asterisk per the previous examples, you should see the state of your subscriptions change in response to whatever the far end set is doing. You can also monitor this from Asterisk’s perspective using a command such as:

$ watch -n 0.5 "sudo asterisk -rx 'core show hints'"

The configuration of presence on physical desk telephones is essentially the same, but it can be more difficult to make sense of the specific syntax each manufacturer requires. Our advice is to get it working with MicroSIP (which you should be able to run on WINE under Linux or macOS). It’s an easy setup, and from there you’ll have a known-good configuration you can trust when you’re sorting out a similar config for one of your desk phones.

Using Custom Device States

In addition to the devices Asterisk knows internally how to monitor (PJSIP, ConfBridge, Park, Calendar), Asterisk also provides the ability to create custom device states, which can be very useful in the development of some interesting applications.

Custom device states are defined using a prefix of Custom:. The text that comes after the prefix can be anything you want. To set or read the value of a custom device state, use the DEVICE_STATE() dialplan function. Put this into your extensions.conf right after extension 235:

exten => 235,1,Noop(The state of 100@hints is ${EXTENSION_STATE(100@hints)} )
  same => n,Hangup()

exten => 236,1,Noop(Set a custom status)
  same => n(blink),Set(DEVICE_STATE(Custom:rudolph)=UNAVAILABLE)
  same => n,Set(DEVICE_STATE(Custom:santa)=NOT_INUSE)
  same => n,Wait(0.75)
  same => n,Set(DEVICE_STATE(Custom:rudolph)=NOT_INUSE)
  same => n,Set(DEVICE_STATE(Custom:santa)=UNAVAILABLE)
  same => n,Wait(0.75)
  same => n,Goto(blink)

Then add this to your [hints] context:

exten => 221,hint,ConfBridge:221
exten => santa,hint,Custom:santa
exten => rudolph,hint,Custom:rudolph

Festive, yeah?

Note

You will notice that when you hang up, one of the custom device states will remain “Unavailable.” This is an important point: there is nothing in the system that will update your custom device states, unless you yourself have implemented something to do that.

Conclusion

The device states functionality in Asterisk can be used to track the state of various resources and deliver information about those states to various subscribers. Commonly (and traditionally) used for Busy Lamp Fields, the Custom device state allows this resource to be far more flexible than it would be in a traditional PBX.

1 Items 2 and 3 may be formed as a single string, looking like 100@hints, or something similar.

2 Which is written using the same PJSIP library that Asterisk uses.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset