node-red-contrib-alice 2.2.5 → 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.
package/src/alice.ts CHANGED
@@ -1,92 +1,67 @@
1
- import {NodeAPI, Node, NodeDef, NodeCredentials, NodeCredential } from "node-red";
1
+ import { NodeAPI } from "node-red";
2
2
  import axios from "axios";
3
3
  import mqtt from "mqtt";
4
-
5
- interface NodeAliceConfig
6
- extends NodeDef {
7
- name:string;
8
- };
9
-
10
- interface NodeAliceCredentials
11
- extends NodeCredential {
12
- email:string;
13
- id:string;
14
- password:string;
15
- token:string;
16
- };
17
-
18
- interface AliceNode
19
- extends Node {
20
- credentials: NodeAliceCredentials;
21
- isOnline:boolean;
22
- getToken():string;
23
- send2gate(topic:string,data:any,retain:boolean):void;
24
- // on(event: 'hello', listener: (name: string) => void): this;
25
- on(event: string, listener: Function): this;
26
- };
27
-
28
- export = (RED: NodeAPI):void =>{
29
- function AliceService(this:AliceNode, config:NodeAliceConfig):void {
30
- RED.nodes.createNode(this,config);
31
- this.debug("Starting Alice service... ID: "+this.id);
32
-
33
- const email = this.credentials.email;
34
- const login = this.credentials.id;
35
- const password = this.credentials.password;
36
- const token = this.credentials.token;
37
-
38
- //вызов для удаления всех устройств
39
- const suburl = Buffer.from(email).toString('base64');
40
- RED.httpAdmin.get("/noderedhome/"+suburl+"/clearalldevice",(req,res)=>{
41
- const option = {
42
- method: 'POST',
43
- url: 'https://api.nodered-home.ru/gtw/device/clearallconfigs',
44
- headers: {
45
- 'content-type': 'application/json',
46
- 'Authorization': "Bearer "+this.getToken()
47
- },
48
- data: {}
49
- };
50
- axios.request(option)
51
- .then(result=>{
52
- this.trace("All devices configs deleted on gateway successfully");
53
- // console.log(result)
54
- res.sendStatus(200);
55
- })
56
- .catch(error=>{
57
- this.debug("Error when delete All devices configs deleted on gateway: "+error.message);
58
- res.sendStatus(500);
59
- });
4
+ import { AliceServiceConfig, AliceServiceNode } from "./types.js";
5
+
6
+ export = (RED: NodeAPI): void => {
7
+ function AliceService(this: AliceServiceNode, config: AliceServiceConfig): void {
8
+ RED.nodes.createNode(this, config);
9
+ this.debug("Starting Alice service... ID: " + this.id);
10
+
11
+ const email = this.credentials.email;
12
+ const login = this.credentials.id;
13
+ const password = this.credentials.password;
14
+ const token = this.credentials.token;
15
+
16
+ //вызов для удаления всех устройств
17
+ const suburl = Buffer.from(email).toString('base64');
18
+ RED.httpAdmin.get("/noderedhome/" + suburl + "/clearalldevice", (_req, res) => {
19
+ axios.request({
20
+ method: 'POST',
21
+ url: 'https://api.nodered-home.ru/gtw/device/clearallconfigs',
22
+ headers: {
23
+ 'content-type': 'application/json',
24
+ 'Authorization': "Bearer " + this.getToken()
25
+ },
26
+ data: {}
27
+ })
28
+ .then(() => {
29
+ this.trace("All devices configs deleted on gateway successfully");
30
+ res.sendStatus(200);
31
+ })
32
+ .catch(error => {
33
+ this.debug("Error when delete All devices configs deleted on gateway: " + error.message);
34
+ res.sendStatus(500);
60
35
  });
36
+ });
61
37
 
62
- RED.httpAdmin.get("/noderedhome/"+this.id+"/getfullconfig",(req,res)=>{
63
- const option = {
64
- method: 'GET',
65
- url: 'https://api.iot.yandex.net/v1.0/user/info',
66
- headers: {
67
- 'content-type': 'application/json',
68
- 'Authorization': "Bearer "+this.getToken()
69
- }
70
- };
71
- axios.request(option)
72
- .then(result=>{
73
- this.trace("Full Alice SmartHome config successfully retrieved");
74
- // console.log(result)
75
- res.json(result.data);
76
- })
77
- .catch(error=>{
78
- this.debug("Error when retrieve Alice SmartHome config: "+error.message);
79
- res.sendStatus(500);
80
- });
38
+ RED.httpAdmin.get("/noderedhome/" + this.id + "/getfullconfig", (_req, res) => {
39
+ axios.request({
40
+ method: 'GET',
41
+ url: 'https://api.iot.yandex.net/v1.0/user/info',
42
+ headers: {
43
+ 'content-type': 'application/json',
44
+ 'Authorization': "Bearer " + this.getToken()
45
+ }
46
+ })
47
+ .then(result => {
48
+ this.trace("Full Alice SmartHome config successfully retrieved");
49
+ res.json(result.data);
50
+ })
51
+ .catch(error => {
52
+ this.debug("Error when retrieve Alice SmartHome config: " + error.message);
53
+ res.sendStatus(500);
81
54
  });
55
+ });
82
56
 
83
57
  this.isOnline = false;
84
- //// проверяем а есть ли токен
85
- if (!token){
58
+
59
+ if (!token) {
86
60
  this.error("Authentication is required!!!");
87
61
  return;
88
- };
89
- const mqttClient = mqtt.connect("mqtts://mqtt.cloud.yandex.net",{
62
+ }
63
+
64
+ const mqttClient = mqtt.connect("mqtts://mqtt.cloud.yandex.net", {
90
65
  port: 8883,
91
66
  clientId: login,
92
67
  rejectUnauthorized: false,
@@ -95,202 +70,77 @@ export = (RED: NodeAPI):void =>{
95
70
  reconnectPeriod: 10000
96
71
  });
97
72
 
98
- mqttClient.on("message",(topic:string, payload:string)=>{
73
+ mqttClient.on("message", (topic: string, payload: Buffer) => {
99
74
  const arrTopic = topic.split('/');
100
- const data = JSON.parse(payload);
101
- this.trace("Incoming:" + topic +" timestamp:"+new Date().getTime());
102
- if (payload.length && typeof data === 'object'){
103
- if (arrTopic[3]=='message'){
75
+ const data = JSON.parse(payload.toString());
76
+ this.trace("Incoming:" + topic + " timestamp:" + new Date().getTime());
77
+ if (payload.length && typeof data === 'object') {
78
+ if (arrTopic[3] == 'message') {
104
79
  this.warn(data.text);
105
- }else{
106
- this.emit(arrTopic[3],data);
107
- };
80
+ } else {
81
+ this.emit(arrTopic[3], data);
82
+ }
108
83
  }
109
84
  });
110
- mqttClient.on("connect",()=>{
85
+
86
+ mqttClient.on("connect", () => {
111
87
  this.debug("Yandex IOT client connected. ");
112
88
  this.emit('online');
113
- // Подписываемся на получение комманд
114
- mqttClient.subscribe("$me/device/commands/+",_=>{
89
+ mqttClient.subscribe("$me/device/commands/+", () => {
115
90
  this.debug("Yandex IOT client subscribed to the command");
116
91
  });
117
92
  });
118
- mqttClient.on("offline",()=>{
93
+
94
+ mqttClient.on("offline", () => {
119
95
  this.debug("Yandex IOT client offline. ");
120
96
  this.emit('offline');
121
97
  });
122
- mqttClient.on("disconnect",()=>{
98
+
99
+ mqttClient.on("disconnect", () => {
123
100
  this.debug("Yandex IOT client disconnect.");
124
101
  this.emit('offline');
125
102
  });
126
- mqttClient.on("reconnect",()=>{
103
+
104
+ mqttClient.on("reconnect", () => {
127
105
  this.debug("Yandex IOT client reconnecting ...");
128
106
  });
129
- mqttClient.on("error",(err)=>{
130
- this.error("Yandex IOT client Error: "+ err.message);
107
+
108
+ mqttClient.on("error", (err) => {
109
+ this.error("Yandex IOT client Error: " + err.message);
131
110
  this.emit('offline');
132
111
  });
133
112
 
134
- this.on('offline', ()=>{
113
+ this.on('offline', () => {
135
114
  this.isOnline = false;
136
115
  });
137
116
 
138
- this.on('online', ()=>{
117
+ this.on('online', () => {
139
118
  this.isOnline = true;
140
119
  });
141
120
 
142
- this.on('close',(done:Object)=>{
121
+ this.on('close', (done: () => void) => {
143
122
  this.emit('offline');
144
- setTimeout(()=>{
145
- mqttClient.end(false,done);
146
- },500)
123
+ setTimeout(() => {
124
+ mqttClient.end(false, {}, done);
125
+ }, 500);
147
126
  });
148
127
 
149
- this.send2gate = (path:string,data:any,retain:boolean)=>{
150
- // this.debug(path);
151
- // this.debug(data);
152
- this.trace("Outgoing: "+path);
153
- mqttClient.publish(path, data ,{ qos: 0, retain: retain });
154
- }
155
-
128
+ this.send2gate = (path: string, data: string, retain: boolean) => {
129
+ this.trace("Outgoing: " + path);
130
+ mqttClient.publish(path, data, { qos: 0, retain: retain });
131
+ };
156
132
 
157
- this.getToken = ()=>{
158
- return JSON.parse(token).access_token;
133
+ this.getToken = () => {
134
+ return JSON.parse(token).access_token;
135
+ };
136
+ }
137
+
138
+ RED.nodes.registerType("alice-service", AliceService, {
139
+ credentials: {
140
+ email: { type: "text" },
141
+ password: { type: "password" },
142
+ token: { type: "password" },
143
+ id: { type: "text" }
159
144
  }
160
- };
161
-
162
- RED.nodes.registerType("alice-service",AliceService,{
163
- credentials: {
164
- email: {type: "text"},
165
- password: {type: "password"},
166
- token: {type: "password"},
167
- id:{type:"text"}
168
- }
169
- });
170
- }
171
-
172
- // const mqtt = require('mqtt');
173
- // const axios = require('axios');
174
-
175
- // module.exports = function(RED) {
176
- // //Sevice node, Alice-Service (credential)
177
- // function AliceService(config) {
178
- // RED.nodes.createNode(this,config);
179
- // this.debug("Starting Alice service...");
180
-
181
- // const email = this.credentials.email;
182
- // const login = this.credentials.id;
183
- // const password = this.credentials.password;
184
- // const token = this.credentials.token;
185
-
186
- // const suburl = Buffer.from(email).toString('base64');
187
- // RED.httpAdmin.get("/noderedhome/"+suburl+"/clearalldevice",(req,res)=>{
188
- // const option = {
189
- // method: 'POST',
190
- // url: 'https://api.nodered-home.ru/gtw/device/clearallconfigs',
191
- // headers: {
192
- // 'content-type': 'application/json',
193
- // 'Authorization': "Bearer "+this.getToken()
194
- // },
195
- // data: {}
196
- // };
197
- // axios.request(option)
198
- // .then(result=>{
199
- // this.trace("All devices configs deleted on gateway successfully");
200
- // // console.log(result)
201
- // res.sendStatus(200);
202
- // })
203
- // .catch(error=>{
204
- // this.debug("Error when delete All devices configs deleted on gateway: "+error.message);
205
- // res.sendStatus(500);
206
- // });
207
- // });
208
-
209
- // this.isOnline = false;
210
- // if (!token){
211
- // this.error("Authentication is required!!!");
212
- // return;
213
- // };
214
- // const mqttClient = mqtt.connect("mqtts://mqtt.cloud.yandex.net",{
215
- // port: 8883,
216
- // clientId: login,
217
- // rejectUnauthorized: false,
218
- // username: login,
219
- // password: password,
220
- // reconnectPeriod: 10000
221
- // });
222
- // mqttClient.on("message",(topic, payload)=>{
223
- // const arrTopic = topic.split('/');
224
- // const data = JSON.parse(payload);
225
- // this.trace("Incoming:" + topic +" timestamp:"+new Date().getTime());
226
- // if (payload.length && typeof data === 'object'){
227
- // if (arrTopic[3]=='message'){
228
- // this.warn(data.text);
229
- // }else{
230
- // this.emit(arrTopic[3],data);
231
- // };
232
- // }
233
- // });
234
- // mqttClient.on("connect",()=>{
235
- // this.debug("Yandex IOT client connected. ");
236
- // this.emit('online');
237
- // // Подписываемся на получение комманд
238
- // mqttClient.subscribe("$me/device/commands/+",_=>{
239
- // this.debug("Yandex IOT client subscribed to the command");
240
- // });
241
- // });
242
- // mqttClient.on("offline",()=>{
243
- // this.debug("Yandex IOT client offline. ");
244
- // this.emit('offline');
245
- // });
246
- // mqttClient.on("disconnect",()=>{
247
- // this.debug("Yandex IOT client disconnect.");
248
- // this.emit('offline');
249
- // });
250
- // mqttClient.on("reconnect",(err)=>{
251
- // this.debug("Yandex IOT client reconnecting ...");
252
- // });
253
- // mqttClient.on("error",(err)=>{
254
- // this.error("Yandex IOT client Error: "+ err.message);
255
- // this.emit('offline');
256
- // });
257
-
258
- // this.on('offline', ()=>{
259
- // this.isOnline = false;
260
- // })
261
-
262
- // this.on('online', ()=>{
263
- // this.isOnline = true;
264
- // })
265
-
266
- // this.on('close',(done)=>{
267
- // this.emit('offline');
268
- // setTimeout(()=>{
269
- // mqttClient.end(false,done);
270
- // },500)
271
- // });
272
-
273
- // this.send2gate= (path,data,retain)=>{
274
- // // this.debug(path);
275
- // // this.debug(data);
276
- // this.trace("Outgoing: "+path);
277
- // mqttClient.publish(path, data ,{ qos: 0, retain: retain });
278
- // }
279
-
280
- // this.getToken = ()=>{
281
- // return JSON.parse(token).access_token;
282
- // }
283
-
284
- // };
285
- // RED.nodes.registerType("alice-service",AliceService,{
286
- // credentials: {
287
- // email: {type: "text"},
288
- // password: {type: "password"},
289
- // token: {type: "password"},
290
- // id:{type:"text"}
291
- // }
292
- // });
293
- // };
294
-
295
-
296
-
145
+ });
146
+ };
package/src/types.ts ADDED
@@ -0,0 +1,157 @@
1
+ import { Node, NodeDef } from "node-red";
2
+
3
+ // ==================== Конфигурации нод ====================
4
+
5
+ export interface AliceServiceConfig extends NodeDef {
6
+ name: string;
7
+ }
8
+
9
+ export interface AliceDeviceConfig extends NodeDef {
10
+ service: string;
11
+ name: string;
12
+ description: string;
13
+ room: string;
14
+ dtype: string;
15
+ }
16
+
17
+ export interface AliceCapabilityConfig extends NodeDef {
18
+ device: string;
19
+ name: string;
20
+ response?: boolean;
21
+ instance?: string;
22
+ }
23
+
24
+ export interface AliceOnOffConfig extends AliceCapabilityConfig {
25
+ split?: boolean;
26
+ }
27
+
28
+ export interface AliceRangeConfig extends AliceCapabilityConfig {
29
+ retrievable: boolean;
30
+ unit: string;
31
+ min: string;
32
+ max: string;
33
+ precision: string;
34
+ }
35
+
36
+ export interface AliceColorConfig extends AliceCapabilityConfig {
37
+ color_support?: boolean;
38
+ scheme: string;
39
+ temperature_k?: boolean;
40
+ temperature_min: string;
41
+ temperature_max: string;
42
+ color_scene?: string[];
43
+ }
44
+
45
+ export interface AliceModeConfig extends AliceCapabilityConfig {
46
+ modes: string[];
47
+ }
48
+
49
+ export interface AliceSensorConfig extends NodeDef {
50
+ device: string;
51
+ name: string;
52
+ stype: string;
53
+ instance: string;
54
+ unit: string;
55
+ }
56
+
57
+ export interface AliceEventConfig extends NodeDef {
58
+ device: string;
59
+ name: string;
60
+ instance: string;
61
+ events: string[];
62
+ }
63
+
64
+ export interface AliceVideoConfig extends NodeDef {
65
+ device: string;
66
+ name: string;
67
+ stream_url: string;
68
+ protocol: string;
69
+ }
70
+
71
+ // ==================== Типы состояний ====================
72
+
73
+ export interface CapabilityState {
74
+ id?: string;
75
+ type: string;
76
+ state: {
77
+ instance: string;
78
+ value: any;
79
+ relative?: boolean;
80
+ };
81
+ }
82
+
83
+ export interface SensorState {
84
+ id?: string;
85
+ type: string;
86
+ state: {
87
+ instance: string;
88
+ value: any;
89
+ };
90
+ }
91
+
92
+ // ==================== Конфигурация умения/сенсора для регистрации ====================
93
+
94
+ export interface CapabilityRegistration {
95
+ id?: string;
96
+ type: string;
97
+ retrievable: boolean;
98
+ reportable: boolean;
99
+ parameters: Record<string, any>;
100
+ }
101
+
102
+ export interface SensorRegistration {
103
+ id?: string;
104
+ type: string;
105
+ retrievable: boolean;
106
+ reportable: boolean;
107
+ parameters: Record<string, any>;
108
+ }
109
+
110
+ // ==================== Интерфейсы нод ====================
111
+
112
+ export interface AliceServiceNode extends Node {
113
+ credentials: {
114
+ email: string;
115
+ id: string;
116
+ password: string;
117
+ token: string;
118
+ };
119
+ isOnline: boolean;
120
+ getToken(): string;
121
+ send2gate(topic: string, data: string, retain: boolean): void;
122
+ on(event: string, listener: (...args: any[]) => void): this;
123
+ }
124
+
125
+ export interface AliceDeviceNode extends Node {
126
+ initState: boolean;
127
+ setCapability(capId: string, capab: CapabilityRegistration): Promise<boolean>;
128
+ setSensor(sensId: string, sensor: SensorRegistration): Promise<boolean>;
129
+ updateCapabState(capId: string, state: CapabilityState): Promise<boolean>;
130
+ updateSensorState(sensId: string, state: SensorState): Promise<boolean>;
131
+ delCapability(capId: string): Promise<boolean>;
132
+ delSensor(sensId: string): Promise<boolean>;
133
+ on(event: string, listener: (...args: any[]) => void): this;
134
+ }
135
+
136
+ // ==================== Конфигурация устройства для шлюза ====================
137
+
138
+ export interface DeviceConfig {
139
+ id: string;
140
+ name: string;
141
+ description: string;
142
+ room: string;
143
+ type: string;
144
+ device_info: {
145
+ manufacturer: string;
146
+ model: string;
147
+ sw_version: string;
148
+ };
149
+ capabilities: CapabilityRegistration[];
150
+ properties: SensorRegistration[];
151
+ }
152
+
153
+ export interface DeviceStates {
154
+ id: string;
155
+ capabilities: CapabilityState[];
156
+ properties: SensorState[];
157
+ }