homebridge-securitysystem 8.2.0-beta.1 → 8.3.0-beta.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/package.json +1 -1
  2. package/src/index.js +166 -139
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "homebridge-securitysystem",
3
3
  "displayName": "Homebridge Security System",
4
- "version": "8.2.0-beta.1",
4
+ "version": "8.3.0-beta.1",
5
5
  "description": "Homebridge plugin that creates a security system accessory that can be triggered by HomeKit sensors.",
6
6
  "main": "src/index.js",
7
7
  "scripts": {
package/src/index.js CHANGED
@@ -794,77 +794,70 @@ SecuritySystem.prototype.getCurrentState = function (callback) {
794
794
  };
795
795
 
796
796
  SecuritySystem.prototype.setCurrentState = function (state, origin) {
797
+ // Update arming motion sensor
798
+ this.resetArmingMotionDetected();
799
+
800
+ // Audio
801
+ this.playAudio("current", state);
802
+
797
803
  // Check if mode already set
798
804
  if (this.currentState === state) {
805
+ this.log.warn("Current mode (Already set)");
799
806
  return;
800
- }
801
-
802
- this.currentState = state;
803
- this.service.setCharacteristic(
804
- Characteristic.SecuritySystemCurrentState,
805
- state
806
- );
807
+ } else {
808
+ this.currentState = state;
809
+ this.service.setCharacteristic(
810
+ Characteristic.SecuritySystemCurrentState,
811
+ state
812
+ );
807
813
 
808
- this.logMode("Current", state);
809
- this.handleCurrentStateChange(false);
814
+ this.logMode("Current", state);
815
+ }
810
816
 
811
- // Audio
812
- this.playAudio("current", state);
817
+ this.handleCurrentStateChange(state, origin);
818
+ this.save();
819
+ };
813
820
 
821
+ SecuritySystem.prototype.handleCurrentStateChange = function (state, origin) {
814
822
  // Commands
815
823
  this.executeCommand("current", state, origin);
816
824
 
817
825
  // Webhooks
818
826
  this.sendWebhookEvent("current", state, origin);
819
827
 
820
- if (state === Characteristic.SecuritySystemCurrentState.ALARM_TRIGGERED) {
821
- // Update triggered motion sensor
822
- this.triggeredMotionSensorInterval = setInterval(() => {
823
- this.updateTriggeredMotionDetected();
824
- }, options.triggeredMotionSensorSeconds * 1000);
825
-
826
- // Automatically arm the security system
827
- // when time runs out
828
- this.resetTimeout = setTimeout(() => {
829
- this.resetTimeout = null;
830
- this.log.info("Reset (Finished)");
831
-
832
- this.triggerResetSensor();
828
+ const isCurrentStateAlarmTriggered =
829
+ state === Characteristic.SecuritySystemCurrentState.ALARM_TRIGGERE;
833
830
 
834
- // Alternative flow (Triggered -> Off -> Armed mode)
835
- if (options.resetOffFlow) {
836
- const originalTargetState = this.targetState;
837
- this.updateTargetState(
838
- Characteristic.SecuritySystemTargetState.DISARM,
839
- originTypes.INTERNAL,
840
- false,
841
- null
842
- );
831
+ if (isCurrentStateAlarmTriggered) {
832
+ this.handleTriggeredState();
833
+ }
834
+ };
843
835
 
844
- setTimeout(() => {
845
- this.updateTargetState(
846
- originalTargetState,
847
- originTypes.INTERNAL,
848
- true,
849
- null
850
- );
851
- }, 100);
836
+ SecuritySystem.prototype.handleTriggeredState = function () {
837
+ // Trigger triggered motion sensor
838
+ // every configured seconds
839
+ this.triggeredMotionSensorInterval = setInterval(() => {
840
+ this.updateTriggeredMotionDetected();
841
+ }, options.triggeredMotionSensorSeconds * 1000);
852
842
 
853
- return;
854
- }
843
+ // Automatically arm the security system
844
+ // when time runs out
845
+ this.resetTimeout = setTimeout(() => {
846
+ this.resetTimeout = null;
847
+ this.log.info("Reset (Finished)");
855
848
 
856
- // Normal flow
857
- this.handleTargetStateChange(false);
858
- this.setCurrentState(this.targetState, false);
859
- }, options.resetMinutes * 60 * 1000);
860
- }
849
+ this.triggerResetSensor();
861
850
 
862
- this.save();
863
- };
851
+ // Alternative flow (Triggered -> Off -> Armed mode)
852
+ if (options.resetOffFlow) {
853
+ this.resetUsingOffMode();
854
+ return;
855
+ }
864
856
 
865
- SecuritySystem.prototype.handleCurrentStateChange = function (alarmTriggered) {
866
- // Arming motion sensor
867
- this.updateArmingMotionDetected(false);
857
+ // Normal flow
858
+ this.handleTargetStateChange(false);
859
+ this.setCurrentState(this.targetState, false);
860
+ }, options.resetMinutes * 60 * 1000);
868
861
  };
869
862
 
870
863
  SecuritySystem.prototype.triggerResetSensor = function () {
@@ -882,6 +875,26 @@ SecuritySystem.prototype.triggerResetSensor = function () {
882
875
  }, 750);
883
876
  };
884
877
 
878
+ SecuritySystem.prototype.resetUsingOffMode = function () {
879
+ const originalTargetState = this.targetState;
880
+
881
+ this.updateTargetState(
882
+ Characteristic.SecuritySystemTargetState.DISARM,
883
+ originTypes.INTERNAL,
884
+ false,
885
+ null
886
+ );
887
+
888
+ setTimeout(() => {
889
+ this.updateTargetState(
890
+ originalTargetState,
891
+ originTypes.INTERNAL,
892
+ true,
893
+ null
894
+ );
895
+ }, 100);
896
+ };
897
+
885
898
  SecuritySystem.prototype.resetTimers = function () {
886
899
  // Clear trigger timeout
887
900
  if (this.triggerTimeout !== null) {
@@ -940,7 +953,10 @@ SecuritySystem.prototype.resetTimers = function () {
940
953
  }
941
954
  };
942
955
 
943
- SecuritySystem.prototype.handleTargetStateChange = function (alarmTriggered) {
956
+ SecuritySystem.prototype.handleTargetStateChange = function (
957
+ origin,
958
+ alarmTriggered
959
+ ) {
944
960
  // Reset double-knock
945
961
  this.isKnocked = false;
946
962
 
@@ -948,17 +964,25 @@ SecuritySystem.prototype.handleTargetStateChange = function (alarmTriggered) {
948
964
  this.resetModeSwitches();
949
965
  this.updateModeSwitches();
950
966
 
951
- // Keep characteristic & switches on
967
+ // Commands
968
+ this.executeCommand("target", this.targetState, origin);
969
+
970
+ // Webhooks
971
+ this.sendWebhookEvent("target", this.targetState, origin);
972
+
973
+ // Trigger reset sensor for mode
974
+ // change in triggered state
952
975
  if (alarmTriggered) {
976
+ if (isCurrentStateAlarmTriggered) {
977
+ this.triggerResetSensor();
978
+ }
979
+
980
+ // Keep characteristic & switches on
953
981
  return;
954
982
  }
955
983
 
956
984
  // Reset tripped motion sensor
957
- const trippedOnCharacteristic = this.tripSwitchService.getCharacteristic(
958
- Characteristic.On
959
- );
960
-
961
- if (trippedOnCharacteristic.value) {
985
+ if (this.tripSwitchService.getCharacteristic(Characteristic.On).value) {
962
986
  this.updateTripSwitch(false, originTypes.INTERNAL, true, null);
963
987
  }
964
988
 
@@ -966,12 +990,7 @@ SecuritySystem.prototype.handleTargetStateChange = function (alarmTriggered) {
966
990
  this.resetTripSwitches();
967
991
  };
968
992
 
969
- SecuritySystem.prototype.updateTargetState = function (
970
- state,
971
- origin,
972
- delay,
973
- callback
974
- ) {
993
+ SecuritySystem.prototype.isBadTargetState = function (state) {
975
994
  const isTargetStateAlreadySet = this.targetState === state;
976
995
  const isCurrentStateAlarmTriggered =
977
996
  this.currentState ===
@@ -982,25 +1001,13 @@ SecuritySystem.prototype.updateTargetState = function (
982
1001
  // Check if target state is already set
983
1002
  if (isTargetStateAlreadySet && isCurrentStateAlarmTriggered === false) {
984
1003
  this.log.warn("Target mode (Already set)");
985
-
986
- if (callback !== null) {
987
- callback(null);
988
- }
989
-
990
- return false;
1004
+ return true;
991
1005
  }
992
1006
 
993
1007
  // Check if state is enabled
994
1008
  if (this.availableTargetStates.includes(state) === false) {
995
1009
  this.log.warn("Target mode (Disabled)");
996
-
997
- if (callback !== null) {
998
- // Tip: this will revert the original state
999
- // HomeKit error
1000
- callback(Characteristic.SecuritySystemTargetState.DISARM);
1001
- }
1002
-
1003
- return false;
1010
+ return true;
1004
1011
  }
1005
1012
 
1006
1013
  // Check arming lock switches
@@ -1014,11 +1021,20 @@ SecuritySystem.prototype.updateTargetState = function (
1014
1021
  this.isArmingLocked(state)
1015
1022
  ) {
1016
1023
  this.log.warn("Arming lock (Not allowed)");
1024
+ return true;
1025
+ }
1026
+ };
1017
1027
 
1028
+ SecuritySystem.prototype.updateTargetState = function (
1029
+ state,
1030
+ origin,
1031
+ delay,
1032
+ callback
1033
+ ) {
1034
+ // Validate target state
1035
+ if (this.isBadTargetState(state)) {
1018
1036
  if (callback !== null) {
1019
- // Tip: this will revert the original state
1020
- // HomeKit error
1021
- callback(Characteristic.SecuritySystemTargetState.DISARM);
1037
+ callback(null);
1022
1038
  }
1023
1039
 
1024
1040
  return false;
@@ -1028,13 +1044,6 @@ SecuritySystem.prototype.updateTargetState = function (
1028
1044
  this.targetState = state;
1029
1045
  this.logMode("Target", state);
1030
1046
 
1031
- const isTargetStateHome =
1032
- this.targetState === Characteristic.SecuritySystemTargetState.STAY_ARM;
1033
- const isTargetStateAway =
1034
- this.targetState === Characteristic.SecuritySystemTargetState.AWAY_ARM;
1035
- const isTargetStateNight =
1036
- this.targetState === Characteristic.SecuritySystemTargetState.NIGHT_ARM;
1037
-
1038
1047
  // Update characteristic
1039
1048
  if (origin === originTypes.INTERNAL || origin === originTypes.EXTERNAL) {
1040
1049
  this.service.updateCharacteristic(
@@ -1043,24 +1052,13 @@ SecuritySystem.prototype.updateTargetState = function (
1043
1052
  );
1044
1053
  }
1045
1054
 
1046
- // Reset everything
1047
- this.handleTargetStateChange(false);
1048
-
1049
- // Commands
1050
- this.executeCommand("target", state, origin);
1051
-
1052
- // Webhooks
1053
- this.sendWebhookEvent("target", state, origin);
1054
-
1055
1055
  // Check if current state is already set
1056
1056
  if (state === this.currentState) {
1057
- this.log.warn("Current mode (Already set)");
1058
-
1059
- // Reset arming motion sensor
1060
- this.updateArmingMotionDetected(false);
1057
+ // Clear arming timeout
1058
+ clearTimeout(this.armTimeout);
1061
1059
 
1062
- // Play audio
1063
- this.playAudio("current", this.currentState);
1060
+ // Run set current state logic again
1061
+ this.setCurrentState(state, origin);
1064
1062
 
1065
1063
  if (callback !== null) {
1066
1064
  callback(null);
@@ -1069,47 +1067,18 @@ SecuritySystem.prototype.updateTargetState = function (
1069
1067
  return false;
1070
1068
  }
1071
1069
 
1072
- // Trigger reset sensor for mode
1073
- // change in triggered state
1074
- if (isCurrentStateAlarmTriggered) {
1075
- this.triggerResetSensor();
1076
- }
1070
+ // Handle mode change
1071
+ this.handleTargetStateChange(origin, false);
1077
1072
 
1078
1073
  // Set arming delay
1079
1074
  let armSeconds = 0;
1080
1075
 
1081
1076
  if (delay) {
1082
- armSeconds = options.armSeconds;
1083
-
1084
- // No delay when triggered or set to Off
1085
- if (isCurrentStateAlarmTriggered || isTargetStateDisarm) {
1086
- armSeconds = 0;
1087
- }
1088
-
1089
- // Custom mode seconds
1090
- if (isTargetStateHome && options.isValueSet(options.homeArmSeconds)) {
1091
- armSeconds = options.homeArmSeconds;
1092
- } else if (
1093
- isTargetStateAway &&
1094
- options.isValueSet(options.awayArmSeconds)
1095
- ) {
1096
- armSeconds = options.awayArmSeconds;
1097
- } else if (
1098
- isTargetStateNight &&
1099
- options.isValueSet(options.nightArmSeconds)
1100
- ) {
1101
- armSeconds = options.nightArmSeconds;
1102
- }
1077
+ armSeconds = this.getArmingSeconds();
1103
1078
 
1104
1079
  // Delay actions
1105
1080
  if (armSeconds > 0) {
1106
- this.isArming = true;
1107
-
1108
- // Trigger arming motion sensor
1109
- this.updateArmingMotionDetected(true);
1110
-
1111
- // Play sound
1112
- this.playAudio("target", state);
1081
+ this.handleArmingState();
1113
1082
 
1114
1083
  // Log
1115
1084
  this.log.info("Arm delay (" + armSeconds + " second/s)");
@@ -1119,8 +1088,8 @@ SecuritySystem.prototype.updateTargetState = function (
1119
1088
  // Arm the security system
1120
1089
  this.armTimeout = setTimeout(() => {
1121
1090
  this.armTimeout = null;
1122
- this.setCurrentState(state, origin);
1123
1091
  this.isArming = false;
1092
+ this.setCurrentState(state, origin);
1124
1093
  }, armSeconds * 1000);
1125
1094
 
1126
1095
  if (callback !== null) {
@@ -1130,6 +1099,50 @@ SecuritySystem.prototype.updateTargetState = function (
1130
1099
  return true;
1131
1100
  };
1132
1101
 
1102
+ SecuritySystem.prototype.getArmingSeconds = function () {
1103
+ let armSeconds = options.armSeconds;
1104
+
1105
+ const isCurrentStateAlarmTriggered =
1106
+ this.currentState ===
1107
+ Characteristic.SecuritySystemCurrentState.ALARM_TRIGGERED;
1108
+ const isTargetStateDisarm =
1109
+ this.targetState === Characteristic.SecuritySystemTargetState.DISARM;
1110
+
1111
+ // No delay when triggered or set to Off
1112
+ if (isCurrentStateAlarmTriggered || isTargetStateDisarm) {
1113
+ return 0;
1114
+ }
1115
+
1116
+ const isTargetStateHome =
1117
+ this.targetState === Characteristic.SecuritySystemTargetState.STAY_ARM;
1118
+ const isTargetStateAway =
1119
+ this.targetState === Characteristic.SecuritySystemTargetState.AWAY_ARM;
1120
+ const isTargetStateNight =
1121
+ this.targetState === Characteristic.SecuritySystemTargetState.NIGHT_ARM;
1122
+
1123
+ // Custom mode seconds
1124
+ if (isTargetStateHome && options.isValueSet(options.homeArmSeconds)) {
1125
+ armSeconds = options.homeArmSeconds;
1126
+ } else if (isTargetStateAway && options.isValueSet(options.awayArmSeconds)) {
1127
+ armSeconds = options.awayArmSeconds;
1128
+ } else if (
1129
+ isTargetStateNight &&
1130
+ options.isValueSet(options.nightArmSeconds)
1131
+ ) {
1132
+ armSeconds = options.nightArmSeconds;
1133
+ }
1134
+
1135
+ return armSeconds;
1136
+ };
1137
+
1138
+ SecuritySystem.prototype.handleArmingState = function () {
1139
+ // Trigger arming motion sensor
1140
+ this.updateArmingMotionDetected(true);
1141
+
1142
+ // Play sound
1143
+ this.playAudio("target", this.targetState);
1144
+ };
1145
+
1133
1146
  SecuritySystem.prototype.getTargetState = function (callback) {
1134
1147
  callback(null, this.targetState);
1135
1148
  };
@@ -2432,6 +2445,20 @@ SecuritySystem.prototype.updateArmingMotionDetected = function (value) {
2432
2445
  );
2433
2446
  };
2434
2447
 
2448
+ SecuritySystem.prototype.resetArmingMotionDetected = function () {
2449
+ let isArmingMotionSensorTriggered =
2450
+ this.armingMotionSensorService.getCharacteristic(
2451
+ Characteristic.MotionDetected
2452
+ ).value;
2453
+
2454
+ if (isArmingMotionSensorTriggered) {
2455
+ this.armingMotionSensorService.updateCharacteristic(
2456
+ Characteristic.MotionDetected,
2457
+ false
2458
+ );
2459
+ }
2460
+ };
2461
+
2435
2462
  // Tripped Motion Sensor
2436
2463
  SecuritySystem.prototype.getTrippedMotionDetected = function (callback) {
2437
2464
  const value = this.trippedMotionSensorService.getCharacteristic(