UNPKG

mm_os

Version:

MM_OS服务端架构,用于快速构建应用程序,支持网站建设、小程序后台、AI应用、物联网(IOT/AIOT)、游戏服务端等多种场景。

723 lines (670 loc) 18 kB
/** * 查询个人记录 * @param {string} clientid 客户端ID * @param {object} param 查询参数 * @returns {object} 执行结果 */ exports.getLog = async function(clientid, param) { var res = await this.push('GetRecordsByPicOrID', clientid, param); return res; }; /** * 考勤打卡 * @param {string} clientid 客户端ID * @param {object} uuid 用户唯一标识 * @param {string} avatar base64头像 * @returns {object} 执行结果 */ exports.signIn = async function(clientid, uuid, avatar) { var res = await this.push('PullRecordOnlyPic', clientid, { 'personID': uuid, 'picinfo': avatar }); if (!res || res.result == 'fail') { return '打卡失败!'; } }; /** * 下发二维码(没用到) * @param {string} clientid 客户端ID * @param {object} param 二维码参数 * @returns {object} 执行结果 */ exports.pushQrcode = function(clientid, param) { return this.push('ShowQRCode', clientid, param); }; /** * 以图搜人 * @param {string} clientid 客户端ID * @param {object} avatar 人脸照片 * @returns {object} 执行结果 */ exports.getMemberPic = async function(clientid, avatar) { var res = await this.push('GetPictureSearch', clientid, { 'facesluiceId': clientid, 'MaxSimilarity': 80, 'MaxNum': 1, 'picinfo': avatar }); var user; if (res) { if (res.result == 'fail') { } else { var u = res.SearchInfo[0]; var name = u.name || u.persionName; var custom_id = u.customId.trim(); var phone = (u.telnum || '').trim(); var idcard = (u.idCard || '').trim(); user = { name, custom_id, phone, idcard }; } } return user; }; /** * 远程开门 * @param {string} clientid 客户端ID * @param {string} uuid 用户唯一标识 * @param {boolean} pass 是否可通行 true为是 * @param {string} tip 提示信息 * @returns {object} 执行结果 */ exports.unlock = async function(clientid, uuid = '0', pass = false, tip = '没有访问权限') { var res = await this.push('Unlock', clientid, { 'uid': uuid, // 0不开门,1开门 'openDoor': pass ? '1' : '0', 'showInfo': tip }); if (!res || res.result == 'fail') { return '非内部人员!'; } }; /** * 远程锁门(没用到) * @param {string} clientid 客户端ID * @param {string} uuid 用户唯一标识 * @param {boolean} pass 是否可通行 true为是 * @param {string} tip 提示信息 * @returns {object} 执行结果 */ exports.lock = async function(clientid, uuid = '0', pass = false, tip = '没有访问权限') { var res = await this.push('Lock', clientid, { 'uid': uuid, 'showInfo': tip }); if (!res || res.result == 'fail') { return '已锁门!'; } }; /** * 删除成员 * @param {string} clientid 客户端ID * @param {string} uuid 用户唯一标识 * @returns {object} 执行结果 */ exports.delMember = async function(clientid, uuid) { var res = await this.push('DeletePersons', clientid, { 'customId': uuid }); return res; }; /** * 批量删除成员 * @param {string} clientid 客户端ID * @param {object} arr 成员列表 * @param {number} longtime 超时回馈 * @returns {object} 执行结果 */ exports.delMemberBatch = async function(clientid, arr, longtime) { var res = await this.push('DeletePersons', clientid, { begin: 'BeginFlag', end: 'EndFlag', person_num: arr.length.toString(), customId: arr }, longtime); var result; var error = 0; var success = 0; var error_info = []; var success_info = []; if (res) { if (res.result == 'ok') { var now = new Date().toStr('yyyy-MM-dd hh:mm:ss'); error = number(res.DelErrNum); success = number(res.DelSucNum); error_info = res.DelErrInfo.map((o) => { o.time_create = now; return o; }); success_info = res.DelSucInfo.map((o) => { o.time_create = now; return o; }); result = res.result; } else if (res.detail && res.detail.indexOf('busy') === -1) { result = 'fail'; } } return { error, success, error_info, success_info, result }; return; }; /** * 重启设备 * @param {string} clientid 设备sn * @returns {object} 执行结果 */ exports.rebootDevice = async function(clientid) { var res = await this.push('RebootDevice', clientid, {}); if (!res || res.result == 'ok') { return; } return '重启设备失败'; }; /** * 设置设备时间 * @param {string} clientid 设备sn * @param {string} datetime 日期时间 格式为yyyy-MM-dd hh:mm:ss * @returns {object} 执行结果 */ exports.setDeviceTime = async function(clientid, datetime) { var res = await this.push('SetSysTime', clientid, { 'SysTime': datetime.replace(' ', 'T') }); if (!res || res.result == 'ok') { return; } return '重置时间失败'; }; /** * 恢复出厂设置 * @param {string} clientid 设备sn * @param {boolean} record 是否恢复控制记录,true为恢复 * @param {boolean} member 是否恢复成员,true为恢复 * @param {boolean} log 是否恢复请求日志,true为恢复 * @returns {object} 执行结果 */ exports.resetDevice = async function(clientid, record = true, member = false, log = true) { var res = await this.push('SetFactoryDefault', clientid, { defalt_record: record ? '1' : '0', defalt_person: member ? '1' : '0', defalt_log: log ? '1' : '0' }); if (!res || res.result == 'ok') { return; } return '恢复出厂设置失败'; }; /** * 查询下发进度 * @param {string} clientid 设备sn * @param {string} mode 查询方式 默认为更新 * @returns {object} 执行结果 */ exports.getProgress = async function(clientid, mode = 'update') { var type = ''; if (mode == 'update') { type = 'EditPersonsNew'; } else { type = 'DeletePersons'; } var res = await this.push('QueryProgress', clientid, { 'QueryType': type }); if (res) { if (res.Status !== '0') { return 1; } else { return 0; } } return -1; }; /** * 考勤补卡 * @param {string} clientid 设备sn * @param {string} uuid 用户唯一标识 * @param {string} time 时间 * @param {string} avatar 头像 * @returns {object} 执行结果 */ exports.replacement = async function(clientid, uuid, time, avatar) { var res = await this.push('PullRecordOnlyPic', clientid, { 'personID': uuid, 'time': time, 'picinfo': avatar }); if (!res || res.result == 'fail') { return '补卡失败!'; } return; }; /** * 查询人员名单 * @param {string} clientid 客户端ID * @param {number} longtime 超时回馈 * @returns {object} 执行结果 */ exports.getMember = function(clientid, longtime = 0) { return this.push('QueryPerson', clientid, longtime); }; /** * 查询人员名单 * @param {string} clientid 客户端ID * @param {string} uuid 用户唯一标识 * @param {number} longtime 超时回馈 * @returns {object} 人员信息 */ exports.getMemberOne = function(clientid, uuid, longtime = 0) { return this.push('QueryPerson', clientid, { 'personId': uuid }, longtime); }; /** * 格式化时间 * @param {*} time 时间值 * @returns {string} 格式化后的时间字符串 */ exports._formatTime = function(time) { if (typeof(time) == 'object') { return time.toStr('yyyy-MM-dd hh:mm:ss'); } else { return time.toTime().toStr('yyyy-MM-dd hh:mm:ss'); } }; /** * 检查时间有效性 * @param {*} time_end 结束时间 * @returns {boolean} 是否有效 */ exports._isTimeValid = function(time_end) { if (!time_end) { return false; } var end_time = time_end.toTime(); return end_time > '2021-01-01 00:00:00'.toTime() && end_time <= '2038-01-01 00:00:00'.toTime(); }; /** * 设置时间有效性 * @param {object} obj 目标对象 * @param {object} m 成员对象 * @returns {object} 修改后的对象 */ exports._setTimeValidity = function(obj, m) { var result = { ...obj }; if (this._isTimeValid(m.time_valid_end)) { result.cardValidBegin = this._formatTime(m.time_valid_start); result.cardValidEnd = this._formatTime(m.time_valid_end); result.tempCardType = 1; } else { result.tempCardType = 0; } return result; }; /** * 创建基础成员对象 * @param {object} m 原始的成员对象 * @returns {object} 基础成员对象 */ exports._createBaseMember = function(m) { var nfc = m.nfc || ''; return { 'customId': m.customId, 'name': m.name, 'native': m.place || '', 'nation': m.nation || '', 'address': m.address || '', 'idCard': m.idcard || '', 'gender': m.sex - 1, 'phone': m.phone, 'birthday': m.birthday, 'cardType2': 2, 'cardNum2': nfc, 'RFCardMode': 0, 'RFIDCard': nfc, 'notes': '', 'personType': m.state == 4 ? 1 : 0, 'cardType': 0, 'picURI': this.fullUrl(m.avatar) }; }; /** * 成员模型 * @param {object} m 原始的成员对象 * @returns {object} 转换后的成员对象 */ exports.memberModelOut = function(m) { var obj = this._createBaseMember(m); this._setTimeValidity(obj, m); return obj; }; /** * 添加时间戳到信息列表 * @param {Array} list 信息列表 * @param {string} now 当前时间 * @returns {Array} 处理后的列表 */ exports._addTimeToList = function(list, now) { return list.map((o) => { o.time_create = now; return o; }); }; /** * 解析批量操作结果 * @param {object} res 响应结果 * @returns {object} 解析后的结果 */ exports._parseBatch = function(res) { var result; var error = 0; var success = 0; var error_info = []; var success_info = []; if (res) { if (res.result == 'ok') { var now = new Date().toStr('yyyy-MM-dd hh:mm:ss'); error = number(res.AddErrNum); success = number(res.AddSucNum); error_info = this._addTimeToList(res.AddErrInfo, now); success_info = this._addTimeToList(res.AddSucInfo, now); result = res.result; } else if (res.detail && res.detail.indexOf('busy') === -1) { result = 'fail'; } } return { error, success, error_info, success_info, result }; }; /** * 批量下发人员名单 * @param {string} clientid 客户端ID * @param {Array} list 人员名单 * @param {number} longtime 超时回馈 * @returns {object} 执行结果 */ exports.updateMemberBatch = async function(clientid, list, longtime = 180) { var res = await this.pushS(clientid, { 'messageId': this.getMsgid('EditPersonsNew'), 'DataBegin': 'BeginFlag', 'DataEnd': 'EndFlag', 'operator': 'EditPersonsNew', 'PersonNum': list.length, 'info': list.map((o) => { return this.memberModelOut(o); }) }, longtime); return this._parseBatch(res); }; /** * 下发人员名单 * @param {string} clientid 设备ID * @param {object} user 人员信息 * @param {number} longtime 超时回馈 * @returns {object} 执行结果 */ exports.updateMember = function(clientid, user, longtime = 0) { return this.pushS(clientid, { 'messageId': this.getMsgid('EditPerson'), 'DataBegin': 'BeginFlag', 'DataEnd': 'EndFlag', 'method': 'EditPerson', 'info': this.memberModelOut(user) }, longtime); }; /** * 初始化函数, 用于定义开放给前端的函数 */ exports.init = function() { var m = this.methods; _regBasicMethods(m, this); _regDeviceMethods(m, this); _regRecordMethods(m, this); }; /** * 注册基本方法 * @param {object} m 方法对象 * @param {object} self 实例 * @private */ var _regBasicMethods = function(m, self) { m['HeartBeat'] = function(clientid, params) { if (!self.drives[clientid]) { self.drives[clientid] = {}; } self.drives[clientid].online = 1; self.drives[clientid].time_last = new Date().getTime(); // console.log("心跳", clientid, self.drives[clientid]); }; /** * 离线通知 * @param {string} clientid 设备sn * @param {object} params 设备信息 */ m['Offline'] = async function(clientid, params) { self.updateOnline(clientid, 0); // console.log("离线", clientid, self.drives[clientid]); }; /** * 在线通知 * @param {string} clientid 设备sn * @param {object} params 设备信息 * @returns {object} 执行结果 */ m['Online'] = async function(clientid, params) { await self.updateOnline(clientid, 1, params.ip); return { 'facesluiceId': clientid, 'result': 'ok', 'detail': '' }; }; }; /** * 注册设备方法 * @param {object} m 方法对象 * @param {object} self 实例 * @private */ var _regDeviceMethods = function(m, self) { /** * 更新人体生命体征,如温度、湿度、位置、 * @param {string} clientid 设备sn * @param {object} params 设备信息 */ m['life'] = async function(clientid, params) { self.updateLife(clientid, { // 心率 heart_rate: 0, // 睡眠状态 是深度睡眠还是浅睡眠 sleep: 0, // 血氧饱和度 oxygen: 0, // 行走步数 step: 0, // 压力 pressure: 0, // 时间戳 timestamp: 0, // GPS横坐标,保留生命体脱下设备时的最后位置 gps_x: 0, // GPS纵坐标,保留生命体脱下设备时的最后位置 gps_y: 0 }); // console.log("离线", clientid, _this.drives[clientid]); }; /** * 更新设备信息,如温度、湿度、位置 * @param {string} clientid 设备sn * @param {object} params 设备信息 */ m['info'] = async function(clientid, params) { self.updateDeviceInfo(clientid, { // 温度 temperature: 0, // 湿度 humidity: 0, // 氧气 oxygen: 0, // 二氧化碳 carbon_dioxide: 0, // 光照强度 light: 0, // 烟雾浓度 smoke: 0, // 压力 pressure: 0, // 光敏 photosensitive: 0, // 声波 acoustic_wave: 0, // 磁力 magnetism: 0, // 火焰 flame: 0, // 震动 vibrate: 0, // 时间戳 timestamp: 0, // GPS横坐标 gps_x: 0, // GPS纵坐标 gps_y: 0 }); // console.log("离线", clientid, _this.drives[clientid]); }; }; /** * 获取记录类型 * @param {string} otype 操作类型 * @returns {number} 记录类型 * @private */ var _getRecordType = function(otype) { var typeMap = { '7': 2, '27': 2, '47': 3, '48': 3, '55': 3, '56': 3, '57': 3, '21': 4, '22': 4, '24': 4, '25': 4 }; return typeMap[otype] || 1; }; /** * 发送确认消息 * @param {string} clientid 设备sn * @param {string} record_id 记录ID * @param {object} self 实例 * @private */ var _sendAck = function(clientid, record_id, self) { self.send(`mqtt/face/${clientid}`, { 'messageId': self.getMsgid('PushAck'), 'operator': 'PushAck', 'info': { 'PushAckType': '2', 'SnapOrRecordID': record_id } }); }; /** * 获取 NFC * @param {object} params 上报参数 * @returns {string} NFC * @private */ var _getNfc = function(params) { var nfc = (params.cardNum2 || params.RFIDCard || '').trim(); return nfc == '0' ? '' : nfc; }; /** * 格式化时间 * @param {string|object} time 时间 * @returns {string} 格式化后的时间 * @private */ var _formatTime = function(time) { if (typeof(time) == 'object') { return time.toStr('yyyy-MM-dd hh:mm:ss'); } return time.toTime().toStr('yyyy-MM-dd hh:mm:ss'); }; /** * 创建日志对象 * @param {object} params 上报参数 * @param {string} clientid 设备sn * @param {number} type 记录类型 * @returns {object} 日志对象 * @private */ var _createLog = function(params, clientid, type) { var name = params.persionName || params.name; if (!name) { return null; } return { custom_id: params.customId.trim(), name, phone: (params.telnum || '').trim(), idcard: (params.idCard || '').trim(), nfc: _getNfc(params), clientid, type, person_type: params.PersonType == '1' ? 2 : 1, record_type: params.RecordType ? number(params.RecordType) + 1 : 1, action: '刷脸验证', time: _formatTime(params.time), avatar: params.pic || '' }; }; /** * 注册记录方法 * @param {object} m 方法对象 * @param {object} self 实例 * @private */ var _regRecordMethods = function(m, self) { /** * 上报 * @param {string} clientid 设备sn * @param {object} params 上报参数 * @param {object} msg 上报消息 * @param {string} id 消息ID */ m['RecPush'] = async function(clientid, params, msg, id) { _sendAck(clientid, params.RecordID, self); var type = _getRecordType(params.otype); if (type == 2) { return; } var log = _createLog(params, clientid, type); if (log) { $.server.execLog(clientid, log); } }; m['QRCodePush'] = async function(clientid, params, msg, id) { var qrcode = params.QRCodeInfo; var { uuid, pass, tip, device } = await $.server.execQrcode(clientid, qrcode); if (device && device.online) { await self.unlock(clientid, uuid, pass, tip); } }; };