sensecap
Version:
## Install ``` npm install sensecap --save ```
333 lines (305 loc) • 13 kB
JavaScript
var logger = require('../utils/loggerUtil')
var assert = require('assert');
function DataResult(options) {
this.context = options;
}
DataResult.prototype = {
/**
* 获取最新一条数据
*/
latestData: function (callback) {
var deviceEui = this.context.deviceEui;
assert(deviceEui, 'deviceEui is required');
var channelIndex = this.context.channelIndex;
var measurementId = this.context.measurementId;
var telemetryDataListener = this.context.telemetryDataListener;
this.context.dataNetModule.viewLatestTelemetryData(deviceEui, channelIndex, measurementId, function (error, body) {
var telemetryDataList = [];
if (!error) {
var data = body.data;
if (data && data.length > 0) {
for (var i = 0; i < data.length; i++) {
for (var j=0; j< data[i].points.length; j++) {
data[i].points[j].time = new Date(data[i].points[j].time).valueOf() / 1000;
}
telemetryDataList.push(data[i]);
}
}
}
if (callback) {
callback(error, telemetryDataList);
}
})
this._handlerTelemetryDataListener(deviceEui, channelIndex, measurementId, telemetryDataListener);
},
/**
* 获取历史数据
*/
dataList: function (callback) {
var deviceEui = this.context.deviceEui;
assert(deviceEui, 'deviceEui is required');
var channelIndex = this.context.channelIndex;
var measurementId = this.context.measurementId;
var startTime = this.context.startTime;
var endTime = this.context.endTime;
var limit = this.context.limit;
var telemetryDataListener = this.context.telemetryDataListener;
var that = this;
if (startTime !== 0 || endTime !== 0) {
this.context.dataNetModule.viewHistoryTelemetryData(deviceEui, channelIndex, measurementId, startTime, endTime, limit, function (error, body) {
var telemetryDataList = [];
if (!error) {
// telemetryDataList = body.data.list;
telemetryDataList = that._clearUpTelemetryData(body.data.list);
}
if (callback) {
callback(error, telemetryDataList);
}
})
}
this._handlerTelemetryDataListener(deviceEui, channelIndex, measurementId, telemetryDataListener);
},
/**
* 获取折线图数据点,原openapi方式
*/
getChartPointData: function (callback) {
var deviceEui = this.context.deviceEui;
assert(deviceEui, 'deviceEui is required');
var channelIndex = this.context.channelIndex;
var measurementId = this.context.measurementId;
var startTime = this.context.startTime;
var endTime = this.context.endTime;
var interval = this.context.interval;
var that = this;
this.context.dataNetModule.viewChartPoints(deviceEui, channelIndex, measurementId, interval, startTime, endTime, function (error, body) {
var telemetryDataList = [];
if (!error) {
// telemetryDataList = body.data;
telemetryDataList = that._clearUpChartPointData(body.data);
}
if (callback) {
callback(error, telemetryDataList);
}
})
},
/**
* 获取折线图数据
*/
getChartData: function (callback) {
var deviceEui = this.context.deviceEui;
assert(deviceEui, 'deviceEui is required');
var channelIndex = this.context.channelIndex;
var measurementId = this.context.measurementId;
var endTime = this.context.endTime || new Date().getTime();
var startTime = this.context.startTime || (endTime - 86400000);
var interval = this.context.interval || 30;
var that = this;
var intervalTime = 0;
var pointInterval = 0;
if (endTime - startTime <= 86400000) {
// 一天内返回所有点
intervalTime = 1000;
} else {
intervalTime = interval * 60 * 1000 // 转成毫秒
}
if (interval < 60) {
pointInterval = 7200; // 秒 2小时
} else {
pointInterval = interval * 2 * 60; // 秒
}
// 获取历史数据
this.context.dataNetModule.viewHistoryTelemetryData(deviceEui, channelIndex, measurementId, startTime, endTime, null, function (error, body) {
var telemetryDataList = [];
if (!error) {
telemetryDataList = that._clearUpTelemetryData(body.data.list);
telemetryDataList = that._clearUpChartData(telemetryDataList, intervalTime, pointInterval, startTime, endTime);
}
if (callback) {
callback(error, telemetryDataList);
}
})
},
/**
* [{
"channelIndex": 1,
"measurementId": 4099,
"values": [
[1606023000, null],
[1606375800, null],
[1606728600, 267.34],
[1607491800, 1765.96],
[1607493508, 2421.47]
]
}]
*/
_clearUpTelemetryData: function (telemetryDataList) {
var dataList = []
var channelAndMeasurementIdArr = telemetryDataList[0]
var valueAndTimeArr = telemetryDataList[1]
for (var i = 0; i < channelAndMeasurementIdArr.length; i++) {
var item = channelAndMeasurementIdArr[i];
var data = {
'channel_index': item[0],
'measurement_id': item[1],
'values': []
}
for (var j = 0; j < valueAndTimeArr[i].length; j++) {
var element = valueAndTimeArr[i][j];
var value = element[0];
var time = new Date(element[1]).valueOf() / 1000;
data.values.push([value, time])
}
dataList.push(data);
}
return dataList
},
/**
* openapi方式的图表数据整理
*/
_clearUpChartPointData: function (pointData) {
var dataList = [];
for (var i = 0; i < pointData.length; i++) {
var item = pointData[i];
var measurementList = {};
for (var j = 0; j < item.lists.length; j++) {
var element = item.lists[j];
var measurementId = element.measurement_id
if (!measurementList[measurementId]) {
measurementList[measurementId] = []
}
measurementList[measurementId].push([new Date(element.time) / 1000, element.average_value])
}
var measurementIds = Object.keys(measurementList);
for (var j = 0; j < measurementIds.length; j++) {
var data = {
'channel_index': item.channel,
'measurement_id': measurementIds[j],
'values': measurementList[measurementIds[j]]
}
dataList.push(data);
}
}
return dataList;
},
/**
* "values":[[0.74,1607500530000]]
* * 补点规则
* interval<=60 每缺两个小时的数据中间补一个点
* interval>60 每缺 interval*2 小时的数据中间补一个点
* 首位补点
* 比较【查询时间开始点】和【实际数据首位时间点】按照补点规则补点,满足规则则补上首位点时间
* 末尾补点
* 比较【查询时间结束点】和【实际数据末尾时间点】按照补点规则补点,满足规则则补上末尾点,末尾时间按查询结束时间精确到具体秒补点
*/
_clearUpChartData: function (telemetryDataList, intervalTime, pointInterval, startTime, endTime) {
for (var i = 0; i < telemetryDataList.length; i++) {
var item = telemetryDataList[i];
var values = item.values;
var newValues = [];
var list = {
value: {},
count: {}
}
var keyList = []
for (var j = 0; j < values.length; j++) {
var element = values[j];
var key = parseInt(element[1] / intervalTime + 1);
if (list.value[key]) {
list.value[key] = list.value[key] + element[0];
list.count[key]++;
} else {
list.value[key] = element[0];
list.count[key] = 1;
keyList.push(key);
// logger.log('key========: ' + key + ',element[1]: ' + new Date(element[1]).toLocaleString() + ',time: ' + element[1])
}
}
var keys = Object.keys(list.value)
for (var j = 0; j < keys.length; j++) {
var key = keys[j];
var data = []
if (key < new Date().valueOf() / 10000) {
data[0] = key * (intervalTime / 1000);
} else {
data[0] = key;
}
if (list.value[key] !== null) {
data[1] = list.value[key] / list.count[key];
} else {
data[1] = null;
}
newValues.push(data);
}
// logger.log('newValues before========');
// for (var i = 0; i < newValues.length; i++) {
// logger.log('newValues time========' + new Date(newValues[i][0] * 1000).toLocaleString() + ',value:' + newValues[i][1] + ',time: ' + newValues[i][0])
// }
// 补点
var fullValues = []
startTime = startTime / 1000;
// 补首点
if (newValues[0][0] - startTime > pointInterval) {
fullValues[0] = [startTime, null];
fullValues[1] = [(startTime + newValues[0][0]) / 2, null];
fullValues[2] = newValues[0];
}
// 补中间点
for (var i = 0; i < newValues.length - 1; i++) {
var value1 = newValues[i];
var value2 = newValues[i + 1];
while (value2[0] - value1[0] > pointInterval) {
fullValues.push([value1[0] + pointInterval, null])
value1[0] = value1[0] + pointInterval;
}
fullValues.push(value2)
}
// 补尾点
endTime = endTime / 1000;
if (endTime - newValues[newValues.length - 1][0] > pointInterval) {
fullValues.push([(endTime + newValues[newValues.length - 1][0]) / 2, null]);
fullValues.push([endTime, null]);
}
// logger.log('fullValues after========');
// for (var i = 0; i < fullValues.length; i++) {
// logger.log('fullValues time========' + new Date(fullValues[i][0] * 1000).toLocaleString() + ',value:' + fullValues[i][1] + ',time: ' + fullValues[i][0])
// }
item.values = fullValues;
}
return telemetryDataList;
},
/**
* 关闭订阅
*/
stopTelemetryDataListener: function (callback) {
var deviceEui = this.context.deviceEui;
assert(deviceEui, 'deviceEui is required');
var channelIndex = this.context.channelIndex;
var measurementId = this.context.measurementId;
this.context.dataNetModule.baseMqtt.unSubscribe(deviceEui, channelIndex, measurementId, callback);
},
_handlerTelemetryDataListener: function (deviceEui, channelIndex, measurementId, telemetryDataListener) {
if (telemetryDataListener) {
// 订阅最新消息
var that = this
this.context.dataNetModule.getOrganizationId(function (error, body) {
if (!error) {
that.context.dataNetModule.baseMqtt.setOrgId(body.data.orgId)
that._connectMqtt(deviceEui, channelIndex, measurementId, telemetryDataListener);
} else {
telemetryDataListener(error);
}
});
}
},
_connectMqtt: function (deviceEui, channelIndex, measurementId, telemetryDataListener) {
var that = this
this.context.dataNetModule.baseMqtt.connect(function (error) {
if (!error) {
that.context.dataNetModule.baseMqtt.subscribeData(deviceEui, channelIndex, measurementId, telemetryDataListener)
} else {
telemetryDataListener(error.toString());
}
})
}
};
module.exports = DataResult;