node-red-contrib-alice 2.2.4 → 2.3.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.
Files changed (43) hide show
  1. package/.claude/settings.local.json +11 -0
  2. package/CLAUDE.md +54 -0
  3. package/nodes/alice-color.js +208 -231
  4. package/nodes/alice-device.html +6 -1
  5. package/nodes/alice-device.js +252 -286
  6. package/nodes/alice-event.js +110 -114
  7. package/nodes/alice-get.html +91 -0
  8. package/nodes/alice-get.js +9 -0
  9. package/nodes/alice-mode.js +136 -145
  10. package/nodes/alice-onoff.js +126 -130
  11. package/nodes/alice-range.js +144 -150
  12. package/nodes/alice-sensor.html +0 -2
  13. package/nodes/alice-sensor.js +101 -106
  14. package/nodes/alice-togle.js +118 -125
  15. package/nodes/alice-video.js +88 -132
  16. package/nodes/alice.js +127 -122
  17. package/nodes/types.js +3 -0
  18. package/package.json +22 -8
  19. package/src/alice-color.html +255 -0
  20. package/src/alice-color.ts +227 -0
  21. package/src/alice-device.html +94 -0
  22. package/src/alice-device.ts +301 -0
  23. package/src/alice-event.html +148 -0
  24. package/src/alice-event.ts +112 -0
  25. package/src/alice-get.html +67 -6
  26. package/src/alice-get.ts +12 -15
  27. package/src/alice-mode.html +296 -0
  28. package/src/alice-mode.ts +139 -0
  29. package/src/alice-onoff.html +93 -0
  30. package/src/alice-onoff.ts +132 -0
  31. package/src/alice-range.html +293 -0
  32. package/src/alice-range.ts +144 -0
  33. package/src/alice-sensor.html +307 -0
  34. package/src/alice-sensor.ts +103 -0
  35. package/src/alice-togle.html +96 -0
  36. package/src/alice-togle.ts +122 -0
  37. package/src/alice-video.html +90 -0
  38. package/src/alice-video.ts +99 -0
  39. package/src/alice.html +242 -0
  40. package/src/alice.ts +146 -0
  41. package/src/types.ts +157 -0
  42. package/tsconfig.json +13 -106
  43. package/.eslintrc.json +0 -20
@@ -1,299 +1,265 @@
1
- const axios = require('axios');
2
-
3
- module.exports = function(RED) {
4
- // ***************************** Alice DEVICE ****************************
5
- function AliceDevice(config){
6
- const pjson = require('../package.json');
7
- RED.nodes.createNode(this,config);
8
- const service = RED.nodes.getNode(config.service);
9
- service.setMaxListeners(service.getMaxListeners() + 1); // увеличиваем лимит для event
10
- const name = config.name;
11
- const description = config.description;
12
- const room = config.room;
13
- const dtype = config.dtype;
14
- this.initState = false;
15
- let updating = false;
16
- let needSendEvent = false;
17
- let capabilites = {};
18
- let sensors = {};
19
- let deviceconfig = {
20
- id: this.id,
21
- name: config.name,
22
- description: config.description,
23
- room: config.room,
24
- type: config.dtype,
25
- device_info:{
26
- manufacturer: "NodeRed Home",
27
- model: "virtual device",
28
- sw_version: pjson.version
29
- },
30
- capabilities:[],
31
- properties:[]
32
- };
33
- let states = {
34
- id: this.id,
35
- capabilities: [],
36
- properties: []
37
- };
38
-
39
- if (service.isOnline){
40
- this.emit("online");
41
- this.initState = true;
42
- };
43
- // функция обновления информации об устройстве
44
- this._updateDeviceInfo= _=>{
45
- let now = false;
46
-
47
- if (deviceconfig.capabilities.length==0 && deviceconfig.properties.length==0){
48
- this.debug("DELETE Device config from gateway ...");
49
- /// отправка по http
50
- const option = {
51
- timeout: 5000,
52
- method: 'POST',
53
- url: 'https://api.nodered-home.ru/gtw/device/config',
54
- headers: {
55
- 'content-type': 'application/json',
56
- 'Authorization': "Bearer "+service.getToken()
57
- },
58
- data: {
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ const axios_1 = __importDefault(require("axios"));
6
+ const package_json_1 = __importDefault(require("../package.json"));
7
+ module.exports = (RED) => {
8
+ function AliceDevice(config) {
9
+ RED.nodes.createNode(this, config);
10
+ const service = RED.nodes.getNode(config.service);
11
+ service.setMaxListeners(service.getMaxListeners() + 1);
12
+ this.initState = false;
13
+ let updating = false;
14
+ let needSendEvent = false;
15
+ const capabilites = {};
16
+ const sensors = {};
17
+ const deviceconfig = {
59
18
  id: this.id,
60
- config: deviceconfig
61
- }
62
- };
63
- axios.request(option)
64
- .then(res=>{
65
- this.trace("Device config deleted on gateway successfully");
66
- })
67
- .catch(error=>{
68
- this.debug("Error when delete device config on gateway: "+error.message);
69
- });
70
- return;
71
- };
72
-
73
- if (!updating){
74
- updating = true;
75
- setTimeout(() => {
76
- this.debug("Updating Device config ...");
77
- updating = false;
78
- const option = {
79
- timeout: 5000,
80
- method: 'POST',
81
- url: 'https://api.nodered-home.ru/gtw/device/config',
82
- headers: {
83
- 'content-type': 'application/json',
84
- 'Authorization': "Bearer "+service.getToken()
19
+ name: config.name,
20
+ description: config.description,
21
+ room: config.room,
22
+ type: config.dtype,
23
+ device_info: {
24
+ manufacturer: "NodeRed Home",
25
+ model: "virtual device",
26
+ sw_version: package_json_1.default.version
85
27
  },
86
- data: {
87
- id: this.id,
88
- config: deviceconfig
89
- }
90
- };
91
- axios.request(option)
92
- .then(res=>{
93
- this.trace("Device config updated successfully");
94
- })
95
- .catch(error=>{
96
- this.debug("Error when update device config: "+error.message);
97
- });
98
- }, 1000);
99
- }
100
- };
101
- // функция обновления состояния устройства (умений и сенсоров)
102
- this._updateDeviceState= (event=null)=>{
103
- const option = {
104
- timeout: 5000,
105
- method: 'POST',
106
- url: 'https://api.nodered-home.ru/gtw/device/state',
107
- headers: {
108
- 'content-type': 'application/json',
109
- 'Authorization': "Bearer "+service.getToken()
110
- },
111
- data: {
112
- id: this.id,
113
- event: event,
114
- state: states
115
- }
116
- };
117
- axios.request(option)
118
- .then(res=>{
119
- this.trace("Device state updated successfully");
120
- })
121
- .catch(error=>{
122
- this.debug("Error when update device state: "+error.message);
123
- })
124
- };
125
- // отправка эвентов
126
- this._sendEvent = (event)=>{
127
- let data = JSON.stringify(event);
128
- service.send2gate('$me/device/events/'+this.id, data ,false);
129
- };
130
- // Установка параметров умения
131
- this.setCapability = (capId, capab)=>{
132
- return new Promise((resolve,reject)=>{
133
- let intsance = capab.parameters.instance || '';
134
- let capabIndex = capab.type+"."+intsance;
135
- if (capabilites[capabIndex] && capabilites[capabIndex]!=capId){
136
- reject(new Error("Dublicated capability on same device!"));
137
- return;
28
+ capabilities: [],
29
+ properties: []
138
30
  };
139
- // проверям было ли такое умение раньше и удалем перед обновлением
140
- if (deviceconfig.capabilities.findIndex(a => a.id === capId)>-1){
141
- this.delCapability(capId);
142
- };
143
- capabilites[capabIndex] = capId; // добавляем новое уменя в локальный список
144
- capab.id = capId;
145
- deviceconfig.capabilities.push(capab);
146
- this._updateDeviceInfo();
147
- resolve(true);
148
- })
149
- };
150
- // Установка параметров сенсора
151
- this.setSensor = (sensId, sensor)=>{
152
- return new Promise((resolve,reject)=>{
153
- let sensorIndex = sensor.type+"."+sensor.parameters.instance;
154
- if (sensors[sensorIndex] && sensors[sensorIndex]!=sensId){
155
- reject(new Error("Dublicated sensor on same device!"));
156
- return;
157
- };
158
- // проверям было ли такое сенсор раньше и удалем перед обновлением
159
- if (deviceconfig.properties.findIndex(a => a.id === sensId)>-1){
160
- this.delSensor(sensId);
31
+ const states = {
32
+ id: this.id,
33
+ capabilities: [],
34
+ properties: []
161
35
  };
162
- sensors[sensorIndex] = sensId; // добавляем новый сенсор в локальный список
163
- sensor.id = sensId;
164
- deviceconfig.properties.push(sensor);
165
- this._updateDeviceInfo();
166
- resolve(true);
167
- })
168
- };
169
-
170
- // обновление текущего state умения
171
- this.updateCapabState = (capId,state)=>{
172
- return new Promise((resolve,reject)=>{
173
- state.id = capId;
174
- if (needSendEvent){
175
- this._sendEvent(state);
36
+ if (service.isOnline) {
37
+ this.emit("online");
38
+ this.initState = true;
39
+ }
40
+ const _updateDeviceInfo = () => {
41
+ if (deviceconfig.capabilities.length == 0 && deviceconfig.properties.length == 0) {
42
+ this.debug("DELETE Device config from gateway ...");
43
+ axios_1.default.request({
44
+ timeout: 5000,
45
+ method: 'POST',
46
+ url: 'https://api.nodered-home.ru/gtw/device/config',
47
+ headers: {
48
+ 'content-type': 'application/json',
49
+ 'Authorization': "Bearer " + service.getToken()
50
+ },
51
+ data: {
52
+ id: this.id,
53
+ config: deviceconfig
54
+ }
55
+ })
56
+ .then(() => {
57
+ this.trace("Device config deleted on gateway successfully");
58
+ })
59
+ .catch(error => {
60
+ this.debug("Error when delete device config on gateway: " + error.message);
61
+ });
62
+ return;
63
+ }
64
+ if (!updating) {
65
+ updating = true;
66
+ setTimeout(() => {
67
+ this.debug("Updating Device config ...");
68
+ updating = false;
69
+ axios_1.default.request({
70
+ timeout: 5000,
71
+ method: 'POST',
72
+ url: 'https://api.nodered-home.ru/gtw/device/config',
73
+ headers: {
74
+ 'content-type': 'application/json',
75
+ 'Authorization': "Bearer " + service.getToken()
76
+ },
77
+ data: {
78
+ id: this.id,
79
+ config: deviceconfig
80
+ }
81
+ })
82
+ .then(() => {
83
+ this.trace("Device config updated successfully");
84
+ })
85
+ .catch(error => {
86
+ this.debug("Error when update device config: " + error.message);
87
+ });
88
+ }, 1000);
89
+ }
176
90
  };
177
- const index = states.capabilities.findIndex(a => a.id === capId);
178
- if (index>-1){
179
- states.capabilities.splice(index, 1);
91
+ const _updateDeviceState = (event = null) => {
92
+ axios_1.default.request({
93
+ timeout: 5000,
94
+ method: 'POST',
95
+ url: 'https://api.nodered-home.ru/gtw/device/state',
96
+ headers: {
97
+ 'content-type': 'application/json',
98
+ 'Authorization': "Bearer " + service.getToken()
99
+ },
100
+ data: {
101
+ id: this.id,
102
+ event: event,
103
+ state: states
104
+ }
105
+ })
106
+ .then(() => {
107
+ this.trace("Device state updated successfully");
108
+ })
109
+ .catch(error => {
110
+ this.debug("Error when update device state: " + error.message);
111
+ });
180
112
  };
181
- states.capabilities.push(state);
182
- const currentevent = {
183
- id: this.id,
184
- capabilities:[state]
113
+ const _sendEvent = (event) => {
114
+ const data = JSON.stringify(event);
115
+ service.send2gate('$me/device/events/' + this.id, data, false);
185
116
  };
186
- this._updateDeviceState(currentevent);
187
- resolve(true);
188
- // reject(new Error("Device not ready"));
189
- })
190
- };
191
- // обновление текущего state сенсора
192
- this.updateSensorState = (sensID,state)=>{
193
- return new Promise((resolve,reject)=>{
194
- state.id = sensID;
195
- const index = states.properties.findIndex(a => a.id === sensID);
196
- if (index>-1){
197
- states.properties.splice(index, 1);
117
+ this.setCapability = (capId, capab) => {
118
+ return new Promise((resolve, reject) => {
119
+ const instance = capab.parameters.instance || '';
120
+ const capabIndex = capab.type + "." + instance;
121
+ if (capabilites[capabIndex] && capabilites[capabIndex] != capId) {
122
+ reject(new Error("Dublicated capability on same device!"));
123
+ return;
124
+ }
125
+ if (deviceconfig.capabilities.findIndex(a => a.id === capId) > -1) {
126
+ this.delCapability(capId);
127
+ }
128
+ capabilites[capabIndex] = capId;
129
+ capab.id = capId;
130
+ deviceconfig.capabilities.push(capab);
131
+ _updateDeviceInfo();
132
+ resolve(true);
133
+ });
198
134
  };
199
- states.properties.push(state);
200
- const currentevent = {
201
- id: this.id,
202
- properties:[state]
135
+ this.setSensor = (sensId, sensor) => {
136
+ return new Promise((resolve, reject) => {
137
+ const sensorIndex = sensor.type + "." + sensor.parameters.instance;
138
+ if (sensors[sensorIndex] && sensors[sensorIndex] != sensId) {
139
+ reject(new Error("Dublicated sensor on same device!"));
140
+ return;
141
+ }
142
+ if (deviceconfig.properties.findIndex(a => a.id === sensId) > -1) {
143
+ this.delSensor(sensId);
144
+ }
145
+ sensors[sensorIndex] = sensId;
146
+ sensor.id = sensId;
147
+ deviceconfig.properties.push(sensor);
148
+ _updateDeviceInfo();
149
+ resolve(true);
150
+ });
203
151
  };
204
- this._updateDeviceState(currentevent);
205
- resolve(true);
206
- // reject(new Error("Device not ready"));
207
- })
208
- };
209
-
210
- // удаление умения
211
- this.delCapability= (capId)=>{
212
- return new Promise((resolve,reject)=>{
213
- // удаляем из конфига
214
- const index = deviceconfig.capabilities.findIndex(a => a.id === capId);
215
- if (index>-1){
216
- deviceconfig.capabilities.splice(index, 1);
152
+ this.updateCapabState = (capId, state) => {
153
+ return new Promise((resolve) => {
154
+ state.id = capId;
155
+ if (needSendEvent) {
156
+ _sendEvent(state);
157
+ }
158
+ const index = states.capabilities.findIndex(a => a.id === capId);
159
+ if (index > -1) {
160
+ states.capabilities.splice(index, 1);
161
+ }
162
+ states.capabilities.push(state);
163
+ const currentevent = {
164
+ id: this.id,
165
+ capabilities: [state]
166
+ };
167
+ _updateDeviceState(currentevent);
168
+ resolve(true);
169
+ });
217
170
  };
218
- // удаляем из карты
219
- let capabIndex = Object.keys(capabilites).find(key => capabilites[key] === capId);
220
- delete capabilites[capabIndex];
221
- this._updateDeviceInfo();
222
- // удаляем его текущее состояние
223
- const stateindex = states.capabilities.findIndex(a => a.id === capId);
224
- if (stateindex>-1){
225
- states.capabilities.splice(stateindex, 1);
171
+ this.updateSensorState = (sensID, state) => {
172
+ return new Promise((resolve) => {
173
+ state.id = sensID;
174
+ const index = states.properties.findIndex(a => a.id === sensID);
175
+ if (index > -1) {
176
+ states.properties.splice(index, 1);
177
+ }
178
+ states.properties.push(state);
179
+ const currentevent = {
180
+ id: this.id,
181
+ properties: [state]
182
+ };
183
+ _updateDeviceState(currentevent);
184
+ resolve(true);
185
+ });
226
186
  };
227
- this._updateDeviceState();
228
- resolve(true);
229
- })
230
- };
231
-
232
- // удаление сенсора
233
- this.delSensor= (sensID)=>{
234
- return new Promise((resolve,reject)=>{
235
- // удаляем из конфига
236
- const index = deviceconfig.properties.findIndex(a => a.id === sensID);
237
- if (index>-1){
238
- deviceconfig.properties.splice(index, 1);
239
- }
240
- // удаляем из карты
241
- let sensorIndex = Object.keys(sensors).find(key => sensors[key] === sensID);
242
- delete sensors[sensorIndex];
243
- this._updateDeviceInfo();
244
- // удаляем текущее состояние
245
- const stateindex = states.properties.findIndex(a => a.id === sensID);
246
- if (stateindex>-1){
247
- states.properties.splice(stateindex, 1);
187
+ this.delCapability = (capId) => {
188
+ return new Promise((resolve) => {
189
+ const index = deviceconfig.capabilities.findIndex(a => a.id === capId);
190
+ if (index > -1) {
191
+ deviceconfig.capabilities.splice(index, 1);
192
+ }
193
+ const capabIndex = Object.keys(capabilites).find(key => capabilites[key] === capId);
194
+ if (capabIndex)
195
+ delete capabilites[capabIndex];
196
+ _updateDeviceInfo();
197
+ const stateindex = states.capabilities.findIndex(a => a.id === capId);
198
+ if (stateindex > -1) {
199
+ states.capabilities.splice(stateindex, 1);
200
+ }
201
+ _updateDeviceState();
202
+ resolve(true);
203
+ });
248
204
  };
249
- this._updateDeviceState();
250
- resolve(true);
251
- })
252
- };
253
-
254
- service.on("online",()=>{
255
- this.debug("Received a signal online from the service");
256
- this.emit("online");
257
- this.initState = true;
258
- });
259
-
260
- service.on("offline",()=>{
261
- this.debug("Received a signal offline from the service");
262
- this.emit("offline");
263
- this.initState = false;
264
- this.status({fill:"red",shape:"dot",text:"offline"});
265
- });
266
-
267
- service.on(this.id,(states)=>{
268
- setTimeout(() => {
269
- needSendEvent = false;
270
- }, 2000);
271
- needSendEvent = true;
272
- states.forEach(cap => {
273
- let capabIndex = cap.type+"."+cap.state.instance;
274
- if (cap.type==="devices.capabilities.color_setting"){
275
- capabIndex = cap.type+".";
205
+ this.delSensor = (sensID) => {
206
+ return new Promise((resolve) => {
207
+ const index = deviceconfig.properties.findIndex(a => a.id === sensID);
208
+ if (index > -1) {
209
+ deviceconfig.properties.splice(index, 1);
210
+ }
211
+ const sensorIndex = Object.keys(sensors).find(key => sensors[key] === sensID);
212
+ if (sensorIndex)
213
+ delete sensors[sensorIndex];
214
+ _updateDeviceInfo();
215
+ const stateindex = states.properties.findIndex(a => a.id === sensID);
216
+ if (stateindex > -1) {
217
+ states.properties.splice(stateindex, 1);
218
+ }
219
+ _updateDeviceState();
220
+ resolve(true);
221
+ });
276
222
  };
277
- const capId = capabilites[capabIndex];
278
- this.emit(capId,cap.state.value, cap.state);
279
- });
280
- })
281
-
282
- this.on('close', (removed, done)=>{
283
- this.emit('offline');
284
- if (removed){
285
- deviceconfig.capabilities = [];
286
- deviceconfig.properties = [];
287
- states.capabilities = [];
288
- states.properties = [];
289
- this._updateDeviceState();
290
- this._updateDeviceInfo();
291
- };
292
- setTimeout(()=>{
293
- // this.emit('offline');
294
- done();
295
- },500)
296
- });
297
- };
298
- RED.nodes.registerType("alice-device",AliceDevice);
299
- };
223
+ service.on("online", () => {
224
+ this.debug("Received a signal online from the service");
225
+ this.emit("online");
226
+ this.initState = true;
227
+ });
228
+ service.on("offline", () => {
229
+ this.debug("Received a signal offline from the service");
230
+ this.emit("offline");
231
+ this.initState = false;
232
+ this.status({ fill: "red", shape: "dot", text: "offline" });
233
+ });
234
+ service.on(this.id, (incomingStates) => {
235
+ setTimeout(() => {
236
+ needSendEvent = false;
237
+ }, 2000);
238
+ needSendEvent = true;
239
+ incomingStates.forEach(cap => {
240
+ let capabIndex = cap.type + "." + cap.state.instance;
241
+ if (cap.type === "devices.capabilities.color_setting") {
242
+ capabIndex = cap.type + ".";
243
+ }
244
+ const capId = capabilites[capabIndex];
245
+ this.emit(capId, cap.state.value, cap.state);
246
+ });
247
+ });
248
+ this.on('close', (removed, done) => {
249
+ this.emit('offline');
250
+ if (removed) {
251
+ deviceconfig.capabilities = [];
252
+ deviceconfig.properties = [];
253
+ states.capabilities = [];
254
+ states.properties = [];
255
+ _updateDeviceState();
256
+ _updateDeviceInfo();
257
+ }
258
+ setTimeout(() => {
259
+ done();
260
+ }, 500);
261
+ });
262
+ }
263
+ RED.nodes.registerType("alice-device", AliceDevice);
264
+ };
265
+ //# sourceMappingURL=alice-device.js.map