Differences
This shows you the differences between two versions of the page.
| Both sides previous revision Previous revision Next revision | Previous revision | ||
| homegrown_security_system [2013/08/09 17:33] – jay | homegrown_security_system [2026/04/07 18:27] (current) – external edit 127.0.0.1 | ||
|---|---|---|---|
| Line 1: | Line 1: | ||
| + | ====== Building a Security System with Indigo 6 or greater ====== | ||
| + | When we purchased a travel trailer (TT for short), I hadn't really given much thought to doing any automation. On our first outing with it, my spouse asked me if I could add some kind of security system. Of course, I jumped at the chance. Another thing we quickly found was that the lighting in the TT, particularly at night, was pretty awful - with the overhead lights on, it was glaringly bright direct light (pancakes in R | ||
| + | V terms). With them off, it was too dark. We have lots of indirect lights in our house, so I needed to figure out a way to do that in the TT as well. | ||
| + | |||
| + | Before we get into the details, a bit of a warning: this article addresses some pretty complex requirements and therefore it's a pretty complex solution. I don't take the step-by-step approach to implementation as we do in some of the How-To articles: if you're ready to implement a homegrown alarm system, you should probably already be fairly familiar with Indigo. If you find yourself becoming frustrated because you don't understand some of the concepts, I recommend digging into the documentation deeper on those specific topics to help gain a better understanding of how they work. I've provided links to the documentation for most of the concepts used in this article to help you jump directly to the specific discussion. Indigo is a complex DIY automation system and the best way to learn is to experiment. We have a lot of step-by-step [[start|How-To articles in the wiki]] that will help you get started. | ||
| + | |||
| + | A quick note on text styling conventions that I'll be using throughout the rest of this article: Indigo object types (Trigger, Action Group, etc.) will be links to their respective section of the documentation. Object names in this solution will be in italics (//30 Second Timer//, //Arm Security System//, etc.). Specific values will be in '' | ||
| + | |||
| + | ==== My Requirements ==== | ||
| + | I thought about my requirements and made a list of functions/ | ||
| + | |||
| + | - Sensors - various sensors to detect when the TT (zone) had been breached. | ||
| + | - Zone - a way to create a single object that represented the TT via a collection of sensors. | ||
| + | - Device to Arm/Disarm that didn't require a lot of work (I didn't want to have to use the Mac directly). Preferably a remote control that could also be used to operate the lighting (see above). | ||
| + | - Alert - some way to alert that the system had faulted. This might include email but would definitely require some kind of audio siren and potentially visual cue. | ||
| + | - Arm the system - complete with an audio countdown (30 seconds) for exiting the TT before it actually armed. | ||
| + | - Disarm the system - also with a 30-second countdown to complete the disarm process before the alarm faulted. Disarm also needed to cancel the arming process if it hadn't finished yet (i.e. you forgot something while exiting). | ||
| + | |||
| + | === Selecting the Technology === | ||
| + | We would be carrying my MacBook Pro with all of our video media on it and have it connected to the TV so that we could watch anything we want. So, my first thought about automation would be to use the PowerLinc 2448 (RF only dongle) that I have along with a LampLinc to control some kind of 110v lighting (to solve my lighting problem). I also had a TriggerLinc (Door/ | ||
| + | |||
| + | My next thought was to use Z-Wave - it was a new technology to us but I felt pretty good about using it. So, I put in a Z-Wave lamp module and connected the Z-Stick to my Mac. It worked perfectly. Now on to the plans for the security system (you can read more about [[how I solved my lighting problem]] if you're interested but it is secondary to this discussion). | ||
| + | |||
| + | === Selecting the Devices === | ||
| + | For <color green># | ||
| + | |||
| + | {{: | ||
| + | |||
| + | You might ask why I don't just flip the sensor over so the tamper switch is on the bottom rather than the top. Apparently the sensor is on one side of the device so if it's upside down it won't detect the magnet. In any event, this solution seems to be working fine. | ||
| + | |||
| + | The other sensor is an [[http:// | ||
| + | |||
| + | <color green># | ||
| + | |||
| + | {{: | ||
| + | |||
| + | So, much like a zone in your home's security system, which shows a light on your keypads whenever one of the sensors in the zone is open, the //Alarm Zone 1// will show **ON** in Indigo whenever motion is detected, the door is open, or the door sensor has been removed from the wall. | ||
| + | |||
| + | For <color green># | ||
| + | |||
| + | <color green># | ||
| + | |||
| + | One more Indigo device that I added was a Timer Device called //30 Second Timer// which will be used for the entry and exit countdowns and for arming and faulting the system as appropriate. We'll discuss it more throughout the rest of this article. See below the full device list for the alarm devices. The //Remote// and the lights used for parts of the system are in other folders. | ||
| + | |||
| + | {{: | ||
| + | |||
| + | ==== Implementing the Logic ==== | ||
| + | So, once I had the devices in place, it was time to make them work together. I ended up using about every type of object and feature that Indigo provides. This makes it an ideal article to showcase Indigo' | ||
| + | |||
| + | === Arming === | ||
| + | The next task, then, was to figure out how to arm the system. The high-level requirements for arming were this: | ||
| + | |||
| + | - Single operation (button press) to begin the arming process. | ||
| + | - Single operation (button press) to stop the arming process (we'll discuss that in the [[# | ||
| + | - A spoken 30-second countdown that would speak every 5 seconds how much time was left - and the last 5 seconds needed to be a 5-4-3-2-1 countdown. | ||
| + | - An audible beep - once a second during the 30 second countdown (like the alarm system in our house). | ||
| + | |||
| + | == Parts == | ||
| + | There are quite a few moving parts, so I'm going to list each Indigo object used in Arming the system first, then tie them all together. So, here's the list: | ||
| + | |||
| + | * //Alarm Button Pressed to Arm// [[indigo_6_documentation: | ||
| + | * //Countdown Beep// [[indigo_6_documentation: | ||
| + | * //Timer Expires While Exiting// [[indigo_6_documentation: | ||
| + | * // | ||
| + | * //Exit TT// [[indigo_6_documentation: | ||
| + | * //Speak Message Upon Exiting// [[indigo_6_documentation: | ||
| + | * //Speak Seconds Only// [[indigo_6_documentation: | ||
| + | * //Create 5 Second Countdown Pester// [[indigo_6_documentation: | ||
| + | * //Arm System// [[indigo_6_documentation: | ||
| + | |||
| + | == Arming Trigger == | ||
| + | I decided that starting the arming process would be accomplished by a press of button #4 on //Remote// and that disarming would be a press and hold on button #4, so those would be the triggering events. Here's the //Alarm Button Pressed to Arm// trigger definition: | ||
| + | |||
| + | {{: | ||
| + | |||
| + | Part of the solution requires that a variable, '' | ||
| + | |||
| + | The conditions for the //Alarm Button Pressed to Arm// trigger are pretty simple: we only want to arm the system if it's currently '' | ||
| + | |||
| + | {{: | ||
| + | |||
| + | The actions for the trigger have been encapsulated in the //Exit TT// action group: | ||
| + | |||
| + | {{: | ||
| + | |||
| + | We'll discuss each of these in the next section. | ||
| + | |||
| + | == Exiting Actions == | ||
| + | So, when you arm an alarm system, you don't want it to come on immediately - if it did, then when you opened the door to leave the system would go off. So you need some time to exit the TT before the system actually arms itself. That's what the //Exit TT// action group does. I separated it out into an action group rather than performing the actions directly in the //Alarm Button Pressed to Arm// trigger in case I decided to add another way to start the exiting process. | ||
| + | |||
| + | //**Start Timer**// | ||
| + | |||
| + | The first action starts the //30 Second Timer//. This timer will provide the next pester with the amount of time left before the system becomes armed. And if the timer runs out (isn't stopped prematurely) another trigger will fire that will actually arm the system (discussed a bit later). | ||
| + | |||
| + | //**Create Pester**// | ||
| + | |||
| + | The next action creates a [[plugins: | ||
| + | |||
| + | {{: | ||
| + | |||
| + | This pester cycles every 5 seconds for 5 times. Each cycle will execute the //Speak Message Upon Exiting// action group. The only action in this Action Group at the moment is the following embedded Python script: | ||
| + | |||
| + | {{: | ||
| + | |||
| + | This script gets the timer device and uses the " | ||
| + | |||
| + | The final action of the pester is different - it's the //Create 5 Second Countdown Pester// action group. There are 2 actions in this action group: to speak the number 5 (since the group will be executed exactly 5 seconds before the timer expires): | ||
| + | |||
| + | {{: | ||
| + | |||
| + | and another Create Pester action that creates a pester called //5 Second Countdown// that repeats every second for 5 times. The action group that's executed for all iterations is the //Speak Seconds Only// group. The only action in this group is an embedded Python script shown on the right: | ||
| + | |||
| + | {{: | ||
| + | |||
| + | This script does almost exactly the same thing that the last script does but it just says the number of seconds left with no other text. | ||
| + | |||
| + | //**Speak Text**// | ||
| + | |||
| + | The next action in the //Exit TT// action group is for it to speak the string '' | ||
| + | |||
| + | //**Set Variable**// | ||
| + | |||
| + | The final action in the group is to set the '' | ||
| + | |||
| + | == Countdown Beep == | ||
| + | I also wanted an audible beep, once a second, while counting down the timer (like what my home alarm does). That's what this trigger is for: | ||
| + | |||
| + | {{: | ||
| + | |||
| + | It's actually a pretty simple trigger: any time //30 Second Timer//' | ||
| + | |||
| + | {{: | ||
| + | |||
| + | I only want the trigger to fire if the alarm status is '' | ||
| + | |||
| + | {{: | ||
| + | |||
| + | This will cause Mac OS X to play the selected beep sound. I've selected '' | ||
| + | |||
| + | == Arming the System == | ||
| + | The final trigger, //Timer Expires While Exiting//, will actually do the arming of the system after the countdown has expired: | ||
| + | |||
| + | {{: | ||
| + | |||
| + | We use the Timer Expired event because we only want the trigger to fire if the timer naturally ran out of time (as opposed to it being explicitly stopped - which will happen if you disarm while exiting which we'll discuss a little later). Again, we'll set the condition such that it only fires if the // | ||
| + | |||
| + | {{: | ||
| + | |||
| + | The action is to execute the action group //Arm System//, which is currently defined with two actions: we set the // | ||
| + | |||
| + | {{: | ||
| + | |||
| + | === Arming Summary === | ||
| + | OK, to summarize the arming process: I press button #4 on //Remote//. That fires the //Alarm Button Pressed to Arm// trigger (if // | ||
| + | |||
| + | === Disarming === | ||
| + | We're now going to discuss how to disarm the system. We haven' | ||
| + | |||
| + | There are several different times during the alarm lifecycle where you'll want to disarm: | ||
| + | |||
| + | - While you're exiting. I don't know about you but it's pretty common for me to forget something only to remember it after I've started the arming process. Disarming must work while the // | ||
| + | - When you enter the TT after the system has been armed - the // | ||
| + | - When the alarm has faulted (the siren is going off, etc.). The // | ||
| + | |||
| + | So, the requirement is pretty simple for disarming: when we press and hold button #4 on //Remote//, and the // | ||
| + | |||
| + | {{: | ||
| + | |||
| + | To simplify the conditions, we'll just say if the // | ||
| + | |||
| + | {{: | ||
| + | |||
| + | And, finally, the action will be to execute the //Disarm System// action group. That's by far the most complicated part of disarming the system. Let's go through the actions in the action group one at a time and discuss each in detail. | ||
| + | |||
| + | == Stop Timer == | ||
| + | {{: | ||
| + | |||
| + | Perhaps the most important action is to stop the //30 Second Timer//. This will keep it from executing the trigger to arm (or disarm which we'll discuss in a bit) the system if we're in entering or exiting mode - those action groups will either arm the system or fault the system. Very important. | ||
| + | |||
| + | == Set the Alarm Status == | ||
| + | {{: | ||
| + | |||
| + | This one is very simple: we just set the // | ||
| + | |||
| + | == Cancel Pesters == | ||
| + | {{: | ||
| + | |||
| + | There are a potential of 3 pesters running when you want to disarm the system: //Exiting Countdown//, | ||
| + | |||
| + | == Stop System Fault == | ||
| + | We haven' | ||
| + | |||
| + | Here's the //Disarm System// action group overview: | ||
| + | |||
| + | {{: | ||
| + | |||
| + | === Disarming Summary === | ||
| + | When we press and hold the #4 button on //Remote// and if // | ||
| + | |||
| + | === Alarm Fault === | ||
| + | The final part of the system is when the alarm system detects a zone fault (a breach). There are two stages whenever the system detects that the zone was faulted: it immediately goes into '' | ||
| + | |||
| + | == Parts == | ||
| + | There are quite a few moving parts for entering just like there were for exiting. In fact, some are actually reused. We'll list those here as well for completeness but know that if something is named identically with something earlier in this article we're just referring to it again (it's not something new). | ||
| + | |||
| + | * //Zone Fault Detected// [[indigo_6_documentation: | ||
| + | * //Countdown Beep// [[indigo_6_documentation: | ||
| + | * //Timer Expires While Entering// [[indigo_6_documentation: | ||
| + | * //Flash Zone 1 Lights// [[indigo_6_documentation: | ||
| + | * //Speak Message Upon Entering// [[indigo_6_documentation: | ||
| + | * //Speak Seconds Only// [[indigo_6_documentation: | ||
| + | * //Create 5 Second Countdown Pester// [[indigo_6_documentation: | ||
| + | * //Fault System// [[indigo_6_documentation: | ||
| + | * //Stop System Fault// [[indigo_6_documentation: | ||
| + | |||
| + | == Zone Fault Detected == | ||
| + | This trigger is very straight-forward: | ||
| + | |||
| + | {{: | ||
| + | |||
| + | Of course, we only care when that happens if the // | ||
| + | |||
| + | {{: | ||
| + | |||
| + | The actions are the interesting part of this trigger: | ||
| + | |||
| + | {{: | ||
| + | |||
| + | First, we start the //30 Second Timer//. If it counts down to 0 that will be our signal to sound the alarm. | ||
| + | |||
| + | Next, we create a pester called //Entering Countdown// | ||
| + | |||
| + | {{: | ||
| + | |||
| + | It's much the same as the //Exiting Countdown// created above: the pester cycles every 5 seconds for 5 times. Each cycle will execute the //Speak Message Upon Entering// action group. The only action in this Action Group at the moment is the following embedded Python script: | ||
| + | |||
| + | < | ||
| + | dev = indigo.devices[3827472] # "30 Second Timer" | ||
| + | # convert the " | ||
| + | # insert that into a string and send the string to the speak server command | ||
| + | indigo.server.speak(" | ||
| + | |||
| + | This script gets the timer device and uses the " | ||
| + | |||
| + | The final action of the pester is the //Create 5 Second Countdown Pester// action group that we created earlier. So that's the Create Pester action. | ||
| + | |||
| + | The last action in the //Zone Fault Detected// trigger is to just speak " | ||
| + | |||
| + | Note that the [[# | ||
| + | |||
| + | == Flash Zone 1 Lights == | ||
| + | As an extra visual feature of the alarm system faulting, I want to flash a couple of Z-Wave lights that I have: one is inside and the other is outside. So, this schedule executes every 6 seconds: | ||
| + | |||
| + | {{: | ||
| + | |||
| + | I picked 6 seconds because one of the lights that I'm flashing has a relatively slow ramp rate so I wanted it to turn all the way on before I turn it back off (the actions have an auto off of 3 seconds as you'll see below). | ||
| + | |||
| + | The condition should be when the // | ||
| + | |||
| + | {{: | ||
| + | |||
| + | and the actions are to execute an action group called //Flash Lights Once// which turns on a couple of lights and has an auto-off after 3 seconds. | ||
| + | |||
| + | {{: | ||
| + | |||
| + | The net result is that while this schedule is running, the lights go on for a 3 seconds then go off for 3 seconds. Obviously you'll want to modify this schedule, actions, and action group to be more custom for your environment. | ||
| + | |||
| + | When you create this schedule you'll probably want to immediately disable it - it may go off depending on what the alarmStatus variable is set to! We'll enable it only when we need it and disable it when we reset the system. You may wonder why we have the condition if we're going to enable/ | ||
| + | |||
| + | == Timer Expires While Entering == | ||
| + | So, lastly, if the //30 Second Timer// expires without disarming, then we need to do all the alerting that we want to do. That trigger is defined like this: | ||
| + | |||
| + | {{: | ||
| + | |||
| + | but only if // | ||
| + | |||
| + | {{: | ||
| + | |||
| + | and the action will be to execute the //Fault System// action group - described next. | ||
| + | |||
| + | == Fault System == | ||
| + | This action group has the following actions: | ||
| + | |||
| + | {{: | ||
| + | |||
| + | * It turns on // | ||
| + | * It sets the // | ||
| + | * It enables the //Flash Zone 1 Lights// schedule. | ||
| + | * It sends me an SMS (via my cell phone provider' | ||
| + | * It inserts a timestamp into a variable named // | ||
| + | |||
| + | == Stop System Fault == | ||
| + | This action group just stops the repetitive stuff started above: it turns // | ||
| + | |||
| + | === Alarm Fault Summary === | ||
| + | So - you open a door (or in some other way trip the zone) which starts the //30 Second Countdown// with audible alerts. If you press and hold #4 on //Remote// you will disarm the system. If you don't, then when the countdown reaches 0, the siren goes off, lights start flashing, and you get an SMS. You can then press and hold #4 on //Remote// to disarm. | ||
| + | |||
| + | === Alarm Button Pressed to Reset Fault === | ||
| + | One final bit to my solution: another trigger that fires when button #4 is pressed on //Remote//: | ||
| + | |||
| + | {{: | ||
| + | |||
| + | The condition is if // | ||
| + | |||
| + | {{: | ||
| + | |||
| + | and the action is to execute the //Disarm System// action group. This makes it easy to disarm the system when it's faulted - you don't have to press and hold #4, just a regular press will also work. | ||
| + | |||
| + | ==== Summary ==== | ||
| + | So that's my alarm system. It has a lot of moving parts (9 devices including the lights I flash, 7 triggers, 1 schedule, 10 action groups, 2 variables, pesters, scripts, emails, timers, device groups). However it is a pretty complete solution particularly for my TT. You could also use this article as a starting point for building a security system in your house, though professionally monitored systems are always a better alternative IMO. But the other major use of this article is to show the power and flexibility of Indigo and it's available components. We believe Indigo can be used in a bunch of different scenarios and we hope you see the possibilities as well. | ||