isy-nodejs 1.0.1-alpha.1 → 1.0.1-alpha.2
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/dist/cjs/ISY.js +113 -110
- package/dist/cjs/ISY.js.map +1 -1
- package/dist/cjs/ISYNode.js +21 -5
- package/dist/cjs/ISYNode.js.map +1 -1
- package/dist/cjs/types/ISY.d.ts +37 -37
- package/dist/cjs/types/ISY.d.ts.map +1 -1
- package/dist/cjs/types/ISYNode.d.ts.map +1 -1
- package/dist/esm/ISY.js +152 -149
- package/dist/esm/ISY.js.map +1 -1
- package/dist/esm/ISYNode.js +21 -5
- package/dist/esm/ISYNode.js.map +1 -1
- package/dist/esm/types/ISY.d.ts +37 -37
- package/dist/esm/types/ISY.d.ts.map +1 -1
- package/dist/esm/types/ISYNode.d.ts.map +1 -1
- package/dist/tsconfig.cjs.tsbuildinfo +1 -1
- package/dist/tsconfig.esm.tsbuildinfo +1 -1
- package/package.json +3 -5
- package/src/ISY.ts +790 -820
- package/src/ISYNode.ts +19 -6
- package/dist/esm/Devices/Brultech/index.js +0 -4
- package/dist/esm/Devices/Brultech/index.js.map +0 -1
- package/dist/esm/Devices/Constructor.js +0 -2
- package/dist/esm/Devices/Constructor.js.map +0 -1
- package/dist/esm/Devices/DeviceFactory.js +0 -13
- package/dist/esm/Devices/DeviceFactory.js.map +0 -1
- package/dist/esm/Devices/DeviceMap.js +0 -4
- package/dist/esm/Devices/DeviceMap.js.map +0 -1
- package/dist/esm/Devices/Elk/ElkAlarmPanelDevice.js +0 -181
- package/dist/esm/Devices/Elk/ElkAlarmPanelDevice.js.map +0 -1
- package/dist/esm/Devices/Elk/ElkAlarmSensorDevice.js +0 -107
- package/dist/esm/Devices/Elk/ElkAlarmSensorDevice.js.map +0 -1
- package/dist/esm/Devices/EndpointFor.js +0 -31
- package/dist/esm/Devices/EndpointFor.js.map +0 -1
- package/dist/esm/Devices/ISYDevice.js +0 -35
- package/dist/esm/Devices/ISYDevice.js.map +0 -1
- package/dist/esm/Devices/ISYDeviceNode.js +0 -62
- package/dist/esm/Devices/ISYDeviceNode.js.map +0 -1
- package/dist/esm/Devices/ISYMultiNodeDevice.js +0 -89
- package/dist/esm/Devices/ISYMultiNodeDevice.js.map +0 -1
- package/dist/esm/Devices/Insteon/InsteonBallastDimmerDevice.js +0 -8
- package/dist/esm/Devices/Insteon/InsteonBallastDimmerDevice.js.map +0 -1
- package/dist/esm/Devices/Insteon/InsteonBaseDevice.js +0 -47
- package/dist/esm/Devices/Insteon/InsteonBaseDevice.js.map +0 -1
- package/dist/esm/Devices/Insteon/InsteonCOSensorDevice.js +0 -14
- package/dist/esm/Devices/Insteon/InsteonCOSensorDevice.js.map +0 -1
- package/dist/esm/Devices/Insteon/InsteonDevice.js +0 -17
- package/dist/esm/Devices/Insteon/InsteonDevice.js.map +0 -1
- package/dist/esm/Devices/Insteon/InsteonDeviceFactory.js +0 -875
- package/dist/esm/Devices/Insteon/InsteonDeviceFactory.js.map +0 -1
- package/dist/esm/Devices/Insteon/InsteonDimmableDevice.js +0 -32
- package/dist/esm/Devices/Insteon/InsteonDimmableDevice.js.map +0 -1
- package/dist/esm/Devices/Insteon/InsteonDimmerOutletDevice.js +0 -7
- package/dist/esm/Devices/Insteon/InsteonDimmerOutletDevice.js.map +0 -1
- package/dist/esm/Devices/Insteon/InsteonDimmerSwitchDevice.js +0 -8
- package/dist/esm/Devices/Insteon/InsteonDimmerSwitchDevice.js.map +0 -1
- package/dist/esm/Devices/Insteon/InsteonDoorWindowSensorDevice.js +0 -11
- package/dist/esm/Devices/Insteon/InsteonDoorWindowSensorDevice.js.map +0 -1
- package/dist/esm/Devices/Insteon/InsteonFanDevice.js +0 -56
- package/dist/esm/Devices/Insteon/InsteonFanDevice.js.map +0 -1
- package/dist/esm/Devices/Insteon/InsteonKeypadDevice.js +0 -8
- package/dist/esm/Devices/Insteon/InsteonKeypadDevice.js.map +0 -1
- package/dist/esm/Devices/Insteon/InsteonKeypadDimmerDevice.js +0 -8
- package/dist/esm/Devices/Insteon/InsteonKeypadDimmerDevice.js.map +0 -1
- package/dist/esm/Devices/Insteon/InsteonKeypadRelayDevice.js +0 -8
- package/dist/esm/Devices/Insteon/InsteonKeypadRelayDevice.js.map +0 -1
- package/dist/esm/Devices/Insteon/InsteonLeakSensorDevice.js +0 -11
- package/dist/esm/Devices/Insteon/InsteonLeakSensorDevice.js.map +0 -1
- package/dist/esm/Devices/Insteon/InsteonLockDevice.js +0 -32
- package/dist/esm/Devices/Insteon/InsteonLockDevice.js.map +0 -1
- package/dist/esm/Devices/Insteon/InsteonMotionSensorDevice.js +0 -36
- package/dist/esm/Devices/Insteon/InsteonMotionSensorDevice.js.map +0 -1
- package/dist/esm/Devices/Insteon/InsteonOnOffOutletDevice.js +0 -19
- package/dist/esm/Devices/Insteon/InsteonOnOffOutletDevice.js.map +0 -1
- package/dist/esm/Devices/Insteon/InsteonRelayDevice.js +0 -46
- package/dist/esm/Devices/Insteon/InsteonRelayDevice.js.map +0 -1
- package/dist/esm/Devices/Insteon/InsteonRelaySwitchDevice.js +0 -8
- package/dist/esm/Devices/Insteon/InsteonRelaySwitchDevice.js.map +0 -1
- package/dist/esm/Devices/Insteon/InsteonSmokeSensorDevice.js +0 -11
- package/dist/esm/Devices/Insteon/InsteonSmokeSensorDevice.js.map +0 -1
- package/dist/esm/Devices/Insteon/InsteonThermostatDevice.js +0 -30
- package/dist/esm/Devices/Insteon/InsteonThermostatDevice.js.map +0 -1
- package/dist/esm/Devices/Insteon/index.js +0 -31
- package/dist/esm/Devices/Insteon/index.js.map +0 -1
- package/dist/esm/Devices/Lutron/index.js +0 -4
- package/dist/esm/Devices/Lutron/index.js.map +0 -1
- package/dist/esm/Devices/MapsTo.js +0 -2
- package/dist/esm/Devices/MapsTo.js.map +0 -1
- package/dist/esm/Devices/NCD/index.js +0 -4
- package/dist/esm/Devices/NCD/index.js.map +0 -1
- package/dist/esm/Devices/NodeFactory.js +0 -48
- package/dist/esm/Devices/NodeFactory.js.map +0 -1
- package/dist/esm/Devices/Poly/index.js +0 -4
- package/dist/esm/Devices/Poly/index.js.map +0 -1
- package/dist/esm/Devices/Scene/index.js +0 -4
- package/dist/esm/Devices/Scene/index.js.map +0 -1
- package/dist/esm/Devices/UDI/index.js +0 -4
- package/dist/esm/Devices/UDI/index.js.map +0 -1
- package/dist/esm/Devices/ZWave/ZWaveBaseDevice.js +0 -38
- package/dist/esm/Devices/ZWave/ZWaveBaseDevice.js.map +0 -1
- package/dist/esm/Devices/ZWave/ZWaveDimmerSwitchDevice.js +0 -8
- package/dist/esm/Devices/ZWave/ZWaveDimmerSwitchDevice.js.map +0 -1
- package/dist/esm/Devices/ZWave/ZWaveLockDevice.js +0 -35
- package/dist/esm/Devices/ZWave/ZWaveLockDevice.js.map +0 -1
- package/dist/esm/Devices/ZWave/index.js +0 -20
- package/dist/esm/Devices/ZWave/index.js.map +0 -1
- package/dist/esm/Devices/index.js +0 -9
- package/dist/esm/Devices/index.js.map +0 -1
package/dist/esm/ISY.js
CHANGED
|
@@ -1,54 +1,54 @@
|
|
|
1
|
-
import WebSocket from
|
|
2
|
-
import { writeFile } from
|
|
3
|
-
import { Parser } from
|
|
4
|
-
import { parseBooleans, parseNumbers } from
|
|
5
|
-
import { XmlDocument } from
|
|
6
|
-
import axios from
|
|
7
|
-
import { EventEmitter } from
|
|
8
|
-
import winston, { format, Logger, loggers } from
|
|
9
|
-
import { Category } from
|
|
10
|
-
import { Family } from
|
|
11
|
-
import { DeviceFactory } from
|
|
12
|
-
import { ELKAlarmPanelDevice } from
|
|
13
|
-
import { ElkAlarmSensorDevice } from
|
|
14
|
-
import { InsteonBaseDevice } from
|
|
15
|
-
import { InsteonOutletDevice } from
|
|
16
|
-
import { InsteonDimmableDevice } from
|
|
17
|
-
import { InsteonDimmerOutletDevice } from
|
|
18
|
-
import { InsteonDimmerSwitchDevice } from
|
|
19
|
-
import { InsteonDoorWindowSensorDevice } from
|
|
20
|
-
import { InsteonFanDevice, InsteonFanMotorDevice } from
|
|
21
|
-
import { InsteonKeypadButtonDevice } from
|
|
22
|
-
import { InsteonKeypadDimmerDevice } from
|
|
23
|
-
import { InsteonKeypadRelayDevice } from
|
|
24
|
-
import { InsteonLeakSensorDevice } from
|
|
25
|
-
import { InsteonLockDevice } from
|
|
26
|
-
import { InsteonMotionSensorDevice } from
|
|
27
|
-
import { InsteonOnOffOutletDevice } from
|
|
28
|
-
import { InsteonRelayDevice } from
|
|
29
|
-
import { InsteonSmokeSensorDevice } from
|
|
30
|
-
import { InsteonThermostatDevice } from
|
|
31
|
-
import { EventType } from
|
|
32
|
-
import { NodeType, Props, States, VariableType } from
|
|
33
|
-
import { ISYNode } from
|
|
34
|
-
import { ISYDeviceNode } from
|
|
35
|
-
import { ISYScene } from
|
|
36
|
-
import { ISYVariable } from
|
|
37
|
-
import * as Utils from
|
|
38
|
-
import { XMLParser } from
|
|
1
|
+
import WebSocket from 'faye-websocket';
|
|
2
|
+
import { writeFile } from 'fs';
|
|
3
|
+
import { Parser } from 'xml2js';
|
|
4
|
+
import { parseBooleans, parseNumbers } from 'xml2js/lib/processors.js';
|
|
5
|
+
import { XmlDocument } from 'xmldoc';
|
|
6
|
+
import axios from 'axios';
|
|
7
|
+
import { EventEmitter } from 'events';
|
|
8
|
+
import winston, { format, Logger, loggers } from 'winston';
|
|
9
|
+
import { Category } from './Definitions/Global/Categories.js';
|
|
10
|
+
import { Family } from './Definitions/Global/Families.js';
|
|
11
|
+
import { DeviceFactory } from './Devices/DeviceFactory.js';
|
|
12
|
+
import { ELKAlarmPanelDevice } from './Devices/Elk/ElkAlarmPanelDevice.js';
|
|
13
|
+
import { ElkAlarmSensorDevice } from './Devices/Elk/ElkAlarmSensorDevice.js';
|
|
14
|
+
import { InsteonBaseDevice } from './Devices/Insteon/InsteonBaseDevice.js';
|
|
15
|
+
import { InsteonOutletDevice } from './Devices/Insteon/InsteonDevice.js';
|
|
16
|
+
import { InsteonDimmableDevice } from './Devices/Insteon/InsteonDimmableDevice.js';
|
|
17
|
+
import { InsteonDimmerOutletDevice } from './Devices/Insteon/InsteonDimmerOutletDevice.js';
|
|
18
|
+
import { InsteonDimmerSwitchDevice } from './Devices/Insteon/InsteonDimmerSwitchDevice.js';
|
|
19
|
+
import { InsteonDoorWindowSensorDevice } from './Devices/Insteon/InsteonDoorWindowSensorDevice.js';
|
|
20
|
+
import { InsteonFanDevice, InsteonFanMotorDevice } from './Devices/Insteon/InsteonFanDevice.js';
|
|
21
|
+
import { InsteonKeypadButtonDevice } from './Devices/Insteon/InsteonKeypadDevice.js';
|
|
22
|
+
import { InsteonKeypadDimmerDevice } from './Devices/Insteon/InsteonKeypadDimmerDevice.js';
|
|
23
|
+
import { InsteonKeypadRelayDevice } from './Devices/Insteon/InsteonKeypadRelayDevice.js';
|
|
24
|
+
import { InsteonLeakSensorDevice } from './Devices/Insteon/InsteonLeakSensorDevice.js';
|
|
25
|
+
import { InsteonLockDevice } from './Devices/Insteon/InsteonLockDevice.js';
|
|
26
|
+
import { InsteonMotionSensorDevice } from './Devices/Insteon/InsteonMotionSensorDevice.js';
|
|
27
|
+
import { InsteonOnOffOutletDevice } from './Devices/Insteon/InsteonOnOffOutletDevice.js';
|
|
28
|
+
import { InsteonRelayDevice } from './Devices/Insteon/InsteonRelayDevice.js';
|
|
29
|
+
import { InsteonSmokeSensorDevice } from './Devices/Insteon/InsteonSmokeSensorDevice.js';
|
|
30
|
+
import { InsteonThermostatDevice } from './Devices/Insteon/InsteonThermostatDevice.js';
|
|
31
|
+
import { EventType } from './Events/EventType.js';
|
|
32
|
+
import { NodeType, Props, States, VariableType } from './ISYConstants.js';
|
|
33
|
+
import { ISYNode } from './ISYNode.js';
|
|
34
|
+
import { ISYDeviceNode } from './Devices/ISYDeviceNode.js';
|
|
35
|
+
import { ISYScene } from './ISYScene.js';
|
|
36
|
+
import { ISYVariable } from './ISYVariable.js';
|
|
37
|
+
import * as Utils from './Utils.js';
|
|
38
|
+
import { XMLParser } from 'fast-xml-parser';
|
|
39
39
|
import { NodeFactory } from './Devices/NodeFactory.js';
|
|
40
|
-
export { Category as Categories, ELKAlarmPanelDevice, ElkAlarmSensorDevice, Family, InsteonBaseDevice, InsteonDimmableDevice, InsteonDimmerOutletDevice, InsteonDimmerSwitchDevice, InsteonDoorWindowSensorDevice, InsteonFanDevice, InsteonFanMotorDevice, InsteonKeypadButtonDevice, InsteonKeypadDimmerDevice, InsteonKeypadRelayDevice, InsteonLeakSensorDevice, InsteonLockDevice, InsteonMotionSensorDevice, InsteonOnOffOutletDevice, InsteonOutletDevice, InsteonRelayDevice, InsteonSmokeSensorDevice, InsteonThermostatDevice, ISYDeviceNode as ISYDevice, ISYNode, ISYScene, ISYVariable, NodeType, Props, States, Utils, VariableType
|
|
40
|
+
export { Category as Categories, ELKAlarmPanelDevice, ElkAlarmSensorDevice, Family, InsteonBaseDevice, InsteonDimmableDevice, InsteonDimmerOutletDevice, InsteonDimmerSwitchDevice, InsteonDoorWindowSensorDevice, InsteonFanDevice, InsteonFanMotorDevice, InsteonKeypadButtonDevice, InsteonKeypadDimmerDevice, InsteonKeypadRelayDevice, InsteonLeakSensorDevice, InsteonLockDevice, InsteonMotionSensorDevice, InsteonOnOffOutletDevice, InsteonOutletDevice, InsteonRelayDevice, InsteonSmokeSensorDevice, InsteonThermostatDevice, ISYDeviceNode as ISYDevice, ISYNode, ISYScene, ISYVariable, NodeType, Props, States, Utils, VariableType };
|
|
41
41
|
const defaultParserOptions = {
|
|
42
42
|
explicitArray: false,
|
|
43
43
|
mergeAttrs: true,
|
|
44
44
|
attrValueProcessors: [parseNumbers, parseBooleans],
|
|
45
45
|
valueProcessors: [parseNumbers, parseBooleans],
|
|
46
|
-
tagNameProcessors: [(tagName) => (tagName ===
|
|
46
|
+
tagNameProcessors: [(tagName) => (tagName === 'st' || tagName === 'cmd' || tagName === 'nodeDef' ? '' : tagName)]
|
|
47
47
|
};
|
|
48
48
|
const defaultXMLParserOptions = {
|
|
49
49
|
parseAttributeValue: true,
|
|
50
50
|
allowBooleanAttributes: true,
|
|
51
|
-
attributeNamePrefix:
|
|
51
|
+
attributeNamePrefix: '',
|
|
52
52
|
attributesGroupName: false,
|
|
53
53
|
ignoreAttributes: false,
|
|
54
54
|
// updateTag(tagName, jPath, attrs) {
|
|
@@ -56,20 +56,20 @@ const defaultXMLParserOptions = {
|
|
|
56
56
|
// // return false;
|
|
57
57
|
// //return tagName;
|
|
58
58
|
// },
|
|
59
|
-
textNodeName:
|
|
60
|
-
commentPropName:
|
|
61
|
-
cdataPropName:
|
|
59
|
+
textNodeName: '_',
|
|
60
|
+
commentPropName: '$comment',
|
|
61
|
+
cdataPropName: '$cdata',
|
|
62
62
|
ignoreDeclaration: true,
|
|
63
63
|
tagValueProcessor: (tagName, tagValue, jPath, hasAttributes, isLeafNode) => {
|
|
64
|
-
if (tagValue ===
|
|
64
|
+
if (tagValue === '')
|
|
65
65
|
return null;
|
|
66
66
|
return tagValue;
|
|
67
67
|
},
|
|
68
68
|
isArray(tagName, jPath, isLeafNode, isAttribute) {
|
|
69
|
-
if (tagName ===
|
|
69
|
+
if (tagName === 'property')
|
|
70
70
|
return true;
|
|
71
71
|
return false;
|
|
72
|
-
}
|
|
72
|
+
}
|
|
73
73
|
};
|
|
74
74
|
axios.defaults.transitional.forcedJSONParsing = false;
|
|
75
75
|
const parser = new Parser(defaultParserOptions);
|
|
@@ -90,7 +90,7 @@ export class ISY extends EventEmitter {
|
|
|
90
90
|
sceneList = new Map();
|
|
91
91
|
storagePath;
|
|
92
92
|
variableList = new Map();
|
|
93
|
-
wsprotocol =
|
|
93
|
+
wsprotocol = 'ws';
|
|
94
94
|
zoneMap = new Map();
|
|
95
95
|
static instance;
|
|
96
96
|
configInfo;
|
|
@@ -102,35 +102,35 @@ export class ISY extends EventEmitter {
|
|
|
102
102
|
model;
|
|
103
103
|
nodesLoaded = false;
|
|
104
104
|
productId = 5226;
|
|
105
|
-
productName =
|
|
105
|
+
productName = 'eisy';
|
|
106
106
|
serverVersion;
|
|
107
|
-
vendorName =
|
|
107
|
+
vendorName = 'Universal Devices, Inc.';
|
|
108
108
|
webSocket;
|
|
109
109
|
// #endregion Properties (30)
|
|
110
110
|
// #region Constructors (1)
|
|
111
111
|
constructor(config, logger = new Logger(), storagePath) {
|
|
112
112
|
super();
|
|
113
113
|
this.enableWebSocket = config.enableWebSocket ?? true;
|
|
114
|
-
this.storagePath = storagePath ??
|
|
115
|
-
this.displayNameFormat = config.displayNameFormat ??
|
|
114
|
+
this.storagePath = storagePath ?? './';
|
|
115
|
+
this.displayNameFormat = config.displayNameFormat ?? '${location ?? folder} ${spokenName ?? name}';
|
|
116
116
|
this.host = config.host;
|
|
117
117
|
this.port = config.port;
|
|
118
118
|
this.credentials = {
|
|
119
119
|
username: config.username,
|
|
120
|
-
password: config.password
|
|
120
|
+
password: config.password
|
|
121
121
|
};
|
|
122
122
|
this.protocol = config.protocol;
|
|
123
|
-
this.wsprotocol = config.protocol ===
|
|
123
|
+
this.wsprotocol = config.protocol === 'https' ? 'wss' : 'ws';
|
|
124
124
|
this.elkEnabled = config.elkEnabled ?? false;
|
|
125
125
|
this.nodesLoaded = false;
|
|
126
126
|
var fopts = format((info) => {
|
|
127
127
|
info.message = JSON.stringify(info.message);
|
|
128
128
|
return info;
|
|
129
|
-
})({ label:
|
|
130
|
-
this.logger = loggers.add(
|
|
129
|
+
})({ label: 'ISY' });
|
|
130
|
+
this.logger = loggers.add('isy', {
|
|
131
131
|
transports: logger.transports,
|
|
132
132
|
levels: logger.levels,
|
|
133
|
-
format: format.label({ label:
|
|
133
|
+
format: format.label({ label: 'ISY' })
|
|
134
134
|
});
|
|
135
135
|
this.guardianTimer = null;
|
|
136
136
|
if (this.elkEnabled) {
|
|
@@ -216,7 +216,7 @@ export class ISY extends EventEmitter {
|
|
|
216
216
|
else if (evt.action instanceof Number || evt.action instanceof String) {
|
|
217
217
|
actionValue = Number(evt.action);
|
|
218
218
|
}
|
|
219
|
-
const stringControl = Number(evt.control?.replace(
|
|
219
|
+
const stringControl = Number(evt.control?.replace('_', ''));
|
|
220
220
|
switch (stringControl) {
|
|
221
221
|
case EventType.Elk:
|
|
222
222
|
if (actionValue === 2) {
|
|
@@ -245,9 +245,9 @@ export class ISY extends EventEmitter {
|
|
|
245
245
|
this.logger.debug(`Received ${EventType[Number(stringControl)]} Signal from ISY: ${JSON.stringify(evt)}`);
|
|
246
246
|
break;
|
|
247
247
|
default:
|
|
248
|
-
if (evt.node !==
|
|
248
|
+
if (evt.node !== '' && evt.node !== undefined && evt.node !== null) {
|
|
249
249
|
//
|
|
250
|
-
const impactedDevice = this.
|
|
250
|
+
const impactedDevice = this.getNode(evt.node);
|
|
251
251
|
if (impactedDevice !== undefined && impactedDevice !== null) {
|
|
252
252
|
impactedDevice.handleEvent(evt);
|
|
253
253
|
}
|
|
@@ -276,7 +276,7 @@ export class ISY extends EventEmitter {
|
|
|
276
276
|
await this.#finishInitialize(true);
|
|
277
277
|
}
|
|
278
278
|
catch (e) {
|
|
279
|
-
this.handleInitializeError(
|
|
279
|
+
this.handleInitializeError('initialize', e);
|
|
280
280
|
}
|
|
281
281
|
finally {
|
|
282
282
|
if (this.nodesLoaded !== true) {
|
|
@@ -287,7 +287,7 @@ export class ISY extends EventEmitter {
|
|
|
287
287
|
}
|
|
288
288
|
initializeWebSocket() {
|
|
289
289
|
const that = this;
|
|
290
|
-
const auth = `Basic ${Buffer.from(`${this.credentials.username}:${this.credentials.password}`).toString(
|
|
290
|
+
const auth = `Basic ${Buffer.from(`${this.credentials.username}:${this.credentials.password}`).toString('base64')}`;
|
|
291
291
|
this.logger.info(`Opening webSocket: ${this.wsprotocol}://${this.address}/rest/subscribe`);
|
|
292
292
|
if (this.webSocket) {
|
|
293
293
|
try {
|
|
@@ -297,42 +297,42 @@ export class ISY extends EventEmitter {
|
|
|
297
297
|
this.logger.warn(`Error closing existing websocket: ${e.message}`);
|
|
298
298
|
}
|
|
299
299
|
}
|
|
300
|
-
this.webSocket = new WebSocket.Client(`${this.wsprotocol}://${this.address}/rest/subscribe`, [
|
|
300
|
+
this.webSocket = new WebSocket.Client(`${this.wsprotocol}://${this.address}/rest/subscribe`, ['ISYSUB'], {
|
|
301
301
|
headers: {
|
|
302
|
-
Origin:
|
|
303
|
-
Authorization: auth
|
|
302
|
+
Origin: 'com.universal-devices.websockets.isy',
|
|
303
|
+
Authorization: auth
|
|
304
304
|
},
|
|
305
|
-
ping: 10
|
|
305
|
+
ping: 10
|
|
306
306
|
});
|
|
307
307
|
this.lastActivity = new Date();
|
|
308
308
|
this.webSocket
|
|
309
|
-
.on(
|
|
309
|
+
.on('message', (event) => {
|
|
310
310
|
that.logger.silly(`Received message: ${JSON.stringify(event.data, null, 2)}`);
|
|
311
311
|
that.handleWebSocketMessage(event);
|
|
312
312
|
})
|
|
313
|
-
.on(
|
|
313
|
+
.on('error', (err, response) => {
|
|
314
314
|
that.logger.warn(`Websocket subscription error: ${JSON.stringify(err.message)}`);
|
|
315
315
|
/// throw new Error('Error calling ISY' + err);
|
|
316
316
|
})
|
|
317
|
-
.on(
|
|
317
|
+
.on('fail', (data, response) => {
|
|
318
318
|
that.logger.warn(`Websocket subscription failure: ${data}`);
|
|
319
|
-
throw new Error(
|
|
319
|
+
throw new Error('Failed calling ISY');
|
|
320
320
|
})
|
|
321
|
-
.on(
|
|
322
|
-
that.logger.warn(
|
|
323
|
-
throw new Error(
|
|
321
|
+
.on('abort', () => {
|
|
322
|
+
that.logger.warn('Websocket subscription aborted.');
|
|
323
|
+
throw new Error('Call to ISY was aborted');
|
|
324
324
|
})
|
|
325
|
-
.on(
|
|
325
|
+
.on('timeout', (ms) => {
|
|
326
326
|
that.logger.warn(`Websocket subscription timed out after ${ms} milliseconds.`);
|
|
327
|
-
throw new Error(
|
|
327
|
+
throw new Error('Timeout contacting ISY');
|
|
328
328
|
});
|
|
329
329
|
}
|
|
330
330
|
async loadConfig() {
|
|
331
331
|
try {
|
|
332
|
-
this.logger.info(
|
|
333
|
-
const configuration = (await this.sendRequest(
|
|
332
|
+
this.logger.info('Loading ISY Config');
|
|
333
|
+
const configuration = (await this.sendRequest('config')).configuration;
|
|
334
334
|
if (this.isDebugEnabled) {
|
|
335
|
-
writeFile(this.storagePath +
|
|
335
|
+
writeFile(this.storagePath + '/ISYConfigDump.json', JSON.stringify(configuration), this.logger.error);
|
|
336
336
|
}
|
|
337
337
|
const controls = configuration.controls;
|
|
338
338
|
this.model = configuration.deviceSpecs.model;
|
|
@@ -354,18 +354,18 @@ export class ISY extends EventEmitter {
|
|
|
354
354
|
return configuration;
|
|
355
355
|
}
|
|
356
356
|
catch (e) {
|
|
357
|
-
this.handleInitializeError(
|
|
357
|
+
this.handleInitializeError('config', e);
|
|
358
358
|
throw Error(`Error Loading Config: ${e.message}`);
|
|
359
359
|
}
|
|
360
360
|
}
|
|
361
361
|
async loadNodes() {
|
|
362
362
|
try {
|
|
363
|
-
const result = await this.sendRequest(
|
|
363
|
+
const result = await this.sendRequest('nodes');
|
|
364
364
|
if (this.isDebugEnabled)
|
|
365
|
-
writeFile(this.storagePath +
|
|
366
|
-
await this.#readFolderNodes(result).catch((p) => this.logger.error(
|
|
367
|
-
await this.#readDeviceNodes(result).catch((p) => this.logger.error(
|
|
368
|
-
await this.#readSceneNodes(result).catch((p) => this.logger.error(
|
|
365
|
+
writeFile(this.storagePath + '/ISYNodesDump.json', JSON.stringify(result), this.logger.error);
|
|
366
|
+
await this.#readFolderNodes(result).catch((p) => this.logger.error('Error Loading Folders', p));
|
|
367
|
+
await this.#readDeviceNodes(result).catch((p) => this.logger.error('Error Loading Devices', p));
|
|
368
|
+
await this.#readSceneNodes(result).catch((p) => this.logger.error('Error Loading Scenes', p));
|
|
369
369
|
return result;
|
|
370
370
|
}
|
|
371
371
|
catch (e) {
|
|
@@ -394,9 +394,9 @@ export class ISY extends EventEmitter {
|
|
|
394
394
|
async refreshStatuses() {
|
|
395
395
|
try {
|
|
396
396
|
const that = this;
|
|
397
|
-
const result = await that.sendRequest(
|
|
397
|
+
const result = await that.sendRequest('status');
|
|
398
398
|
if (that.isDebugEnabled) {
|
|
399
|
-
writeFile(that.storagePath +
|
|
399
|
+
writeFile(that.storagePath + '/ISYStatusDump.json', JSON.stringify(result), this.logger.error);
|
|
400
400
|
}
|
|
401
401
|
this.logger.debug(result);
|
|
402
402
|
for (const node of result.nodes.node) {
|
|
@@ -451,14 +451,14 @@ export class ISY extends EventEmitter {
|
|
|
451
451
|
async sendNodeCommand(node, command, parameters) {
|
|
452
452
|
let uriToUse = `nodes/${node.address}/cmd/${command}`;
|
|
453
453
|
if (parameters !== null && parameters !== undefined) {
|
|
454
|
-
if (typeof parameters ==
|
|
454
|
+
if (typeof parameters == 'object') {
|
|
455
455
|
var q = parameters;
|
|
456
456
|
for (const paramName of Object.getOwnPropertyNames(q)) {
|
|
457
457
|
uriToUse += `/${paramName}/${q[paramName]}`;
|
|
458
458
|
}
|
|
459
459
|
//uriToUse += `/${q[((p : Record<string,number|number>) => `${p[]}/${p.paramValue}` ).join('/')}`;
|
|
460
460
|
}
|
|
461
|
-
else if (typeof parameters ==
|
|
461
|
+
else if (typeof parameters == 'number' || typeof parameters == 'string') {
|
|
462
462
|
uriToUse += `/${parameters}`;
|
|
463
463
|
}
|
|
464
464
|
}
|
|
@@ -468,28 +468,28 @@ export class ISY extends EventEmitter {
|
|
|
468
468
|
async sendRequest(url, options = { trailingSlash: true }) {
|
|
469
469
|
const requestLogLevel = options.requestLogLevel ?? winston.config.cli.levels.debug;
|
|
470
470
|
const responseLogLevel = options.responseLogLevel ?? winston.config.cli.levels.silly;
|
|
471
|
-
url = `${this.protocol}://${this.address}/rest/${url}${options.trailingSlash ?
|
|
471
|
+
url = `${this.protocol}://${this.address}/rest/${url}${options.trailingSlash ? '/' : ''}`;
|
|
472
472
|
this.logger.log(`Sending request: ${url}`, requestLogLevel);
|
|
473
473
|
try {
|
|
474
474
|
const response = await axios.get(url, {
|
|
475
|
-
auth: { username: this.credentials.username, password: this.credentials.password }
|
|
475
|
+
auth: { username: this.credentials.username, password: this.credentials.password }
|
|
476
476
|
});
|
|
477
477
|
if (response.data) {
|
|
478
|
-
if (response.headers[
|
|
478
|
+
if (response.headers['content-type'].toString().includes('xml')) {
|
|
479
479
|
let curParser = parser;
|
|
480
480
|
if (options.parserOptions)
|
|
481
481
|
curParser = new Parser({ ...defaultParserOptions, ...options.parserOptions });
|
|
482
482
|
var altParser = new XMLParser(defaultXMLParserOptions);
|
|
483
483
|
var s = altParser.parse(response.data);
|
|
484
|
-
this.logger.log(`Response: ${JSON.stringify(s)}`, requestLogLevel ??
|
|
484
|
+
this.logger.log(`Response: ${JSON.stringify(s)}`, requestLogLevel ?? 'debug');
|
|
485
485
|
return s;
|
|
486
486
|
}
|
|
487
|
-
else if (response.headers[
|
|
488
|
-
this.logger.log(`Response: ${JSON.stringify(response.data)}`, requestLogLevel ??
|
|
487
|
+
else if (response.headers['content-type'].toString().includes('json')) {
|
|
488
|
+
this.logger.log(`Response: ${JSON.stringify(response.data)}`, requestLogLevel ?? 'debug');
|
|
489
489
|
return JSON.parse(response.data);
|
|
490
490
|
}
|
|
491
491
|
else {
|
|
492
|
-
this.logger.log(`Response Header: ${JSON.stringify(response.headers)} Response: ${JSON.stringify(response.data)}`, responseLogLevel ??
|
|
492
|
+
this.logger.log(`Response Header: ${JSON.stringify(response.headers)} Response: ${JSON.stringify(response.data)}`, responseLogLevel ?? 'debug');
|
|
493
493
|
return response.data;
|
|
494
494
|
}
|
|
495
495
|
}
|
|
@@ -510,9 +510,7 @@ export class ISY extends EventEmitter {
|
|
|
510
510
|
// #endregion Public Methods (22)
|
|
511
511
|
// #region Private Methods (11)
|
|
512
512
|
#checkForFailure(response) {
|
|
513
|
-
return
|
|
514
|
-
response instanceof Error ||
|
|
515
|
-
(response.RestResponse !== undefined && response.RestResponse.status !== 200));
|
|
513
|
+
return response === null || response instanceof Error || (response.RestResponse !== undefined && response.RestResponse.status !== 200);
|
|
516
514
|
}
|
|
517
515
|
#createVariableKey(type, id) {
|
|
518
516
|
return `${type}:${id}`;
|
|
@@ -543,14 +541,14 @@ export class ISY extends EventEmitter {
|
|
|
543
541
|
#guardian() {
|
|
544
542
|
const timeNow = new Date();
|
|
545
543
|
if (Number(timeNow) - Number(this.lastActivity) > 60000) {
|
|
546
|
-
this.logger.info(
|
|
544
|
+
this.logger.info('Guardian: Detected no activity in more then 60 seconds. Reinitializing web sockets');
|
|
547
545
|
this.initializeWebSocket();
|
|
548
546
|
}
|
|
549
547
|
}
|
|
550
548
|
#loadElkInitialStatus(result) {
|
|
551
549
|
const p = new Parser({
|
|
552
550
|
explicitArray: false,
|
|
553
|
-
mergeAttrs: true
|
|
551
|
+
mergeAttrs: true
|
|
554
552
|
});
|
|
555
553
|
p.parseString(result, (err, res) => {
|
|
556
554
|
if (err) {
|
|
@@ -574,7 +572,7 @@ export class ISY extends EventEmitter {
|
|
|
574
572
|
}
|
|
575
573
|
#loadElkNodes(result) {
|
|
576
574
|
const document = new XmlDocument(result);
|
|
577
|
-
const nodes = document.childNamed(
|
|
575
|
+
const nodes = document.childNamed('areas').childNamed('area').childrenNamed('zone');
|
|
578
576
|
for (let index = 0; index < nodes.length; index++) {
|
|
579
577
|
const id = nodes[index].attr.id;
|
|
580
578
|
const name = nodes[index].attr.name;
|
|
@@ -584,65 +582,70 @@ export class ISY extends EventEmitter {
|
|
|
584
582
|
}
|
|
585
583
|
}
|
|
586
584
|
async #readDeviceNodes(obj) {
|
|
587
|
-
this.logger.info(
|
|
585
|
+
this.logger.info('Loading Device Nodes');
|
|
588
586
|
for (const nodeInfo of obj.nodes.node) {
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
if (m) {
|
|
609
|
-
newDevice = newDevice ?? new m.class(this, nodeInfo);
|
|
610
|
-
newDevice.productName = m.name;
|
|
611
|
-
newDevice.model = `(${m.modelNumber}) ${m.name} v.${m.version}`;
|
|
612
|
-
newDevice.modelNumber = m.modelNumber;
|
|
613
|
-
newDevice.version = m.version;
|
|
614
|
-
}
|
|
615
|
-
if (enabled) {
|
|
616
|
-
if (newDevice === null) {
|
|
617
|
-
this.logger.warn(`Device type resolution failed for ${nodeInfo.name} with type: ${nodeInfo.type} and nodedef: ${nodeInfo.nodeDefId}`);
|
|
618
|
-
newDevice = new ISYDeviceNode(this, nodeInfo);
|
|
587
|
+
try {
|
|
588
|
+
this.logger.debug(`Loading Device Node: ${JSON.stringify(nodeInfo)}`);
|
|
589
|
+
if (!this.deviceMap.has(nodeInfo.pnode)) {
|
|
590
|
+
const address = nodeInfo.address;
|
|
591
|
+
this.deviceMap[nodeInfo.pnode] = {
|
|
592
|
+
address
|
|
593
|
+
};
|
|
594
|
+
}
|
|
595
|
+
else {
|
|
596
|
+
this.deviceMap[nodeInfo.pnode].push(nodeInfo.address);
|
|
597
|
+
}
|
|
598
|
+
let newDevice = null;
|
|
599
|
+
// let deviceTypeInfo = this.isyTypeToTypeName(device.type, device.address);
|
|
600
|
+
// this.logger.info(JSON.stringify(deviceTypeInfo));
|
|
601
|
+
const enabled = nodeInfo.enabled ?? true;
|
|
602
|
+
const d = await NodeFactory.get(nodeInfo);
|
|
603
|
+
const m = DeviceFactory.getDeviceDetails(nodeInfo);
|
|
604
|
+
if (d) {
|
|
605
|
+
newDevice = new d(this, nodeInfo);
|
|
619
606
|
}
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
607
|
+
if (m) {
|
|
608
|
+
newDevice = newDevice ?? new m.class(this, nodeInfo);
|
|
609
|
+
newDevice.productName = m.name;
|
|
610
|
+
newDevice.model = `(${m.modelNumber}) ${m.name} v.${m.version}`;
|
|
611
|
+
newDevice.modelNumber = m.modelNumber;
|
|
612
|
+
newDevice.version = m.version;
|
|
613
|
+
}
|
|
614
|
+
if (enabled) {
|
|
615
|
+
if (newDevice === null) {
|
|
616
|
+
this.logger.warn(`Device type resolution failed for ${nodeInfo.name} with type: ${nodeInfo.type} and nodedef: ${nodeInfo.nodeDefId}`);
|
|
617
|
+
newDevice = new ISYDeviceNode(this, nodeInfo);
|
|
623
618
|
}
|
|
624
|
-
|
|
625
|
-
|
|
619
|
+
else if (newDevice !== null) {
|
|
620
|
+
if (m.unsupported) {
|
|
621
|
+
this.logger.warn('Device not currently supported: ' + JSON.stringify(nodeInfo) + ' /n It has been mapped to: ' + d.name);
|
|
622
|
+
}
|
|
623
|
+
try {
|
|
624
|
+
await newDevice.refreshNotes();
|
|
625
|
+
}
|
|
626
|
+
catch (e) {
|
|
627
|
+
this.logger.debug('No notes found.');
|
|
628
|
+
}
|
|
629
|
+
// if (!newDevice.hidden) {
|
|
630
|
+
// }
|
|
631
|
+
// this.deviceList.push(newDevice);
|
|
626
632
|
}
|
|
627
|
-
|
|
628
|
-
this.logger.debug("No notes found.");
|
|
633
|
+
else {
|
|
629
634
|
}
|
|
630
|
-
|
|
631
|
-
// }
|
|
632
|
-
// this.deviceList.push(newDevice);
|
|
635
|
+
this.nodeMap.set(newDevice.address, newDevice);
|
|
633
636
|
}
|
|
634
637
|
else {
|
|
638
|
+
this.logger.info(`Ignoring disabled device: ${nodeInfo.name}`);
|
|
635
639
|
}
|
|
636
|
-
this.nodeMap.set(newDevice.address, newDevice);
|
|
637
640
|
}
|
|
638
|
-
|
|
639
|
-
this.logger.
|
|
641
|
+
catch (e) {
|
|
642
|
+
this.logger.error(`Error loading device node: ${e.message}`);
|
|
640
643
|
}
|
|
641
644
|
}
|
|
642
645
|
this.logger.info(`${this.nodeMap.size} devices added.`);
|
|
643
646
|
}
|
|
644
647
|
async #readFolderNodes(result) {
|
|
645
|
-
this.logger.info(
|
|
648
|
+
this.logger.info('Loading Folder Nodes');
|
|
646
649
|
if (result?.nodes?.folder) {
|
|
647
650
|
for (const folder of result.nodes.folder) {
|
|
648
651
|
this.logger.info(`Loading Folder Node: ${JSON.stringify(folder)}`);
|
|
@@ -651,9 +654,9 @@ export class ISY extends EventEmitter {
|
|
|
651
654
|
}
|
|
652
655
|
}
|
|
653
656
|
async #readSceneNodes(result) {
|
|
654
|
-
this.logger.info(
|
|
657
|
+
this.logger.info('Loading Scene Nodes');
|
|
655
658
|
for (const scene of result.nodes?.group) {
|
|
656
|
-
if (scene.name ===
|
|
659
|
+
if (scene.name === 'ISY' || scene.name === 'IoX' || scene.name === 'Auto DR') {
|
|
657
660
|
continue;
|
|
658
661
|
} // Skip ISY & Auto DR Scenes
|
|
659
662
|
const newScene = new ISYScene(this, scene);
|
|
@@ -661,7 +664,7 @@ export class ISY extends EventEmitter {
|
|
|
661
664
|
await newScene.refreshNotes();
|
|
662
665
|
}
|
|
663
666
|
catch (e) {
|
|
664
|
-
this.logger.debug(
|
|
667
|
+
this.logger.debug('No notes found.');
|
|
665
668
|
}
|
|
666
669
|
this.sceneList.set(newScene.address, newScene);
|
|
667
670
|
}
|