import moment from 'moment'; import { getDeviceRealData, getDeviceRealDataByTime, queryFormCurrentData, queryFormHistoryData, } from '@/services/ProjectAdmin'; const computePrefixExpression = (function() { var s1 = [], result; return function(prefixExpression) { s1.length = 0; //计算 while (prefixExpression.length > 0) { var o = prefixExpression.shift(); if (operator_map.indexOf(o) == -1) { s1.push(Number(o)); } else { switch (o) { case '+': { result = s1.pop() + s1.pop(); break; } case '-': { result = s1.pop() - s1.pop(); break; } case '*': { result = s1.pop() * s1.pop(); break; } case '/': { result = s1.pop() / s1.pop(); break; } } s1.push(result); } } return s1[0]; }; })(); export async function getOptions(values, datas, formula, projectId) { let allDatas = getAllParams(datas, formula); let optionsData = getOptionsData(datas, formula, values); // 请求接口 const { plcData, formData } = await queryData(values, allDatas, projectId); optionsData = optionsData.map(item => { const paramsInfo = item.paramsInfo; let res; if (paramsInfo.data_type == 0) { // plc数据 res = findPlcData(paramsInfo, plcData, values.timeType); } else if (paramsInfo.data_type == 1) { // form数据 res = findFormData(paramsInfo, formData, values.timeType); } else if (paramsInfo.data_type == 2) { // 获取公式的值 res = getFormulaData(item.paramsInfo, plcData, formData, values.timeType); } return { ...item, ...res }; }); return { ...values, data: optionsData, }; } // 根据表单的数据项获取请求参数 function getFormParams(datas, projectId) { let params = {}; datas.forEach(item => { if (!params[item.data_name]) params[item.data_name] = []; params[item.data_name].push(item.data_title); }); return Object.keys(params).map(data_name => ({ formName: data_name, titles: params[data_name], projectId, })); } async function queryData(values, datas, projectId) { let plcDatas = [], formDatas = []; datas.forEach(item => { if (item.data_type == 0) { plcDatas.push(item); } else { formDatas.push(item); } }); // 根据params获取form的数据 var formData = await getFormData(values, formDatas, projectId); var plcData = await getPlcData(values, plcDatas); if (values.timeType) { // 获得时间轴全集 let times = getTimes(plcData[0]?.data, formData[0]?.data); // 根据时间全集补填数据 formatData(plcData, times); formatData(formData, times); } return { plcData, formData, }; } // 根据时间进行格式化数据 function formatData(datas, times) { datas.forEach(item => { // 默认数据 let newItemData = []; let i = 0; times.forEach(t => { if (item.data[i]?.htime != t) { // 空缺时间要补0 newItemData.push({ htime: t, val: 0, }); } else { newItemData.push(item.data[i]); i++; } }); // 使用新值 item.data = newItemData; }); } function getTimes(plcTimes = [], formTimes = []) { let times = {}; plcTimes.forEach(item => { times[item.htime] = true; }); formTimes.forEach(item => { times[item.htime] = true; }); return Object.keys(times).sort((a, b) => new Date(a) - new Date(b)); } async function getFormData(values, datas, projectId) { let arrtData = values.data || []; const params = getFormParams(datas, projectId); if (!values.timeType) { // 请求最新数据 return await getFormCurrentData(params, values); } else { // 请求历史数据 return await getFormHistoryData(params, values); } } // 请求表单最新数据 async function getFormCurrentData(params, values) { const { timeType, date } = values; let data = []; for (let i = 0; i < params.length; i++) { const resData = await queryFormCurrentData(params[i]); data = [...data, ...resData]; } return data; } // 请求表单历史数据 async function getFormHistoryData(params, values) { const { timeType, date } = values; let sTime, eTime; let data = []; // -1为自选日期 从date内获取时间 if (timeType == -1) { let clear = { hour: 0, minute: 0, second: 0, millisecond: 0 }; eTime = moment(date[1]) .set(clear) .format('YYYY-MM-DD HH:mm:ss'); sTime = moment(date[0]) .set(clear) .format('YYYY-MM-DD HH:mm:ss'); } else { let currentDate = moment(); eTime = currentDate.format('YYYY-MM-DD HH:mm:ss'); sTime = currentDate.add(-1 * timeType, 'hour').format('YYYY-MM-DD HH:mm:ss'); } for (let i = 0; i < params.length; i++) { const resData = await queryFormHistoryData({ ...params[i], eTime, sTime }); data = [...data, ...resData]; } return data; } async function getPlcData(values, datas) { let arrtData = values.data || []; let params = getSingleData(datas); if (!values.timeType) { let res = await getData(params, values); return res.data; } else { let singleData = []; for (let i = 0; i < params.length; i++) { const item = params[i]; let res = await getData(item, values); singleData.push({ paramsInfo: item, name: item.deviceName, data: (res.data || []).map(item => { return { val: Number(item.val), htime: moment(item.htime_at).format('YYYY-MM-DD HH:mm:ss'), }; }), }); } return singleData; } } // 根据数据项获取请求参数 function getSingleData(datas) { let params = []; datas.forEach(({ device_id, device_items, seq }) => { if (device_id && device_items) { params.push({ deviceName: seq, deviceId: device_id, deviceItems: device_items, }); } }); return params; } function findPlcData(paramsInfo, plcData, timeType) { // 实时数据与历史数据结构不一致 需判断 if (timeType) { return plcData.find(resItem => resItem.paramsInfo.deviceName == paramsInfo.seq); } else { let res = plcData.find(resItem => resItem.alias == paramsInfo.seq); return { name: res.alias, value: res.val, }; } } function findFormData(paramsInfo, formData, timeType) { // 实时数据与历史数据结构不一致 需判断 if (timeType) { return formData.find(resItem => resItem.name == paramsInfo.data_title); } else { let res = formData.find(resItem => resItem.title == paramsInfo.data_title); return { name: res.title, value: res.value, }; } } function getAllParams(datas, formula) { let allDatas = [...datas]; formula.forEach(f => { f.params.forEach(params => { if (params.data_type == 0) { if (!datas.find(item => item.seq == params.seq)) { allDatas.push(params); } } else { if (!datas.find(item => item.data_title == params.data_title)) { allDatas.push(params); } } }); }); return allDatas; } function getOptionsData(datas, formula, values) { let valuesData = values.data || []; let optionsData = []; formula.forEach((item, index) => { var arrData = valuesData[index] || {}; item.data_type = 2; arrData.paramsInfo = item; optionsData.push(arrData); }); datas.forEach((data, index) => { var arrData = valuesData[index + formula.length] || {}; arrData.paramsInfo = data; optionsData.push(arrData); }); return optionsData; } var DATA_CACHE = {}; // 请求plc数据 async function getData(params, values) { const { timeType, date, size, interval, aggregator } = values; let key, etime, stime; if (!timeType) { key = `${params.map(item => item.deviceItems).join(',')}-${timeType}`; } else if (timeType != -1) { key = `${params.deviceItems}-${timeType}-${size}-${interval}-${aggregator}`; } else { let clear = { hour: 0, minute: 0, second: 0, millisecond: 0 }; etime = moment(date[1]).set(clear) * 1; stime = moment(date[0]).set(clear) * 1; key = `${params.deviceItems}-${stime}-${etime}-${size}-${interval}-${aggregator}`; } if (!DATA_CACHE[key]) { if (!timeType) { DATA_CACHE[key] = await getDeviceRealData(params); } else { if (timeType != -1) { let currentDate = moment(); etime = currentDate * 1; stime = currentDate.add(-1 * timeType, 'hour') * 1; } DATA_CACHE[key] = await getDeviceRealDataByTime({ deviceid: params.deviceId * 1, dataitemid: params.deviceItems, stime, etime, size, interval, aggregator, }); } } return DATA_CACHE[key]; } function getFormulaData(formula, plcData, formData, timeType) { let expression = [...formula.expression]; let resDatas = formula.params.map(params => { let res; if (params.data_type == 0) { res = findPlcData(params, plcData, timeType); return { ...params, ...res, }; } else { res = findFormData(params, formData, timeType); return { ...params, ...res, }; } }); if (timeType) { let optionsData = []; // 获取时间 let time = resDatas[0].data.map(item => item.htime); time.forEach((htime, index) => { resDatas.forEach(params => { // 根据index去替换表达式中对应的值 expression[params.index] = params.data[index].val || 0; }); optionsData.push({ htime: moment(htime).format('YYYY-MM-DD HH:mm:ss'), val: computePrefixExpression([...expression]), }); }); return { data: optionsData, name: formula.FormulaName, }; } else { resDatas.forEach(params => { // 根据index去替换表达式中对应的值 expression[params.index] = params.value || 0; }); return { value: computePrefixExpression([...expression]), name: formula.FormulaName, }; } }