Wednesday, February 17, 2010

BIRT: BIRT Report Item Extensions Released by Innovent Solutions

As part of its commitment and involvement with the BIRT project Innovent Solutions, the company I work for, has created a project that offers a few graphical controls to illustrate BIRTs report item extension point. There are two extensions offered in these libraries. The first one is a Dot Bar. The Dot bar provides a quick visual representation of numeric values. This is useful for a quick, at a glance, representation, rather than overwhelm users with numbers everywhere in a report. The second is a Rotating Text graphic element, based off the original rotating text example illustrated in “Integrating and Extending BIRT”. The rotating text is useful when you are trying to conserve space on a report.

These extension elements are available at http://code.google.com/p/birt-controls-lib/.

Installation instructions are provided on the above link, but we will cover this real quick. There are two components necessary to install these into the BIRT Report Designer. There is a bb.birt.controls.xxx.jar, and a bb.birt.controler.ui.xxx.jar. The UI component is necessary for the BIRT report designer to show these new elements in the palette. The other jar contains the necessary runtime libraries for BIRT to know how to use these elements in a report.

The easiest installation method is to use the update site. The update site is provided in the instructions.

Once installed, you will have the two new components available on the Palette.

So, lets say I want to demonstrate these. In the following example, I will create a simple report that will show the offices and employee count for the Classic Cars sample database. Assume I already have the above components installed, and I am using BIRT 2.5.1.

1. Create a new report called newComponentTest.rptDesign.

2. Create a new Data Source using the Classic Cars example database.

3. Create a new dataset from the following query:

select

CLASSICMODELS.OFFICES.OFFICECODE,

CLASSICMODELS.OFFICES.CITY,

(select count('1') from employees where officecode = CLASSICMODELS.OFFICES.OFFICECODE) officecount

from

CLASSICMODELS.OFFICES

4. Right-mouse click on the data set, and choose Insert in Layout.

The report will look like so:

5. Now, select the OfficeCount detail data component, and delete it.

6. Insert a DotBar in the OfficeCount detail cell.

7. In the DotBar dialog, use the following details:

8. Now, remove the OfficeCode column (1st column).

9. In the City Detail cell, remove the City data component.

10. Insert a Rotated Text component into the cell.

11. Use the following properties:

The final report will look something like this:

And when you run the report, it should look like so:

The source for these components are available to be extended as well from the above linked Google Code site.

Tuesday, February 09, 2010

VOIP: Set Up Asterisk and LinkSys 3102 to work with SIPDroid.

My most recent project has been to set up a VOIP setup on my Droid so that I can VPN into my home network using either my 3G service or WiFi and use the unused landline that I have so that I don’t burn minutes. As a secondary objective, I’d also like to be able to have calls made to my house ring on my cell phone after a few rings on my house phone.

In order to accomplish this task, I needed 2 things:

A means to connect my landline to my Asterisk server

An old machine to run Asterisk on

The old machine was easy. I have an old Compaq that has been sitting idle since the early 2006 or 2007. It had Ubuntu Dapper Drake. Although I would have liked to have put something newer, it appears that most newer distributions don’t agree with the hardware, and I really don’t have time to mess around with passing in various kernel parameters in a trial and error manner since the error messages were non-existent. Since this was the case, I enabled the universe repository under /etc/apt/sources.list, and ran the following command to get Asterisk running:

apt-get –f install asterisk

I didn’t change any of the configuration files, I want to keep them stock since I will use a special configuration wizard.

Now, the hardware I used to connect the phone was a Linksys 3102 ATA. I also did not do anything in configuration outside of enabling configuration through the outside WAN since this is only connected to my Intranet.

Configuration, despite how confusing all this looked initially, turned out to be a piece of cake, thanks to this handy dandy configuration utility, courtesy of the nice folks at Voxilla. I simply followed the wizard, which automatically configured the 3102 to work with Asterisk. To configure Asterisk, I made a backup of the sip.conf, voicemail.conf, and extensions.conf, removed them, and copy and pasted in the appropriate configuration sections from the wizard into the appropriate files. So, to do that, it looked something like:

root@cloya-desktop:/etc/asterisk# mkdir backup

root@cloya-desktop:/etc/asterisk# cp sip.conf backup/

root@cloya-desktop:/etc/asterisk# cp extensions.conf backup/

root@cloya-desktop:/etc/asterisk# cp voicemail.conf backup/

root@cloya-desktop:/etc/asterisk# rm sip.conf

root@cloya-desktop:/etc/asterisk# nano sip.conf

root@cloya-desktop:/etc/asterisk# rm voicemail.conf

root@cloya-desktop:/etc/asterisk# nano voicemail.conf

root@cloya-desktop:/etc/asterisk# rm extensions.conf

root@cloya-desktop:/etc/asterisk# nano extensions.conf

root@cloya-desktop:/etc/asterisk# cat sip.conf

[digiassn]

type=friend

host=dynamic

context=home

secret=secretPassword

mailbox=digiassn

dtmfmode=rfc2833

disallow=all

allow=ulaw

[pstn]

; If you're using Asterisk, this goes into the Incoming settings

; For your Trunk

type=friend

host=dynamic

; If using Asterisk@home, change the below line to context=from-internal

context=home

secret= secretPassword

dtmfmode=rfc2833

disallow=all

allow=ulaw

insecure=very

[pstn-spa3k]

; If you're using Asterisk, this section goes into the Outgoing Settings

; for your trunk.

type=peer

auth=md5

host=192.168.1.110

port=5061

secret= secretPassword

username=asterisk

fromuser=asterisk

dtmfmode=rfc2833

; If using Asterisk@home, change the below line to context=from-internal

context=home

insecure=very

root@cloya-desktop:/etc/asterisk# cat voicemail.conf

[default]

digiassn => digiassn,John Ward,user.com,user-pager.com,tz=pacific

root@cloya-desktop:/etc/asterisk# cat extensions.conf

[home]

exten => digiassn,1,Ringing

exten => digiassn,2,Dial(SIP/digiassn,20,T)

exten => digiassn,3,Voicemail(udigiassn)

exten => digiassn,4,Hangup

exten => 911,1,Dial(SIP/911@pstn-spa3k,60,)

exten => 911,2,Congestion

exten => _XXXXXXX,1,Dial(SIP/${EXTEN}@pstn-spa3k,60,)

exten => _XXXXXXX,2,Congestion

exten => _1800XXXXXXX,1,Dial(SIP/${EXTEN}@pstn-spa3k,60,)

exten => _1800XXXXXXX,2,Congestion

exten => _1888XXXXXXX,1,Dial(SIP/${EXTEN}@pstn-spa3k,60,)

exten => _1888XXXXXXX,2,Congestion

exten => _1877XXXXXXX,1,Dial(SIP/${EXTEN}@pstn-spa3k,60,)

exten => _1877XXXXXXX,2,Congestion

exten => _1866XXXXXXX,1,Dial(SIP/${EXTEN}@pstn-spa3k,60,)

exten => _1866XXXXXXX,2,Congestion

Then, I need to edit the /etc/default/asterisk file to change the line that says

RUNASTERISK=no

to say

RUNASTERISK=yes

Now, before I actually start this up, I needed to make one final change. When I actually started this up and played with it, the dial in from my land line did not ring the VOIP setup on my Droid the way I wanted. The reason is the extension.conf file was not set up correctly from the script. The way it works by default is that any calls coming in the digiassn extension would ring the digiassn extension for 20 seconds then go to voice mail. This is not what I want. I want calls coming in the pstn extension to ring the pstn extension for 20 seconds (which would be the physical home phone line), then ring my VOIP setup on my cell (digiassn) for 10 seconds, then go to voicemail. Most normal configurations won’t require this, but I included it here to show my final configuration. First, go into the SPA configuration utility, and under Voice/Line 1/Proxy and Registration, change the value of Use Outbound Proxy to true. I don’t know why, but the handset wouldn’t ring without this set. Then change the below configuration for extensions.conf:

[home]

exten => pstn,1,Ringing

exten => pstn,2,Dial(SIP/digiassn,20,T) #ring the handset first

exten => pstn,3,Dial(SIP/pstn,15,T) #then ring the SIPDroid

exten => pstn,4,Voicemail(udigiassn)

exten => pstn,5,Hangup

exten => 911,1,Dial(SIP/911@pstn-spa3k,60,)

exten => 911,2,Congestion

exten => _XXXXXXX,1,Dial(SIP/${EXTEN}@pstn-spa3k,60,)

exten => _XXXXXXX,2,Congestion

exten => _1800XXXXXXX,1,Dial(SIP/${EXTEN}@pstn-spa3k,60,)

exten => _1800XXXXXXX,2,Congestion

exten => _1888XXXXXXX,1,Dial(SIP/${EXTEN}@pstn-spa3k,60,)

exten => _1888XXXXXXX,2,Congestion

exten => _1877XXXXXXX,1,Dial(SIP/${EXTEN}@pstn-spa3k,60,)

exten => _1877XXXXXXX,2,Congestion

exten => _1866XXXXXXX,1,Dial(SIP/${EXTEN}@pstn-spa3k,60,)

exten => _1866XXXXXXX,2,Congestion

Now, I can start up Asterisk by running /etc/init.d/asterisk restart.

Now, I need a VOIP client. I am using SIPDroid to make my connections. To do this, I configure SIPDroid as follows:

Under SIP Account Settings:

Authorization Username: pstn

Password:

Server: 192.168.1.111 (The address of the Asterix box).

Port: 5060

Protocol: UDP

Everything else I leave default. That’s it. When I’m connected to my WiFi network, I can use the VoIP setup to connect directly to my landline.

So, after using this for a day, there were some definite things I wanted to change. The dial plan that is on by default sucked. Since I am using Android and SIPVoice to dial, and by default SIPDroid uses the full number mask stored in contacts (XXX-XXX-XXXX), Asterisk refused to dial. I would see SIPDroid try to dial but hang up immediately without completing the call. Took me a while to figure out what was going on, so some new dial masks needed to be created. Voicemail was not set up correctly. Since I don’t have an answering machine on my landline, I figured Asterisk can play double duty and serve as an answering machine as well. The wizard doesn’t create a workable voicemail password, so that needed to be fixed. Also, after some investigation, it turns out that Asterisk also has a little feature that works just like the Telezapper, and will play the “out of service” tone when you answer a phone so telemarketers and such will register you in the Do Not Call database. This is a feature that I need to have since the National Do Not Call database is such a joke. There are also all sorts of neat scripts you can run to forward telemarketers to annoying endless voice prompt loops, or just hang up on them, but I won’t cover them here.

So, to accomplish what I wanted, I modified all three configuration files like so.

Voicemail.conf:

[default]

digiassn => 1234,John Ward,john@email,tz=pacific

Note the 1234. This is the 4 digit numeric password you need to enter to check and manage your voicemailbox.

Extensions.conf:

[home]

exten => pstn,1,Ringing

#add zapateller

exten => pstn,2,Zapateller(answer)

exten => pstn,3,Dial(SIP/digiassn,15,T)

exten => pstn,4,Dial(SIP/pstn,10,T)

exten => pstn,5,Voicemail(udigiassn)

exten => pstn,6,Hangup

exten => 911,1,Dial(SIP/911@pstn-spa3k,60,)

exten => 911,2,Congestion

#dialing 9999 will get me my voicemail box

exten => 9999,1,VoiceMailMain(digiassn)

#dialmasks, local calls

exten => _XXXXXXX,1,Dial(SIP/${EXTEN}@pstn-spa3k,60,)

exten => _XXXXXXX,2,Congestion

#if coming from cell phone, only take the phone number, minus the 1 and the area code

exten => _1210XXXXXXX,1,Dial(SIP/${EXTEN:-7}@pstn-spa3k,60,)

exten => _1210XXXXXXX,2,Congestion

#same as above, only without the 1. this is for local calls

exten => _210XXXXXXX,1,Dial(SIP/${EXTEN:-7}@pstn-spa3k,60,)

exten => _210XXXXXXX,2,Congestion

#Any other number, with the 1

exten => _1XXXXXXXXXX,1,Dial(SIP/${EXTEN}@pstn-spa3k,60,)

exten => _1XXXXXXXXXX,2,Congestion

#without the 1

exten => _XXXXXXXXXX,1,Dial(SIP/1${EXTEN}@pstn-spa3k,60,)

exten => _XXXXXXXXXX,2,Congestion

#dont believe the rest need to be here, but I will leave them jic

exten => _1800XXXXXXX,1,Dial(SIP/${EXTEN}@pstn-spa3k,60,)

exten => _1800XXXXXXX,2,Congestion

exten => _1888XXXXXXX,1,Dial(SIP/${EXTEN}@pstn-spa3k,60,)

exten => _1888XXXXXXX,2,Congestion

exten => _1877XXXXXXX,1,Dial(SIP/${EXTEN}@pstn-spa3k,60,)

exten => _1877XXXXXXX,2,Congestion

exten => _1866XXXXXXX,1,Dial(SIP/${EXTEN}@pstn-spa3k,60,)

exten => _1866XXXXXXX,2,Congestion

Wednesday, January 27, 2010

BIRT: Get Access to Chart Element and Modify Properties from ReportRunnable in BIRT 2.5

Helping someone out from the forums on BIRT Exchange. The question was how can you get access to a chart in a ReportRunnable object, modify its properties, and run the report with the modified properties. While I have given pieces of how to do that here and here, I have never put them together in a single example. Below is an example of how to do this.

package com.digiassn.blogspot.birt;

import java.util.logging.Level;

import org.eclipse.birt.chart.model.ChartWithoutAxes;
import org.eclipse.birt.chart.model.attribute.ChartDimension;
import org.eclipse.birt.core.exception.BirtException;
import org.eclipse.birt.core.framework.Platform;
import org.eclipse.birt.report.engine.api.EngineConfig;
import org.eclipse.birt.report.engine.api.EngineException;
import org.eclipse.birt.report.engine.api.HTMLRenderOption;
import org.eclipse.birt.report.engine.api.IReportEngine;
import org.eclipse.birt.report.engine.api.IReportEngineFactory;
import org.eclipse.birt.report.engine.api.IReportRunnable;
import org.eclipse.birt.report.engine.api.IRunAndRenderTask;
import org.eclipse.birt.report.model.api.ExtendedItemHandle;
import org.eclipse.birt.report.model.api.extension.ExtendedElementException;

public class ModifyChart {

/**
* @param args
*/
public static void main(String[] args) {
try {
IReportEngine engine = null;
EngineConfig config = null;

// Configure the Engine and start the Platform
config = new EngineConfig();
config
.setEngineHome("C:/Libraries/birt-runtime-2_5_1/ReportEngine");
// set log config using ( null, Level ) if you do not want a log file
config.setLogConfig("C:/temp", Level.FINE);

//start birt platform and create factories
Platform.startup(config);
IReportEngineFactory factory = (IReportEngineFactory) Platform
.createFactoryObject(IReportEngineFactory.EXTENSION_REPORT_ENGINE_FACTORY);
engine = factory.createReportEngine(config);
engine.changeLogLevel(Level.WARNING);

//open report design
IReportRunnable design = engine
.openReportDesign("C:/contracts/BirtExamples/BirtReportEngine/PieChart.rptdesign");

//get chart element handle called "PieChart"
ExtendedItemHandle eih = (ExtendedItemHandle) design.getDesignHandle()
.getDesignHandle().findElement("PieChart");

//get the actual chart instance since Charts are extended item handles
ChartWithoutAxes cwa = (ChartWithoutAxes) eih.getReportItem().getProperty(
"chart.instance");

//set title of chart to New Label
cwa.getTitle().getLabel().getCaption().setValue("New Label");

//set 2d with depth
cwa.setDimension(ChartDimension.TWO_DIMENSIONAL_WITH_DEPTH_LITERAL);

// Create task to run and render the report,
IRunAndRenderTask task = engine.createRunAndRenderTask(design);

// Set rendering options - such as file or stream output,
// output format, whether it is embeddable, etc
HTMLRenderOption options = new HTMLRenderOption();
options.setBaseURL("http://localhost/");
options.setBaseImageURL("http://localhost/myimages");
options.setImageDirectory("C:/xampplite/htdocs/myimages");
options.setSupportedImageFormats("JPG;PNG;BMP;SVG");

options.setOutputStream(System.out);

// Set output format
options.setOutputFormat("html");
task.setRenderOption(options);

// run the report and destroy the engine
// Note - If the program stays resident do not shutdown the Platform or
// the Engine
task.run();
task.close();

task.close();
Platform.shutdown();
System.out.println("Finished");
} catch (ExtendedElementException e) {
e.printStackTrace();
} catch (EngineException e) {
e.printStackTrace();
} catch (BirtException e) {
e.printStackTrace();
}

}

}


The thing to remember about charts in BIRT reports is that they are Chart types stored withing a ExtendedItemHandler. So you need to find the ExtendedItemHandler first, then get the chart inside of it. Charts can be ChartsWithAxis (bar charts, lines charts), or ChartsWithoutAxis (pie charts). Reference on the chart types can be found here.

ChartWithAxes
ChartWithoutAxes

Musing: Mobile Technology

One of the things that is always on my mind is how can I keep myself mobile, without the need to carry around a laptop. For a few years I have kept it in the back of my mind that my smartphone would be perfect for this, however previous models didn't quite do everything that I needed. I can say, this is no longer the case with the Droid.

I am writing this sitting in a Chipotle and using my foldout keyboard on my Motorola Droid. I am using the wireless tether that I hacked previously to connect my iPod Touch online so I can play Scrabble (until there is a native Droid version that is). I am using the GDocs application to write this (although I have a few other text editors that save locally instead of "in the cloud"). Using the Droid Meebo app, I can stay connected to coworkers via IM. Since the Droid multitasks, I can have the IM, email, tether app, and a few other things running simultaneously. The only thing I lack here is VOIP via WiFi, which I suspect will be simplified enough soon enough. I think my next tasks here are to try to run a modified BIRT Designer. Then I can do some rudimentary troubleshooting on BIRT reports when not at my desk.

I couldn't do all this 5 years ago on the Razr, or last year with the Touch/Vogue. The difference between mobile and desktop is closing. I wonder how businesses deal with the security issues with this new found mobility?

Monday, January 25, 2010

Droid: WiFi Tethering/Hotspot on the Droid

Since the announcement of the Pre+ for Verizon would have WiFi hotspot built in, I have been salivating for the wireless hotspot functionality. Of course, I kicked myself because I just bought a Droid. Well, I can hold off my wanting because some clever hackers figured out how to do the same thing with the Droid. That’s right, the Droid is capable of being a WiFi hotspot.

So how is this feat accomplished?

That’s it. Pretty easy. Took me about 20 minutes to do. Although not indicated in the article because it assumes prior understanding, the “ADB” application refered to requires the Android SDK, and is a tool located under the “tools” folder. Also, the step to “flash_image” was actually not needed since this is part of the Android Root Helper application. Also, during the WirelessTetherPather programs final stages, it asks you to “login, and run the tether app”. This actually refers to running the “Wireless tether for Root users” application under your applications menu on the Droid, not running it using Busybox using ADB. That step confused me for some reason.

If your having problems finding the “Droid Root Helper” application, you can use the one I found here. Apparently, it is also in the Marketplace.

That’s it, the last little void from my HTC Touch has been filled. Seriously, how could Verizon NOT want this? This is just so freaking awesome, it should be a standard feature.

Monday, January 18, 2010

Getting HP Foldable Bluetooth Keyboard FA287A Working on Motorola Droid

I’ve had an old Bluetooth keyboard I used to use with my HP Ipaq. It is a model number FA287A. I’ve always had a fondness for this keyboard and using it with my mobile devices. It has a number pad on the top, and it has a nice feel to the keys. I managed to get this keyboard working on my HTC Touch Vogue with some help from this driver.

I am happy to discover that this keyboard, which has served me well for years, lives on with my Motorola Droid. That’s right, this oddball keyboard that was designed specifically for the HP Ipaq, works with my Android based mobile phone. How is this possible? Thanks to a little application called KeyPro available in the Android Marketplace, and at http://www.mymobilegear.com/AndroidKBDriver.php (note, this site was down at the time of this writing, the URL comes from Google).

To get this working, I used the following steps.

  • Installed KeyPro from the Marketplace.
  • Opened up Droids settings app.
  • Went into Language and Keyboard, and clicked on the check next to KeyPro.
  • Clicked Back.
  • Clicked on Wireless and Networks.
  • Turned on Bluetooth.
  • Went into Bluetooth Settings
  • Clicked on Scan for Devices, it found “BT-FoldableKB”
  • Paired with it, and put in Passcode “0000”
  • Pushed the Home button
  • Opened the apps menu, started KeyPro
  • Opened the Settings menu.
  • Changed the Keyboard Model to “Freedom Universal”
  • Clicked on the Scan next to Keyboard Address textbox.
  • It found the “BT-FoldableKB”.
  • Scrolled down and clicked on Save.

Keypro then showed status at bottom of app saying “initialized”, then “connecting”, then “connected”. With it connected, I clicked on the Search button. Nothing happened. So I held my finger up to the search text box for a second, and a dialog poped up for Input Method. I clicked on Input Method, and selected KeyPro. And guess what. Now what I typed showed up. I can use my Bluetooth keyboard on my Android. This works out great when I want to take notes in a meeting and I don’t want to bring my laptop with me, and another reason to leave my IPod Touch at home.