const moment = require('moment') module.exports = function (app, opts) { const cameraOnlinePush = app.fs.scheduleInit( { interval: '0 */15 * * * *', // interval: '* */1 * * * *', // interval: '*/5 * * * * *', immediate: false, proRun: true, }, async () => { try { const { models, ORM: sequelize } = app.fs.dc const { pushBySms, pushByEmail } = app.fs.utils const configRes = await models.CameraStatusPushConfig.findAll({ where: { forbidden: false }, include: [ { model: models.CameraStatusPushMonitor, attributes: ['cameraId'], required: false, duplicating: true }, { model: models.CameraStatusPushReceiver, attributes: ['receiver'], duplicating: false, required: false, }, ], }) const timeNow = moment().startOf('minute').format() for (let c of configRes) { console.log('上下线推送方式', c.pushWay,); // 查配置信息所对应的摄像头15min内的在离线状态 const cameraIds = c.cameraStatusPushMonitors.map(m => m.cameraId) const offlineStatusRes = await models.CameraStatusOfflineLog.findAll({ where: { cameraId: { $in: cameraIds }, // !!! 時間限制 time: { $between: [moment(timeNow).subtract(15, 'minutes').format(), timeNow] } }, include: [{ model: models.Camera, attributes: ['name'] }], order: [['time', 'ASC']], }) console.log('上下线推送路线记录', offlineStatusRes); if (offlineStatusRes.length) { const cameraStatusMap = {} // 当前逻辑 // 只要最后状态是离线 就做离线推送 // 只要出现一次上线 就做上线推送 for (let s of offlineStatusRes) { if (cameraStatusMap[s.cameraId]) { cameraStatusMap[s.cameraId].status.push({ status: s.status, time: s.time, }) } else { cameraStatusMap[s.cameraId] = { status: [{ status: s.status, time: s.time, }], cameraId: s.cameraId, name: s.camera.name, } } } let offArr = [] let onArr = [] for (let k of Object.keys(cameraStatusMap).sort()) { const data = cameraStatusMap[k] if (data.status[0].status == 'OFF') { offArr.push({ cameraId: data.cameraId, name: data.name, time: data.status[0].time, }) } const onLineIndex = data.status.findIndex(s => s.status == 'ON') if (onLineIndex >= 0) { const onLineLastOffIndex = data.status.findIndex((s, i) => s.status == 'OFF' && i > onLineIndex) // 当前在线记录的上一次离线记录 let onlineData = { cameraId: data.cameraId, name: data.name, time: data.status[onLineIndex].time, } if (onLineLastOffIndex >= 0) { onlineData.offTime = data.status[onLineLastOffIndex].time } onArr.push(onlineData) } } // 查当前配置由谁配置 const corUser = await app.fs.authRequest.get(`user/${c.createUser}/message`, { query: { // TODO 这里拿不到 token 去鉴权 怎么能系统间鉴权呢 // 暂时取消了鉴权系统对这里的判断 token: '' } }) const receiver = c.cameraStatusPushReceivers.map(r => r.receiver) const logData = { pushConfigId: c.id, receiver: receiver, timing: c.timing, time: moment(timeNow).format(), pushWay: c.pushWay, // camera: cameraIds, } // 离线推送 console.log('上下线推送数据', offArr, onArr); console.log('上下线推送接收', receiver); if (offArr.length && c.noticeWay && c.noticeWay.includes('offline') && receiver.length) { if (c.pushWay == 'email') { // 邮件 let text = `【${corUser[0].username}】账号下的设备,截止【${moment(timeNow).format('MM月DD日 HH时mm分')}】,有${offArr.length}个设备掉线:\n` text += offArr.map(o => `【${o.name}】于【${moment(o.time).format('MM月DD日 HH时mm分')}】掉线,`).join('\n') text += `\n请及时处理!` await pushByEmail({ email: receiver, title: '尚视设备离线通知', text, }) await models.CameraStatusPushLog.create({ ...logData, pushWay: 'email', noticeWay: ['offline'], camera: offArr.map(o => o.cameraId) }) } else if (c.pushWay == 'phone') { // 短信 let templateParam = { name: `【${corUser[0].username}】`, } let useTempCode = 'SMS_248205074' // let text = `【${corUser[0].username}】账号下的` if (offArr.length == 1) { // text += `【${offArr[0].name}】离线,请及时处理!【${moment(offArr[0].time).format('MM月DD日 HH时mm分')}】` templateParam.deviceName = `【${offArr[0].name}】` templateParam.timeRange = moment(offArr[0].time).format('MM月DD日 HH时mm分') } else { let text = '' text += offArr.map(o => `【${o.name}】`).join('') if (text.length > 35) { text = text.substring(0, 35) + '...' // text += `等${offArr.length}个摄像头离线` templateParam.deviceCount = offArr.length useTempCode = 'SMS_248250074' } templateParam.deviceName = text // text += `,请及时处理!【${moment().format('MM月DD日HH时mm分')}-${moment(timeNow).subtract(15, 'minutes').format('MM月DD日HH时mm分')}】` templateParam.timeRange = `【${moment().format('MM月DD日HH时mm分')} -${moment(timeNow).subtract(15, 'minutes').format('MM月DD日HH时mm分')}】` } await pushBySms({ phone: receiver, templateCode: useTempCode, templateParam: templateParam, }) await models.CameraStatusPushLog.create({ ...logData, pushWay: 'phone', noticeWay: ['offline'], camera: offArr.map(o => o.cameraId) }) } } // 上线推送 if (onArr.length && c.noticeWay && c.noticeWay.includes('online') && receiver.length) { if (c.pushWay == 'email') { // 邮件 const outTimeCameraOff = onArr.filter(a => !a.offTime) if (outTimeCameraOff.length) { let cameraIds = outTimeCameraOff.map(a => a.cameraId) const lastOfflineRes = await models.CameraStatusOfflineLog.findAll({ where: { cameraId: { $in: cameraIds }, status: 'OFF', time: { $lt: moment(timeNow).subtract(15, 'minutes').format() } }, group: ['cameraId'], attributes: ['cameraId', [sequelize.fn('max', sequelize.col('time')), 'time']], }) for (let a of onArr) { if (!a.offTime) { const lastOffline = lastOfflineRes.find(l => l.cameraId == a.cameraId) if (lastOffline) { a.offTime = lastOffline.time } } } } let text = `【${corUser[0].username}】账号下的设备:\n` text += onArr.map(o => `【${o.name}】于【${moment(o.offTime).format('MM月DD日HH时mm分')}】掉线,【${moment(o.time).format('MM月DD日HH时mm分')}】已恢复`).join('\n') await pushByEmail({ email: receiver, title: '尚视设备上线通知', text, }) await models.CameraStatusPushLog.create({ ...logData, pushWay: 'email', noticeWay: ['online'], camera: onArr.map(o => o.cameraId) }) } else if (c.pushWay == 'phone') { // 短信 // let text = `【${corUser[0].username}】账号下的` let templateParam = { name: `【${corUser[0].username}】`, } let useTempCode = 'SMS_248250073' if (onArr.length == 1) { // text += `【${onArr[0].name}】已恢复上线,请及时处理!【${moment(onArr[0].time).format('MM月DD日 HH时mm分')}】` templateParam.deviceName = `【${onArr[0].name}】` templateParam.date = moment(onArr[0].time).format('MM月DD日 HH时mm分') } else { let text = '' text += onArr.map(o => `【${o.name}】`).join('') let timeRange = `【${moment().format('MM月DD日HH时mm分')}-${moment(timeNow).subtract(15, 'minutes').format('MM月DD日HH时mm分')}】!` if (text.length > 35) { text = text.substring(0, 35) + '...' // text += `等${onArr.length}个摄像头已恢复上线!` templateParam.deviceCount = onArr.length useTempCode = 'SMS_248120080' templateParam.timeRange = timeRange } else { templateParam.date = timeRange } templateParam.deviceName = text } await pushBySms({ phone: receiver, templateCode: useTempCode, templateParam: templateParam, }) await models.CameraStatusPushLog.create({ ...logData, pushWay: 'phone', noticeWay: ['online'], camera: onArr.map(o => o.cameraId) }) } } } } } catch (error) { console.error('15min 上下线推送错误:', error); } } ) // 摄像头离线定时统计推送 const cameraOnlineTimingPush = app.fs.scheduleInit( { interval: '0 */5 * * * *', // interval: '*/10 * * * * *', // dev immediate: false, // immediate: true, // dev proRun: true, }, async () => { try { const { models, ORM: sequelize } = app.fs.dc const { pushBySms, pushByEmail } = app.fs.utils const timeNow = moment().format() const configRes = await models.CameraStatusPushConfig.findAll({ where: { forbidden: false, noticeWay: { $contains: ['timing'] }, // !!! 此时此刻 timing: moment(timeNow).format('HH:mm') }, include: [ { model: models.CameraStatusPushMonitor, attributes: ['cameraId'], required: false, duplicating: true }, { model: models.CameraStatusPushReceiver, attributes: ['receiver'], duplicating: false, required: false, }, ], }) for (let c of configRes) { // 查配置信息所对应的摄像头15min内的在离线状态 const cameraIds = c.cameraStatusPushMonitors.map(m => m.cameraId) const offlineRes = await models.Camera.findAll({ where: { id: { $in: cameraIds }, }, attributes: ['id', 'name'], include: [{ model: models.GbCamera, attributes: ['id', 'online'], required: true, where: { online: 'OFF' } }], }) if (offlineRes.length) { // 查当前配置由谁配置 const corUser = await app.fs.authRequest.get(`user/${c.createUser}/message`, { query: { token: '' } }) const receiver = c.cameraStatusPushReceivers.map(r => r.receiver) if (receiver.length) { const logData = { pushConfigId: c.id, receiver: receiver, timing: c.timing, time: moment(timeNow).format(), pushWay: c.pushWay, camera: offlineRes.map(o => o.id), } if (c.pushWay == 'email') { // 邮件 const offlineTimeRes = await models.CameraStatusOfflineLog.findAll({ attributes: ['cameraId', [sequelize.fn('max', sequelize.col('time')), 'time']], where: { cameraId: { $in: offlineRes.map(oc => oc.id) }, status: 'OFF', }, group: ['cameraId'], }) if (offlineTimeRes.length) { let text = `【${corUser[0].username}】账号下的设备,截止${moment(timeNow).format('MM月DD日 HH时mm分')},有${offlineRes.length}个设备掉线:\n` text += offlineTimeRes.map(o => { let corCamera = offlineRes.find(c => c.id == o.cameraId) if (corCamera) { return `【${(corCamera || {}).name}】于【${moment(o.time).format('MM月DD日 HH时mm分')}】掉线,` } return '' }).join('\n') text += `\n请及时处理!` await pushByEmail({ email: receiver, title: '尚视设备离线定时统计通知', text, }) await models.CameraStatusPushLog.create({ ...logData, pushWay: 'email', noticeWay: ['timing'] }) } } else if (c.pushWay == 'phone') { // 短信 // let text = `【${corUser[0].username}】账号下截止${moment(timeNow).format('YYYY年MM月DD日 HH时')},有${offlineRes.length}个设备掉线,请及时处理!` await pushBySms({ phone: receiver, templateCode: 'SMS_248095009', templateParam: { name: corUser[0].username, time: moment(timeNow).format('YYYY年MM月DD日 HH时'), deviceCount: offlineRes.length, }, }) await models.CameraStatusPushLog.create({ ...logData, pushWay: 'phone', noticeWay: ['timing'] }) } } } } } catch (error) { console.error(error); } } ) return { cameraOnlinePush, cameraOnlineTimingPush, } }