Sunday, February 15, 2015

Hybrid Responsive HTML with Foundation

If you are using Foundation with Interchange you have seen extra requests that the client has to make to download the content. This is fine for images since that is a separate request anyway, but for HTML content I didn't want that extra request for mobile devices.

My solution, so far, was to exclude my default template size, (small), from the data-interchange variable, and include that small template directly into the div as the default content. This works fine with loading on a small template since no other requests are done. But if the browser is resized to medium and back to small it would stay with the medium html loaded by interchange.

To get around this I setup a new data attribute, and a little javascript.

in the div where data-interchange exists, I added a data-interchangeonreplace attribute.

Here is my example Div
<div id="testcontent" data-interchange="[medium.html, (medium)], [large.html, (large)]" data-interchangeonreplace="[small.html,(small)],[medium.html, (medium)], [large.html, (large)]">
  <div data-alert class="alert-box secondary radius">
    This is the default content.
    <a href="#" class="close">×

Here is the javascript:

$(document).on('replace', 'div', function (e, new_path, original_path) {
	var divid = $('#' +;
	if (divid.attr('data-interchangeonreplace')) {
		divid.removeAttr('data-interchangeonreplace');'interchange', 'reflow');

now when resizing past small it will add small.html back to the list so it if is then resized smaller it will display properly.

The same can be done in reverse, use whatever methods to determine your default template to display and only include it back in if the size changes, eliminating an extra client HTTP request for each block of code you load dynamically on your page.

Open Source Contribution - sort of

Who says I don't contribute to open source technologies, just paid to have Asterisk 13 support built for the unimrcp project. It now will compile properly with asterisk 13, tested up to 13.1.1. We also needed a feature to allow the mrcprecog function to play multiple audio files, since we use that format for our prompts. Link is here for the multiple file syntax:

Monday, November 17, 2014

Asterisk - recording confbridge

When you find a business case to record a conference in asterisk here are some tips I have found.

Don't set record_conference to yes in the conf file, instead set only the conferences you want to record in the dialplan.  This can be done with


but there are some caveats, as you can see I tried to name the file as a variable.wav, however the file will actually be named variable-timestamp.wav, which can cause issues if you don't expect it.  Sure there are ways to get the filename in the dialplan (MIXMONITOR_FILENAME I think), but our solution, which processes the files after the call is done was found on the internet and just runs this command in PHP
$cmd = 'mv /var/spool/asterisk/confbridge/'.$data['phone_call_id'].'-*.wav /var/spool/asterisk/confbridge/' . $data['phone_call_id'] . '.wav';

In Asterisk 11 we were able to start our conference with

which would still use our settings set above to record the conference, however in asterisk 13 which we just upgraded to this command now has to be

which uses the custom channel bridge variable setup by the CONFBRIDGE function

Friday, November 7, 2014

Windows Phone 8.1 vs Android

Let me preface by saying I have used a windows phone since it was an inch thick and slid up giving an actual keyboard.  Recently I had a need to test some android video streaming for work, so I headed to Best Buy and purchased a Samsung Galaxy S5 outright ($799), along with 2 years protection ($199) and a really great glass screen protector ($40) and used it for a month.  Here are my experiences and comparisons to my HTC 8X.


clearly android has the edge here, everything under the sun is released for android.  I was able to join my friends in clash of clans, catch up on candy crush, watch xfinity live tv when the cable was having problems, update blogger, etc.   Windows phone has a good number of important apps and a lot of good games, but just doesn't get the support of developers since the marketshare of the phone isn't high enough, its a tough cycle to get out of, Microsoft is doing their best to buy up applications like minecraft to bring them to the platform and hopefully attract some market share.
Winner: Android

Phone Design - Hardware

Android has a back button, home button, and a button that brought up a task manager (may just be default option on the galaxy s5).  Windows has a back button, windows button (home), and search button (cortana).  Windows phone brings up task manager/switcher by holding down the back button. Android and Windows phone are available on a variety of comparable hardware.
Winner: Tie  

Phone Design - Software

Here is the big difference, this is where you notice the difference.  Android gives a flexible design where you can install other apps to change things around, but this was the most frustrating thing in using android.  Out of the box it just wasn't as good as it should be.  I downloaded a different launcher (google now maybe), a different app to handle txt messages, had to download twitter, facebook, etc, then had to setup the homescreen which wasn't that easy to figure out.  Windows Phone uses the microsoft live tile design, its square and retro looking, but once you use it you see how much better and simpler it is.  Microsoft started their marketing campaign about being able to look at your phone and see everything, and it really is like that, I move my home screen around and rarely have to scroll down or view the app list.  Which brings me to the app list, android like iphone displays pages if icons, that do little more than take up space.  Windows phone uses a single alphabetical list with the ability to jump to any letter.
Winner: Windows Phone

Voice Assistant

Cortana was added to the windows phone in version 8.1 and acts more like an assistant.  Android's OK Google seems to function in the same manner, though I don't use voice interaction with my phone much.  Though I nice feature added, not really voice, but related to cortana is quiet time. Cortana will handle your calls/txts during those hours, so if you don't want to be bothered cortana can reply to your txt messages, of course allowing someone to get you in the case of an emergency, they will just have to call or txt twice.
Winner: Tie


Android app support is great, but it was a pain to go into the twitter app to check my twitter feed, then into the facebook app to check my facebook feed, and using two different mail clients for my corporate and personal email (though there may be something to merge them, I didn't look that hard). I don't having to research the best launcher or the best app for messaging or the best keyboard.  I guess the flexibility is nice and a lot of people like that.  Windows Phone just has everything right there from the start.  My people tile has my twitter and facebook feed, my email is easily linked so all my accounts display in one area.  I wish the windows email would allow the swipe to delete like the android app I found.  The windows word flow keyboard was much nicer than the samsung swipe keyboard, it predicted better, had better guessing on what I meant and most of all if I hit the backspace to make a change to a word it doesn't know it doesn't keep changing it like the samsung keyboard.

I also tested Android Wear with a moto360 watch.  It was the first android watch I saw that I liked the design of.  I was hoping I could load multiple watch faces and switch them at will.  I could, but had to purchase a facer app, download watch faces and load them into the app, and have to change them via the phone instead of on the phone, but that wasn't too much of a problem.  Battery life lasted for a day, notifications were nice when the phone is in your pocket, it didn't quite turn on perfectly, sometimes I had to move my wrist around to see the time.  I will test the microsoft band and update that test when they get more in stock and I can purchase one.

These are my experiences using android for 30 days. I have just switched back to my windows phone and will update here to see what I miss from the android phone, if anything.

Monday, October 27, 2014

Asterisk quick tips 1

Quick asterisk tips part 1

1. variables

when using expressions and a variable may not exist enclose it in double quotes so it gets interpreted into valid code and doesn't thrown an error

So if the VAR variable doesn't exist this gets interpreted into ""="ENDED" which will be false.

2. variable as variable name

If you get to advanced asterisk there may be a case where you need a variable to be a variable name, here is how to check if it is set


in this example ARG3 is a variable that holds the name of the variable to check.

3. stackpop

when using subroutines you have to return() to go back to the calling location.  But inevitably there are cases where you don't want to return.  No problem, just use stackpop() to remove the return location and you can go wherever you want in the dialplan without worrying about memory issues tracking the return location which isn't needed.

4. Special extensions

Learn the asterisk special extensions available.  Specifically the T extension, it allows you to set the timeout for a call, but instead of the system just hanging up you can run dialplan code to handle the channel properly.

  • s - What to do when an extension context is entered (unless overridden by the low level channel interface) This is used in macros, and some special cases. "s" is not a generic catch-all wildcard extension.
  • i - What to do if an invalid extension is entered
  • h - The hangup extension, executed at hangup
  • t - What to do if nothing is entered in the requisite amount of time.
  • T - This is the extension that is executed when the 'absolute' timeout is reached. See "core show function TIMEOUT" for more information on setting timeouts.
  • e - This extension will substitute as a catchall for any of the 'i', 't', or 'T' extensions, if any of them do not exist and catching the error in a single routine is desired. The function EXCEPTION may be used to query the type of exception or the location where it occurred.

PRK (Lasik) after one year

After years of using glasses I finally tried contacts and loved it. So after 2 years of contacts and the daily routine required I finally started to look into lasik. I setup my appointment with LasikPlus.

1. First appointment 

assistant had me do a number of different tests, looked into 3 different machines, and then the last step of getting drops put into my eyes to numb them for more testing.  After that they give a recommendation, in my case Photorefractive keratectomy (PRK) since my cornea was apparently too thin to slice it open.  More gory details on PRK later.

2. Preparation

No contacts for 14 days prior to surgery.  And don't have any problems giving yourself eye drops since there are 3 sets of them multiple times a day leading up to the day of surgery.  Some of the drops burned a little, but not much issue.

3. Surgery day

Get someone to drive you.  Got called into the waiting room which was the first time actually meeting the surgeon, got some powerful eye drops that numbed everything around your eyes.  Surgeon talked for a few minutes, prefaced that the next few days will really suck (his actual words).  PRK differs from Lasik in that the epithelial layer of the eye is scraped off instead of a flap being created during lasik.  After the short conversation we went into the laser room, laid down on in the chair to get positioned under the laser.

4. Surgery

Overall the entire process couldn't have taken more than 5 minutes.  Here are all the details.  First they put a device to hold open the eye lids, don't worry the eyes are so numb I didn't feel a thing.  The surgeon does so many of these he is quick.  My other eye was covered with some sort of patch.  At that point the epithelial layer was removed with what seemed like a little power tool with a soft tip.  There was some pressure, but felt nothing.  He then took some brush to clear off my eye.  He positioned me under the laser and asked me to focus on the lighted circle and to keep both eyes open, which I found impossible.  At that point the laser fired, I saw flashes of purple light with my vision varying with each pulse.  It was very quick, then the eye was flushed with cold water, and a bandage contact lens was positioned on my eye and the entire process was repeated for the other eye.  After that I got up and was done, immediately saw improvement.

5 Post Surgery - First few days

It was explained that the first few days could be bad, pain, tearing etc.  For me it wasn't too bad, only one morning had tearing, I just went back to bed and was fine by the afternoon.  Eye drops continued.  After 5 days I was able to drive myself to the followup appointment where the bandage contact lens was removed.

6 Post Surgery - First month

The first month was very difficult.  I have a tech job which means a lot of work on the computer.  But for the first month, till the steroid drops were done, everything on a screen was doubled.  Nothing I could do, closing one eye or the other still everything doubled.  So it took a lot of focusing and frustration to get through that point.  Apparently the steroid drops that are continued for the first month may be there to slow the healing process of the epithelial layer that was removed so that it doesn't scar.  Good news was once those drops were done vision immediately improved.  1 month visit and I had better than 20/20 vision (which I had with my contacts prior to the surgery).

7 Post Surgery - First year

Its amazing how quickly the daily routine of waking up not being able to see the alarm clock and having to put in contacts and clean them every night is forgotten.  I am very pleased with the surgery and would recommend it if you were considering it, my experience was very good and successful.  Only issue I have is when tired there is some starburst while driving and blurryness reading the TV on screen guide.

Asterisk IVR application tips

Finding good documentation on asterisk can be a chore, there are a lot of examples using old versions, and examples using simple dial plans for an office phone, but not much for advanced IVR applications.  Here are a few of the tips and tricks we have found over the last year using asterisk as an IVR application platform.

1. Use hangup handler

Your application will usually require some processing when a call ends.  Don't put h extensions in every context.  You can have issues if you need to update, or if you are in a macro/sub when the hangup happens.  Instead asterisk has a nice feature:
this hangup handler makes sure your code runs in all cases.  Just make sure you call that line at every entry point into the asterisk dialplan

2. Use AGI

AGI, similar to what CGI was for web applications, allows you to use development resources in other programming languages to run advanced code.  PHP is used for command line scripts for our applications.  This allows us to use the same PHP classes and code from asterisk and from our website.
AGI scripts can get variables directly from asterisk; however, testing from the command line then becomes impossible.
Something to keep in mind asterisk is unavailable while the script is running, so keep the scripts simple, keep reading for examples where scripts are expected to run lone (credit card processing).

3. Use GoSub and Macro

Don't duplicate dialplan code, learn to use gosub and macro functions

4. Inject audio into a channel

There are numerous reasons to play audio into a channel, whispers for time remaining, etc.  The dialplan code for this is very simple:
exten => s,1,Answer()
 same => n,Wait(0.3)
 same => n,Playback(${AUDIO})
 same => n,Hangup()

exten => do_chanspy,1,Answer()
 same => n,Chanspy(${CHANNEL},qW)
 same => n,Hangup()
the script code is what originates the call and sets the variable with the audio to play, this uses the phpagi project, though we modified the send_request function to a new version that allows multiple variables.
if ($AsteriskAMI->connect($SERVER . ':5038','AMIUSERNAME','AMIPASSWORD')) {
 $asm_data[4]['value']='CHANNEL=' . $channel;
 $asm_data[5]['value']='AUDIO=' . $audio;
 $call = send_request2('Originate',$asm_data);
This code originates a call to the asterisk system, uses the chanspy app to connect to the channel you want to play the audio on, plays the audio, then hangs up.

5. Redirect a channel to another context

This is useful in a number of cases when you need another channel to be moved based on the action of another, e.g. one caller is waiting on the system to call another then move both into a conference

6. Don't allow endless loops

Not sure why, but you will get people or scripts that just sit on the system, so make sure all options that request input from the user.
;arg1=current count
;arg2=max count
;arg3=context to goto if at max count
exten => s,1,GotoIf($[${ARG1} >= ${ARG2}]?${ARG3},${ARG4},${ARG5})

exten => s,1,Set(Tries=0)
 same =>   n(start),Set(Tries=$[${Tries} + 1])
 same =>   n,Macro(Tries,${Tries},10,BadTries,s,1)
 same =>   n,GoSub(Press_Or_Say,start,1(AUDIOFILE,1,129*,DTMF))
 same =>   n,GoToIf($[${RETURN_CODE}=1]?opt${ENTRY},1)
 same =>   n,Goto(s,start)
this is the framework of an example that will only allow a subroutine, that gets the users menu input, and if the expected results aren't received will retry for 10 times, then forward to the BadTries context where you can give an audio message or just hangup.

7. Long running AGI

As mentioned above AGI holds up asterisk processing, you don't want seconds of dead air while a customer is on the phone.  Here is one example on running a script in the background, looping audio while waiting for a response.

;ARG1 audio that plays
;ARG2 script to call - script has to accept channel as first parameter
;ARG3 variable to check - script must set this variable on the channel given using AMI
;ARG4 audio while processing
;ARG5 number of times to play audio recording before returning failure
;ARG6 return without playing the arg1 audio if script is done quickly
;ARG7 redirect channel immediatly on completed processing - script has to accept this as second parameter
;ARG8 arguments to pass to script, space separated
exten => s,1,Set(i=0)
 same =>   n,AGI(BackgroundProcess.php,${CDR(channel)},${ARG7},${ARG2},${ARG8})
 same =>   n,ExecIF($[${ARG6}=1 && "${${ARG3}}"!=""]?Return())
 same =>   n,Playback(${ARG1})
 same =>   n(waitingloop),ExecIF($["${${ARG3}}"!=""]?Goto(success,1))
 same =>   n,ExecIF($[${ARG5}<${i}]?Goto(failure,1))
 same =>   n,Playback(${ARG4})
 same =>   n,Set(i=$[${i} + 1])
 same =>   n,Goto(waitingloop)

exten => success,1,Set(BACKGROUNDPROCESS=TRUE)
 same =>   n,Return()

exten => failure,1,Set(BACKGROUNDPROCESS=FALSE)
 same =>   n,Return()
And the PHP script
/* BackgroundProcess
 * runs a script in the background so AGI can return to asterisk
 * script should take channel and redirect as first to parameters
 * script should set variable that the dialplan expects, or redirects the user to the redirect context,channel,priority
try {
if (!empty($argv[1]) && is_numeric($argv[1])) {
 $script_override_theater_id = $argv[1];

//this is an internal function that sets up the arg variables
$data = asterisk_arguments($argv, array(
 'channel' => 'string', //users channel inside asterisk
 'redirect' => 'string', //context,extension,priority to redirect to or empty if no redirect
 'script_name' => 'string', //php script to run, assumes in the agi-bin/TL directory of the project
 'parameters' => 'string' //parameters to pass to the script, should be space and quoted already

$result = array(

if (!empty($data)) {
 $cmd_start = '/var/lib/asterisk/agi-bin/TL/' . $data['script_name'];
 $cmd_end = ' > /dev/null &';
 $cmd = $cmd_start . ' "' . $data['channel'] . '" ' .      
  '"' . $data['redirect'] . '" ' .
  $data['parameters'] . 

} catch (exception $e) {