Using Custom Device States to control BLF lamps

Do you want to know how to use a custom device state to control the lamp on a programmable key of an IP phone? In this article I explain how to set up the hints and make any number of IP phones subscribe to a custom device state and how to switch the custom status from within the Asterisk dial plan.

In later articles I plan to show how this can be put to a practical use. I will explain how to switch the state from an external script and use this to provide a shared voicemail box linked to a programmable key on several extension phones.

Does your version of Asterisk support custom device states?

The first step is to make sure Asterisk supports custom device states. Version 1.2 and all earlier versions did not support this feature. Version 1.6 does support it. If you have version 1.4 then it might or might not support the feature – it did not come as standard, but was available as a kind of after-sales upgrade. The module we are looking for is and you should check that it is available on your Asterisk server before proceeding.

You can check if the module is present by typing the command “module show like devstate” at the Asterisk CLI (Command Line Interface). If the module is installed, you should see the following output:

Module              Description                               Use Count    Gets or sets a device state in the dialp  0
1 modules loaded

A further check is to look for the Asterisk function that is exported by the devstate module. The function we are looking for is DEVICE_STATE. You can search for installed functions using a CLI command. To check for any function containing the word “STATE”, the command would be “core show functions like STATE”. You should see the following output:

Matching Custom Functions:
DEVICE_STATE      DEVICE_STATE(device)                 Get or Set a device state
EXTENSION_STATE   EXTENSION_STATE(extension[@context]  Get an extension's state
2 matching custom functions installed.

Using the DEVICE_STATE function

Custom devices are dynamically created when the dial plan assigns a value to one of them using the Set command. Each new custom device takes whatever name you choose when assigning the value – there is no pre-existing master list of custom devices and no list has to be explicitly created or maintained. This has advantages (simplicity) and disadvantages (typing errors in device names will not be trapped). Note, however, that there is a pre-defined list of states that can be assigned to a device – see below.

From the Asterisk CLI, you can view information about the DEVICE_STATE function by typing the command “core show function DEVICE_STATE”. This shows you how to set a state for a custom device called “lamp1” and it also shows a list of all the permitted state values that you may assign to a device. Depending on the make of IP phone you are using, different states will typically cause the lamp to go on continuously, to flash fast or slow or potentially even to change colour where that is an option. You should experiment to see what happens for different values, but remember what happens on a Snom may not be the same on a Grandstream, etc. The states available are:


For example, to assign the INUSE value to a custom device called OnLeave:

exten => _X.,n,Set(DEVICE_STATE(Custom:OnLeave)=INUSE)

Linking a device state to an Asterisk hint

Remote SIP devices, such as IP phones, use a subscribe-notify mechanism to monitor the status of a device on Asterisk. To do this they send a SUBSCRIBE request to Asterisk with an identification tag that must match an Asterisk hint. In other words, custom device states (and any other device state) can only be seen by using a hint in the dialplan. Hints are explained in more detail in my article here.

Adding the following to your dial plan would link the subscribe tag 6123 to the state of the custom device called OnLeave:

exten => 6123,hint,Custom:OnLeave

To be sure that the hint can be found, it is best to add it to the context that is normally used by the subscribing phone. This may be the “default” context or, if using Trixbox or FreePBX, it would usually be the “from-internal” context. To add a hint for your Trixbox or FreePBX extensions, you will have to edit the file /etc/asterisk/extensions_custom.conf and add a context called ext-local-custom and put the hint in that. It would look like this:

; Add hint to link to the Custom Device State
exten => 6123,hint,Custom:OnLeave

The “tag” value of 6123 that was used for the example above is, in part, an arbitrary number. It must be unique, at least so no two hints use the same number in the same context. It must match the value you set on the subscribing device (usually that means the number assigned to the BLF programmable key on your IP phone). However, for reasons that should become apparent as you read on, your choice for this number may be influenced by your wish to not only activate a lamp on your IP phone, but to also make the key next to that lamp do something relevant and useful.

Setting up the BLF programmable key on the IP phone

BLF stands for Busy Lamp Field and the terminology is inherited from older phone systems where the operator could view the status of every extension and trunk on a display board. The board would be populated with an array of lamps, each representing one extension or one trunk line on the telephone system. The manufacturers of modern IP phones use BLF to describe the option that is available on programmable keys to make them subscribe (via SIP) to monitor the status of other extensions or other devices. This is the how you can link a programmable key and its associated lamp to a device state in Asterisk.

Setting up the IP phone should be very straightforward provided your phone has a spare programmable BLF key. Not all phones have directly programmable keys – for example the Linksys SPA942 has four line keys, but they cannot be re-assigned using the web interface. One of my favourite budget IP phones for use as an Asterisk extension is the Aastra 6731i – it has a total of 8 programmable keys although two of these are pre-assigned and harder to change, but that still leaves 6. Snom refer to them as Function Keys, but they are the same thing.

Each make of phone is different, but generally it should be straightforward to use the web interface of your phone, find the page where programmable keys are set and choose the key you want to set. Set the type as BLF and set the number (or value) to match the tag number used in the hint – 6123 in the examples above. There is often another field for each key where you can select the account or line. In almost all cases you should set this to be the account that is used to register the phone with Asterisk. Don’t forget to save the new settings and reboot the phone if needed (it is not usually necessary).

That should be sufficient. The phone will send a SUBSCRIBE request to Asterisk. Asterisk will match it to the hint which in turn links it to the custom state. You can check what subscriptions are active at the Asterisk command line interface using the command “sip show subscriptions”. It is also possible to see a list of all the hints – i.e. what you can subscribe to – using the CLI command “core show hints”. The last column in the output from this command is a column showing how many “Watchers” are subscribed to this hint. It is perfectly acceptable for more than one IP phone to subscribe to the same hint at the same time.

If you press the button on a BLF programmed key, it will place a call to the number that you assigned to the key. Since there is considerable flexibility in your choice for this number and further flexibility in the Asterisk dial plans to respond to a dialled number, you should be able to configure the system so the action of the key is sensibly linked to the activation of the lamp. One example is for the lamp to show that there are messages waiting in a shared voicemail box and the key is used to access the messages in the box. Details of how to do this are now available in a 2-part article on this site – click here for part 1.

6 thoughts on “Using Custom Device States to control BLF lamps”

  1. Wonderful, understandable explanation! It is so nice to see someone who understands complexity well enough to describe it with simple language.

    I am trying to use the blf function on my asterisk (1.8) pbx connected to my Aastra 57i (v3.2) phones.

    I got it working just fine in one install where the pbx and phones are on the same domain ( behind a firewall.

    I cannot get it to work in another installation and the only difference I can figure is that in the second installation, the phones are on one domain ( and the pbx is on another domain (

    Does blf usually NOT work if the phones and pbx are on different domains?

    What little hair I have left is being pulled out over this one so I hope you have some insight.

    • I can think of more than one possible explanation, mostly linked to “privacy/security”. The first and most likely concerns the context where the hints were inserted. Does it match the context that the phone on the other domain uses?

      Check out this link. Take a look at the section headed “Standard Priorities” and especially the paragraph that explains about Privacy considerations and “subscribecontext”:

      Unfortunately, there is almost no documentation explaining about the subscribecontext parameter (that I could find). There’s some examples of its use shown here:

      Have you established if the subscription is registering at all? i.e. have you checked the output of the CLI commands “core show hints” and “sip show subscriptions” (for more info about this check my other article here:

      One final point – I don’t want to criticise, but when you talk about “domains” your terminology is a little ambiguous. I always try to refer to different IP address spaces as subnets. Domains can be SIP Domains, Windows Active Directory domains, DNS domains, etc. Asterisk can support different SIP Domains and these can be used as part of a security policy which just might be behind your problems, but it depends if you are using SIP domains and if that is what you mean. See this article for more details:

      Ah, and one final thought – you can get odd behaviour when the IP routing is not working properly between two subnets. To identify this type of problem, it is useful to capture the raw SIP messages using wireshark or similar. If it comes to that, you could email me a pcap file and I will take a look.

      Hope this helps.

  2. This is really a good post.

    I want to use this for knowing the state of a sip trunk, but is really difficult to see were I have to put the sentences.

    Is there a way for doing that simplier?

    thanks in advance

    • It is quite difficult to use a custom device state to monitor a SIP trunk. If the trunk is able to carry more than one concurrent call then you would have to increment a count (a global variable) every time a call started on the trunk and decrement the variable every time a call ended. When the global variable is zero you would switch the lamp off, when it is positive you switch the lamp on.

      It would be simpler if your SIP trunk never handled more than one call at a time. The solution would also depend if you are using native Asterisk or a package like Trixbox or FreePBX.

      Regrettably, it is a bit too complicated to answer here.

Comments are closed.