Bringing Telecommunications In-House - Part 4:
Digium D70

The fourth part in the series bringing my telecommunications in-house. This article will cover setting up my Digium D70 with Asterisk 13 LTS.

Unboxing

The first step in setting up the phone is to get it out of the packaging.

The second step in setting up the phone is to follow the instructions provided of how to assemble it.

The third step in setting up the phone is checking the "What's in the box" section of the "Quick Setup Guide" and noting the following list item:

  • Phone power cord (optional)

The fourth step in setting up the phone is checking the box a second, third, fourth, and fifth time, and realising that you probably should have compared the specifications as well as prices when deciding where to buy it from.

That is correct. I went with the cheapest (taking delivery costs and quickest delivery into account) without looking at why it was cheaper. The retailer wanting 30 GBP more was including the Power over Ethernet (PoE) injector.

Powering the Phone

That left me in a bit of a conundrum. I wanted to set up the phone today (well, yesterday now) because I also have my SIP2SIM card in the post and want this up and running before working on setting up my mobile.

After researching Power over Ethernet, the best option was 25-30 GBP for an injector. No retail stores that I thought might sell them did. So I then searched for PoE compatible switches and routers. Maplin could get one in 3 days, and my local PC World could get one and I could collect it after 5pm tomorrow (today).

OK, how about Amazon? Well, after reading more about PoE and 802.3af (and finally finding out 802.3at is the newer PoE Plus variety), and that my D70 supports PoE and PoE+, I started looking at the reviews of injectors and switches.

While I was considering what I needed and looking at reviews of the items available for evening delivery, I then pondered my future needs.

I plan to, at some point, have an IP security camera and/or web cam, a professional/prosumer Wi-Fi access point (AP) and maybe some other things that can be powered over ethernet.

Thus I decided that a switch with 4 PoE ports that could barely manage to power two D70 phones just won't be worth it, even if it does cost about twice as much as an injector.

I settled on a switch that has 8 Gigabit 802.3at/802.3af compatible ports, with a maximum 30 watts power per port and about 120 watts total PoE. Amazon same day evening delivery, and then I just waited for it.

When it turned up (thanks courier!) I unboxed it, plugged in the power jack, connected a CAT6 cable to my other Gigabit switch, and then hooked up my phone using the CAT5 cable that was supplied with it. The screen lit up! It started booting! It has power and that switch truly was "Plug and Play".

Firmware Update

After booting up the first time, the phone complained it couldn't find an Asterisk server and gave me an IP address to visit on the LAN. I visited it and logged in using the username/password on the Quick Start Guide.

After setting up a profile manually (extension 6003), I made several attempts at trying to upgrade the firmware before Googling the error message.

Getting the Phone to Update Its Own Firmware

Digium provide a help page that explains how to update the firmware manually. Basically it involves creating an XML file and then telling the phone where it is.

I won't go into how it works exactly, but I'll provide a sample of what my xml file looked like:

<?xml version="1.0" ?>
<config>
    <firmwares>
      <firmware model="D70" version="1_4_2_0_63880" url="https://sip.thejc.me.uk/1_4_2_0_63880_D70_firmware.eff" />
    </firmwares>
</config>

The process is, basically, download the firmware file, tar zxvf it, stick the correct .eff file (i.e. ...D70_firmware.eff for me) on a publicly accessible server, stick the URL in an XML file, and then tell the phone to read that XML file.

By "tell the phone", it involves keying stuff in on the phone.

Digium have a help page How to solve the problem writing to disk while upgrading phone firmware and the XML file above is what I used for my phone.

After putting the file on a publicly accessible server, on the phone (assuming it is booted), choose More... (if applicaable) until you see the Menu option, then select Advaned, and then select Reconfigure.

At the Choose Digium Configuration Server screen, press Settings and then select Fetch Configuration File From URL.

A note about fetching from an URL: the server must be accessible by IP address as the phone only allows an IP address to be entered for the server host.

Asterisk DPMA License and Module

The final thing I did was to create an account with Digium, register my D70 product, and get a license key for DPMA.

After getting a key, I followed the steps in getting the module licensed and installed, and then I ran a full system backup and backed up the license key to CD.

Make sure you follow the instructions as they are written. I had to re-run ./register after sudo su because the first time I ran it my Asterisk became unlicensed again a short while later.

Another thing worth pointing out at this stage is that you should check your cat /etc/resolv.conf and make sure the first server listed has an IPv4 IP address - I had trouble running the register utility when an IPv6 DNS resolver was first in the resolv.conf file.

One thing worth mentioning is that the license is tied to the ethernet adapters installed. I'm not sure if that means if I remove/swap my E220 modem my license will stop working or not, but it is something worth noting.

After DPMA is installed, it is time to use DPMA to configure the phone.

There is a reason I am going to be using DPMA for configuration - it seems like it will provide more functionality.


DPMA and sip.conf

For the purposes of setting up my Digium D70 with Asterisk 13 LTS, I am going to be using sip.conf rather than pjsip.conf for one simple reason: I do not yet have enough knowledge about pjsip.conf to be able to create a configuration that works as intended.

One of the things I have done is have the phone configure itself upon power on. I have also not used msdns because I couldn't get it to work. Although I had trouble with DTMF being sent yesterday, it was possibly related to a problem with my ISP rather than a configuration issue given that I made a phone call from my D70 this morning and my DTMF tones were recognised by the DWP phone system.

Anyway, after following Asterisk's DPMA Installation tutorial, you should have the following:

sudo asterisk -rvvv
digium_phones license status
OK, Valid product license found

We are now able to move on and tell the phone what to do.

sudo nano /etc/asterisk/res_digium_phone.conf
[general]
;...
server_uuid=jcsip1
;...
config_auth=mac
;...
[network-jc]
type=network
alias=John Cook Phone Network
cidr=192.168.1.0/24
registration_address=192.168.1.20
registration_port=5060
file_url_prefix = https://192.168.1.20/phoneprov/digium/
public_firmware_url_prefix = http://dphone.dl.digium.com/firmware/asterisk/
ntp_server=0.uk.pool.ntp.org
;...
[John]
type=phone
network=network-jc
mac=000FFF000FFF
active_locale=en_GB
line=6003
line=6004
line=6005
line=6006
line=6007
line=6008
full_name=John Cook
timezone=Europe/London
active_locale=en_GB
ntp_resync=86400
web_ui_enabled=yes
record_own_calls=yes
send_to_vm=yes
lock_preferences=no
d70_logo_file=d70_jc-uk.png
dim_backlight=yes
backlight_timeout=30
backlight_dim_level=0
ringer_volume=10
blf_items=blfitems.xml
blf_contact_group=Internal
contact=contacts.xml

[6003]
type=line
digit_map=6XXX|[0]xx.|[2-9]xxxxx|[2-9]xxxxxxx
line_label=Nominet 6003
transport=udp
reregistration_timeout=300
registration_retry_interval=25
registration_max_retries=5
secret=xxxpasswordxxx

[6004]
type=line
digit_map=6XXX|[0]xx.|[2-9]xxxxx|[2-9]xxxxxxx
line_label=Localphone 6004
transport=udp
reregistration_timeout=300
registration_retry_interval=25
registration_max_retries=5
secret=xxxpasswordxxx

[6005]
type=line
digit_map=6XXX|[0]xx.|[2-9]xxxxx|[2-9]xxxxxxx
line_label=Sipgate 6005
transport=udp
reregistration_timeout=300
registration_retry_interval=25
registration_max_retries=5
secret=xxxpasswordxxx

[6006]
type=line
digit_map=6XXX|[0]xx.|[2-9]xxxxx|[2-9]xxxxxxx
line_label=netSIP 6006
transport=udp
reregistration_timeout=300
registration_retry_interval=25
registration_max_retries=5
secret=xxxpasswordxxx

[6007]
type=line
digit_map=6XXX|[0]xx.|[2-9]xxxxx|[2-9]xxxxxxx
line_label=Dial Out Line 1
transport=udp
reregistration_timeout=300
registration_retry_interval=25
registration_max_retries=5
secret=xxxpasswordxxx

[6008]
type=line
digit_map=6XXX|[0]xx.|[2-9]xxxxx|[2-9]xxxxxxx
line_label=Dial Out Line 2
transport=udp
reregistration_timeout=300
registration_retry_interval=25
registration_max_retries=5
secret=xxxpasswordxxx

In the above, my phone is named John, and the lines 6003-6008 are "internal" to Asterisk (i.e. a sip.conf peer/friend).

As for the phone [John]'s preferences, I will now detail the options I have used:

type=phone
It is a phone.
network=network-jc
The network this phone belongs to is called network-jc in this file.
mac=000FFF000FFF
This phone has the MAC address 000FFF000FFF (not really, replace as applicable).
line=600x
This phone supports 6 lines, and I'm going to use all of them. See sections [6003] through [6008] for more details.
full_name=John Cook
My name is John Cook.
timezone=Europe/London
My timezone is that of the UK.
active_locale=en_GB
Use British English please.
ntp_resync=86400
Check time accuracy every 86,400 seconds (24 hours)
web_ui_enabled=yes
Enable the Web User Interface.
record_own_calls=yes
Enable the option to record calls.
send_to_vm=yes
Enable the option to send to voicemail.
lock_preferences=no
Let me change settings from the phone.
d70_logo_file=d70_jc-uk.png
There is an 8-bit PNG file with this name in the network's (network-jc) file_url_prefix.
dim_backlight=yes
Dim the backlight.
backlight_timeout=30
Dim after 30 seconds.
backlight_dim_level=0
Dim the backlight to level 0 (off).
ringer_volume=10
Set the volume level to maximum.
blf_items=blfitems.xml
The BLF Items file for this phone has this file name.
blf_contact_group
The contact group in the BLF file is called Internal.
contact=contacts.xml
The Contacts file for this phone has this file name.

All the files are stored in (and accessible to the phone from) the directory https://192.168.1.20/phoneprov/digium/.

At this point you should be able to tell the phone to reconfigure itself, as was done for firmware updating but this time refresh the servers list and select the right server/network.

I may have missed a couple of things here, as I had a lot of trouble getting the phone to configure itself. I should also point out that because my sip.thejc.me.uk server was, at that point in time, publicly accessible my contacts.xml did not contain the phone numbers of any people I know (i.e. personally identifiable information).

Restricting /digium/ to LAN

As I have previously mentioned, I am using nginx as a HTTPS termination point, and lighttpd as a web server.

sudo nano /etc/nginx/conf.d/example_ssl.conf
server {
        listen 443 ssl spdy;
        server_name sip.thejc.me.uk;
        ssl_certificate         /etc/ssl/asterisk/sip_thejc_me_uk.pem;
        ssl_certificate_key     /etc/ssl/asterisk/sip_thejc_me_uk.key;

        ssl_session_cache       shared:SSL:1m;
        ssl_session_timeout     5m;

        ssl_ciphers             "ECDH+AESGCM:DH+AESGCM:ECDH+AES256:DH+AES256:ECDH+AES128:DH+AES:ECDH+3DES:DH+3DES:RSA+AESGCM:RSA+AES:RSA+3DES:!aNULL:!MD5:!DSS";

        location / {
                proxy_pass      http://sip.lighttpd;
                proxy_set_header        Accept-Encoding $spdy_ae;
                proxy_set_header        Host    $host;
                proxy_set_header        X-Real-IP       $remote_addr;
                proxy_set_header        X-Forwarded-For $proxy_add_x_forwarded_for;
                proxy_pass_request_headers      on;
        }
}
sudo nano /etc/nginx/nginx.conf
...
user www-data;
...
http {

upstream sip.lighttpd {
        server 192.168.1.20:8090;
}

ssl_protocols TLSv1 TLSv1.1 TLSv1.2;

map $spdy $spdy_ae {
        default  $http_accept_encoding;
#       default "gzip";
        2        "gzip, deflate";
        3        "gzip, deflate";
        3.1        "gzip, deflate";
    }

map $spdy $spdy_connection {
        default "0";
        2       "1";
        3       "1";
        3.1     "1";
}

proxy_pass_request_headers on;
...
sudo nano /etc/lighttpd/lighttpd.conf
include "modules.conf"

server.chroot               = "/home/www"
server.document-root        = "/var/www"
server.upload-dirs          = ( "/var/cache/lighttpd/uploads" )
accesslog.filename          = "/var/log/lighttpd/access.log"
server.errorlog             = "/var/log/lighttpd/error.log"
server.pid-file             = "/var/run/lighttpd.pid"
server.username             = "www-data"
server.groupname            = "www-data"
server.port                 = 80
server.bind                 = "192.168.1.20"
extforward.forwarder = (
        "192.168.1.20" => "trust",
)
...
include "vhosts.d/johncook.co.uk"
sudo nano /etc/lighttpd/modules.conf
server.modules = (
        "mod_access",
        "mod_alias",
        "mod_compress",
        "mod_redirect",
#       "mod_rewrite",
        "mod_accesslog",
        "mod_extforward",
)

include "conf.d/fastcgi.conf"
sudo nano /etc/lighttpd/vhosts.d/johncook.co.uk
...
$SERVER["socket"] == "192.168.1.20:8090" {
        var.servername = "/sip.thejc.me.uk"
        server.document-root = var.basedir + servername
        $HTTP["remoteip"] !~ "^192\.168\.1\." {
                url.access-deny = (
                        "/phoneprov/",
                )
        }
}

This is a lot of code, but the main things to note are that nginx is sending a forwarded by header, lighttpd has mod_extforward enabled (position is important), lighttpd trusts forwarder headers from the IP address nginx uses (192.168.1.20), and when it comes to the Web site at 192.168.1.20:8090, lighttpd denies access to /phoneprov/* to IP addresses that do not start with 192.168.1..

Before putting contact details of people (as opposed to internal extensions and publicly listed phone numbers for organisations), check that the restrictions are working (i.e. accessing /digium/ over 3G should result in a 403, whereas over Wi-Fi a 404).

BLF File

My BLF file and contacts file are straight forward once you understand them.

nano /home/www/var/www/sip.thejc.me.uk/phoneprov/digium/blfitems.xml
<?xml version="1.0">
<config>
<smart_blf>
<blf_items>
<blf_item location="side" index="0" paging="0" contact_id="101">
        <behaviors>
                <behavior phone_state="idle" target_status="ringing" press_action="intercept" press_function="dial" />
        </behaviors>
<indicators>
<indicator target_status="unknown" ring="0" led_color="amber" led_state="on" />
<indicator target_status="idle" ring="0" led_color="green" led_state="off" />
<indicator target_status="ringing" ring="0" led_color="red" led_state="fast" />
<indicator target_status="on_the_phone" ring="0" led_color="red" led_state="on" />
<indicator target_status="on_hold" ring="0" led_color="amber" led_state="fast" />
</indicators>
</blf_item>
<blf_item location="side" index="1" paging="0" contact_id="102">
        <behaviors>
                <behavior phone_state="idle" target_status="ringing" press_action="intercept" press_function="dial" />
        </behaviors>
<indicators>
<indicator target_status="unknown" ring="0" led_color="amber" led_state="on" />
<indicator target_status="idle" ring="0" led_color="green" led_state="off" />
<indicator target_status="ringing" ring="0" led_color="red" led_state="fast" />
<indicator target_status="on_the_phone" ring="0" led_color="red" led_state="on" />
<indicator target_status="on_hold" ring="0" led_color="amber" led_state="fast" />
</indicators>
</blf_item>
<blf_item location="side" index="2" paging="0" contact_id="103">
        <behaviors>
                <behavior phone_state="idle" target_status="ringing" press_action="intercept" press_function="dial" />
        </behaviors>
<indicators>
<indicator target_status="unknown" ring="0" led_color="amber" led_state="on" />
<indicator target_status="idle" ring="0" led_color="green" led_state="off" />
<indicator target_status="ringing" ring="0" led_color="red" led_state="fast" />
<indicator target_status="on_the_phone" ring="0" led_color="red" led_state="on" />
<indicator target_status="on_hold" ring="0" led_color="amber" led_state="fast" />
</indicators>
</blf_item>
<blf_item location="side" index="3" paging="0" contact_id="105">
</blf_item>
<blf_item location="side" index="4" paging="1" contact_id="104"></blf_item>
<blf_item location="side" index="5" paging="1" contact_id="106"></blf_item>
<blf_item location="side" index="6" paging="1" contact_id="107"></blf_item>
<blf_item location="side" index="7" paging="1" contact_id="108"></blf_item>
<blf_item location="side" index="8" paging="1" contact_id="109"></blf_item>
<blf_item location="side" index="9" paging="1" contact_id="110"></blf_item>
<blf_item location="side" index="4" paging="1" contact_id="111"></blf_item>
<blf_item location="side" index="5" paging="1" contact_id="112"></blf_item>
<blf_item location="side" index="6" paging="1" contact_id="119"></blf_item>
<blf_item location="side" index="7" paging="1" blank="1"></blf_item>
<blf_item location="side" index="8" paging="1" blank="1"></blf_item>
<blf_item location="side" index="9" paging="1" blank="1"></blf_item>
<blf_item location="side" index="4" paging="1" contact_id="113"></blf_item>
<blf_item location="side" index="5" paging="1" contact_id="114"></blf_item>
<blf_item location="side" index="6" paging="1" contact_id="115"></blf_item>
<blf_item location="side" index="7" paging="1" contact_id="116"></blf_item>
<blf_item location="side" index="8" paging="1" contact_id="117"></blf_item>
<blf_item location="side" index="9" paging="1" contact_id="118"></blf_item>
</blf_items>
</smart_blf>
</config>

There are two options for location, main and side. Main is the main display (where the line keys are) and side is for the side panel. I do not use location="main" in blfitems.xml because I have fully populated the main display, and wouldn't want contacts there anyway.

There are ten BLF items on the side panel. One of the reasons I went with the D70 is because it has an electronic side panel, which I have already referred to for a telephone number (Virgin Media wanted my landlord's phone number).

You can have multiple pages on the D70, but if you say an item has paging="0" then it will be fixed across pages. Digium phones do not correct you when it comes to valid XML, so if you make a mistake (e.g. editing the wrong contact so you ended up with your landlord being dialled when you press *8) you may not notice at first. Thankfully I knew this, so the first line on my phone can only dial internal lines and SIP ENUM results.

Because there can be multiple pages, and you can have items fixed across pages, you might want to separate contacts so they are in groups. For example, on the second page I have assigned it as the place for medical contacts.

As I only have 3 medical contacts (because, for example, the third one (contact 119) is for Mental Health and the primary number is for appointments, but pressing the info key and then Mental Health gives the option for dialling Appointments, Switchboard, 2nd Floor, 3rd Floor, and Out of Hours) I have 3 spare spaces and wanted to put the next group of contacts (family) on the 3rd page.

As I said, the D70 doesn't guess what is meant by your XML. That is why index 7, 8, and 9, on the thrid page are blank="1" signifying a blank space. Without them, contacts 116, 117, and 118 would be displayed on the second page.

Finally, there are the first 4 contacts on page 1 (all with paging="0". Behaviors are how the phone acts depending on what is happening. The primary action in contacts.xml for contacts 101, 102, and 103 is to dial 6001, 6002, and 6010 respectively.

If that extension, however, is "ringing", and the D70 is idle (phone_state="idle") then pressing the button now will cause the intercept action to happen. In the case of contact 101, that is a primary action of dial="6001" and an intercept action of dial="6001" dial_prefix="**" - that is, if contact 101 has a status of ringing, pressing the BLF key will dial **6001, which (as the action describes) will intercept the call.

The Digium D70 has 3 led colours (led_color): red, amber, and green. Extension 6001 is Groundwire on my iPhone, 6002 is Groundwire on my iPad, and 6010 is my AAISP SIP2SIM mobile. If those 3 indicator lights aren't on, all is good. If any of them are red and I am not making the call, there is the possibiliy the credentials for that extension have been compromised.

A flashing red 6010 means my mobile is ringing and I can hit the button and answer that line. This will occur when I have set the status on my D70 to Do Not Disturb, which will cause only my mobile to ring (and possibly Groundwire if set to receive calls). A steadly amber 6010 means my SIP2SIM probably needs to re-register else it might be unreachable for an hour. A steady amber 6001 and 6002 means either my iPhone/iPad are out of 3G/Wi-Fi range, the push server is broken, they aren't configured properly, or some other issue. If all 3 are amber it is possible my public IP address has changed and I need to flush the DNS cache (or wait).

The reason I have included target_status="idle" is for testing purposes. If I want to check the lamps are working as expected I set led_state="slow" so I can debug.

One of the advantages of this setup is that my phone is below my monitor and in my eye line. If extension 6001 has an unknown state, I will see the light come on in the corner of my eye letting me know that text messages might not come through. Also, if I forget to turn DND off on my D70 (or I am awoken by my mobile rining) I can hit the button for ringing extension 6010 on the D70 and not only answer the call but also save the pennies per minute of needlessly answering it on my mobile.

Contacts File

Again, the contacts.xml file is pretty self-explanatory.

nano /home/www/var/www/sip.thejc.me.uk/phoneprov/digium/contacts.xml
<?xml version="1.0">
<phonebooks>
<contacts group_name="Internal" editable="0" id="0">
<contact server_uuid="jcsip1"
id="101"
first_name="John"
last_name="Cook"
contact_type="sip"
notes="Mobile Wi-Fi/3G"
subscribe_to="6001">
<actions>
<action id="primary" dial="6001" label="iPhone Wi-Fi/3G" />
<action id="intercept" dial="6001" dial_prefix="**" label="Intercept" />
</actions>
</contact>
<contact server_uuid="jcsip1"
id="102"
first_name="John"
last_name="Cook"
contact_type="sip"
notes="iPad Wi-Fi/3G"
subscribe_to="6002">
<actions>
<action id="primary" dial="6002" dial_prefix="" label="iPad Wi-Fi/3G" />
<action id="intercept" dial="6002" dial_prefix="**" label="Intercept" />
</actions>
</contact>
<contact server_uuid="jcsip1"
id="103"
first_name="John"
last_name="Cook"
contact_type="sip"
notes="Mobile Phone"
subscribe_to="6010">
<actions>
<action id="primary" dial="6010" label="Mobile Phone" />
<action id="intercept" dial="8" dial_prefix="*" label="Intercept" />
</actions>
</contact>
<contact server_uuid="jcsip1"
id="105"
first_name="John"
last_name="Cook"
contact_type="special"
notes="D70 Presence"
subscribe_to="6003"></contact>
</contacts>
<contacts group_name="Property" editable="0" id="1">
<contact server_uuid="jcsip1"
id="104"
first_name="Name of"
last_name="Landlord"
contact_type="sip">
<actions>
        <action id="primary" dial="+447..." label="Mobile Phone" />
</actions>
</contact>
<contact server_uuid="jcsip"
id="106"
first_name="Neighbour 1"
contact_type="sip">
<actions>
<action id="primary" dial="+447..." label="Left Neighbour" />
</actions>
</contact>
<contact server_uuid="jcsip1"
id="107"
first_name="Neighbour"
last_name="2"
contact_type="sip">
<actions>
<action id="primary" dial="+441923..." label="Other Neighbour" />
</actions>
</contact>
</contacts>
<contacts group_name="Friends" editable="0" id="2">
<contact server_uuid="jcsip1"
id="108"
first_name="Friend"
last_name="Name"
contact_type="sip">
<actions>
<action id="primary" dial="+447..." label="Mobile Phone" />
</actions>
</contact>
</contacts>
<contacts group_name="Family" editable="0" id="3">
<contact server_uuid="jcsip1"
id="109"
first_name="..."
last_name="..."
contact_type="sip">
<actions>
<action id="primary" dial="+447..." label="Mobile Phone" />
</actions>
</contact>
<contact server_uuid="jcsip1"
id="110"
first_name="..."
last_name="..."
contact_type="sip">
<actions>
<action id="primary" dial="+447..." label="Mobile Phone" />
</actions>
</contact>
<contact server_uuid="jcsip1"
id="113"
first_name="..."
contact_type="sip">
<actions>
<action id="primary" dial="+441923..." label="Parents Home" />
</actions>
</contact>
<contact server_uuid="jcsip1"
id="114"
first_name="..."
last_name="..."
contact_type="sip">
</contact>
<contact server_uuid="jcsip1"
id="115"
first_name="..."
last_name="..."
contact_type="sip">
</contact>
<contact server_uuid="jcsip1"
id="116"
first_name="..."
last_name="..."
contact_type="sip">
</contact>
<contact server_uuid="jcsip1"
id="117"
first_name="..."
last_name="..."
contact_type="sip">
</contact>
<contact server_uuid="jcsip1"
id="118"
first_name="..."
contact_type="sip">
<actions>
<action id="primary" dial="+441255..." label="Grandparents Home" />
</actions>
</contact>
</contacts>
<contacts group_name="Health" editable="0" id="4">
<contact server_uuid="jcsip1"
id="111"
first_name="GP"
organization="..."
contact_type="sip">
<actions>
        <action id="primary" dial="+441923..." label="GP Office" />
        </actions>
</contact>
<contact server_uuid="jcsip1"
id="112"
first_name="Dentist"
organization="..."
contact_type="sip">
<actions>
<action id="primary" dial="+441923..." label="Dentist Office" />
</actions></contact>
<contact server_uuid="jcsip1"
id="119"
first_name="Mental Health"
contact_type="sip">
<actions>
<action id="primary" dial="+441923..." label="Appointments" />
<action id="switchboard" dial="+441923..." label="Switchboard" />
<action id="floor2" dial="+441923..." label="2nd Floor" />
<action id="floor3" dial="+441923..." label="3rd Floor" />
<action id="outofhours" dial="+441438..." label="Out of Hours" />
</actions>
</contact>
</contacts>
</phonebooks>

I don't think that file needs any explanation.

Dial Plan Hints

At this point, I have the auto_hint_'s for the 6 lines on the phone (as shown in Asterisk core show hints) but not extensions 6001, 6002, and 6010. In order to fix this, we need to edit extensions.conf:

sudo nano /etc/asterisk/extensions.conf
...
[internal]
; All internal extensions are 4 digits and start with 6.
exten => 6001,hint,SIP/6001
exten => 6002,hint,SIP/6002
exten => 6009,hint,SIP/6009
exten => 6010,hint,SIP/6010
exten => 6010,1,Set(CALLERID(name)=${CALLERID(num)})
exten => 6010,2,Dial(SIP/6010,0,tr)
exten => _6XXX,1,Set(__PICKUPMARK=${EXTEN})
exten => _6XXX,n,Dial(SIP/${EXTEN})
exten => _**6XXX,1,Pickup(${EXTEN:2}@PICKUPMARK)

; Replace 00 with +
exten => _00.,1,Verbose(1,Replacing 00 with +)
exten => _00.,n,Goto(+${EXTEN:2},1)

; Replace 0 with +44
exten => _0.,1,Verbose(1,Replacing 0 with +44)
exten => _0.,n,Goto(+44${EXTEN:1},1)

; Assume all 6 digit length numbers are Watford area code, 0 is trunk, 1 is national.
; TODO: If at a later date Watford (01923) requires dialling of the area code
;  because there are not enough available phone numbers, so that 01923 1XX XXX
;  and 01923 0XX XXX can start to be allocated, comment out _ZXXXXX lines.
exten => _ZXXXXX,1,Verbose(1,Adding Watford Area Code)
exten => _ZXXXXX,n,Goto(+441923${EXTEN},1)
; Assume all 8 digit length numbers are London area code, 0 is trunk, 1 is national.
exten => _ZXXXXXXX,1,Verbose(1,Adding London Area Code)
exten => _ZXXXXXXX,n,Goto(+4420${EXTEN},1)

...

By adding those hint priorities, the BLF indicator lights should now work. I have included the whole [internal] section here to show the result of my original thinking and consequent extension numbering. The D70 cannot dial a plus symbol, but since the internal context is included in the contexts used for the 6 lines, dialing the international dialling prefix will get converted to a plus symbol, and dialling the trunk prefix will replace the 0 prefix with a +44 UK prefix.

Likewise, I can dial a 6 digit number from my mobile phone and it will call a +441923 Watford number, and calling an 8 digit number will result in Asterisk prefixing it with +4420 and dial a London number.