Following on my expansion into telephony posts (See a previous one, on making FreePBX work with Twilio). A lot of people have been asking me to provide more information on how to make your phone say things or play and MP3 file.  In particular while in a conference room…

Lets break this down into two parts; Making ‘Say or Play Bots’ and then adding our ‘Say or Play Bot’ to a conference and doing something.

Making a ‘Say or Play Bot’

Using Twilio there are lots of ways to make an automated voice say something to a caller / listener;

Twimlet Message (https://www.twilio.com/labs/twimlets/message) Static Message or MP3 file
TwimelBin (http://twimlbin.com) Static Message
Static XML hosted on your webserver Static Message
Dynamic web script that generates custom Say XML hosted on your webserver Dynamic Message
Dynamic web script that plays a custom message pending some criteria Dynamic Message

Twimlet Message:

In this example we are going to use a Twimlet message to say “Hi, This is you’re 9 AM Meeting Reminder, The current time is 8.55 AM. You have a meeting with Bob in 5 minutes.”

The message could be anything, in this case I’ve choose to use a meeting reminder message. If you follow the URL: https://www.twilio.com/labs/twimlets/message You can input your message into the Twimlet generator and it will spit out the URL you need to use with Twilio to get your message spoken:

http://twimlets.com/message?Message%5B0%5D=Hi%2C%20This%20is%20you’re%209%20AM%20Meeting%20Reminder%2C%20The%20current%20time%20is%208.55%20AM.%20You%20have%20a%20meeting%20with%20Bob%20in%205%20minutes.&

As you can see our message has now been encoded into a URL form, the spaces between words have been filled in with %20 if we were to buy a phone number now and use this in the Voice URL we would hear this message.

Twimelbin:

Twimelbin is an external tool that you can use to test writing your TwiML (XML) writing skills.  It will validate your TwiML and ensure that the syntax is correct, you can then use the URL link provided to reference this TwiML in your Twilio account.  In this example I’m going to copy and paste my TwiML here so you can see what the structure looks like:

<?xml version=”1.0″ encoding=”UTF-8″?>
<Response>
<Say>Hi Caller.</Say>
<Say>I’m just in the shower at the moment</Say>
<Say>Please let me wash my hair in peace and I will call you back later today</Say>
<Say>Thanks!</Say>
</Response>

Here you can see I have linked lots of ‘Say’ commands together in one response. We could if we wanted to be annoying (if!) get each command to be spoken in a different voice or even language (https://www.twilio.com/docs/api/twiml/say) but ill skip that for now.

When your finished composing your Twimelbin entry you take the URL at the top of the page and use this to look up your TwiML in your phone number URL.

Static XML hosted on your own machine:

Static XML and a Twimelbin response are exactly the same, the only difference that one is hosted on your platform and one is hosted by Twimelbin. There are benefits to both; I won’t go into the merits of self hosting vs a 3rd party for any kind of HTTP activity here.

Dynamically generated TwiML response: 

This is where is gets fun! With a dynamic script we can make our message be customised to the caller, the time of day, the weather or any other factor we want! Lets say for example that we have two callers; Mathew and Steve. Mathew’s number is +44123456 and Steve’s is: +44987654 as we are generating this response on demand we can input these names into the <Say> response and give the caller a more personal response.

In this example I’m using PHP, but you could easily use another web language.

<?php

$people = array(
“+44123456″=>”Mathew”,”+44987654″=>”Steve”);

// if the caller is known, then greet them by name
if(!$name = $people[$_REQUEST[‘From’]]) $name = “Caller”;

// now greet the caller
header(“content-type: text/xml”);
echo “<?xml version=\”1.0\” encoding=\”UTF-8\”?>\n”;
?>
<Response>
<Say>Hello <?php echo $name ?>.</Say>
</Response>

In this example, I made an array of data – mine and Steve’s number and then used the array to look up the name, if either Steve or I called the Twilio number from those numbers it would say Hi ‘Steve / Mathew’ if none of the numbers were recognised the caller would be just greater as just a ‘Hello Caller’

You can use the same kind of dynamic scripting language to play specific files, this could be to either specific times of the day, caller ID’s or special events.

I won’t go into the code here but the basic set up is:

IF event is true

Do this

Else (if not true)

Do this

So for example:

If time = before 12

Play the morning MP3 file

Else (If not true)

Play the Afternoon MP3 file

an example of this in PHP would be:

<?php

if (date(‘H’) < 12) {
$mp3_file=”http://domain.com/morning_mp3.mp3″;
}
else
{
$mp3_file =”http://domain.com/afternoon_mp3.mp3″;
}

// Play the AM / PM file to the caller
header(“content-type: text/xml”);
echo “<?xml version=\”1.0\” encoding=\”UTF-8\”?>\n”;
?>
<Response>
<Play><?php echo $mp3_file; ?></Play>
</Response>

When this script is called it will check the time, if the clock is before 12 it will fetch the morning MP3 file and if its in the afternoon  it will fetch the afternoon mp3 file. You could go one step further and make an evening file. But for this setup lets assume an morning and afternoon setup 🙂

So whats a bot?

In simple terms a bot is a program / application that just does one thing. In the use case here you could have a phone bot that people could ring and it would recite company open hours.

Example:

http://twimlets.com/message?Message%5B0%5D=Hello%20and%20welcome%20to%20Mathew’s%20super%20store.%20Our%20open%20hours%20are%208%20AM%20to%207%20PM%20Monday%20to%20Friday.%20&Message%5B1%5D=We%20are%20open%20Saturdays%2C%20from%2010%20AM%20to%203%20PM.%20We%20are%20not%20open%20Sundays&Message%5B2%5D=Have%20a%20nice%20day.&

 

This Twimlet just informs the callers of the times, Mathew’s superstore will be open.

 

So more recently I have been playing around with cloud technologies, namely building a cloud based hosting platform to replace an ageing home-based server solution. Don’t get me wrong my little Mac Mini server has been phenomenal, but the more recent releases of Mac OS X Server have left me wanting a bit more control and a bit less hardware.

Enter Digital Ocean (shameless referral plug: https://www.digitalocean.com/?refcode=8dc34df963c1 ) who allow you to build a very quick virtual machine capable of handling mail, HTTP and other web service based systems (that I have now retired and / or moved to the cloud).

One of the more recent projects I have wanted to build is a private branch exchange (PBX (Phone network)) so that I can adopt a singular 1 number per country approach, i.e. have a US based number that people can call and SMS, a UK based number that people can call and SMS, etc. This would save giving people a whole lot of different numbers – when Im in the UK ring a local uk number when I’m in the US ring a local us number..

Following lots of sniffing around for how to install PBX software onto a hosted platform I stumbled across this document: https://www.digitalocean.com/community/articles/how-to-install-freepbx-on-centos-6-4

I’m not going to copy and paste the guide word for word as its fairly self explanatory. If you have any problems following the guide, check out the comments at the bottom of the page as they helped.

From here we need to configure three things; Trunks (Calling in and Out), Extensions (Phones to answer the calls) and Routing (What calls go where based on logic).

First lets get extensions setup, its the quickest way to test your PBX is working correctly.

Navigate to your server and login to the FreePBX login it should be something like: YOURDOMAIN.com/admin/config.php

From here you want ‘Applications’ drop down menu and then ‘Extensions’

We are going to add 2 SIP based devices so select the option for ‘Generic SIP Device’ and then click submit.

As this is a private PBX I don’t foresee needing a lot of numbers, however a good organisational setup is still good idea. – Don’t go charging ahead into making your first extension ‘1’ and your second extension ‘2’.

I use the two hundred block for all my extensions, IE the first extension is 201 and the second extension is 202. As I need to add more extensions to the PBX they will become 203, 204, 205, etc.

The three main values we need to set here, are the user extension, Display Name and secret (password).  If you follow my convention you should setup ‘201’, ‘Mathew’ and ‘mysupersecretpassword’. Once you have setup your first user, do the same again so you have a second user (appending the next extension, username and password).  – Now we can test our PBX. If you have an iPhone – I recommend downloading any of the open VOIP Clients, my fav is ‘LinPhone‘. Its simple, easy to use and you can turn on the debugger if you need to.

If you have more than 1 phone you can download Linphone to that as well (Or another VOIP client) and try to ring each other. Or if you have 1 phone and your computer look at downloading x-lite (X-Lite)

To ring another IP phone on your PBX just punch in the extension number, 202 to ring the second phone from the first and 201 to ring the first phone from the second.

Once you have established that your phones are working we can begin to get calls into the PBX from the outside world.

Inbound Calling

First we need to organise inbound calling from Twilio.

Head over to Twilio.com and sign up for a trial account, you will need an email address and a mobile / cell phone to validate yourself against. Once you signed up you will need to provision a telephone number, you can do this in your account at: https://www.twilio.com/user/account/phone-numbers/available/local

Next we need to configure what we want to happen with that number when someone calls it, as Twilio uses TWiML (an extremely well documented type of XML) we can set Twillio to make a sip call to our PBX and connect the call over. On a hosted platform place a new xml document. Something like: www.yourdomain.com/twilio.xml

Our XML needs to look like this:

<?xml version=”1.0″ encoding=”UTF-8″?>
<Response>
<Dial>
<Sip>sip:[email protected]</Sip>
</Dial>
</Response>

We can also use a Twimlet to perform the same thing (except it doesn’t look as nice as the above XML:

http://twimlets.com/echo?Twiml=%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22UTF-8%22%3F%3E%3CResponse%3E%3CDial%3E%3CSip%3Esip%3A201%40YourDomain.com%3C%2FSip%3E%3C%2FDial%3E%3C%2FResponse%3E&

As you can see, the XML very easy to read, should anyone now dial our newly provisioned number, Twilio will transfer the call to our 201 extension on the PBX. (Almost – we have a bit more setup to do first!).

Login to your PBX via a root terminal and navigate to /etc/asterisk/ by typing

cd /etc/asterisk/

Here we need to edit the sip.conf by typing:

nano -w sip.conf

Here we are going to add all the known IP addresses of Twilio so that when one of the gateways makes a request to our PBX the PBX will answer the call and route it accordingly.

The SIP document held at: https://www.twilio.com/docs/sip contains the list of IP addresses used by Twilio for connections via SIP. To add them to sip.conf we need to add the following to the document:

[twiliocaller](!)
context = fromtwilio
type = peer
qualify=no
allowguest=yes

[twilioip-1](twiliocaller)
host=107.21.222.153

[twilioip-2](twiliocaller)
host=107.21.211.20

[twilioip-3](twiliocaller)
host=107.21.231.147

[twilioip-4](twiliocaller)
host=54.236.81.101

[twilioip-5](twiliocaller)
host=54.236.96.128

[twilioip-6](twiliocaller)
host=54.236.97.29

[twilioip-7](twiliocaller)
host=54.236.97.135

[twilioip-8](twiliocaller)
host=54.232.85.81

[twilioip-9](twiliocaller)
host=54.232.85.82

[twilioip-10](twiliocaller)
host=54.232.85.84

[twilioip-11](twiliocaller)
host=54.232.85.85

[twilioip-12](twiliocaller)
host=54.228.219.168

[twilioip-13](twiliocaller)
host=54.228.233.229

[twilioip-14](twiliocaller)
host=176.34.236.224

[twilioip-15](twiliocaller)
host=176.34.236.247

[twilioip-16](twiliocaller)
host=46.137.219.1

[twilioip-17](twiliocaller)
host=46.137.219.3

[twilioip-18](twiliocaller)
host=46.137.219.35

[twilioip-19](twiliocaller)
host=46.137.219.135

[twilioip-20](twiliocaller)
host=54.249.244.21

[twilioip-21](twiliocaller)
host=54.249.244.24

[twilioip-22](twiliocaller)
host=54.249.244.27

[twilioip-23](twiliocaller)
host=54.249.244.28

 

Save the file and now either reboot asterisk or the server. As the server takes seconds to reboot I tend to follow the save command with just

Sudo reboot

which reboots the whole thing, as this server is for my own use; I’m less worried about the number of users who I will be kicking off when I do this.

Once your back up and working again, if you navigate to: FreePBX system status, it should tell you that 20+ gateways are online. With your backup phone or laptop logged in as your SIP extension we set the look up (201 in the above case) you should be able to call your number and your VOIP phone should ring! (Take 5 mins to strut around the room looking proud and ring yourself a few times!)

Outbound Calling: 

Outbound calling allows you to make call from your VOIP client via your PBX to the real world using Twilio as the gateway. In short we are going to get Twilio to connect the VOIP client to the rest of the world using the callerID we already provisioned.

There is a lot of reference material regarding SIP on the SIP Twilio Page (https://www.twilio.com/docs/sip/sending-sip-how-it-works)

The basics of it include, we need to make a SIP endpoint on Twilio, then when your SIP route references this endpoint, Twilio will make a URL request back to your server to get TwiML to decide what to do with the call.

Head over to: https://www.twilio.com/user/account/sip/domains and click the button ‘Create SIP Domain’

We need to create a Twilio SIP domain, pick something nice and unique such as mypbxservername  – Twilio will append .sip.twilio.com onto this so you will end up with a complete string that looks like this: mypbxservername.sip.twilio.com

Next we need to give it a friendly name, this is just so you can remember what it’s called.

In voice URL, please fill in:

http://twimlets.com/message?Message%5B0%5D=Congratulations!%20You%20just%20made%20your%20first%20call%20with%20Twilio%20SIP.

This will give us a nice uncomplicated message, indicating our success from going from FreePBX to Twilio.

Next we need to generate a way to protect our SIP endpoint.  As Im using a static IP server I can add this to a white list. Click ‘CreateIP Access Control List’ and a new drop down will appear. Here we want to add the IP address of our server and then give it a friendly name.

Save all the changes and then save the domain to Twilio.

Move over to your FreePBX server and add a trunk in the usual fashion: Connectivity > Trunks. 

Here we need to make a new SIP Trunk; so click ‘Add SIP Trunk’

Call the Trunk something like ‘Twilio’ and then move down to the next trunk name (again, Twilio). In Peer details we need to add the three points:

type=peer
host=mypbxservername.sip.twilio.com
qualify=no

Then click submit changes – Ignore an errors you get.

Then we need to add in outbound route, setting it so that when we dial a number on our extensions, FreePBX knows to route the call to our Twilio Trunk.

So, lets add a outbound route; Connectivity > Outbound Routes.

Here, I have set the route name to be ‘Twilio’, now scroll down to ‘Dial Patterns that will use this Route’. We need to configure the PBX so that when we dial a certain prefix, FreePBX will pick up this prefix, remove the prefix and then hand the call over to Twilio to be dialled and connected.

The window is broken up into three boxes, ‘Prepend’, ‘Prefix’ and ‘Match Pattern’. We do not need to worry about ‘Prepend’ so the next bit we need to add a dial prefix so that the PBX knows we want to use this route. I have chosen the prefix of 71, so if I wanted to dial a phone number of 1 415123 1234 I would dial 7114151231234. Here FreePBX will pick up the 71, remove those digits from the string and then hand the 14151231234 to Twilio for dialling. The last part ‘match pattern’ is used to match we have the right numbers dialled. For example in the US, a long distance number would be 1-415-123-1234 so the match pattern would be 1XXXXXXXXXX as we only want +1 numbers to be routed this way. You could also narrow this down do only a certain area code could be called by doing this: 1901XXXXXXX – where 901 is the area code only accepted.

To dial the UK on this dial pattern you would need to setup: 44XXXXXXXXXX, again if you wanted to setup only landlines you could do: 441XXXXXXXXX and 442XXXXXXXXX which would limit numbers to only 441 and 442 (as in 44 1895 and 44 208).

You should now be able to dial a real number from your PBX extensions and you should hear ‘Congratulations, You just Made your first call with Twilio SIP’. PERFECT! This means that your FreePBX box was able to hand over a call to Twilio, and Twilio was able to execute the message we predefined earlier!

Now we need to modify our Twilio URL so that it points to a file we can use to dial our actual end point. On an internet facing server create a new file called asterisk.PHP

to which we need to add:

<?xml version=”1.0″ encoding=”UTF-8″?>
<Response>
<Dial callerId=”+YOURCALLERID”>
<Number><?php preg_match(‘/:([0-9]+)@/’, $_POST[‘To’], $matches); echo $matches[1]; ?></Number>
</Dial>
</Response>

You need to append YOURCALLERID with a caller ID from your account, either a verified number or one of your Twilio numbers. This will be the caller ID used when your PBX dials out via Twilio.

Now take the internet facing location of this file. I’m going to assume: http://domain.com/asterisk.php  – Just update the URL location that was Twimlets message of congratulations with your URL. This should now setup your PBX so that when it makes a request to Twilio, Twilio looks up the URL and injects the TO number into the TwiML, followed up by dialling that number.

Tada!! That should be it! You should now be able to dial your PSTN number and have it call your PBX extensions and you should now be able to dial out from your PBX to PSTN lines using Twilio!

After many (many!) attempts and learning’s.

Everything from PCB design via software, PCB manufacture via toner transfer and ensuring your board is soldered correctly has had to be designed, re-engineered and put into practice on almost a production line state of mind.

Finally the initial board is ready to rock!

Completed BeeSafe Board, Version 1

Completed BeeSafe Board, Version 1

This board features, 5 LED’s; 4 of which are configurable. 3 Temperature Sensors, input for a switch and an I2C based accelerometer. *NB* The board above only has 1 of the three temperature sensors attached as at time of writing the other two sensors were in the post.

This board connects into a Raspberry Pi via the large 26 Pin header in the top left. Connected to the Pi is a USB GPS and USB 3G Data stick. *NB* the Pi’s on board USB ports aren’t able to provide enough power to support the 3G Data stick so an additional hub or secondary PCB will have to be provided should 3G be needed (Which I suspect it will!).

In total the BeeSafe project has the following sensors and communication gateways:

Circuit Temperature BeeSafe Board
Brood Temperature BeeSafe Board
External Environmental Temperature BeeSafe Board
XYZ Accelerometer BeeSafe Board
5 x Status LED’s BeeSafe Board
Switch Sensor BeeSafe Board
GPS Raspberry Pi
3G Data Modem Raspberry Pi
Ethernet Connection Raspberry Pi

With the hardware now complete (for the moment!); my attention has turned to the software to power BeeSafe. This is comprised of two parts: Software localised on the device and software hosted in the cloud to collect, store and interpret all the data.

A lot of people have asked why I chose to use the Raspberry Pi to power this device, a micro-controller such as Arduino would have been more than capable of reading temperature sensors, XYZ data, parsing GPS data and submitting it all via a comm’s device to the cloud. But the Pi stands out as a standalone computer. It’s capable of hosting its on database, serve pages and data to other computers and networks. An Arduino works in a single hive, but a Pi could work with many.

An Example; quite often bee hives are clustered together and are known as apiaries. If each beehive had a 1-2-1 connection to the internet that would mean each hive would require a 3G stick, its own sim card and data plan. Quickly the costs of keeping an apiary online would rack up.

Using a Raspberry Pi you could create a star network, one device could become a host. Using a USB WiFi stick to create a local WiFi access point (like your WiFi at home, one hub serves many users with an internet connection). This could keep costs and maintenance down as each apiary would only need one connection to the internet.

Additionally, if there is no cell signal, a Raspberry Pi could be used as a localised storage option for all the data collected. While this means you would loose some of the advantages of monitoring your Bee Hive remotely, the data is still invaluable and could be downloaded at a later point.

The next steps for BeeSafe include a start up program that will scan the hardware and configure everything into appropriate sections. For the moment I am doing this manually using a mix of python scrips to test the internet connection, GPS data, LED’s, temperature and XYZ position.

My ultimate goal is to produce a initial start up script that will on boot, self-test the LED’s, check for internet connection, scan for temperature sensors, check for the presence of an Accelerometer and then store all this data within an XML file to be used by the default BeeSafe program.

An example of the XML configuration file is below:

<?xml version=”1.0″?>
<BeeSafe>
<BeeSafeDeviceID></BeeSafeDeviceID> #Unique Serial Number used to identify the BeeSafe
<RedLED><RedLED> #GPIO Pin number for Red LED
<AmberLED></AmberLED> #GPIO Pin number for AmberLED
<GreenLED0></GreenLED0> #GPIO Pin number for First Green LED
<GreenLED1></GreenLED1> #GPIO Pin number for Second GreenLED
<BoardTemp></BoardTemp> #Identifier for Board Temp Sensor
<BroodTemp></BroodTemp> #Identifier for BroodTemp Sensor
<EnvironmentTemp></EnvironmentTemp> #Identifier for External Temp Sensor
<MagSwitch></MagSwitch> #GPIO Pin number for Magnetic Switch
<XYZ></XYZ> #Identifier for I2C Accelerometer
</BeeSafe>


The BeeSafe Device ID is used to track and log the data submitted by a BeeSafe device, my initial thoughts were that I could use the serial number from the Raspberry Pi attached, but this quickly led to issues as should a user wish to swap out the Pi for another one, the serial number would change and the data would be lost. Additionally I did not want to tie a BeeSafe device to a specific email address as should an individual user have more than one BeeSafe active, managing each device this way could prove to be problematic.

So whats the solution?
A BeeSafe’s Device ID will be generated on demand from the cloud, as a new device comes online and communicates with the cloud for the first time, it will be assigned a device ID which will be saved to the XML config file. While this ID will not be dependent on the PI it is connected to, the Pi’s serial number will be submitted so that should the worst occur and the SD card with the config file be lost, if the same Pi attempts to reconnect to the cloud, as a new user, it will be assigned the same device ID.

From a human perspective; one user can be in control of many BeeSafe devices.
Should the worst occur and the user need to be contacted, if more than one device has an alert status (such as a whole apiary) the user would be alerted once rather than receiving multiple alerts for a cluster of hives suffering the same issue. For example, if a cluster of BeeHives have collapsed, a single alert would be sent out stating that X number of hives currently need attention, rather than bombarding the user with an alert for each individual hive.

So one of the buzzword’s used in 2012 was ‘Big Data’, representing the interconnection of lots of databases from a variety of sources all communicating together.

Why might you want to engage with big data? Well say your website or app wants to make use of a post code search tool to confirm someones address, or allow your visitors to look up a weather report for a holiday destination you are offering without the user leaving your website or app.

This is achieved through the use of some technology known as ‘web services’ or an ‘Application Programming Interface’ (API).

One of my projects for 2013 involves making use of API’s to load data from a web server so I thought I would share how API’s work through this demo:

Lets say you have a database of recipes containing:

  • Recipe ID
  • Title
  • Thumbnail of the Dish
  • Ingredients & Method
  • Author

Next you would need to define what formats you want your data to be presented back, in this case I am going to use JSON and XML formatting.

On your web server create a new folder or appropriate place to store your API data file. In my case I have chosen: domain.com/api_interface/ and add a new file titled ‘API.php’

Inside API.php we can start to add some code:

<?php

//Checking and Getting the two variables format and number of records
if(isset($_GET[‘format’]) and intval($_GET[‘num’])) {

//Set our variables
$format = strtolower($_GET[‘format’]);
$num = intval($_GET[‘num’]);

In this code we open the PHP tags and check that we are getting two variables from the HTTP request – the format (either XML or JSON) and num (number of rows of data).

After this we need to connect to the database and start to query for data:

//Connect to the Database
$con = mysql_connect(“localhost”,”username”,”password”) or die (‘MySQL Connection Error.’);
mysql_select_db(“database_name”, $con) or die(‘MySQL Table Error.’);

//Run the API query
$result = mysql_query(‘SELECT * FROM table ORDER BY `recipe_id` ASC LIMIT ‘ . $num, $con) or die(‘MySQL Query Error.’);

This query will look-up the table ‘table’ from the database ‘database_name’ and return in ASCENDING order rows of data.

Now we have the data we can build an array and begin to present the data we would like.

//Preapre our output
if($format == ‘json’) {

$recipes = array();
while($recipe = mysql_fetch_array($result, MYSQL_ASSOC)) {
$recipes[] = array(‘post’=>$recipe);
}

$output = json_encode(array(‘posts’ => $recipes));

Fortunately for us PHP includes an encoder for JSON so specifying that we want the data in JSON format we can load the data into an array and then write the data directly into the correct format.

If on the other hand we would like our data in XML format we can use a loop inside php to load the array and then fill in the XML tags to present back the XML format required:

elseif($format == ‘xml’) {

header(‘Content-type: text/xml’);
$output .= “<?xml version=\”1.0\”?>\n”;
$output .= “<recipes>\n”;

for ($i = 0 ; $i < mysql_num_rows($result) ; $i++)
{
$row = mysql_fetch_assoc($result);
$output .= “<recipe> \n”;
$output .= “<recipe_id>” . $row[‘recipe_id’] . “</recipe_id> \n”;
$output .= “<recipe_name>” . $row[‘title’] . “</recipe_name> \n”;
$output .= “<recipe_img_small>” . $row[‘thumbnail_photo_url’] . “</recipe_img_small> \n”;
$output .= “<recipe_link>http://www.domain.com/recipes/recipe_detail.php?=” . $row[‘recipe_id’] . “</recipe_link> \n”;
$output .= “</recipe> \n”;
}

$output .= “</recipes>”;

The else if statement is connected to the IF statement above and relates to the users choice of data they would like (JSON Vs XML). As the If statement is run it loops through the statement filling in the blanks with data from the Array creating a complete XML file.

This is what the files look like in their respective outputs.

JSON:

{“posts”:[{“post”:{“recipe_id”:”1″,”title”:”Quick and Easy Rice”,”large_photo_url”:”tbd”,”thumbnail_photo_url”:”tbd”,”ingredients”:”Rice\r\nBoiling Water\r\nSesame Oil – Optional\r\n”,”method”:”Cook some rice”,”Author”:”Mathew”,”thumbs”:”1″}}]}

XML:

<recipes>
<recipe>
<recipe_id>1</recipe_id>
<recipe_name>Quick and Easy Rice</recipe_name>
<recipe_img_small>tbd</recipe_img_small>
<recipe_link>http://www.domain.com/recipes/recipe_detail.php?=1</recipe_link>
</recipe>
</recipes>

Building an API like this gives developers the most amount of flexibility when it comes to interfacing with your information and data.

Its worth noting that this API has got NO limitations attached to it and that should someone get a hold of your the API they would be able to spam your web server countless times bringing it down. I HIGHLY recommend the use of an API Key system such as mashery.com or  3scale.net/