Raspberry Pi Home Automation & Security System: Android Ionic App

Raspberry Pi Home Automation & Security System: Android Ionic App

This is the second tutorial post on Raspberry Pi: Home Automation & Security System series. In this post, we are going to design and develop the Android app based on Ionic Framework with which we can remotely send/receive commands and feedbacks from our prototype home.

In the previous post, we did well to outline both the software and hardware components required for the success of this project. One of the components is an Android App based on Ionic Framework and I will assume that my readers have some knowledge of Javascript, nodeJS, Ionic and Android app development so lets get started immediately:

See also:

Please refer to Ionic framework website or docs on how to setup your system for Ionic app projects. Navigate to the folder of your choice ( I am using my desktop folder), then run this command to get started:

ionic start homeAuto blank

this command creates a folder called homeAuto and installs the packages for ionic app development inside. ‘homeAuto’ is my choice of folder name, you might as well choose yours while ‘blank’ means we want a blank template with tabs, sidemenu etc. if this commands executes successfully, you can now run this command to enter or cd into the newly created folder. ionic serve is use for testing the app on the browser

cd homeAuto
ionic serve

 

Using a code editor of your choice but I prefer visual studio code, open the folder and you should see this file/folder hierarchy:

ionic folder - steinacoz
ionic folder – steinacoz

Now, we need to install some packages from npm or we will be stock here:

npm install pubnub pubnub-angular2 --save

Pubnub Angular2 service is a wrapper for PubNub JavaScript SDK version 4 that adds a few of extra features to simplify Angular integrations.

Open src/app/app.module.ts and update it with pubnubAngular2 which should be under providers , your final code should look like this:

import { BrowserModule } from '@angular/platform-browser';
import { ErrorHandler, NgModule } from '@angular/core';
import { IonicApp, IonicErrorHandler, IonicModule } from 'ionic-angular';
import { SplashScreen } from '@ionic-native/splash-screen';
import { StatusBar } from '@ionic-native/status-bar';
import { PubNubAngular } from  'pubnub-angular2' //import the package

import { MyApp } from './app.component';
import { HomePage } from '../pages/home/home';

@NgModule({
  declarations: [
    MyApp,
    HomePage
  ],
  imports: [
    BrowserModule,
    IonicModule.forRoot(MyApp)
  ],
  bootstrap: [IonicApp],
  entryComponents: [
    MyApp,
    HomePage
  ],
  providers: [
    PubNubAngular, //add under providers
    StatusBar,
    SplashScreen,
    {provide: ErrorHandler, useClass: IonicErrorHandler}
  ]
})
export class AppModule {}

 

Open src/pages/home.html and make some modifications to it. Infact delete all its content and add these lines of codes to it:

<ion-header>
  <ion-navbar>
    <ion-title>
      HOME AUTO APP
    </ion-title>
  </ion-navbar>
</ion-header>

<ion-content ion-scroll padding>
  
    <div style="background: red; height: 30%">
      <!--url to get video feed-->
      <img src="http://192.168.43.241/video_feed">
    </div>

    <ion-item>
    <ion-label> {{ stat }}</ion-label>
    
  </ion-item>

  <ion-item>
    <ion-label style="color: red"> temperature:</ion-label>
    <ion-label> {{ temp }}</ion-label>
  </ion-item>

  <ion-item>
    <ion-label style="color: red"> humidity:</ion-label>
    <ion-label> {{ humid }}</ion-label>
  </ion-item>

  <ion-item>
    <ion-label> Security Lights</ion-label>
    <ion-toggle [checked]="securityLights" [(ngModel)]="securityLights" (ngModelChange)="operationSecurityLights($event)"></ion-toggle>
  </ion-item>

  <ion-item>
    <ion-label> Garage Light</ion-label>
    <ion-toggle [checked]="garageLight" [(ngModel)]="garageLight" (ngModelChange)="operationGarageLight($event)"></ion-toggle>
  </ion-item>

  <ion-item>
    <ion-label> Sitting Room Light</ion-label>
    <ion-toggle [checked]="sittingRoomLight" [(ngModel)]="sittingRoomLight" (ngModelChange)="operationSittingRoomLight($event)"></ion-toggle>
  </ion-item>

  <ion-item>
    <ion-label> Fan</ion-label>
    <ion-toggle [checked]="fan" [(ngModel)]="fan" (ngModelChange)="operationFan($event)"></ion-toggle>
  </ion-item>

  <ion-item>
    <ion-label> Back Security Light</ion-label>
    <ion-toggle [checked]="backSecurityLight" [(ngModel)]="backSecurityLight" (ngModelChange)="operationBackSecurityLight($event)"></ion-toggle>
  </ion-item>


 <ion-item>
    <ion-label> Bedroom Light</ion-label>
    <ion-toggle [checked]="bedroomLight" [(ngModel)]="bedroomLight" (ngModelChange)="operationBedroomLight($event)"></ion-toggle>
  </ion-item>

  <ion-item>
    <ion-label> Garage Door</ion-label>
    <ion-toggle [checked]="garageDoor" [(ngModel)]="garageDoor" (ngModelChange)="operationGarageDoor($event)"></ion-toggle>
  </ion-item>

  <ion-item>
    <ion-label> Front Door</ion-label>
    <ion-toggle [checked]="frontDoor" [(ngModel)]="frontDoor" (ngModelChange)="operationFrontDoor($event)"></ion-toggle>
  </ion-item>

  <ion-item>
    <button ion-button color="danger" large (click)="panRight($event)"> Right</button>
    <button ion-button color="danger" large (click)="panLeft($event)"> Left</button>
  </ion-item>

    

  
</ion-content>

The home.html file just contains a bunch of html button, labels and toggle button tags which a newbie should under stand and grab easily. Let me throw more light on the tags:

  • stat label: holds the feedback from the Raspberry Pi. The Pi sends back a feedback whenever it recieves a command and executes it successfully. It also shows the status of a publish activity via pubnub. If there is an error during a publishing activity, this tag is updated inorder to notify the user.
  • temperature label: holds the temperature value/reading received from the Raspberry Pi.
  • humidity label: holds the humidity value/reading received from the Raspberry Pi.
  • toggle buttons: just as it sounds, it is used to ON/OFF or OPEN/CLOSE a door or light.
  • Direction button: used to send command to the Raspberry Pi to pan the camera right or left.
  • red Image tab: thats our screen/monitor for viewing video feed from the Pi.
<div style="background: red; height: 30%">
      <!--url to get video feed-->
      <img src="http://192.168.43.241/video_feed">
    </div>

Pay very close attention to this lines of codes, we use img tab src attribute to get video feed using the URL from our Python Flask server.

Finally, open app/src/pages/home.ts. Delete its content and update it with these lines of code. I tried as best as possible to comment it well but it is mostly self explanatory:

import { Component,  Injectable } from '@angular/core';
import { NavController } from 'ionic-angular';

import { PubNubAngular } from 'pubnub-angular2';


@Component({
  selector: 'page-home',
  templateUrl: 'home.html'
})
export class HomePage {

// pubnub channels
LIGHTS:string = 'LIGHTS';
DOORS:string = 'DOORS';
ELECTRICAL:string = 'ELECTRICAL';
CAMERA:string = 'CAMERA';
SENSORS:string = 'SENSORS';
SENSORS_TEMP:string = 'SENSORS_TEMP';
SENSORS_HUMID:string = 'SENSORS_HUMID';
FEEDBACKS:string = 'FEEDBACKS';
MODE:string =  'MODE';

//pubnub payloads
//pubnub payloads
sensors_data:string = 'get data';
//operating lights
securityLight_ON:string = 'SECURITY LIGHT ON';
securityLight_OFF:string = 'SECURITY LIGHT OFF';

backSecurityLight_ON:string = 'BACK SECURITY LIGHT ON';
backSecurityLight_OFF:string = 'BACK SECURITY LIGHT OFF';

garageLight_ON:string = 'GARAGE LIGHT ON';
garageLight_OFF:string = 'GARAGE LIGHT OFF';

sittingRoomLight_ON:string = 'SITTING ROOM LIGHT ON';
sittingRoomLight_OFF:string = 'SITTING ROOM LIGHT OFF';

bedroomLight_ON:string = 'BEDROOM LIGHT ON';
bedroomLight_OFF:string = 'BEDROOM LIGHT OFF';

//operating doors
garageDoor_OPEN:string = 'GARAGE DOOR OPEN';
garageDoor_CLOSE:string = 'GARAGE DOOR CLOSE';

frontDoor_OPEN:string = 'FRONT DOOR OPEN';
frontDoor_CLOSE:string = 'FRONT DOOR CLOSE';

//operating electrical appliances
fan_ON:string = 'FAN ON';
fan_OFF:string = 'FAN OFF';

light_ON:string = 'LIGHT ON';
light_OFF:string = 'LIGHT OFF';

//operating camera
camera_Right:string = 'RIGHT';  //right is to sitting room
camera_Left:string = 'LEFT';  //left is to bedroom

//changing mode
changeMode_AUTO:string = 'AUTO';
changeMode_MANUAL:string = 'MANUAL';

//detecting motion
MOTION_PIR1:string = 'PIR1 MOTION';
MOTION_PIR2:string = 'PIR2 MOTION';
MOTION_PIR3:string = 'PIR3 MOTION';

stat: string = '';
humid: any;
temp: any;

//models for the toggle buttons
securityLights: boolean = false;
garageLight: boolean = false;
sittingRoomLight: boolean = false;
fan: boolean = false;
backSecurityLight: boolean = false;
bedroomLight: boolean = false;
garageDoor: boolean = false;
frontDoor: boolean = false;



  constructor(public navCtrl: NavController, public pubnub: PubNubAngular ) {
    
  
      //this.pubnubSubcribeChannels()
      
  }


  ionViewDidLoad() {
    console.log('ionViewDidLoad Page');
   this.pubnub.init({
            subscribeKey: "sub-c-a8169944-3833-11e7-9361-0619f8945a4f",
            publishKey: "pub-c-6e287234-f550-4a51-a25a-5fe510f91dd6",
            ssl: true
        });

//start listening from here
    this.pubnubAddListener();

//subscribe to all relevant channels
    this.pubnub.subscribe({
    channels: [this.LIGHTS, this.CAMERA, this.DOORS, this.ELECTRICAL, this.FEEDBACKS, this.MODE, this.SENSORS, this.SENSORS_HUMID, this.SENSORS_TEMP], triggerEvents: true,
    withPresence: true
});


  }

  

  //function to publish commands
  pubnubPublishCommands(publishChannel: string, publishMessage: string):void {
    this.pubnub.publish(
    {
        message: publishMessage,
        channel: publishChannel
//use promise to update UI
    }).then((status) => {
        console.log(status);
        this.stat = 'success in publishing';
        console.log('success');
    }).catch((error) => {
        console.log(error)
        this.stat = 'error in publishing';
        console.log('error');
    });
    
 
  }

  //function to add listeners
  pubnubAddListener(){
     //request for temp and umidity values
     var getSensorData = this.pubnubPublishCommands(this.SENSORS, this.sensors_data);
    this.pubnub.addListener({
    message: function(m) {
        // handle message
        var channelName = m.channel; // The channel for which the message belongs
        var channelGroup = m.subscription; // The channel group or wildcard subscription match (if exists)
        var pubTT = m.timetoken; // Publish timetoken
        var msg = m.message; // The Payload

        console.log(channelName);
        console.log(msg);

        
    },

    presence: function(p) {
        // handle presence
        var action = p.action; // Can be join, leave, state-change or timeout
        var channelName = p.channel; // The channel for which the message belongs
        var occupancy = p.occupancy; // No. of users connected with the channel
        var state = p.state; // User State
        var channelGroup = p.subscription; //  The channel group or wildcard subscription match (if exists)
        var publishTime = p.timestamp; // Publish timetoken
        var timetoken = p.timetoken;  // Current timetoken
        var uuid = p.uuid; // UUIDs of users who are connected with the channel
    },
    status: function(s) {
        var affectedChannelGroups = s.affectedChannelGroups;
        var affectedChannels = s.affectedChannels;
        var category = s.category;
        var operation = s.operation;

        console.log(category);

        if ( category === "PNConnectedCategory") {
                getSensorData;
            }

            if (category === "PNTimeoutCategory"){
                
            }

            if (category === "PNReconnectedCategory"){
                getSensorData;
            } 
            if (category === "PNNetworkIssuesCategory"){
                
            } 

            if (category === "PNNetworkDownCategory"){
               
            }

            if (category === "PNNetworkUpCategory"){
                
            } 



    }
});

//grab messages/payload from specfic channnels
this.pubnub.getMessage([this.SENSORS], (m) => {
    
    this.stat = m.message;
})

this.pubnub.getMessage([this.SENSORS_TEMP], (me) => {
    console.log(me.message);

    this.temp = me.message;
    
})

this.pubnub.getMessage([this.SENSORS_HUMID], (me) => {
    console.log(me.message);

    this.humid = me.message;
})




  }
  


  //function to on and off security Lights
  operationSecurityLights($event): void{
    if(this.securityLights){
      
      this.pubnubPublishCommands(this.LIGHTS, this.securityLight_ON);
      console.log(this.securityLight_ON, this.securityLights);
      this.securityLights = true;
    }else{
      
      this.pubnubPublishCommands(this.LIGHTS, this.securityLight_OFF);
      console.log(this.securityLight_OFF, this.securityLights);
      this.securityLights = false;
    }
  }

  //function to on and off Garage Light
  operationGarageLight($event): void{
    if(this.garageLight){
      this.pubnubPublishCommands(this.LIGHTS, this.garageLight_ON);
      console.log(this.garageLight_ON, this.garageLight);   
      this.garageLight = true;
    }else{
      
      this.pubnubPublishCommands(this.LIGHTS, this.garageLight_OFF);
      console.log(this.garageLight_OFF, this.garageLight);
      this.garageLight = false;
      
    }
  }


  //function to on and off Sitting Room Light
  operationSittingRoomLight($event): void{
    if(this.securityLights){
      this.pubnubPublishCommands(this.LIGHTS, this.sittingRoomLight_ON);
      console.log(this.sittingRoomLight_ON, this.sittingRoomLight);   
      this.sittingRoomLight = true;
    }else{
      
      this.pubnubPublishCommands(this.LIGHTS, this.sittingRoomLight_OFF);
      console.log(this.sittingRoomLight_OFF, this.sittingRoomLight);
      this.sittingRoomLight = false;
      
    }
  }


   //function to on and off fan
  operationFan($event): void{
    if(this.fan){
      this.pubnubPublishCommands(this.ELECTRICAL, this.fan_ON);
      console.log(this.fan_ON, this.fan);   
      this.fan = true;
    }else{
      
      this.pubnubPublishCommands(this.ELECTRICAL, this.fan_OFF);
      console.log(this.fan_OFF, this.fan);
      this.fan = false;
      
    }
  }

   //function to on and off Back Security Light
  operationBackSecurityLight($event): void{
    if(this.backSecurityLight){
      this.pubnubPublishCommands(this.ELECTRICAL, this.backSecurityLight_ON);
      console.log(this.backSecurityLight_ON, this.backSecurityLight);   
      this.backSecurityLight = true;
    }else{
      
      this.pubnubPublishCommands(this.ELECTRICAL, this.backSecurityLight_OFF);
      console.log(this.backSecurityLight_OFF, this.backSecurityLight);
      this.backSecurityLight = false;
      
    }
  }

   //function to on and off Bedroom Light
  operationBedroomLight($event): void{
    if(this.bedroomLight){
      this.pubnubPublishCommands(this.LIGHTS, this.bedroomLight_ON);
      console.log(this.bedroomLight_ON, this.bedroomLight_ON);   
      this.bedroomLight = true;
    }else{
      
      this.pubnubPublishCommands(this.LIGHTS, this.bedroomLight_OFF);
      console.log(this.bedroomLight_OFF, this.bedroomLight);
      this.bedroomLight;
      
    }
  }

   //function to open and close Garage Door
  operationGarageDoor($event): void{
    if(this.garageDoor){
      this.pubnubPublishCommands(this.DOORS, this.garageDoor_OPEN);
      console.log(this.garageDoor_OPEN, this.garageDoor);   
      this.garageDoor = true;
    }else{
      
      this.pubnubPublishCommands(this.DOORS, this.garageDoor_CLOSE);
      console.log(this.garageDoor_CLOSE, this.garageDoor);
      this.garageDoor = false;
      
    }
  }

   //function to on and off Front Door
  operationFrontDoor($event): void{
    if(this.frontDoor){
      this.pubnubPublishCommands(this.DOORS, this.frontDoor_OPEN);
      console.log(this.frontDoor_OPEN, this.frontDoor);   
      this.frontDoor = true;
    }else{
      
      this.pubnubPublishCommands(this.DOORS, this.frontDoor_CLOSE);
      console.log(this.frontDoor_CLOSE, this.frontDoor);
      this.frontDoor = false;
      
    }
  }


  //function to move camera Right
  panRight($event): void {
    this.pubnubPublishCommands(this.CAMERA, this.camera_Right);
  }

   //function to move camera Right
  panLeft($event): void {
    this.pubnubPublishCommands(this.CAMERA, this.camera_Left);
  }

  

}


 

As you can see, I tried to explain the lines using comments but you can always contact me through any of our social media channels or drop a comment and I will surely attend to it.

You can now add android platform and either serve or build:

Ionic cordova platform add android

 

Ionic cordova platform build android

 

android ionic app - steinacoz
android ionic app – steinacoz

 

Leave a Reply

Your email address will not be published. Required fields are marked *