mm_os 2.3.2 → 2.3.3

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.
@@ -2,19 +2,19 @@
2
2
  // 名称, 由中英文和下“_”组成, 用于修改或卸载 例如: demo
3
3
  "name": "{0}",
4
4
  // mqtt 服务标题
5
- "title": "",
5
+ "title": "{1}",
6
6
  // mqtt 服务介绍
7
7
  "description": "",
8
8
  // 状态 0未启用,1启用
9
9
  "state": 1,
10
10
  // 订阅的主题
11
- "topic": ["mqtt/server/sn/#", "mqtt/face/sn/#"],
12
- // 主题回复
13
- "topic_receive": ["mqtt/client/", "mqtt/face/"],
11
+ "topic": ["mqtt/face/#", "face/+/response", "mqtt/server/#"],
12
+ // 回复订阅主题
13
+ "topic_receive": ["mqtt/face/${clientid}", "face/${clientid}/request"],
14
14
  // 给客户端推送的主题
15
- "topic_push": "mqtt/client/${clientid}",
15
+ "topic_push": "mqtt/face/${clientid}",
16
16
  // 接收方式
17
- "qos": 1,
17
+ "qos": 2,
18
18
  // 保持接收
19
19
  "retain": true,
20
20
  // 超时反馈
@@ -24,7 +24,7 @@
24
24
  // 客户端ID
25
25
  "clientid": "clientid",
26
26
  // 消息ID
27
- "msgid": "msgid",
27
+ "msgid": "messageId",
28
28
  // 请求方法
29
29
  "method": "operator",
30
30
  // 参数
@@ -2,7 +2,6 @@ const os = require('os');
2
2
  const util = require('util');
3
3
  const Item = require('mm_machine').Item;
4
4
 
5
-
6
5
  /**
7
6
  * mqtt驱动类
8
7
  * @extends {Item}
@@ -90,9 +89,9 @@ Drive.prototype.model = function() {
90
89
  // 状态 0未启用,1启用
91
90
  "state": 1,
92
91
  // 订阅的主题
93
- "topic": ["mqtt/server/sn/#", "mqtt/face/sn/#"],
92
+ "topic": ["mqtt/face/#", "face/+/response", "mqtt/server/#"],
94
93
  // 回复订阅主题
95
- "topic_receive": ["mqtt/client/", "mqtt/face/"],
94
+ "topic_receive": ["mqtt/face/${clientid}", "face/${clientid}/request"],
96
95
  // 给客户端推送的主题
97
96
  "topic_push": "mqtt/client/${clientid}",
98
97
  // 接收方式
@@ -301,6 +300,29 @@ Drive.prototype.pushS = function(clientid, msg, longtime) {
301
300
  });
302
301
  }
303
302
 
303
+ /**
304
+ * 更新设备在线
305
+ * @param {String} clientid 客户端ID
306
+ */
307
+ Drive.prototype.update_online = async function(clientid) {
308
+ if (!_this.drives[clientid]) {
309
+ _this.drives[clientid] = {};
310
+ }
311
+ var time_last = new Date().getTime(); // 跟新时间戳
312
+ _this.drives[clientid].online = 1;
313
+ _this.drives[clientid].time_last = time_last;
314
+ var {
315
+ tip,
316
+ device
317
+ } = await $.server.check_device(clientid);
318
+ if (device) {
319
+ if (!device.online) {
320
+ device.online = 1;
321
+ }
322
+ device.time_last = time_last;
323
+ }
324
+ }
325
+
304
326
  /**
305
327
  * 推送消息
306
328
  * @param {String} method 方法
@@ -36,13 +36,17 @@ class MQTT extends Index {
36
36
  password: "asd123",
37
37
  clean: false,
38
38
  longtime: 15000,
39
+ // 在线有效期时长判断 单位:毫秒,150000毫秒为2.5分钟
40
+ online_expires: 150000,
41
+ online_interval: 10000,
39
42
  connectTimeout: 4000,
40
43
  // maxInflight: 20,
41
44
  // 重连间隔
42
45
  // interval: 6000,
43
46
  reconnectPeriod: 6000 // 重连间隔1秒
44
47
  }
45
-
48
+ // 定时器
49
+ this.timer = null;
46
50
  // mqtt客户端服务器
47
51
  this.client = null;
48
52
  /**
@@ -177,6 +181,7 @@ MQTT.prototype.init = function(config) {
177
181
  * @param {Object} config 配置参数
178
182
  */
179
183
  MQTT.prototype.start = function() {
184
+ this.start_timer();
180
185
  this.connecting = true;
181
186
  var err;
182
187
  try {
@@ -405,6 +410,87 @@ MQTT.prototype.reqASync = function(topic, method, params) {
405
410
  });
406
411
  };
407
412
 
413
+ /**
414
+ * 保存在线到数据库
415
+ * @param {Array} arr 客户端ID数组
416
+ * @param {Number} online 在线情况 0为不在线,1为在线
417
+ * @param {Number} time_last 最后上线时间
418
+ */
419
+ MQTT.prototype.save_online = async function(arr, online, time_last) {
420
+ if (!arr || !arr.length) {
421
+ return
422
+ }
423
+ var body = {
424
+ online
425
+ }
426
+ if (time_last) {
427
+ body.time_last = time_last;
428
+ // time_last = (new Date()).toStr('yyyy-MM-dd hh:mm:ss');
429
+ }
430
+ var sql = $.mysql_admin('sys');
431
+ sql.open();
432
+ var db = sql.db();
433
+ db.table = "face_device";
434
+ db.size = 0;
435
+ await db.set({
436
+ clientid_has: arr
437
+ }, body);
438
+ }
439
+
440
+ /**
441
+ * 更新在线设备
442
+ */
443
+ MQTT.prototype.update_online = async function() {
444
+ var list = this.list;
445
+ var list_online = [];
446
+ var list_offline = [];
447
+ var now = new Date().getTime();
448
+ var online_expires = this.config.online_expires; // 180
449
+ for (var i = 0; i < list.length; i++) {
450
+ var dict = list[i].drives;
451
+ for (var clientid in dict) {
452
+ var o = dict[clientid];
453
+ if (!o.online) {
454
+ list_offline.push(clientid);
455
+ } else {
456
+ if (o.time_last) {
457
+ var cha = now - o.time_last;
458
+ if (cha > online_expires) {
459
+ list_offline.push(clientid);
460
+ o.online = 0;
461
+ delete dict[clientid];
462
+ } else {
463
+ list_online.push(clientid);
464
+ }
465
+ }
466
+ }
467
+ }
468
+ }
469
+ var list_on = list_online.to2D(30);
470
+ for (var i = 0; i < list_on.length; i++) {
471
+ await this.save_online(list_on[i], 1);
472
+ }
473
+ var list_off = list_offline.to2D(30);
474
+ for (var i = 0; i < list_off.length; i++) {
475
+ await this.save_online(list_off[i], 0);
476
+ }
477
+ }
478
+
479
+ /**
480
+ * 开始计时器
481
+ */
482
+ MQTT.prototype.start_timer = function() {
483
+ if (!this.timer) {
484
+ this.timer = setInterval(() => {
485
+ try {
486
+ this.update_online();
487
+ } catch (err) {
488
+
489
+ }
490
+ }, this.config.online_interval);
491
+ }
492
+ }
493
+
408
494
  module.exports = MQTT;
409
495
 
410
496
 
@@ -1,34 +1,435 @@
1
1
  /**
2
- * 主函数, 用于处理订阅内容
3
- * @param {String} topic 订阅的主题
4
- * @param {Object} body 消息格式
5
- * @param {Number} index 索引
6
- * @return {Object} 返回执行结果
2
+ * 查询个人记录
3
+ * @param {String} clientid 客户端ID
4
+ * @param {Object} param
7
5
  */
8
- exports.main = async function(topic, msg, index) {
9
- $.log.debug('收到消息', topic, msg, index);
10
- };
6
+ exports.get_log = function(clientid, param) {
7
+ return this.push("GetRecordsByPicOrID", clientid, param);
8
+ }
9
+
10
+ /**
11
+ * 考勤打卡
12
+ * @param {String} clientid 客户端ID
13
+ * @param {Object} uuid 用户唯一标识
14
+ * @param {String} avatar base64头像
15
+ * @param {Number} longtime 超时回馈
16
+ */
17
+ exports.sign_in = function(clientid, uuid, avatar) {
18
+ return this.push("PullRecordOnlyPic", clientid, {
19
+ "personID": uuid,
20
+ "picinfo": avatar
21
+ });
22
+ }
23
+
24
+ /**
25
+ * 下发二维码(没用到)
26
+ * @param {String} clientid
27
+ * @param {Object} param
28
+ * @param {Number} longtime 超时回馈
29
+ */
30
+ exports.push_qrcode = function(clientid, param) {
31
+ return this.push("ShowQRCode", clientid, param);
32
+ }
33
+
34
+ /**
35
+ * 以图搜人
36
+ * @param {String} clientid 客户端ID
37
+ * @param {Object} avatar 人脸照片
38
+ * @param {Number} longtime 超时回馈
39
+ */
40
+ exports.get_member_pic = async function(clientid, avatar) {
41
+ var res = await this.push("GetPictureSearch", clientid, {
42
+ "facesluiceId": clientid,
43
+ "MaxSimilarity": 80,
44
+ "MaxNum": 1,
45
+ "picinfo": avatar
46
+ });
47
+ var user;
48
+ if (res) {
49
+ if (res.result == "fail") {
50
+
51
+ } else {
52
+ var u = res.SearchInfo[0];
53
+ var name = u.name || u.persionName;
54
+ var customId = u.customId.trim();
55
+ var phone = (u.telnum || "").trim();
56
+ var idcard = (u.idCard || "").trim();
57
+ user = {
58
+ name,
59
+ customId,
60
+ phone,
61
+ idcard
62
+ }
63
+ }
64
+ }
65
+ return user
66
+ }
67
+
68
+ /**
69
+ * 远程开门
70
+ * @param {String} clientid 客户端ID
71
+ * @param {String} uuid 用户唯一标识
72
+ * @param {Boolean} pass 是否可通行 true为是
73
+ * @param {String} tip 提示
74
+ */
75
+ exports.unlock = async function(clientid, uuid = '0', pass = false, tip = '没有访问权限') {
76
+ var res = await this.push("Unlock", clientid, {
77
+ "uid": uuid,
78
+ // 0不开门,1开门
79
+ "openDoor": pass ? "1" : "0",
80
+ "showInfo": tip
81
+ });
82
+
83
+ if (!res || res.result == "fail") {
84
+ return "非内部人员!";
85
+ }
86
+ }
87
+
88
+ /**
89
+ * 删除成员
90
+ * @param {String} clientid 客户端ID
91
+ * @param {String} uuid 用户唯一标识
92
+ * @param {Number} longtime 超时回馈
93
+ */
94
+ exports.delete_member = function(clientid, uuid) {
95
+ return this.push("DeletePersons", clientid, {
96
+ "customId": uuid
97
+ });
98
+ }
99
+
100
+ /**
101
+ * 批量删除成员
102
+ * @param {String} clientid 客户端ID
103
+ * @param {Object} arr 成员列表
104
+ * @param {Number} longtime 超时回馈
105
+ */
106
+ exports.delete_member_batch = function(clientid, arr, longtime) {
107
+ return this.push("DeletePersons", clientid, {
108
+ DataBegin: "BeginFlag",
109
+ DataEnd: "EndFlag",
110
+ PersonNum: arr.length.toString(),
111
+ customId: arr
112
+ }, longtime);
113
+ }
114
+
115
+ /**
116
+ * 重启设备
117
+ * @param {String} clientid 设备sn
118
+ */
119
+ exports.reboot_device = function(clientid) {
120
+ return this.push("RebootDevice", clientid, {});
121
+ }
122
+
123
+ /**
124
+ * 设置设备时间
125
+ * @param {String} clientid 设备sn
126
+ * @param {String} datetime 日期时间
127
+ */
128
+ exports.set_device_time = async function(clientid, datetime) {
129
+ var res = await this.push("SetSysTime", clientid, {
130
+ "SysTime": datetime.replace(" ", "T")
131
+ });
132
+ if (!res || res.result == "ok") {
133
+ return
134
+ }
135
+ return "重置时间失败"
136
+ }
137
+
138
+ /**
139
+ * 恢复出厂设置
140
+ * @param {String} clientid 设备sn
141
+ * @param {Boolean} record 是否恢复控制记录,true为恢复
142
+ * @param {Boolean} member 是否恢复成员,true为恢复
143
+ * @param {Boolean} log 是否恢复请求日志,true为恢复
144
+ */
145
+ exports.reset_device = async function(clientid, record = true, member = false, log = true) {
146
+ var res = await this.push("SetFactoryDefault", clientid, {
147
+ DefaltRecord: record ? "1" : "0",
148
+ DefaltPerson: member ? "1" : "0",
149
+ DefaltLog: log ? "1" : "0"
150
+ });
151
+
152
+ if (!res || res.result == "ok") {
153
+ return
154
+ }
155
+ return "恢复出厂设置失败"
156
+ }
157
+
158
+ /**
159
+ * 查询下发进度
160
+ * @param {String} clientid 设备sn
161
+ * @param {String} mode 查询方式 默认为更新
162
+ */
163
+ exports.get_progress = async function(clientid, mode = 'update') {
164
+ var type = "";
165
+ if (mode == 'update') {
166
+ type = "EditPersonsNew";
167
+ } else {
168
+ type = "DeletePersons";
169
+ }
170
+ var res = await this.push("QueryProgress", clientid, {
171
+ "QueryType": type
172
+ });
173
+ if (res) {
174
+ if (res.Status !== "0") {
175
+ return 1;
176
+ } else {
177
+ return 0;
178
+ }
179
+ }
180
+ return -1;
181
+ }
182
+
183
+ /**
184
+ * 考勤补卡
185
+ * @param {String} clientid 设备sn
186
+ * @param {Object} param 其他信息
187
+ * @param {Number} longtime 超时回馈
188
+ */
189
+ exports.replacement = function(clientid, uuid, time, avatar) {
190
+ return this.push("PullRecordOnlyName", clientid, {
191
+ "personID": uuid,
192
+ "time": time,
193
+ "picinfo": avatar
194
+ }, longtime);
195
+ }
196
+
197
+ /**
198
+ * 查询人员名单
199
+ * @param {String} clientid 客户端ID
200
+ * @param {Number} longtime 超时回馈
201
+ */
202
+ exports.get_member = function(clientid, longtime = 0) {
203
+ return this.push("QueryPerson", clientid, longtime);
204
+ }
205
+
206
+ /**
207
+ * 查询人员名单
208
+ * @param {String} clientid 客户端ID
209
+ * @param {String} uuid 用户唯一标识
210
+ * @param {Number} longtime 超时回馈
211
+ */
212
+ exports.get_member_one = function(clientid, uuid, longtime = 0) {
213
+ return this.push("QueryPerson", clientid, {
214
+ "personId": uuid
215
+ }, longtime);
216
+ }
217
+
218
+ /**
219
+ * 成员模型
220
+ * @param {Object} m 原始的成员
221
+ */
222
+ exports.member_model_out = function(m) {
223
+ var nfc = m.nfc || '';
224
+ var obj = {
225
+ "customId": m.customId,
226
+ "name": m.name,
227
+ "native": m.place || '',
228
+ "nation": m.nation || '',
229
+ "address": m.address || '',
230
+ "idCard": m.idcard || '',
231
+ "gender": m.sex - 1,
232
+ "phone": m.phone,
233
+ "birthday": m.birthday,
234
+ "cardType2": 2,
235
+ "cardNum2": nfc,
236
+ "RFCardMode": 0,
237
+ "RFIDCard": nfc,
238
+ "notes": "",
239
+ "personType": m.state == 4 ? 1 : 0,
240
+ "cardType": 0,
241
+ "picURI": this.fullUrl(m.avatar)
242
+ }
243
+
244
+ if (m.time_valid_end && m.time_valid_end > "2021-01-01 00:00:00".toTime() && m.time_valid_end <=
245
+ "2038-01-01 00:00:00".toTime()) {
246
+ if (typeof(m.time_valid_start) == "object") {
247
+ obj.cardValidBegin = m.time_valid_start.toStr("yyyy-MM-dd hh:mm:ss");
248
+ } else {
249
+ obj.cardValidBegin = m.time_valid_start.toTime().toStr("yyyy-MM-dd hh:mm:ss");
250
+ }
251
+ if (typeof(m.time_valid_end) == "object") {
252
+ obj.cardValidEnd = m.time_valid_end.toStr("yyyy-MM-dd hh:mm:ss");
253
+ } else {
254
+ obj.cardValidEnd = m.time_valid_end.toTime().toStr("yyyy-MM-dd hh:mm:ss");
255
+ }
256
+ obj.tempCardType = 1;
257
+ } else {
258
+ obj.tempCardType = 0;
259
+ }
260
+ return obj
261
+ }
262
+
263
+ /**
264
+ * 批量下发人员名单
265
+ * @param {String} clientid 客户端ID
266
+ * @param {Array} list 人员名单
267
+ * @param {Number} longtime 超时回馈
268
+ */
269
+ exports.update_member_batch = async function(clientid, list, longtime = 180) {
270
+ var res = await this.pushS(clientid, {
271
+ "messageId": this.get_msgid('EditPersonsNew'),
272
+ "DataBegin": "BeginFlag",
273
+ "DataEnd": "EndFlag",
274
+ "operator": "EditPersonsNew",
275
+ "PersonNum": list.length,
276
+ "info": list.map((o) => {
277
+ return this.member_model_out(o);
278
+ })
279
+ }, longtime);
280
+ return res;
281
+ }
282
+
283
+ /**
284
+ * 下发人员名单
285
+ * @param {String} clientid 设备ID
286
+ * @param {Object} user 人员信息
287
+ * @param {Number} longtime 超时回馈
288
+ */
289
+ exports.update_member = function(clientid, user, longtime = 0) {
290
+ return this.pushS(clientid, {
291
+ "messageId": this.get_msgid('EditPerson'),
292
+ "DataBegin": "BeginFlag",
293
+ "DataEnd": "EndFlag",
294
+ "method": "EditPerson",
295
+ "info": this.member_model_out(user)
296
+ }, longtime);
297
+ }
11
298
 
12
299
  /**
13
300
  * 初始化函数, 用于定义开放给前端的函数
14
301
  */
15
- exports.init = async function() {
302
+ exports.init = function() {
16
303
  var m = this.methods;
304
+ var _this = this;
305
+
306
+ m["HeartBeat"] = function(clientid, params) {
307
+ if (!_this.drives[clientid]) {
308
+ _this.drives[clientid] = {};
309
+ }
310
+ _this.drives[clientid].online = 1;
311
+ _this.drives[clientid].time_last = new Date().getTime();
312
+ }
17
313
 
18
314
  /**
19
- * 获取所有方法
20
- * @param {Object} params 参数
21
- * @param {Object} mqtt MQTT服务
315
+ * 在线通知
316
+ * @param {String} clientid 设备sn
317
+ * @param {Object} param 其他信息
22
318
  */
23
- m.get_method = function(params, mqtt) {
24
- return Object.keys(m);
319
+ m["Offline"] = async function(clientid, params) {
320
+ if (_this.drives[clientid]) {
321
+ _this.drives[clientid].online = 0;
322
+ }
323
+ var {
324
+ tip,
325
+ device
326
+ } = await $.server.check_device(clientid);
327
+ if (device) {
328
+ device.online = 0;
329
+ }
330
+ // console.log("离线", clientid, _this.drives[clientid]);
25
331
  };
26
332
 
27
333
  /**
28
- * @param {Object} params 参数
29
- * @param {Object} mqtt MQTT服务
334
+ * 在线通知
335
+ * @param {String} clientid 设备sn
336
+ * @param {Object} param 其他信息
30
337
  */
31
- m.test = function(params, mqtt) {
32
- return "你好"
338
+ m["Online"] = async function(clientid, params) {
339
+ await this.update_online(clientid);
340
+ return {
341
+ "facesluiceId": clientid,
342
+ "result": "ok",
343
+ "detail": ""
344
+ };
345
+ // console.log("上线", clientid, _this.drives[clientid]);
33
346
  };
347
+
348
+ m["RecPush"] = async function(clientid, params, msg, id) {
349
+ var type = 1;
350
+ switch (params.otype) {
351
+ // (1人脸验证|2远程开门|3智码开门|4刷卡验证)
352
+ case "7":
353
+ case "27":
354
+ type = 2;
355
+ break;
356
+ case "47":
357
+ case "48":
358
+ case "55":
359
+ case "56":
360
+ case "57":
361
+ type = 3;
362
+ break;
363
+ case "21":
364
+ case "22":
365
+ case "24":
366
+ case "25":
367
+ type = 4;
368
+ break;
369
+ default:
370
+ break;
371
+ }
372
+ if (type == 2) {
373
+ return;
374
+ }
375
+ // 1白名单|2黑名单
376
+ var person_type = params.PersonType == "1" ? 2 : 1;
377
+ var record_type = params.RecordType ? Number(params.RecordType) + 1 : 1;
378
+
379
+ // 拿到打卡人的姓名
380
+ var name = params.persionName || params.name;
381
+ if (!name) {
382
+ return;
383
+ }
384
+ var customId = params.customId.trim();
385
+ var phone = (params.telnum || "").trim();
386
+ var idcard = (params.idCard || "").trim();
387
+ var nfc = (params.cardNum2 || params.RFIDCard || "").trim();
388
+ var time = params.time;
389
+ var avatar = "";
390
+ if (params.pic) {
391
+ avatar = params.pic;
392
+ }
393
+ if (typeof(time) == "object") {
394
+ time = time.toStr("yyyy-MM-dd hh:mm:ss");
395
+ } else {
396
+ time = time.toTime().toStr("yyyy-MM-dd hh:mm:ss");
397
+ }
398
+ var log = {
399
+ customId,
400
+ name,
401
+ phone,
402
+ idcard,
403
+ nfc,
404
+ clientid,
405
+ type,
406
+ person_type,
407
+ record_type,
408
+ time,
409
+ avatar
410
+ }
411
+ $.server.exec_log(clientid, log);
412
+
413
+ _this.send(`mqtt/face/${clientid}`, {
414
+ "messageId": _this.get_msgid('PushAck'),
415
+ "operator": "PushAck",
416
+ "info": {
417
+ "PushAckType": "2",
418
+ "SnapOrRecordID": params.RecordID
419
+ }
420
+ });
421
+ }
422
+
423
+ m["QRCodePush"] = async function(clientid, params, msg, id) {
424
+ var qrcode = params.QRCodeInfo;
425
+ var {
426
+ uuid,
427
+ pass,
428
+ tip,
429
+ device
430
+ } = $.server.exec_qrcode(clientid, qrcode);
431
+ if (device && device.online) {
432
+ await _this.unlock(clientid, uuid, pass, tip);
433
+ }
434
+ }
34
435
  };
@@ -103,9 +103,13 @@ exports.reboot_device = function(clientid) {
103
103
  * @param {String} datetime 日期时间
104
104
  */
105
105
  exports.set_device_time = function(clientid, datetime) {
106
- return this.push("SetSysTime", clientid, {
106
+ var res = this.push("SetSysTime", clientid, {
107
107
  "SysTime": datetime.replace(" ", "T")
108
108
  });
109
+ if (!res || res.result == "ok") {
110
+ return
111
+ }
112
+ return "重置时间失败"
109
113
  }
110
114
 
111
115
  /**
@@ -252,6 +256,7 @@ exports.init = function() {
252
256
  _this.drives[clientid] = {};
253
257
  }
254
258
  _this.drives[clientid].online = 1;
259
+ _this.drives[clientid].time_last = new Date().getTime();
255
260
  console.log("心跳", clientid, _this.drives[clientid]);
256
261
  }
257
262
 
@@ -66,7 +66,7 @@
66
66
  // 协议头
67
67
  "protocol": "mqtt",
68
68
  // MQTT服务器地址
69
- "hostname": "mqtt.laieliantong.com",
69
+ "hostname": "mqtt.aieliantong.com",
70
70
  // "hostname": "127.0.0.1",
71
71
  // MQTT服务器用户名
72
72
  "username": "developer",
@@ -66,7 +66,11 @@ module.exports = function(server, config) {
66
66
  var str = await $.cache.get("ip_" + ip);
67
67
  var json;
68
68
  if (str) {
69
- json = JSON.parse(str);
69
+ if (typeof(str) === "string") {
70
+ json = JSON.parse(str);
71
+ } else {
72
+ json = str;
73
+ }
70
74
  if (json.date !== date) {
71
75
  num = 1;
72
76
  } else {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mm_os",
3
- "version": "2.3.2",
3
+ "version": "2.3.3",
4
4
  "description": "这是超级美眉服务端框架,用于快速构建应用程序。",
5
5
  "main": "index.js",
6
6
  "scripts": {
@@ -44,7 +44,7 @@
44
44
  "mm_machine": "^1.7.4",
45
45
  "mm_mongodb": "^1.4.2",
46
46
  "mm_mqtt": "^1.0.6",
47
- "mm_mysql": "^1.8.0",
47
+ "mm_mysql": "^1.8.1",
48
48
  "mm_redis": "^1.4.2",
49
49
  "mm_ret": "^1.3.9",
50
50
  "mm_session": "^1.4.7",