Courtney Achen
Published © GPL3+

GarageBot - The Connected Garage Door Opener

In this project I used a Particle Photon to control my garage door via an Android App.

IntermediateWork in progress8 hours2,828
GarageBot - The Connected Garage Door Opener

Things used in this project

Hardware components

Photon
Particle Photon
×1
Relay (generic)
×1
Proximity Sensor - Generic
×1

Story

Read more

Schematics

Breadboard Schematic

Code

Firmware - GarageBot

Arduino
This is the code for the Photon.
// Set-up variables, Pin D1 will control the door relay and Pin D4 will check whether the door is open or closed
int door = D1;
int status = D4;

int statusvalue;


void setup()
{
// Sets the door relay pin as an output and the status pin as an input
   pinMode(door, OUTPUT);
   pinMode(status, INPUT);

// This sets up a Spark function that will recieve the open/close command from the Spark Cloud.  
   Spark.function("led",doorToggle);

// This sets the initail condition of the relay.  It is off by default.
   digitalWrite(door, LOW);
   
//  This sends the door status open/closed to the Spark Cloud.
   Spark.variable("status", &statusvalue, INT);

}

void loop()
{
// Constantly checks the status of the door (open or closed).  
    statusvalue = digitalRead(status);

}

// This gets called if the Spark Cloud commands a door open/close
int doorToggle(String command) {

// If the command is "on" the relay closes for 1 second and then opens again.
// You may have to adjust the delay depending on your garage door opener.
    if (command=="on") {
        digitalWrite(door,HIGH);
        delay(1000);
        digitalWrite(door,LOW);
        return 1;
    }
    else if (command=="off") {
        digitalWrite(door,LOW);
        return 0;
    }
    else {
        return -1;
    }
}

Android App - Main Activity

Java
This is the code that actually opens and closes the garage door. This code does not include a timeout for communication to the Spark Cloud.
package com.example.garagebot;

import java.util.ArrayList;
import java.util.List;
import org.apache.http.NameValuePair;
import org.apache.http.message.BasicNameValuePair;
import org.json.JSONException;
import org.json.JSONObject;

import android.os.Bundle;
import android.app.Activity;
import android.view.View.OnClickListener;
import android.app.ProgressDialog;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.SharedPreferences.Editor;
import android.os.AsyncTask;
import android.preference.PreferenceManager;
import android.util.Log;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TabHost;
import android.widget.TextView;
import android.widget.Toast;

public class MainActivity extends Activity implements OnClickListener{


public Button mTrigger, mRefresh;
public String savedstatus, statusString;
public Integer status;

     // Progress Dialog 
    public ProgressDialog Dialog;

    // JSON parser class 
    JSONParser jsonParser = new JSONParser(); 

	//Communication to Spark Cloud.  
    //Type in your Photon ID where it says Your Photon Id below.
    //Type in your Acess Token where is says Your Access Token below.
    private static final String Trigger = "https://api.particle.io/v1/devices/Your Photon Id/led?access_token=Your Access Token" ;
    private static final String StatusCheck = "https://api.particle.io/v1/devices/Your Photon Id/status?access_token=Your Access Token" ;
    
    //JSON element ids from response of php script: 
    private static final String TAG_SUCCESS = "return_value"; 
    private static final String TAG_RESULT = "result"; 

    @Override 
    public void onCreate(Bundle savedInstanceState) { 
    // TODO Auto-generated method stub 
    	
        super.onCreate(savedInstanceState); 

        setContentView(R.layout.activity_main);
        
        //setup input fields 

        //setup buttons 
         mTrigger = (Button)findViewById(R.id.trigger); 
         mRefresh = (Button)findViewById(R.id.refresh); 

         //register listeners 
         mTrigger.setOnClickListener(this); 
         mRefresh.setOnClickListener(this); 
         
         new CheckStatus().execute();
    } 
		
    @Override 
     public void onClick(View v) { 
         switch (v.getId()) { 
         
         //When the Open/Close button is pressed the Trigger function is executed.
         case R.id.trigger: 
            new Trigger().execute(); 
         
         break; 
     
         //When the Refresh button is pressed the CheckStatus function is executed.
         case R.id.refresh:
        	 new CheckStatus().execute();

         } 
    }
    
    //The Trigger function opens and closes the door.
    protected class Trigger extends AsyncTask<String, String, String> {
    	
    	boolean failure = false;
    	
    	//Pops up a dialog box saying the the door is opening or closing.
    	@Override
    	protected void onPreExecute(){
    		super.onPreExecute();
    		Dialog = new ProgressDialog(MainActivity.this);
    		Dialog.setMessage("Opening/Closing...");
    		Dialog.setIndeterminate(false);
    		Dialog.setCancelable(true);
    		Dialog.show();
    	}
    	
    	//The network call is done on a background thread.
    	@Override
    	protected String doInBackground(String... args) {
    	
    	try {
    		//Sets up the parameters to send to the Spark Cloud.
    		List<NameValuePair> params = new ArrayList<NameValuePair>();
    		params.add(new BasicNameValuePair("args", "on"));
    		
    		//Calls the JSON parser which sends a POST to the Spark Cloud.
    		JSONObject json = jsonParser.makeHttpRequest(Trigger, "POST", params);
    		
    		//Diagnostic message that dumps the JSON data to Logcat.
    		Log.d("Login attempt", json.toString());
    		
    		//Checks whether the request was successful.
    		int success = json.getInt(TAG_SUCCESS);

    	} catch (JSONException e) {
    		e.printStackTrace();
    	}
    	
    	//This is a delay to give the door time to open or close before you check the status.
    	//This will have to be adjusted depending on your door.
    	try {
			Thread.sleep(12000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    	return null;    		
  
    	}
    	
    	//Dismisses the dialog box and checks the status of the door.
    	protected void onPostExecute(String file_url) {
    		Dialog.dismiss();
    		new CheckStatus().execute();
    }
    }

//This function checks whether the door is up or down.
protected class CheckStatus extends AsyncTask<String, String, String> {
    	
    	boolean failure = false;
    	
    	//Pops up a dialog box saying the the door status is being checked.
    	@Override
    	protected void onPreExecute(){
    		super.onPreExecute();
    		Dialog = new ProgressDialog(MainActivity.this);
    		Dialog.setMessage("Checking Door Status...");
    		Dialog.setIndeterminate(false);
    		Dialog.setCancelable(true);
    		Dialog.show();
    	}
    	
    	//The network call is done in a background thread.
    	@Override
    	protected String doInBackground(String... args) {
    	
    	try {
    		List<NameValuePair> params = new ArrayList<NameValuePair>();
    		
    		//Sends a GET request to the Spark Cloud to retrieve the door status.
    		JSONObject json = jsonParser.makeHttpRequest(StatusCheck, "GET", params);
    		
    		//Diagnostic message that dumps the JSON data to Logcat.
    		Log.d("Login attempt", json.toString());
    		
    		//Gets the status from the JSON data.
    		status = json.getInt(TAG_RESULT);
    		
    		//Diagnotics to see what the status value is.
    		Log.d("Status", String.valueOf(status));

    	} catch (JSONException e) {
    		e.printStackTrace();
    	}
    	return null;    		
  
    	}
    	
    	//Dismisses the dialog box and displays whether the door is open or closed.
    	protected void onPostExecute(String file_url) {
    		Dialog.dismiss();
    		if (status == 0){
    			TextView text = (TextView) findViewById(R.id.status);
    			text.setText("Close");
    		}else{
    			TextView text = (TextView) findViewById(R.id.status);
    			text.setText("Open");
    		}
    		
    		}
    }
}

Android App - XML

XML
XML file for the screen layout.
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context="com.example.garagebot.MainActivity" >

    <TextView
        android:id="@+id/textView1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_below="@+id/trigger"
        android:layout_centerHorizontal="true"
        android:layout_marginTop="35dp"
        android:text="Door Status"
        android:textAppearance="?android:attr/textAppearanceLarge" />

    <TextView
        android:id="@+id/status"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_below="@+id/textView1"
        android:layout_centerHorizontal="true"
        android:text="Open/Close"
        android:textAppearance="?android:attr/textAppearanceLarge" />

    <Button
        android:id="@+id/trigger"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentLeft="true"
        android:layout_alignParentRight="true"
        android:layout_alignParentTop="true"
        android:layout_marginTop="35dp"
        android:onClick="Trigger"
        android:text="Open/Close" />

    <Button
        android:id="@+id/refresh"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_below="@+id/status"
        android:layout_centerHorizontal="true"
        android:text="Refresh" />

</RelativeLayout>

Android App - JSON Parser

Java
This code makes the network calls and parses the JSON data.
package com.example.garagebot;

import java.io.BufferedReader; 
import java.io.IOException; 
import java.io.InputStream; 
import java.io.InputStreamReader; 
import java.io.UnsupportedEncodingException; 
import java.util.List;

import org.apache.http.HttpEntity; 
import org.apache.http.HttpResponse; 
import org.apache.http.NameValuePair; 
import org.apache.http.client.ClientProtocolException; 
import org.apache.http.client.entity.UrlEncodedFormEntity; 
import org.apache.http.client.utils.URLEncodedUtils;
import org.apache.http.client.methods.HttpGet; 
import org.apache.http.client.methods.HttpPost; 
import org.apache.http.impl.client.DefaultHttpClient; 
import org.apache.http.params.BasicHttpParams;
import org.apache.http.conn.ClientConnectionManager;
import org.apache.http.conn.ConnectTimeoutException;
import org.apache.http.conn.scheme.SchemeRegistry;
import org.apache.http.impl.client.BasicResponseHandler;
import org.apache.http.params.HttpConnectionParams;
import org.apache.http.params.HttpParams;
import org.json.JSONException; 
import org.json.JSONObject; 

import android.util.Log; 

public class JSONParser { 
    static InputStream is = null; 
    static JSONObject jObj = null; 
    static String json = "";
    static Integer timeoutConnection = 10000;
    static Integer timeoutSocket = 20000;

    // constructor 
    public JSONParser() { 

    } 

    public JSONObject getJSONFromUrl(final String url) { 
        // Making HTTP request 
        try { 
        	HttpPost httpPost = new HttpPost(url); 
        	
        	HttpParams httpParameters = new BasicHttpParams();
        	
        	HttpConnectionParams.setConnectionTimeout(httpParameters,  timeoutConnection);
        	
        	HttpConnectionParams.setSoTimeout(httpParameters,  timeoutSocket);
        	
        	// defaultHttpClient 
            DefaultHttpClient httpClient = new DefaultHttpClient(httpParameters); 
            
            HttpResponse httpResponse = httpClient.execute(httpPost); 
            HttpEntity httpEntity = httpResponse.getEntity(); 
            is = httpEntity.getContent(); 
        } catch (UnsupportedEncodingException e) { 
            e.printStackTrace(); 
        } catch (ClientProtocolException e) { 
            e.printStackTrace(); 
        } catch (IOException e) { 
            e.printStackTrace();
            Log.d("jsonparser", "Timeout");
        } 
        try { 
            BufferedReader reader = new BufferedReader(new InputStreamReader( 
                    is, "iso-8859-1"), 8); 

            StringBuilder sb = new StringBuilder(); 
            String line = null; 
            while ((line = reader.readLine()) != null) { 
                sb.append(line + "\n"); 
            } 
            is.close(); 
            json = sb.toString(); 
        } catch (Exception e) { 
            Log.e("Buffer Error", "Error converting result " + e.toString()); 
        } 

        // try parse the string to a JSON object 

        try { 

            jObj = new JSONObject(json); 

        } catch (JSONException e) { 

            Log.e("JSON Parser", "Error parsing data " + e.toString()); 

        } 

        // return JSON String 
        return jObj; 
 
    } 

    // function get json from url 
    // by making HTTP POST or GET method 
    public JSONObject makeHttpRequest(String url, String method, List<NameValuePair> params) { 
        // Making HTTP request 

        try { 

            // check for request method 
            if(method == "POST"){ 
                // request method is POST 
  
          // defaultHttpClient 
            	HttpPost httpPost = new HttpPost(url); 
            	
            	HttpParams httpParameters = new BasicHttpParams();
            	
            	HttpConnectionParams.setConnectionTimeout(httpParameters,  timeoutConnection);
            	
            	HttpConnectionParams.setSoTimeout(httpParameters,  timeoutSocket);
            	
            	DefaultHttpClient httpClient = new DefaultHttpClient(httpParameters);   
                   
                httpPost.setEntity(new UrlEncodedFormEntity(params)); 
                HttpResponse httpResponse = httpClient.execute(httpPost); 
                HttpEntity httpEntity = httpResponse.getEntity();   
                is = httpEntity.getContent(); 
                
            }else if(method == "GET"){ 
                // request method is GET 
            	HttpGet httpGet = new HttpGet(url); 
            	
            	HttpParams httpParameters = new BasicHttpParams();
            	
            	HttpConnectionParams.setConnectionTimeout(httpParameters,  timeoutConnection);
            	
            	HttpConnectionParams.setSoTimeout(httpParameters,  timeoutSocket);
            	
            	DefaultHttpClient httpClient = new DefaultHttpClient(httpParameters); 
                
                String paramString = URLEncodedUtils.format(params, "utf-8"); 
                url += "?" + paramString; 
                               
            	HttpResponse httpResponse = httpClient.execute(httpGet); 
                HttpEntity httpEntity = httpResponse.getEntity(); 
                is = httpEntity.getContent(); 
            }            

        } catch (UnsupportedEncodingException e) { 
            e.printStackTrace(); 
        } catch (ClientProtocolException e) { 
            e.printStackTrace(); 
        } catch (IOException e) { 
            e.printStackTrace(); 
            Log.d("jsonparser", "timeout");
        } 

        try { 
            BufferedReader reader = new BufferedReader(new InputStreamReader(is, "iso-8859-1"), 8); 
            StringBuilder sb = new StringBuilder(); 
            String line = null; 
            while ((line = reader.readLine()) != null) { 
                sb.append(line + "\n"); 
            }
            is.close(); 
            json = sb.toString(); 

        } catch (Exception e) { 
            Log.e("Buffer Error", "Error converting result " + e.toString()); 
        } 

        // try parse the string to a JSON object 
        try { 

            jObj = new JSONObject(json); 
        } catch (JSONException e) { 
            Log.e("JSON Parser", "Error parsing data " + e.toString()); 
        } 

        // return JSON String 
        return jObj; 

    } 

} 

Android App - Manifest

Java
You will need to add internet access the the Manifest file.
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.garagebot"
    android:versionCode="1"
    android:versionName="1.0" >

    <uses-sdk
        android:minSdkVersion="8"
        android:targetSdkVersion="21" />
    
    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />

    <application
        android:allowBackup="true"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >
        <activity
            android:name=".MainActivity"
            android:label="@string/app_name" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>

GarageBot Code

The zip folder labeled Garagebot.zip includes the complete Android Project. It was written using Eclipse. The file labeled GarageBot.ino is the firmware for the Particle Photon.

Credits

Courtney Achen

Courtney Achen

4 projects • 27 followers
Electro-Mechanical Engineer

Comments