const vs = require("../systemScripts/variable");
const http = require('http');
const moment = require("moment");
const sdkClient = require('../modules/sdk-module');
async function getLastNValues(id, n) {
return new Promise(function (resolve, reject) {
sdkClient.apis.getLastNVarValues(id, n, function (error, res) {
if (error) {
console.log(error);
resolve([]);
} else if (res && res.success && res.data) {
resolve(res.data);
} else {
resolve([]);
}
});
});
}
const fT = (m) => m.format('YYYY-MM-DD HH:mm:ss');
const mT = (s) => moment(s, 'YYYY-MM-DD HH:mm:ss');
const mHT = (s) => moment(s, 'HH:mm:ss');
const sumFunc = (arr) => arr.reduce((prev, curr) => prev + curr, 0);
const strToTimestamp = (str) => new Date(str).getTime();
const ONE_MIN_MILLIONS = 60 * 1000;
function addDatePrefix(obj) {
const sStr = obj['startTime'].format('YYYY-MM-DD');
const eStr = obj['endTime'].format('YYYY-MM-DD');
const hStr = obj['startTime'].format('HH:mm:ss');
if (obj['startTime'].isSame(obj['endTime'], 'day')) {
obj['restTimes'] = obj['restTimes'].map(i => {
return {
start: mT(`${sStr} ${i['start']}`),
end: mT(`${sStr} ${i['end']}`)
};
}).sort((a, b) => a['start'].valueOf() - b['start'].valueOf())
} else {
obj['restTimes'] = obj['restTimes'].map(i => {
return {
start: mHT(i['start']).isBefore(mHT(hStr)) ? mT(`${eStr} ${i['start']}`) : mT(`${sStr} ${i['start']}`),
end: mHT(i['end']).isBefore(mHT(hStr)) ? mT(`${eStr} ${i['end']}`) : mT(`${sStr} ${i['end']}`)
};
}).sort((a, b) => a['start'].valueOf() - b['start'].valueOf())
}
}
const safeRate = value => {
value = Number(value);
if (Number.isNaN(value)) {
value = 0;
}
if (value > 1) {
value = 1;
}
if (value < 0) {
value = 0;
}
return value;
}
const postResponse = async (host, port, url, data) => {
let option = {
host: host,
port: port,
path: url,
method: 'POST',
headers: {
'accept': '*/*',
'content-type': "application/json"
}
};
return new Promise((resolve, reject) => {
let chunks = [];
let size = 0;
let req = http.request(option, res => {
res.on('data', body => {
chunks.push(body);
size += body.length;
});
res.on('end', () => {
let buffer = Buffer.concat(chunks, size);
let data = JSON.parse(buffer.toString());
resolve(data);
});
});
req.on('error', error => {
resolve(null);
})
req.write(JSON.stringify(data));
req.end();
});
};
const convertRateString = rate => {
return `${(rate * 100).toFixed(2)}%`;
};
async function getDeviceProductionTime(deviceNos, d, odIP, odPort) {
const reqData = {
date: typeof (d) === 'string' ? d : d.format('YYYY-MM-DD'),
deviceNos
};
let res = await postResponse(odIP, odPort, '/api/ol/pp', reqData);
console.log('请求od拿到的生产计划');
console.log(res);
if (res && Array.isArray(res['data'])) {
const mapObj = {};
for (let i of res['data']) {
mapObj[i['deviceNo']] = i['dateVoList'] ? i['dateVoList'].map(item => ({
startTime: item['startTime'],
endTime: item['endTime'],
restTimes: [...item['coffeeBreakDateVoList']]
})) : [];
}
return mapObj
}
return {}
}
function cutCurrentPeriodTime(timeList) {
const now = moment();
const arr = timeList.filter(i => {
return now.isSameOrAfter(mT(i['startTime'])) && now.isSameOrBefore(mT(i['endTime']))
});
if (arr.length <= 0) {
return []
}
const currentPeriod = arr[0];
currentPeriod['startTime'] = mT(currentPeriod['startTime']);
currentPeriod['endTime'] = mT(currentPeriod['endTime']);
let result = [];
if (currentPeriod['restTimes'].length === 0) {
result.push({s: fT(currentPeriod['startTime']), e: fT(now)})
return result;
}
addDatePrefix(currentPeriod);
if (currentPeriod['restTimes'].length === 1) {
let s = currentPeriod['startTime'];
let rS = currentPeriod['restTimes'][0]['start'];
let rE = currentPeriod['restTimes'][0]['end'];
switch (true) {
case now.isBefore(rS):
result.push({s, e: now})
break;
case now.isSameOrAfter(rS) && now.isSameOrBefore(rE):
result.push({s, e: rS})
break;
case now.isAfter(rE):
result.push({s, e: rS})
result.push({s: rE, e: now})
break;
default :
;
}
} else {
const rests = currentPeriod['restTimes'];
const slicedTimes = [];
for (let i = 0; i < rests.length; i++) {
if (i === 0) {
slicedTimes.push({s: currentPeriod['startTime'], e: rests[i]['start'], isRest: false});
slicedTimes.push({s: rests[i]['start'], e: rests[i]['end'], isRest: true});
} else {
slicedTimes.push({s: rests[i - 1]['end'], e: rests[i]['start'], isRest: false});
slicedTimes.push({s: rests[i]['start'], e: rests[i]['end'], isRest: true});
}
if (i === rests.length - 1) {
slicedTimes.push({s: rests[i]['end'], e: currentPeriod['endTime'], isRest: false});
}
}
for (let i = 0; i < slicedTimes.length; i++) {
const curr = slicedTimes[i];
if (now.isBetween(curr['s'], curr['e'], null, '[]')) {
curr['isRest'] || result.push({s: curr['s'], e: now});
break;
} else {
curr['isRest'] || result.push({s: curr['s'], e: curr['e']})
}
}
}
return result
}
const isRunning = value => {
return value === '2' || value === 2;
};
async function getRealTimeBySection(device, time) {
let statusVarId = device['deviceStatusVarId'];
let startTime = typeof(time['s']) === 'string' ? time['s'] : fT(time['s']);
let endTime = typeof(time['e']) === 'string' ? time['e'] : fT(time['e']);
let result = 0;
let res = await vs.getVariablesInTimeRange(statusVarId, startTime, endTime);
console.log('getVariablesInTimeRange');
console.log(res);
let len = res.length;
let resultTimesArray = [];
let lastNVal = [];
if (len <= 0) {
let last1Val = await getLastNValues(device['deviceStatusVarId'], 1);
if (isRunning(last1Val[0]['value'])) {
result = strToTimestamp(endTime) - strToTimestamp(startTime);
}
} else {
lastNVal = await getLastNValues(device['deviceStatusVarId'], len + 1);
lastNVal = lastNVal.reverse();
console.log('lastNVal');
console.log(lastNVal);
lastNVal.forEach((item, index) => {
if (isRunning(item['value'])) {
let currDiffValue = 0;
if (index === 0) {
currDiffValue = strToTimestamp(lastNVal[index + 1]['timestamp']) - strToTimestamp(startTime);
} else if (index < len) {
currDiffValue = strToTimestamp(lastNVal[index + 1]['timestamp']) - strToTimestamp(item['timestamp']);
} else {
currDiffValue = strToTimestamp(endTime) - strToTimestamp(item['timestamp'])
}
resultTimesArray.push(currDiffValue)
}
});
result = sumFunc(resultTimesArray);
}
console.log(result);
return {
timeRange: time,
getVariablesInTimeRangeArray: res,
len: len,
lastNVal: lastNVal,
getRealTimeBySectionValue: resultTimesArray,
result: result
};
}
async function calcActivation(device, cuttedTimes) {
console.log('cuttedTimes');
console.log(cuttedTimes);
let workTimeMills = 0;
let realWorkTimeMills = 0;
let debugArray = [];
for (let item of cuttedTimes) {
workTimeMills += strToTimestamp(item['e']) - strToTimestamp(item['s']);
const thisSectionRealTimeObj = await getRealTimeBySection(device, item);
debugArray.push(thisSectionRealTimeObj);
realWorkTimeMills += thisSectionRealTimeObj['result'];
}
let res = safeRate(realWorkTimeMills / workTimeMills);
console.log('稼动率');
console.log(res);
return {
debugArray,
realWorkTimeMills,
workTimeMills,
activationRate: res
}
}
async function calcOkRate(device) {
let okRate = 0;
const {qualifiedNumVarId, totalNumVarId} = device;
const qualifiedNumObj = await vs.getCurrentValue(qualifiedNumVarId);
const totalNumObj = await vs.getCurrentValue(totalNumVarId);
const qualifiedNum = Number(qualifiedNumObj['value']);
const totalNum = Number(totalNumObj['value']);
if (qualifiedNum > 0 && totalNum > 0) {
okRate = qualifiedNum / totalNum;
okRate = safeRate(okRate);
}
return {
qualifiedNum,
totalNum,
okRate
};
}
async function calcPerformanceRate(device, realWorkTimeMills, totalNum, efficiency) {
totalNum = Number(totalNum);
efficiency = Number(efficiency);
let performanceRate = 0;
if (totalNum > 0 && efficiency > 0) {
let expectQualifiedNum = (realWorkTimeMills / ONE_MIN_MILLIONS) * efficiency;
if (expectQualifiedNum) {
performanceRate = safeRate(totalNum / expectQualifiedNum);
}
}
return performanceRate;
}
async function calcOeeRate(activateRate, okRate, performanceRate) {
let oeeRate = okRate * activateRate * performanceRate;
oeeRate = safeRate(oeeRate);
return oeeRate;
}
async function calcEachDevice(device, cuttedTimes, variableMap) {
const {deviceCode, efficiencyVarId, performanceRateId, cropRateId, okRateId, oeeRateId} = device;
const efficiency = variableMap[efficiencyVarId];
const resultPromises = [];
const activationRateObject = await calcActivation(device, cuttedTimes);
resultPromises.push(vs.setVariable(cropRateId, convertRateString(activationRateObject['activationRate'])));
const okRateObject = await calcOkRate(device);
resultPromises.push(vs.setVariable(okRateId, convertRateString(okRateObject['okRate'])));
const {
qualifiedNum,
totalNum,
} = okRateObject;
const {
realWorkTimeMills,
workTimeMills,
} = activationRateObject;
const performanceRate = await calcPerformanceRate(device, realWorkTimeMills, totalNum, efficiency);
resultPromises.push(vs.setVariable(performanceRateId, convertRateString(performanceRate)));
const oeeRate = await calcOeeRate(activationRateObject['activationRate'], okRateObject['okRate'], performanceRate);
resultPromises.push(vs.setVariable(oeeRateId, convertRateString(oeeRate)));
await Promise.all(resultPromises);
return {
activationRateObject,
deviceCode,
realWorkTimeMills,
workTimeMills,
qualifiedNum,
totalNum,
efficiency
}
}
const mainLogic = async function (configStr, ip, port) {
const d = moment();
let configObj = JSON.parse(configStr);
if (!configObj || !Array.isArray(configObj.devices)) {
throw new Error('无效的入参配置');
}
let devices = configObj.devices;
let deviceCodeStr = devices.map(i => i.deviceCode).join(',');
const deviceTimesMap = await getDeviceProductionTime(deviceCodeStr, d, ip, port);
let inputIds = [];
devices.forEach(item => {
let qualifiedNumVarId = Number(item['qualifiedNumVarId']);
if (qualifiedNumVarId > 0) {
inputIds.push(qualifiedNumVarId);
}
let totalNumVarId = Number(item['totalNumVarId']);
if (totalNumVarId > 0) {
inputIds.push(totalNumVarId);
}
let efficiencyVarId = Number(item['efficiencyVarId']);
if (efficiencyVarId > 0) {
inputIds.push(efficiencyVarId);
}
});
let variables = await vs.getVariablesByIds(inputIds.join(','));
let variableMap = {};
for (let item of variables) {
variableMap[item.id] = item.value;
}
let promises = [];
for (let device of devices) {
let deviceCuttedTimes = cutCurrentPeriodTime(deviceTimesMap[device['deviceCode']]);
let deviceStatusVarId = Number(device['deviceStatusVarId']);
if (Number.isNaN(deviceStatusVarId) || deviceStatusVarId <= 0 || !deviceCuttedTimes) {
continue;
}
promises.push(calcEachDevice(device, deviceCuttedTimes, variableMap))
}
let results = await Promise.all(promises);
let totalRunningMillions = 0;
let totalPlanWorkingMillions = 0;
let totalQualifiedNum = 0;
let totalOutputNum = 0;
let totalExceptOutputNum = 0;
results.forEach(i => {
totalRunningMillions += i.realWorkTimeMills;
totalPlanWorkingMillions += i.workTimeMills;
totalQualifiedNum += i.qualifiedNum;
totalOutputNum += i.totalNum;
totalExceptOutputNum += (i.realWorkTimeMills / ONE_MIN_MILLIONS) * i.efficiency;
});
totalExceptOutputNum = parseInt(totalExceptOutputNum);
let totalCropRate = 0;
if (totalPlanWorkingMillions > 0) {
totalCropRate = safeRate(totalRunningMillions / totalPlanWorkingMillions);
}
let totalOkRate = 0;
if (totalOutputNum > 0) {
totalOkRate = safeRate(totalQualifiedNum / totalOutputNum);
}
let totalPerformace = 0;
if (totalExceptOutputNum > 0) {
totalPerformace = safeRate(totalOutputNum / totalExceptOutputNum);
}
let totalOee = safeRate(totalCropRate * totalOkRate * totalPerformace);
let totalSetPromises = [];
const {debugVarId, totalCropRateId, totalOkRateId, totalOeeRateId, totalPlanRunningId, totalRealRunningId, totalExpectOutputId} = configObj;
if (totalCropRateId) {
totalSetPromises.push(vs.setVariable(totalCropRateId, convertRateString(totalCropRate)));
}
if (totalOkRateId) {
totalSetPromises.push(vs.setVariable(totalOkRateId, convertRateString(totalOkRate)));
}
if (totalOeeRateId) {
totalSetPromises.push(vs.setVariable(totalOeeRateId, convertRateString(totalOee)));
}
if (totalPlanRunningId) {
totalSetPromises.push(vs.setVariable(totalPlanRunningId, totalPlanWorkingMillions));
}
if (totalRealRunningId) {
totalSetPromises.push(vs.setVariable(totalRealRunningId, totalRunningMillions));
}
if (totalExpectOutputId) {
totalSetPromises.push(vs.setVariable(totalExpectOutputId, totalExceptOutputNum));
}
await Promise.all(totalSetPromises);
if (debugVarId) {
let debugObj = {
deviceTimesMap: deviceTimesMap,
devices: results
};
await vs.setVariable(debugVarId, JSON.stringify(debugObj));
}
};
module.exports = {
main: mainLogic
};
console