Story

In this project I used a Particle Photon to control my garage door via an Android App. The app has a button on screen that you press to open and close the door. It also checks the status of the door so you know if it is open or closed.

This is my first project with the Particle Photon. The Photon is super easy to use and I was able to find a lot of good tutorials online.

However I couldn't find any good tutorials regarding integrating it with an Android App. So I decided to post my code.

I used a simple relay to control the door. Most garage door openers have 2 wires and by pressing the button you just short the wires together. Disclaimer - This worked on my door but I can't guarantee it will work on all doors. Test your door with a multi-meter to make sure it is just shorting the 2 wires together. I just spliced into the wiring running to the door switch.

caption (optional)

For checking the door status I used a magnetic reed switch with a magnet on the door. However you can use any sensor you want.

Proximity Sensor - Detects when the door is open

The code for the Photon and Android App are listed below. The only thing I will probably change in the future is putting a timeout in the Android app so if the app can't communicate to the Photon it will simply timeout instead of eventually crashing the app as it does now.

Schematics

Breadboard Schematic

Code

Firmware - GarageBotArduino

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 closedintdoor=D1;intstatus=D4;intstatusvalue;voidsetup(){// Sets the door relay pin as an output and the status pin as an inputpinMode(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);}voidloop(){// Constantly checks the status of the door (open or closed). statusvalue=digitalRead(status);}// This gets called if the Spark Cloud commands a door open/closeintdoorToggle(Stringcommand){// 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);return1;}elseif(command=="off"){digitalWrite(door,LOW);return0;}else{return-1;}}

Android App - Main ActivityJava

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.

packagecom.example.garagebot;importjava.util.ArrayList;importjava.util.List;importorg.apache.http.NameValuePair;importorg.apache.http.message.BasicNameValuePair;importorg.json.JSONException;importorg.json.JSONObject;importandroid.os.Bundle;importandroid.app.Activity;importandroid.view.View.OnClickListener;importandroid.app.ProgressDialog;importandroid.content.Intent;importandroid.content.SharedPreferences;importandroid.content.SharedPreferences.Editor;importandroid.os.AsyncTask;importandroid.preference.PreferenceManager;importandroid.util.Log;importandroid.view.Menu;importandroid.view.MenuInflater;importandroid.view.MenuItem;importandroid.view.View;importandroid.widget.Button;importandroid.widget.EditText;importandroid.widget.TabHost;importandroid.widget.TextView;importandroid.widget.Toast;publicclassMainActivityextendsActivityimplementsOnClickListener{publicButtonmTrigger,mRefresh;publicStringsavedstatus,statusString;publicIntegerstatus;// Progress Dialog publicProgressDialogDialog;// JSON parser class JSONParserjsonParser=newJSONParser();//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.privatestaticfinalStringTrigger="https://api.particle.io/v1/devices/Your Photon Id/led?access_token=Your Access Token";privatestaticfinalStringStatusCheck="https://api.particle.io/v1/devices/Your Photon Id/status?access_token=Your Access Token";//JSON element ids from response of php script: privatestaticfinalStringTAG_SUCCESS="return_value";privatestaticfinalStringTAG_RESULT="result";@OverridepublicvoidonCreate(BundlesavedInstanceState){// 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);newCheckStatus().execute();}@OverridepublicvoidonClick(Viewv){switch(v.getId()){//When the Open/Close button is pressed the Trigger function is executed.caseR.id.trigger:newTrigger().execute();break;//When the Refresh button is pressed the CheckStatus function is executed.caseR.id.refresh:newCheckStatus().execute();}}//The Trigger function opens and closes the door.protectedclassTriggerextendsAsyncTask<String,String,String>{booleanfailure=false;//Pops up a dialog box saying the the door is opening or closing.@OverrideprotectedvoidonPreExecute(){super.onPreExecute();Dialog=newProgressDialog(MainActivity.this);Dialog.setMessage("Opening/Closing...");Dialog.setIndeterminate(false);Dialog.setCancelable(true);Dialog.show();}//The network call is done on a background thread.@OverrideprotectedStringdoInBackground(String...args){try{//Sets up the parameters to send to the Spark Cloud.List<NameValuePair>params=newArrayList<NameValuePair>();params.add(newBasicNameValuePair("args","on"));//Calls the JSON parser which sends a POST to the Spark Cloud.JSONObjectjson=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.intsuccess=json.getInt(TAG_SUCCESS);}catch(JSONExceptione){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(InterruptedExceptione){e.printStackTrace();}returnnull;}//Dismisses the dialog box and checks the status of the door.protectedvoidonPostExecute(Stringfile_url){Dialog.dismiss();newCheckStatus().execute();}}//This function checks whether the door is up or down.protectedclassCheckStatusextendsAsyncTask<String,String,String>{booleanfailure=false;//Pops up a dialog box saying the the door status is being checked.@OverrideprotectedvoidonPreExecute(){super.onPreExecute();Dialog=newProgressDialog(MainActivity.this);Dialog.setMessage("Checking Door Status...");Dialog.setIndeterminate(false);Dialog.setCancelable(true);Dialog.show();}//The network call is done in a background thread.@OverrideprotectedStringdoInBackground(String...args){try{List<NameValuePair>params=newArrayList<NameValuePair>();//Sends a GET request to the Spark Cloud to retrieve the door status.JSONObjectjson=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(JSONExceptione){e.printStackTrace();}returnnull;}//Dismisses the dialog box and displays whether the door is open or closed.protectedvoidonPostExecute(Stringfile_url){Dialog.dismiss();if(status==0){TextViewtext=(TextView)findViewById(R.id.status);text.setText("Close");}else{TextViewtext=(TextView)findViewById(R.id.status);text.setText("Open");}}}}