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.
- package/package.json +1 -1
- 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.
|
|
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
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
);
|
|
807
|
+
} else {
|
|
808
|
+
this.currentState = state;
|
|
809
|
+
this.service.setCharacteristic(
|
|
810
|
+
Characteristic.SecuritySystemCurrentState,
|
|
811
|
+
state
|
|
812
|
+
);
|
|
807
813
|
|
|
808
|
-
|
|
809
|
-
|
|
814
|
+
this.logMode("Current", state);
|
|
815
|
+
}
|
|
810
816
|
|
|
811
|
-
|
|
812
|
-
this.
|
|
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
|
-
|
|
821
|
-
|
|
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
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
Characteristic.SecuritySystemTargetState.DISARM,
|
|
839
|
-
originTypes.INTERNAL,
|
|
840
|
-
false,
|
|
841
|
-
null
|
|
842
|
-
);
|
|
831
|
+
if (isCurrentStateAlarmTriggered) {
|
|
832
|
+
this.handleTriggeredState();
|
|
833
|
+
}
|
|
834
|
+
};
|
|
843
835
|
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
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
|
-
|
|
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
|
-
|
|
857
|
-
this.handleTargetStateChange(false);
|
|
858
|
-
this.setCurrentState(this.targetState, false);
|
|
859
|
-
}, options.resetMinutes * 60 * 1000);
|
|
860
|
-
}
|
|
849
|
+
this.triggerResetSensor();
|
|
861
850
|
|
|
862
|
-
|
|
863
|
-
|
|
851
|
+
// Alternative flow (Triggered -> Off -> Armed mode)
|
|
852
|
+
if (options.resetOffFlow) {
|
|
853
|
+
this.resetUsingOffMode();
|
|
854
|
+
return;
|
|
855
|
+
}
|
|
864
856
|
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
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 (
|
|
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
|
-
//
|
|
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
|
-
|
|
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.
|
|
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
|
-
|
|
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
|
-
|
|
1058
|
-
|
|
1059
|
-
// Reset arming motion sensor
|
|
1060
|
-
this.updateArmingMotionDetected(false);
|
|
1057
|
+
// Clear arming timeout
|
|
1058
|
+
clearTimeout(this.armTimeout);
|
|
1061
1059
|
|
|
1062
|
-
//
|
|
1063
|
-
this.
|
|
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
|
-
//
|
|
1073
|
-
|
|
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 =
|
|
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.
|
|
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(
|