Wednesday, March 16, 2016

Typeahead search with RxJS in AngularJS applications

This blog aims to demonstrate concept of Observables in AngularJS. I'm using Typeahead search as an example. It describes implementing Typeahead search in Angular 1.x

Introduction

RxJS - Reactive Extensions JavaScript is dealing with streams of data asynchronously. Observables is one of the important aspects of RxJS. Observable results in stream of data.  Many times, for understanding Observables they are compared to Promises. Both deal with asynchronous actions. Difference is unlike Observable, Promise is done once the asynchronous operation is complete. Consider a Http call. Promise is complete once response is obtained (or the call errors out). With Obserables data or items are emitted continuously like a stream.

Where do we see stream of data in JavaScript, especially in a browser? I could think of couple of examples,
  1. Data bound to UI controls: As user interacts with the UI, edits a text field, selects an option in the drop down, and continues to do so, there are series of changes emitted from the control.
  2. Web Socket - a persistent connection. Server could send a stream of data. As long as the connection is open, browser (or other clients) could continue to obtain new pieces of data. Unlike a XHR, it's not done once we receive response soon after establishing connection.
Another difference between Promises and Observables is that, Observables can be unsubscribed (cancelled). 

In the blog, I'm planning to write about "Typeahead search". Here the UI control is an Observable. It emits data items. As user starts keying in search term into the text box results are updated. It triggers XHR request with each change or set of key strokes in the text field. Show results using the latest response. Cancel in-progress, old and obsolete XHRs.

Sample is using AngularJS (v1.x) and RxJS libraries to code this functionality.

Run with Angular 1.x

bower install angular angular-rx

Reference the libraries
  <script src="bower_components/rxjs/dist/rx.lite.min.js"></script>        
  <script src="bower_components/angular/angular.min.js"></script>
  <script src="bower_components/angular-rx/dist/rx.angular.js"></script>

Bootstrap Angular module with "rx" module as a dependency.
angular.module("typeAheadSample", ["rx"]);

Consider the following template for text field. This is where user keys in the search term.
<input type="text" ng-model="searchString" ng-change="search()">

Notice we are calling "search()" controller function (on $scope) for changes detected with the text field. In the controller inject "rx" service for creating an Observable and $http for making API calls.

Create an observable function using rx service API,
var searchControlObservable= $scope
          .$createObservableFunction('search');

RxJS has galore of operators (which are functions in JS). Before I describe one such operator, remember an Observable emits items or data. In our example as and when user keys in values into text field, observable is emitting the text to all observers (subscribers). 

Each search term results in search result (from the API). And we have series of results. That means we have Observables of Observables.

Consider following code,
 searchControlObservable searchControlObservable
         .debounce(500)// Observable holds off 500 milliseconds before emitting data.
         .flatMapLatest(function(term){
             return rx.Observable                                
                   .fromPromise($http({
                      url: "http://localhost:3001/api/search?term=" + $scope.searchString,
                      method: "get"                                
                    }))
                   .map(function(response){                                
                       return response.data;    
                    });
               });

The callback for flatMapLatest is invoked for every emitted item of searchControlObservable (which is result of text field change events). This in turn returns Observables out of XHR calls. These are Observables from promises.

flatMap is an operator, useful in such scenarios where we have Observables of Observables. It transforms and merges. A variant of flatMap is flatMapLatest. In our scenario only the latest search result matters. Previous ones could be ignored. So it stops or unsubscribes from previous Observables. As stated earlier unlike Promises, Observables could be stopped or unsubscribed from.

Also notice debounce(500); It will hold off emitting items for 500 ms. This will help control number of XHR calls. We can increase / decrease the number depending on the requirement, acceptable limit for load on the API etc. Ideally we want search calls made for considerable text keyed-in, instead of every little change.

With debounce

Without debounce























And finally, map returns transformed object. 

Subscribe to receive items emitted by Observable,
  .subscribe(function(results) {
                            $scope.$apply(function(){
                                $scope.messages = results;  
                            });
                        });      

Note: Subscribe function accepts three callbacks or another Observer instance. i) Above example has onNext handler (which receives items emitted by Observer). ii) Error handler iii) onCompleted handler. If an Observer object is passed, its callbacks are invoked.

Loop through the response to show the list of ,
<div ng-repeat="message in messages track by $index">
    <div>{{message.name}}</div>
</div>

Note: The API in the sample (http://localhost:3001/api/search?term=) is a dummy node API that reads from a file and returns results. It's a quick search service for demonstration purposes.          

Follow the link for complete code sample. Follow instructions in ReadMe to download and run the sample.

References




Thursday, January 14, 2016

IoT: Is someone there? RPi, Arduino and Firebase!

"This blog is about detecting motion and showing it on a Web page. IoT device will identify movement and publish status to a service on cloud. A web page integrated with the service will show the status on screen. Also, let's glow green LED when no motion is detected and red when there is movement."
Here is a quick demo -

Arduino with Raspberry Pi (RPi)

Using Arduino to interface with motion sensor. Code in Arduino detects motion and lights a red LED and sends high to connected Raspberry Pi pin as well. The RPi is integrated with Firebase on Cloud. Used REST API to update a flag in Firebase data source. A web page that shows default status that no moment detected (safe) will change with the flag on Firebase to notify movement (Someone's there).

Following picture depicts Arduino, RPi and motion sensor connections I have.
RPi is powering Arduino, 5v on RPi is connected to vin on Arduino. Ground to ground and RPi board pin 3/GPIO02 to Arduino pin 9. Arduino detects motion from the sensor and sends high signal to RPi on this pin.

Motion sensor has three pins. It's powered by 5v pin on Arduino. Ground to ground and pin 8 receives input from the sensor. Value will be high whenever the sensor detects motion.

In the video, got green and red LEDs indicating motion on the device. It's standard LED connections. Here is a picture.


Arduino sends high to pin 6 by default; It sends high on pin 7 and pin 9 when motion is detected. 7 lights red LED And high signal on 9 makes RPi update cloud service indicating motion. 

Code on Arduino

#define greenLed 6 #define redLed 7
#define motionSensor 8
#define rpi 9
void setup(){
Serial.begin(9600);
pinMode(greenLed, OUTPUT);
pinMode(redLed, OUTPUT);
pinMode(motionSensor, INPUT);
pinMode(rpi, OUTPUT);
}
void loop(){
delay(500); // If High motion is detected.
if(digitalRead(motionSensor) == HIGH){
lightRed();
digitalWrite(rpi, HIGH);
}else{
lightGreen();
digitalWrite(rpi, LOW);
}
}
void lightRed(){
digitalWrite(greenLed, LOW);
digitalWrite(redLed, HIGH);
}
void lightGreen(){
digitalWrite(redLed, LOW);
digitalWrite(greenLed, HIGH);
}
Following Python code on RPi updates Firebase Cloud back end that motion is detected (or vice versa). a page integrated with this data source shows the status on a web page. This code is using Firebase REST API to update status flag.

import RPi.GPIO as GPIO import time
import http.client
import json
arduinoPin = 3
GPIO.setmode(GPIO.BOARD)
GPIO.setup(arduinoPin, GPIO.IN)
while True:
if GPIO.input(arduinoPin) == GPIO.HIGH:
print('Switching ON...')
client = http.client.HTTPSConnection('vencki-iot-sample.firebaseio.com')
client.request('PUT','/proximityWarning.json', '{"isClose":true}')
response = client.getresponse()
print (response.reason)
else:
print('Switching OFF...')
client = http.client.HTTPSConnection('vencki-iot-sample.firebaseio.com')
client.request('PUT','/proximityWarning.json', '{"isClose":false}')
response = client.getresponse()
print (response.reason)
time.sleep(2)
print('quitting...')
GPIO.cleanup()

Saturday, January 2, 2016

IoT: Hello World - Toggle LED with a button on a Web Page

"This blog is about toggling LED on or off with a button click on a web page, from a phone or a desktop."

Happy New Year! I recently started exploring long pending IoT in my things to learn. I'm planning to document as tryout samples. As a Hello World I tried out blinking LED using a Raspberry Pi 2, took it little further, toggled LED on or off as you tap on a button in a web page.

Here is a quick demo-

Why Raspberry Pi? 

I've a choice (available with me) between Arduino and Raspberry Pi. With Arduino, I would need to buy additional WiFi module. Arduino can do one job at a time and it can do that well. It works great with direct sensor interactions, may it be temperature sensor, proximity sensor etc.

Raspberry Pi is a computer in it self. It comes with LAN cable connectivity, I could connect a 300 INR (5 USD appx) Wifi dongle and get it connected to Internet. I'm using Raspbian. Microsoft has Windows 10 IoT core which could be installed on a (micro) SD card and used with Raspberry Pi 2.

There is a choice of programing languages with Raspberry Pi. In this sample I'm using more popular Python.

Web Page that toggles LED

Just needed a central location on cloud to store on/off state. It could be anything. Firebase is a good solution for such things. And I believe it's a good platform for IoT going forward. 
  • Firebase is literally no setup, ready made cloud back-end. 
  • It's no schema and JSON data store. 
  • Easy to get and update data with REST API and setup security rules. 
  • It's backed by Google Cloud if you are thinking scalability.
I uploaded a simple page with button that flips a flag on Firebase as you click on the button. This page is deployed to Firebase hosting service. Raspberry Pi uses this flag, turns LED on if the value is true (and vice versa).

Raspberry Pi Setup

Raspberry Pi 2 has a 40 pin layout. Refer to below picture- pins are 
  • GPIO (General Purpose Input/Output) - could be used in code to set a value HIGH or LOW to interface with sensors and devices.
  • Ground
  • 3.3 volts and 5 volts power
Reference - http://www.element14.com/community/docs/DOC-73950/l/raspberry-pi-2-model-b-gpio-40-pin-block-pinout
Here is the connection to LED. Positive on LED connects to Pin 7/GIPO04 and ground on LED connects to a resistor which in turn connects to ground on pin 06. Resistor is to make sure too much current doesn't get pass through the LED which could damage it. 
Below is the Python code that looks for flag value on cloud and toggles LED. Read through comments for explanation

import RPi.GPIO as GPIO 
import time 
import http.client 
import json 

pin = 7 
GPIO.setmode(GPIO.BOARD) 
# Board mode is safer option to use with pin numbers matching between older and 
# newer versions of Raspberry Pi, hence no confusion 
GPIO.setup(pin, GPIO.OUT) 
while True: 
  client = http.client.HTTPSConnection('<< firebase URL>>')
  client.request('GET','/LED.json') 
  httpResponse = client.getresponse() 
  dataStream = httpResponse.read() 
  dataString = str(dataStream, 'utf-8') 
  switchLedOn = json.loads(dataString) 
  print(switchLedOn) 
  # switchLedOn holds true/false as user toggles the switch 
  # with a button on the web page. 
  
  if (switchLedOn): 
     print('Switching ON...') 
     GPIO.output(pin, GPIO.HIGH) 
 else: 
     print('Switching OFF...') 
     GPIO.output(pin, GPIO.LOW) 

 time.sleep(2) 
 #retry after 2 seconds. 

GPIO.cleanup()

Complete sample is uploaded to Github. Happy Coding and Happy New Year.

Monday, December 28, 2015

Service Worker - Give native app experience to web app on mobile

Context:

In today's mobile app development, there are lot of things web apps on mobile can't do compared to native apps. But the gap is filling fast. Offline access is one such example. Facebook native app for example, when disconnected shows recent 15+ posts. You may continue to use the app. When connected to Internet it will sync data. Imagine similar functionality to a Web App. It's especially useful on  mobile devices - phones and tablets.

Service Worker helps cache application (JavaScript, HTML, CSS) and data. It's a specification created by Google Chrome and Mozilla.

Following is a sample I tried out with SW-PreCache and SW-Toolbox repos. I'm documenting steps to create the service worker in the sample app below, The sample app shows dinosaur data from a Web URL (thanks to Firebase - it's one of the sample data sets provided by Firebase).

Sample App

Here is the complete code repo for sample app.

The sample app is coded using AngularJS, Bootstrap CSS framework for responsive design on mobile screen. Controller accesses dinosaur data from Web URL and assigns to scope. If there is a problem accessing data it will set flag so that UI can show error message.

$http.get("https://dinosaur-facts.firebaseio.com/dinosaurs.json")
.success(function(results){
$scope.dinosaurs = results;
})

.error(function(error){
  // Set flag - show error message when there is a problem retrieving data.
$scope.showAlert = true;
$scope.errorMessage = "Ooops, Jurassic park is unavailable! Are you connected to Internet?";

});

View is HTML in index.html - ng-repeat to show data.

<div class="container" ng-controller="firstController">
<table class="table table-striped">
<tr ng-repeat="(dinosaur,prop) in dinosaurs">
<td><strong>{{dinosaur}}</strong></td>
<td>Appeared {{prop.appeared}} years ago</td>
<td>{{prop.height}} meters long</td>
<td>{{prop.length}} meters wide</td>
<td>{{prop.weight}} pounds</td>
</tr>
</table>
</div>


Or show error message when no there is no connectivity,
<div ">
<div ng-show="showAlert" class="alert alert-danger alert-dismissible " role="alert">
<button type="button" class="close" data-dismiss="alert" aria-label="Close"><span aria-hidden="true">&times;</span></button>
{{errorMessage}}
</div>

Browser error vs graceful error: 

On a browser go to a link when offline, you would see browser error page. How about native like graceful error message? Create a shortcut to home screen like a native app and as you tap it graceful error message is shown (if there is no network connectivity). You could provide more details of the error as well. It's better user experience compared to browser error page. Following is an example




For this, we could use Service Worker to cache application skeleton. SW-PreCache makes this process simple.
  1. Install using bower install sw-precache
  2. Modify grunt file in demo app, Update staticFileGlobs property to new files in the sample. Modify handleFetch property to true so that it starts serving cached content. Here is the link to new file.
  3. Run grunt swPrecache. It now generates service-worker.js. It need to be registered with Service Worker on the browser. A service-worker-registration.js file is reusable. It takes care of checking service worker feature availability on the browser, checking if there is a newer version of service-worker.js so that it can be re-installed etc.
  4. Include this file in Index.html so that registration happens.
You are done. As you run the app, all specified files in grunt task are cached. Even if network is disconnected, cache is used. 

Note: I'm using grunt to generate pre-cache for the sample. Gulp is supported and there are multiple examples using gulp as well.

Cache Data:

sw-toolbox helps cache data easily. 
  1. Install sw-toolbox using bower. bower install sw-toolbox
  2. Import toolbox script using importScripts('node_modules/sw-toolbox/sw-toolbox.js');
  3. Provide following configuration for caching data from given XHR calls. It caches all calls to dinosaur-facts.firebaseio.com. 
toolbox.router.get('/(.*)', toolbox.networkFirst, { 
 // Use a dedicated cache for the responses, separate from the default cache. 
 cache: { 
   name: 'sample-app', // Store up to 10 entries in that cache. 
   maxEntries: 10, // Expire any entries that are older than 30 seconds. 
   maxAgeSeconds: 30 
 }, 
 origin: 'dinosaur-facts.firebaseio.com' 
});
This Service Worker once registered with the browser will use cached data when disconnected.

It caches any URL pattern. Handler toolbox.networkFirst is used so that first preference is given to network. Only if network connection is unavailable, cached data is used. We could use cacheFirst where data is immediately loaded from cache and then updated once obtained over network. More options are fastest - make both calls network and cache, whichever comes first will be used. networkOnly - when you never want to use cached data for a route. cacheOnly - when you are sure network call won't be made for that route.

Here is a quick demo of Service Worker Sample App


Link to the demo page.

In conclusion I believe Service Worker is going to be revolutionary for mobile web app development. Recent Chrome Dev Summit had shout-out for Flipkart for implementing this feature on Chrome. I explored chrome://serviceworker-internals to see Facebook and Medium are using it as well.

Happy coding Service Worker in the new year 2016 !

Code repo for sample app.

Tuesday, December 15, 2015

Firebase Samples

AngularFire is AngularJS API for Firebase. This repo has a sample app to demonstrate features during my demo.

About Me,
V Keerti Kotaru | Tweets @kvkirthy | Blogs at bit.ly/kotaru 

Monday, November 30, 2015

Firebase - Two Salient Features.

Three way data binding with AngularFire:

Imagine user keys in lots of data into a form and had to navigate away from the page. Often I saw apps presenting a dialog box that says data is going to be lost. I don't think it's a good solution. How about allowing user start from where he/she left. Here is a Firebase feature to address the same,


Maintain state as you move away from the form:

Among many things AngularJS provides, two way data binding is salient. Firebase takes it further, add another dimension - data store. Three way data binding synchronizes, view (Html template), model (Scope) and Firebase data store.

Consider following code snippet

// Initialize Firebase object
// say user variable has user name of the logged in user.

     var firebaseObj = $firebaseObject(new Firebase("< Firebase Data Source Url >").child(user));
     // three way data bind email message field on scope to firebase object created above.
     firebaseObj.$bindTo($scope, "emailMessage");


Any changes to $scope.emailMessage are bound all the way to data source on Firebase. User can any time navigate away and yet data is not lost. As and when user comes back to this page, can start where he/she left off.


In the video, on the left is the form field and on the right is the Firebase data source. You can see it's updated as and when more characters are typed into the text area.

Sync as you go online: 

Firebase makes it that much more easier to continue to work as you get disconnected. In fact no additional code required. API automatically maintains data in disconnected state. It will sync as and when user goes online.


Knowing connection state:

Use /.info/connected on the data source's URL to know current connection status.

$scope.connectionStatus = $firebaseObject(new Firebase("https://Your Firebase App/.info/connected"));

Bind connection status to a green/red icon in the template. 

 <img ng-show="connectionStatus.$value" src="images/green.png" style="max-height:24px" />
 <img ng-show="!connectionStatus.$value" src="images/red.png" style="max-height:24px" />


Track connection status on server-side

JavaScript API onDisconnect will attach a server side event. You may set a value when disconnection occurs,

// The variable "user" holds user name of the logged in user
// If Kotaru is the user name, JSON will be {Kotaru:{conectionStatus:"disconnected"}}


firebaseReference.child(user).child("connectionStatus").onDisconnect().set("disconnected");

// You can override this object when user comes online

JavaScript API to get Offline or Online:

Finally you may chose to go offline or online with functions Firebase.goOffline() and Firebase.goOnline() . These are as good as disconnecting and connecting the application's connection with Firebase. You might allow user to perform multiple offline changes to dataset and at some point get online to sync.