@jgrimard/homebridge-vivint 2.0.0

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 (62) hide show
  1. package/LICENSE +13 -0
  2. package/README.md +107 -0
  3. package/config.schema.json +90 -0
  4. package/dist/devices/camera.js +368 -0
  5. package/dist/devices/camera.js.map +1 -0
  6. package/dist/devices/carbonMonoxideSensor.js +44 -0
  7. package/dist/devices/carbonMonoxideSensor.js.map +1 -0
  8. package/dist/devices/contactSensor.js +65 -0
  9. package/dist/devices/contactSensor.js.map +1 -0
  10. package/dist/devices/device.js +147 -0
  11. package/dist/devices/device.js.map +1 -0
  12. package/dist/devices/dimmerSwitch.js +12 -0
  13. package/dist/devices/dimmerSwitch.js.map +1 -0
  14. package/dist/devices/garageDoor.js +58 -0
  15. package/dist/devices/garageDoor.js.map +1 -0
  16. package/dist/devices/index.js +55 -0
  17. package/dist/devices/index.js.map +1 -0
  18. package/dist/devices/lightGroup.js +15 -0
  19. package/dist/devices/lightGroup.js.map +1 -0
  20. package/dist/devices/lightSwitch.js +42 -0
  21. package/dist/devices/lightSwitch.js.map +1 -0
  22. package/dist/devices/lock.js +49 -0
  23. package/dist/devices/lock.js.map +1 -0
  24. package/dist/devices/motionSensor.js +73 -0
  25. package/dist/devices/motionSensor.js.map +1 -0
  26. package/dist/devices/multiLevelSwitchBase.js +55 -0
  27. package/dist/devices/multiLevelSwitchBase.js.map +1 -0
  28. package/dist/devices/panel.js +79 -0
  29. package/dist/devices/panel.js.map +1 -0
  30. package/dist/devices/smokeSensor.js +47 -0
  31. package/dist/devices/smokeSensor.js.map +1 -0
  32. package/dist/devices/thermostat.js +216 -0
  33. package/dist/devices/thermostat.js.map +1 -0
  34. package/dist/homebridge-ui/public/index.html +138 -0
  35. package/dist/homebridge-ui/server.js +120 -0
  36. package/dist/homebridge-ui/server.js.map +1 -0
  37. package/dist/index.js +9 -0
  38. package/dist/index.js.map +1 -0
  39. package/dist/platform.js +393 -0
  40. package/dist/platform.js.map +1 -0
  41. package/dist/settings.js +12 -0
  42. package/dist/settings.js.map +1 -0
  43. package/dist/types.js +2 -0
  44. package/dist/types.js.map +1 -0
  45. package/dist/utils/debounce.js +49 -0
  46. package/dist/utils/debounce.js.map +1 -0
  47. package/dist/utils/ports.js +39 -0
  48. package/dist/utils/ports.js.map +1 -0
  49. package/dist/utils/redact.js +19 -0
  50. package/dist/utils/redact.js.map +1 -0
  51. package/dist/utils/sanitizeName.js +22 -0
  52. package/dist/utils/sanitizeName.js.map +1 -0
  53. package/dist/vivint/api.js +246 -0
  54. package/dist/vivint/api.js.map +1 -0
  55. package/dist/vivint/datapatch.js +52 -0
  56. package/dist/vivint/datapatch.js.map +1 -0
  57. package/dist/vivint/dictionary.js +66 -0
  58. package/dist/vivint/dictionary.js.map +1 -0
  59. package/dist/vivint/eventStream.js +77 -0
  60. package/dist/vivint/eventStream.js.map +1 -0
  61. package/dist/vivint/vivint_dictionary.json +8720 -0
  62. package/package.json +62 -0
@@ -0,0 +1,65 @@
1
+ import { sanitizeDeviceName } from '../utils/sanitizeName.js';
2
+ import { VivintDict } from '../vivint/dictionary.js';
3
+ import { VivintDevice } from './device.js';
4
+ const EQUIPMENT_CODES = [
5
+ 'DW21R_RECESSED_DOOR',
6
+ 'DW10_THIN_DOOR_WINDOW',
7
+ 'DW11_THIN_DOOR_WINDOW',
8
+ 'DW20_RECESSED_DOOR',
9
+ 'EXISTING_DOOR_WINDOW_CONTACT',
10
+ 'TAKE_TAKEOVER',
11
+ 'GB1_GLASS_BREAK',
12
+ 'GB2_GLASS_BREAK',
13
+ 'EXISTING_GLASS_BREAK',
14
+ 'HW_GLASS_BREAK_5853',
15
+ 'TILT_SENSOR_2GIG_345',
16
+ 'EXISTING_HEAT',
17
+ 'EXISTING_FLOOD_TEMP',
18
+ 'SWS1_SMART_WATER_SENSOR',
19
+ 'DW12_THIN_DOOR_WINDOW',
20
+ 'GB3_GLASS_BREAK',
21
+ 'PIR3_MOTION',
22
+ 'APOLLO_COMBO_SMOKE',
23
+ 'APOLLO_COMBO_CO',
24
+ 'GARAGE01_RESOLUTION_TILT',
25
+ ].map(name => VivintDict.EquipmentCode[name]);
26
+ export class ContactSensor extends VivintDevice {
27
+ static className = 'ContactSensor';
28
+ static hasBattery = true;
29
+ service;
30
+ constructor(platform, accessory, data) {
31
+ super(platform, accessory, data);
32
+ this.service = this.ensureService(this.Service.ContactSensor, sanitizeDeviceName(this.name, this.id));
33
+ this.batteryService?.updateCharacteristic(this.Characteristic.ChargingState, this.Characteristic.ChargingState.NOT_CHARGEABLE);
34
+ this.service.getCharacteristic(this.Characteristic.ContactSensorState)
35
+ .onGet(() => this.getSensorState());
36
+ this.service.getCharacteristic(this.Characteristic.StatusTampered)
37
+ .onGet(() => this.getTamperedState());
38
+ this.notify();
39
+ }
40
+ getSensorState() {
41
+ return this.data.Status
42
+ ? this.Characteristic.ContactSensorState.CONTACT_NOT_DETECTED
43
+ : this.Characteristic.ContactSensorState.CONTACT_DETECTED;
44
+ }
45
+ notify() {
46
+ super.notify();
47
+ this.service.updateCharacteristic(this.Characteristic.ContactSensorState, this.getSensorState());
48
+ this.service.updateCharacteristic(this.Characteristic.StatusTampered, this.getTamperedState());
49
+ }
50
+ static appliesTo(data) {
51
+ return data.Type === VivintDict.PanelDeviceType.WirelessSensor
52
+ && EQUIPMENT_CODES.includes(data.EquipmentCode);
53
+ }
54
+ static inferCategory(data, categories) {
55
+ const name = data.Name ?? '';
56
+ if (name.match(/\bwindow\b/i)) {
57
+ return categories.WINDOW;
58
+ }
59
+ else if (name.match(/\bdoor(way)?\b/i)) {
60
+ return categories.DOOR;
61
+ }
62
+ return categories.SENSOR;
63
+ }
64
+ }
65
+ //# sourceMappingURL=contactSensor.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"contactSensor.js","sourceRoot":"","sources":["../../src/devices/contactSensor.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,147 @@
1
+ import { dataPatch } from '../vivint/datapatch.js';
2
+ /**
3
+ * Base class for all Vivint device handlers. A handler wraps one Homebridge
4
+ * accessory, keeps the latest device data from the Vivint API, and pushes
5
+ * state changes into HomeKit.
6
+ */
7
+ export class VivintDevice {
8
+ platform;
9
+ accessory;
10
+ /**
11
+ * Stable class name stored in accessory.context.deviceClassName. Must not
12
+ * change between releases, or cached accessories would be recreated.
13
+ */
14
+ static className = 'VivintDevice';
15
+ /** Whether this device type exposes a Battery service. */
16
+ static hasBattery = false;
17
+ id;
18
+ name;
19
+ data;
20
+ batteryService;
21
+ constructor(platform, accessory, data) {
22
+ this.platform = platform;
23
+ this.accessory = accessory;
24
+ this.id = accessory.context.id;
25
+ this.name = accessory.context.name;
26
+ this.data = data ?? { Id: this.id };
27
+ const ctor = this.constructor;
28
+ if (ctor.hasBattery) {
29
+ this.batteryService = this.ensureService(this.platform.Service.Battery, `${this.name} Battery`);
30
+ this.batteryService.getCharacteristic(this.platform.Characteristic.StatusLowBattery)
31
+ .onGet(() => this.getLowBatteryState());
32
+ this.batteryService.getCharacteristic(this.platform.Characteristic.BatteryLevel)
33
+ .onGet(() => this.getBatteryLevelValue());
34
+ }
35
+ }
36
+ /**
37
+ * Returns the existing service of the given type, adding it first if the
38
+ * cached accessory does not have it yet.
39
+ */
40
+ ensureService(type, name) {
41
+ const existing = this.accessory.getService(type);
42
+ if (existing) {
43
+ return existing;
44
+ }
45
+ // Concrete service classes take (displayName?, subtype?) — the abstract
46
+ // base type does not reflect that, hence the cast.
47
+ const ServiceCtor = type;
48
+ return this.accessory.addService(new ServiceCtor(name));
49
+ }
50
+ get Characteristic() {
51
+ return this.platform.Characteristic;
52
+ }
53
+ get Service() {
54
+ return this.platform.Service;
55
+ }
56
+ get log() {
57
+ return this.platform.log;
58
+ }
59
+ get vivintApi() {
60
+ return this.platform.vivintApi;
61
+ }
62
+ get config() {
63
+ return this.platform.config;
64
+ }
65
+ getBatteryLevelValue() {
66
+ return typeof this.data.BatteryLevel === 'number' ? this.data.BatteryLevel : 100;
67
+ }
68
+ getLowBatteryState() {
69
+ const threshold = this.config.lowBatteryLevel;
70
+ const low = threshold
71
+ ? this.getBatteryLevelValue() <= threshold
72
+ : Boolean(this.data.LowBattery);
73
+ return low
74
+ ? this.Characteristic.StatusLowBattery.BATTERY_LEVEL_LOW
75
+ : this.Characteristic.StatusLowBattery.BATTERY_LEVEL_NORMAL;
76
+ }
77
+ getTamperedState() {
78
+ return this.data.Tamper
79
+ ? this.Characteristic.StatusTampered.TAMPERED
80
+ : this.Characteristic.StatusTampered.NOT_TAMPERED;
81
+ }
82
+ /**
83
+ * Replaces the cached data with a full snapshot from the API.
84
+ */
85
+ handleSnapshot(data) {
86
+ if (data.Id !== this.id) {
87
+ this.log.warn(`Ignoring snapshot for device ${data.Id} delivered to device ${this.id}`);
88
+ return;
89
+ }
90
+ this.data = data;
91
+ this.notifySafely();
92
+ }
93
+ /**
94
+ * Applies an incremental realtime patch to the cached data.
95
+ */
96
+ handlePatch(patch) {
97
+ if (patch.Id !== this.id) {
98
+ this.log.warn(`Ignoring patch for device ${patch.Id} delivered to device ${this.id}`);
99
+ return;
100
+ }
101
+ dataPatch(this.data, patch);
102
+ this.notifySafely();
103
+ }
104
+ notifySafely() {
105
+ try {
106
+ this.notify();
107
+ }
108
+ catch (error) {
109
+ // One misbehaving device must never break updates for the others.
110
+ this.log.error(`Error while updating HomeKit state for '${this.name}':`, error);
111
+ }
112
+ }
113
+ /**
114
+ * Pushes the current cached state into HomeKit.
115
+ */
116
+ notify() {
117
+ if (this.batteryService) {
118
+ this.batteryService.updateCharacteristic(this.Characteristic.StatusLowBattery, this.getLowBatteryState());
119
+ this.batteryService.updateCharacteristic(this.Characteristic.BatteryLevel, this.getBatteryLevelValue());
120
+ }
121
+ }
122
+ /**
123
+ * Wraps a HomeKit "set" action with uniform error handling: failures are
124
+ * logged with a helpful message and surfaced to HomeKit as a communication
125
+ * failure rather than crashing the plugin.
126
+ */
127
+ async runSetAction(description, action) {
128
+ try {
129
+ await action();
130
+ }
131
+ catch (error) {
132
+ this.log.error(`Failed to ${description} for '${this.name}':`, error instanceof Error ? error.message : error);
133
+ throw new this.platform.api.hap.HapStatusError(-70402 /* this.platform.api.hap.HAPStatus.SERVICE_COMMUNICATION_FAILURE */);
134
+ }
135
+ }
136
+ /** Whether this handler manages the given Vivint device. */
137
+ static appliesTo(data) {
138
+ void data;
139
+ return false;
140
+ }
141
+ /** The HomeKit accessory category to use when first publishing the accessory. */
142
+ static inferCategory(data, categories) {
143
+ void data;
144
+ return categories.OTHER;
145
+ }
146
+ }
147
+ //# sourceMappingURL=device.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"device.js","sourceRoot":"","sources":["../../src/devices/device.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,12 @@
1
+ import { VivintDict } from '../vivint/dictionary.js';
2
+ import { MultiLevelSwitchBase } from './multiLevelSwitchBase.js';
3
+ export class DimmerSwitch extends MultiLevelSwitchBase {
4
+ static className = 'DimmerSwitch';
5
+ static appliesTo(data) {
6
+ return data.Type === VivintDict.PanelDeviceType.MultiLevelSwitch;
7
+ }
8
+ static inferCategory(data, categories) {
9
+ return categories.SWITCH;
10
+ }
11
+ }
12
+ //# sourceMappingURL=dimmerSwitch.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dimmerSwitch.js","sourceRoot":"","sources":["../../src/devices/dimmerSwitch.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAC;AAErD,OAAO,EAAE,oBAAoB,EAAE,MAAM,2BAA2B,CAAC;AAEjE,MAAM,OAAO,YAAa,SAAQ,oBAAoB;IACpD,MAAM,CAAmB,SAAS,GAAG,cAAc,CAAC;IAEpD,MAAM,CAAU,SAAS,CAAC,IAAgB;QACxC,OAAO,IAAI,CAAC,IAAI,KAAK,UAAU,CAAC,eAAe,CAAC,gBAAgB,CAAC;IACnE,CAAC;IAED,MAAM,CAAU,aAAa,CAAC,IAAgB,EAAE,UAAyB;QACvE,OAAO,UAAU,CAAC,MAAM,CAAC;IAC3B,CAAC"}
@@ -0,0 +1,58 @@
1
+ import { sanitizeDeviceName } from '../utils/sanitizeName.js';
2
+ import { VivintDict } from '../vivint/dictionary.js';
3
+ import { VivintDevice } from './device.js';
4
+ export class GarageDoor extends VivintDevice {
5
+ static className = 'GarageDoor';
6
+ service;
7
+ constructor(platform, accessory, data) {
8
+ super(platform, accessory, data);
9
+ this.service = this.ensureService(this.Service.GarageDoorOpener, sanitizeDeviceName(this.name, this.id));
10
+ this.service.getCharacteristic(this.Characteristic.CurrentDoorState)
11
+ .onGet(() => this.getGarageDoorCurrentState());
12
+ this.service.getCharacteristic(this.Characteristic.TargetDoorState)
13
+ .onGet(() => this.getGarageDoorTargetState())
14
+ .onSet(value => this.setTargetState(value));
15
+ this.notify();
16
+ }
17
+ async setTargetState(targetState) {
18
+ const closing = targetState === this.Characteristic.TargetDoorState.CLOSED;
19
+ const targetVivintState = closing ? VivintDict.GarageDoorStates.Closing : VivintDict.GarageDoorStates.Opening;
20
+ await this.runSetAction(`${closing ? 'close' : 'open'} the garage door`, () => this.vivintApi.setGarageDoorState(this.id, targetVivintState));
21
+ }
22
+ getGarageDoorCurrentState() {
23
+ switch (this.data.Status) {
24
+ case VivintDict.GarageDoorStates.Unknown: // treat unknown as closed to avoid double notifications
25
+ case VivintDict.GarageDoorStates.Closed:
26
+ return this.Characteristic.CurrentDoorState.CLOSED;
27
+ case VivintDict.GarageDoorStates.Closing:
28
+ return this.Characteristic.CurrentDoorState.CLOSING;
29
+ case VivintDict.GarageDoorStates.Opening:
30
+ return this.Characteristic.CurrentDoorState.OPENING;
31
+ case VivintDict.GarageDoorStates.Opened:
32
+ return this.Characteristic.CurrentDoorState.OPEN;
33
+ default:
34
+ return this.Characteristic.CurrentDoorState.STOPPED;
35
+ }
36
+ }
37
+ getGarageDoorTargetState() {
38
+ switch (this.data.Status) {
39
+ case VivintDict.GarageDoorStates.Opening:
40
+ case VivintDict.GarageDoorStates.Opened:
41
+ return this.Characteristic.TargetDoorState.OPEN;
42
+ default:
43
+ return this.Characteristic.TargetDoorState.CLOSED;
44
+ }
45
+ }
46
+ notify() {
47
+ super.notify();
48
+ this.service.updateCharacteristic(this.Characteristic.CurrentDoorState, this.getGarageDoorCurrentState());
49
+ this.service.updateCharacteristic(this.Characteristic.TargetDoorState, this.getGarageDoorTargetState());
50
+ }
51
+ static appliesTo(data) {
52
+ return data.Type === VivintDict.PanelDeviceType.GarageDoor;
53
+ }
54
+ static inferCategory(data, categories) {
55
+ return categories.GARAGE_DOOR_OPENER;
56
+ }
57
+ }
58
+ //# sourceMappingURL=garageDoor.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"garageDoor.js","sourceRoot":"","sources":["../../src/devices/garageDoor.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,55 @@
1
+ import { Camera } from './camera.js';
2
+ import { CarbonMonoxideSensor } from './carbonMonoxideSensor.js';
3
+ import { ContactSensor } from './contactSensor.js';
4
+ import { VivintDevice } from './device.js';
5
+ import { DimmerSwitch } from './dimmerSwitch.js';
6
+ import { GarageDoor } from './garageDoor.js';
7
+ import { LightGroup } from './lightGroup.js';
8
+ import { LightSwitch } from './lightSwitch.js';
9
+ import { Lock } from './lock.js';
10
+ import { MotionSensor } from './motionSensor.js';
11
+ import { Panel } from './panel.js';
12
+ import { SmokeSensor } from './smokeSensor.js';
13
+ import { Thermostat } from './thermostat.js';
14
+ export { VivintDevice };
15
+ /**
16
+ * All supported device handlers, in matching priority order.
17
+ */
18
+ export const DEVICE_HANDLERS = [
19
+ ContactSensor,
20
+ SmokeSensor,
21
+ CarbonMonoxideSensor,
22
+ MotionSensor,
23
+ Lock,
24
+ Thermostat,
25
+ GarageDoor,
26
+ Panel,
27
+ Camera,
28
+ LightSwitch,
29
+ DimmerSwitch,
30
+ LightGroup,
31
+ ];
32
+ export function findHandlerForData(data) {
33
+ return DEVICE_HANDLERS.find(handler => handler.appliesTo(data));
34
+ }
35
+ export function findHandlerByClassName(className) {
36
+ return DEVICE_HANDLERS.find(handler => handler.className === className);
37
+ }
38
+ /**
39
+ * Device types that exist in the Vivint snapshot but have no HomeKit purpose.
40
+ * They are silently skipped instead of being reported as unsupported.
41
+ */
42
+ export const IRRELEVANT_DEVICE_TYPES = [
43
+ 'sensor_group',
44
+ 'network_hosts_service',
45
+ 'panel_diagnostics_service',
46
+ 'iot_service',
47
+ 'scheduler_service',
48
+ 'yofi_device',
49
+ 'keyfob_device',
50
+ 'control4_device',
51
+ 'lgit_poe_wifi_bridge_device',
52
+ 'mqtt_audio_sync_service',
53
+ 'holiday_theme_service',
54
+ ];
55
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/devices/index.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AACrC,OAAO,EAAE,oBAAoB,EAAE,MAAM,2BAA2B,CAAC;AACjE,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACnD,OAAO,EAAiB,YAAY,EAAE,MAAM,aAAa,CAAC;AAC1D,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AACjD,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAC7C,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAC7C,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAC/C,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AACjD,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AACnC,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAC/C,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAE7C,OAAO,EAAE,YAAY,EAAE,CAAC;AAaxB;;GAEG;AACH,MAAM,CAAC,MAAM,eAAe,GAAyB;IACnD,aAAa;IACb,WAAW;IACX,oBAAoB;IACpB,YAAY;IACZ,IAAI;IACJ,UAAU;IACV,UAAU;IACV,KAAK;IACL,MAAM;IACN,WAAW;IACX,YAAY;IACZ,UAAU;CACX,CAAC;AAEF,MAAM,UAAU,kBAAkB,CAAC,IAAgB;IACjD,OAAO,eAAe,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC,OAAO,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC;AAClE,CAAC;AAED,MAAM,UAAU,sBAAsB,CAAC,SAAiB;IACtD,OAAO,eAAe,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC,OAAO,CAAC,SAAS,KAAK,SAAS,CAAC,CAAC;AAC1E,CAAC;AAED;;;GAGG;AACH,MAAM,CAAC,MAAM,uBAAuB,GAAG;IACrC,cAAc;IACd,uBAAuB;IACvB,2BAA2B;IAC3B,aAAa;IACb,mBAAmB;IACnB,aAAa;IACb,eAAe;IACf,iBAAiB;IACjB,6BAA6B;IAC7B,yBAAyB;IACzB,uBAAuB;CACxB,CAAC"}
@@ -0,0 +1,15 @@
1
+ import { VivintDict } from '../vivint/dictionary.js';
2
+ import { MultiLevelSwitchBase } from './multiLevelSwitchBase.js';
3
+ export class LightGroup extends MultiLevelSwitchBase {
4
+ static className = 'LightGroup';
5
+ static appliesTo(data) {
6
+ return data.Type === VivintDict.PanelDeviceType.GroupDevices
7
+ && Array.isArray(data.panel_capability_types)
8
+ && data.panel_capability_types.includes(VivintDict.PanelCapabilityType.Dimmable)
9
+ && data.panel_capability_types.includes(VivintDict.PanelCapabilityType.GroupDevices);
10
+ }
11
+ static inferCategory(data, categories) {
12
+ return categories.SWITCH;
13
+ }
14
+ }
15
+ //# sourceMappingURL=lightGroup.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lightGroup.js","sourceRoot":"","sources":["../../src/devices/lightGroup.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAC;AAErD,OAAO,EAAE,oBAAoB,EAAE,MAAM,2BAA2B,CAAC;AAEjE,MAAM,OAAO,UAAW,SAAQ,oBAAoB;IAClD,MAAM,CAAmB,SAAS,GAAG,YAAY,CAAC;IAElD,MAAM,CAAU,SAAS,CAAC,IAAgB;QACxC,OAAO,IAAI,CAAC,IAAI,KAAK,UAAU,CAAC,eAAe,CAAC,YAAY;eACvD,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,sBAAsB,CAAC;eAC1C,IAAI,CAAC,sBAAsB,CAAC,QAAQ,CAAC,UAAU,CAAC,mBAAmB,CAAC,QAAQ,CAAC;eAC7E,IAAI,CAAC,sBAAsB,CAAC,QAAQ,CAAC,UAAU,CAAC,mBAAmB,CAAC,YAAY,CAAC,CAAC;IACzF,CAAC;IAED,MAAM,CAAU,aAAa,CAAC,IAAgB,EAAE,UAAyB;QACvE,OAAO,UAAU,CAAC,MAAM,CAAC;IAC3B,CAAC"}
@@ -0,0 +1,42 @@
1
+ import { sanitizeDeviceName } from '../utils/sanitizeName.js';
2
+ import { VivintDict } from '../vivint/dictionary.js';
3
+ import { VivintDevice } from './device.js';
4
+ /**
5
+ * Binary Z-Wave switch. Exposed as a lightbulb, fan or plain switch depending
6
+ * on the device name.
7
+ */
8
+ export class LightSwitch extends VivintDevice {
9
+ static className = 'LightSwitch';
10
+ service;
11
+ constructor(platform, accessory, data) {
12
+ super(platform, accessory, data);
13
+ const sanitizedName = sanitizeDeviceName(this.name, this.id);
14
+ if (this.name.match(/\blight\b/i)) {
15
+ this.service = this.ensureService(this.Service.Lightbulb, sanitizedName);
16
+ }
17
+ else if (this.name.match(/\bfan\b/i)) {
18
+ this.service = this.ensureService(this.Service.Fan, sanitizedName);
19
+ }
20
+ else {
21
+ this.service = this.ensureService(this.Service.Switch, sanitizedName);
22
+ }
23
+ this.service.getCharacteristic(this.Characteristic.On)
24
+ .onGet(() => Boolean(this.data.Status))
25
+ .onSet(value => this.setSwitchState(value));
26
+ }
27
+ async setSwitchState(targetState) {
28
+ const on = Boolean(targetState);
29
+ await this.runSetAction(`turn the switch ${on ? 'on' : 'off'}`, () => this.vivintApi.putDevice('switches', this.id, { s: on, _id: this.id }));
30
+ }
31
+ notify() {
32
+ super.notify();
33
+ this.service.updateCharacteristic(this.Characteristic.On, this.data.Value !== 0);
34
+ }
35
+ static appliesTo(data) {
36
+ return data.Type === VivintDict.PanelDeviceType.BinarySwitch;
37
+ }
38
+ static inferCategory(data, categories) {
39
+ return categories.SWITCH;
40
+ }
41
+ }
42
+ //# sourceMappingURL=lightSwitch.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lightSwitch.js","sourceRoot":"","sources":["../../src/devices/lightSwitch.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,kBAAkB,EAAE,MAAM,0BAA0B,CAAC;AAC9D,OAAO,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAC;AACrD,OAAO,EAAiB,YAAY,EAAE,MAAM,aAAa,CAAC;AAE1D;;;GAGG;AACH,MAAM,OAAO,WAAY,SAAQ,YAAY;IAC3C,MAAM,CAAmB,SAAS,GAAG,aAAa,CAAC;IAElC,OAAO,CAAU;IAElC,YAAY,QAAwB,EAAE,SAAoD,EAAE,IAA4B;QACtH,KAAK,CAAC,QAAQ,EAAE,SAAS,EAAE,IAAI,CAAC,CAAC;QAEjC,MAAM,aAAa,GAAG,kBAAkB,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,EAAE,CAAC,CAAC;QAC7D,IAAI,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,EAAE,CAAC;YAClC,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,OAAO,CAAC,SAAS,EAAE,aAAa,CAAC,CAAC;QAC3E,CAAC;aAAM,IAAI,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC,EAAE,CAAC;YACvC,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,aAAa,CAAC,CAAC;QACrE,CAAC;aAAM,CAAC;YACN,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,aAAa,CAAC,CAAC;QACxE,CAAC;QAED,IAAI,CAAC,OAAO,CAAC,iBAAiB,CAAC,IAAI,CAAC,cAAc,CAAC,EAAE,CAAC;aACnD,KAAK,CAAC,GAAG,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;aACtC,KAAK,CAAC,KAAK,CAAC,EAAE,CAAC,IAAI,CAAC,cAAc,CAAC,KAAK,CAAC,CAAC,CAAC;IAChD,CAAC;IAEO,KAAK,CAAC,cAAc,CAAC,WAAgC;QAC3D,MAAM,EAAE,GAAG,OAAO,CAAC,WAAW,CAAC,CAAC;QAChC,MAAM,IAAI,CAAC,YAAY,CAAC,mBAAmB,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,EAAE,EAAE,GAAG,EAAE,CACnE,IAAI,CAAC,SAAS,CAAC,SAAS,CAAC,UAAU,EAAE,IAAI,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,EAAE,EAAE,GAAG,EAAE,IAAI,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC;IAC5E,CAAC;IAEQ,MAAM;QACb,KAAK,CAAC,MAAM,EAAE,CAAC;QACf,IAAI,CAAC,OAAO,CAAC,oBAAoB,CAAC,IAAI,CAAC,cAAc,CAAC,EAAE,EAAE,IAAI,CAAC,IAAI,CAAC,KAAK,KAAK,CAAC,CAAC,CAAC;IACnF,CAAC;IAED,MAAM,CAAU,SAAS,CAAC,IAAgB;QACxC,OAAO,IAAI,CAAC,IAAI,KAAK,UAAU,CAAC,eAAe,CAAC,YAAY,CAAC;IAC/D,CAAC;IAED,MAAM,CAAU,aAAa,CAAC,IAAgB,EAAE,UAAyB;QACvE,OAAO,UAAU,CAAC,MAAM,CAAC;IAC3B,CAAC"}
@@ -0,0 +1,49 @@
1
+ import { sanitizeDeviceName } from '../utils/sanitizeName.js';
2
+ import { VivintDict } from '../vivint/dictionary.js';
3
+ import { VivintDevice } from './device.js';
4
+ export class Lock extends VivintDevice {
5
+ static className = 'Lock';
6
+ static hasBattery = true;
7
+ service;
8
+ constructor(platform, accessory, data) {
9
+ super(platform, accessory, data);
10
+ this.service = this.ensureService(this.Service.LockMechanism, sanitizeDeviceName(this.name, this.id));
11
+ this.batteryService?.updateCharacteristic(this.Characteristic.ChargingState, this.Characteristic.ChargingState.NOT_CHARGEABLE);
12
+ this.service.getCharacteristic(this.Characteristic.LockCurrentState)
13
+ .onGet(() => this.getLockState());
14
+ this.service.getCharacteristic(this.Characteristic.LockTargetState)
15
+ .onSet(value => this.setTargetState(value));
16
+ this.notify();
17
+ }
18
+ async setTargetState(targetState) {
19
+ const locked = targetState === this.Characteristic.LockTargetState.SECURED;
20
+ await this.runSetAction(`set lock state to ${locked ? 'locked' : 'unlocked'}`, () => this.vivintApi.setLockState(this.id, locked));
21
+ }
22
+ getLockState() {
23
+ switch (this.data.Status) {
24
+ case false:
25
+ return this.Characteristic.LockCurrentState.UNSECURED;
26
+ case true:
27
+ return this.Characteristic.LockCurrentState.SECURED;
28
+ case this.Characteristic.LockCurrentState.JAMMED:
29
+ return this.Characteristic.LockCurrentState.JAMMED;
30
+ default:
31
+ return this.Characteristic.LockCurrentState.UNKNOWN;
32
+ }
33
+ }
34
+ notify() {
35
+ super.notify();
36
+ const state = this.getLockState();
37
+ this.service.updateCharacteristic(this.Characteristic.LockCurrentState, state);
38
+ this.service.updateCharacteristic(this.Characteristic.LockTargetState, state === this.Characteristic.LockCurrentState.SECURED
39
+ ? this.Characteristic.LockTargetState.SECURED
40
+ : this.Characteristic.LockTargetState.UNSECURED);
41
+ }
42
+ static appliesTo(data) {
43
+ return data.Type === VivintDict.PanelDeviceType.DoorLock;
44
+ }
45
+ static inferCategory(data, categories) {
46
+ return categories.DOOR_LOCK;
47
+ }
48
+ }
49
+ //# sourceMappingURL=lock.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lock.js","sourceRoot":"","sources":["../../src/devices/lock.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,73 @@
1
+ import { sanitizeDeviceName } from '../utils/sanitizeName.js';
2
+ import { VivintDict } from '../vivint/dictionary.js';
3
+ import { VivintDevice } from './device.js';
4
+ const EQUIPMENT_CODES = [
5
+ 'PIR1_MOTION',
6
+ 'PIR2_MOTION',
7
+ 'EXISTING_MOTION_DETECTOR',
8
+ ].map(name => VivintDict.EquipmentCode[name]);
9
+ export class MotionSensor extends VivintDevice {
10
+ static className = 'MotionSensor';
11
+ static hasBattery = true;
12
+ service;
13
+ occupancyService;
14
+ occupancyTimeoutMs;
15
+ lastSensedMotion;
16
+ occupancyTimer;
17
+ constructor(platform, accessory, data) {
18
+ super(platform, accessory, data);
19
+ const sanitizedName = sanitizeDeviceName(this.name, this.id);
20
+ this.occupancyTimeoutMs = (this.config.motionDetectedOccupancySensorMins ?? 0) * 60 * 1000;
21
+ this.service = this.ensureService(this.Service.MotionSensor, sanitizedName);
22
+ this.batteryService?.updateCharacteristic(this.Characteristic.ChargingState, this.Characteristic.ChargingState.NOT_CHARGEABLE);
23
+ this.service.getCharacteristic(this.Characteristic.MotionDetected)
24
+ .onGet(() => this.getMotionDetectedState());
25
+ this.service.getCharacteristic(this.Characteristic.StatusTampered)
26
+ .onGet(() => this.getTamperedState());
27
+ if (this.occupancyTimeoutMs > 0) {
28
+ this.occupancyService = this.ensureService(this.Service.OccupancySensor, `${sanitizedName} Occupancy`);
29
+ this.occupancyService.getCharacteristic(this.Characteristic.OccupancyDetected)
30
+ .onGet(() => this.getOccupancyState());
31
+ this.occupancyTimer = setInterval(() => this.notifyOccupancy(), 60 * 1000);
32
+ this.occupancyTimer.unref();
33
+ }
34
+ else {
35
+ // The occupancy sensor was disabled in the config; drop a stale service
36
+ // left over on the cached accessory.
37
+ const stale = accessory.getService(this.Service.OccupancySensor);
38
+ if (stale) {
39
+ accessory.removeService(stale);
40
+ }
41
+ }
42
+ this.notify();
43
+ }
44
+ getOccupancyState() {
45
+ if (this.lastSensedMotion !== undefined && Date.now() - this.lastSensedMotion < this.occupancyTimeoutMs) {
46
+ return this.Characteristic.OccupancyDetected.OCCUPANCY_DETECTED;
47
+ }
48
+ return this.Characteristic.OccupancyDetected.OCCUPANCY_NOT_DETECTED;
49
+ }
50
+ getMotionDetectedState() {
51
+ return Boolean(this.data.Status);
52
+ }
53
+ notifyOccupancy() {
54
+ this.occupancyService?.updateCharacteristic(this.Characteristic.OccupancyDetected, this.getOccupancyState());
55
+ }
56
+ notify() {
57
+ super.notify();
58
+ if (this.getMotionDetectedState()) {
59
+ this.lastSensedMotion = Date.now();
60
+ }
61
+ this.service.updateCharacteristic(this.Characteristic.MotionDetected, this.getMotionDetectedState());
62
+ this.service.updateCharacteristic(this.Characteristic.StatusTampered, this.getTamperedState());
63
+ this.notifyOccupancy();
64
+ }
65
+ static appliesTo(data) {
66
+ return data.Type === VivintDict.PanelDeviceType.WirelessSensor
67
+ && EQUIPMENT_CODES.includes(data.EquipmentCode);
68
+ }
69
+ static inferCategory(data, categories) {
70
+ return categories.SENSOR;
71
+ }
72
+ }
73
+ //# sourceMappingURL=motionSensor.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"motionSensor.js","sourceRoot":"","sources":["../../src/devices/motionSensor.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,55 @@
1
+ import { debounceLeading } from '../utils/debounce.js';
2
+ import { sanitizeDeviceName } from '../utils/sanitizeName.js';
3
+ import { VivintDevice } from './device.js';
4
+ const BRIGHTNESS_DEBOUNCE_MS = 500;
5
+ /**
6
+ * Shared behavior for dimmable devices (dimmer switches and Philips Hue light
7
+ * groups). Exposed as a fan with rotation speed when the device name contains
8
+ * "fan", otherwise as a dimmable lightbulb.
9
+ */
10
+ export class MultiLevelSwitchBase extends VivintDevice {
11
+ service;
12
+ isFan;
13
+ lastOnState;
14
+ lastLevel;
15
+ setLevelDebounced;
16
+ constructor(platform, accessory, data) {
17
+ super(platform, accessory, data);
18
+ const sanitizedName = sanitizeDeviceName(this.name, this.id);
19
+ this.isFan = Boolean(this.name.match(/\bfan\b/i));
20
+ this.service = this.isFan
21
+ ? this.ensureService(this.Service.Fan, sanitizedName)
22
+ : this.ensureService(this.Service.Lightbulb, sanitizedName);
23
+ this.service.getCharacteristic(this.Characteristic.On)
24
+ .onGet(() => Boolean(this.data.Status))
25
+ .onSet(value => this.setSwitchState(value));
26
+ // Dragging the brightness/speed slider produces a burst of set requests;
27
+ // debounce them so only the first and final values reach the Vivint API.
28
+ this.setLevelDebounced = debounceLeading((level) => this.vivintApi.putDevice('switches', this.id, { val: level, _id: this.id }), BRIGHTNESS_DEBOUNCE_MS);
29
+ const levelCharacteristic = this.isFan ? this.Characteristic.RotationSpeed : this.Characteristic.Brightness;
30
+ this.service.getCharacteristic(levelCharacteristic)
31
+ .onGet(() => this.data.Value ?? 0)
32
+ .onSet(value => this.setLevel(value));
33
+ }
34
+ async setSwitchState(targetState) {
35
+ const on = Boolean(targetState);
36
+ await this.runSetAction(`turn ${on ? 'on' : 'off'}`, () => this.vivintApi.putDevice('switches', this.id, { s: on, _id: this.id }));
37
+ }
38
+ async setLevel(value) {
39
+ await this.runSetAction(`set the level to ${value}`, () => this.setLevelDebounced(value));
40
+ }
41
+ notify() {
42
+ super.notify();
43
+ // Vivint typically sends each change twice; only push actual changes.
44
+ if (this.data.Value !== this.lastLevel) {
45
+ this.lastLevel = this.data.Value;
46
+ const levelCharacteristic = this.isFan ? this.Characteristic.RotationSpeed : this.Characteristic.Brightness;
47
+ this.service.updateCharacteristic(levelCharacteristic, this.data.Value ?? 0);
48
+ }
49
+ if (this.data.Status !== this.lastOnState) {
50
+ this.lastOnState = this.data.Status;
51
+ this.service.updateCharacteristic(this.Characteristic.On, Boolean(this.data.Status));
52
+ }
53
+ }
54
+ }
55
+ //# sourceMappingURL=multiLevelSwitchBase.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"multiLevelSwitchBase.js","sourceRoot":"","sources":["../../src/devices/multiLevelSwitchBase.ts"],"names":[],"mappings":"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"}