Device control over HDMI via CEC. libcec FTW.

Blimey, it’s been a while.  I’ve been a bit busy, and let’s be honest; writing up blog posts always sounds like a good idea, but when you get in to it – it’s really hard work.

Anyway – I finally got round to buying a Pulse-Eight CEC to USB adapter:

This awesome little box of tricks makes up for the lack of CEC control in the vast majority of HDMI-Out equipped graphics cards.  It’s the final piece in the jigsaw of a Linux based home entertainment device.  It allows you to talk to the other devices in your HDMI network; your surround sound amplifier and your big screen TV being the best examples (assuming they support CEC of course).

CEC has been around for a long time but for some reason it doesn’t seem to be widely used, or very well implemented, in most consumer electronics devices.  It’s a published standard but with OEM manufacturers wanting to differentiate their products and introduce a bit of vendor lock-in, they all call it something different.  The fact is that your Toshiba Regza Link TV will talk to your Sony Bravia Link Amp just fine, for the most part.  There might be a couple of proprietary things which don’t work, but on, off, volume up, volume down etc will all just work.

Pulse Eight’s USB to CEC adapter lets your computer get in on the act too, and opens up a whole realm of automatic switching, which really cuts down on the number of remote controls you need and the number of buttons you have to remember the purpose of.

The good folk at Pulse Eight have also made libCEC, an open source library to allow pretty much any software to take advantage of the USB adapter.

It comes with C++, C and .NET interfaces, and a CLI utility called cec-client.  XBMC & MythTV already support libCEC and have some neat features baked right in.  It’s good, but it’s not exactly what I was looking for – I want a bit more control.

Now, I don’t know anything about C++ or C or .NET, so until someone writes some Python bindings, my ticket to this party lies solely with the CLI utility cec-client.  It can do most things on the “transmit” side, so you can send commands to your other CEC devices fairly easily.  Acting on a request, or listening to the CEC traffic is a bit more complex – but not beyond the realms of possibility.

This weekend I wrote (and rewrote and rewrote) a couple of Bash scripts to:

  • Let me control the system volume (i.e. the real hardware, not the mixer on the computer) on the TV & Amp from the PCs remote control
  • Let me switch the TV & Amp on and off
  • Activate proper muting, again not the mixer on the computer – the hardware itself
  • Switch the amp & TV to my MythTV PC
  • Power off all the hardware when the PC suspends, and then switching it all back on again
  • Shut the whole lot down when the screensaver on the PC kicks in.

I make these scripts available for your amusement:

cecsimple is a client of the “server” which itself is a client of cec-client.  Fire up the server and then issue it commands down the FIFO either directly or via the abstraction layer which is


I hooked up the volume control and amp power via “irexec” and lirc.  I tell irexec to execute, for example, “ volup” or “ ampon”.  If the server component is already running then these commands are sent very quickly and you don’t really notice the lag.

To switch the TV off when the PC goes in to suspend mode I added a script in /etc/pm/sleep.d which calls “ tvoff” and then “ tvon” when it resumes.  In theory if the TV is using the Amp to output surround sound audio then the TV will tell the Amp to turn off, it it’s not – it wont.

To switch things off when the screensaver kicks in, I simply “sudo pm-suspend” from an “xscreensaver-command -watch” script.


The practical upshot is that I can now control 99% of my media centre from a single remote control.  I’ve opted to use the remote connected to the PC as I found it to be the least laggy – using the TV remote to send up/down/left/right etc to the PC was sluggish.


I think it should be possible to parse the log output from cec-client and write a “listener” component too, but it’s probably a better idea to learn some rudimentary C and do it properly.  Or some Python bindings.  Oh yeah, and you know what would be really cool, a hook in to MythTV so that when I’m watching something in surround sound the amp turns on automatically. That would be cool.


UPDATE 3 Dec 2013:  When someone leaves the amp’s HDMI switch set on the PS3 and you switch the MythTV box on from the remote, the amp doesn’t automatically switch to MythTV.  This has been annoying me for a while now, so I fixed it.

In the scripts linked to above the “active source” command does this:

send_command "tx 45 82 11 00"

4 (the MythTV device) to 5 (the amp) – 82 (switch active source) to – but my Sony amp just ignores this request.

I spent some time trying out a few alternatives with cec-client and I’ve found one which works, and it kinda makes sense why:

send_command "tx 45 70 11 00"

4 (MythTV) to 5 (Sony amp) 70 (System Audio Mode) (the input where MythTV is connected)

My assumption is that amp only speaks “system audio” – what with it being an amp.  I’ve changed the “activesrc” with the 45:70:11:00 code and now it works!  (It also switches the amp on, whether I like it or not – so it’s not perfect).



Useful links:


Over engineering FTW

Working from home has many advantages.  No commuting, relaxed approach to being dressed, loud music.

One of the drawbacks however, is that you are entirely reliant on your broadband connection.  You could, as many do, have a 3G modem/phone as a backup.  Fine for a few hours, but you’re soon going to run in to data caps, invisible proxies and traffic shapers (more so than a fixed line telco).


So what to do?  My solution has been to get a second line installed.  The big UK telcos are running a lot of offers at the moment to try and secure as many customers as they can in readiness for their Triple & Quadruple Play strategies.  This means you can get a reasonable ADSL line and line rental for about 15 to 20 quid a month.

When you’re as reliant on a connection as I am, that’s money well spent.  It also gives you a perfect opportunity to play with some new toys!

Now, you could simply plug in another wifi router to the new line, and when the primary connection fails move your connections over to the secondary one.  But where’s the fun in that?  What you really want to do is some load-balancing and multi-path routing over both the lines.  You won’t see a sudden doubling in download speeds in normal browsing, but certain activities which open a lot of connections to different IP address should benefit, and you get to play with routing tables.

Here’s what it looks like:


We don’t really get much diversity until we get south of the exchange, and even then we’re probably going to live in the same fibre all the way to The Internet, but we do work round the much more common problem of ISP configuration errors.

Here’s how it works:

Router 1 (R1) and Router 2 (R2) are two independent ADSL modem/routers  connected to a phone line each and the ethernet port connected to a NIC in a server.  These modem/routers also take care of NAT, so that any traffic coming from inside your network will be translated to appear as if it had come from the appropriate router on it’s way to the rest of the internet.  The server has three NICs in total, one each for the two routers and one back to the LAN for everyone else on the network to use as a gateway.

$IF0 = eth0
$IF1 = eth1
$IF2 = eth2

The IP addresses associated with those interfaces are:

$IP0 =
$IP1 =
$IP2 =

The routers are configured with these LAN IPs:

$P1 =
$P2 =

As you can see on the diagram, the networks are all /24 ( which gives us network numbers of:

$P0_NET =
$P1_NET =
$P2_NET =

Then we configure the Ubuntu box as a router & NATing gateway:

1.  Enable IP forwarding by editing /etc/sysctl.conf and uncommenting or adding a line like this:


2.  Create two new routing tables.  Edit /etc/iproute2/rt_tables and add a line for each of your providers.  For example:

1 my_isp_name
2 my_other_isp_name

3. Create some routes in each of the routing tables so the server knows where to send data.  They take the general format of:

ip route add $P1_NET dev $IF1 src $IP1 table my_isp_name
ip route add default via $P1 table my_isp_name
ip route add $P2_NET dev $IF2 src $IP2 table my_other_isp_name
ip route add default via $P2 table my_other_isp_name


Using the real numbers and the template above gives us this actual set of commands:

ip route add dev eth1 src table my_isp_name
ip route add default via via eth1 table my_isp_name
ip route add dev eth2 src table my_other_isp_name
ip route add default via via eth1 table my_other_isp_name


In english, that means:  In order to send traffic to the network or the network send it out of eth1 or eth2 from IP address or  These routes are then stored in the relevent routing table; either one called my_isp_name or one called my_other_isp_name.


4. Create some additional routes for communicating between the routing tables and the local interfaces.  This is as much of an efficiency saving as anything, telling each routing table the quickest way to the other interfaces.

ip route add $P0_NET dev $IF0 table my_isp_name
ip route add $P2_NET dev $IF2 table my_isp_name
ip route add dev lo table my_isp_name
ip route add $P0_NET dev $IF0 table my_other_isp_name
ip route add $P1_NET dev $IF1 table my_other_isp_name
ip route add dev lo table my_other_isp_name

5.  Add the routes to the main routing table, so that traffic knows how to find the networks which have the gateways to the internet on:

ip route add $P1_NET dev $IF1 src $IP1
ip route add $P2_NET dev $IF2 src $IP2

6.  Apply the correct routing rules depending on where the traffic is coming from:

ip rule add from $IP1 table my_isp_name
ip rule add from $IP2 table my_other_isp_name

7.  The science bit.  Create a route which will send traffic down each of the internet connections in turn.  This is a global default route, so any traffic which isn’t bound for the local $P0_NET network will use this rule to get to the internet.

ip route add default scope global nexthop via $P1 dev $IF1 weight 2 nexthop via $P2 dev $IF2 weight 1

As you can see, this isn’t a 50/50 split.  We’ve applied some weighting, in this case because I get more GBs with my_isp_name.  We’re actually going to send twice as much traffic down $IF1 as we are down $IF2.

8.  By default, routes to other networks are cached for 10 mins.  This means that once a route is decided on, traffic will always follow the same route for at least the next 10 minutes.  The counter will be reset every time that particular route is used.  This is great for large downloads because it means that your IP address isn’t suddenly going to change half way through getting the file.  But, for something like IRC where it’s possible that no traffic will be sent for 10 minutes, then the IRC server could well see your IP address changing as traffic flips between the two routes.  IRC servers don’t like that.  So you need to fix some routes so that traffic will always follow the same path.

ip route add via $P2

This sets the route to a specific Freenode IRC server to always go via my_other_isp_name.

9.  Last of all, we need to add an extra layer of NAT so that traffic can find its way back to the host on the LAN side.  This is necessary because our internet modem/routers are not really routers at all.  They simply take traffic from one side, rewrite the headers and push it out the other side, while maintaining a look up table of what came from where and doing the reverse when a reply arrives. If you can configure the routes on to your modem, then you don’t need to be reading this in the first place, so let’s assume you can’t.

iptables --table nat --append POSTROUTING --out-interface $IF1 -j MASQUERADE
iptables --table nat --append POSTROUTING --out-interface $IF2 -j MASQUERADE
iptables --append FORWARD --in-interface $IF0 -j ACCEPT

For things like port forwarding you do now have to deal with a bit of an odd NAT situation.  For example, let’s assume I want to run a web server on the same machine that runs the routing.  I decide to only make the server available on the WAN IP address of $R1.  I set up Router 1 to NAT port 80 on the WAN to port 80 on $IP1.  Then I need to configure the web server on the routing server to listen on that interface.  Not too bad really.

And there you have it.  Two internet connections, both available to all the clients on your network.  Make sure that your clients use the IP address of the server as their default gateway and everything should just work.  The additional load on the server is negligible.

If you reboot the server you’ll need to add all the routing information again, so create yourself a Bash and have it run from /etc/rc.local or something.


NOOP scheduler – not worth it for SSD

I’ve got a new Thinkpad X220i with a 128GB SSD.

Reading around the internet I found a lot of stuff about squeezing a bit more throughput from your drive.

I did a couple of benchmarks in Ubuntu 11.04:

  • Adding noatime,discard to /etc/fstab

Result:  No change.  Not better or worse, but in theory the “discard” will help in the long term

Decision:  Switch this on.

  • Setting the scheduler to noop in /etc/rc.local

Result: Average read rate increased by 2MB/s but Average access time went from 0.2ms to 0.3 ms.  In itself that’s not a real problem, but the graphs show a different picture.

Without NOOP

Note the scale on the right hand side.




The access speed is all over the place.

Decision:  Switch this off


I’d be interested in hearing if your experience differs, but it seems to me that “Doing nothing” is a valid choice.  Ubuntu, out of the box, doesn’t really require any fettling in order to get the best from your SSD.



Trimming Freesat Channels In MythTV

There are loads and loads of free-to-air channels available on the Astra 28 constellation, the vast majority of which I do not watch.

So to make things a bit easier for me after a full re-scan, I’ve put together a list of the channels I don’t watch and with a tiny bit of SQL I can trim them from my channel list.

To make things a bit easier for you here is a SQL dump of my “unwatched channels” list:


And here is the SQL to trim these from your channel list:

update channel set visible=0,useonairguide=0 where name in (select name from unwatched_channels)

You’ll probably want to edit that list yourself to remove and add the channels as you prefer. Generally speaking, my list trims:

  • Regional variations
  • Specialist interest
  • Shopping
  • Games and other text based services

I’ll update this list occasionally, this page will always have my most up to date information.

  • UPDATE: 6 Sept 11.  Refreshed channel list
  • UPDATE: 8 Oct 11. Refreshed channel list
  • UPDATE: 14 Dec 2011.  Refreshed channel list
  • UPDATE: 4 Aug 2012.  Refreshed channel list
  • UPDATE: 29 Dec 2013.  New list of channel IDs available here: unwatched_by_chanid.  Add a new table and import that CSV file.  Then do a “update channel set visible=0 where chanid in (select chanid from <your new table>”

g729 in Asterisk

I run Asterisk 1.8 at home for my own amusement.  I’ve just got a SIP trunk running again to SIPGate which had stopped running for some reason.  I’d set the DID for the SIPGate number to check for faxes and then, if it’s not a fax, go to my MOH application, but for some reason it didn’t work.

I also couldn’t access voicemail from the SIPGate trunk either, but I could get it to work with a phone connected to an ATA.

I had a look in the logs:

channel.c: Unable to find a codec translation path from 0x100 (g729) to 0x40 (slin)

Since slin is, I think, the Asterisk native format this is quite bad.  My assumption is that SIPGate sends through G.729 encoded audio regardless of whether you want it to or not (as configured in your allow/disallow lines for the SIP trunk PEER).

G729 from SIPGate works to the ATA because the ATA supports G729 and G729 to G729 pass-through works without any extra requirements from Asterisk.

So – in order to get SIPGate to Asterisk apps working again I installed the G729 codec binaries from here:

and restarted Asterisk.  Now a:

         core show translations

shows I can convert between G729 and loads of other codecs.

Getting NUT to talk to LiebertPSP UPS

I got hold of a couple of LiebertPSP UPSes and connected to my servers.  They’re perfectly good for what I need them for, namely stopping my servers having the rug pulled out from underneath them with no notice if there is a power cut.

They don’t appear to have advanced functions like switching off the load independently of the supply which means you can’t power down the servers and then have the UPS switch them back on again once the power is restored and the battery has had a chance to charge, but I can live without that sort of thing.

I assumed that something somewhere would support these, and for the most part NUT does a bang up job.  It’s a bit advanced for my needs but most of the work has already been done.  In NUT the LiebertPSP is sort-of-supported by the Belkin USB driver with a few notable exceptions:

  • The Online/On Battery indication doesn’t work
  • The numeric values don’t work for things like Output Voltage

The numbers I can live without but the Online / On Battery is really rather important.

So I’ve cobbled together a new sub-driver using the tools supplied with Nut.  It’s far from complete but it does fix most of the annoying problems.

You’ll need to download the Nut source and put the .c and .h files in the above tarball in to the drivers directory, then you’ll need to apply this patch in the drivers directory to get the new driver included in the build and to stop the native Belkin driver from claiming the ID of the LiebertPSP:

Then recompile Nut.

If everything works you should see a bit more info from your UPS:

battery.type: PbAc
device.mfr: Emerson Network Power
device.model: LiebertPSP
device.type: ups usbhid-ups
driver.parameter.bus: 004
driver.parameter.pollfreq: 30
driver.parameter.pollinterval: 2
driver.parameter.port: auto
driver.version: 2.4.3-2519M LiebertPSP HID 0.1
driver.version.internal: 0.35
ups.input.frequency: 50.0
ups.input.voltage: 243
ups.mfr: Emerson Network Power
ups.model: LiebertPSP
ups.output.percentload: 54
ups.output.voltage: 240
ups.powersummary.capacitygranularity1: 1
ups.powersummary.capacitygranularity2: 1
ups.powersummary.capacitymode: 2
ups.powersummary.configvoltage: 12.0
ups.powersummary.designcapacity: 100
ups.powersummary.fullchargecapacity: 100
ups.powersummary.imanufacturer: 19
ups.powersummary.ioeminformation: 19
ups.powersummary.iproduct: 1
ups.powersummary.presentstatus.batterypresent: 1
ups.powersummary.presentstatus.belowremainingcapacitylimit: 0
ups.powersummary.presentstatus.charging: 1
ups.powersummary.presentstatus.discharging: 0
ups.powersummary.presentstatus.needreplacement: 0
ups.powersummary.presentstatus.shutdownimminent: 0
ups.powersummary.rechargeable: 1
ups.powersummary.remainingcapacity: 100
ups.powersummary.remainingcapacitylimit: 38
ups.powersummary.voltage: 14
ups.powersummary.warningcapacitylimit: 38
ups.productid: 0001
ups.status: OL
ups.vendorid: 10af

Search hints:

Vendor ID: 0x10af

Product ID: 0x0001

Hauppauge WinTV Nova-S Plus on Linux

The Nova-S Plus is a  good card.

But, it would appear there is a defect in these boards, or at least a strange design, which means that they won’t lock on to some frequencies which require the 22kHz tone sending to the LNB with new drivers because there’s no link between the flange and dolphin-points.  There’s plenty to read about here:

And there’s a patch which fixes the problem by controlling the tone generator directly but it’ll never get in to the main kernel.  For your convenience here is a link to a binary driver built for Ubuntu Lucid kernel version 2.6.32-23-generic:

Replace the current isl6421.ko from /lib/modules/2.6.32-23-generic/kernel/drivers/media/dvb/frontends/isl6421.ko with this one.  It might also work for newer kernel versions, or not.  Who knows?  Not me.

I’ve also got a Hauppauge S2 HD and this patched driver doesn’t seem to effect it.

Search hints:

Hauppauge Nova S plus linux won’t lock horizontal 22khz tone can’t pick up some channels. You can also check out my guide on Everything You Need to Set Up a Backyard Cinema.

Asterisk set up in the UK with SMS

EDIT: 25 Sept 2010
The below specifically refers to Asterisk 1.4. Go to the bottom for an update on 1.6

Why do I always get myself in to these situations?

Many years ago I knocked up a set of scripts to record TV programs from a DVB-T card.  Getting the TV card working was really hard work.  I had to hack about with the driver source code, compile custom kernels, build endless versions of the driver, and so on and so on and so on.  It was a pain in the arse, which was compounded by the fact that at the time very few other people (end users) were trying to get these cards working, so there wasn’t much community support.  My scripts were great and everything and I could record TV, taxes were low and life was, on the whole, pretty good.

Then Stuart put me on to MythTV.  It quickly became evident that although my scripts were functional they were nothing compared to Myth.  So I moved over.  Again with the pain.

The basics were there but DVB support was in it’s infancy and it was a lot of hard work getting it working.  I persevered and learnt a lot about MythTV in the process.  Yay me.  At the beginning MythTV was a foreign country.  By the time I’d got it working the way I wanted it was my home town.

And so it will be with Asterisk, I hope.

Things I have learnt about Asterisk

  1. The cheap FXO cards they sell on eBay are more trouble than they are worth.
  2. The documentation on the voip-info site is often out of date.
  3. UK Caller ID works with the TDM400’s out of the box.
  4. Sending & receiving SMS’s does work, but it’s a bitch, and unreliable.
  5. The logic in Asterisks’ dial plan (extensions.conf et al) is illogical to me
  6. FreePBX is both a blessing and a curse.
  7. I love it.

In a bit more detail then:

1.  The FXO cards you can get from eBay for about 20 quid work perfectly well.  For making calls.  But, there are a few drawbacks.  They don’t support polarity reversal which is the method by which incoming calls and Caller ID are announced to Asterisk.  You’ll still get ringing indications and be able to make calls, but you won’t get Caller ID.  Or rather, you can get Caller ID but you need to patch the Zaptel drivers and the Asterisk source.  The patches are old and don’t apply perfectly.  They are also seemingly unsupported now, in that no one cares if you are having problems with them.  I got the patches applied but Asterisk wouldn’t compile and I don’t know/care enough to fix it.  I was in the market for an ATA anyway so I put that 40 quid towards the cost of the TDM400p11 from NovaVox and if I hadn’t bought the AX-100 then the initial outlay for a fully supported card isn’t so bad.  It also works out cheaper to add another FXS port the to TDM400 than it does to buy another ATA.  The AX-100 also has a US spec. “hybrid” in it which means that the unbalanced UK spec phone lines and the AX-100 are not perfectly matched which can cause wicked echo.  The TDM400 has a tunable hybrid, and that’s a good thing.  All that said – for 20quid I still think it’s worth getting one to play with.  Ask me about doing a swap, if you’ve got any cool toys you don’t want  (I’ve got a DVB-T card going spare as well!).

2.  The site is a really good source of data.  The website might be ugly, but there is a lot of Asterisk data on there.  Unfortunately there is little in the way of information, and some of the data is way out of date.  It acts as a good reference point but isn’t for the beginner because most pages assume a lot of prior knowledge.  Sure – I could go in and edit the Wiki, but I don’t know if what I’m doing is the best way of doing it, or even the correct way to do it.  So for now that’s what this blog post is for.

3.  BT send the Caller ID information before the first ring.  The process goes something like this:

Line polarity reversed -> Caller ID sent as FSK (sort of modem tones) -> Phone starts to ring -> Call Connected -> Charlie Brown's Teacher -> Call Hung Up -> Line polarity reversed

You can see the importance of being able to detect polarity reversal in the call set-up and tear-down.  The AX100 simply doesn’t do it.  The TDM400 does, and it’s fully supported out of the box, as is UK style Caller ID, where the ID is sent before the first ring.  The hack for the AX100 keeps a buffer running all the time and then once a call comes in it looks in this buffer for the caller ID FSK and decodes it.  Shonky, I think you’ll agree.  My advice is that if you want to do caller ID in the UK buy a TDM400.  If you are a masochist then feel free to try with the AX100, I’d love to read your HowTo once you’ve got it working.

4.  SMS.  What a bitch.  I recently discovered my subscription with BT gives me 200 free SMS text messages a month.  So to make sure I was getting best value from the phone subscription I went out and spent 100quid on a PCI card and then spent hours and hours and hours fiddling about trying to get it working.  I don’t know why, I probably send about 3 text’s a month from my mobile, the whole “Because it’s there” thing I guess.  A pox on you, Mallory.

Last night I finally got it working semi-reliably for incoming and outgoing texts.  I can send and receive from my mobile, but Stuart doesn’t receive my messages.  Ho hum.

Firstly, receiving SMS’s. Now, I don’t really understand the extensions.conf language.  It’s all a bit, well, wrong, to my eyes.  All I can tell you is that this is how I got it working.  NOTE:  This WILL NOT work for you if you just copy and paste. Sorry about that.  Perhaps someone can help me re-write it so that it does?

I’m using FreePBX as a GUI and it rewrites some of the Asterisk config files for you.  I’m not sure if the context [from-pstn] is one that I created, or a standard one.  What you need to find out is what route incoming calls from the PSTN take i.e. which contexts they pass through before they start ringing on your internal phones.  You can do this my running the Asterisk console and turning verbosity up to about 6 (core set verbose 6) and then calling in from outside.  You should see a trace of what contexts get called as the call comes in.

For example, my call flow goes something like this:

[from-zaptel] -> [from-pstn] -> [macro-user-callerid] -> 600@[ext-group]

Where 600 is an extensions number I set up with FreePBX to ring all internal phones.

I chose to test for SMS’s in the [from-pstn] context. You can visualise what the [from-pstn] context does when a call comes in by using the Asterisk CLI.  Use the command “dialplan show s@from-pstn” to see the instructions that would be followed when [from-pstn] gets called at position “s”, or start.

Originally, mine went something like this:

[ Included context 'ext-did-0001' created by 'pbx_config' ]
's' =>            1. Set(__FROM_DID=${EXTEN})                   [pbx_config]
2. Gosub(cidlookup|cidlookup_1|1)             [pbx_config]
3. ExecIf($[ "${CALLERID(name)}" = "" ] |Set|CALLERID(name)=${CALLERID(num)}) [pbx_config]
5. SetCallerPres(allowed_not_screened)        [pbx_config]
6. Goto(ext-group|600|1)                      [pbx_config]

You can follow the call progression through this quite easily.  We jump in at position (or priority) 1, we set a variable, then we jump to some cidlookup sub-routine, then if the CALLERID(name) is blank we set it to be the same as the caller id number, then something about CALLINGPRES, not sure what that does, ditto the next line, and then we go to ext-group|600|1.  Ahhaaa!  I know that 600 is the group that I call to ring all the phones, so that must be where the call is handed off to other contexts or functions that let you do talking to people.  Since an incoming SMS doesn’t need to get as far as ringing on a phone, it makes sense to me to interrupt the call flow during [from-pstn].

So I added [from-pstn-custom] to /etc/asterisk/extensions_custom.conf like this:

exten => s,3,GotoIf($["${CALLERID(num)}" = "08005875290"]?will-sms,s,1)
exten => s,4,Verbose("Not an incoming SMS")
exten => s,5,Gosub(cidlookup,cidlookup_1,1)
exten => s,n,ExecIf($[ "${CALLERID(name)}" = "" ] ,Set,CALLERID(name)=${CALLERID(num)})
exten => s,n,SetCallerPres(allowed_not_screened)
exten => s,n,Goto(ext-group,600,1)

exten => s,1,Verbose(=============Entered Will SMS)
exten => s,n,Answer()
exten => s,n,Wait(2)
exten => s,n,SMS(default|a)
exten => s,n,Verbose(=============Done with Will SMS)
exten => s,n,Hangup(16)

How does it work?  The [from-pstn-custom] overrides the [from-pstn] from the main extensions.conf file provided by FreePBX and adds a line that branches to a context called [will-sms] which then uses the SMS application to receive the SMS and then hangup the phone.  (Actually, I think SMS hangs up for you.  But, you know, whatever)

In [from-pstn] in extensions.conf is a line that “includes” the config from “from-pstn-custom”.  By virtue of being imported, the instructions in [from-pstn-custom] take precedence over the other config, because it is imported first.  The config files are read line by line in the order they appear in the file.  But, the imported instructions do not completely replace the config that is already there.  They are sort of merged. That’s why I’ve copied a load of bits from the original call flow in to my new [from-pstn-custom].  If I left them out, then some bits of my new context would be applied and some wouldn’t.  The way I got it to work was to replicate the call flow to the point of it branching off to [ext-group] in my new context.  If you do a “dialplan show s@from-pstn” now, you see this:

[ Included context 'from-pstn-custom' created by 'pbx_config' ]
's' =>            3. GotoIf($["${CALLERID(num)}" = "08005875290"]?will-sms|s|1) [pbx_config]
4. Verbose("Not an incoming SMS")             [pbx_config]
6. Gosub(cidlookup|cidlookup_1|1)             [pbx_config]
7. ExecIf($[ "${CALLERID(name)}" = "" ] |Set|CALLERID(name)=${CALLERID(num)}) [pbx_config]
10. SetCallerPres(allowed_not_screened)       [pbx_config]
11. Goto(ext-group|600|1)                     [pbx_config]

[ Included context 'ext-did-0001' created by 'pbx_config' ]
's' =>            1. Set(__FROM_DID=${EXTEN})                   [pbx_config]
2. Gosub(cidlookup|cidlookup_1|1)             [pbx_config]
3. ExecIf($[ "${CALLERID(name)}" = "" ] |Set|CALLERID(name)=${CALLERID(num)}) [pbx_config]
5. SetCallerPres(allowed_not_screened)        [pbx_config]
6. Goto(ext-group|600|1)                      [pbx_config]

[ Included context 'ext-did-catchall' created by 'pbx_config' ]
'_.' =>           1. Noop(Catch-All DID Match - Found ${EXTEN} - You probably want a DID for this.) [pbx_config]
2. Goto(ext-did|s|1)                          [pbx_config]

You can see my new [from-pstn-custom] context at the start, along with the copied commands from ext-did-001 to ensure that they run in the way I expected.  The upshot of this is that I now branch to my new context [will-sms] when the incoming caller ID is the BT 0800 number from where SMS’s originate.  You should note that the 0800 number can change if you have more than one incoming SMS box registered, so don’t do that.  Just register one incoming address  (more on this later).

The [will-sms] is pretty straight forward.  Answer the phone, wait 2 seconds, and then start the SMS application which does all the clever noises.  The key here is Wait.  Without it SMS reception is intermittent at best.  The SMS(default|a) tells the SMS app to receive in to the default queue (this works, don’t understand fully why) and to do an “a” for answer.  I had a load of problems with the example from VOIP-info where it passes in the extension number, which is “s” for start.  If the SMS application sees an “s” it thinks it means “send”.  That won’t work!

If you manage to bodge all this in to your dial plan then you should find your incoming SMS’s in /var/spool/asterisk/sms/mtrx

Make sure that /var/spool/asterisk is writeable by the same user as Asterisk is running as.

Sending SMS’s. Was a whole bunch of no fun as well.  Especially if you don’t understand Asterisk properly.

The command line I’m using to send an SMS is:

smsq --motx-channel=Zap/2/17094009 -d <phone number>  -m "<message>"

That works because zap channel 2 is my PSTN line.  You might need to change this.  17094009 is the SMSC centre number for BT to accept SMS messages for delivery to other networks.

When I was trying to get sending working, which I actually did first, I couldn’t reliably get Asterisk to talk to the SMSC.  Before I had the receive working properly the BT system would ring me up and I’d answer the phone, then not hearing a carrier the BT system would hang up again.  This gave me an idea, if I could emulate the carrier then I could hear what the BT system was sending down the line.  I sent an SMS to the home phone, it rang in on one of the extensions and I whistled at it.  Because I am just so 1337 I hit the right tone and I could hear FSK noises coming down the line, but they were really really quiet.  I tweaked the gain up a little bit in the /etc/asterisk/zapata.conf file:


and tried again.  It was louder!  Sending a test message to “00000” with the text of “test”  causes the BT system to send a message back to you  (you need to send “register” to 00000 before BT will send you messages as text instead of reading them to you by the way – but if it can’t successfully deliver the message back to you to say it has received your “register” message it will ignore the request and you’ll keep getting the messages read to you by a friendly robot – hence the need to get receiving working first).  It sent!  I saw some hex coming from the SMS application in the Asterisk log.  I sent a text to my mobile, and it arrived.  Yay!  problem solved.

5.  Asterisk’s dial plan.  Bonkers.  I still can’t make sense of them.  Oh well, I’ll get there in the end.

6.  FreePBX is brilliant if you want to get Asterisk configured with some very complex applications (think voicemail) in a matter of minutes.  But, if it makes editing the config files by hand a bit more complicated because you have to use xxxx_custom files.  Thus, all the replication of code when as above when you don’t understand how it all works.

7.  Check out my hold music hacked together from various online sources, and no doubt subject to various copyright restrictions.  I’ve compressed the hell out of it, if you want a better quality version for your own amusement let me know.

Hold Music

I crack myself up, I really do.

Also – think of all the cool things you could do if you could phone or text your computer and get it to do things for you.

Now I’m off to write myself an gmail <-> SMS gateway doodad.

Ok – with Asterisk 1.6 the above is slightly less relevant.  Try this in your dialplan instead:

exten => s,1,Verbose(=============Entered Will SMS)
exten => s,n,Answer()
exten => s,n,SMS(default,ap(1500))
exten => s,n,Verbose(=============Done with Will SMS)
exten => s,n,Hangup(16)

The SMS application has the option to add a pause which I've set to 1500 ms.  Seems to work.