So I would have to say that this is the largest automation/electronic project I have done so far, and I came out of it thinking that it wasn’t so bad. Wasn’t necessarily cheap, wasn’t necessarily hard, and a lot of things were in place already for me that made the project easier, but I am happy with the outcome and the price I paid.
My Problem.
I wanted a security system that I didn’t have to pay monthly for, but I also didn’t want to use a wireless solution. A) Because wireless is way more expensive than wired. B) Wireless can be defeated/interfered with using simple electronics. C) My house was already wired, so why not use what I already had and D) it was a fun learning experience. I have 9 windows and 3 doors that I wanted to monitor the status of and eventually use the “Smart Home Monitor” on the dashboard of the ST app.
My Background.
I am kind of an all around Geek. I love devices, computers, and just about anything that goes beep. I work in IT, mostly with networking, and am an amateur programmer. My first languages were C and BASIC (dating myself a bit here), but I have done more extensive work with Visual Basic, Visual C#, Powershell, ObjectPAL, Labview, Python, and a tiny bit of java script. I am by no means an expert programmer. However, I do know concepts and even though groovy is completely new to me, I do see where they have borrowed some ideas and concepts from other languages. Also, I did go to college for electronic engineering, however, I never really used the knowledge in 15 years outside of a couple small projects and have since lost most all of it. I mention all of this not to pop my collar or anything, but someone going into a project like this may need some of these fundamentals and concepts before getting started.
Assumptions, errata, and all the dumb things I did.
So, let me start off saying that what I ended up with may not be the cheapest solution, the best solution, or even the right solution. I may burn my house down with what I have done. However, if you see something I did wrong or stupid, definitely tell me. However, let’s all be nice and civil like as we are all here to help each other. That is why I am writing all of this up. If someone comes along and needs help like I did, maybe there is something I did that could help someone else. Having said that, I am not liable if you decide to do the same dumb things I did. This will serve as your only warning. 
Parts. Parts. Parts
I did cite cost as one of the main reasons I did this and essentially it was. However, that doesn’t mean I am above spending money. I also cited that I didn’t want to use wireless, but in a way, I still ended up with a wireless solution. So, yeah, there is a bit of a contradiction, but it is what it is.
The parts I used are:
Arduino with the ThingShield
Reed sensors from Amazon
Three terminal blocks
Some pre-made jumper wires and solid strand hookup wire
One large electrical junction box
One small electrical in-wall cut in box (is that the right name?)
Various screws, grommets, nuts, bolts, and stuff
First things first.
I discovered that all of the windows were wired to a temporary plug that I thought were sensors. Ha! So after posting in another thread asking if anyone knew what the hell they were, and after finally ripping them out, I found out that they were just plugs to hold the wires that were already run in my house. So after about 80 dollars in sensors from Amazon, I was good to go. Here are some pictures of the steps. I think they are pretty straight forward so I won’t explain all of the steps, except for the first picture. The first picture is the plug I was referring to that were holding the wires.


Hopefully you get the idea.
Problem Number 1!
I guess in an effort to save money, wiring, whatever, some of the windows were wired together. In other words, one window would have a wire going to another window, before going back to where the panel should be. So I decided to wire them together in series. Since the sensors are normally closed with magnet, one opening would still trigger the circuit open. So basically on one window, you will have one pair of wires, in the next window, you will have two pair. All you have to do is expose the wire on the window with one pair. On the window with two, expose the wire and then short one of the pairs.
Using a multi-meter, set it to the ‘beep’ on continuity setting and see if you have continuity on the window with only one pair. If not, short the other pair and see. Once you have identified the pair that goes to the single pair window, you can take the negative lead of the pair going back to the panel and the positive lead of the pair going to the other window and short those together. Giving you something that looks like this:
Next, I just used a crimp connector to splice the two wires together which leaves you with a single positive and negative pair, like this:
Finally, I used some shrink tubing and wired the sensor up:
For the doors I just used some Honeywell Form A SPST Reeds. Hardest part was drilling the hole.
Mock it Up!
So after I learned how to use the Arduino and ThingShield:
I decided how I wanted to mount all of this in the box. The box is just a large junction box that seemed to fit what I wanted to do. It was pretty much all I could find that would work at Home Depot and Lowe’s, but I am happy with the outcome. I then mounted the Arduino to an in-wall cut-in box just to give it a little elevation so it would make wiring a little easier. It’s a little large but I have large hands and didn’t want too much difficulty wiring.
After it was all mocked up and how I wanted it, I got to wiring:
So basically what you have here is that all of the reed sensors are switches and since they are normally closed with magnet switches, you have to have something going down the wire at all times to detect whether the circuit is complete or not. If it’s not, we let the hub know about it. So forgive me for not giving a wiring diagram as I am lazy and think I can explain it just as well. Since all of the sensors are the same, and all need 5v, I took the terminal block you see on the left of the picture, and shorted all of the connections together with some hookup wire. I then connected the 5v pin on the Arduino on the bottom left connector, and then wired the positive side of the sensor to each individual screw. The negative side of the sensor is connected to the block on the right. The other side of that block is connected to the pin I am monitoring on the Arduino AND ground with a 220k resistor soldered inline. So the block at the top is similar to the 5v side. All of the connectors are shorted with the top left connection going to the GND connector on the Arduino.
The flow is kinda like this: Arduino 5v --> Positive Red Wire --> Sensor --> Negative Black Wire --> Arduino PIN AND 220k resistor --> from resistor only --> Arduino GND. If this is too confusing I may draw something up later. (This is long!)
Could I have done end of line resistors and also detected tampering? Yeah, but then I would only have 4 analog PINs and I am only using an UNO. So that might be another addition to the project down the road.
And after everything was working, mounted I it:
The Code!
Oh the humanity. 
I say that because the documentation is VERY sparse. Shame on Samsung for releasing this with very limited documentation. However, some thanks and credits are due. I can’t thank everyone because I can’t remember the hundred or so pages and posts I read and youtube videos I watched to cobble this all together. However, the main thanks goes to stevesell, Dan “ogiewon”, and lailoken on the message board here. Without you guys, I would have had A LOT lot harder time.
On the Ardiuno side I used mostly what lailoken came up with on the ‘Arduino SmartShield Garage Controller’ post of this board. I modified it for my connections and also added a polling feature. I added it because every time I install my SmartApp it doesn’t seem to update the state on the first go. So I have the SmartApp send a poll() and the Arduino responds with the current state of the pins.
/**
* Arduino Contact Sensor Monitor
*
*/
//*****************************************************************************
#include <SoftwareSerial.h>
#include <SmartThings.h>
//*****************************************************************************
// Pin Definitions
//*****************************************************************************
#define PIN_THING_RX 3
#define PIN_THING_TX 2
#define PIN_RESERVED 6
#define PIN_OFFICE_CONTACT 4 // input
#define PIN_DININGROOM_CONTACT 5 // input
#define PIN_BEDROOM_CONTACT 7 // input
#define PIN_LIVINGROOM_CONTACT 8 // input
#define PIN_KITCHEN_CONTACT 9 // input
#define PIN_FRONTDOOR_CONTACT 10 // input
#define PIN_BACKDOOR_CONTACT 11 // input
#define PIN_GARAGEDOOR_CONTACT 12 // input
#define OPEN 1 // HIGH
#define CLOSED 0 // LOW
#define UNKNOWN 2 // --- reset / force update
//*****************************************************************************
// Global Variables
//*****************************************************************************
SmartThingsCallout_t messageCallout; // call out function forward decalaration
SmartThings smartthing(PIN_THING_RX, PIN_THING_TX, messageCallout); // constructor
int officeStatus = UNKNOWN;
int diningRoomStatus = UNKNOWN;
int bedroomStatus = UNKNOWN;
int livingRoomStatus = UNKNOWN;
int kitchenStatus = UNKNOWN;
int frontDoorStatus = UNKNOWN;
int backDoorStatus = UNKNOWN;
int garageDoorStatus = UNKNOWN;
bool isDebugEnabled=true; // enable or disable debug in this example
int stateLED; // state to track last set value of LED
int stateNetwork; // state of the network
//*****************************************************************************
// Logic
//*****************************************************************************
int contactState(int pin)
{
// LOW -> closed
// HIGH -> open
return (digitalRead(pin) == HIGH)?CLOSED:OPEN;
}
void updateContactStatus()
{
int currentStatus;
char* msg = NULL;
currentStatus = contactState(PIN_OFFICE_CONTACT);
if (officeStatus != currentStatus)
{
officeStatus = currentStatus;
if(officeStatus == CLOSED) msg = "office closed";
else msg = "office open";
smartthing.shieldSetLED(0, 2, 0); // green
smartthing.send(msg);
if(isDebugEnabled) Serial.println(msg);
return; // only one message per loop
}
currentStatus = contactState(PIN_DININGROOM_CONTACT);
if (diningRoomStatus != currentStatus)
{
diningRoomStatus = currentStatus;
if(diningRoomStatus == CLOSED) msg = "diningroom closed";
else msg = "diningroom open";
smartthing.shieldSetLED(0, 2, 0); // green
smartthing.send(msg);
if(isDebugEnabled) Serial.println(msg);
return; // only one message per loop
}
currentStatus = contactState(PIN_BEDROOM_CONTACT);
if (bedroomStatus != currentStatus)
{
bedroomStatus = currentStatus;
if(bedroomStatus == CLOSED) msg = "bedroom closed";
else msg = "bedroom open";
smartthing.shieldSetLED(0, 2, 0); // green
smartthing.send(msg);
if(isDebugEnabled) Serial.println(msg);
return; // only one message per loop
}
currentStatus = contactState(PIN_LIVINGROOM_CONTACT);
if (livingRoomStatus != currentStatus)
{
livingRoomStatus = currentStatus;
if(livingRoomStatus == CLOSED) msg = "livingroom closed";
else msg = "livingroom open";
smartthing.shieldSetLED(0, 2, 0); // green
smartthing.send(msg);
if(isDebugEnabled) Serial.println(msg);
return; // only one message per loop
}
currentStatus = contactState(PIN_KITCHEN_CONTACT);
if (kitchenStatus != currentStatus)
{
kitchenStatus = currentStatus;
if(kitchenStatus == CLOSED) msg = "kitchen closed";
else msg = "kitchen open";
smartthing.shieldSetLED(0, 2, 0); // green
smartthing.send(msg);
if(isDebugEnabled) Serial.println(msg);
return; // only one message per loop
}
currentStatus = contactState(PIN_FRONTDOOR_CONTACT);
if (frontDoorStatus != currentStatus)
{
frontDoorStatus = currentStatus;
if(frontDoorStatus == CLOSED) msg = "frontdoor closed";
else msg = "frontdoor open";
smartthing.shieldSetLED(0, 2, 0); // green
smartthing.send(msg);
if(isDebugEnabled) Serial.println(msg);
return; // only one message per loop
}
currentStatus = contactState(PIN_BACKDOOR_CONTACT);
if (backDoorStatus != currentStatus)
{
backDoorStatus = currentStatus;
if(backDoorStatus == CLOSED) msg = "backdoor closed";
else msg = "backdoor open";
smartthing.shieldSetLED(0, 2, 0); // green
smartthing.send(msg);
if(isDebugEnabled) Serial.println(msg);
return; // only one message per loop
}
currentStatus = contactState(PIN_GARAGEDOOR_CONTACT);
if (garageDoorStatus != currentStatus)
{
garageDoorStatus = currentStatus;
if(garageDoorStatus == CLOSED) msg = "garagedoor closed";
else msg = "garagedoor open";
smartthing.shieldSetLED(0, 2, 0); // green
smartthing.send(msg);
if(isDebugEnabled) Serial.println(msg);
return; // only one message per loop
}
}
//*****************************************************************************
void setNetworkStateLED()
{
SmartThingsNetworkState_t tempState = smartthing.shieldGetLastNetworkState();
if (tempState != stateNetwork)
{
switch (tempState)
{
case STATE_NO_NETWORK:
if (isDebugEnabled) Serial.println("ST Network State is : NO_NETWORK");
smartthing.shieldSetLED(2, 2, 0); // red
break;
case STATE_JOINING:
if (isDebugEnabled) Serial.println("ST Network State is : JOINING");
smartthing.shieldSetLED(2, 2, 0); // yellow
break;
case STATE_JOINED:
if (isDebugEnabled) Serial.println("ST Network State is : JOINED");
smartthing.shieldSetLED(0, 0, 2); // blue
// force report of current door state
officeStatus = UNKNOWN;
diningRoomStatus = UNKNOWN;
bedroomStatus = UNKNOWN;
livingRoomStatus = UNKNOWN;
kitchenStatus = UNKNOWN;
frontDoorStatus = UNKNOWN;
backDoorStatus = UNKNOWN;
garageDoorStatus = UNKNOWN;
break;
case STATE_JOINED_NOPARENT:
if (isDebugEnabled) Serial.println("ST Network State is : JOINED_NOPARENT");
smartthing.shieldSetLED(2, 0, 2); // purple
break;
case STATE_LEAVING:
if (isDebugEnabled) Serial.println("ST Network State is : LEAVING");
smartthing.shieldSetLED(2, 2, 0); // yellow
break;
default:
case STATE_UNKNOWN:
if (isDebugEnabled) Serial.println("ST Network State is : UNKNOWN");
smartthing.shieldSetLED(2, 0, 0); // red
break;
}
stateNetwork = tempState;
}
}
//*****************************************************************************
// API Functions | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
// V V V V V V V V V V V V V V V V V V V V V V V V V V V V V V
//*****************************************************************************
void setup()
{
// setup default state of global variables
isDebugEnabled = true;
stateNetwork = STATE_JOINED; // set to joined to keep state off if off
// setup hardware pins
pinMode(PIN_OFFICE_CONTACT, INPUT);
pinMode(PIN_DININGROOM_CONTACT, INPUT);
pinMode(PIN_BEDROOM_CONTACT, INPUT);
pinMode(PIN_LIVINGROOM_CONTACT, INPUT);
pinMode(PIN_KITCHEN_CONTACT, INPUT);
pinMode(PIN_FRONTDOOR_CONTACT, INPUT);
pinMode(PIN_BACKDOOR_CONTACT, INPUT);
pinMode(PIN_GARAGEDOOR_CONTACT, INPUT);
if(isDebugEnabled)
{ // setup debug serial port
Serial.begin(9600); // setup serial with a baud rate of 9600
Serial.println("Starting up.."); // print out 'setup..' on start
}
}
//*****************************************************************************
void loop()
{
// run smartthing logic
smartthing.run();
// Check network connections (and send initial states on Join)
setNetworkStateLED();
if(stateNetwork == STATE_JOINED)
{
// Check the open/closed state of the doors
updateContactStatus();
}
}
//*****************************************************************************
void messageCallout(String message)
{
smartthing.shieldSetLED(2, 2, 2); // white
// if debug is enabled print out the received message
if(isDebugEnabled)
{
Serial.print("Received message: '");
Serial.print(message);
Serial.println("' ");
}
if(message.equals("poll"))
{
// if asked for polling update then force update by setting all devices to unknown.
officeStatus = UNKNOWN;
diningRoomStatus = UNKNOWN;
bedroomStatus = UNKNOWN;
livingRoomStatus = UNKNOWN;
kitchenStatus = UNKNOWN;
frontDoorStatus = UNKNOWN;
backDoorStatus = UNKNOWN;
garageDoorStatus = UNKNOWN;
}
smartthing.shieldSetLED(0, 0, 0); // off
}
Next, I needed to set up my Device Type code. To interact with the Arduino:
/**
* Arduino Contact Sensor Monitor
*
*/
metadata {
definition (name: "Arduino Contact Sensor Monitor", author: "Chrisotpher Etheridge") {
fingerprint profileId: "0104", deviceId: "0138", inClusters: "0000"
// capability "Sensor"
// capability "Contact Sensor"
attribute "office", "string"
attribute "diningroom", "string"
attribute "bedroom", "string"
attribute "livingroom", "string"
attribute "kitchen", "string"
attribute "frontdoor", "string"
attribute "backdoor", "string"
attribute "garagedoor", "string"
command "poll"
}
simulator {
}
// Preferences
// tile definitions
tiles {
standardTile("office", "device.office", width: 1, height: 1, canChangeIcon: true, canChangeBackground: true) {
state "closed", label: "Closed", icon: "st.contact.contact.closed", backgroundColor: "#79b821"
state "open", label: "Open", icon: "st.contact.contact.open", backgroundColor: "#ffa81e"
}
standardTile("diningroom", "device.diningroom", width: 1, height: 1, canChangeIcon: true, canChangeBackground: true) {
state "closed", label: "Closed", icon: "st.contact.contact.closed", backgroundColor: "#79b821"
state "open", label: "Open", icon: "st.contact.contact.open", backgroundColor: "#ffa81e"
}
standardTile("bedroom", "device.bedroom", width: 1, height: 1, canChangeIcon: true, canChangeBackground: true) {
state "closed", label: "Closed", icon: "st.contact.contact.closed", backgroundColor: "#79b821"
state "open", label: "Open", icon: "st.contact.contact.open", backgroundColor: "#ffa81e"
}
standardTile("livingroom", "device.livingroom", width: 1, height: 1, canChangeIcon: true, canChangeBackground: true) {
state "closed", label: "Closed", icon: "st.contact.contact.closed", backgroundColor: "#79b821"
state "open", label: "Open", icon: "st.contact.contact.open", backgroundColor: "#ffa81e"
}
standardTile("kitchen", "device.kitchen", width: 1, height: 1, canChangeIcon: true, canChangeBackground: true) {
state "closed", label: "Closed", icon: "st.contact.contact.closed", backgroundColor: "#79b821"
state "open", label: "Open", icon: "st.contact.contact.open", backgroundColor: "#ffa81e"
}
standardTile("frontdoor", "device.frontdoor", width: 1, height: 1, canChangeIcon: true, canChangeBackground: true) {
state "closed", label: "Closed", icon: "st.contact.contact.closed", backgroundColor: "#79b821"
state "open", label: "Open", icon: "st.contact.contact.open", backgroundColor: "#ffa81e"
}
standardTile("backdoor", "device.backdoor", width: 1, height: 1, canChangeIcon: true, canChangeBackground: true) {
state "closed", label: "Closed", icon: "st.contact.contact.closed", backgroundColor: "#79b821"
state "open", label: "Open", icon: "st.contact.contact.open", backgroundColor: "#ffa81e"
}
standardTile("garagedoor", "device.garagedoor", width: 1, height: 1, canChangeIcon: true, canChangeBackground: true) {
state "closed", label: "Closed", icon: "st.contact.contact.closed", backgroundColor: "#79b821"
state "open", label: "Open", icon: "st.contact.contact.open", backgroundColor: "#ffa81e"
}
main(["office","diningroom","bedroom","livingroom","kitchen","frontdoor","backdoor","garagedoor"])
details(["office","diningroom","bedroom","livingroom","kitchen","frontdoor","backdoor","garagedoor"])
}
}
def parse(String description) {
def msg = zigbee.parse(description)?.text
log.debug "Parse got '${msg}'"
def parts = msg.split(" ")
def name = parts.length>0?parts[0].trim():null
def value = parts.length>1?parts[1].trim():null
name = value != "ping" ? name : null
def result = createEvent(name: name, value: value)
log.debug result
return result
}
def poll() {
log.debug "Polling requested"
zigbee.smartShield(text: "poll").format()
}













