Skip to content

Commit

Permalink
Add files via upload
Browse files Browse the repository at this point in the history
  • Loading branch information
SteidlD authored Jun 2, 2020
1 parent b0a61a8 commit 2207769
Show file tree
Hide file tree
Showing 8 changed files with 1,091 additions and 0 deletions.
12 changes: 12 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# Changelog for homebridge-home-security-lite
This is the change log for the plugin, all relevant changes will be listed here.

For documentation please see the [README](https://github.com/SteidlD/homebridge-home-security-lite/blob/master/README.md)

## 0.3.0
- Bugfix: Open window warning wasn't set back in certain cases
- JSDoc documentation added to code
- go public

## 0.2.0
- first private check-in
259 changes: 259 additions & 0 deletions HomeSecurityLitePlatform.js

Large diffs are not rendered by default.

51 changes: 51 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
# homebridge-home-security-lite
A homebridge-plugin for using your available homekit sensors and actors to build a security system.

### Features:
- include door and window sensors
- get reminded of opened windows after a configurable time
- get reminded of opened windows when leaving your home
- get an alarm if a window or door is opened when security system is armed

## Installation:

### 1. Install homebridge and home-security-lite plugin.
- 1.a `sudo npm install -g homebridge --unsafe-perm`
- 1.b `sudo npm install -g homebridge-home-security-lite`

### 2. Update homebridge configuration file.
```
"platforms": [
{
"platform" : "HomeSecurityLite",
"name" : "HomeSecurityLite",
"plugin_map" :
{
"plugin_name" : "homebridge-home-security-lite"
},
"prefix_remind_me" : "Remind me of",
"prefix_reminder" : "Reminder:",
"prefix_reminder_accessory" : "Remind timer",
"forgot_window_warning_name" : "Forgot open window or door",
"home_security_lite_name" : "Home Security Lite",
"security_system_name" : "Security system",
"fast_cyclic_reminder_name" : "Remind me fast again",
"windows_and_doors" :
[
{
"name" : "bathroom window",
"description" : "input/output for the window contact sensor in the bathroom"
},
{
"name" : "patio door",
"first_remind" : 1200,
"fast_cyclic_remind" : 180,
"slow_cyclic_remind" : 43200
}
],
"first_remind" : 900,
"fast_cyclic_remind" : 120,
"slow_cyclic_remind" : 1800
}
]
```
327 changes: 327 additions & 0 deletions SecuritySystemAccessory.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,327 @@
// Implements the SecuritySystemAccessory class that is executing the security system
//
//-----------------------------------------------------------------------
// Date Author Change
//-----------------------------------------------------------------------
// 15.05.2020 D.Steidl Created
// 31.05.2020 D.Steidl JSDoc added
// 02.06.2020 D.Steidl Bugfix: Open window warning wasn't set back in certain cases
//-----------------------------------------------------------------------

//-----------------------------------------------------------------------
// Global variables
//-----------------------------------------------------------------------

// variables have to be declared explicitly
'use strict'

/** @const {Object} LSTATES Strings for the logging of the actual security system state */
const LSTATES = ["STAY_ARMED", "AWAY_ARMED", "NIGHT_ARMED", "DISARMED", "ALARM_TRIGGERED"];
/** @const {Object} LTARGETSTATES Strings for the logging of the target security system state */
const LTARGETSTATES = ["STAY_ARM", "AWAY_ARM", "NIGHT_ARM", "DISARM"];

//-----------------------------------------------------------------------
// Imports
//-----------------------------------------------------------------------

// from JavaScript

// from HomeSecurityLite

//-----------------------------------------------------------------------
// Classes
//-----------------------------------------------------------------------

/**
* This class provides a security system based on doors and windows. If you arm it (i.e. automatically when
* the last person leave your home), then it checks whether all of the doors and windows are closed. If not
* it will sent you a message to remind you, that you left a window or a door open. Otherwise - once armed -
* it will react on any door or window opening and will trigger the alarm.
*/
class cSecuritySystemAccessory
{
/**
* Constructor of the class
*
* @param {Object} cLog Pointer to logging class
* @param {Object} cActAccessory Pointer to own accessory
* @param {Object} dConfig Configuration for the plugin
* @returns {void} Nothing
*/
constructor(cLog, cActAccessory, dConfig)
{
// Store values
this.cActAccessory = cActAccessory; // Pointer to logging class
this.cLog = cLog; // Pointer to own accessory
this.Config = dConfig; // Configuration for the plugin

// Initialize
this.eTargetState = cCharacteristic.SecuritySystemTargetState.DISARM; // Target state of the security system (disarmed)
this.eCurrentState = cCharacteristic.SecuritySystemCurrentState.DISARMED; // Actual state of the security system (disarmed)
this.bCurrentSensorState = false; // Actual state of the reminder (off)
this.iTimeoutId = undefined; // Id of a set timeout to find it again (no timeout started)
this.lWindowStates = []; // Array with the states of the windows/doors

// Set Information Accessory
var cInfo = this.cActAccessory.getService(global.cService.AccessoryInformation); // Temporary variable with the AccessoryInformation service
cInfo.setCharacteristic(global.cCharacteristic.Manufacturer, "D. Steidl");
cInfo.setCharacteristic(global.cCharacteristic.Model, "SecuritySystem");
cInfo.setCharacteristic(global.cCharacteristic.SerialNumber, "1");
cInfo.setCharacteristic(global.cCharacteristic.FirmwareRevision, global.strFWVersion);

// Initialize SecuritySystem (set values, getter and setter for the target state and the actual state)
this.cSecuritySystem = this.cActAccessory.getService(global.cService.SecuritySystem); // Pointer to the SecuritySystem service
this.cSecuritySystem
.getCharacteristic(global.cCharacteristic.SecuritySystemTargetState)
.setValue(this.eTargetState)
.on('get', this.getSecuritySystemTargetState.bind(this))
.on('set', this.setSecuritySystemTargetState.bind(this));
this.cSecuritySystem
.getCharacteristic(global.cCharacteristic.SecuritySystemCurrentState)
.setValue(this.eCurrentState)
.on('get', this.getSecuritySystemCurrentState.bind(this));

// Initialize the ContactSensor Service (set value and the getter method)
this.cContactSensorService = this.cActAccessory.getService(global.cService.ContactSensor); // Pointer to the ContactSensor service
this.cContactSensorService
.getCharacteristic(global.cCharacteristic.ContactSensorState)
.setValue(this.bCurrentSensorState)
.on('get', this.getCurrentSensorState.bind(this));

// Accessory is online now
// this.cActAccessory.updateReachability(true);
return;
}

/**
* "Get" function for the target state. Delivers the stored state set before only
*
* @param {function} fCallback Callback function to give back the stored security system target state
* @returns {void} Nothing (value will be given by Callback)
*/
getSecuritySystemTargetState(fCallback)
{
var self = this;
self.cLog("%s - target state: %s", self.cActAccessory.displayName, LTARGETSTATES[self.eTargetState]);
// Give back stored state
fCallback(null, self.eTargetState);
return;
}

/**
* "Set" function for the target state.
*
* @param {boolean} bValue New value for the security system target state
* @param {function} fCallback Callback function (send back value if value was set)
* @returns {void} Nothing (value will be given by Callback)
*/
setSecuritySystemTargetState(bValue, fCallback)
{
var self = this;
// Compare with old value
var bChanged = (self.eTargetState != bValue); // Value has been changed

if (bChanged)
{ // If value has changed
// Store value
self.eTargetState = bValue;
self.cLog("%s - setting target state: %s, Changed: %s", this.cActAccessory.displayName, LTARGETSTATES[self.eTargetState], (bChanged ? "true" : "false"));
// Run statemachine
self.RunStatemachine(bChanged, false);
}
fCallback(null, self.bCurrentSwitchState);
return;
}

/**
* "Get" function for the current state. Delivers the state calculated by the state machine
*
* @param {function} fCallback Callback function to give back the stored security system state
* @returns {void} Nothing (value will be given by Callback)
*/
getSecuritySystemCurrentState(fCallback)
{
var self = this;
self.cLog("%s - current state: %s", self.cActAccessory.displayName, LSTATES[self.eCurrentState]);
// Give back stored state
fCallback(null, self.eCurrentState);
return;
}

/**
* Function to actively change the current state of the security system
*
* @param {Enumerator} eValue New value of the actual security system state
* @returns {void} Nothing
*/
UpdateSecuritySystemCurrentState(eValue)
{
var self = this;
self.cLog("%s - updating current state to %s", this.cActAccessory.displayName, LSTATES[eValue]);
// Store value local and send it to homebridge
self.eCurrentState = eValue;
self.cSecuritySystem.getCharacteristic(global.cCharacteristic.SecuritySystemCurrentState).setValue(eValue, undefined, self.cActAccessory.context);
return;
}

/**
* "Get" function for current state of the forgot_window_warning
*
* @param {function} fCallback Callback function to give back the actual state of the forgot_window_warning reminder
* @returns {void} Nothing (value will be given by Callback)
*/
getCurrentSensorState(fCallback)
{
var self = this;
self.cLog("%s - getting current forgot_window_warning state", this.cActAccessory.displayName);
// Give back current state
fCallback(null, self.bCurrentSensorState);
return;
}

/**
* Function to actively change the state of the virtual window
*
* @param {boolean} bValue New state of the forgot_window_warning reminder
* @returns {void} Nothing
*/
UpdateCurrentSensorState(bValue)
{
var self = this;
self.cLog("%s - updating current forgot_window_warning state to %s", this.cActAccessory.displayName, (bValue ? "true" : "false"));
// Store value local and send it to homebridge
self.bCurrentSensorState = bValue;
self.cContactSensorService.getCharacteristic(global.cCharacteristic.ContactSensorState).setValue(bValue, undefined, self.cActAccessory.context);
return;
}

/**
* Function that is called from the WindowAndDoorAccessory class every time a window state changes. The state of the corresponding
* window will be stored and the state machine will be run to see what effects this will take.
*
* @param {number} iSerial Serial number of the window or door
* @param {boolean} bState New state of the window or door
* @returns {void} Nothing
*/
setWindowState(iSerial, bState)
{
var self = this;
self.lWindowStates[iSerial] = bState;
self.RunStatemachine(false, false);
return;
}

/**
* State machine that is doing the actual security system.
*
* @param {boolean} bChangedTargetState True if the statemachine is run because of a new target state
* @param {boolean} bTimeout True if the statemachine is run because of a timeout
* @returns Nothing
*/
RunStatemachine(bChangedTargetState, bTimeout)
{
var eNewCurrentState; // New actual state of the security system to be changed to
var bNewCurrentSensorState; // New reminder state to be changed to
var self = this;

// If there's still a timeout running, then stop it
clearTimeout(self.iTimeoutId);
self.iTimeoutId = undefined;

// In case of alarm triggered wait for disarm only
if ((self.eCurrentState == global.cCharacteristic.SecuritySystemCurrentState.ALARM_TRIGGERED) &&
(self.eTargetState != global.cCharacteristic.SecuritySystemTargetState.DISARM))
{
return;
}

// Determine whether a window is opened
var bWindowOpened = false;
self.lWindowStates.forEach(bThisWindowOpened => { bWindowOpened = bWindowOpened || bThisWindowOpened; });

// The state machine
switch (self.eTargetState)
{
//---------------------------------------------------------------
// STATE: Disarmed
//-----------------
case global.cCharacteristic.SecuritySystemTargetState.DISARM:
// Always go to new state without condition
eNewCurrentState = global.cCharacteristic.SecuritySystemCurrentState.DISARMED;
// If switched off then release forgot_window_warning
bNewCurrentSensorState = false;
break;

//---------------------------------------------------------------
// STATE: At home
//-----------------
case global.cCharacteristic.SecuritySystemTargetState.STAY_ARM:
// Always go to new state without condition
eNewCurrentState = global.cCharacteristic.SecuritySystemCurrentState.STAY_ARM;
// If I'm back home release forgot_window_warning
bNewCurrentSensorState = false;
break;

//---------------------------------------------------------------
// STATE: Away
//-----------------
case global.cCharacteristic.SecuritySystemTargetState.AWAY_ARM:

if (self.eCurrentState != global.cCharacteristic.SecuritySystemCurrentState.AWAY_ARM)
{ // If the security system is not armed yet, then try to arm it
if (bWindowOpened)
{ // If a window is opened, then the security system cannot be activated and a warning for the opened window / door shall be sent
bNewCurrentSensorState = true;
}
else
{ // otherwise switch of warning and activate the security system
bNewCurrentSensorState = false;
eNewCurrentState = global.cCharacteristic.SecuritySystemCurrentState.AWAY_ARM;
}
}
else
{ // If it already was armed before and now a window opens, an alarm will be triggered
if (bWindowOpened)
eNewCurrentState = global.cCharacteristic.SecuritySystemCurrentState.ALARM_TRIGGERED;
}
break;

//---------------------------------------------------------------
// STATE: At night
//-----------------
case global.cCharacteristic.SecuritySystemTargetState.NIGHT_ARM:

if (self.eCurrentState != global.cCharacteristic.SecuritySystemCurrentState.NIGHT_ARM)
{ // If the security system is not armed for the night yet, then try to arm it
if (bWindowOpened)
{ // If a window is opened, then the security system cannot be activated and a warning for the opened window / door shall be sent
bNewCurrentSensorState = true;
}
else
{ // otherwise switch of warning and activate the security system
bNewCurrentSensorState = false;
eNewCurrentState = global.cCharacteristic.SecuritySystemCurrentState.NIGHT_ARM;
}
}
else
{ // If it already was armed before and now a window opens, an alarm will be triggered
if (bWindowOpened)
eNewCurrentState = global.cCharacteristic.SecuritySystemCurrentState.ALARM_TRIGGERED;
}
break;
}

// If values have been changed, call update functions
if (eNewCurrentState != this.eCurrentState)
self.UpdateSecuritySystemCurrentState(eNewCurrentState);
if (bNewCurrentSensorState != this.bCurrentSensorState)
self.UpdateCurrentSensorState(bNewCurrentSensorState);
return;
}
}

//-----------------------------------------------------------------------
// Exports
//-----------------------------------------------------------------------

module.exports = cSecuritySystemAccessory;
Loading

0 comments on commit 2207769

Please sign in to comment.