Thursday, April 3, 2014

Java 8 Features Part 2

In a previous post I covered the features Parallel Operations and Method References newly available in Java 8. But the most significant and effecting feature is the Lambda Expressions. Lambda Expressions is a vast subject and was available in many other programming languages for sometime now. Java being an Object oriented programming language (with the exception of primitives of course) didn't support this up until its 1.8.0 version.

Problem (Or at least lack of efficiency) : Java was always Object oriented mostly methods are merely used to implement behavior or provide getters or setters. And more importantly a method can not exists without it being inside of a Class. This is a strong OOP Principle and has been having no problem for developers also.

Except! when you want to do this;

    public static void main(String[] args) {
        new Thread(new Runnable() { 
            public void run() {
                System.out.println("Hello, World!");
            }
        }).start();
    }

Well this code doesn't look any harm but as you can see for Just to pass the implementation which is in the Runnable.run() you need to create an anonymous class. In a scenario where you have different type of Classes and accepting Interfaces as arguments such in Swing ActionListener this can become a headache. Languages such as Javascript allows passing of functions around which eliminates this type of unnecessary codes. But Java didn't support it for good reasons.

Solution : Lambda Expressions to the Rescue! Lambda Expressions allows you to pass in Methods as if Java supports Global Methods. Enabling the flexibility of not defining anonymous classes and keeping the code clean and simple.

    public static void main(String[] args) {
        new Thread(() -> { System.out.println("Hello, World!"); }).start();
    }

What the HTML! is that?. Your inner Java coder would have screamed looking at that code. But fear not, not only this code compiles but it also runs and produces the exact same result.

Basically Lambda Expressions enables the developer to define a method at the location of where it is required or have a reference to a Method (This was covered in previous post). This feature enables the developer to simplify the code. Lambda Expression is a really vast area and can not be covered in one blog post. So I highly recommend you to read the links in the references section.

References

  • Lambda Expressions - http://docs.oracle.com/javase/tutorial/java/javaOO/lambdaexpressions.html

Wednesday, March 26, 2014

Java 8 Features Part 1

"Change is the only thing that doesn't change". This statement explains well anything and Java is not an exception in this regard. Java version 8 is released officially and you can download it from Oracle. There are some significant changes introduced in Java 8 and following are some of those;
  1. Parallel Operations - Parallel Operations for JVMs running on top of Multi Core Platforms
  2. Method References - Ability to pass in a Method as a Reference. 
  3. Lambda Expressions - Biggest Syntax Changes to Java Ever
So I'll start off with Parallel Operations and make my way down on each topic. 

Parallel Operations have been introduced to leverage the Multiple CPUs available in almost every modern computer. Operations such as Sorting could become significantly faster if Multiple CPUs were used. The Arrays.parallel* methods provide these functions.

import java.util.Arrays;

public class ParallelOperations {

    public static void main(String[] args) {
        Integer[] ints = Util.generateRandomIntegers();
        sort(ints);
        Util.display(ints);
        ints = Util.generateRandomIntegers();
        parallelSort(ints);
        Util.display(ints);
    }

    public static void sort(Integer[] ints) {
        long startTime = System.currentTimeMillis();
        Arrays.sort(ints);
        long endTime = System.currentTimeMillis();
        System.out.printf("sort() Finished in %d milliseconds\n",
                (endTime - startTime));
    }

    public static void parallelSort(Integer[] ints) {
        long startTime = System.currentTimeMillis();
        Arrays.parallelSort(ints);
        long endTime = System.currentTimeMillis();
        System.out.printf("parallelSort() Finished in %d milliseconds\n",
                (endTime - startTime));
    }

}


And passing method references can be done as following;

import java.util.Arrays;
import java.util.Comparator;
import java.util.function.BiConsumer;
import java.util.function.Consumer;

public class MethodReferences {

    public static void main(String[] args) {
        Integer[] ints = Util.generateRandomIntegers();
        // Passing Arrays.sort static method as an argument
        sort(Arrays::sort, ints);
        Util.display(ints);
        ints = Util.generateRandomIntegers();
        // Passing Arrays.parallelSort static method as an argument
        sort(Arrays::parallelSort, ints);
        Util.display(ints);
        String[] strings = new String[] {"one", "TWO", "tHree"};
        // Passing Arrays.parallelSort static method and String.compareTo instance method as an arguments
        sort(Arrays::sort, String::compareTo, strings);
        Util.display(strings);
        strings = new String[] {"ball", "apple", "cat"};
        // Passing Arrays.parallelSort static method and String.compareToIgnoreCase instance method as an arguments
        sort(Arrays::parallelSort, String::compareToIgnoreCase, strings);
        Util.display(strings);
    }
    
    public static void sort(Consumer<Integer[]> sorter, Integer[] values) {
        sorter.accept(values);
    }
    
    public static void sort(BiConsumer<String[], Comparator<String>> sorter, Comparator<String> comparator, String[] values) {
        sorter.accept(values, comparator);
    }
}

References
  • Java 8 Compiler support for Eclipse Kepler - https://wiki.eclipse.org/JDT/Eclipse_Java_8_Support_For_Kepler

Tuesday, March 25, 2014

Tiny Url with Redis

As part of work, I was asked to research about Redis, a Distributed Key-Value Persistence Store developed to make caching extremely fast. So far I have found the following by going through documentation, Redis;
  1. An In-memory Key-Value persistence store with off the shelf advanced data structures and algorithms
  2. Supports Hashes (Tables), Lists, Sets, Sorted Sets and of course Key-Value pairs
  3. Enables I/O concurrency but no execution parallelism (Single threaded engine).
  4. Supports command pipelining for lesser network roundtrips.
  5. Supports transactions on demand by queuing commands.
  6. Supports Custom Script Execution (Similar to Stored Procedures)
  7. Supports Publish/Subscribe on topics
Redis stands out from Memcached because of its built-in datastructures and operations such as Lists, Sets, Hashes and Sorting functions. Redis is widely used in alot of applications which requires high performance such Twitter, Instagram, Stackoverflow and many more.

To get some hands on experience on Redis I wrote a simple Tiny Url application using Redis and Spring MVC. Two Hash data structures are used in my application to store both the Url Code to Url Mapping and Url Code to Click Counts. 
  • tinyurls - To store Url Code to Url Mapping
  • tinyurls:clicks - To store Url Code to Click Counts
The controller for the application looks as the following. Where jedisClient is an instance of Jedis, a Java Client for Redis. 

package com.shazin.tinyurl;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.inject.Inject;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.servlet.ModelAndView;

import redis.clients.jedis.Jedis;
import redis.clients.jedis.TransactionBlock;
import redis.clients.jedis.exceptions.JedisException;

@Controller
@RequestMapping("/")
public class TinyUrlController {

    private static final String CLICKS = "tinyurls:clicks";

    private static final String TINY_URLS = "tinyurls";

    @Inject
    private Jedis jedisClient;

    @RequestMapping(value = "create", method = RequestMethod.POST)
    public ModelAndView create(@RequestParam("url") String url,
            HttpServletRequest request) {
        ModelMap map = new ModelMap();
        String tinyUrl = null;
        Long timeInMillis = System.currentTimeMillis();
        String urlKey = Long.toHexString(timeInMillis);
        jedisClient.hset(TINY_URLS, urlKey, url);
        jedisClient.hset(CLICKS, urlKey, "0");

        tinyUrl = generateTinyUrl(request, urlKey);

        map.put("tinyurl", tinyUrl);
        return new ModelAndView("home", map);
    }

    public String generateTinyUrl(HttpServletRequest request, String urlKey) {
        String tinyUrl;
        tinyUrl = new StringBuilder()
                .append((request.isSecure() ? "https://" : "http://"))
                .append(request.getServerName()).append(":")
                .append(request.getServerPort())
                .append(request.getContextPath()).append("/u/").append(urlKey)
                .toString();
        return tinyUrl;
    }

    @RequestMapping(value = "u/{urlKey}", method = RequestMethod.GET)
    public ModelAndView forwardUrl(@PathVariable("urlKey") String urlKey, HttpServletResponse response) {
        String destinationUrl = null;
        ModelMap map = new ModelMap();
        String url = jedisClient.hget(TINY_URLS, urlKey);
        if(url != null && url.length() > 0) {
            jedisClient.hincrBy(CLICKS, urlKey, 1);
            map.put("url", url);
            destinationUrl = "redirect";
        } else {
            map.put("errorMsg", "Invalid Code in Url!");
            destinationUrl = "home";
        }
        
        return new ModelAndView(destinationUrl, map);
    }
    
    @RequestMapping(value="/", method=RequestMethod.GET)
    public ModelAndView home() {
        return new ModelAndView("home");
    }
    
    @RequestMapping(value="/clicks", method=RequestMethod.GET)
    public ModelAndView clicks(HttpServletRequest request) {
        ModelMap map = new ModelMap();
        Map<String, String> clickCounts = jedisClient.hgetAll(CLICKS);
        
        Map<String, String> counts = new HashMap<String, String>();
        
        for(Map.Entry<String, String> entry:clickCounts.entrySet()) {
            counts.put(generateTinyUrl(request, entry.getKey()), entry.getValue());
        }
        
        map.put("clickCounts", counts);
        
        return new ModelAndView("clicks", map);
    }
}


And the home.jsp looks as the following.



<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<html>
<head>
<title>Tiny Url</title>
<link href="${pageContext.request.contextPath}/resources/main.css" type="text/css" rel="stylesheet"/>
</head>
<body>
    <form id="urlShortenerForm" action="${pageContext.request.contextPath}/create" method="POST">
        <center style="margin-top: 10%">
            <c:if test="${errorMsg != null}">
                <p style="color: red;">
                    <b>${errorMsg}</b>
                </p>
            </c:if>            
            <p>Shorten any url!</p>
            <c:if test="${tinyurl != null}">
                <p>
                    <b>The Tiny Url is <a href="${tinyurl}">${tinyurl}</a></b>
                </p>
            </c:if>
            <p>
                <textarea id="url" name="url" rows="5" cols="50"></textarea>
            </p>
            <p>
                <input type="button" onclick="validateUrl()" value="Shorten" />
            </p>
            <p>
                <a href="${pageContext.request.contextPath}/clicks">Clicks Count</a>
            </p>
        </center>
    </form>
</body>
<script type="text/javascript">
    function validateUrl() {
        var textArea = document.getElementById("url");
        var valid = false;
        var value = textArea.value;
        if(value.length > 0) {
            var httpIndex = value.toLowerCase().indexOf("http");
            var columnIndex = value.indexOf(":");
            var slashIndex = value.indexOf("/");        
            if(httpIndex > -1 && columnIndex > -1 && slashIndex > -1) {
                valid = true;
            }
        }
        if(valid) {
            var urlShortenerForm = document.getElementById("urlShortenerForm");
            urlShortenerForm.submit();
        } else {
            alert("Invalid Url, Please enter a valid Url");
            textArea.value = "";
            textArea.focus();
        }
    }
</script>
</html>

After submitting a URL, this how the Tiny URL will look like.


The clicks.jsp will look like the following


<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<html>
<head>
<title>Tiny Url Click Counts</title>
<link href="${pageContext.request.contextPath}/resources/main.css" type="text/css" rel="stylesheet"/>
<style type="text/css">
table
{
border-collapse:collapse;
}
table, td
{
border: 1px solid black;
text-align: center;
}
th {
background: aqua;
}
</style>
</head>
<body>
    <center style="margin-top: 10%">
        <p>Click Counts</p>

        <p>
        <table border="1">
            <tr>
                <th>Url</th>
                <th>Click Count</th>
            </tr>
            <c:choose>
                <c:when test="${clickCounts.size() != 0}">
                    <c:forEach items="${clickCounts}" var="clickCount">
                        <tr>
                            <td><a href="${clickCount.key}">${clickCount.key}</a></td>
                            <td>${clickCount.value}</td>
                        </tr>
                    </c:forEach>
                </c:when>
                <c:otherwise>
                    <tr>
                        <td colspan="2">No clicks found</td>
                    </tr>
                </c:otherwise>
            </c:choose>

        </table>
        </p>

        <p>
            <a href="${pageContext.request.contextPath}">Back</a>
        </p>
    </center>
</body>
</html>

Finally the redirect.jsp will use a Javascript to redirect to the destination URL.

<html>
    <script type="text/javascript">
        window.location = "${url}";
    </script>
    <b>Redirecting Please wait...</b>
</html>

So in the backend the Url Code is generated using the Current Time in Milliseconds converted to Hexadecimal, and stored with the URL in tinyurls hash along with the click count which is 0 in tinyurls:clicks hash. And when the generated tiny url is clicked the corresponding url is retrieved from tinyurls hash based on the Url Code and tinyurls:clicks is incremented by one based on Url Code. Finally the user is redirected to Original URL. 

For this to work redis-server must be running!

This is just a basic example of the capabilities of Redis but is a good starting point. Hoping to learn further!


Friday, February 28, 2014

Custom Hibernate NamingStrategy

As part of my work my lead asked me to find a way to dynamically pre-pend a prefix to all the Hibernate Entities which uses JPA @Entity Annotation. This is to create a way to implement a flexible, customizable way to generate Entities which can be used across different projects by just changing the prefix.

So after some googling I found a link [1] where it is explained how to use a Custom NamingStrategy but it didn't quite do the exact my lead was looking for because it worked only with @Entity annotated classes which do not have @Table annotation. But my lead wanted to keep the @Table annotation and he wanted the @JoinTable annotation names also to be prefixed.

So after some trial and error I came up with the following changes with a Custom implementation of org.hibernate.cfg.ImprovedNamingStrategy and one hibernate configuration.

import org.hibernate.cfg.ImprovedNamingStrategy;

public class CustomNamingStrategy extends ImprovedNamingStrategy {
    
    private String prefix = "customprefix_";
    
    public String tableName(String tableName) {
        return _prefix(super.tableName(tableName));
    }
    
    public void setPrefix(String prefix) {
        this.prefix = prefix;
    }
    
    private String _prefix(String table) {
        return prefix + table;
    }

}


and following configuration for hibernate

<prop key="hibernate.ejb.naming_strategy">CustomNamingStrategy</prop>

  1. http://www.petrikainulainen.net/programming/tips-and-tricks/implementing-a-custom-namingstrategy-with-hibernate/

Thursday, February 27, 2014

Spring Security Custom FilterChainProxy Configuration

I have worked with Spring Security extensively for the past six months as part of my current job. But my work mostly involved configuring the most important FilterChainProxy of Spring Security using namespaces. But I wanted to dig deeper and to see how the internals of the Spring Security FilterChainProxy so I completely read the Spring Security Documentation for version 3.1.4.RELEASE and realized that in fact I can configure a custom FilterChainProxy given that I define the following filters which are a must have for the FilterChainProxy.
  1. SecurityContextPersistenceFilter
  2. ExceptionTranslationFilter
  3. FilterSecurityInterceptor
The document had a small snippet of declaring these inside of the custom FilterChainProxy but that didn't show the complete set of beans required to get the FilterChainProxy working. So I wanted to get the bottom of it so I configured it myself by going through documentation.

Basically you can have a working FilterChainProxy with the name springSecurityFilterChain by just using the following Spring Declarations using security namespace.

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:security="http://www.springframework.org/schema/security"
    xsi:schemaLocation="http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-3.1.xsd
        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

     <security:http security="none" pattern="/resources/**" />
     <security:http auto-config="true" use-expressions="true">
        <security:intercept-url pattern="/login*"
            access="isAnonymous()" />
        <security:intercept-url pattern="/**"
            access="isAuthenticated()" />
        <security:form-login login-page="/login"
            default-target-url="/" always-use-default-target="true"
            authentication-failure-url="/login?error=true" />
        <security:logout invalidate-session="true"
            delete-cookies="JSESSIONID" logout-success-url="/login" />
    </security:http>

    <security:authentication-manager alias="authenticationManager">
        <security:authentication-provider
            user-service-ref="userService">
            <security:password-encoder hash="md5"
                base64="true">
                <security:salt-source user-property="salt" />
            </security:password-encoder>
        </security:authentication-provider>
    </security:authentication-manager>
    
</beans>

But as you can see here I have set auto-config attribute of security:http namespace to true in order to generate all the required configurations of Filters for me. This is easy but not the most flexible declaration.

So the same thing can be declared explicitly without using the security namespace as follows.


<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:security="http://www.springframework.org/schema/security"
    xsi:schemaLocation="http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-3.1.xsd
        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

    <security:authentication-manager alias="authenticationManager">
        <security:authentication-provider
            user-service-ref="userService">
            <security:password-encoder hash="md5"
                base64="true">
                <security:salt-source user-property="salt" />
            </security:password-encoder>
        </security:authentication-provider>
    </security:authentication-manager>

    <bean id="springSecurityFilterChain" class="org.springframework.security.web.FilterChainProxy">
        <constructor-arg>
            <list>
                <security:filter-chain pattern="/login**" filters="none"/>
                <security:filter-chain pattern="/resources/**" filters="none"/>
                <security:filter-chain pattern="/**"
                    filters="securityContextPersistenceFilterWithASCTrue,    
                                                          logoutFilter,                                                
                                                             formLoginFilter,                                                              
                                                             formLoginExceptionTranslationFilter,
                                                             filterSecurityInterceptor" />
            </list>
        </constructor-arg>
    </bean>

    <bean id="securityContextPersistenceFilterWithASCTrue"
        class="org.springframework.security.web.context.SecurityContextPersistenceFilter">
        <constructor-arg>
            <bean class="org.springframework.security.web.context.HttpSessionSecurityContextRepository"/>
        </constructor-arg>
    </bean>
    
    <bean id="formLoginExceptionTranslationFilter"
        class="org.springframework.security.web.access.ExceptionTranslationFilter">
        <constructor-arg>
            <bean
                class="org.springframework.security.web.authentication.LoginUrlAuthenticationEntryPoint">
                <constructor-arg value="/login"/>                
            </bean>
        </constructor-arg>
        <property name="accessDeniedHandler">
            <bean
                class="org.springframework.security.web.access.AccessDeniedHandlerImpl">
                <property name="errorPage" value="/exception" />
            </bean>
        </property>
    </bean>

    <bean id="formLoginFilter"
        class="org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter">
        <property name="authenticationManager" ref="authenticationManager"/>
        <property name="allowSessionCreation" value="true"/>
        <property name="authenticationSuccessHandler">
            <bean class="org.springframework.security.web.authentication.SimpleUrlAuthenticationSuccessHandler">
                <constructor-arg value="/"/>
                <property name="alwaysUseDefaultTargetUrl" value="true"/>
            </bean>
        </property>
        <property name="authenticationFailureHandler">
            <bean class="org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler">
                <constructor-arg value="/login?error=true"/>
            </bean>
        </property>
    </bean>

    <bean id="filterSecurityInterceptor"
        class="org.springframework.security.web.access.intercept.FilterSecurityInterceptor">
        <property name="authenticationManager" ref="authenticationManager" />
        <property name="accessDecisionManager" ref="accessDecisionManager" />
        <property name="runAsManager" ref="runAsManager" />
        <property name="securityMetadataSource">
            <security:filter-security-metadata-source use-expressions="true">
                <security:intercept-url pattern="/**"
                    access="isAuthenticated()" />
            </security:filter-security-metadata-source>
        </property>
    </bean>

    <bean id="accessDecisionManager"
        class="org.springframework.security.access.vote.AffirmativeBased">
        <constructor-arg>
            <list>
                <bean class="org.springframework.security.access.vote.RoleVoter"/>
                <bean class="org.springframework.security.web.access.expression.WebExpressionVoter"/>
            </list>
        </constructor-arg>
        <property name="allowIfAllAbstainDecisions" value="false"/>
    </bean>

    <bean id="runAsManager"
        class="org.springframework.security.access.intercept.RunAsManagerImpl">
        <property name="key" value="TELCO_RUN_AS"/>
    </bean>
        
    <bean id="logoutFilter" class="org.springframework.security.web.authentication.logout.LogoutFilter">
        <constructor-arg value="/login"/>        
        <constructor-arg>
            <list>
                <bean class="org.springframework.security.web.authentication.logout.CookieClearingLogoutHandler">
                    <constructor-arg>
                        <list>
                            <value>JSESSIONID</value>
                        </list>                        
                    </constructor-arg>
                </bean>
                <bean class="org.springframework.security.web.authentication.logout.SecurityContextLogoutHandler"/>
            </list>
        </constructor-arg>
    </bean>
    
</beans>


Wow Spring Security namespace is a real life saver when it comes to configuring right? but critics might ask why declare explicitly when it generates.

  1. Gives more control over the configurations
  2. Enables to understand the flow
  3. Enables flexibility
For this Custom FilterChainProxy to work it must be named similar to the filter name of DelegatingFilterProxy in the web.xml configuration, for example with the following configuration;

<filter>
        <filter-name>springSecurityFilterChain</filter-name>
        <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
    </filter>

    <filter-mapping>
        <filter-name>springSecurityFilterChain</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>
The explicitly declared FilterChainProxy must be named springSecurityFilterChain.

Trackbacks/Pings

Saturday, February 1, 2014

Interfacing Force Sensing Resistor with Arduino

Today I got the time to test a Arduino compatible component I had for a long time. It is a 1.5" Force Sensing Resistor (FSR) cable of measuring the force applied onto its surface area. The following shows a really small demo/tutorial on how to connect the FSR to Arduino and read its force value. More details on the FSR can be found here.


Above is the Fritzing layout of the connected Arduino and FSR. And below you can see the photo of the FSR connected.


The following the Arduino sketch which reads the value of the FSR and prints in the Serial.

int value = 0;

void setup() {
  Serial.begin(9600); 
}

void loop() {
  value = analogRead(A0);
  Serial.print("Force : ");
  Serial.print(value, DEC);
  Serial.print("\n");
  delay(100); 
}

Output of the Serial is as follows.



References 
  1. http://bildr.org/2012/11/force-sensitive-resistor-arduino/

Monday, January 13, 2014

Face following RC Car using Android + Arduino + USB Host Shield

I have been working with an Arduino + RC Car setup for a quite a sometime in this post and this post. Finally I wanted to do something with it by integrating it to an Android phone. After some googling I found that I can connect the Android + Arduino using USB Host Shield in two different ways. One is where the Arduino + USB Host Shield acts as an Android Accessory (I have a done a post using that too) and the other one is where the Arduino + USB Host Shield is connected through Android Debug Bridge (ADB). I used the ADB method because I have already tried the Accessory method.

The uniqueness in this approach is that many people have done RC Car Hacks using Arduino to control the Remote Control not directly the car itself. The following hack directly controls the car instead of sending commands using the Remote control.

So I have already connected the RC Car's control pins to Arduino (Check out the previous posts) and so started coding my arduino sketch which is below.

 #include <SPI.h>  
 #include <Adb.h>  
 #define FW_PIN 3  
 #define BW_PIN 4  
 #define LF_PIN 5  
 #define RT_PIN 6  
 // Adb connection.  
 Connection * connection;  
 // Elapsed time for ADC sampling  
 long lastTime;  
 void actuate(int pin);  
 void turnLeft();  
 void turnRight();  
 // Event handler for the shell connection.   
 void adbEventHandler(Connection * connection, adb_eventType event, uint16_t length, uint8_t * data)  
 {  
  int i;  
  // Data packets contain two bytes, one for each servo, in the range of [0..180]  
  if (event == ADB_CONNECTION_RECEIVE)  
  {  
   Serial.println(data[0], DEC);  
   if(data[0] == 0x01) {  
     actuate(FW_PIN);  
   } else if(data[0] == 0x02) {  
     actuate(BW_PIN);   
   } else if(data[0] == 0x03) {  
     turnLeft();   
   } else if(data[0] == 0x04) {  
     turnRight();   
   }  
  }  
 }  
 void setup()  
 {  
  Serial.begin(9600);  
  // Note start time  
  lastTime = millis();  
  pinMode(FW_PIN, OUTPUT);  
  pinMode(BW_PIN, OUTPUT);  
  pinMode(LF_PIN, OUTPUT);  
  pinMode(RT_PIN, OUTPUT);  
  // Initialise the ADB subsystem.   
  ADB::init();  
  // Open an ADB stream to the phone's shell. Auto-reconnect  
  connection = ADB::addConnection("tcp:4567", true, adbEventHandler);   
 }  
 void loop()  
 {  
  lastTime = millis();  
  // Poll the ADB subsystem.  
  ADB::poll();  
  delay(50);  
 }  
 void actuate(int pin) {  
  digitalWrite(pin, HIGH);  
  delay(50);  
  digitalWrite(pin, LOW);   
 }  
 void turnLeft() {  
  digitalWrite(LF_PIN, HIGH);  
  actuate(FW_PIN);  
  digitalWrite(LF_PIN, LOW);  
 }  
 void turnRight() {  
  digitalWrite(RT_PIN, HIGH);  
  actuate(FW_PIN);  
  digitalWrite(RT_PIN, LOW);  
 }  

And for the Android Face detection app I made use of OpenCV Sample - face detection app which is available in the OpenCV for Android SDK version 2.4.7 samples directory. I added the microbridge server source codes which I downloaded from ADB Microbridge google code site and did slight following modifications to OpenCV Android Face detection app.

AndroidManifest.xml

 <uses-permission android:name="android.permission.INTERNET">  

Because the Microbridge server is a TCP Server which listens on port 4567.

FdActivity.java


1:  package org.opencv.samples.facedetect;  
2:  ...  
3:  public class FdActivity extends Activity implements CvCameraViewListener2 {  
4:       ...       
5:       private Server server;  
6:       /** Called when the activity is first created. */  
7:       @Override  
8:       public void onCreate(Bundle savedInstanceState) {  
9:            ...  
10:            // Create TCP server  
11:            server = null;  
12:            try {  
13:                 server = new Server(4567);  
14:                 server.start();  
15:            } catch (IOException e) {  
16:                 Log.e("microbridge", "Unable to start TCP server", e);  
17:                 System.exit(-1);  
18:            }            
19:       }  
20:       public Mat onCameraFrame(CvCameraViewFrame inputFrame) {  
21:            ...  
22:            Rect firstFace = null;  
23:            if(facesArray.length > 0) { 
24:                 Size size = mRgba.size(); 
25:                 firstFace = facesArray[0];  
26:                 byte[] data = new byte[1];  
27:                 if(firstFace.x > size.width / 2) {  
28:                      data[0] = 0x03;  
29:                 } else if(firstFace.x < size.width / 2) {  
30:                      data[0] = 0x04;  
31:                 }   
32:                 try {  
33:                      server.send(data);  
34:                 } catch (IOException e) {  
35:                      // TODO Auto-generated catch block  
36:                      e.printStackTrace();  
37:                 }  
38:            }  
39:            return mRgba;  
40:       }       
41:  }  

The logic I have used here is if the First Detected Face is in the right half of the image then turn right or else turn left and go forward. In order for Android and Arduino to communicate using ADB USB Debugging must be enabled in Android.

Finally you can see the entire thing working together in the below video.





The USB cable to Arduino is only connected to power up the whole unit. I tried a 9v Battery and you can see the battery connector connected to the Arduino but the phone was also drawing power from the battery thus it wasn't enough to power up the system. But I think a 12v Battery may be sufficient enough.

If anyone need the full source codes please email me at shazin (dot) sadakath (at) gmail (dot) com or put a comment here with your email.

References
Trackbacks/Pings