Browse Source

推送配置搜索

dev
巴林闲侠 2 years ago
parent
commit
8dc209efec
  1. 2
      api/app/lib/controllers/push/config.js
  2. 205
      api/app/lib/schedule/alarms_push.js
  3. 62
      api/app/lib/utils/push.js

2
api/app/lib/controllers/push/config.js

@ -7,7 +7,7 @@ async function list (ctx) {
const sequelize = ctx.fs.dc.ORM;
const { clickHouse } = ctx.app.fs
const { utils: { anxinStrucIdRange, pomsProjectRange } } = ctx.app.fs
const { keyword, keywordTarget, alarmType, state, tactics, pomsProjectId } = ctx.request.body
const { keyword, keywordTarget, alarmType, state, tactics, pomsProjectId } = ctx.query
let findOption = {
where: {

205
api/app/lib/schedule/alarms_push.js

@ -53,11 +53,11 @@ module.exports = function (app, opts) {
for (let { dataValues: c } of configListRes) {
if (c.tacticsParams && c.tactics) {
const { projectCorrelation, strucId, pomsProjectId } = c
const { projectCorrelation, strucId, pomsProjectId, } = c
const { interval, deviceProportion } = c.tacticsParams
if (
curMinOfYear % interval == 0
curMinOfYear % parseInt(interval) == 0
) {
const corPepProject = projectCorrelation.pepProjectId ?
pepProjectRes.find(p => p.id == projectCorrelation.pepProjectId)
@ -69,18 +69,63 @@ module.exports = function (app, opts) {
&& c.timeType.some(ct => ct == corPepProject.construction_status_id)
)
) {
// TODO 查当前 poms 下的结构物 并把不包含的去掉
const { anxinProjectId, pepProjectId } = projectCorrelation
const strucListRes = strucId.length ? await clickHouse.anxinyun.query(`
SELECT id, iota_thing_id, name
FROM t_structure
WHERE id IN (${strucId.join(',')})
`).toPromise() : []
// 查当前 poms 下的结构物 并把不包含的去掉
// 可能有结构物已解绑
const strucListRes = strucId.length && anxinProjectId.length ?
await clickHouse.anxinyun.query(
`
SELECT
DISTINCT id,
t_structure.id AS id,
t_structure.name AS name,
t_structure.iota_thing_id AS iotaThingId
FROM
t_project
LEFT JOIN
t_project_structure
ON t_project_structure.project = t_project.id
LEFT JOIN
t_project_structuregroup
ON t_project_structuregroup.project = t_project.id
LEFT JOIN
t_structuregroup_structure
ON t_structuregroup_structure.structuregroup = t_project_structuregroup.structuregroup
LEFT JOIN
t_project_construction
ON t_project_construction.project = t_project.id
LEFT JOIN
t_structure_site
ON t_structure_site.siteid = t_project_construction.construction
RIGHT JOIN
t_structure
ON t_structure.id = t_project_structure.structure
OR t_structure.id = t_structuregroup_structure.structure
OR t_structure.id = t_structure_site.structid
WHERE
project_state != -1
AND t_project.id IN (${anxinProjectId.join(',')})
AND t_structure.id IN (${strucId.join(',')})
`
).toPromise() :
[]
let searchStrucIds = strucListRes.map(s => s.id)
if (searchStrucIds.length) {
searchStrucIds.unshift(-1)
}
let pepProjectName = pepProjectId ?
pepProjectRes.find(p => p.id == pepProjectId).project_name
: projectCorrelation.name
let emailTitle = `${pepProjectName}-${c.name}-`
let emailSubTitle = ''
let dataAlarmOption = []
let dataAlarmGroupOption = []
let dataAlarms = []
let videoAlarmWhereOption = []
let videoAlarms = []
let appAlarmWhereOption = {
@ -89,17 +134,26 @@ module.exports = function (app, opts) {
let appAlarms = []
let deviceCount = 0
let alarmDeviceCount = 0
let cameraCount = 0
let alarmCameraCount = 0
// 判断推送策略
let pointTime = moment().subtract(interval, 'minute').format('YYYY-MM-DD HH:mm:ss')
let nowTime = moment().startOf('minute')
let pointTime = moment().subtract(parseInt(interval), 'minute').startOf('minute').format('YYYY-MM-DD HH:mm:ss')
if (c.tactics == 'immediately') {
dataAlarmOption.push(`StartTime >= '${pointTime}'`);
appAlarmWhereOption.createTime = { $gte: pointTime }
// dataAlarmOption.push(`StartTime >= '${pointTime}'`);
// appAlarmWhereOption.createTime = { $gte: pointTime }
// videoAlarmWhereOption.push(`camera_status_alarm.create_time >= '${pointTime}'`)
emailTitle += `即时推送服务`
emailSubTitle += `截止${moment(pointTime).format('YYYY年MM月DD日 HH时mm分')}-${moment(nowTime).format('HH时mm分')}`
} else if (c.tactics == 'continue') {
dataAlarmOption.push(`StartTime <= '${pointTime}'`);
appAlarmWhereOption.createTime = { $lte: pointTime }
// dataAlarmOption.push(`StartTime <= '${pointTime}'`);
// appAlarmWhereOption.createTime = { $lte: pointTime }
// videoAlarmWhereOption.push(`camera_status_alarm.create_time <= '${pointTime}'`)
emailTitle += `持续时长推送服务`
emailSubTitle += `告警持续时长超${interval}分钟的告警源,详情如下:`
} else if (c.tactics == 'abnormal_rate') {
dataAlarmOption.push(`StartTime <= '${pointTime}'`);
// dataAlarmOption.push(`StartTime <= '${pointTime}'`);
if (c.alarmType.includes('data_outages') || c.alarmType.includes('data_exception')) {
// 查了设备异常率 去安心云查当前项目下的设备数量
// TODO 等同步以太数据再查
@ -110,15 +164,19 @@ module.exports = function (app, opts) {
}
if (c.alarmType.includes('video_exception')) {
// 查了视频异常 去安心云查 接入的 萤石 设备数量
cameraCount = strucId.length ?
cameraCount = searchStrucIds.length ?
(await clickHouse.anxinyun.query(`
SELECT count(*) AS count FROM t_video_ipc
WHERE structure IN (${strucId.join(',')})
WHERE structure IN (${searchStrucIds.join(',')})
`).toPromise())[0].count
: 0
}
appAlarmWhereOption.createTime = { $lte: pointTime }
// appAlarmWhereOption.createTime = { $lte: pointTime }
// videoAlarmWhereOption.push(`camera_status_alarm.create_time <= '${pointTime}'`)
emailTitle += `异常率推送服务`
emailSubTitle += `持续产生时间超过${interval}分钟的异常设备数量${interval}个,异常率达到项目或结构物内设备总数量${deviceCount + cameraCount}个的${interval}%,详情如下`
}
emailTitle += '——POMS飞尚运维中台'
// 判断告警数据范围
if (c.alarmType.includes('data_outages')) {
@ -131,7 +189,7 @@ module.exports = function (app, opts) {
dataAlarmGroupOption.push(3)
}
if (c.alarmType.includes('video_exception')) {
videoAlarms = strucId.length ? await clickHouse.vcmp.query(
videoAlarms = searchStrucIds.length ? await clickHouse.vcmp.query(
`
SELECT
cameraAlarm.cameraId AS cameraId,
@ -167,13 +225,15 @@ module.exports = function (app, opts) {
INNER JOIN ${anxinyun}.t_video_ipc
ON toString(${anxinyun}.t_video_ipc.channel_no) = camera_status_alarm.channel_no
AND ${anxinyun}.t_video_ipc.serial_no = camera_status_alarm.serial_no
AND ${anxinyun}.t_video_ipc.structure IN (${strucId.join(',')})
AND ${anxinyun}.t_video_ipc.structure IN (${searchStrucIds.join(',')})
INNER JOIN camera
ON camera.serial_no = camera_status_alarm.serial_no
AND camera.channel_no = camera_status_alarm.channel_no
AND camera.delete = false
AND camera.recycle_time is null
WHERE camera_status_alarm.confirm_time IS null
WHERE
camera_status_alarm.confirm_time IS null
${videoAlarmWhereOption.length ? ` AND ${videoAlarmWhereOption.join(' AND ')}` : ''}
) AS cameraAlarm
LEFT JOIN camera_status
ON cameraAlarm.platform = camera_status.platform
@ -186,7 +246,7 @@ module.exports = function (app, opts) {
AND anxinIpc.serial_no = cameraAlarm.cameraSerialNo
LEFT JOIN ${anxinyun}.t_structure AS anxinStruc
ON anxinStruc.id = anxinIpc.structure
AND anxinStruc.id IN (${strucId.join(',')})
AND anxinStruc.id IN (${searchStrucIds.join(',')})
LEFT JOIN ${anxinyun}.t_video_ipc_station AS anxinIpcStation
ON anxinIpcStation.ipc = anxinIpc.id
LEFT JOIN ${anxinyun}.t_sensor AS anxinStation
@ -275,21 +335,120 @@ module.exports = function (app, opts) {
dataAlarmGroupOption.push(4)
dataAlarmGroupOption.push(5)
}
//
if (dataAlarmGroupOption.length) {
// 查数据告警 三警合一
if (dataAlarmGroupOption.length && searchStrucIds.length) {
dataAlarmGroupOption.push(-1)
dataAlarmOption.push(`AlarmGroup IN (${dataAlarmGroupOption.join(',')})`)
dataAlarms = await clickHouse.dataAlarm.query(`
SELECT * FROM alarms
WHERE
State NOT IN (3, 4)
AND StructureId IN (${searchStrucIds.join(',')})
${dataAlarmOption.length ? ' AND ' + dataAlarmOption.join(' AND ') : ''}
`).toPromise()
console.log(dataAlarms);
}
let dataAlarmTitle = [{
n: '项目',
k: '',
v: pepProjectName
}, {
n: '结构物',
k: '',
f: (d) => {
return (strucListRes.find(s => s.id == d.StructureId) || {}).name
}
}, {
n: '告警源名称',
k: 'SourceName'
}, {
n: '告警源类型',
k: '',
f: (d) => {
switch (d.SourceTypeId) {
case 0:
return 'DTU'
case 1:
return '传感器'
case 2:
return '测点'
default:
return ''
}
}
}, {
n: '告警信息',
k: 'AlarmContent'
}, {
n: '告警等级(当前)',
k: '',
f: (d) => {
switch (d.CurrentLevel) {
case 1:
return '一级'
case 2:
return '二级'
case 3:
return '三级'
default:
return ''
}
}
}, {
n: '持续时间',
k: '',
f: (d) => {
return d.StartTime ?
'超过' + moment().diff(moment(d.StartTime), 'minutes') + '分钟' : ''
}
},]
let html = ''
let tableTitlePostfix = ',详情如下:'
function packageTableTitle (tArr) {
}
if (c.alarmType.includes('data_outages')) {
let tableTitlePrefix = '数据中断告警源'
let newAddCount = 0
let alarmHtml = ''
if (c.tactics == 'immediately') {
for (let a of dataAlarms.filter(d => d.AlarmGroup == 1)) {
alarmHtml += 1
}
tableTitlePrefix += 1
} else if (c.tactics == 'continue') {
} else if (c.tactics == 'abnormal_rate') {
}
}
if (c.alarmType.includes('data_exception')) {
}
if (c.alarmType.includes('strategy_hit')) {
}
if (c.alarmType.includes('video_exception')) {
}
if (c.alarmType.includes('app_exception')) {
}
if (c.alarmType.includes('device_exception')) {
}
await pushByEmail({
email: ['1650192445@qq.com'],
title: emailTitle,
text: '',
html: ''
})
}
}
}
}

62
api/app/lib/utils/push.js

@ -0,0 +1,62 @@
'use strict';
const moment = require('moment')
const Core = require('@alicloud/pop-core');
const nodemailer = require('nodemailer')
module.exports = function (app, opts) {
const pushBySms = async ({ phone = [], templateCode, templateParam } = {}) => {
try {
if (phone.length) {
const client = new Core({
accessKeyId: opts.sms.accessKey,
accessKeySecret: opts.sms.accessSecret,
endpoint: 'http://dysmsapi.aliyuncs.com',//固定
apiVersion: '2017-05-25'//固定
});
const SendSmsRes = await client.request('SendSms', {
"PhoneNumbers": phone.join(','),//接收短信的手机号码。
"SignName": "飞尚尚视",//短信签名名称。必须是已添加、并通过审核的短信签名。
"TemplateCode": templateCode,//短信模板ID。必须是已添加、并通过审核的短信签名;且发送国际/港澳台消息时,请使用国际/港澳台短信模版。
"TemplateParam": JSON.stringify(templateParam)//短信模板变量对应的实际值,JSON格式。
}, {
method: 'POST'
});
return SendSmsRes
}
} catch (error) {
throw error
}
}
const pushByEmail = async ({ email = [], title, text = '', html = '', attachments = undefined, } = {}) => {
try {
let transporter = nodemailer.createTransport({
host: opts.email.host,
port: opts.email.port,
secure: true,
auth: {
user: opts.email.sender.address,
pass: opts.email.sender.password,
}
});
// send mail with defined transport object
await transporter.sendMail({
from: `${opts.email.sender.name}<${opts.email.sender.address}>`, // sender address
to: email.join(','), // list of receivers 逗号分隔字符串
subject: title, // Subject line
text: text, // plain text body
html: html, // html body
attachments: attachments
});
} catch (error) {
throw error
}
}
return {
pushByEmail,
pushBySms,
}
}
Loading…
Cancel
Save