SOLVED : Home Security System Tapping with Arduino

Hey, so … uh … better late than never, right? Right?

I finally got around to working further on this project and I’ve an Arduino successfully reading values off from my Z1100 security system and then sending state changes to a Raspberry Pi running EasyIOT via an NRF24L01+ with the MySensors library. I’m using the voltage divider method and there does not appear to be any negative impact regarding the Z1100’s ability to still function. A voltage divider is an easy enough idea, but it took me some time to understand what exactly was happening…

I’ve attached a Fritzing diagram below of my hookup. This is the first time I’ve ever used Fritzing so hopefully it’s sufficiently legible.

This isn’t yet a finish product. Things that still need to be done:

  • - Code is clunky in spots and needs to be optimized.
  • - It's possible for the Arduino and RPI to get desynced if a zone state is changed during a reboot. This is, in part, because the Arduino assumes that all the zones are closed at boot. It syncs back up after opening and closing the affected zone, but the RBI will not see that first open/close cycle - not great for a security system! To fix this, the Arduino should check the current values of all the zone states when it reboots.
  • - Additional zones on the Z1100 still need to be connected.
  • - Detect if the Z1100 is ARMED. Pretty sure there's a pin for this on the Z1100 and I should be able to tap it just as I have for the zones.
  • - Detect if the Z1100 is actuating the siren. As with the ARMED state, I think there's a pin for that too, but I haven't dug too deeply.
  • - I'd really like to do something with the data - like send a text if a zone is opened while the Z1100 is ARMED ... I'm always in search of better home automation controllers. EasyIOT is the best I've found for my needs so far, but it's still a work in progress. I'm thinking I might just parse the data into Splunk for more advance analytics.
  • At any rate, here’s my code :

    /*
     *
     * Multimeter Code taken from : https://blog.udemy.com/arduino-voltmeter/
     * Thanks, Jennifer Marsh!
     *
     * Communication of the zone states is handled by the very cool MySensors library : http://www.mysensors.org/
     * Thanks to all the contributors to that project!
     * 
     * Thanks, Mee_n_Mac for your help!
     * 
     * Notes :
     * ~6V Closed; ~13V Open
     * Pin A* = Sensor * (Pins and Sensors start at 1, not 0)
     */
     
    #include <MySensor.h>
    #include <SPI.h>
    
    #define CHILD_ID_ZONE_1 1
    #define CHILD_ID_ZONE_2 2
    #define CHILD_ID_ZONE_3 3
    #define CHILD_ID_ZONE_4 4
    
    MySensor gw;
    MyMessage msg_Zone_1(CHILD_ID_ZONE_1,V_TRIPPED);
    MyMessage msg_Zone_2(CHILD_ID_ZONE_2,V_TRIPPED);
    MyMessage msg_Zone_3(CHILD_ID_ZONE_3,V_TRIPPED);
    MyMessage msg_Zone_4(CHILD_ID_ZONE_4,V_TRIPPED);
    
    // Variables for reading voltage
    // These resistors should make it safe to read up to ~55VDC)
    float vPow = 4.7;
    float r1 = 100000;
    float r2 = 10000;
    
    // Number of zones to check 
    int numZones = 4;
    
    // Last Known State variables
    char* lkstate[]={"Closed", "Closed", "Closed", "Closed"};
    
    void setup() {
      
      // Spin up MySensors
      gw.begin();
      
      // Let the controller know about our children
      gw.present(CHILD_ID_ZONE_1, S_DOOR);
      gw.present(CHILD_ID_ZONE_2, S_DOOR);
      gw.present(CHILD_ID_ZONE_3, S_DOOR);
      gw.present(CHILD_ID_ZONE_4, S_DOOR);
      
      // Sensor is on wall power, so peg battery level at 100%
      gw.sendBatteryLevel(100);
    }
    
    void loop() {
      
      for (int child = 1; child < numZones + 1; child++) {
        Serial.println("\n\n\n");
        // Let Serial know which sensor we're checking.
        Serial.println("Checking child: " + String(child));
        
        // Let Serial know what the last known state was.
        Serial.println("Last Known State of child: " + String(lkstate[child-1]));
        
        // Check the voltage into the Analog Input.
        int voltage = (int)((analogRead(child) * vPow) / 1024)/(r2 / ( r1 + r2));
            
        // Let Serial know what voltage we detected on the sensor.
        Serial.println("Voltage is measured at: " + String(voltage));
        
        // If the voltage is detected at below 9DCV, probably ~6DCV, the zone is Closed.    
        if (voltage <= 9) {
          if (lkstate[child-1]=="Open") {   // If the Last Known State was Open,
            lkstate[child-1]="Closed";      // Change it to Closed and ...
            sendUpdate(child);              // Send an update to the Controller and ...
            Serial.println("Last Known State of sensor changed. Now: " + String(lkstate[child-1]));  // Let Serial know of the state change.
          }
        }
        
        // If the voltage is detected at above 9DCV, probably ~13DCV, the zone is Open.
        else if (voltage > 9) {
          if (lkstate[child-1]=="Closed") {  // If the Last Known State was Closed,
            lkstate[child-1]="Open";         // Change it to Open and ...
            sendUpdate(child);               // Send an update to the Controller and ...
            Serial.println("Last Known State of child changed. Now: " + String(lkstate[child-1]));  // Let Serial know of the state change.        
          }
        }      
        delay(250);
      }
    }
    
    void sendUpdate(int child){
      
      //Switch on the child value
      switch (child) {
        
        case 1:
          if (lkstate[child-1]=="Open") {
            gw.send(msg_Zone_1.set(1));
          } else if (lkstate[child-1]=="Closed") {
            gw.send(msg_Zone_1.set(0));
          }
          break;
        
        case 2:
          if (lkstate[child-1]=="Open") {
            gw.send(msg_Zone_2.set(1));
          } else if (lkstate[child-1]=="Closed") {
            gw.send(msg_Zone_2.set(0));
          }
          break;
          
        case 3:
          if (lkstate[child-1]=="Open") {
            gw.send(msg_Zone_3.set(1));
          } else if (lkstate[child-1]=="Closed") {
            gw.send(msg_Zone_3.set(0));
          }
          break;
    
        case 4:
          if (lkstate[child-1]=="Open") {
            gw.send(msg_Zone_4.set(1));
          } else if (lkstate[child-1]=="Closed") {
            gw.send(msg_Zone_4.set(0));
          }
          break;
          
      }
    }
    

    This is part of a larger home automation project, but it’s unlikely I’ll make any additional progress on it for a good number of months. My hope is to put some documentation together of the whole project upon its completion … but let’s be honest … it took me two and half years to get around to this, so I wouldn’t hold my breath. :stuck_out_tongue: That said, I wanted to get this out less some poor reader experience this : https://xkcd.com/979/

    Thanks again, @Mee_n_Mac. Apologies I wasn’t around to see your post, @derkosjo. I hope you’ve made some good progress on your project!