How it started…
The office I currently work at is located in a building that has an interphone system. So when any of us wants to get in, just push the button an awaits for someone to answer and push a button on the interphone auricular to open the door.
The problem arise when there’s no one inside (or is in the bathroom) to open the door.
So we came up with the idea of creating a service to open the door with the phone. How do we do this?
The algorithm goes something like this:
1) Find out how the auricular button works
2) Create a circuit to hack the signal
3) Code a service to activate the circuit
4) Code a phone application to communicate with the service
So let’s get it on!
Find out how the auricular works
Fortunately, I work with very skilled folks. So I asked one of them, Javier, to take a look at the device. It turns out that the door works with a magnetic device. The button interrupts the power that keeps the magnet energized. It does that by touching 2 small plates. It couldn’t be any simpler.
Create a circuit to hack the signal
Using a breadboard, Javier came up with a circuit that consisted of a relay and an arduino (together with an ethernet shield). The idea was to hook some cables into the plates, and use the relay to close the circuit. To activate the relay, we would have to send an instruction to the Arduino connected to the modem. So all we have to do it’s to connect to the wireless network and send a command to the Arduino’s ip address.
Code a service to activate the circuit
Since i didn’t have any significative experience coding anything on an Arduino (though I had coded something for a rabbit microcontroller before) i went with one of the demos for a web server. After some tweaking and testing, ended up with something like:
#include <SPI.h> #include <Ethernet.h> // Enter a MAC address and IP address for your controller below. // The IP address will be dependent on your local network: byte mac[] = { 0x60, 0xA5, 0xEA, 0x0E, 0x07, 0x10 }; IPAddress ip(200, 200, 200, 200); EthernetServer server(80); void setup() { // Open serial communications and wait for port to open: Serial.begin(9600); pinMode(7,OUTPUT); while (!Serial) { ; // wait for serial port to connect. Needed for native USB port only } // start the Ethernet connection and the server: Ethernet.begin(mac, ip); server.begin(); Serial.print("server is at "); Serial.println(Ethernet.localIP()); } void loop() { // listen for incoming clients EthernetClient client = server.available(); if (client) { Serial.println("new client"); // an http request ends with a blank line boolean currentLineIsBlank = true; String currentLine = ""; String command = ""; while (client.connected()) { if (client.available()) { char c = client.read(); currentLine = currentLine + c; // if you've gotten to the end of the line (received a newline // character) and the line is blank, the http request has ended, // so you can send a reply if (c == '\n' && currentLineIsBlank && command == "some command") { digitalWrite(7, HIGH); delay(1000); digitalWrite(7, LOW); //delay(1000); // send a standard http response header client.println("HTTP/1.1 200 OK"); client.println("Content-Type: text/html"); client.println("Connection: close"); // the connection will be closed after completion of the response client.println(); client.println("<!DOCTYPE HTML>"); client.println("<html>"); client.println(command); client.println("</html>"); command = ""; break; } // you're starting a new line if (c == '\n') { currentLineIsBlank = true; Serial.println("current line = " + currentLine); currentLine = ""; } // you've gotten a character on the current line else if (c != '\r') { currentLineIsBlank = false; } //get the command else if (c == '\r' and currentLine.startsWith("GET")){ int start = currentLine.indexOf('/')+1; int endAt = currentLine.indexOf(' ',start); command = currentLine.substring(start, endAt); } } } // give the web browser time to receive the data delay(1); // close the connection: client.stop(); Serial.println("client disconnected"); Ethernet.maintain(); } }
The idea behind was to provide a web API that listens for the request to a particular URL. It then extracts the last part of the requested url and uses that command to activate the relay and therefore close the door. Anyone with the ip address and the right URL can activate the relay, as long as it’s one the same subnet as the Arduino.
Code a phone application to communicate with the service
So, Josue (another coworker) suggested that since I had created the web api I could as well create a phone app to consume it. Since most of the people on the office use an android phone, i thought this would be a good opportunity to test the platform. I have zero knowledge of the Android programming model, so on Josues suggestion I took a look to Xamarin. It turn out to be fairly simple. I still have to learn more of the platform tough….
Here’s the code:
[Activity(Label = "Jarvis", MainLauncher = true, Icon = "@drawable/icon")] public class MainActivity : Activity { private string url = "http://200.200.200.200/"; protected override void OnCreate(Bundle bundle) { base.OnCreate(bundle); // Set our view from the "main" layout resource SetContentView(Resource.Layout.Main); // Get our button from the layout resource, // and attach an event to it Button button = FindViewById<Button>(Resource.Id.MyButton); TextView text = FindViewById<TextView>(Resource.Id.textView1); button.Click += async(sender,e) => { try { await send(jarvisCommands.openDoor); text.Text += "Get in! \n\r"; } catch (Exception ex) { text.Text += ex.Message + "\n\r" + Resources.GetString(Resource.String.Error) + "\n\r"; } }; } private async Task send(jarvisCommands command) { HttpWebRequest request = (HttpWebRequest) HttpWebRequest.Create(new Uri(url + command.ToString())); request.ContentType = "application/text"; request.Method = "GET"; await request.GetResponseAsync(); } enum jarvisCommands { openDoor} }
Learned things:
1) Necessity is the mother of ingenuity
2) You can create interesting stuff when you are surrounded by interesting people
3) If you know Java, C++, C# or any other curly braces language, odds are that you’re already capable of writing something for the Arduino
4) The Intent concept on the Android platform it’s just an implementation of a message bus
I think this is it. Until the next post! (I’ll write often, promise)