...
You do not have to contribute your plugin to SIPfoundry. However if you do, sipXconfig team will keep your code up-to-date with platform changes.
Prerequisites
Adding support will require basic experience in XML, Java and Linux. Before you start developing you need to know how to download, build and install sipXconfig and become familiar with sipXconfig web interface.
sipXconfig works best with phones that download (pull) their configuration through TFTP, FTP or HTTP. Other protocols and configuration methods (OMA/DM, SNMP) are also possible.
Introducing the Acme Phone
We'll create support for a fictitious phone called the Acme Phone. It supports 5 lines (also called registrations) and a handful of SIP related settings. It loads a single configuration file from a TFTP server and the format looks like a typical "INI" File.
Code Listing
Here is the final copy of all the source files for our sample phone that will be references throughout this document. You can use these files are starting points for your implementation.
- AcmePhone.java - Java source code
- AcmePhoneTest.java - Java unit test source code
- expected-config - Java unit test source code
- acmePhone/phone.xml - sipXconfig settings file format for phone settings
- acmePhone/line.xml - sipXconfig settings file format for phone line settings
- acme/acme-models.beans.xml - Plugin Definition Spring Framework file used to dynamically load your phone
- acmePhone/config.vm - Configuration Velocity template for creating configuration file
Step 1: Capture Phone Settings - phone.xml
sipXconfig is a model driven configurator. Each configuration parameter is known as "setting". Your first task is to describe all the configuration parameters in a special XML format used by sipXconfig. This will ensure that sipXconfig knows how to generate configuration screens for your phones, and store settings values in the database.
...
If your phone can keep copies of local and provisioned settings, then you may want to concentrate on settings that are critical to a phones operation and that would need to be set for a large set of phones. For example, Outbound Proxy Transport Protocol: UDP v.s. TCP. If for some reason an admin needed to use one over the other.
Step 2: Capture Line Settings - line.xml
Phones that support multiple registrations will have a subset of settings that apply to each line or registration. For example, the authorization user id, the password (or passtoken). You need to pull these settings into a separate file named line.xml
Step 3: Implement Phone Object - AcmePhone.java
Start with a copy of AcmePhone.java, you'll want to make the following changes
Subclass from base phone class.
Code Block |
---|
public class AcmePhone extends Phone \{ |
...
It's important to know that a new instance of your phone class is instantiated each time sipXconfig generates a new configuration file, reboots a phone or displays settings screen in the web UI.
Define setting constants
Code Block |
---|
private static final String USER_ID_SETTING = "credential/userId"; |
The field name is arbitrary, but the path should correspond to path in phone.xml
or line.xml
. You only need to define settings that will need special processing, one of which is described in the next section.
Support for external lines
Code Block |
---|
@Override protected void setLineInfo(Line line, LineInfo info) \{ line.setSettingValue(USER_ID_SETTING, info.getUserId()); ... \} |
...
Here we account for all the very basic line information the system would need to examine and create a registration for your phone. This information is important when creating external line registrations, but may have other uses in the future.
Load settings files
Code Block |
---|
@Override protected Setting loadSettings() \{ return getModelFilesContext().loadModelFile("phone.xml", getBeanId()); \} @Override protected Setting loadLineSettings() \{ return getModelFilesContext().loadModelFile("line.xml", getBeanId()); \} |
This is required and typical for all phones. Here you would have an opportunity to alter the settings model, for each phone instance.
Line Runtime Defaults
Approach 1: Java annotations
...
When the settings you want to influence match a particular pattern, you should investigate implementing SettingValueHandler interface. For example, all integer settings, or setting names that end with "_xyz"
Phone Runtime Defaults
Phone-wide settings (as opposed to line settings) have a similiar opportunity to supply defaults by implementing initialize()
method.
Step 4: Create Plugin Descriptor - acme-models.beans.xml
In order for the system to load support for you new phone model, you must create this descriptor file. File name must match the following wildcard expression *-models.bean.xml
to get loaded automatically by the Spring framework.
File Format
Code Block |
---|
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd"> |
You may have noticed from the DTD reference that this is a Spring Framework file. You don't need to know Spring Framework, all that you should need is described below.
Phone Model(s)
Code Block |
---|
<bean id="acmePhoneStandard" class="org.sipfoundry.sipxconfig.phone.PhoneModel"> <property name="beanId" value="acmePhone"/> <property name="label" value="Acme"/> <property name="maxLineCount" value="5"/> </bean> |
...
- id - unique identifier for one particular model of your phone. This must not change (unless you create a database patch beyond the scope of this document.)
- label - Name that appears from web UI to distinguish your phone to end user
- maxLineCount - Total number of registrations your phone can support. This is not the number of simultaneous calls, which is not captured here.
Phone Class
Code Block |
---|
<bean id="acmePhone" class="org.sipfoundry.sipxconfig.phone.acme.AcmePhone" singleton="false" parent="abstractPhone"> </bean> |
...
- id - unique identifier for your implementation
- singleton="false" - required are must always be false, this is to ensure a new instance of your phone is created to represent each phone in your system
- parent="abstractPhone" - injects all the typical services a phone uses.
Advanced Topic: Access to other settings or services
From this plugin descriptor file you can gain access to other parts of the system that are of interest to your phone. For example, if your phone could browse LDAP servers, you could get access to the LDAP settings
...
-- MichalBielicki
Q: How does one know what services are available or their names?
-- Lazyboy
A: No great way, but every part of the system is available from Spring so if it's configurable it's available somewhere.
Browse all *.beans.xml files. This also looks promising http://opensource.atlassian.com/confluence/spring/display/BDOC/Home
Step 5: Generating Profiles - config.vm
AcmePhone will generate its configation in the text file in the TFTP root directory. Although overkill for this simple example I will use Velocity to create a template to help generate a profile. You can implement any scheme you want including simply dumping setting values into a flat file using standard Java file IO. Velocity is a templating tool and is embedded into sipXconfig but it is not required to be used for configuration file generation. Its templating language is documented on the Velocity web site.
...
This template will copy all settings directly into the configuration file. Because of the simplicity of this method the setting groups and settings must be organized exactly how the config file breaks its settings into INI sections. The is fine for generating profiles, but may not always be helpful for the user. This is fine for now, however if this changes then settings can be filtered before passing them to Velocity or Velocity can call filter methods from java.
Step 6: Creating a unit test - AcmePhoneTest.java
Code Block | ||
---|---|---|
| ||
... public void testGenerateTypicalProfile() throws Exception { AcmePhone phone = new AcmePhone(); // call this to inject dummy data PhoneTestDriver.supplyTestData(phone); StringWriter actualWriter = new StringWriter(); phone.generateProfile(actualWriter); InputStream expectedProfile = getClass().getResourceAsStream("expected-config"); String expected = IOUtils.toString(expectedProfile); expectedProfile.close(); assertEquals(expected, actualWriter.toString()); } ... |
This instructs your phone to generate a configuration into memory, then compares the configuration to what you expect it to be. Here we use a utility class PhoneTestDriver
to create sample data but may create your own. Every single setting is compared, so means the unit test will have to be updated quite regularly, however if there was a problem with any of the settings, this is the best way for you and others find the issue.
Running unit test
To run my test, I go to unix or DOS prompt and run the following commands:
...
All the unit tests can run from eclipse if you've set up your eclipse environment accordingly.
Step 6: Submitting to sipXconfig project
Before submitting your code you need to run a couple of checks.
...
Code Block |
---|
ant -Dwith.clover clean default test-all clover.viewer |
Advanced Features
Speed dials
Support for speed dials allows phone to take advantage of Speed Dial UI screen available in User Portal.
...
SpeedDial object contains a list of buttons. If phone supports BLF it should check if the button is "monitored" and treat it appropriately.
See LG-Nortel plugin for an example.
Phonebooks
sipXconfig admin can configure phonebooks for end user. To take advantage of the phonebook feature phone plug-in needs to retrieve the list of entries for the phone and then use the list when generating configuration profiles.
...
See Polycom plugin provides a good example.
Others
- DST parameters
- NTP address and other network paramters
- Model variations and conditional settings
- Profile delivery
Contributed Phone Support To Date
- Niels Ohlmeier added support for the Snom Phones
- Hannu Strang added support for the Grandstream Phones
- Hannu Strang also added support for Cisco Phones
- Michal Bielicki added support for the Hitachi wireless Phones
- Michal Bielicki also upgraded support for the Snom Phones
- Douglas Hubler added support for Polycom Phones
- Sen Heng added support for the Linksys Phones
- Sen Heng also added support for the New Cisco Phones
- Your name here and your phone here