alemonjs 2.1.0-alpha.26 → 2.1.0-alpha.28

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.
@@ -1,6 +1,6 @@
1
1
  import { ResultCode } from '../core/code.js';
2
2
  import { createResult } from '../core/utils.js';
3
- import { generateUniqueId, actionResolves, deviceId, actionTimeouts, timeoutTime } from './config.js';
3
+ import { generateUniqueId, deviceId, actionResolves, actionTimeouts, timeoutTime } from './config.js';
4
4
  import * as flattedJSON from 'flatted';
5
5
 
6
6
  /**
@@ -10,14 +10,24 @@ import * as flattedJSON from 'flatted';
10
10
  const sendAction = (data) => {
11
11
  const actionId = generateUniqueId();
12
12
  return new Promise(resolve => {
13
- actionResolves.set(actionId, resolve);
14
13
  // 设置唯一标识符
15
14
  data.actionId = actionId;
16
15
  // 设置设备 ID
17
16
  data.DeviceId = deviceId;
18
- // 发送消息
19
- global.chatbotClient.send(flattedJSON.stringify(data));
20
- // 12 秒后超时
17
+ // 沙盒模式
18
+ if (global.sandbox) {
19
+ if (!global.testoneClient) {
20
+ return resolve([createResult(ResultCode.Fail, '未连接到客户端', null)]);
21
+ }
22
+ // 发送消息
23
+ global.testoneClient.send(flattedJSON.stringify(data));
24
+ }
25
+ else {
26
+ global.chatbotClient.send(flattedJSON.stringify(data));
27
+ }
28
+ // 设置回调函数
29
+ actionResolves.set(actionId, resolve);
30
+ // 超时
21
31
  const timeout = setTimeout(() => {
22
32
  // 被清理了
23
33
  if (!actionResolves.has(actionId) || !actionTimeouts.has(actionId)) {
@@ -30,6 +40,7 @@ const sendAction = (data) => {
30
40
  // 不会当错误进行处理。而是传入错误码
31
41
  resolve([createResult(ResultCode.Fail, '行为超时', null)]);
32
42
  }, timeoutTime);
43
+ // 设置超时
33
44
  actionTimeouts.set(actionId, timeout);
34
45
  });
35
46
  };
package/lib/cbp/api.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import { ResultCode } from '../core/code.js';
2
2
  import { createResult } from '../core/utils.js';
3
- import { generateUniqueId, apiResolves, deviceId, apiTimeouts, timeoutTime } from './config.js';
3
+ import { generateUniqueId, deviceId, apiResolves, apiTimeouts, timeoutTime } from './config.js';
4
4
  import * as flattedJSON from 'flatted';
5
5
 
6
6
  /**
@@ -10,14 +10,24 @@ import * as flattedJSON from 'flatted';
10
10
  const sendAPI = (data) => {
11
11
  const ApiId = generateUniqueId();
12
12
  return new Promise(resolve => {
13
- apiResolves.set(ApiId, resolve);
14
13
  // 设置唯一标识符
15
14
  data.apiId = ApiId;
16
15
  // 设置设备 ID
17
16
  data.DeviceId = deviceId;
18
- // 发送消息
19
- global.chatbotClient.send(flattedJSON.stringify(data));
20
- // 12 秒后超时
17
+ // 沙盒模式
18
+ if (global.sandbox) {
19
+ if (!global.testoneClient) {
20
+ return resolve([createResult(ResultCode.Fail, '未连接到客户端', null)]);
21
+ }
22
+ // 发送消息
23
+ global.testoneClient.send(flattedJSON.stringify(data));
24
+ }
25
+ else {
26
+ // 发送消息
27
+ global.chatbotClient.send(flattedJSON.stringify(data));
28
+ }
29
+ apiResolves.set(ApiId, resolve);
30
+ // 超时
21
31
  const timeout = setTimeout(() => {
22
32
  // 被清理了
23
33
  if (!apiResolves.has(ApiId) || !apiTimeouts.has(ApiId)) {
@@ -30,6 +40,7 @@ const sendAPI = (data) => {
30
40
  // 不会当错误进行处理。而是传入错误码
31
41
  resolve([createResult(ResultCode.Fail, '接口超时', null)]);
32
42
  }, timeoutTime);
43
+ // 设置超时
33
44
  apiTimeouts.set(ApiId, timeout);
34
45
  });
35
46
  };
@@ -0,0 +1,10 @@
1
+ import { CBPClientOptions } from './typings.js';
2
+
3
+ /**
4
+ * CBP 客户端
5
+ * @param url
6
+ * @param onopen
7
+ */
8
+ declare const cbpClient: (url: string, options?: CBPClientOptions) => void;
9
+
10
+ export { cbpClient };
@@ -0,0 +1,159 @@
1
+ import { WebSocket } from 'ws';
2
+ import { onProcessor } from '../app/event-processor.js';
3
+ import { ResultCode } from '../core/code.js';
4
+ import { deviceId, FULL_RECEIVE_HEADER, DEVICE_ID_HEADER, USER_AGENT_HEADER, apiResolves, apiTimeouts, actionResolves, actionTimeouts, reconnectInterval } from './config.js';
5
+ import { createResult } from '../core/utils.js';
6
+ import * as flattedJSON from 'flatted';
7
+ import { useHeartbeat } from './connect.js';
8
+
9
+ /**
10
+ * CBP 客户端
11
+ * @param url
12
+ * @param onopen
13
+ */
14
+ const cbpClient = (url, options = {}) => {
15
+ /**
16
+ * 纯 cbpClient 连接,会没有 一些 全局变量。
17
+ * 需要在此处进行判断并设置
18
+ */
19
+ if (global.chatbotClient) {
20
+ delete global.chatbotClient;
21
+ }
22
+ const { open = () => { }, isFullReceive = true } = options;
23
+ const [heartbeatControl] = useHeartbeat({
24
+ ping: () => {
25
+ global?.chatbotClient?.ping?.();
26
+ },
27
+ isConnected: () => {
28
+ return global?.chatbotClient && global?.chatbotClient?.readyState === WebSocket.OPEN;
29
+ },
30
+ terminate: () => {
31
+ try {
32
+ // 强制断开连接
33
+ global?.chatbotClient?.terminate?.();
34
+ }
35
+ catch (error) {
36
+ logger.debug({
37
+ code: ResultCode.Fail,
38
+ message: '强制断开连接失败',
39
+ data: error
40
+ });
41
+ }
42
+ }
43
+ });
44
+ const start = () => {
45
+ global.chatbotClient = new WebSocket(url, {
46
+ headers: {
47
+ [USER_AGENT_HEADER]: 'client',
48
+ [DEVICE_ID_HEADER]: deviceId,
49
+ [FULL_RECEIVE_HEADER]: isFullReceive ? '1' : '0'
50
+ }
51
+ });
52
+ global.chatbotClient.on('open', () => {
53
+ open();
54
+ heartbeatControl.start(); // 启动心跳
55
+ });
56
+ global.chatbotClient.on('pong', () => {
57
+ heartbeatControl.pong(); // 更新 pong 时间
58
+ });
59
+ // 客户端接收,被标准化的平台消息
60
+ global.chatbotClient.on('message', message => {
61
+ try {
62
+ // 解析消息
63
+ const parsedMessage = flattedJSON.parse(message.toString());
64
+ logger.debug({
65
+ code: ResultCode.Ok,
66
+ message: '客户端接收到消息',
67
+ data: parsedMessage
68
+ });
69
+ if (parsedMessage?.activeId) {
70
+ // 主端端主动消息。
71
+ if (parsedMessage.active === 'sync') {
72
+ const configs = parsedMessage.payload;
73
+ // env 同步
74
+ const env = configs.env || {};
75
+ for (const key in env) {
76
+ process.env[key] = env[key];
77
+ }
78
+ }
79
+ }
80
+ else if (parsedMessage?.apiId) {
81
+ // 如果有 apiId,说明是一个接口请求。要进行处理
82
+ const resolve = apiResolves.get(parsedMessage.apiId);
83
+ if (resolve) {
84
+ apiResolves.delete(parsedMessage.apiId);
85
+ // 清除超时器
86
+ const timeout = apiTimeouts.get(parsedMessage.apiId);
87
+ if (timeout) {
88
+ apiTimeouts.delete(parsedMessage.apiId);
89
+ clearTimeout(timeout);
90
+ }
91
+ // 调用回调函数
92
+ if (Array.isArray(parsedMessage.payload)) {
93
+ resolve(parsedMessage.payload);
94
+ }
95
+ else {
96
+ // 错误处理
97
+ resolve([createResult(ResultCode.Fail, '接口处理错误', null)]);
98
+ }
99
+ }
100
+ }
101
+ else if (parsedMessage?.actionId) {
102
+ // 如果有 actionId
103
+ const resolve = actionResolves.get(parsedMessage.actionId);
104
+ if (resolve) {
105
+ actionResolves.delete(parsedMessage.actionId);
106
+ // 清除超时器
107
+ const timeout = actionTimeouts.get(parsedMessage.actionId);
108
+ if (timeout) {
109
+ actionTimeouts.delete(parsedMessage.actionId);
110
+ clearTimeout(timeout);
111
+ }
112
+ // 调用回调函数
113
+ if (Array.isArray(parsedMessage.payload)) {
114
+ resolve(parsedMessage.payload);
115
+ }
116
+ else {
117
+ // 错误处理
118
+ resolve([createResult(ResultCode.Fail, '消费处理错误', null)]);
119
+ }
120
+ }
121
+ }
122
+ else if (parsedMessage.name) {
123
+ // 如果有 name,说明是一个事件请求。要进行处理
124
+ onProcessor(parsedMessage.name, parsedMessage, parsedMessage.value);
125
+ }
126
+ }
127
+ catch (error) {
128
+ logger.error({
129
+ code: ResultCode.Fail,
130
+ message: '客户端解析消息失败',
131
+ data: error
132
+ });
133
+ }
134
+ });
135
+ global.chatbotClient.on('close', () => {
136
+ heartbeatControl.stop(); // 停止心跳
137
+ logger.warn({
138
+ code: ResultCode.Fail,
139
+ message: '连接关闭,尝试重新连接...',
140
+ data: null
141
+ });
142
+ delete global.chatbotClient;
143
+ // 重新连接逻辑
144
+ setTimeout(() => {
145
+ start(); // 重新连接
146
+ }, reconnectInterval); // 6秒后重连
147
+ });
148
+ global.chatbotClient.on('error', err => {
149
+ logger.error({
150
+ code: ResultCode.Fail,
151
+ message: '客户端错误',
152
+ data: err
153
+ });
154
+ });
155
+ };
156
+ start();
157
+ };
158
+
159
+ export { cbpClient };
package/lib/cbp/config.js CHANGED
@@ -34,7 +34,7 @@ const generateUniqueId = () => {
34
34
  return Date.now().toString(36) + Math.random().toString(36).substring(2);
35
35
  };
36
36
  // 超时时间
37
- const timeoutTime = 1000 * 12; // 12秒
37
+ const timeoutTime = 1000 * 60 * 3; // 3分钟
38
38
  // 失败重连
39
39
  const reconnectInterval = 1000 * 6; // 6秒
40
40
  // 心跳间隔
@@ -1,9 +1,5 @@
1
- import { WebSocket } from 'ws';
2
- import { onProcessor } from '../app/event-processor.js';
3
1
  import { ResultCode } from '../core/code.js';
4
- import { deviceId, FULL_RECEIVE_HEADER, DEVICE_ID_HEADER, USER_AGENT_HEADER, apiResolves, apiTimeouts, actionResolves, actionTimeouts, reconnectInterval, HEARTBEAT_INTERVAL } from './config.js';
5
- import { createResult } from '../core/utils.js';
6
- import * as flattedJSON from 'flatted';
2
+ import { HEARTBEAT_INTERVAL } from './config.js';
7
3
 
8
4
  // 心跳
9
5
  const useHeartbeat = ({ ping, isConnected, terminate }) => {
@@ -62,310 +58,5 @@ const useHeartbeat = ({ ping, isConnected, terminate }) => {
62
58
  };
63
59
  return [control];
64
60
  };
65
- /**
66
- * CBP 客户端
67
- * @param url
68
- * @param onopen
69
- */
70
- const cbpClient = (url, options = {}) => {
71
- /**
72
- * 纯 cbpClient 连接,会没有 一些 全局变量。
73
- * 需要在此处进行判断并设置
74
- */
75
- if (!global.chatbotClient) {
76
- delete global.chatbotClient;
77
- }
78
- const { open = () => { }, isFullReceive = true } = options;
79
- const [heartbeatControl] = useHeartbeat({
80
- ping: () => {
81
- global?.chatbotClient?.ping?.();
82
- },
83
- isConnected: () => {
84
- return global?.chatbotClient && global?.chatbotClient?.readyState === WebSocket.OPEN;
85
- },
86
- terminate: () => {
87
- try {
88
- // 强制断开连接
89
- global?.chatbotClient?.terminate?.();
90
- }
91
- catch (error) {
92
- logger.debug({
93
- code: ResultCode.Fail,
94
- message: '强制断开连接失败',
95
- data: error
96
- });
97
- }
98
- }
99
- });
100
- const start = () => {
101
- global.chatbotClient = new WebSocket(url, {
102
- headers: {
103
- [USER_AGENT_HEADER]: 'client',
104
- [DEVICE_ID_HEADER]: deviceId,
105
- [FULL_RECEIVE_HEADER]: isFullReceive ? '1' : '0'
106
- }
107
- });
108
- global.chatbotClient.on('open', () => {
109
- open();
110
- heartbeatControl.start(); // 启动心跳
111
- });
112
- global.chatbotClient.on('pong', () => {
113
- heartbeatControl.pong(); // 更新 pong 时间
114
- });
115
- // 客户端接收,被标准化的平台消息
116
- global.chatbotClient.on('message', message => {
117
- try {
118
- // 解析消息
119
- const parsedMessage = flattedJSON.parse(message.toString());
120
- logger.debug({
121
- code: ResultCode.Ok,
122
- message: '客户端接收到消息',
123
- data: parsedMessage
124
- });
125
- if (parsedMessage?.activeId) {
126
- // 主端端主动消息。
127
- if (parsedMessage.active === 'sync') {
128
- const configs = parsedMessage.payload;
129
- // env 同步
130
- const env = configs.env || {};
131
- for (const key in env) {
132
- process.env[key] = env[key];
133
- }
134
- }
135
- }
136
- else if (parsedMessage?.apiId) {
137
- // 如果有 apiId,说明是一个接口请求。要进行处理
138
- const resolve = apiResolves.get(parsedMessage.apiId);
139
- if (resolve) {
140
- apiResolves.delete(parsedMessage.apiId);
141
- // 清除超时器
142
- const timeout = apiTimeouts.get(parsedMessage.apiId);
143
- if (timeout) {
144
- apiTimeouts.delete(parsedMessage.apiId);
145
- clearTimeout(timeout);
146
- }
147
- // 调用回调函数
148
- if (Array.isArray(parsedMessage.payload)) {
149
- resolve(parsedMessage.payload);
150
- }
151
- else {
152
- // 错误处理
153
- resolve([createResult(ResultCode.Fail, '接口处理错误', null)]);
154
- }
155
- }
156
- }
157
- else if (parsedMessage?.actionId) {
158
- // 如果有 actionId
159
- const resolve = actionResolves.get(parsedMessage.actionId);
160
- if (resolve) {
161
- actionResolves.delete(parsedMessage.actionId);
162
- // 清除超时器
163
- const timeout = actionTimeouts.get(parsedMessage.actionId);
164
- if (timeout) {
165
- actionTimeouts.delete(parsedMessage.actionId);
166
- clearTimeout(timeout);
167
- }
168
- // 调用回调函数
169
- if (Array.isArray(parsedMessage.payload)) {
170
- resolve(parsedMessage.payload);
171
- }
172
- else {
173
- // 错误处理
174
- resolve([createResult(ResultCode.Fail, '消费处理错误', null)]);
175
- }
176
- }
177
- }
178
- else if (parsedMessage.name) {
179
- // 如果有 name,说明是一个事件请求。要进行处理
180
- onProcessor(parsedMessage.name, parsedMessage, parsedMessage.value);
181
- }
182
- }
183
- catch (error) {
184
- logger.error({
185
- code: ResultCode.Fail,
186
- message: '客户端解析消息失败',
187
- data: error
188
- });
189
- }
190
- });
191
- global.chatbotClient.on('close', () => {
192
- heartbeatControl.stop(); // 停止心跳
193
- logger.warn({
194
- code: ResultCode.Fail,
195
- message: '连接关闭,尝试重新连接...',
196
- data: null
197
- });
198
- delete global.chatbotClient;
199
- // 重新连接逻辑
200
- setTimeout(() => {
201
- start(); // 重新连接
202
- }, reconnectInterval); // 6秒后重连
203
- });
204
- global.chatbotClient.on('error', err => {
205
- logger.error({
206
- code: ResultCode.Fail,
207
- message: '客户端错误',
208
- data: err
209
- });
210
- });
211
- };
212
- start();
213
- };
214
- const cbpPlatform = (url, options = {
215
- open: () => { }
216
- }) => {
217
- if (!global.chatbotPlatform) {
218
- delete global.chatbotPlatform;
219
- }
220
- const { open = () => { } } = options;
221
- const [heartbeatControl] = useHeartbeat({
222
- ping: () => {
223
- global?.chatbotPlatform?.ping?.();
224
- },
225
- isConnected: () => {
226
- return global?.chatbotPlatform && global?.chatbotPlatform?.readyState === WebSocket.OPEN;
227
- },
228
- terminate: () => {
229
- try {
230
- global?.chatbotPlatform?.terminate?.();
231
- }
232
- catch (error) {
233
- logger.debug({
234
- code: ResultCode.Fail,
235
- message: '强制断开连接失败',
236
- data: error
237
- });
238
- }
239
- }
240
- });
241
- /**
242
- * 发送数据
243
- * @param data
244
- */
245
- const send = (data) => {
246
- if (global.chatbotPlatform && global.chatbotPlatform.readyState === WebSocket.OPEN) {
247
- data.DeviceId = deviceId; // 设置设备 ID
248
- global.chatbotPlatform.send(flattedJSON.stringify(data));
249
- }
250
- };
251
- const actionReplys = [];
252
- const apiReplys = [];
253
- /**
254
- * 消费数据
255
- * @param data
256
- * @param payload
257
- */
258
- const replyAction = (data, payload) => {
259
- if (global.chatbotPlatform && global.chatbotPlatform.readyState === WebSocket.OPEN) {
260
- // 透传消费。也就是对应的设备进行处理消费。
261
- global.chatbotPlatform.send(flattedJSON.stringify({
262
- action: data.action,
263
- payload: payload,
264
- actionId: data.actionId,
265
- DeviceId: data.DeviceId
266
- }));
267
- }
268
- };
269
- const replyApi = (data, payload) => {
270
- if (global.chatbotPlatform && global.chatbotPlatform.readyState === WebSocket.OPEN) {
271
- // 透传消费。也就是对应的设备进行处理消费。
272
- global.chatbotPlatform.send(flattedJSON.stringify({
273
- action: data.action,
274
- apiId: data.apiId,
275
- DeviceId: data.DeviceId,
276
- payload: payload
277
- }));
278
- }
279
- };
280
- /**
281
- * 接收行为
282
- * @param reply
283
- */
284
- const onactions = (reply) => {
285
- actionReplys.push(reply);
286
- };
287
- /**
288
- * 接收接口
289
- */
290
- const onapis = (reply) => {
291
- apiReplys.push(reply);
292
- };
293
- /**
294
- * 启动 WebSocket 连接
295
- */
296
- const start = () => {
297
- global.chatbotPlatform = new WebSocket(url, {
298
- headers: {
299
- [USER_AGENT_HEADER]: 'platform',
300
- [DEVICE_ID_HEADER]: deviceId
301
- }
302
- });
303
- global.chatbotPlatform.on('open', () => {
304
- open();
305
- heartbeatControl.start(); // 启动心跳
306
- });
307
- global.chatbotPlatform.on('pong', () => {
308
- heartbeatControl.pong(); // 更新 pong 时间
309
- });
310
- global.chatbotPlatform.on('message', message => {
311
- try {
312
- const data = flattedJSON.parse(message.toString());
313
- logger.debug({
314
- code: ResultCode.Ok,
315
- message: '平台端接收消息',
316
- data: data
317
- });
318
- if (data.apiId) {
319
- for (const cb of apiReplys) {
320
- cb(data,
321
- // 传入一个消费函数
322
- val => replyApi(data, val));
323
- }
324
- }
325
- else if (data.actionId) {
326
- for (const cb of actionReplys) {
327
- cb(data,
328
- // 传入一个消费函数
329
- val => replyAction(data, val));
330
- }
331
- }
332
- }
333
- catch (error) {
334
- logger.error({
335
- code: ResultCode.Fail,
336
- message: '解析消息失败',
337
- data: error
338
- });
339
- }
340
- });
341
- global.chatbotPlatform.on('close', err => {
342
- heartbeatControl.stop(); // 停止心跳
343
- logger.warn({
344
- code: ResultCode.Fail,
345
- message: '平台端连接关闭,尝试重新连接...',
346
- data: err
347
- });
348
- delete global.chatbotPlatform;
349
- // 重新连接逻辑
350
- setTimeout(() => {
351
- start(); // 重新连接
352
- }, reconnectInterval); // 6秒后重连
353
- });
354
- global.chatbotPlatform.on('error', err => {
355
- logger.error({
356
- code: ResultCode.Fail,
357
- message: '平台端错误',
358
- data: err
359
- });
360
- });
361
- };
362
- start();
363
- const client = {
364
- send,
365
- onactions,
366
- onapis
367
- };
368
- return client;
369
- };
370
61
 
371
- export { cbpClient, cbpPlatform };
62
+ export { useHeartbeat };
@@ -0,0 +1,19 @@
1
+ import { EventsEnum } from '../typing/event/map.js';
2
+ import '../global.js';
3
+ import { ActionReplyFunc, ApiReplyFunc } from './typings.js';
4
+
5
+ /**
6
+ * CBP 平台端
7
+ * @param url
8
+ * @param options
9
+ * @returns
10
+ */
11
+ declare const cbpPlatform: (url: string, options?: {
12
+ open: () => void;
13
+ }) => {
14
+ send: (data: EventsEnum) => void;
15
+ onactions: (reply: ActionReplyFunc) => void;
16
+ onapis: (reply: ApiReplyFunc) => void;
17
+ };
18
+
19
+ export { cbpPlatform };