Monthly Archive for March, 2012

MacRuby, CocoaPods, 10.7, and XCode 4.3

I have a MacRuby project that uses CocoaPods for many of its ObjC dependencies. I had a bit of trouble getting it to run properly with the latest version of Xcode (4.3). This had to do with a recent change I made to MABSupportFolder (use of isEmpty()) which triggered a fairly obscure bug in addition to the new XCode 4.3 organizational structure not being properly recognized at first.

The obscure MacRuby bug was being caused by running -count on an NSString. When using MacRuby if you test if a NSString responds to -count using -respondsToSelector: you’ll get true as the response because of Ruby’s String#count method. However, that method requires an argument, but running respondsToSelector:@selector(count) will return true for an NSString. This bug was triggered because of my usage of Will Shipley’s isEmpty() function.

If you recently upgraded to Xcode 4.3, make sure you run this command (got this tip from here):

sudo xcode-select -switch /Applications/Xcode.app/Contents/Developer

Or `pod install` will not run properly. Also, I just found out that CocoaPods does not use macruby anymore – you can run it using the system ruby install.

For someone trying to get MacRuby working with CocoaPods here is my Podfile:

platform :osx

dependency 'FMDB'
dependency 'ASIHTTPRequest'
dependency 'MABToolkit'
dependency 'KFAppleScriptHandlerAdditions'

# Enable garbage collection support, which MacRuby requires.
post_install do |installer|
installer.project.targets.each do |target|
target.buildConfigurations.each do |config|
config.buildSettings['GCC_ENABLE_OBJC_GC'] = 'supported'
end
end
end

generate_bridge_support!

The top of your main.rb should look like this:

framework 'Cocoa'

load_bridge_support_file NSBundle.mainBundle.pathForResource("Pods", ofType:"bridgesupport")

Create Gzipped Tar Archive Service for OS X 10.6 + 10.7

Although the tgz command line syntax is very simplistic, I’ve never managed to remember the exact flags for the command line interface. Additionally, if I’m clicking around in the Finder I don’t want to have to fall back to the command line to create a tgz archive. Inspired by this hint you can download a service to create a tgz archive that works with Snow Leopard and Lion.

Scripting OmniGraffle: MySQL Visualization & JSON Representations

OmniGraffle is a great tool for visually mapping out complex relationships or hierarchical structures. Often when working in groups where some of the personnel have no programming or mathematical background OmniGraffle is a great tool to bridge the gap.

Converting OmniGraffle Hierarchy to JSON

Often I’ll use OmniGraffle to map out site structures with non-programmers. The challenge is once everything has been done in OmniGraffle it is normally a manual process to convert the data in OmniGraffle to a structured data representation, like JSON, that is easy to programmatically work with. Or, in my specific case, output the structured OmniGraffle document into a text document that could be reviewed and edited by others on a Google Doc. I wrote a script to pull structured data out of an OmniGraffle document.

Visual MySQL Database Structure in OmniGraffle

Pretty cool tool to visual a MySQL database in OmniGraffle (including foreign keys!). I did not write the original version, but I modified it to work with the latest version of OmniGraffle. Check out the modified MySQL to OmniGraffle visualizer.

JPEG + PNG Color Management Strategies for the Web

The first step in the design process of any website is to mockup the design in Photoshop. One of the most frustrating parts of the design process can be converting your mockup into image slices whose colors mix well with native CSS styles. Mark Edwards, over at Bjango, has a great writeup on color profile management and UI design. The basic tenants are: don’t color manage, use native monitor color profile, use RGB, and do not attach color profiles to JPG or PNG images.

However, in my senario, I often work with graphics that have been designed by people who work in print and don’t understand web image generation in the slightest. Often I’ll receive unoptimized PNGs, JPGs in CMYK, images with color profiles, etc. This can cause image display issues in IE, color shifting, and generally hurt the performance of a website.

In order to help myself optimize images for the web I created a small tool with an associated BASH script to convert CYMK images to RGB, strip color profiles, and optimize image file size.

This tool arose from noticing that Preview.app seems to optimize file size pretty well for PNG and JPEG. I tried to mimick the Preview.app export and while looking through the NSImage APIs noticed you could pretty easily strip color profiles and convert CMYK to RGB.

Introduction to VOIP Telephony: Setting up a Business Phone System with Asterisk and Polycom

I was recently charged with picking out a new telephone system for a new office the company I work for was moving into. We were previously using a 3Com NBX 100. Inbound and outbound call volume for this company is relatively low. The needs of the company included: 1) easy + extensible conference calls 2) ability to use softphones (software) 3) good voicemail system 4) reliability. The company was not looking for a unified messaging system, video conferencing, color LCD phones with automatic VPN connections, etc. A basic PBX to support the phone needs of a small company was all that was needed.

Proposals from a couple providers yielded total costs of a 10 hard phone + 10 soft phone system to be around $8,000 – $12,000 with an ongoing contract. This seemed a bit high considering the simplicity of the needs of the company. After some research and a lot of trial and error I was able to get the entire phone system deployed for less than $2,100 ($350 POE switch, 10 phones * $85, ~$900 analog card, used an old Windows box lying around). It took me about a week of full-time work to figure out how all the peices fit together and deploy the system. Although VOIP may seem a bit intimidating with all the lingo and plethora of options, it isn’t as hard or mysterious as it may seem at first.

Hopefully this compilation of notes will help someone in a similar situation develop and deploy a VOIP Asterisk based solution. Enjoy.

Vocabulary

  • POTS = Plain Old Telephone Service = Analog Lines = Copper Lines
  • SIP = Session Initiation Protocol. This is the traffic that will travel over your LAN and communicate with your office phones (in my case, Polycom 321s and Telephone.app)
  • SIP Trunk = A digital alternative to POTS. I did not utilize a SIP Trunk in my setup, but from what I understand you basically grab a special card that then connects through your WAN to a remote SIP Trunk provider. Essentially your phone lines are routed through your internet (similar to Skype).
  • PBX = Private Branch Exchange. This is box that sits between your telephone endpoints (SIP trunk or POTS) and your phones connected to your lan
  • POE = Power Over Ethernet. Many modern phones can be powered through the ethernet cable that they use to communicate with the LAN, this eliminates the need for power adaptors for each individual phone. Some ‘pre-built’ / commercial PBXs have POE built in. In my setup I purchased a NetGear FS728TP-100NAS
  • TFTP = Trivial File Transfer Protocol. The Polycoms (and many other phones) use TFTP to pull their application binary, configuration settings, and other information.
  • ARP = Address Resolution Protocol. I don’t really understand this piece too much, but
  • FreePBX / Elastix = GUI for the Asterisk configuration files
  • DAHDI = software that integrates with Digium (and other) analog and digital PCI hardware devices. This used to be called Zaptel. This software runs on the driver level of operating system (it isn’t a service like Asterisk). Essentially is bridges asterisk with POTS or SIP trunks.

Basic System Overview

  • Separate cat6 voice + data lines to each work station
  • Data lines connected to gigabit switch
  • Voice lines connected to POE 10/100 switch referenced above
  • POE switch tied to the gigabit switch via 2 gigabit ethernet ports
  • Asterisk running on couple-year-old Dell dual-core 2.8ghz, 3GB of ram, gigabit ethernet
  • Asterisk box (PBX) connected to gigabit switch
  • 6 POTS lines through Verizon
  • 10 Polycom SoundPoint 321
  • 10+ Softphones
  • Remote users accessing PBX via VPN
  • ack instead of grep on the command line
  • Asterisk 1.8.8.1, FreePBX 2.9.0.9, DAHDI 2.5.0.2, CentOS 2.6.18-274.17.1.el5 (`uname -r`)

Setting Up an Asterisk-Based VOIP System with Polycom Phones

Basic AsteriskNOW Installation Procedure

There a couple ways to handle Asterisk installation, and a couple GUIs to choose from. I settled on AsteriskNOW + FreePBX GUI. After downloading the image, burning it to disk, and booting from the disk on your asterisk box you still need to update to the latest versions of the software by running `yum update`. After running `yum update` you’ll have to update the FreePBX software. You can sort of do this through the FreePBX module interface, but there was an extra step involved that I couldn’t find my notes on.

Duplicate IP Message on Polycom 321 Phones

This message was caused because of an old Microsoft 2003 Business server that was still connected to the network. DHCP used to be handled by the server, but we switched DHCP to the SonicWall. Although DHCP was disabled on the MS server, it seemed to be sending out some sort of broadcast that caused the phones (and only the phones!) to report a duplicate IP. Eliminating the MS server was the only solution that worked (all services relating to DHCP had been turned off on the server.

Updating Polycom 321 Firmware via TFTP

The Polycom devices support both FTP + TFTP configuration + boot loading. However, I was trying to simply the setup as much as possible and trivial FTP sounded a bit more simple. However, a TFTP server is not configured by default on an AsteriskNOW installation. To enable TFTP, first run `nano /etc/xinetd.d/tftp` from the command line and then change `disable = yes` to `disable = no`; save the file. Finally, run `service xinetd restart` from the command line. The TFTP server should be up and running.

The TFTP server does not have `ls` and other FTP-like commands. The easiest way to test if it is working is to grab a file from it from another machine:

$ tftp pbx.localhost
tftp> get LoudRing.wav
Received 128810 bytes in 0.1 seconds
tftp>

Sending Phone Boot Server via DHCP

Apparently there are many parameters you can send to clients via DHCP. DHCP was running on a SonicWall 210 in this specific configuration. I had a bit of trouble getting this working, but the following settings worked on the SonicWall for me:

  • option 66: tftp://pbx.localhost
  • option 160: tftp://pbx.localhost
  • option 150: tftp://pbx.localhost
Note that the “tftp://” is important. In this specific instance I had a local DNS server running on a Mac Mini Server (Lion) that all clients were configured to hit before hitting the external DNS.

Upgrading the Polycom BootRom & Sip.ld (Application)

This was a bit tricky, and I did not document exactly how I got to it work, but here are some pointers. You’ll need to download “UC_Software_3_3_3_release_sig_split” the not the latest ”UC_Software_4_0_1B_release_sig_combined.zip” from Polycom support. Looking at the end point manager’s package.json it seems as though the latest supported version is 3.3.3. I tried downloading the split version but it didn’t seem to work as well for me. You’ll also need to download the latest BootRom ”spip_ssip_BootROM_4_3_1_release_sig.zip”. After downloading these pieces you’ll have to send them to your /tftpboot folder (I used `scp sip.ld root@pbx.local:/tftpboot` to move the files over). After putting the pieces in place, `ls -l /tftpboot` should look something like this:

-rw-rw-rw- 1 asterisk asterisk 2437 Feb 20 14:30 000000000000.cfg
-rw-rw-rw- 1 asterisk asterisk 2079 Feb 18 15:39 0004f2a8077e.cfg
-rw-rw-rw- 1 asterisk asterisk 7470 Feb 18 12:53 0004f2a8077e_reg.cfg
# ... (more configuration)
-rwxr-xr-x 1 asterisk asterisk 639624 Jan 27 14:27 2345-12360-001.bootrom.ld
-rwxr-xr-x 1 asterisk asterisk 3322061 Jan 27 14:41 2345-12360-001.sip.ld
-rwxr-xr-x 1 asterisk asterisk 7591196 Jan 27 13:45 bootrom.ld
drwxr-xr-x 2 asterisk asterisk 4096 Feb 18 14:34 contacts
drwxr-xr-x 2 asterisk asterisk 4096 Jan 26 14:59 licenses
drwxr-xr-x 2 asterisk asterisk 4096 Feb 18 12:53 logs
-rw-rw-rw- 1 asterisk asterisk 127966 Feb 20 14:30 LoudRing.wav
drwxr-xr-x 2 asterisk asterisk 4096 Feb 13 16:12 overrides
-rw-rw-rw- 1 asterisk asterisk 8537 Feb 20 14:30 sip.cfg
-rwxr-xr-x 1 asterisk asterisk 14 Jan 27 14:41 sip.ver
drwxr-xr-x 2 asterisk asterisk 4096 Jan 26 14:59 SoundPointIPLocalization
-rw-rw-rw- 1 asterisk asterisk 95926 Feb 20 14:30 SoundPointIPWelcome.wav

I’m not sure if you needed an updated bootrom.ld and the specific 2345-12360-001.bootrom.ld; but it worked.

Using End Point Manager to Generate Configuration XML for Polycom

In order to install End Point Manager I had to upload the module via the FreePBX Module Admin. For my installation (details given above) I used version 2.9.2.9 (list of .tar.gz versions can be found here, GitHub repo here. After installing, go to advanced options and set “Time Server” to “pool.ntp.org” and nmap to “/usr/bin/nmap” (you may have to install nmap via yum, I can’t remember if it was installed by default or not). If you are using TFTP, make sure that configuration option is set as well. I could not get the automatic phone vendor packages to work. I had to download the “provisioner_net.tgz” and manually upload the package via the “Manual Endpoint Modules Upload/Export” under “End Point Advanced Settings.”

At this point, with the DHCP options correctly set, for new phones you should be able to plug them into the network, run a scan using nmap, and add the phones via the end point manager GUI. Unplug & replug the Polycom phone in and it should pull the configuration from the TFTP server (the PBX box) set in the DHCP options and startup just fine.

Default “Phone Book” / Directory on Polycom

Although the phones claim to support loading the `000000000000-directory.xml` file into all phones; I could not get this to work even after factory resetting the phones. I grabbed the XML for the polycom directory by using this modified version of the printextensions module, copying the XML into the `000000000000-directory.xml` file, and then running this BASH script to copy the default to each of the phones custom directory.xml files. Do not use this with a production system as it will overwrite any users customizations.

Installing Git on CentOS (Default AsteriskNOW OS)

Yum is the default package manager on CentOS, but the default repos don’t contain git. I wanted to pull in my dotfiles to the Asterisk box as well as manage the custom print extensions repo that I was working on. Here are the two BASH lines you need:

rpm -Uvh http://repo.webtatic.com/yum/centos/5/latest.rpm
yum install --enablerepo=webtatic git-all

Software vs Hardware High Performance Echo Cancellation (HPEC)

This is specific to Digium based cards. I didn’t know this until after purchasing the TDM800 with hardware echo cancellation, but after talking with an Digium customer support representative I learned that the algorithm used for echo cancelation is the same for the software based and hardware based echo cancellation. The CPU load on my installation hovers around 1%, I’m guessing for a < 20 person office environment the software based echo cancelation would of worked just fine (although I don’t have experiential evidence to support this).

Call Logging

Initially call logging did not work in my installation. You can check if call logging is configured correctly by running `asterisk -r` and then running `cdr show status` from the Asterisk prompt. You should see something like:

Call Detail Record (CDR) settings
----------------------------------
Logging: Enabled
Mode: Simple
Log unanswered calls: No

* Registered Backends
-------------------
mysql
cdr-custom

If your installation is working correctly. Mine wasn’t, working off this guide, the following BASH commands worked for me:

# check if the mysql addons are installed
yum list installed|ack mysql

# if they aren't, install the mysql addons
yum install asterisk18-addons-mysql

Digium Has Incredible Customer Support

I was throughly impressed by the quality of Digium’s customer support. They answered non-hardware related questions, ssh’d into my machine to debug some issues, and there was a less than one minute wait time.

Outbound Call Configuration

This was something that ended up being a bit more tricky that I thought. I ended up configuring the dial patterns to force long distance formatting (01+xxx+xxx+xxxx) on all numbers. I wanted to ability for people to dial with and without the 1, this seems to be working fine so far:

Asterisk Outbound Route Configuration

Asterisk Outbound Trunk Configuration

POTS Call Tuning

Different POTS lines have different levels and other ‘analog stuff’. To clear out noise and optimize your configuration you need to run the following script (retrieved from a Digium rep):

service asterisk stop
# tunes impendence on the analog lines
fxotune -x -i

# restart dahdi and start asterisk
service dahdi stop && service dahdi start
service asterisk start

Setting up IVR Auto Answer

Configure your IVR, then go to Setup –> Inbound Routes. Choose “any DID / any CID”. At the bottom of the page switch “Destination” to IVR + desired auto attendant.

Configuring Backups

I usually login to the Asterisk box as root. I configured the backups with my root SSH key, but the Asterisk backup process runs on the Asterisk user. Make sure that the SSH keys you hand off to FreePBX are readable by the asterisk process.

Inbound + Outbound Call Volume Tuning

Word of warning: I haven’t actually done this yet. These are the notes I’ve compiled, but I wasn’t able to get all this information together before the phone system was deployed.

Most of the guides I was able to find were a bit out of date. When reading through those resources recall that Dahdi is the new Zaptel. There are two gain adjustments: inbound (rxgain) and outbound (txgain). In order to test the levels run the following command: dahdi_monitor 1 -vv. These levels can be calibrated against a 102 milliwat test number, I found one here: 670-234-0102.

For the TDM800, here are the instructions from Digium on how to edit the two gain levels:

The gains are typically edited in /etc/modprobe.d/dahdi.conf. The parameters are set like:

options wctdm24xxp fxotxgain=<value>db fxorxgain=<value>db fxstxgain=<value>db fxsrxgain=<value>db

The default value is -4.5db (decibels)

They can also be edited in /etc/asterisk/chan_dahdi.conf

rxgain=<value>
txgain=<value>

In this case the ‘db’ is assumed by asterisk. In chan_dahdi.conf the default value is 0.0.

We encourage you to make small changes to any of these values as it can dramatically effect your audio.

Misc Tips

  • If calls are dropping after a couple seconds, check your external IP in Tools –> Asterisk IAX Settings
  • Uninstalling Asterisk modules:
    /var/lib/asterisk/bin/module_admin uninstall endpointman
  • The Music on Hold directory is
     /var/lib/asterisk/moh/
  • Grabbing the DAHDI version from the command line:
    dmesg|ack dah
  • To add a invalid extension or timeout fallback to your IVR / autoattendant add two options in the IVR GUI: i & t (you specify i or t instead of a number) and then specify a action just like you would a normal IVR option.
  • Restart DAHDI & Asterisk in one line:
    service asterisk stop && service asterisk start && service dahdi stop && service dahdi start
  • Copy default directory.xml to specific directory.xml’s for all Polycom devices linked to the EndPoint Manager
  • Location of HPEC license(s):
     /var/lib/asterisk/licenses
  • Convert standard wav files into Asterisk / POTS compatible wav:
    sox autoattendant.wav  -r 8000 -c 1 -s -w auto-new.wav resample -ql
  • Caller ID is not consistent across carriers. Some carriers can disregard caller ID information altogether.
  • I had trouble with the built-in Polycom phone restart script contained in the endpoint manager. I wrote a quick script to work with someone’s Polycom restart script as a workaround.
  • I originally tested the system on an XP100 clone card, and I’m pretty sure that was the source of this issue, but this information was helpful in temporarily resolving that issue before I purchased the TDM800.
  • FXO hardware’s context must be set to “from-pstn” for the IVR to be routed correctly
  • If all your inbound calls are coming in as “Unknown” you might want to check with your service provider. According to my Verizon account rep, inbound calls can sometimes come in as Unknown on new lines if your account is configured incorrectly
  • Dashes and parentheses outbound numbers inputted into softphones seems to cause issues with dialplans
  • You can export Asterisk compatible .wav files directly from Audacity without using any command line tools to post-process the audio.
  • To reset a Polycom 321 phone, reboot the phone and hold 1 + 3 + 5 + 7. The default admin password on these devices is 456.
  • In order to enable the “Line 2″ button on the polycom phones you’ll need to edit the master configuration file and change the “reg.1.lineKeys” preference to “2″

References

Here is a list of links I found helpful while researching this stuff.

Polycom Phones

Asterisk

Software