tag:blogger.com,1999:blog-10102212927296587422024-03-12T21:31:02.149-07:00Free Range Code MonkeyExpert Plain And Fancy Bit Twiddlingguycolehttp://www.blogger.com/profile/13546414963444312679noreply@blogger.comBlogger29125tag:blogger.com,1999:blog-1010221292729658742.post-29959739082545917742017-05-21T20:37:00.001-07:002017-05-21T20:37:49.985-07:00Android/BeagleBone interaction via Bluetooth RFCOMMIn this posting I will demonstrate how to connect between an Android phone and a <a href="https://beagleboard.org/black-wireless" target="_blank">BeagleBone Black Wireless</a> (BBBW) using bluetooth RFCOMM (basically a wireless RS-232 link).<br />
<br />
For this demonstration I have created an Android application which<br />
<ol>
<li>discovers bluetooth devices</li>
<li>connects to a bluetooth device</li>
<li>toggles LED connected to bluetooth device</li>
</ol>
The BBBW hosts a python application which accepts a connection request and manages three LED which are remotely controlled from the Android application.<br />
<h2>
BBBW Preparation</h2>
<ol>
<li>Flash your BBBW w/the <a href="https://beagleboard.org/latest-images" target="_blank">latest image</a>, currently <b><span style="font-family: "times" , "times new roman" , serif;">bone-debian-8.7-iot-armhf-2017-03-19-4gb.img </span></b></li>
<li><span style="font-family: "courier new" , "courier" , monospace;">apt-get update; apt-get upgrade</span></li>
<li><span style="font-family: "courier new" , "courier" , monospace;">apt-get install python-bluez</span></li>
<li>Pull the python sources from <a href="https://github.com/guycole/perky-blue-bb" target="_blank">github</a></li>
<li>Add green/red/yellow LED to BBGW. You can changes the port assignments in perky_blue.py <table>
<tbody>
<tr><th>LED</th><th>GPIO</th></tr>
<tr><td>green</td><td>48</td></tr>
<tr><td>red</td><td>49</td></tr>
<tr><td>yellow</td><td>60</td></tr>
</tbody></table>
</li>
<li>As root, make BBBW discoverable for bluetooth by invoking bluetoothctl(1)</li>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://1.bp.blogspot.com/-mOOqVfu4_Lk/WSJU_CGuBmI/AAAAAAAAHkA/AwNXdPWDpnMi-nrFHnCokMUGz_sBILNbwCLcB/s1600/Screen%2BShot%2B2017-05-21%2Bat%2B8.01.57%2BPM.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="104" src="https://1.bp.blogspot.com/-mOOqVfu4_Lk/WSJU_CGuBmI/AAAAAAAAHkA/AwNXdPWDpnMi-nrFHnCokMUGz_sBILNbwCLcB/s320/Screen%2BShot%2B2017-05-21%2Bat%2B8.01.57%2BPM.png" width="320" /></a></div>
<li> You might see an error like the screenshot below:</li>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://3.bp.blogspot.com/-cHRdee9PCEg/WSJWGwK84-I/AAAAAAAAHkI/eVqYYhbHq-gbqWshBidg0KF9804ZtTl3ACLcB/s1600/Screen%2BShot%2B2017-05-21%2Bat%2B4.27.23%2BPM.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="61" src="https://3.bp.blogspot.com/-cHRdee9PCEg/WSJWGwK84-I/AAAAAAAAHkI/eVqYYhbHq-gbqWshBidg0KF9804ZtTl3ACLcB/s320/Screen%2BShot%2B2017-05-21%2Bat%2B4.27.23%2BPM.png" width="320" /></a></div>
If so, you need to tweak /etc/systemd/system/dbus-org.bluez.service.
Change this line: <code></code><code>ExecStart=/usr/lib/bluetooth/bluetoothd</code>
to
<code>ExecStart=/usr/lib/bluetooth/bluetoothd -C</code>
<code>Save the file and reboot. Start again at item 6.</code>
<li>BBBW should now be ready for Android commands.</li>
</ol>
<h2>
Android Preparation</h2>
<ol>
<li>Pull the source from <a href="https://github.com/guycole/perky-blue-android" target="_blank">github </a></li>
<li>Compile using Android Studio and deploy to phone.</li>
<li>Ensure bluetooth is enabled on your phone </li>
<li>Start the application ("PerkyBlue")</li>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://4.bp.blogspot.com/-Jz8um4URCsg/WSJa0198d2I/AAAAAAAAHkY/cXaEFsz4Xbw3cRtj6mj3sT0Z7UGrMxRGgCLcB/s1600/Screenshot_20170519-122832.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="320" src="https://4.bp.blogspot.com/-Jz8um4URCsg/WSJa0198d2I/AAAAAAAAHkY/cXaEFsz4Xbw3cRtj6mj3sT0Z7UGrMxRGgCLcB/s320/Screenshot_20170519-122832.png" width="180" /></a></div>
<li>Press "Start Discovery" and wait ~20 seconds for completion.<div class="separator" style="clear: both; text-align: center;">
<a href="https://4.bp.blogspot.com/-KNTVVcWjJPA/WSJa2I4CpOI/AAAAAAAAHks/mDonBO3nZVE8fk0cKDSx5wcWmBcpVn1nwCEw/s1600/Screenshot_20170519-123148.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="320" src="https://4.bp.blogspot.com/-KNTVVcWjJPA/WSJa2I4CpOI/AAAAAAAAHks/mDonBO3nZVE8fk0cKDSx5wcWmBcpVn1nwCEw/s320/Screenshot_20170519-123148.png" width="180" /></a></div>
</li>
<li>Usually the host name is "beaglebone" (in this case it is "porkchop"). Press on the host to connect. When connection succeeds you will see both the Android app and the python app update.<div class="separator" style="clear: both; text-align: center;">
<a href="https://2.bp.blogspot.com/-sXcPnyedZgk/WSJa3yNoFaI/AAAAAAAAHks/MmR5FNjqBxsoFZWcTqId9v_pEfI6RqrPwCEw/s1600/Screenshot_20170519-125157.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="320" src="https://2.bp.blogspot.com/-sXcPnyedZgk/WSJa3yNoFaI/AAAAAAAAHks/MmR5FNjqBxsoFZWcTqId9v_pEfI6RqrPwCEw/s320/Screenshot_20170519-125157.png" width="180" /></a></div>
</li>
<li>You can now press for red/yellow/green LED toggle, the corresponding LED should light on BeagleBone.</li>
</ol>
guycolehttp://www.blogger.com/profile/13546414963444312679noreply@blogger.com0tag:blogger.com,1999:blog-1010221292729658742.post-8595560767419754372017-01-24T14:26:00.001-08:002017-01-24T19:17:33.471-08:00BeagleBone Green Wireless IoT Developer Prototyping KitHave you noticed that <a href="https://cloud.google.com/" target="_blank">Google Cloud</a> is promoting an <a href="https://cloud.google.com/solutions/iot/kit/" target="_blank">IoT Developer Prototyping Kit</a> which features the <a href="https://beagleboard.org/green-wireless" target="_blank">BeagleBone Green Wireless</a> (BBGW)? I purchased one, because I was hoping for better instructions on using the <a href="http://wiki.seeed.cc/Grove_System/" target="_blank">Grove System</a> w/BBGW.<br />
<div>
<br /></div>
<div>
Sadly, the only documentation included w/the proto kit is a lame brochure w/a <a href="https://cloud.google.com/solutions/iot/" target="_blank">cloud solutions</a> URL with unhelpful <a href="https://www.arduino.cc/" target="_blank">Arduino</a> examples. Yaay for Arduino, but I bought the BBGW kit.<br />
<br />
Fine. Challenge accepted. Here are some notes on using BBGW and Grove System.<br />
<br class="Apple-interchange-newline" />
There are dedicated images for the BBGW and any Debian reference (within this post) is tied to <a href="https://beagleboard.org/latest-images" target="_blank">bone-debian-8.6-seeed-iot-armhf-2016-11-06-4gb.img</a></div>
<div>
<br /></div>
<div>
<a href="http://wiki.seeed.cc/Grove_System/">"Grove is a modular, standardized connector prototyping system."</a> which is a good single line summary. The catalog is full of many sensors, switches and shiny, blinky things which plug into standard connectors. The BBGW exposes two Grove connectors, one for I2C and the other to UART. Two connections are OK to start, but you most likely will want the <a href="https://www.seeedstudio.com/Grove-Base-Cape-for-Beaglebone-v2.0-p-2644.html">Grove Base Cape</a> (included in proto kit) because this offers more connections and access to the ADC.<br />
<br />
If you already know the BB, you will not be surprised to learn that the Grove connectors map directly to P8/P9 and there is no added functionality apart from the connectors. Put another way, anything you can implement w/Grove could also be implemented the usual way via overlays and P8/P9.<br />
<br />
There has to be software to control the interfaces and BBGW Grove promotes <a href="https://github.com/intel-iot-devkit/mraa">MRAA</a> as a wrapper to the BBGW devices. MRAA comes w/the Debian Seeed image and has (yet another) pin encoding scheme. Look <a href="http://www.seeed.cc/project_detail.html?id=1592">here</a> for pin mapping. The Debian Seeed image also has example python code in
<code>/usr/share/mraa/examples/python</code>
<br />
<br />
Start easy w/a GPIO demo "blink-io8.py"<br />
<code><br /></code>
<code>
import mraa <br />
import time <br /><br />
</code><br />
<code># Using BBG GPIO_51<br />
x = mraa.Gpio(62)<br />
x.dir(mraa.DIR_OUT)<br />
<br />
while True:<br /> x.write(1)<br /> time.sleep(0.2)<br /> x.write(0)<br /> time.sleep(0.2)<br />
</code>
<br />
<br />
Note the "mraa.Gpio(62)" which <a href="http://www.seeed.cc/project_detail.html?id=1592">maps</a> to P9_16 on BBGW and has a dedicated socket on the <a href="https://www.seeedstudio.com/Grove-Base-Cape-for-Beaglebone-v2.0-p-2644.html">Grove Base Cape</a> (look at the middle row, the GPIO are silk screened next to the Grove sockets). <br />
<br />
Use the <a href="http://wiki.seeed.cc/Grove-3-Axis_Digital_Accelerometer-16g/">3 axis accelerometer</a> from the proto kit as an I2C example. One of the <a href="http://www.seeed.cc/BBGW-starter-tutorial%231-The-breath-LED-p-1641.html">Seeed example</a> worked, scroll to item "03 How to use Grove - 3-Axis digital Accelerometer (16g)" for a python example.<br />
<br />
Now for an ADC example, look at this <a href="http://www.seeed.cc/BBGW-starter-tutorial%234%3AHow-hot-is-it-today%3F-Ask-BBGW!-p-1645.html">Seeed project</a> (scroll to "02 How to use Grove - Light Sensor & Temperature Sensor"). The wiring diagram is OK (i.e light sensor to AIN0 and temperature to AIN2) but the code is not quite working. Here is the corrected code:<br />
<code>
import time<br />
import pyupm_grove as grove<br />
<br />
light = grove.GroveLight(1)<br />
temp = grove.GroveTemp(3)<br />
<br />
while True:<br />
print light.name() + " raw value is %d" % light.raw_value() + ", which is roughly %d" % light.value() + " lux"<br />
celsius = temp.value()<br />
fahrenheit = celsius * 9.0/5.0 + 32.0<br />
print "%d degrees Celsius, or %d degrees Fahrenheit" % (celsius, fahrenheit)<br />
time.sleep(2)</code></div>
<br />
What about those two Grove connectors on the BBGW? One is for UART, the other is I2C, both support GPIO. Here is an example Python script which uses the UART connector w/a button:<br />
<code>
import mraa<br />
import time<br />
<br />
x = mraa.Gpio(68)<br />
x.dir(mraa.DIR_IN)<br />
<br />
while True:<br />
time.sleep(1)<br />
if x.read() > 0:<br />
print 'button press'<br />
else:<br />
print 'button not press'<br />
</code>
<br />
<br />
<style type="text/css">
p.p1 {margin: 0.0px 0.0px 0.0px 0.0px; font: 12.0px Courier; color: #4c2f2d; background-color: #dfdbc4}
span.s1 {font-variant-ligatures: no-common-ligatures}
</style>guycolehttp://www.blogger.com/profile/13546414963444312679noreply@blogger.com0tag:blogger.com,1999:blog-1010221292729658742.post-91465590317175269152017-01-24T13:26:00.002-08:002017-01-24T13:53:36.258-08:00BeagleBone Black vs BeagleBone GreenYet another post comparing the <a href="https://beagleboard.org/green-wireless" target="_blank">BeagleBone Green Wireless</a> (BBGW) to the <a href="https://beagleboard.org/black" target="_blank">BeagleBone Black</a>.<br />
<br />
<a href="http://www.mouser.com/new/seeedstudio/BeagleBone-black-vs-green/" target="_blank">Mouser</a> has a great (hardware) comparison.<br />
<br />
<div>
The links on the BBGW documentation pamphlet are mostly wrong, but you can find the BBGW wiki <a href="http://wiki.seeed.cc/SeeedStudio_BeagleBone_Green_Wireless/" target="_blank">here</a> (worth a visit).</div>
<div>
<br />
Brief recap of differences between the BBB and BBGW hardware: HDMI is gone along w/the 5V barrel jack. USB connector has gone from mini to micro, and if you need 5V it must be injected via the P9 header. The RJ45 (ethernet) connector has been removed, put there are now bluetooth and WiFi radios. <span style="background-color: yellow;">There are now 4 USB ports which are tall and will interfere w/most capes. </span> </div>
<div>
<br /></div>
<div>
There are dedicated images for the BBGW and any Debian reference (within this post) is tied to <a href="https://beagleboard.org/latest-images" target="_blank">bone-debian-8.6-seeed-iot-armhf-2016-11-06-4gb.img</a></div>
<div>
<br /></div>
<div>
The BBGW I2C bus maps i2c-0 and i2c-2 while BBB maps i2c-0 and i2c-1. Expect this to be an issue when migrating applications from BBB to BBGW.<br />
<br />
BBGW $SLOTS is at /sys/devices/platform/bone_capemgr/slots.<br />
<div class="p1">
<code>
root@beaglebone:~# cat $SLOTS<br />
0: PF---- -1<br />
1: PF---- -1<br />
2: PF---- -1<br />
3: PF---- -1<br />
</code>
<br />
<style type="text/css">
p.p1 {margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo; background-color: #fef49c}
span.s1 {font-variant-ligatures: no-common-ligatures}
</style>
<br />
<br /></div>
<style type="text/css">
p.p1 {margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo; background-color: #fef49c}
span.s1 {font-variant-ligatures: no-common-ligatures}
</style></div>
guycolehttp://www.blogger.com/profile/13546414963444312679noreply@blogger.com0tag:blogger.com,1999:blog-1010221292729658742.post-62382877990742454492017-01-15T17:01:00.001-08:002017-01-15T17:09:24.723-08:00BeagleBone Green Wireless as a LAMP ServerThis post demonstrates how to configure a <a href="http://wiki.seeed.cc/SeeedStudio_BeagleBone_Green_Wireless/" target="_blank">BeagleBone Green Wireless</a> (BBGW) first for WiFi tethering and then as a LAMP server. For context, I have an IoT project (not described here) which uses the BBGW for data collection which can be examined using a web browser.<br />
<br />
Flash your BBGW w/the <a href="https://beagleboard.org/latest-images" target="_blank">latest image</a>. I am using "Jessie for SeeedStudio BeagleBone GreenWireless" (bone-debian-8.6-seeed-iot-armhf-2016-11-06-4gb.img). <br />
<br />
After updating the BBGW image, log in to configure WiFi using connmanctl(1), there are example instructions in /etc/network/interfaces.<br />
<br />
Now that you have internet connectivity, update the software using apt-get(8):<br />
<ul>
<li>"apt-get update"</li>
<li>"apt-get upgrade"</li>
</ul>
<div>
Perform a gratuitous reboot for luck.</div>
<div>
<br /></div>
<div>
When the BBGW returns from reboot, you should detect a fresh WiFi SSID in the form "BeagleBoneXXXXXX" where XXXXXX are integers. This SSID was created by wifidog which is part of the BBGW Debian distribution. </div>
<div>
<br /></div>
<div>
I don't need a captive portal for my purposes, so login to BBGW and invoke "apt-get remove wifidog-gateway" then reboot.</div>
<div>
<br /></div>
<div>
Now when the BBGW returns from reboot, you should detect a fresh WiFi SSID in the form "BeagleBone-XXXX" where XXXX are hex values representing part of the MAC address.</div>
<div>
<br /></div>
<div>
/etc/default/bb-wl18xx contains some tweakable parameters, such as SSID base.</div>
<div>
<br /></div>
<div>
/tmp/hostapd-wl18xx.conf is the actual hostapd(8) configuration file, note the wpa_passphrase "BeagleBone"</div>
<style type="text/css">
p.p1 {margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo; background-color: #fef49c}
span.s1 {font-variant-ligatures: no-common-ligatures}
</style>
<!--?xml version="1.0" encoding="UTF-8" standalone="no"?-->
<br />
<style type="text/css">
p.p1 {margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo; background-color: #fef49c}
span.s1 {font-variant-ligatures: no-common-ligatures}
</style>
<br />
SoftAp0 is the WAP device:<br />
<div class="p1">
<span class="s1">root@beaglebone:/etc/default# ifconfig SoftAp0</span></div>
<div class="p1">
<span class="s1">SoftAp0 Link encap:Ethernet HWaddr b0:d5:cc:ff:65:be </span></div>
<div class="p1">
<span class="s1"> inet addr:192.168.8.1 Bcast:192.168.8.255 Mask:255.255.255.0</span></div>
<div class="p1">
<span class="s1"> inet6 addr: fe80::b2d5:ccff:feff:65be/64 Scope:Link</span></div>
<div class="p1">
<span class="s1"> UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1</span></div>
<div class="p1">
<span class="s1"> RX packets:5220 errors:0 dropped:3 overruns:0 frame:0</span></div>
<div class="p1">
<span class="s1"> TX packets:703 errors:0 dropped:0 overruns:0 carrier:0</span></div>
<div class="p1">
<span class="s1"> collisions:0 txqueuelen:1000 </span></div>
<style type="text/css">
p.p1 {margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo; background-color: #fef49c}
span.s1 {font-variant-ligatures: no-common-ligatures}
</style>
<br />
<div class="p1">
<span class="s1"> RX bytes:1328274 (1.2 MiB) TX bytes:122059 (119.1 KiB)</span></div>
<br />
From your laptop, connect to the BeagleBone device just as you would any other WAP. <br />
<br />
Apache is configured for port 8080. Verify you can connect to apache2(8) by visiting http://192.168.8.1:8080/ with your browser.<br />
<br />
Assuming happy browser response, you now have a BBGW ready for a LAMP stack. Note that the BBGW still has internet connectivity through wlan0 as configured earlier. <br />
<br />
Now install mysqld(8) by invoking "apt-get install mysql-server" - when finished, verify a happy installation using mysql(1) and ensure you can at least login to mysqld(8).<br />
<br />
Now install PHP, et al by invoking "apt-get install php5 libapache2-mod-php5 php5-mysql" - when finished, verify a happy installation by placing the usual phpinfo script into /var/www/html and visiting w/a browser.guycolehttp://www.blogger.com/profile/13546414963444312679noreply@blogger.com1tag:blogger.com,1999:blog-1010221292729658742.post-88623666641163709422016-12-28T16:33:00.000-08:002016-12-28T16:48:41.774-08:00Temperature Sensing w/BeagleBone Black and Adafruit PT100 RTD<span style="background-color: white; color: #333333; font-family: "georgia" , "times new roman" , serif;">Here is a simple example of collecting temperature w/<a href="https://beagleboard.org/black" target="_blank">BeagleBone Black</a> (BBB) and the <a href="https://www.adafruit.com/products/3290" target="_blank">Adafruit PT100 RTD</a> temperature sensor. The PT100 sensor resistance varies directly w/temperature. I can measure voltage drop across the PT100 sensor using an analog to digital converter (ADC) on the BBB and discover the temperature.</span><br />
<span style="font-family: "georgia" , "times new roman" , serif;"><span style="background-color: white; color: #333333;"><br /></span>
<span style="background-color: white; color: #333333;">The BBB offers eight 12 bit ADC inputs. ADC values range from 0 to 4096 (2^12). Reference voltage is 1.8VDC. Schematic below indicates Vref is on P9/pin 32, and the ADC input is P9/pin 39. ADC ground (P9/pin 34) is tied to P9/pin 1 ground. </span></span><br />
<span style="font-family: "georgia" , "times new roman" , serif;"><span style="background-color: white; color: #333333;"><br /></span>
<span style="color: #333333; font-family: "georgia" , serif;"><span style="background-color: white;">My use case ranges from 0C to an upper bound of 400C. The temperature sensor offers a resistance of 100 ohms at 0C and then .385 ohm per degree C or (in this case) a maximum resistance of 100 + 400 * 0.385 = 254 ohms.</span></span></span><br />
<span style="font-family: "georgia" , "times new roman" , serif;"><span style="color: #333333; font-family: "georgia" , serif;"><span style="background-color: white;"><br /></span></span>
<span style="color: #333333; font-family: "georgia" , serif;"><span style="background-color: white;">Given that Vref = 1.8 VDC and Rmin = 100 ohms, the current at minimum resistance is 18mA (this is a problem). To mitigate loading, I added a LM358 op-amp as a voltage follower. Put another way, simply reading the PT100 voltage drop might damage the BBB so I decide for additional circuitry as insurance. </span></span></span><br />
<span style="font-family: "georgia" , "times new roman" , serif;"><span style="color: #333333; font-family: "georgia" , serif;"><span style="background-color: white;"><br /></span></span>
<span style="color: #333333; font-family: "georgia" , serif;"><span style="background-color: white;">I want to use the temperature sensor as half of a voltage divider. What value for the other half? Old school teaches that R = sqrt(Rmin * Rmax) = sqrt(100 * 254) = 160 ohms. Amazingly, I had a 160 ohm resistor available.</span></span></span><br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://2.bp.blogspot.com/-sYH7KGr6MpU/WGRWwm7lrfI/AAAAAAAAGG4/guFTc21GPK8KGq4zSDtRQopyYUL8Wm2MQCLcB/s1600/temperature.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" height="225" src="https://2.bp.blogspot.com/-sYH7KGr6MpU/WGRWwm7lrfI/AAAAAAAAGG4/guFTc21GPK8KGq4zSDtRQopyYUL8Wm2MQCLcB/s400/temperature.png" width="400" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Schematic of temperature sensor demonstration</td></tr>
</tbody></table>
<br />
<span style="font-family: "georgia" , "times new roman" , serif;">My PT100 came w/three wires ending w/</span><span style="font-family: "georgia" , "times new roman" , serif;">a blue and two red terminals. I only needed the blue and one of the red terminals.</span><br />
<span style="font-family: "georgia" , "times new roman" , serif;"><br /></span>
<span style="font-family: "georgia" , "times new roman" , serif;">To enable analog inputs requires some configuration. This example uses Debian 7 image (bone-debian-7.11-lxde-4gb-armhf-2016-06-15-4gb.img).</span><br />
<span style="font-family: "georgia" , "times new roman" , serif;"><br /></span>
<br />
<div class="p1">
<span class="s1" style="background-color: yellow;"><span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;">root@beaglebone:~# echo $SLOTS</span></span></div>
<div class="p1">
<span class="s1" style="background-color: yellow;"><span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;">/sys/devices/bone_capemgr.9/slots</span></span></div>
<div class="p1">
<span class="s1" style="background-color: yellow;"><span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;">root@beaglebone:~# cat $SLOTS</span></span></div>
<div class="p1">
<span class="s1" style="background-color: yellow;"><span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> 0: 54:PF--- </span></span></div>
<div class="p1">
<span class="s1" style="background-color: yellow;"><span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> 1: 55:PF--- </span></span></div>
<div class="p1">
<span class="s1" style="background-color: yellow;"><span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> 2: 56:PF--- </span></span></div>
<div class="p1">
<span class="s1" style="background-color: yellow;"><span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> 3: 57:PF--- </span></span></div>
<div class="p1">
<span class="s1" style="background-color: yellow;"><span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> 4: ff:P-O-L Bone-LT-eMMC-2G,00A0,Texas Instrument,BB-BONE-EMMC-2G</span></span></div>
<div class="p1">
<span class="s1" style="background-color: yellow;"><span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> 5: ff:P-O-- Bone-Black-HDMI,00A0,Texas Instrument,BB-BONELT-HDMI</span></span></div>
<div class="p1">
<span class="s1" style="background-color: yellow;"><span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> 6: ff:P-O-- Bone-Black-HDMIN,00A0,Texas Instrument,BB-BONELT-HDMIN</span></span></div>
<div class="p1">
<span class="s1" style="background-color: yellow;"><span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;">root@beaglebone:~# echo "BB-ADC" > $SLOTS</span></span></div>
<div class="p1">
<span class="s1" style="background-color: yellow;"><span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;">root@beaglebone:~# cat $SLOTS</span></span></div>
<div class="p1">
<span class="s1" style="background-color: yellow;"><span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> 0: 54:PF--- </span></span></div>
<div class="p1">
<span class="s1" style="background-color: yellow;"><span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> 1: 55:PF--- </span></span></div>
<div class="p1">
<span class="s1" style="background-color: yellow;"><span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> 2: 56:PF--- </span></span></div>
<div class="p1">
<span class="s1" style="background-color: yellow;"><span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> 3: 57:PF--- </span></span></div>
<div class="p1">
<span class="s1" style="background-color: yellow;"><span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> 4: ff:P-O-L Bone-LT-eMMC-2G,00A0,Texas Instrument,BB-BONE-EMMC-2G</span></span></div>
<div class="p1">
<span class="s1" style="background-color: yellow;"><span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> 5: ff:P-O-- Bone-Black-HDMI,00A0,Texas Instrument,BB-BONELT-HDMI</span></span></div>
<div class="p1">
<span class="s1" style="background-color: yellow;"><span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> 6: ff:P-O-- Bone-Black-HDMIN,00A0,Texas Instrument,BB-BONELT-HDMIN</span></span></div>
<div class="p1">
<span class="s1" style="background-color: yellow;"><span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> 7: ff:P-O-L Override Board Name,00A0,Override Manuf,BB-ADC</span></span></div>
<br />
<span style="font-family: "georgia" , "times new roman" , serif;">To read an ADC sample:</span><br />
<div class="p1">
<span class="s1" style="background-color: yellow;"><span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;">root@beaglebone:~# cd /sys/bus/iio/devices/iio:device0</span></span></div>
<div class="p1">
<span class="s1" style="background-color: yellow;"><span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;">root@beaglebone:/sys/bus/iio/devices/iio:device0# ls</span></span></div>
<div class="p1">
<span class="s1" style="background-color: yellow;"><span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;">dev in_voltage2_raw in_voltage5_raw name uevent</span></span></div>
<div class="p1">
<span style="background-color: yellow; font-family: "courier new" , "courier" , monospace; font-size: x-small;"><span class="s1">in_voltage0_raw in_voltage3_raw in_voltage6_raw </span><span class="s2"><b>power</b></span></span></div>
<div class="p1">
<span style="background-color: yellow; font-family: "courier new" , "courier" , monospace; font-size: x-small;"><span class="s1">in_voltage1_raw in_voltage4_raw in_voltage7_raw </span><span class="s3"><b>subsystem</b></span></span></div>
<div class="p1">
<span class="s1" style="background-color: yellow;"><span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;">root@beaglebone:/sys/bus/iio/devices/iio:device0# cat in_voltage0_raw</span></span></div>
<div class="p1">
<span class="s1" style="background-color: yellow;"><span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;">2441</span></span></div>
<span style="font-family: "georgia" , "times new roman" , serif;"><br /></span>
<span style="font-family: "georgia" , "times new roman" , serif;">For verification, I placed the PT100 in a pan of water and heated it to boiling while reading BBB ADC (voltage) values every 5 degree C (from cooking thermometer), which yields this graph (circles are samples, line is regression model).</span><br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://1.bp.blogspot.com/-YnjGzGcd0ls/WGNSjBDHQpI/AAAAAAAAGGo/Lx-eZ3BR4S028VAWWADXNKv9xxpuNPuCgCLcB/s1600/adc_vs_temp.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="400" src="https://1.bp.blogspot.com/-YnjGzGcd0ls/WGNSjBDHQpI/AAAAAAAAGGo/Lx-eZ3BR4S028VAWWADXNKv9xxpuNPuCgCLcB/s400/adc_vs_temp.png" width="400" /></a></div>
<div>
<span style="font-size: x-small;"><br /></span></div>
<div>
<span style="font-family: "georgia" , "times new roman" , serif;">Graph illustrates temperature change is linear (and suggests a conversion model). </span><br />
<span style="font-family: "georgia" , "times new roman" , serif;"><br /></span>
<span style="font-family: "georgia" , "times new roman" , serif;">To convert ADC to temperature use: 822 - 0.329512(ADC value)</span><br />
<span style="font-family: "georgia" , "times new roman" , serif;"><br /></span>
<span style="font-family: "georgia" , "times new roman" , serif;">Table (below) illustrates observed vs calculated temperatures. Real world rarely match calculated world, but these values seem close enough for my intended application.</span><br />
<span style="font-family: "georgia" , "times new roman" , serif;"><br /></span>
<br />
<table border="2">
<tbody>
<tr><td>ADC</td><td>Observed C</td><td>Calculated C</td></tr>
<tr><td>2479</td><td>10</td><td>5.14</td></tr>
<tr><td>2437</td><td>15</td><td>18.98</td></tr>
<tr><td>2424</td><td>20</td><td>23.26</td></tr>
<tr><td>2419</td><td>25</td><td>24.91</td></tr>
<tr><td>2403</td><td>30</td><td>30.18</td></tr>
<tr><td>2389</td><td>35</td><td>34.80</td></tr>
<tr><td>2378</td><td>40</td><td>38.42</td></tr>
<tr><td>2358</td><td>45</td><td>45.01</td></tr>
<tr><td>2347</td><td>50</td><td>48.64</td></tr>
<tr><td>2332</td><td>55</td><td>53.58</td></tr>
<tr><td>2318</td><td>60</td><td>58.19</td></tr>
<tr><td>2299</td><td>65</td><td>64.45</td></tr>
<tr><td>2284</td><td>70</td><td>69.39</td></tr>
<tr><td>2267</td><td>75</td><td>75.00</td></tr>
<tr><td>2251</td><td>80</td><td>80.27</td></tr>
<tr><td>2235</td><td>85</td><td>85.54</td></tr>
<tr><td>2218</td><td>90</td><td>91.14</td></tr>
<tr><td>2208</td><td>95</td><td>94.44</td></tr>
<tr><td>2195</td><td>100</td><td>98.72</td></tr>
</tbody></table>
<br /></div>
<div>
<span style="font-family: "georgia" , "times new roman" , serif;"><br /></span></div>
<style type="text/css">
p.p1 {margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo; background-color: #fef49c}
span.s1 {font-variant-ligatures: no-common-ligatures}
</style><style type="text/css">
p.p1 {margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo; background-color: #fef49c}
span.s1 {font-variant-ligatures: no-common-ligatures}
span.s2 {font-variant-ligatures: no-common-ligatures; color: #4d2cdc}
span.s3 {font-variant-ligatures: no-common-ligatures; color: #25b2bf}
</style>guycolehttp://www.blogger.com/profile/13546414963444312679noreply@blogger.com0tag:blogger.com,1999:blog-1010221292729658742.post-21959551258830902202016-12-22T21:12:00.004-08:002017-01-15T17:06:18.215-08:00AWS IoT and BeagleBone Green WirelessThis post demonstrates how to configure a <a href="http://wiki.seeed.cc/SeeedStudio_BeagleBone_Green_Wireless/" target="_blank">BeagleBone Green Wireless</a> for <a href="https://aws.amazon.com/iot" target="_blank">Amazon Web Services "Internet of Things"</a> using the <a href="https://aws.amazon.com/cli" target="_blank">AWS CLI</a>.<br />
<br />
<div>
The ingredients:</div>
<div>
<ul>
<li>AWS Account</li>
<li>BeagleBone Green Wireless (BBGW)</li>
<ul>
<li>Working WiFi</li>
<li>Flashed w/image bone-debian-8.6-seeed-iot-armhf-2016-11-06-4gb.img</li>
<li><!--?xml version="1.0" encoding="UTF-8" standalone="no"?-->
<span style="font-family: "helvetica neue";">apt-get update</span></li>
<li><span style="font-family: "helvetica neue";">apt-get upgrade</span></li>
</ul>
</ul>
<div>
<span style="font-family: "helvetica neue";">Install AWS CLI on BBGW. Perform the following steps:</span></div>
<div>
<ul>
<li><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Create a IAM user for the BeagleBone</span></li>
<ul>
<li><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">download the access key ID/secret access key</span></li>
</ul>
<li><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Install AWS CLI</span></li>
<ul>
<li>pip install awscli</li>
</ul>
<li><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Configure AWS CLI (using the access key ID/secret access key from above)</span></li>
<ul>
<li>aws configure</li>
</ul>
<li><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Verify AWS CLI installation by performing simple command</span></li>
<ul>
<li>aws s3 ls (s3 directories are returned)</li>
</ul>
</ul>
<div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Generate security certificates:</span></div>
</div>
</div>
<div>
<ul>
<li>mkdir aws_certs</li>
<li>cd aws_certs</li>
<li>openssl genrsa -out privateKey.pem 2048</li>
<li>openssl req -new -key privateKey.pem -out cert.csr</li>
<li>aws iot create-certificate-from-csr --certificate-signing-request file://cert.csr --set-as-active > certOutput.txt</li>
<li>grep <span style="background-color: yellow;">certificateId</span> certOutput.txt</li>
<li>aws iot describe-certificate --certificate-id <<span style="background-color: yellow;">certificateId from last step</span>> --output text --query certificateDescription.certificatePem > cert.pem</li>
</ul>
<div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Create a policy and attach generated certificate:</span></div>
</div>
<div>
<ul>
<li><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Create policy document (policy.doc)<br />
</span>{<br />
"Version": "2012-10-17",<br />
"Statement": [{<br />
"Effect": "Allow",<br />
"Action":["iot:*"],<br />
"Resource": ["*"]<br />
}]<br />
}</li>
<li>aws iot create-policy --policy-name PubSubToAnyTopic --policy-document file://policy.doc</li>
<li>grep <span style="background-color: yellow;">certificateArn </span>certOutput.txt</li>
<li>aws iot attach-principal-policy --principal <<span style="background-color: yellow;">certifcateArn from last step</span>> --policy-name "PubSubToAnyTopic" </li>
</ul>
</div>
<div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">At this point, you should be able to see the certificates/policy in the AWS console. From the AWS IoT page, select "certificates" or "policies".</span></div>
<div>
<ul>
<li><a href="https://console.aws.amazon.com/iotv2/home?region=us-east-1#/certificatehub" target="_blank">Certificates</a></li>
<li><a href="https://console.aws.amazon.com/iotv2/home?region=us-east-1#/policyhub" target="_blank">Policies</a></li>
</ul>
<div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Alternatively, ask for certificates using AWS CLI:</span></div>
<div>
<ul>
<li>aws iot list-certificates</li>
</ul>
<div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Register your BeagleBone (thing) and attach to Principal (policy):</span></div>
<div>
<ul>
<li>aws iot create-thing --thing-name bbgw</li>
<li>aws iot attach-thing-principal --thing-name bbgw --principal <<span style="background-color: yellow;">certifcateArn from previous step</span>></li>
</ul>
<div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">At this point you should be able to see the thing in the AWS console. From the AWS IoT page, select "Registry/Things"</span></div>
</div>
<div>
<ul>
<li><a href="https://console.aws.amazon.com/iotv2/home?region=us-east-1#/thinghub" target="_blank"><span style="font-family: "times" , "times new roman" , serif;">Registry/Things</span></a></li>
</ul>
</div>
<div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Alternatively, ask for things using AWS CLI:</span><br />
<ul>
<li><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">aws iot list-things</span></li>
</ul>
<div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Update BBGW status:</span></div>
<div>
<ul>
<li><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">aws iot update-thing --thing-name bbgw --attribute-payload attributes={key1=value1}</span></li>
</ul>
</div>
<div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Verify update:</span><br />
<ul>
<li><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">aws iot list-things</span></li>
</ul>
</div>
</div>
</div>
</div>
<style type="text/css">
p.p1 {margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo; background-color: #fef49c}
span.s1 {font-variant-ligatures: no-common-ligatures}
</style>guycolehttp://www.blogger.com/profile/13546414963444312679noreply@blogger.com0tag:blogger.com,1999:blog-1010221292729658742.post-41462517430588741042016-12-18T17:36:00.001-08:002016-12-18T17:37:09.371-08:00Infrared "break beam" detection using BeagleBone Black and Adafruit 2167Here is a simple example of monitoring a infrared (IR) light beam w/BeagleBone Black. There are many use cases for IR break beam sensors and for US $1.95 the <a href="https://www.adafruit.com/product/2167" target="_blank">Adafruit 2167</a> is an excellent choice.<br />
<br />
The example provided by Adafruit is for the Arduino. Here is a simple example using the BBB.<br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://2.bp.blogspot.com/-5aCZwjF75Z8/WFc2oOSu_wI/AAAAAAAAF_w/k9s3ljgfelAYb2TrMT9ozCNEX17fYtLZgCLcB/s1600/IR1_0.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" height="225" src="https://2.bp.blogspot.com/-5aCZwjF75Z8/WFc2oOSu_wI/AAAAAAAAF_w/k9s3ljgfelAYb2TrMT9ozCNEX17fYtLZgCLcB/s400/IR1_0.png" width="400" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Schematic of "break beam" demo.</td></tr>
</tbody></table>
Any GPIO will do. Below is a runtime example from a BBB using Debian 7 (wheezy). Note that "value" contains a 1 when the IR beam is detected and a 0 when I block the beam.<br />
<br />
<div class="p1">
<span class="s1">root@beaglebone:~# cd /sys/class/gpio</span></div>
<div class="p1">
<span class="s1">root@beaglebone:/sys/class/gpio# echo 115 > export</span></div>
<div class="p1">
<span class="s1">root@beaglebone:/sys/class/gpio# cd gpio115</span></div>
<div class="p1">
<span class="s1">root@beaglebone:/sys/class/gpio/gpio115# echo in > direction</span></div>
<div class="p1">
<span class="s1">root@beaglebone:/sys/class/gpio/gpio115# cat value</span></div>
<div class="p1">
<span class="s1">1</span></div>
<div class="p1">
<span class="s1">root@beaglebone:/sys/class/gpio/gpio115# cat value</span></div>
<div class="p1">
<span class="s1">0</span></div>
<br />
<style type="text/css">
p.p1 {margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo; background-color: #fef49c}
span.s1 {font-variant-ligatures: no-common-ligatures}
</style>guycolehttp://www.blogger.com/profile/13546414963444312679noreply@blogger.com0tag:blogger.com,1999:blog-1010221292729658742.post-57558297292610774522016-04-24T01:47:00.005-07:002016-04-24T01:48:35.354-07:00AWS API Gateway and Lamba (Python) DemonstrationI have a customer interested in AWS API Gateway and Lambda (Python), so I created a small demonstration application to explore this option.<br />
<div>
<br /></div>
<div>
The resulting application is a simple 4 function calculator web service. There is significant overlap between this demo and the LambdaGate example provided by AWS. This application is different because:</div>
<div>
<ul>
<li>Employs Cloud Formation as much as possible</li>
<li>Python (instead of node.js) Lambda function</li>
</ul>
<div>
<a href="https://github.com/guycole/calc-demo-aws" target="_blank">Source and installation instructions available via GitHub</a>.</div>
</div>
guycolehttp://www.blogger.com/profile/13546414963444312679noreply@blogger.com0tag:blogger.com,1999:blog-1010221292729658742.post-56120515637215906712014-06-01T10:32:00.003-07:002014-06-01T19:09:08.430-07:00Google App Engine Development Environment on Mavericks w/IntelliJ and mavenGoogle App Engine/Java is an interesting platform which does not seem to get the same attention as AWS EC2. I work on contract and it is a rare day that someone asks me to work on a GAE project while AWS EC2 is extremely common. I understand there are many reasons for this, and (IMO) one reason is the vast quantity of stale/incomplete blogs posts which make GAE/J difficult to learn and adopt. I am certain this post will also become stale in the future, so ensure the products I am using match your goals before investing. Today is 1 June, 2014 and the tools I want to employ are:<br />
<div>
<ol>
<li>OSX 10.9</li>
<li>Google App Engine 1.9.5</li>
<li>Java 1.7</li>
<li>Maven 3.1</li>
<li>IntelliJ Idea 13</li>
<li><a href="https://code.google.com/p/objectify-appengine/" target="_blank">Objectify</a> 5</li>
</ol>
<div>
Note: example application is located on <a href="https://github.com/guycole/gae-java-demo/tree/objectify" target="_blank">github</a>.</div>
<div>
<br /></div>
<div>
The first issue you may encounter as a OSX user is that GAE requires Java 1.7 and you might still be on Java 1.6 - <span style="background-color: yellow;">DO NOT get the latest Java 1.7</span> (which is currently 1.7.0_60) because of bug JDK-8025876. Instead select Java 1.7.0_25 - there has been much discussion about this issue, here is an example from <a href="http://stackoverflow.com/questions/18794573/objc10012-class-javalaunchhelper-is-implemented-in-both-libinstrument-dyl" target="_blank">Stack Overflow</a>.</div>
<div>
<br /></div>
<div>
You should be able to obtain results similar to this:</div>
<div>
<div class="p1">
<span style="font-family: Courier New, Courier, monospace;">gsc@duckman:72>java -version</span></div>
<div class="p1">
<span style="font-family: Courier New, Courier, monospace;">java version "1.7.0_25"</span></div>
<div class="p1">
<span style="font-family: Courier New, Courier, monospace;">Java(TM) SE Runtime Environment (build 1.7.0_25-b15)</span></div>
<div class="p1">
<span style="font-family: Courier New, Courier, monospace;">Java HotSpot(TM) 64-Bit Server VM (build 23.25-b01, mixed mode)</span></div>
</div>
<div>
<br /></div>
<div>
Now that your system is working on Java 1.7, you should ensure that maven is aware of the update. Simply updating $JAVA_HOME was not sufficient and I also needed to tweak .mavenrc - once again <a href="http://stackoverflow.com/questions/18813828/why-maven-use-jdk-1-6-but-my-java-version-is-1-7" target="_blank">Stack Overflow</a> to the rescue. </div>
<div>
<br /></div>
<div>
You should be able to obtain results similar to this:</div>
<div>
<div class="p1">
<span style="font-family: Courier New, Courier, monospace;">gsc@duckman:73>mvn -v</span></div>
<div class="p1">
<span style="font-family: Courier New, Courier, monospace;">Apache Maven 3.1.1 (NON-CANONICAL_2013-11-17_20-36_gsc; 2013-11-17 20:36:09-0800)</span></div>
<div class="p1">
<span style="font-family: Courier New, Courier, monospace;">Maven home: /Users/gsc/local/apache-maven-3.1.1</span></div>
<div class="p1">
<span style="font-family: Courier New, Courier, monospace;">Java version: 1.7.0_25, vendor: Oracle Corporation</span></div>
<div class="p1">
<span style="font-family: Courier New, Courier, monospace;">Java home: /Library/Java/JavaVirtualMachines/jdk1.7.0_25.jdk/Contents/Home/jre</span></div>
<div class="p1">
<span style="font-family: Courier New, Courier, monospace;">Default locale: en_US, platform encoding: UTF-8</span></div>
<div class="p1">
<span style="font-family: Courier New, Courier, monospace;">OS name: "mac os x", version: "10.9.3", arch: "x86_64", family: "mac"</span></div>
</div>
<div>
</div>
<div>
At this point, java and maven are ready. If you have not already done so, download the latest Google App Engine SDK (currently 1.9.5) and install it on your system. Point to the GAE installation with $APPENGINE_HOME<br />
<br />
Google provides the <a href="https://developers.google.com/appengine/docs/java/gettingstarted/introduction" target="_blank">guestbook</a> tutorial which has been updated recently (note the EAR directory in addition to the original WAR). The application skeleton is generated from maven with features incrementally added through the tutorial. Instructions are reliable until until runtime when <span style="background-color: yellow;">Google shows the old (now wrong) command to start/deploy on a local development server</span>. Assuming you have this directory structure:</div>
</div>
<div>
<div class="p1">
<span style="font-family: Courier New, Courier, monospace;">gsc@duckman:89>ll</span></div>
<div class="p1">
<span style="font-family: Courier New, Courier, monospace;">total 32</span></div>
<div class="p1">
<span style="font-family: Courier New, Courier, monospace;">drwxr-xr-x 8 gsc staff 272 Jun 1 10:21 ./</span></div>
<div class="p1">
<span style="font-family: Courier New, Courier, monospace;">drwxr-xr-x 7 gsc staff 238 Jun 1 10:38 ../</span></div>
<div class="p1">
<span style="font-family: Courier New, Courier, monospace;">-rw-r--r-- 1 gsc staff 106 Jun 1 10:21 .gitignore</span></div>
<div class="p1">
<span style="font-family: Courier New, Courier, monospace;">-rw-r--r-- 1 gsc staff 121 Jun 1 10:21 README.md</span></div>
<div class="p1">
<span style="font-family: Courier New, Courier, monospace;">drwxr-xr-x 6 gsc staff 204 Jun 1 11:47 guestbook-ear/</span></div>
<div class="p1">
<span style="font-family: Courier New, Courier, monospace;">drwxr-xr-x 6 gsc staff 204 Jun 1 11:47 guestbook-war/</span></div>
<div class="p1">
<span style="font-family: Courier New, Courier, monospace;">-rw-r--r-- 1 gsc staff 583 Jun 1 10:21 guestbook.iml</span></div>
<div class="p1">
<span style="font-family: Courier New, Courier, monospace;">-rw-r--r-- 1 gsc staff 1009 Jun 1 10:21 pom.xml</span></div>
<div class="p1">
<br /></div>
<div class="p1">
The correct command to start/deploy on a local development server is:</div>
<div class="p2">
<span style="font-family: Courier New, Courier, monospace;">gsc@duckman:90>mvn -pl guestbook-ear appengine:devserver </span></div>
<div class="p2">
<span style="font-family: Times, Times New Roman, serif;">When you see "</span><span style="font-family: Courier New, Courier, monospace;">[INFO] INFO: Dev App Server is now running" </span><span style="font-family: Times, Times New Roman, serif;">then you should be able to visit the guestbook application at </span><span style="font-family: Courier New, Courier, monospace;">http://localhost:8080</span><span style="font-family: Times, Times New Roman, serif;"> and the GAE console is on </span><span style="font-family: Courier New, Courier, monospace;">http://localhost:8080/_ah/admin </span><span style="font-family: Times, Times New Roman, serif;">(guestbook screenshot below)</span><br />
<span style="font-family: Times, Times New Roman, serif;"><br /></span>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="http://3.bp.blogspot.com/-0ab7uDBrs5o/U4uBzfuIW-I/AAAAAAAADRs/oyonuKTP3tI/s1600/Screen+Shot+2014-06-01+at+12.39.54+PM.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="http://3.bp.blogspot.com/-0ab7uDBrs5o/U4uBzfuIW-I/AAAAAAAADRs/oyonuKTP3tI/s1600/Screen+Shot+2014-06-01+at+12.39.54+PM.png" height="231" width="320" /></a></div>
<span style="font-family: Times, Times New Roman, serif;"><br /></span></div>
<div class="p2">
<br /></div>
<div class="p2">
At this point, you have a simple, working application which you can compile and deploy using command line arguments. Now I bring IntelliJ 13 into the mix.<br />
<br />
First you must configure IntelliJ for your freshly installed Java 1.7 - start IntelliJ and from the splash panel select "Configure"->"Project Defaults"->"Project Structure" and the goal is a display like below.<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="http://4.bp.blogspot.com/-1Yob4AOTiVI/U4uAWsRNRXI/AAAAAAAADRg/b0GLfGa0IWM/s1600/Screen+Shot+2014-06-01+at+12.31.14+PM.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="http://4.bp.blogspot.com/-1Yob4AOTiVI/U4uAWsRNRXI/AAAAAAAADRg/b0GLfGa0IWM/s1600/Screen+Shot+2014-06-01+at+12.31.14+PM.png" height="256" width="320" /></a></div>
</div>
<div class="p2">
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="http://2.bp.blogspot.com/-Zb7GKamTdT0/U4uK90zOHvI/AAAAAAAADR8/J8Sst3oW_nQ/s1600/Screen+Shot+2014-06-01+at+1.18.44+PM.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="http://2.bp.blogspot.com/-Zb7GKamTdT0/U4uK90zOHvI/AAAAAAAADR8/J8Sst3oW_nQ/s1600/Screen+Shot+2014-06-01+at+1.18.44+PM.png" height="257" width="320" /></a></div>
<br />
Now we need a project. You can continue to use the original guestbook application or consider my derivative version from <a href="https://github.com/guycole/gae-java-demo/tree/objectify" target="_blank">github</a>. If you are interested in a quick introduction to <a href="https://code.google.com/p/objectify-appengine/" target="_blank">objectify</a> then use my version.<br />
<br />
IntelliJ can be challenging to configure, YMMV but in my experience the tutorials and help are rarely up to date even for the "ultimate" version. Once again, <a href="http://stackoverflow.com/" target="_blank">Stack Overflow</a> is probably your best resource for assistance.<br />
<br />
Ensure you have the "GAE Integration" plugin enabled. The following screenshots might help in comparing your environment from mine. <br />
<div class="separator" style="clear: both; text-align: center;">
<a href="http://1.bp.blogspot.com/-hD-dh4FisU0/U4uQLN_GxFI/AAAAAAAADSI/zJwm-afPGPI/s1600/Screen+Shot+2014-06-01+at+1.41.22+PM.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="http://1.bp.blogspot.com/-hD-dh4FisU0/U4uQLN_GxFI/AAAAAAAADSI/zJwm-afPGPI/s1600/Screen+Shot+2014-06-01+at+1.41.22+PM.png" height="202" width="320" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="http://3.bp.blogspot.com/-_q7u2uYzk98/U4uRI4B0XNI/AAAAAAAADSQ/MQh77XK0bs4/s1600/Screen+Shot+2014-06-01+at+1.45.43+PM.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="http://3.bp.blogspot.com/-_q7u2uYzk98/U4uRI4B0XNI/AAAAAAAADSQ/MQh77XK0bs4/s1600/Screen+Shot+2014-06-01+at+1.45.43+PM.png" height="272" width="320" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="http://4.bp.blogspot.com/-QvUFNVhoHQ4/U4uRl7zpr1I/AAAAAAAADSY/6xTv_RaBC4I/s1600/Screen+Shot+2014-06-01+at+1.47.44+PM.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="http://4.bp.blogspot.com/-QvUFNVhoHQ4/U4uRl7zpr1I/AAAAAAAADSY/6xTv_RaBC4I/s1600/Screen+Shot+2014-06-01+at+1.47.44+PM.png" height="273" width="320" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="http://1.bp.blogspot.com/-e8w5LwvYOF4/U4uR3woFWYI/AAAAAAAADSg/Wb1OvPrB2bo/s1600/Screen+Shot+2014-06-01+at+1.48.58+PM.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="http://1.bp.blogspot.com/-e8w5LwvYOF4/U4uR3woFWYI/AAAAAAAADSg/Wb1OvPrB2bo/s1600/Screen+Shot+2014-06-01+at+1.48.58+PM.png" height="273" width="320" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="http://1.bp.blogspot.com/-Iw85w5jJmlY/U4uSIY0CmVI/AAAAAAAADSo/TAON7XH6MoY/s1600/Screen+Shot+2014-06-01+at+1.50.02+PM.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="http://1.bp.blogspot.com/-Iw85w5jJmlY/U4uSIY0CmVI/AAAAAAAADSo/TAON7XH6MoY/s1600/Screen+Shot+2014-06-01+at+1.50.02+PM.png" height="268" width="320" /></a></div>
The proof is your success in being able to compile and deploy to your local development server from within IntelliJ. Attempt it now using the "make" triangle in the top right toolbar.<br />
<br />
At this point you should now be able to work on a GAE/J application using IntelliJ (including the debugger). Only <a href="https://code.google.com/p/objectify-appengine/" target="_blank">objectify</a> remains to be explored.<br />
<br />
The original guestbook sample application uses the DatastoreService for persistence in two spots: reading guestbook entries within guestbook.jsp and writing guestbook entries within SignGuestbookServlet.java<br />
<br />
To use <a href="https://code.google.com/p/objectify-appengine/" target="_blank">objectify</a> I have added <a href="https://github.com/guycole/gae-java-demo/blob/master/guestbook/guestbook-war/src/main/java/com/google/appengine/demos/guestbook/Greeting.java" target="_blank">Greeting.java</a> as an Entity and <a href="https://github.com/guycole/gae-java-demo/blob/master/guestbook/guestbook-war/src/main/java/com/google/appengine/demos/guestbook/GreetingDao.java" target="_blank">GreetingDao.java</a> as a DAO. I also modified <a href="https://github.com/guycole/gae-java-demo/blob/master/guestbook/guestbook-war/src/main/webapp/guestbook.jsp" target="_blank">guestbook.jsp</a> and <a href="https://github.com/guycole/gae-java-demo/blob/master/guestbook/guestbook-war/src/main/java/com/google/appengine/demos/guestbook/SignGuestbookServlet.java" target="_blank">SignGuestbookServlet.java</a> to use the DAO (and objectify) rather than the datastore directly.<br />
<br />
This concludes my short tour of making a small GAE project and I hope it saved you some time.</div>
</div>
guycolehttp://www.blogger.com/profile/13546414963444312679noreply@blogger.com0tag:blogger.com,1999:blog-1010221292729658742.post-63693883139330369582014-04-27T07:41:00.000-07:002014-04-27T08:10:59.374-07:00Hybrid Android Applications w/WebViewMany Android applications look entirely native but have at least a portion of the UI implemented using a WebView to display HTML and JavaScript. (In this context, "native" means a UI created in the traditional Java/XML approach and not the NDK). <br />
<div>
<div>
<br /></div>
<div>
This post illustrates the use of <a href="http://developer.android.com/reference/android/webkit/WebView.html" target="_blank">WebView</a> along w/<a href="http://developer.android.com/reference/android/webkit/WebViewClient.html" target="_blank">WebViewClient</a> and <a href="http://developer.android.com/reference/android/webkit/WebChromeClient.html" target="_blank">WebChromeClient</a>. I have created a small demonstration application ("AndroidWebView") which is available on <a href="https://github.com/guycole/AndroidWebView" target="_blank">github</a>.<br />
<br />
AndroidWebView has four tabs to demonstrate different use cases (screenshots below).<br />
<br />
The first tab ("About") illustrates the simple use case of reading a locally stored HTML file into a WebView. Using HTML is a frequent solution for non-interactive, wordy content such as T&C, EULA or perhaps application help pages. As you can see <a href="https://github.com/guycole/AndroidWebView/blob/master/app/src/main/java/com/digiburo/example/wvdemo/app/AboutFragment.java" target="_blank">AboutFragment.java</a> was extremely simple to implement.<br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="float: left; margin-right: 1em; text-align: left;"><tbody>
<tr><td style="text-align: center;"><a href="http://3.bp.blogspot.com/-KHBdZoB3RWQ/U10avND3PkI/AAAAAAAADO4/L55cxApb1Sc/s1600/Screenshot_2014-04-27-15-04-05.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="http://3.bp.blogspot.com/-KHBdZoB3RWQ/U10avND3PkI/AAAAAAAADO4/L55cxApb1Sc/s1600/Screenshot_2014-04-27-15-04-05.png" height="320" width="180" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">"About" tab selection</td></tr>
</tbody></table>
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="http://4.bp.blogspot.com/-gQHq-hx5ksY/U10aoLks3RI/AAAAAAAADOw/ECQj6FiunmQ/s1600/Screenshot_2014-04-27-15-05-13.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="http://4.bp.blogspot.com/-gQHq-hx5ksY/U10aoLks3RI/AAAAAAAADOw/ECQj6FiunmQ/s1600/Screenshot_2014-04-27-15-05-13.png" height="320" width="180" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">"Client" tab selection</td></tr>
</tbody></table>
The second tab ("Client") reads a remote web page and manages interaction w/the remote server using a <a href="http://developer.android.com/reference/android/webkit/WebViewClient.html" target="_blank">WebViewClient</a>. Again <a href="https://github.com/guycole/AndroidWebView/blob/master/app/src/main/java/com/digiburo/example/wvdemo/app/ClientFragment.java" target="_blank">ClientFragment,java</a> is small and simple.<br />
<br />
<a href="https://github.com/guycole/AndroidWebView/blob/master/app/src/main/java/com/digiburo/example/wvdemo/app/DemoWebViewClient.java" target="_blank">DemoWebViewClient.java</a> reacts to events such as "page started", "page finished", "authorization requests", "errors", etc. I have implemented the interesting methods to write log messages so we can view the progress using "adb logcat".<br />
<br />
<div style="-webkit-text-stroke-width: 0px; color: black; font-family: Times; font-size: medium; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; margin: 0px; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px;">
The received web page (above, on the right) and there are four navigation buttons (i.e. "Contact", "News", "Products", "Services") which are implemented as HTTP HREF(s). Within DemoWebViewClient.shouldOverrideUrlLoading() I have arranged for the "News" button to invoke <a href="https://github.com/guycole/AndroidWebView/blob/master/app/src/main/java/com/digiburo/example/wvdemo/app/NewsDialogFragment.java" target="_blank">NewsDialogFragment.java</a> rather than perform the usual HTTP GET. This illustrates the use case of HTML content invoking an Android View.<br />
<br />
<table><tbody>
<tr><td><div style="margin: 0px;">
It is useful to view the log output ("adb logcat") when viewing the "Client" tab. When reviewing the log, you will see the various requests necessary to render the page. This illustrates that you can detect and perhaps alter the content, or react to certain events. The log output should look similar to this:<br />
<br />
<div class="p1">
<span style="font-family: Verdana, sans-serif; font-size: x-small;">DemoWebViewClient(20221): interceptRequest:http://www.digiburo.com/mobi/db_index.html</span></div>
<div class="p2">
<span style="font-family: Verdana, sans-serif; font-size: x-small;">DemoWebViewClient(20221): pageStarted:http://www.digiburo.com/mobi/db_index.html</span></div>
<div class="p2">
<span style="font-family: Verdana, sans-serif; font-size: x-small;">DemoWebViewClient(20221): load:http://www.digiburo.com/mobi/db_index.html</span></div>
<div class="p2">
<span style="font-family: Verdana, sans-serif; font-size: x-small;">DemoWebViewClient(20221): interceptRequest:http://www.digiburo.com/css/stylesheet2.css</span></div>
<div class="p2">
<span style="font-family: Verdana, sans-serif; font-size: x-small;">DemoWebViewClient(20221): load:http://www.digiburo.com/css/stylesheet2.css</span></div>
<div class="p2">
<span style="font-family: Verdana, sans-serif; font-size: x-small;">DemoWebViewClient(20221): interceptRequest:http://www.google-analytics.com/ga.js</span></div>
<div class="p2">
<span style="font-family: Verdana, sans-serif; font-size: x-small;">DemoWebViewClient(20221): load:http://www.google-analytics.com/ga.js</span></div>
<div class="p2">
<span style="font-family: Verdana, sans-serif; font-size: x-small;">DemoWebViewClient(20221): interceptRequest:http://www.digiburo.com/grafix/home_logo.png</span></div>
<div class="p2">
<span style="font-family: Verdana, sans-serif; font-size: x-small;">DemoWebViewClient(20221): load:http://www.digiburo.com/grafix/home_logo.png</span></div>
<div class="p2">
<span style="font-family: Verdana, sans-serif; font-size: x-small;">DemoWebViewClient(20221): interceptRequest:http://www.digiburo.com/grafix/canvas1.png</span></div>
<div class="p2">
<span style="font-family: Verdana, sans-serif; font-size: x-small;">DemoWebViewClient(20221): load:http://www.digiburo.com/grafix/canvas1.png</span></div>
<div class="p2">
<span style="font-family: Verdana, sans-serif; font-size: x-small;">DemoWebViewClient(20221): interceptRequest:http://www.google-analytics.com/__utm.gif? //deleted</span></div>
<div class="p2">
<span style="font-family: Verdana, sans-serif; font-size: x-small;">DemoWebViewClient(20221): load:http://www.google-analytics.com/__utm.gif? //deleted</span></div>
<div class="p2">
<div style="margin: 0px;">
<span style="font-family: Verdana, sans-serif; font-size: x-small;">DemoWebViewClient(20221): pageFinished:http://www.digiburo.com/mobi/db_index.html</span></div>
</div>
<br /></div>
</td></tr>
</tbody></table>
</div>
<table><tbody>
<tr><td><br /></td><td><br /></td>
</tr>
<tr>
<td><!--pix-->
<br />
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
</td>
<td><br /></td></tr>
</tbody></table>
<div class="separator" style="clear: both; text-align: center;">
<a href="http://4.bp.blogspot.com/-D91LWaMuvHQ/U10Pdpb04gI/AAAAAAAADOg/qN-wgJIHJ8g/s1600/Screenshot_2014-04-27-15-06-23.png" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"><img border="0" src="http://4.bp.blogspot.com/-D91LWaMuvHQ/U10Pdpb04gI/AAAAAAAADOg/qN-wgJIHJ8g/s1600/Screenshot_2014-04-27-15-06-23.png" height="320" width="180" /></a></div>
<div class="p2">
<span style="font-family: Verdana, sans-serif; font-size: x-small;"><br /></span></div>
</div>
</div>
<div>
The third tab ("JS") illustrates interaction w/JavaScript. <br />
<br />
<a href="https://github.com/guycole/AndroidWebView/blob/master/app/src/main/java/com/digiburo/example/wvdemo/app/JavaScriptFragment.java" target="_blank">JavaScriptFragment.java</a> creates a WebChromeClient <a href="https://github.com/guycole/AndroidWebView/blob/master/app/src/main/java/com/digiburo/example/wvdemo/app/DemoWebChromeClient.java" target="_blank">DemoWebChromeClient.java</a> which enables support like connecting the JavaScript console to write via the Android log or report loading progress. If you wish to use JavaScript Alert() rather than an Android View, you will need to use WebChromeClient.onJsAlert() (which I have implemented for this purpose). The "generateAlert" button produces a JavaScript alert.<br />
<br />
JavaScriptFragment.java relies upon <a href="https://github.com/guycole/AndroidWebView/blob/master/app/src/main/java/com/digiburo/example/wvdemo/app/DemoJavaScript.java" target="_blank">DemoJavaScript.java</a> to expose Java methods which can be invoked from JavaScript. I have implemented simple examples to illustrate using Android logging or return a String to JavaScript. The "@JavascriptInterface" is limited in many ways regarding parameters and return results: primitives and Strings usually work but you will want to experiment before promising complicated arguments. Note that generatePrimes() returns a String which contains a JSON formatted array, and this is a successful approach. Pressing "generateLog" will cause an Android log message to be written (visible via "adb logcat"). "generatePrime" invokes a Java based prime number generator and returns the results as a JSON formatted String.<br />
<br />
What about the use case of Java invoking JavaScript? This is also possible and pressing "Invoke JavaScript" shows how. "Invoke JavaScript" is a standard Android button which invokes WebView.loadUrl() for <a href="https://github.com/guycole/AndroidWebView/blob/master/app/src/main/assets/html/bridge.html" target="_blank">bridge.html</a> which writes a log entry back to Java.<br />
<br />
The fourth tab ("Simple") <a href="https://github.com/guycole/AndroidWebView/blob/master/app/src/main/java/com/digiburo/example/wvdemo/app/SimpleFragment.java" target="_blank">SimpleFragment.java</a> demonstrates the trivial use case of reading a remote file without WebViewClient or WebChromeClient. </div>
guycolehttp://www.blogger.com/profile/13546414963444312679noreply@blogger.com2tag:blogger.com,1999:blog-1010221292729658742.post-74404725442085758262014-04-13T03:16:00.000-07:002014-04-13T03:19:26.655-07:00Updated BackProp1 Now AvailableI have recently updated the back propagation neural network "backprop1."<br />
<br />
BackProp1 is a derivative of an image classification project I delivered in 2001. It has been available on <a href="http://sourceforge.net/projects/backprop1/" target="_blank">SourceForge</a> since 2009 (and my own web site prior to that). BackProp1 consists of a library which can be embedded in your own projects and three demonstration applications:<br />
<ol>
<li>demo1 is a point classifier which can determine if a point is above or below the line y = -5x + 2</li>
<li>demo2 is the XOR classifier</li>
<li>demo3 features an interactive UI and trains to recognize the digits 0-9. You can select a pattern and then submit it for classification. You can also flip the state of individual pixels and discover if the classifier will still recognize the pattern.</li>
</ol>
Get the latest version of backprop1 on <a href="https://github.com/guycole/BackProp1" target="_blank">github</a>.<br />
<br />
This new offering includes:<br />
<ol>
<li>Demo3 now should look OK on any platform (was effectively broken on OS X).</li>
<li>Now builds w/gradle. </li>
</ol>
guycolehttp://www.blogger.com/profile/13546414963444312679noreply@blogger.com0tag:blogger.com,1999:blog-1010221292729658742.post-57610818940959885912013-12-27T17:31:00.001-08:002014-01-03T01:01:50.571-08:00Spring Messaging w/JMS and NevadoI have recently created some small demonstration applications to illustrate how to use Spring Messaging with <a href="http://activemq.apache.org/" target="_blank">ActiveMQ</a> and <a href="http://nevado.skyscreamer.org/" target="_blank">Nevado</a>/<a href="http://aws.amazon.com/" target="_blank">AWS</a> as <a href="http://en.wikipedia.org/wiki/Java_Message_Service" target="_blank">JMS</a> providers.<br />
<div>
<br /></div>
<div>
Complete sources are available on <a href="https://github.com/guycole/spring-messaging-demo" target="_blank">GitHub</a>. You will need to obtain a copy of ActiveMQ to exercise SimpleQueueDriver and SimpleTopicDriver. To use SqsQueueDriver w/AWS requires an AWS account. Be sure to update <a href="https://github.com/guycole/spring-messaging-demo/blob/master/src/main/resources/aws.properties" target="_blank">aws.properties</a> with your account information.</div>
<div>
<br /></div>
<div>
Since there is plenty of <a href="http://docs.spring.io/spring/docs/3.1.x/spring-framework-reference/html/jms.html" target="_blank">Spring documentation</a> available, I'll skip the tutorial and directly address the sources on GitHub.</div>
<div>
<br /></div>
<div>
<a href="https://github.com/guycole/spring-messaging-demo/blob/master/src/main/java/com/digiburo/spring/demo/simple_aq/SimpleQueueDriver.java" target="_blank">SimpleQueueDriver</a> starts two <a href="https://github.com/guycole/spring-messaging-demo/blob/master/src/main/java/com/digiburo/spring/demo/simple_aq/SimpleListener.java" target="_blank">listeners</a> and then writes a TextMessage. Even though there are two listeners, only one will receive the text message (property of being a queue).</div>
<div>
<br /></div>
<div>
<a href="ttps://github.com/guycole/spring-messaging-demo/blob/master/src/main/java/com/digiburo/spring/demo/simple_aq/SimpleTopicDriver.java" target="_blank">SimpleTopicDriver</a> also starts two <a href="https://github.com/guycole/spring-messaging-demo/blob/master/src/main/java/com/digiburo/spring/demo/simple_aq/SimpleListener.java" target="_blank">listeners</a> and then writes a TextMessage. Both listeners will react to the message (property of being a topic).</div>
<div>
<br /></div>
<div>
<a href="https://github.com/guycole/spring-messaging-demo/blob/master/src/main/java/com/digiburo/spring/demo/aws_sqs/SqsQueueDriver.java" target="_blank">SqsQueueDriver</a> illustrates using <a href="http://nevado.skyscreamer.org/" target="_blank">Nevado</a> as a JMS adapter for <a href="http://aws.amazon.com/" target="_blank">Amazon Web Services</a> <a href="http://aws.amazon.com/sqs/" target="_blank">Simple Queue Service(SQS)</a>. Nevado is valuable because SQS does not expose a JMS API, yet many enterprise architectures are hosted on AWS and rely upon JMS.</div>
<div>
<br /></div>
<div>
<a href="https://github.com/guycole/spring-messaging-demo/blob/master/src/main/resources/sqs-queue-configuration.xml" target="_blank">SqsQueueDriver</a> also starts two <a href="https://github.com/guycole/spring-messaging-demo/blob/master/src/main/java/com/digiburo/spring/demo/aws_sqs/SqsListener.java" target="_blank">listeners</a> and then writes a TextMessage. Even though there are two listeners, only one will receive the text message (property of being a queue).</div>
guycolehttp://www.blogger.com/profile/13546414963444312679noreply@blogger.com0tag:blogger.com,1999:blog-1010221292729658742.post-22214317667111421812013-09-05T00:30:00.001-07:002013-09-05T00:53:01.253-07:00WxTrax: Example Android 4.x Application Using Android Studio/GradleFor your consideration I offer "WxTrax" which is a complete Android 4.x application that collects weather reports from the U.S. National Weather Service. WxTrax illustrates the following concepts:<br />
<ul>
<li>Employs Android 4.x constructs (i.e. loaders, fragments, etc)</li>
<li>Plays nice w/Android Studio (currently on preview version 0.2.6)</li>
<li>Builds using Gradle (currently 1.7)</li>
<li>Is decomposed into an application and a library </li>
<li>Uses Google Maps V2</li>
<li>AppWidget example</li>
<li>Weather stations and observations are stored in SqlLite using a ContentProvider</li>
</ul>
Complete sources are available on <a href="https://github.com/guycole/WxTrax" target="_blank">GitHub</a> <br />
<br />
The US National Weather Service (NWS) makes weather reports available as a XML based web service. Hourly weather observations are usually performed by automated stations colocated at airports, so the observations use the IATA location code (i.e. KPDX for Portland, KSEA for Seattle, KSFO for San Francisco, etc). To obtain the current observation for Los Angeles you would use the URL <a href="http://www.weather.gov/xml/current_obs/KLAX.xml" target="_blank">http://www.weather.gov/xml/current_obs/KLAX.xml</a><br />
<br />
WxTrax will allow you to specify stations of interest and collect these weather reports for you. WxTrax can also display a Google Map w/the station location.<br />
<br />
There is also the concept of a "favorite" station which always displays the most recent report on the "splash" page. If you display the associated AppWidget, the favorite station temperature is given.<br />
<br />
Now on to the sources...<br />
<br />
WxTraxLib contains code I wrote in 2010 for the first version of this application. There is no user interface code here, but it does contain the network support, weather observation collection, XML parser, ContentProvider, etc. I like to decompose my applications into modular components like this. The user interface tends to change quite a depending upon the product team while the supporting components tend to be more stable. Breaking a project into modules allows for reuse across multiple products and makes for easier testing of the "headless" pieces.<br />
<br />
WxTrax2 is new, freshly updated to use Android 4.x components. All the UI components reside in this module, and depends upon WxTraxLib.<br />
<br />
MainActivity exists to host fragments and handle the communication logic between them. Fragment switching is performed within TabHelper. You can add a station from the menu and a dialog will accept your command. StationListFragment will display the known stations. Selecting a station will show the collected observations (via ObservationListFragment). A long press on a station row will allow you to delete a station or select it as the "favorite" station. Selecting the "map" fragment allows Google Maps to display station locations.<br />
<br />
<br />guycolehttp://www.blogger.com/profile/13546414963444312679noreply@blogger.com0tag:blogger.com,1999:blog-1010221292729658742.post-84097217497734458492013-09-02T00:13:00.004-07:002013-09-02T00:14:23.557-07:00Android Fragment Tour - EncoreI have updated FragmentDemo <a href="https://github.com/guycole/FragmentDemo" target="_blank">(GitHub)</a> with a new Fragment (Fragment Five) that connects to a custom CursorAdapter. Fragment Four uses a custom SimpleCursorAdapter. Both example use Loaders/ContentProviders.guycolehttp://www.blogger.com/profile/13546414963444312679noreply@blogger.com0tag:blogger.com,1999:blog-1010221292729658742.post-6567143777870372132013-08-18T23:23:00.000-07:002013-08-18T23:31:12.646-07:00Android Fragment TourThe time has come to embrace Android fragments, especially since well over half of devices are now on Android 4.x. There are many tutorial applications available and here is one more on the pile. This post and supporting example application demonstrate:<br />
<ul>
<li>Use of Android fragments (i.e. Fragment, ListFragment, DialogFragment or PreferenceFragment.</li>
<li>Navigation between fragments and activities</li>
<li>Use of the ActionBar, TabListener and menu support. </li>
<li>Use of Custom ArrayAdapter</li>
<li>Use of Custom CursorAdapter</li>
<li>Using a ContentProvider/ContentResolver and Loader</li>
<li>Use of maven</li>
</ul>
Complete application sources are available on <a href="https://github.com/guycole/FragmentDemo" target="_blank">github</a>, the demonstration application was created on API 16 using Android Studio (thanks, JetBrains) and includes maven support. This demonstration does not use the compatability libraries so you will need API 14 or later to successfully run. <br />
<br />
At application start you should see these:<br />
<table>
<tbody>
<tr>
<!-- first screenshot -->
<td><table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="http://1.bp.blogspot.com/-fGqV--iqFBE/UhFmnfnar5I/AAAAAAAAC6Q/Wt2b2Qdmcw0/s1600/Screenshot_2013-08-18-17-18-45.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="320" src="http://1.bp.blogspot.com/-fGqV--iqFBE/UhFmnfnar5I/AAAAAAAAC6Q/Wt2b2Qdmcw0/s320/Screenshot_2013-08-18-17-18-45.png" width="160" /></a>
</td></tr>
<tr><td class="tr-caption" style="text-align: center;">Tab 1</td></tr>
</tbody></table>
</td>
<!-- second screenshot -->
<td><table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="http://2.bp.blogspot.com/-J03HhcjBHuE/UhFmnl_LMYI/AAAAAAAAC6U/ocAIERTUkAo/s1600/Screenshot_2013-08-18-17-19-43.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="320" src="http://2.bp.blogspot.com/-J03HhcjBHuE/UhFmnl_LMYI/AAAAAAAAC6U/ocAIERTUkAo/s320/Screenshot_2013-08-18-17-19-43.png" width="160" /></a>
</td></tr>
<tr><td class="tr-caption" style="text-align: center;">Tab 2</td></tr>
</tbody></table>
</td>
<!-- xxx -->
</tr>
</tbody></table>
<table>
<tbody>
<tr>
<!-- third screenshot -->
<td><table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="http://2.bp.blogspot.com/-A3F2QzRHm2E/UhFm2H2_WeI/AAAAAAAAC6g/jiCoV4-7hqo/s1600/Screenshot_2013-08-18-17-20-37.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="320" src="http://2.bp.blogspot.com/-A3F2QzRHm2E/UhFm2H2_WeI/AAAAAAAAC6g/jiCoV4-7hqo/s320/Screenshot_2013-08-18-17-20-37.png" width="160" /></a>
</td></tr>
<tr><td class="tr-caption" style="text-align: center;">Tab 3</td></tr>
</tbody></table>
</td>
<!-- fourth screenshot -->
<td><table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="http://2.bp.blogspot.com/-1q5L51F-ePs/UhFm_wsJmjI/AAAAAAAAC6o/uDyKWuVKHx8/s1600/Screenshot_2013-08-18-17-21-23.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="320" src="http://2.bp.blogspot.com/-1q5L51F-ePs/UhFm_wsJmjI/AAAAAAAAC6o/uDyKWuVKHx8/s320/Screenshot_2013-08-18-17-21-23.png" width="160" /></a>
</td></tr>
<tr><td class="tr-caption" style="text-align: center;">Tab 4</td></tr>
</tbody></table>
</td>
<!-- end row -->
</tr>
</tbody></table>
Tab 1 represents a simple form implemented as a Fragment. <a href="https://github.com/guycole/FragmentDemo/blob/master/fragment-demo/src/main/java/com/digiburo/fragdemo/ui/OneFragment.java" target="_blank">(source)</a><br />
<br />
Tab 2 illustrates a simple scrolling list of US states implemented as a ListFragment <a href="https://github.com/guycole/FragmentDemo/blob/master/fragment-demo/src/main/java/com/digiburo/fragdemo/ui/TwoFragment.java" target="_blank">(source)</a> with a resource <a href="https://github.com/guycole/FragmentDemo/blob/master/fragment-demo/res/values/us_states.xml" target="_blank">(source)</a> for the data source. A short press on a row brings up a detail view <a href="https://github.com/guycole/FragmentDemo/blob/master/fragment-demo/src/main/java/com/digiburo/fragdemo/ui/StateDetailFragment.java" target="_blank">(source)</a> and a long press prompts for delete. Short/long press interaction requires the use of a custom listener <a href="https://github.com/guycole/FragmentDemo/blob/master/fragment-demo/src/main/java/com/digiburo/fragdemo/ui/TwoListener.java" target="_blank">(source)</a> to dispatch a request to MainActivity <a href="https://github.com/guycole/FragmentDemo/blob/master/fragment-demo/src/main/java/com/digiburo/fragdemo/ui/MainActivity.java" target="_blank">(source)</a> for service. The delete is not actually performed, but does provide an opportunity to illustrate the use of a PreferenceFragment <a href="https://github.com/guycole/FragmentDemo/blob/master/fragment-demo/src/main/java/com/digiburo/fragdemo/ui/DeleteDialogFragment.java" target="_blank">(source)</a>
<br />
<br />
Tab 3 is another ListFragment <a href="https://github.com/guycole/FragmentDemo/blob/master/fragment-demo/src/main/java/com/digiburo/fragdemo/ui/ThreeFragment.java" target="_blank">(source)</a> example, this time w/a custom ArrayAdapter <a href="https://github.com/guycole/FragmentDemo/blob/master/fragment-demo/src/main/java/com/digiburo/fragdemo/ui/CustomArrayAdapter.java" target="_blank">(source)</a> and multiple row types (you can see from the above image there is a simple row w/a hex string and a more complex row w/radio buttons). The data source for Tab 3 comes from a ContentProvider <a href="https://github.com/guycole/FragmentDemo/blob/master/fragment-demo/src/main/java/com/digiburo/fragdemo/content/DataBaseProvider.java" target="_blank">(source)</a> whose values are randomly generated at application startup <a href="https://github.com/guycole/FragmentDemo/blob/master/fragment-demo/src/main/java/com/digiburo/fragdemo/FragDemoApplication.java" target="_blank">(source)</a>. One final feature of this example is that it employs a list header <a href="https://github.com/guycole/FragmentDemo/blob/master/fragment-demo/res/layout/header_three.xml" target="_blank">(source)</a> and footer <a href="https://github.com/guycole/FragmentDemo/blob/master/fragment-demo/res/layout/footer_three.xml" target="_blank">(source)</a>. The footer contains a EditText and Button widgets which can be detected within ThreeFragment.java <a href="https://github.com/guycole/FragmentDemo/blob/master/fragment-demo/src/main/java/com/digiburo/fragdemo/ui/ThreeFragment.java" target="_blank">(source)</a><br />
<br />
Tab 4 is yet another ListFragment example <a href="https://github.com/guycole/FragmentDemo/blob/master/fragment-demo/src/main/java/com/digiburo/fragdemo/ui/FourFragment.java" target="_blank">(source)</a>, this time w/a custom CursorAdapter <a href="https://github.com/guycole/FragmentDemo/blob/master/fragment-demo/src/main/java/com/digiburo/fragdemo/ui/CustomCursorAdapter.java" target="_blank">(source)</a> which employs a Loader fed from the ContentProvider <a href="https://github.com/guycole/FragmentDemo/blob/master/fragment-demo/src/main/java/com/digiburo/fragdemo/content/DataBaseProvider.java" target="_blank">(source)</a>. As shown in the illustration, the row type consists of an image and a string.<br />
<br />
All of these Fragments are "owned" by MainActivity <a href="https://github.com/guycole/FragmentDemo/blob/master/fragment-demo/src/main/java/com/digiburo/fragdemo/ui/MainActivity.java" target="_blank">(source)</a>
which also provides the ActionBar at the top of the display. The
ActionBar provides the tabs which are used for navigation between
Fragments. The tab navigation code resides within TabHelper <a href="https://github.com/guycole/FragmentDemo/blob/master/fragment-demo/src/main/java/com/digiburo/fragdemo/ui/TabHelper.java" target="_blank">(source)</a>.<br />
<br />
<table>
<tbody>
<tr>
<!-- next image row -->
<td><table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;">
<tbody>
<tr>
<td style="text-align: center;"><a href="http://1.bp.blogspot.com/-XbZ7xtr4XPU/UhF-FEndmcI/AAAAAAAAC64/rlvob3wgVbk/s1600/Screenshot_2013-08-18-19-03-22.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;">
<img border="0" height="320" src="http://1.bp.blogspot.com/-XbZ7xtr4XPU/UhF-FEndmcI/AAAAAAAAC64/rlvob3wgVbk/s320/Screenshot_2013-08-18-19-03-22.png" width="160" />
</a>
</td>
</tr>
<tr><td class="tr-caption" style="text-align: center;">About</td></tr>
</tbody>
</table>
</td>
<!-- second screenshot -->
<td><table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="http://4.bp.blogspot.com/-792zp5VWwUY/UhF-Hz7SRPI/AAAAAAAAC7A/bo8xmunWVOA/s1600/Screenshot_2013-08-18-19-04-09.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="320" src="http://4.bp.blogspot.com/-792zp5VWwUY/UhF-Hz7SRPI/AAAAAAAAC7A/bo8xmunWVOA/s320/Screenshot_2013-08-18-19-04-09.png" width="160" /></a>
</td></tr>
<tr><td class="tr-caption" style="text-align: center;">Settings</td></tr>
</tbody></table>
</td></tr>
</tbody></table>
<!-- end row -->
<br />
Depending upon your phone, you might see three vertical dots at the top right of the display (or you might have a menu key). There are two menu options, one for an "About" display and the other for "Settings" (user preferences). Option menu dispatch is provided by MainActivity which invokes MenuActivity to display the menu fragments.<br />
<br />
Note that MenuActivity <a href="https://github.com/guycole/FragmentDemo/blob/master/fragment-demo/src/main/java/com/digiburo/fragdemo/ui/MenuActivity.java" target="_blank">(source)</a> does not have tab navigation, so when a user selects a menu option the only way to return is the "back" button or by pressing the "FragDemo" icon on the ActionBar (top left). <br />
<br />
The "About" Fragment <a href="https://github.com/guycole/FragmentDemo/blob/master/fragment-demo/src/main/java/com/digiburo/fragdemo/ui/AboutFragment.java" target="_blank">(source)</a> is implemented as a WebView w/the HTML supplied as part of the application.<br />
<br />
The "Settings" Fragment <a href="https://github.com/guycole/FragmentDemo/blob/master/fragment-demo/src/main/java/com/digiburo/fragdemo/ui/SettingsFragment.java" target="_blank">(source)</a> is an example of a PreferenceFragment.<br />
<br />
FragmentDemo can be built and deployed entirely from the command line using the <a href="http://code.google.com/p/maven-android-plugin/" target="_blank">Android maven plugin.</a> I created FragmentDemo using the "Android-QuickStart-Archetype as described <a href="http://stand.spree.de/wiki_details_maven_archetypes" target="_blank">here</a> which was quite helpful.guycolehttp://www.blogger.com/profile/13546414963444312679noreply@blogger.com0tag:blogger.com,1999:blog-1010221292729658742.post-86416343236935183912013-05-20T23:50:00.000-07:002013-05-20T23:50:24.584-07:00What to code after "Hello, Android"This post is for those of you who have decided to join the thundering herd of computer nerds who have decided to code for Android. "Hello, Android" was easy... what happens next?<br />
<div>
<br /></div>
<div>
How about the "Three Activity" project? The "Three Activity" application demonstrates</div>
<div>
<ul>
<li>Navigation between three separate displays (each backed by a dedicated Activity)</li>
<li>How to pass arguments between Activity(s)</li>
<li>How to create and use a Button</li>
<li>How to create and use an EditText</li>
<li>How to use Android log statements<span id="goog_18710343"></span><span id="goog_18710344"></span><a href="http://www.blogger.com/"></a></li>
<li>Special guest appearance w/AndroidManifest.xml</li>
</ul>
<div>
<br /></div>
</div>
<div>
The "Three Activity" project is a simple application consisting of the three Activity(s) shown below.<br />
<div class="separator" style="clear: both; text-align: center;">
</div>
<br /></div>
<table>
<tbody>
<tr><td><table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="http://2.bp.blogspot.com/-rI5XyNja_zI/UZsELtQjRyI/AAAAAAAACsU/FyzPyKGeIIY/s1600/Screen+Shot+2013-05-20+at+10.18.59+PM.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" height="200" src="http://2.bp.blogspot.com/-rI5XyNja_zI/UZsELtQjRyI/AAAAAAAACsU/FyzPyKGeIIY/s200/Screen+Shot+2013-05-20+at+10.18.59+PM.png" width="120" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">StartActivity</td></tr>
</tbody></table>
</td><td><table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="http://3.bp.blogspot.com/-rUpgwGNg3JE/UZsEM3AlXHI/AAAAAAAACs0/skvCk0KHPso/s1600/Screen+Shot+2013-05-20+at+10.19.29+PM.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" height="200" src="http://3.bp.blogspot.com/-rUpgwGNg3JE/UZsEM3AlXHI/AAAAAAAACs0/skvCk0KHPso/s200/Screen+Shot+2013-05-20+at+10.19.29+PM.png" width="120" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">MiddleActivity</td></tr>
</tbody></table>
</td><td><table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="http://3.bp.blogspot.com/-syfP3GKio1k/UZsEMq7I9GI/AAAAAAAACso/z_AhTHeT_LE/s1600/Screen+Shot+2013-05-20+at+10.20.03+PM.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" height="200" src="http://3.bp.blogspot.com/-syfP3GKio1k/UZsEMq7I9GI/AAAAAAAACso/z_AhTHeT_LE/s200/Screen+Shot+2013-05-20+at+10.20.03+PM.png" width="120" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">EndActivity</td></tr>
</tbody></table>
</td></tr>
</tbody></table>
Complete source code for this example is contained on <a href="https://github.com/guycole/ThreeActivity">GitHub</a><br /><div class="separator" style="clear: both; text-align: center;">
</div>
<br />guycolehttp://www.blogger.com/profile/13546414963444312679noreply@blogger.com0tag:blogger.com,1999:blog-1010221292729658742.post-22666442357520407582012-12-03T02:40:00.001-08:002012-12-03T10:52:00.188-08:00Google Web Toolkit - First StepsHere is a short posting about Google Web Toolkit (GWT) w/a simple example application. Like any other evolving framework, GWT is a moving target. This posting was created in December, 2012 using GWT 2.5.0 - hopefully fresh enough for your needs. The key GWT components I wanted to explore include the Place, Activity and UiBinder classes.<br />
<div>
<br />
<div>
The example GWT application is available from <a href="https://github.com/guycole/GwtDemo1">GitHub</a> and should easily import into eclipse (and deploy to Google App Engine).</div>
<div>
<br /></div>
<div>
Below is a screenshot of the sample application, which illustrates a common use case: a banner image along the top and footer along the bottom w/a navigation bar on the left. The remaining (center space) is for content. Pressing a button within the navigation bar will cause the content panel to update.<br />
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="http://2.bp.blogspot.com/-xEqs434SWzE/ULxlfWECX1I/AAAAAAAACfA/GA4fJ5iMHkI/s1600/screenshot.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="229" src="http://2.bp.blogspot.com/-xEqs434SWzE/ULxlfWECX1I/AAAAAAAACfA/GA4fJ5iMHkI/s320/screenshot.png" width="320" /></a></div>
<div>
<div>
<br /></div>
</div>
</div>
</div>
<div>
Below is a UML class diagram to introduce the components of the sample application.</div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="http://4.bp.blogspot.com/-ZpxDk7LfTGw/ULxvbeZ4K8I/AAAAAAAACfQ/bhvQmkkj7Po/s1600/class2.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="166" src="http://4.bp.blogspot.com/-ZpxDk7LfTGw/ULxvbeZ4K8I/AAAAAAAACfQ/bhvQmkkj7Po/s320/class2.jpg" width="320" /></a></div>
<div>
<br /></div>
<div>
You can browse the sources at <a href="https://github.com/guycole/GwtDemo1">GitHub</a>. A brief tour of the sources follows.</div>
<div>
<br /></div>
<div>
<a href="https://github.com/guycole/GwtDemo1/blob/master/src/com/digiburo/gwtdemo1/client/GwtDemo1.java">GwtDemo1</a> extends EntryPoint, which is the usual entry point for a GWT module. I create an instance of <a href="https://github.com/guycole/GwtDemo1/blob/master/src/com/digiburo/gwtdemo1/client/AppShell.java">AppShell</a> and dispatch control via the run() method.</div>
<div>
<br /></div>
<div>
<a href="https://github.com/guycole/GwtDemo1/blob/master/src/com/digiburo/gwtdemo1/client/AppShell.java">AppShell</a> must persist for the duration of the application since it holds references to EventBus and various mappers that glue the application together. The run() method binds <a href="https://github.com/guycole/GwtDemo1/blob/master/src/com/digiburo/gwtdemo1/client/view/RootView.java">RootView</a> to the RootLayoutPanel (as discovered from <a href="https://github.com/guycole/GwtDemo1/blob/master/src/com/digiburo/gwtdemo1/client/GwtDemo1.java">GwtDemo1</a>) which will cause <a href="https://github.com/guycole/GwtDemo1/blob/master/src/com/digiburo/gwtdemo1/client/view/RootView.ui.xml">RootView.ui.xml</a> to be displayed. (The *.ui.xml files are all XML UiBinder files). </div>
<div>
<br /></div>
<div>
Creating <a href="https://github.com/guycole/GwtDemo1/blob/master/src/com/digiburo/gwtdemo1/client/view/RootView.ui.xml">RootView.ui.xml</a> will also create <a href="https://github.com/guycole/GwtDemo1/blob/master/src/com/digiburo/gwtdemo1/client/view/NavigationBar.ui.xml">NavigationBar.ui.xml</a> which contains the Hyperlinks necessary to update the content panel.</div>
<div>
<br /></div>
<div>
At this point the application is displayed and waiting for a Hyperlink event.</div>
<div>
<br /></div>
<div>
The sequence diagram below introduces event flow.</div>
<div class="separator" style="clear: both; text-align: center;">
<a href="http://3.bp.blogspot.com/-lhOe0nNxYVI/ULx9Ni-jZOI/AAAAAAAACfg/CoI5f5lIlyE/s1600/seq2.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="198" src="http://3.bp.blogspot.com/-lhOe0nNxYVI/ULx9Ni-jZOI/AAAAAAAACfg/CoI5f5lIlyE/s320/seq2.jpg" width="320" /></a></div>
<div>
Working from left to right on the sequence diagram, start w/the Hyperlink (contained within <a href="https://github.com/guycole/GwtDemo1/blob/master/src/com/digiburo/gwtdemo1/client/view/NavigationBar.ui.xml">NavigationBar.ui.xml</a>). Pressing a Hyperlink will generate a History frame which is delivered to <a href="https://github.com/guycole/GwtDemo1/blob/master/src/com/digiburo/gwtdemo1/client/HistoryHandler.java">HistoryHandler</a> for distribution to the PlaceController. PlaceController causes a PlaceChange event to be delivered to the ActivityManager which consults <a href="https://github.com/guycole/GwtDemo1/blob/master/src/com/digiburo/gwtdemo1/client/activity/AppPlaceHistoryMapper.java">AppPlaceHistoryMapper</a> and <a href="https://github.com/guycole/GwtDemo1/blob/master/src/com/digiburo/gwtdemo1/client/activity/ContentActivityMapper.java">ContentActivityMapper</a> to determine which Activity should be employed to update the content panel.</div>
<div>
<br /></div>
<div>
The diagram only shows "Content1" selection but the same process is simply replicated for Content1..Content4 scenarios.</div>
<div>
<br /></div>
<div>
<a href="https://github.com/guycole/GwtDemo1/blob/master/src/com/digiburo/gwtdemo1/client/activity/ContentActivityMapper.java">ContentActivityMapper</a> returns <a href="https://github.com/guycole/GwtDemo1/blob/master/src/com/digiburo/gwtdemo1/client/activity/Content1Activity.java">Content1Activity</a> to ActivityManager which in turn invokes start(). This action will cause <a href="https://github.com/guycole/GwtDemo1/blob/master/src/com/digiburo/gwtdemo1/client/view/Content1View.java">Content1View</a> (and companion UiBinder) to be instantiated and then applied to <a href="https://github.com/guycole/GwtDemo1/blob/master/src/com/digiburo/gwtdemo1/client/view/RootView.java">RootView</a> which causes the content panel to update.</div>
<div>
<br /></div>
<div>
I hope you find some utility w/the example. Good luck and enjoy GWT.</div>
guycolehttp://www.blogger.com/profile/13546414963444312679noreply@blogger.com0tag:blogger.com,1999:blog-1010221292729658742.post-51991878944957592492012-03-10T14:10:00.039-08:002012-03-11T15:27:55.854-07:00(Yet Another) Android NDK Blog PostingThe Android NDK (Native Developers Kit) augments the Android SDK and enables one to create portions of a Android application using C or C++ (you knew that or you would not be reading this).<br /><br />This blog post provides an introduction to NDK along w/some anecdotes and a working Android application.<br /><br />Note that I am writing this in March of 2012. The current SDK is version "r16" and the current ndk is version "r7b". My examples should be valid for the current versions. As always, these examples might not age well so YMMV.<br /><br />Some of you might be surprised to discover that Java existed before Android (relax, it's a joke). Java has always provided a mechanism to integrate with C/C++ applications called JNI (Java Native Interface). <a href="http://en.wikipedia.org/wiki/Java_Native_Interface">Wikipedia</a> provides a decent overview of JNI and Sun (now Oracle) provides a comprehensive introduction to JNI <a href="http://docs.oracle.com/javase/1.5.0/docs/guide/jni/">here.</a> Serious developers will want to read the "<a href="http://docs.oracle.com/javase/1.5.0/docs/guide/jni/spec/jniTOC.html">JNI Specification</a>" (also available of the Oracle web site.<br /><br />At runtime, your C/C++ objects will be linked and executed using the JVM. There is a cost to transition the Java/C barrier, make sure you do enough work on the C side to make the transition worth while. Of course, if you include JNI then you have excluded portability (because the C/C++ files must be compiled for every target platform). Portability is not much of a concern for Android since most targets are ARM platforms.<br /><br />In the early days of Java, JNI was a frequent requirement because many vendors had not yet created Java friendly libraries. The usual steps were:<br /><ol><li>Create "native" Java methods to wrap around C functions. I usually collect these in a common class called "JniWrapper" (or "NdkWrapper" for Android).<br /></li><li>Use the "javah" utility to generate a C header file based upon the contents of "JniWrapper" (i.e. "javah -jni java.class")<br /></li><li>Write a C wrapper to act as a bridge between C and Java, the contents of the wrapper correspond to the generated header file (from step 2). Variable conversion, etc. between C/Java is typically performed here.</li></ol><p>The above looks rather straight forward (and it is) but in practice some projects were quite difficult to complete and make stable (different threading models, etc). As Java came to dominate, there was better support for Java and less of a reason to employ JNI. Thanks to Android, this issue is receiving much more attention.<br /></p><p>When I design a JNI application, I break the functionality down into three use cases:</p> <ol><li>Java invokes C (most common example)<br /></li><li>C invokes Java (frequently asynchronous callbacks)</li><li>Shared variables (visible to both C and Java)</li></ol><p>I have created a sample Android NDK application to illustrate these use cases which can be found on <a href="https://github.com/guycole/playpen">GitHub</a> (more about the example later).</p><p>Another design issue relates to using objects as arguments. In general, I try to avoid using complicated containers as arguments. Instead I favor primitive types such as int (not Integer). Strings are the exceptions and JNI provides convenience mechanisms for handling String.</p><p>Now create a Java class to act as the interface between Java and C. Your C methods will be invoked by Java methods marked as "native" (these look like "abstract" methods). This class should also contain a call to "System.loadLibrary()" which will cause your C/C++ objects to be loaded within the JVM.<br /></p><p>The "javah" utility will generate a C header based upon "native" declarations within a Java class file. The resulting file looks something like this:</p><code>/* DO NOT EDIT THIS FILE - it is machine generated */<br />#include <jni.h><br />/* Header for class com_digiburo_example_native_demo_NdkWrapper */<br /><br />#ifndef _Included_com_digiburo_example_native_demo_NdkWrapper<br />#define _Included_com_digiburo_example_native_demo_NdkWrapper<br />#ifdef __cplusplus<br />extern "C" {<br />#endif<br />/*<br />* Class: com_digiburo_example_native_demo_NdkWrapper<br />* Method: nativeSetup<br />* Signature: ()V<br />*/<br />JNIEXPORT void JNICALL Java_com_digiburo_example_native_1demo_NdkWrapper_nativeSetup(JNIEnv *, jobject);<br />#ifdef __cplusplus<br />}<br />#endif<br />#endif<br /></code><br /><p>Note these important features:<br /></p><ol><li>The "jni.h" file which is distributed w/the JDK and provides Java data type definitions, etc.</li><li>JNIEXPORT and JNICALL are macros defined within jni.h<br /></li><li>The C method name looks like a Java signature (i.e. package name, method name).<br /></li><li>The C function will always have at least two arguments: the "JNIEnv" pointer and the "jobject" reference. "JNIEnv" points to the virtual machine and "jobject" points to the Java class which invoked the native method (frequently described as similar to "this").<br /></li><li>Remember the JVM cares about method signatures. Item #2 and item #3 come directly from the "native" declarations in Java and must match exactly or your method will not be invoked. </li></ol>Android NDK relies upon JNI and also provides Android toolchains, i.e. cross compilers for ARM/Intel targets and related libraries along w/a build environment that easily integrates your compiled C/C++ code into an Android APK. There are also a variety of sample applications which are worth your review.<p>While designing your NDK application note that only a small collection of libraries are distributed w/the NDK (library population varies w/NDK version). For example, I recently needed JPEG support but libjpeg.so is not part of the NDK. In this case you might have to build the libraries you need (be sure to build them using the appropriate cross compiler, etc). In my case I simply used the libjpeg headers and library from the Android platform sources. The point is: until you are a NDK master be sure to pad the schedule in case there is a surprise.</p><p>To integrate JNI w/your Android application is simple enough with recent versions of the NDK. Simply create an Android application in eclipse, then create a "jni" directory. The "jni" directory should be a peer to "src", "res", etc. and acts as the root directory for your C/C++ sources.</p><p>Eclipse also provides a C/C++ environment which will be handy for flipping between XML, Java and C/C++. My own preference is to do heavy lifting in emacs and my compiles on the command line.</p><p>To continue w/implementation, copy the "javah" generated header file to the "jni" directory and craft a source file to support it.<br /></p><p>The Android NDK provides a build system which greatly simplifies integrating w/a Android application. Build directives are contained within the "Android.mk" and an optional "Application.mk" files.</p><br /><code><br />#example Android.mk<br />LOCAL_PATH := $(call my-dir)<br />#<br />include $(CLEAR_VARS)<br />#<br />LOCAL_CFLAGS := -fexceptions<br />#<br />LOCAL_MODULE := digiburo-bridge<br />LOCAL_SRC_FILES := NdkWrapper.cpp<br />#<br />LOCAL_LDLIBS += -llog<br />#<br />include $(BUILD_SHARED_LIBRARY)<br /></code><br />Note these import features:<br /><ol><li>LOCAL_MODULE defines the name of your C/C++ library. This must match the name specified in System.loadLibrary().</li><li>LOCAL_SRC_FILES define source files<br /></li><li>LOCAL_LDLIBS specifies link path (in this case to Android logging).</li></ol><p>Compile within the "jni" directory by typing "ndk-build" which is a utility supplied w/the NDK.</p><p>Assuming a successful compile, you should see the results within your Android project in the "libs" and "obj" directories.</p><p>At this point you should be able to deploy and run your Android application using both Java and C.</p><p>I have created a sample Android NDK application called "NativeDemo" which is available from my <a href="https://github.com/guycole/playpen">GitHub</a> repository. NativeDemo provides examples for:</p><ol><li>Java calls C (NdkWrapper.nativeSetup(), NdkWrapper.nativeString(), NdkWrapper.nativeAdder())</li><li>C invokes Java (NdkWrapper.nativeVectorDemo() and NdkWrapper.callBack())</li><li>Shared variables (NdkWrapper._nativeBuffer)</li><li>Exception handling (NdkWrapper.exceptionDemo())</li><li>Demonstration of JNI_OnLoad() and JNI_OnUnload()<br /></li></ol>To compile and run NativeDemo:<br /><ol><li>You need all the usual Android development tools such as eclipse, Android SDK, ADT plugin and of course the Android NDK.</li><li>Import my <a href="https://github.com/guycole/playpen/tree/master/NativeDemo/jni">git repository</a> into your eclipse workspace.</li><li>From the command line, enter the "jni" directory and type "ndk-build" assuming you have the NDK, etc this should compile NdkWrapper.cpp and place the results in the "libs" and "objs" directories.</li><li>Now run the application from eclipse, it should deploy like any other application.</li><li>To see the results, use "adb logcat" - note that log messages are generated both from Java and from NdkWrapper.cpp<br /></li></ol>Hope this saves you some time. Good luck!guycolehttp://www.blogger.com/profile/13546414963444312679noreply@blogger.com1tag:blogger.com,1999:blog-1010221292729658742.post-81437967383257971912011-07-24T18:09:00.000-07:002011-07-24T19:30:11.445-07:00BeagleBoard for AndroidI wanted to learn more about Android internals without risking my phone. At first, I briefly considered the $399 dev phone offered by Google, but decided it would be more fun to have an evaluation board/kit rather than a complete device.<br /><br />There were several candidates but I quickly settled on the <a href="http://beagleboard.org/">BeagleBoard</a>-XM as sold by <a href="http://search.digikey.com/scripts/DkSearch/dksus.dll?PName?Name=296-25798-ND&Site=US&Lang=EN">DigiKey</a> for USD 149. (<a href="http://www.liquidware.com/">LiquidWare</a> had a booth at the San Mateo Maker Faire, and I was sorely tempted to purchase a Beagle embedded starter kit. Perhaps later...)<br /><br />The <a href="http://beagleboard.org/">BeagleBoard</a> site is a great resource and there is not much I can add beyond my personal anecdotes.<br /><br />What you get for $149 is a anti-static bag containing a small (approx 3 inch x 3 inch) PCB and a microSD card. There are no cables supplied.<br /><br />You can get a quick test of the board w/a RS-232, a USB cable and your trusty PC.<br /><br />First, install the microSD card which came w/the BeagleBoard.<br /><br />Second, the USB cable provides power, use the OTG ("On The Go") connector on the BeagleBoard. You should immediately see some LED's light up.<br /><br />Third, connect the RS-232 cable between the BeagleBoard and your PC. I am using Ubuntu 10.04 LTS w/MiniCom as a console. This step might take some experimentation, but it is working for me at 115200 8N1.<br /><br />There are two buttons on the PCB next to the USB sockets. (There is a BeagleBoard manual available as a PDF which illustrates the components). Press "reset" to stimulate console activity.<br /><br /><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/-gPd5m86aYO8/TizHVwPBJmI/AAAAAAAACL4/ATOEfktYnVo/s1600/Screenshot.png"><img style="float: left; margin: 0pt 10px 10px 0pt; cursor: pointer; width: 320px; height: 253px;" src="http://3.bp.blogspot.com/-gPd5m86aYO8/TizHVwPBJmI/AAAAAAAACL4/ATOEfktYnVo/s320/Screenshot.png" alt="" id="BLOGGER_PHOTO_ID_5633096410472719970" border="0" /></a>Here is a screen shot of the TI X-Loader starting to boot...<br /><br />Now that you have at least some interaction w/the BeagleBoard you can start adding additional devices.<br /><br />I purchased a HDMI cable in order to connect an old monitor to my BeagleBoard. I also use USB keyboard and USB mouse to interact w/the BeagleBoard.<br /><br />The BeagleBoard readily supports a variety of platforms, right now I am most interested in TI <a href="http://arowboat.wordpress.com/2011/04/01/ti-android-gingerbread-2-3-devkit-1-0/">arowboat</a> Android distribution (I expect to describe building arowboat in my next post).guycolehttp://www.blogger.com/profile/13546414963444312679noreply@blogger.com1tag:blogger.com,1999:blog-1010221292729658742.post-56229998468385701492010-03-12T23:34:00.000-08:002010-03-13T00:30:41.983-08:00Java Date MathDaylight savings time happens this weekend which provides a certain moment of truth for applications which must calculate the days between dates.<br /><br />There are 86400 seconds in 24 hours. A typical solution might be to convert the days to seconds since the epoch, then subtract them yielding the difference between days in seconds, then divide by 86400 to obtain the days.<br /><br />This algorithm fails because not all days are of the same duration.<br /><br />Julian dates offer a solution. Each day has a unique integer value and caculating the difference is a simple matter of subtraction. Astronomers also use a "julian date" - which represents time and date as a float. (Note: if an integer julian date triggers your Aspergers, please spare me the email. I know the difference).<br /><br />Example Gregorian/Julian routines are available in <a href="http://www.amazon.com/Numerical-Recipes-3rd-Scientific-Computing/dp/0521880688/ref=sr_1_1?ie=UTF8&s=books&qid=1268467022&sr=8-1">Numerical Recipes</a>. <a href="http://www.digiburo.com/%7Egsc/DateMath.java">Here </a>is a Java class which performs the same functions.<br /><br />To calculate the days between two dates:<br /><br />DateMath dm = new DateMath();<br />int jd1 = dm.gregorianToJulian(calendar1);<br />int jd2 = dm.gregorianToJulian(calendar2);<br />int delta = jd1-jd2;guycolehttp://www.blogger.com/profile/13546414963444312679noreply@blogger.com0tag:blogger.com,1999:blog-1010221292729658742.post-13019210620646658882010-01-23T15:10:00.000-08:002010-01-23T15:20:27.345-08:00Junk Or Repair?I have serveral Princeton monitors, including two VL-1919 monitors on my main LINUX development box.<br /><br />The power supplies on these monitors do not age gracefully, and I was a little irritated when both of my VL-1919 started to flake out within weeks of each other.<br /><br />To my surprise, there is someone who repairs these power supplies: go to eBay and search for "resurrectek" - they do a variety of repairs for a fixed rate.<br /><br />For $29 each I now have two happy monitors instead of $100+ for two new tubes plus the ewaste from my old displays.<br /><br />Back to work...guycolehttp://www.blogger.com/profile/13546414963444312679noreply@blogger.com0tag:blogger.com,1999:blog-1010221292729658742.post-42730270627545868242010-01-17T20:09:00.000-08:002010-01-18T11:18:56.940-08:00Mellow Panda and the BC-780-XLTThe Uniden <a href="http://www.universal-radio.com/catalog/scanners/0780.html">BC-780-XLT</a> is a oldie but goodie as radios go. Perform a Google search and you will see there is a lot of love for the 780. Thanks to eBay, I have a several of these radios and they are a lot of fun w/a computer. My only complaint would be the poor image rejection, especially the 2nd harmonic above the FM broadcast band.<br /><br />The 780 is too old for USB and uses a DB-9, which might be a problem since many new computers only have USB ports. I have had good luck w/the TRENDnet TU-S9 USB to RS-232 converter (also works w/my Icom PCR-1000). If you are connecting your 780 to Mellow Panda via USB, you can get the port assignment via dmesg (it will look something like "/dev/ttyUSB1"). This is the value you want for pandad.conf<br /><br />On the 780 itself, jack up the serial speed to 19.2K (all the way up). This also needs to be reflected in pandad.conf<br /><br />Bearcat commands follow a request/response cycle in that the computer issues a command/request and the radio responds. All commands/requests will generate a response from the radio like "OK" or "ERR" or a request specific response. If you issue a command using Mellow Panda and do not see a response, there is a connectivity problem.<br /><br />Note: the 780 will not respond to remote commands if the menu tree is displayed. Press the "menu" key to back out. Of course the RMT flag should also be visible on the display.<br /><br />There are several sources of information on the Bearcat Uniden <a href="http://www.freqofnature.com/index.php?m=Software&p=Uniden%20Protocols"> command set</a>. Most of the commands make sense, especially if you are familiar w/using the radio.<br /><br />Mellow Panda tries hard to make your radio accessible: you can exercise the radio by running pandad in the foreground or you can use the panda client. For example, the "SI" command will return system information such as the radio model and version.<br /><br />For pandad in foreground: <span style="font-size:85%;"><span style="font-family:courier new;">./pandad -x panda://device/raw/bc780.a/SI</span></span><br />For panda client: <span style="font-size:85%;"><span style="font-family:courier new;">./panda -r bc780.a -k raw/SI</span></span><br />Response looks like: <span style="font-size:85%;"><span style="font-family:courier new;">SI BC780XLT,0000000000,103</span><br /></span><br />The real fun starts when you need to string commands together to complete a task. Not everything you want to do has an explicit command. Happily, Mellow Panda makes it easy to experiment and I will provide examples of common 780 tasks.<br /><br />Note:several of these examples are already available as bash scripts in the Mellow Panda demo directory.<br /><br />Store a frequency and then assign a alphanumeric tag (visible in the radio display)<br /><span style=";font-family:courier new;font-size:85%;" >./panda -r radio_name -k "raw/PM005 01220000"<br />./panda -r radio_name -k "raw/TA C 005 Flight Watch"</span><br /><br />Define channel 5 as the priority channel<br /><span style="font-size:85%;"><span style="font-family:courier new;">./panda -r radio_name -k "raw/PC A004"</span></span><br /><br />Monitor a Motorola Type-2/800 trunk system using only the control channel<br /><span style="font-size:85%;"><span style="font-family:courier new;">./panda -r radio_name -k "raw/PM051 08541875"<br /></span><span style="font-family:courier new;">./panda -r radio_name -k "raw/KEY13H"<br /></span><span style="font-family:courier new;">./panda -r radio_name -k "raw/TCN B P1"</span><span style="font-family:courier new;"><br />./panda -r radio_name -k "raw/KEY00"<br /></span><span style="font-family:courier new;">./panda -r radio_name -k "raw/KEY13"</span><br /></span><br />Monitor a Motorola Type-2/800 trunk system by defining all associated frequencies<br /><span style="font-size:85%;"><span style="font-family:courier new;">./panda -r radio_name -k "raw/KEY11"</span><br /><span style="font-family:courier new;">./panda -r radio_name -k "raw/KEY02 3"</span><br /><span style="font-family:courier new;">./panda -r radio_name -k "raw/KEY02 2"</span><br /><span style="font-family:courier new;">./panda -r radio_name -k "raw/KEY02 1"</span><br /><span style="font-family:courier new;">./panda -r radio_name -k "raw/KEY02 1"<br /></span><span style="font-family:courier new;">./panda -r radio_name -k "raw/KEY11"<br /></span><span style="font-family:courier new;">./panda -r radio_name -k "raw/KEY11"</span><br /><span style="font-family:courier new;">./panda -r radio_name -k "raw/KEY11"</span><br /><span style="font-family:courier new;">./panda -r radio_name -k "raw/PM051 08541875"<br /></span><span style="font-family:courier new;">./panda -r radio_name -k "raw/KEY13H"</span><span style="font-family:courier new;"><br />--and more frequencies--</span><span style="font-family:courier new;"><br />./panda -r radio_name -k "raw/SB B"</span><span style="font-family:courier new;"><br />./panda -r radio_name -k "raw/KEY00"</span><br /><span style="font-family:courier new;">./panda -r radio_name -k "raw/KEY13"</span></span>guycolehttp://www.blogger.com/profile/13546414963444312679noreply@blogger.com1tag:blogger.com,1999:blog-1010221292729658742.post-86468457403031033422010-01-16T23:29:00.000-08:002010-01-17T01:22:45.957-08:00Project PandaI have released <a href="http://mellowpanda.sourceforge.net/">Mellow Panda</a> on SourceForge. <br /><br />Mellow Panda is a collection of applications which control radio receivers ("scanners") from LINUX via their RS-232/USB interfaces.<br /><br />Mellow Panda deploys as a daemon (pandad) and specialized clients. pandad is a generic gateway which exposes a TCP stream socket to accept client requests which are relayed to the radios via RS-232/USB. The response returns via the reciprocal path.<br /><br />pandad is generic and does not interpret the radio commands. Each radio model potentially has a different command set and this specialized knowledge is provided by the client. pandad can simultaneously support multiple radios, each a different model. I routinely drive a Icom PCR-1000, BC-780-XLT and a PRO-2052 all using the same instance of pandad (but each w/a dedicated client).<br /><br />A twist to this problem is that many models have an asynchronous messaging capability, i.e. the Uniden Bearcat radios will send a message when squelch breaks or trunk id. The Icom PCR-1000 family has a "bandscan" feature which can be used to produce a spectral graph. Each active radio has a UDP socket which broadcasts all traffic generated by the radio. Clients can issue requests via the TCP socket and accept the response either via TCP or get all messages via UDP.<br /><br />The panda protocol is a simple ASCII string. Even a telnet client is sufficient (I used a telnet client in the early stages for testing).<br /><br />Communication via a socket has all the usual benefits, sharing a scarce resource and flexibility. Clients can be implemented using any platform or language which is convenient. The pandad distribution has a command line client implemented in C which is useful for development/test and simple scripts.<br /><br />Other clients will follow as I get them ready to share. pandapy (python) is almost ready along w/pandaj (Java Swing) and pandalet (Tomcat Servlet). You are welcome to contribute additional clients to the project.<br /><br />Mellow Panda is part of Project Mellow which I am releasing as time permits.guycolehttp://www.blogger.com/profile/13546414963444312679noreply@blogger.com0tag:blogger.com,1999:blog-1010221292729658742.post-68772013101771512462009-11-08T16:17:00.000-08:002009-11-08T17:12:02.158-08:00Android Development on Sprint/HTC Hero and UbuntuI now have a shiny new HTC Hero from Sprint which I purchased just to experiment w/Google Android.<br /><br />My primary devbox is Ubuntu Intrepid. Sprint is still on Cupcake (Android platform 1.5). Still have not figured out how to "sync" between Ubuntu and Android, but development works just fine.<br /><br />The Hero connects to Ubuntu Intrepid via USB and it can be mounted as a file system.<br /><br /><h4>How to use the Hero as a development target.</h4><br /><br />On the Hero, select "Settings" then "Applications"<br/><br />Check the "Unknown Sources" box.<br/><br />Select the "Development" option.<br/><br />There are three options inside Development: "USB Debugging" "Stay awake" "Allow mock locations" - select to your taste (I enable all three). <br/><br /><br />On Ubuntu, I assume you have eclipse w/the ADT plugin.<br />From eclipse, navigate to the build configurations. There is a dialog entitled "Android Device Chooser" - select your Hero and then run. Your application should appear on the Hero.<br /><br /><p><br /><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_EJerrjVDuws/SvdqIAaB6II/AAAAAAAABvs/36VYJ72eBrI/s1600-h/Screenshot-Android+Device+Chooser+.png"><img style="float:left; margin:0 10px 10px 0;cursor:pointer; cursor:hand;width: 320px; height: 208px;" src="http://3.bp.blogspot.com/_EJerrjVDuws/SvdqIAaB6II/AAAAAAAABvs/36VYJ72eBrI/s320/Screenshot-Android+Device+Chooser+.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5401902963834873986" /></a><br /></p><br /><br /><br/><br/><br/><br/><br/><br /><br /><h4>How to mount your Hero as a USB drive from Ubuntu.</h4><br /><br />On your devbox, create /etc/udev/rules.d/51-android.rules<br /><br /><code><br />gsc@cornfed:66>pwd<br />/etc/udev/rules.d<br />gsc@cornfed:67>cat 51-android.rules <br />SUBSYSTEM=="usb", SYSFS{idVendor}=="0bb4", MODE="0666"<br /></code><br /><br />Connect the Hero to your devbox via USB. There should be some chatter in /var/log/messages about the new device. Something like this...<br /><br /><code><br />Nov 8 16:32:49 cornfed kernel: [185299.048021] usb 8-4: new high speed USB device using ehci_hcd and address 13<br />Nov 8 16:32:49 cornfed kernel: [185299.193667] usb 8-4: configuration #1 chosen from 1 choice<br />Nov 8 16:32:49 cornfed kernel: [185299.203424] scsi17 : SCSI emulation for USB Mass Storage devices<br />Nov 8 16:32:54 cornfed kernel: [185304.220343] scsi 17:0:0:0: Direct-Access HTC Android Phone 0100 PQ: 0 ANSI: 2<br />Nov 8 16:32:54 cornfed kernel: [185304.239535] sd 17:0:0:0: [sdc] Attached SCSI removable disk<br />Nov 8 16:32:54 cornfed kernel: [185304.239674] sd 17:0:0:0: Attached scsi generic sg3 type 0<br /></code><br /><br />On the Hero, pull down the status bar (i.e. push the Home symbol then touch the top of the display and drag your finger down). There should be a message saying "USB connected, select to enable". Press this. A dialog will appear warning about the mount. Select OK.<br /><br />At this point you should have a freshly mounted USB filesystem. There will be more chatter in /var/log/messages (like so...)<br /><br /><code>Nov 8 16:36:44 cornfed kernel: [185533.291475] sd 17:0:0:0: [sdc] 3862528 512-byte hardware sectors (1978 MB)<br />Nov 8 16:36:44 cornfed kernel: [185533.294342] sd 17:0:0:0: [sdc] Write Protect is off<br />Nov 8 16:36:44 cornfed kernel: [185533.299343] sd 17:0:0:0: [sdc] 3862528 512-byte hardware sectors (1978 MB)<br />Nov 8 16:36:44 cornfed kernel: [185533.301341] sd 17:0:0:0: [sdc] Write Protect is off<br />Nov 8 16:36:44 cornfed kernel: [185533.302919] sdc: sdc1<br /></code><br /><br />Of course, df(1) will also report the filesystem<br /><br /><code><br />gsc@cornfed:68>df -k<br />Filesystem 1K-blocks Used Available Use% Mounted on<br />--other filesystems deleted for clarity--<br />/dev/sdc1 1928992 631840 1297152 33% /media/disk<br /></code><br /><br />At this point, you can treat this like any other mounted file system. Huzza!<br /><br /><code><br />gsc@cornfed:69>cd /media/disk;ls<br />albumthumbs DCIM HTC Sync rosie_scroll<br />amazonmp3 download Music Wallpaper<br /></code>guycolehttp://www.blogger.com/profile/13546414963444312679noreply@blogger.com1tag:blogger.com,1999:blog-1010221292729658742.post-66004285715532937252009-11-02T04:31:00.000-08:002009-11-08T17:17:52.130-08:00Apple iPhone Tech Talks World Tour - San JoseI was lucky enough to get an invitation for the <a href="http://devworld.apple.com/events/iphone/techtalks"/>iPhone Tech Talks</a> held in San Jose on 29 October, 2009. The talks were held at the Hyatt in Santa Clara (off Great America Parkway). South bay is a 3 hour drive for me and with the Oakland Bay Bridge closure it might take even longer. I considered staying home to keep working on my next iPhone app. Attending was hanging by a thread, but I wanted to see the show and meet other iPhone developers. In the end, I went and I'm glad I did.<br /><br />Registration opened promptly at 0800. The registration lady really does ask for photo ID before issuing your badge and mandatory t-shirt. Apple put on a nice breakfast, coffee, fat pills and some fruit. 0800 is rather early for the valley and small talk was hard to drum up.<br /><br />Shortly before 0900 I was in the large conference room w/Blink-182 (and similar) on the soundtrack. Apple starts promptly and the keynote was a inspiring start for the day. The overall theme: iPhone is cool and popular, write great apps, make money. I like it.<br /><br />There short video promoting the iPhone and applications. Another video from the very big conglomerate why corporate IT is adopting the iPhone. The speaker had a steady stream of poster children for great apps. I rarely cruise the app store, so this was beneficial for me.<br /><br />One example was "things" which features a "companion app" - i.e. there is a desktop app and a iPhone app and they share data. I have an application in development which also needs to share data between iPhone and desktop, but I didn't know this arrangement had a name. <br /><br />There are 3 technical tracks available after the keynote. I stayed in the big hall for "Effective iPhone Development" parts 1 and 2. The talk was good, but I already knew most of the content. One small item I didn't know: don't prefix vars w/a underscore because Apple uses these internally and there might be a collision. <br /><br />Apple provided a catered box lunch w/a sandwich, salad, etc. Not bad. By lunchtime, people were awake and ready to talk. I picked a table that contained the oldest looking people (being ancient myself) and struck up a conversation. After working from home most of the year, it was fun to meet some new people.<br /><br />One distressing item: I asked everybody I met if they were able to sustain themselves by creating iPhone apps. The answer was a resounding "no". Perhaps we are all beginners and just haven't paid our dues. Perhaps there really isn't much money in the app store. Not certain, but to actually earn a living from creating iPhone applications seems to be a rare accomplishment.<br /><br />After lunch I sat through the "Mastering OpenGL ES for iPhone (p1)" - probably should have just snuck out to my truck for a nap. I don't remember much about this talk. If linear algebra scares you... well... perhaps you shouldn't be doing OpenGL. Anyway, less hand wringing/intimidation and more bit twiddling would be an improvement.<br /><br />Next was "Testing and Debugging Your iPhone Application" - which was disappointingly light. I did get some new information though: when you ship an app, keep the .dSym file for crash analysis (makes sense, I should have already discovered that one). Secondly, Snow Leopard (which I have yet to install) has clang which does a thorough job w/static source analysis. I resolve to upgrade to Snow Leopard as soon as I ship my next app.<br /><br />Finally, "Maximizing iPhone App Performance" which was also on the light side, but still worth an hour. I probably should have attended the networking presentation instead.<br /><br />Apple wrapped up the day w/a wine and cheese reception.<br /><br />Wrapup: the Apple people are accessible, they take questions between sessions and there is a lab where you can bring them specific examples for consultation. The developer outreach is nice, and Apple certainly deserves praise for the effort. There is no paper and AFAIK the slides/sources are not available on the web. Take your notes and be quick. <br /><br />There are videos from previous "tech talks" available on the Apple developer web site. There is a fair amount of old material, but there is enough new material to make them worth attending.<br /><br />One factoid tossed out: all the attendees had published iPhone apps (in my case, a very minor application). Write that app if you want to score an invite next year.<br /><br />It was an inspiring day, even if I didn't meet anybody who has struck gold on the appstore. Maybe next year...guycolehttp://www.blogger.com/profile/13546414963444312679noreply@blogger.com0