Sunday, May 21, 2017

Android/BeagleBone interaction via Bluetooth RFCOMM

In this posting I will demonstrate how to connect between an Android phone and a BeagleBone Black Wireless (BBBW) using bluetooth RFCOMM (basically a wireless RS-232 link).

For this demonstration I have created an Android application which
  1. discovers bluetooth devices
  2. connects to a bluetooth device
  3. toggles LED connected to bluetooth device
The BBBW hosts a python application which accepts a connection request and manages three LED which are remotely controlled from the Android application.

BBBW Preparation

  1. Flash your BBBW w/the latest image, currently  bone-debian-8.7-iot-armhf-2017-03-19-4gb.img
  2. apt-get update; apt-get upgrade
  3. apt-get install python-bluez
  4. Pull the python sources from github
  5. Add green/red/yellow LED to BBGW.  You can changes the port assignments in perky_blue.py
    LEDGPIO
    green48
    red49
    yellow60
  6. As root, make BBBW discoverable for bluetooth by invoking bluetoothctl(1)
  7.  You might see an error like the screenshot below:
  8. If so, you need to tweak /etc/systemd/system/dbus-org.bluez.service.   Change this line:  ExecStart=/usr/lib/bluetooth/bluetoothd  to ExecStart=/usr/lib/bluetooth/bluetoothd -C Save the file and reboot.  Start again at item 6.
  9. BBBW should now be ready for Android commands.

Android Preparation

  1. Pull the source from github 
  2. Compile using Android Studio and deploy to phone.
  3. Ensure bluetooth is enabled on your phone
  4. Start the application ("PerkyBlue")
  5. Press "Start Discovery" and wait ~20 seconds for completion.
  6. 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.
  7. You can now press for red/yellow/green LED toggle, the corresponding LED should light on BeagleBone.

Tuesday, January 24, 2017

BeagleBone Green Wireless IoT Developer Prototyping Kit

Have you noticed that Google Cloud is promoting an IoT Developer Prototyping Kit which features the BeagleBone Green Wireless (BBGW)? I purchased one, because I was hoping for better instructions on using the Grove System w/BBGW.

Sadly, the only documentation included w/the proto kit is a lame brochure w/a cloud solutions URL with unhelpful Arduino examples.  Yaay for Arduino, but I bought the BBGW kit.

Fine.  Challenge accepted.  Here are some notes on using BBGW and Grove System.

There are dedicated images for the BBGW and any Debian reference (within this post) is tied to bone-debian-8.6-seeed-iot-armhf-2016-11-06-4gb.img

"Grove is a modular, standardized connector prototyping system." 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 Grove Base Cape (included in proto kit) because this offers more connections and access to the ADC.

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.

There has to be software to control the interfaces and BBGW Grove promotes MRAA as a wrapper to the BBGW devices.  MRAA comes w/the Debian Seeed image and has (yet another) pin encoding scheme.  Look here for pin mapping.  The Debian Seeed image also has example python code in /usr/share/mraa/examples/python

Start easy w/a GPIO demo "blink-io8.py"

import mraa
import time


# Using BBG GPIO_51
x = mraa.Gpio(62)
x.dir(mraa.DIR_OUT)

while True:
  x.write(1)
  time.sleep(0.2)
  x.write(0)
  time.sleep(0.2)


Note the "mraa.Gpio(62)" which maps to P9_16 on BBGW and has a dedicated socket on the Grove Base Cape (look at the middle row, the GPIO are silk screened next to the Grove sockets).

Use the 3 axis accelerometer from the proto kit as an I2C example.  One of the Seeed example worked, scroll to item "03 How to use Grove - 3-Axis digital Accelerometer (16g)" for a python example.

Now for an ADC example, look at this Seeed project (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:
import time
import pyupm_grove as grove

light = grove.GroveLight(1)
temp = grove.GroveTemp(3)

while True:
 print light.name() + " raw value is %d" % light.raw_value() + ", which is roughly %d" % light.value() + " lux"
 celsius = temp.value()
 fahrenheit = celsius * 9.0/5.0 + 32.0
 print "%d degrees Celsius, or %d degrees Fahrenheit" % (celsius, fahrenheit)
 time.sleep(2)

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:
import mraa
import time

x = mraa.Gpio(68)
x.dir(mraa.DIR_IN)

while True:
 time.sleep(1)
 if x.read() > 0:
  print 'button press'
 else:
  print 'button not press'


BeagleBone Black vs BeagleBone Green

Yet another post comparing the BeagleBone Green Wireless (BBGW) to the BeagleBone Black.

Mouser has a great (hardware) comparison.

The links on the BBGW documentation pamphlet are mostly wrong, but you can find the BBGW wiki here (worth a visit).

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.  There are now 4 USB ports which are tall and will interfere w/most capes.  

There are dedicated images for the BBGW and any Debian reference (within this post) is tied to bone-debian-8.6-seeed-iot-armhf-2016-11-06-4gb.img

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.

BBGW $SLOTS is at /sys/devices/platform/bone_capemgr/slots.
root@beaglebone:~# cat $SLOTS
0: PF----  -1
1: PF----  -1
2: PF----  -1
3: PF----  -1



Sunday, January 15, 2017

BeagleBone Green Wireless as a LAMP Server

This post demonstrates how to configure a BeagleBone Green Wireless (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.

Flash your BBGW w/the latest image.  I am using "Jessie for SeeedStudio BeagleBone GreenWireless" (bone-debian-8.6-seeed-iot-armhf-2016-11-06-4gb.img).

After updating the BBGW image, log in to configure WiFi using connmanctl(1), there are example instructions in /etc/network/interfaces.

Now that you have internet connectivity, update the software using apt-get(8):
  • "apt-get update"
  • "apt-get upgrade"
Perform a gratuitous reboot for luck.

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.  

I don't need a captive portal for my purposes, so login to BBGW and invoke "apt-get remove wifidog-gateway" then reboot.

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.

/etc/default/bb-wl18xx contains some tweakable parameters, such as SSID base.

/tmp/hostapd-wl18xx.conf is the actual hostapd(8) configuration file, note the wpa_passphrase "BeagleBone"


SoftAp0 is the WAP device:
root@beaglebone:/etc/default# ifconfig SoftAp0
SoftAp0   Link encap:Ethernet  HWaddr b0:d5:cc:ff:65:be  
          inet addr:192.168.8.1  Bcast:192.168.8.255  Mask:255.255.255.0
          inet6 addr: fe80::b2d5:ccff:feff:65be/64 Scope:Link
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:5220 errors:0 dropped:3 overruns:0 frame:0
          TX packets:703 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000 

          RX bytes:1328274 (1.2 MiB)  TX bytes:122059 (119.1 KiB)

From your laptop, connect to the BeagleBone device just as you would any other WAP.

Apache is configured for port 8080.  Verify you can connect to apache2(8) by visiting http://192.168.8.1:8080/ with your browser.

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.

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).

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.

Wednesday, December 28, 2016

Temperature Sensing w/BeagleBone Black and Adafruit PT100 RTD

Here is a simple example of collecting temperature w/BeagleBone Black (BBB) and the Adafruit PT100 RTD 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.

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.  


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.


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.  


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.

Schematic of temperature sensor demonstration

My PT100 came w/three wires ending w/a blue and two red terminals.  I only needed the blue and one of the red terminals.

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).


root@beaglebone:~# echo $SLOTS
/sys/devices/bone_capemgr.9/slots
root@beaglebone:~# cat $SLOTS
 0: 54:PF--- 
 1: 55:PF--- 
 2: 56:PF--- 
 3: 57:PF--- 
 4: ff:P-O-L Bone-LT-eMMC-2G,00A0,Texas Instrument,BB-BONE-EMMC-2G
 5: ff:P-O-- Bone-Black-HDMI,00A0,Texas Instrument,BB-BONELT-HDMI
 6: ff:P-O-- Bone-Black-HDMIN,00A0,Texas Instrument,BB-BONELT-HDMIN
root@beaglebone:~# echo "BB-ADC" > $SLOTS
root@beaglebone:~# cat $SLOTS
 0: 54:PF--- 
 1: 55:PF--- 
 2: 56:PF--- 
 3: 57:PF--- 
 4: ff:P-O-L Bone-LT-eMMC-2G,00A0,Texas Instrument,BB-BONE-EMMC-2G
 5: ff:P-O-- Bone-Black-HDMI,00A0,Texas Instrument,BB-BONELT-HDMI
 6: ff:P-O-- Bone-Black-HDMIN,00A0,Texas Instrument,BB-BONELT-HDMIN
 7: ff:P-O-L Override Board Name,00A0,Override Manuf,BB-ADC

To read an ADC sample:
root@beaglebone:~# cd /sys/bus/iio/devices/iio:device0
root@beaglebone:/sys/bus/iio/devices/iio:device0# ls
dev              in_voltage2_raw  in_voltage5_raw  name       uevent
in_voltage0_raw  in_voltage3_raw  in_voltage6_raw  power
in_voltage1_raw  in_voltage4_raw  in_voltage7_raw  subsystem
root@beaglebone:/sys/bus/iio/devices/iio:device0# cat in_voltage0_raw
2441

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).

Graph illustrates temperature change is linear (and suggests a conversion model).  

To convert ADC to temperature use: 822 - 0.329512(ADC value)

Table (below) illustrates observed vs calculated temperatures.  Real world rarely match calculated world, but these values seem close enough for my intended application.


ADCObserved CCalculated C
2479105.14
24371518.98
24242023.26
24192524.91
24033030.18
23893534.80
23784038.42
23584545.01
23475048.64
23325553.58
23186058.19
22996564.45
22847069.39
22677575.00
22518080.27
22358585.54
22189091.14
22089594.44
219510098.72


Thursday, December 22, 2016

AWS IoT and BeagleBone Green Wireless

This post demonstrates how to configure a BeagleBone Green Wireless for Amazon Web Services "Internet of Things" using the AWS CLI.

The ingredients:
  • AWS Account
  • BeagleBone Green Wireless (BBGW)
    • Working WiFi
    • Flashed w/image bone-debian-8.6-seeed-iot-armhf-2016-11-06-4gb.img
    • apt-get update
    • apt-get upgrade
Install AWS CLI on BBGW.  Perform the following steps:
  • Create a IAM user for the BeagleBone
    • download the access key ID/secret access key
  • Install AWS CLI
    • pip install awscli
  • Configure AWS CLI (using the access key ID/secret access key from above)
    • aws configure
  • Verify AWS CLI installation by performing simple command
    • aws s3 ls (s3 directories are returned)
Generate security certificates:
  • mkdir aws_certs
  • cd aws_certs
  • openssl genrsa -out privateKey.pem 2048
  • openssl req -new -key privateKey.pem -out cert.csr
  • aws iot create-certificate-from-csr --certificate-signing-request file://cert.csr --set-as-active > certOutput.txt
  • grep certificateId certOutput.txt
  • aws iot describe-certificate --certificate-id <certificateId from last step> --output text --query certificateDescription.certificatePem > cert.pem
Create a policy and attach generated certificate:
  • Create policy document (policy.doc)
    {
    "Version": "2012-10-17",
    "Statement": [{
    "Effect": "Allow",
    "Action":["iot:*"],
    "Resource": ["*"]
    }]
    }
  • aws iot create-policy --policy-name PubSubToAnyTopic --policy-document file://policy.doc
  • grep certificateArn certOutput.txt
  • aws iot attach-principal-policy --principal <certifcateArn from last step> --policy-name "PubSubToAnyTopic" 
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".
Alternatively, ask for certificates using AWS CLI:
  • aws iot list-certificates
Register your BeagleBone (thing) and attach to Principal (policy):
  • aws iot create-thing --thing-name bbgw
  • aws iot attach-thing-principal --thing-name bbgw --principal  <certifcateArn from previous step>
At this point you should be able to see the thing in the AWS console.  From the AWS IoT page, select "Registry/Things"
Alternatively, ask for things using AWS CLI:
  • aws iot list-things
Update BBGW status:
  • aws iot update-thing --thing-name bbgw --attribute-payload attributes={key1=value1}
Verify update:
  • aws iot list-things

Sunday, December 18, 2016

Infrared "break beam" detection using BeagleBone Black and Adafruit 2167

Here 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 Adafruit 2167 is an excellent choice.

The example provided by Adafruit is for the Arduino.  Here is a simple example using the BBB.

Schematic of "break beam" demo.
  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.

root@beaglebone:~# cd /sys/class/gpio
root@beaglebone:/sys/class/gpio# echo 115 > export
root@beaglebone:/sys/class/gpio# cd gpio115
root@beaglebone:/sys/class/gpio/gpio115# echo in > direction
root@beaglebone:/sys/class/gpio/gpio115# cat value
1
root@beaglebone:/sys/class/gpio/gpio115# cat value
0

Sunday, April 24, 2016

AWS API Gateway and Lamba (Python) Demonstration

I have a customer interested in AWS API Gateway and Lambda (Python), so I created a small demonstration application to explore this option.

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:
  • Employs Cloud Formation as much as possible
  • Python (instead of node.js) Lambda function

Sunday, June 1, 2014

Google App Engine Development Environment on Mavericks w/IntelliJ and maven

Google 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:
  1. OSX 10.9
  2. Google App Engine 1.9.5
  3. Java 1.7
  4. Maven 3.1
  5. IntelliJ Idea 13
  6. Objectify 5
Note: example application is located on github.

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 - DO NOT get the latest Java 1.7 (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 Stack Overflow.

You should be able to obtain results similar to this:
gsc@duckman:72>java -version
java version "1.7.0_25"
Java(TM) SE Runtime Environment (build 1.7.0_25-b15)
Java HotSpot(TM) 64-Bit Server VM (build 23.25-b01, mixed mode)

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 Stack Overflow to the rescue.  

You should be able to obtain results similar to this:
gsc@duckman:73>mvn -v
Apache Maven 3.1.1 (NON-CANONICAL_2013-11-17_20-36_gsc; 2013-11-17 20:36:09-0800)
Maven home: /Users/gsc/local/apache-maven-3.1.1
Java version: 1.7.0_25, vendor: Oracle Corporation
Java home: /Library/Java/JavaVirtualMachines/jdk1.7.0_25.jdk/Contents/Home/jre
Default locale: en_US, platform encoding: UTF-8
OS name: "mac os x", version: "10.9.3", arch: "x86_64", family: "mac"
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

Google provides the guestbook 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 Google shows the old (now wrong) command to start/deploy on a local development server.  Assuming you have this directory structure:
gsc@duckman:89>ll
total 32
drwxr-xr-x  8 gsc  staff   272 Jun  1 10:21 ./
drwxr-xr-x  7 gsc  staff   238 Jun  1 10:38 ../
-rw-r--r--  1 gsc  staff   106 Jun  1 10:21 .gitignore
-rw-r--r--  1 gsc  staff   121 Jun  1 10:21 README.md
drwxr-xr-x  6 gsc  staff   204 Jun  1 11:47 guestbook-ear/
drwxr-xr-x  6 gsc  staff   204 Jun  1 11:47 guestbook-war/
-rw-r--r--  1 gsc  staff   583 Jun  1 10:21 guestbook.iml
-rw-r--r--  1 gsc  staff  1009 Jun  1 10:21 pom.xml

The correct command to start/deploy on a local development server is:
gsc@duckman:90>mvn -pl guestbook-ear appengine:devserver                                 
When you see "[INFO] INFO: Dev App Server is now running" then you should be able to visit the guestbook application at http://localhost:8080 and the GAE console is on http://localhost:8080/_ah/admin (guestbook screenshot below)




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.

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.


Now we need a project.  You can continue to use the original guestbook application or consider my derivative version from github.  If you are interested in a quick introduction to objectify then use my version.

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, Stack Overflow is probably your best resource for assistance.

Ensure you have the "GAE Integration" plugin enabled.  The following screenshots might help in comparing your environment from mine.
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.

At this point you should now be able to work on a GAE/J application using IntelliJ (including the debugger).  Only objectify remains to be explored.

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

To use objectify I have added Greeting.java as an Entity and GreetingDao.java as a DAO.  I also modified guestbook.jsp and SignGuestbookServlet.java to use the DAO (and objectify) rather than the datastore directly.

This concludes my short tour of making a small GAE project and I hope it saved you some time.

Sunday, April 27, 2014

Hybrid Android Applications w/WebView

Many 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).

This post illustrates the use of WebView along w/WebViewClient and WebChromeClient.  I have created a small demonstration application ("AndroidWebView") which is available on github.

AndroidWebView has four tabs to demonstrate different use cases (screenshots below).

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 AboutFragment.java was extremely simple to implement.

"About" tab selection
"Client" tab selection
The second tab ("Client") reads a remote web page and manages interaction w/the remote server using a WebViewClient.  Again ClientFragment,java is small and simple.

DemoWebViewClient.java 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".

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 NewsDialogFragment.java rather than perform the usual HTTP GET.  This illustrates the use case of HTML content invoking an Android View.

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:

DemoWebViewClient(20221): interceptRequest:http://www.digiburo.com/mobi/db_index.html
DemoWebViewClient(20221): pageStarted:http://www.digiburo.com/mobi/db_index.html
DemoWebViewClient(20221): load:http://www.digiburo.com/mobi/db_index.html
DemoWebViewClient(20221): interceptRequest:http://www.digiburo.com/css/stylesheet2.css
DemoWebViewClient(20221): load:http://www.digiburo.com/css/stylesheet2.css
DemoWebViewClient(20221): interceptRequest:http://www.google-analytics.com/ga.js
DemoWebViewClient(20221): load:http://www.google-analytics.com/ga.js
DemoWebViewClient(20221): interceptRequest:http://www.digiburo.com/grafix/home_logo.png
DemoWebViewClient(20221): load:http://www.digiburo.com/grafix/home_logo.png
DemoWebViewClient(20221): interceptRequest:http://www.digiburo.com/grafix/canvas1.png
DemoWebViewClient(20221): load:http://www.digiburo.com/grafix/canvas1.png
DemoWebViewClient(20221): interceptRequest:http://www.google-analytics.com/__utm.gif? //deleted
DemoWebViewClient(20221): load:http://www.google-analytics.com/__utm.gif? //deleted
DemoWebViewClient(20221): pageFinished:http://www.digiburo.com/mobi/db_index.html







The third tab ("JS") illustrates interaction w/JavaScript.

JavaScriptFragment.java creates a WebChromeClient  DemoWebChromeClient.java 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.

JavaScriptFragment.java relies upon DemoJavaScript.java 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.

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 bridge.html which writes a log entry back to Java.

The fourth tab ("Simple") SimpleFragment.java demonstrates the trivial use case of reading a remote file without WebViewClient or WebChromeClient.  

Sunday, April 13, 2014

Updated BackProp1 Now Available

I have recently updated the back propagation neural network "backprop1."

BackProp1 is a derivative of an image classification project I delivered in 2001.  It has been available on  SourceForge 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:
  1. demo1 is a point classifier which can determine if a point is above or below the line y = -5x + 2
  2. demo2 is the XOR classifier
  3. 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.
Get the latest version of backprop1 on github.

This new offering includes:
  1. Demo3 now should look OK on any platform (was effectively broken on OS X).
  2. Now builds w/gradle.

Friday, December 27, 2013

Spring Messaging w/JMS and Nevado

I have recently created some small demonstration applications to illustrate how to use Spring Messaging with ActiveMQ and Nevado/AWS as JMS providers.

Complete sources are available on GitHub.  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 aws.properties with your account information.

Since there is plenty of Spring documentation available, I'll skip the tutorial and directly address the sources on GitHub.

SimpleQueueDriver starts two listeners and then writes a TextMessage.  Even though there are two listeners, only one will receive the text message (property of being a queue).

SimpleTopicDriver also starts two listeners and then writes a TextMessage.  Both listeners will react to the message (property of being a topic).

SqsQueueDriver illustrates using Nevado as a JMS adapter for Amazon Web Services Simple Queue Service(SQS).  Nevado is valuable because SQS does not expose a JMS API, yet many enterprise architectures are hosted on AWS and rely upon JMS.

SqsQueueDriver also starts two listeners and then writes a TextMessage.  Even though there are two listeners, only one will receive the text message (property of being a queue).

Thursday, September 5, 2013

WxTrax: Example Android 4.x Application Using Android Studio/Gradle

For 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:
  • Employs Android 4.x constructs (i.e. loaders, fragments, etc)
  • Plays nice w/Android Studio (currently on preview version 0.2.6)
  • Builds using Gradle (currently 1.7)
  • Is decomposed into an application and a library
  • Uses Google Maps V2
  • AppWidget example
  • Weather stations and observations are stored in SqlLite using a ContentProvider
Complete sources are available on GitHub

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 http://www.weather.gov/xml/current_obs/KLAX.xml

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.

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.

Now on to the sources...

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.

WxTrax2 is new, freshly updated to use Android 4.x components.  All the UI components reside in this module, and depends upon WxTraxLib.

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.


Monday, September 2, 2013

Android Fragment Tour - Encore

I have updated FragmentDemo (GitHub) with a new Fragment (Fragment Five) that connects to a custom CursorAdapter.  Fragment Four uses a custom SimpleCursorAdapter.  Both example use Loaders/ContentProviders.

Sunday, August 18, 2013

Android Fragment Tour

The 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:
  • Use of Android fragments (i.e. Fragment, ListFragment, DialogFragment or PreferenceFragment.
  • Navigation between fragments and activities
  • Use of the ActionBar, TabListener and menu support.
  • Use of Custom ArrayAdapter
  • Use of Custom CursorAdapter
  • Using a ContentProvider/ContentResolver and Loader
  • Use of maven
Complete application sources are available on github, 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.

At application start you should see these:
Tab 1
Tab 2
Tab 3
Tab 4
Tab 1 represents a simple form implemented as a Fragment.  (source)

Tab 2 illustrates a simple scrolling list of US states implemented as a ListFragment (source) with a resource (source) for the data source.  A short press on a row brings up a detail view (source) and a long press prompts for delete.  Short/long press interaction requires the use of a custom listener (source) to dispatch a request to MainActivity (source) for service.  The delete is not actually performed, but does provide an opportunity to illustrate the use of a PreferenceFragment (source)

Tab 3 is another ListFragment (source) example, this time w/a custom ArrayAdapter (source) 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 (source) whose values are randomly generated at application startup (source).  One final feature of this example is that it employs a list header (source) and footer (source).  The footer contains a EditText and Button widgets which can be detected within ThreeFragment.java (source)

Tab 4 is yet another ListFragment example (source), this time w/a custom CursorAdapter (source) which employs a Loader fed from the ContentProvider (source).  As shown in the illustration, the row type consists of an image and a string.

All of these Fragments are "owned" by MainActivity (source) 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 (source).

About
Settings

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.

Note that MenuActivity (source) 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). 

The "About" Fragment (source) is implemented as a WebView w/the HTML supplied as part of the application.

The "Settings" Fragment (source) is an example of a PreferenceFragment.

FragmentDemo can be built and deployed entirely from the command line using the Android maven plugin.  I created FragmentDemo using the "Android-QuickStart-Archetype as described here which was quite helpful.

Monday, May 20, 2013

What 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?

How about the "Three Activity" project?  The "Three Activity" application demonstrates
  • Navigation between three separate displays (each backed by a dedicated Activity)
  • How to pass arguments between Activity(s)
  • How to create and use a Button
  • How to create and use an EditText
  • How to use Android log statements
  • Special guest appearance w/AndroidManifest.xml

The "Three Activity" project is a simple application consisting of the three Activity(s) shown below.

StartActivity
MiddleActivity
EndActivity
Complete source code for this example is contained on GitHub

Monday, December 3, 2012

Google Web Toolkit - First Steps

Here 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.

The example GWT application is available from GitHub and should easily import into eclipse (and deploy to Google App Engine).

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.


Below is a UML class diagram to introduce the components of the sample application.


You can browse the sources at GitHub.  A brief tour of the sources follows.

GwtDemo1 extends EntryPoint, which is the usual entry point for a GWT module.  I create an instance of AppShell and dispatch control via the run() method.

AppShell 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 RootView to the RootLayoutPanel (as discovered from GwtDemo1) which will cause RootView.ui.xml to be displayed.  (The *.ui.xml files are all XML UiBinder files).  

Creating RootView.ui.xml will also create NavigationBar.ui.xml which contains the Hyperlinks necessary to update the content panel.

At this point the application is displayed and waiting for a Hyperlink event.

The sequence diagram below introduces event flow.
Working from left to right on the sequence diagram, start w/the Hyperlink (contained within NavigationBar.ui.xml).  Pressing a Hyperlink will generate a History frame which is delivered to HistoryHandler for distribution to the PlaceController.  PlaceController causes a PlaceChange event to be delivered to the ActivityManager which consults AppPlaceHistoryMapper and ContentActivityMapper to determine which Activity should be employed to update the content panel.

The diagram only shows "Content1" selection but the same process is simply replicated for Content1..Content4 scenarios.

ContentActivityMapper returns Content1Activity to ActivityManager which in turn invokes start().  This action will cause Content1View (and companion UiBinder) to be instantiated and then applied to RootView which causes the content panel to update.

I hope you find some utility w/the example.  Good luck and enjoy GWT.