@iotile/iotile-device
Version:
A typescript library for interfacing with IOTile BLE devices
112 lines • 5.53 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
const iotile_reports_1 = require("./iotile-reports");
const iotile_common_1 = require("@iotile/iotile-common");
class SignedListReportMerger {
mergeReports(user, system) {
this.checkReportsForMerging(user, system);
let mergedLength = 20 + (16 * (user.readings.length + system.readings.length)) + 24;
let merged = new ArrayBuffer(mergedLength);
this.insertMergedHeader(merged, user, system);
let readings = this.mergeReadings(merged, user, system);
this.insertMergedFooter(merged, readings.lowestID, readings.highestID);
return new iotile_reports_1.SignedListReport(system.header.uuid, iotile_reports_1.COMBINED_REPORT_STREAMER, merged, system.receivedTime);
}
checkReportsForMerging(user, system) {
let userHeader = user.header;
let systemHeader = system.header;
if (user.validity != iotile_reports_1.SignatureStatus.Valid || system.validity != iotile_reports_1.SignatureStatus.Valid) {
throw new iotile_common_1.ArgumentError("You can only merge reports that have valid signatures");
}
if (userHeader.uuid != systemHeader.uuid) {
throw new iotile_common_1.ArgumentError("Reports did not come from the same device");
}
if (userHeader.selector != iotile_reports_1.SignedReportSelectors.UserOutputs) {
throw new iotile_common_1.ArgumentError("User report did not select user readings");
}
if (systemHeader.selector != iotile_reports_1.SignedReportSelectors.SystemOutputs) {
throw new iotile_common_1.ArgumentError("System report did not select system readings");
}
if (systemHeader.sentTime < userHeader.sentTime) {
throw new iotile_common_1.ArgumentError("System report was sent before user report");
}
if (systemHeader.reportID < userHeader.reportID) {
throw new iotile_common_1.ArgumentError("System report ID was lower than user report");
}
}
insertMergedHeader(merged, user, system) {
let userHeader = user.header;
let systemHeader = system.header;
let header = iotile_common_1.packArrayBuffer('BBHLLLBBH', 1, merged.byteLength & 0xFF, merged.byteLength >> 8, userHeader.uuid, systemHeader.reportID, systemHeader.sentTime, 0, iotile_reports_1.COMBINED_REPORT_STREAMER, iotile_reports_1.SignedReportSelectors.CombinedOutputs);
iotile_common_1.copyArrayBuffer(merged, header, 0, 0, header.byteLength);
}
mergeReadings(merged, user, system) {
let userI = 0;
let systemI = 0;
let totalReadings = user.readings.length + system.readings.length;
let insertI = 0;
let lowest = 0xFFFFFFFF;
let highest = 0;
let readings = [];
let now = new Date();
let onTime = new Date(now.valueOf() - (system.header.sentTime * 1000));
while (insertI < totalReadings) {
let pickSystem = this.pickNextReading(user, userI, system, systemI);
let reading;
if (pickSystem) {
reading = system.readings[systemI++];
}
else {
reading = user.readings[userI++];
}
if (reading.id != 0 && reading.id < lowest) {
lowest = reading.id;
}
if (reading.id != 0 && reading.id > highest) {
highest = reading.id;
}
readings.push(new iotile_reports_1.RawReading(reading.stream, reading.value, reading.timestamp, onTime, reading.id));
this.insertReading(merged, (20 + 16 * insertI), reading.timestamp, reading.stream, reading.value, reading.id);
insertI += 1;
}
return {
lowestID: lowest,
highestID: highest,
readings: readings
};
}
pickNextReading(user, userI, system, systemI) {
if (userI == user.readings.length && systemI == system.readings.length) {
throw new iotile_common_1.ArgumentError("Both reports have been exhausted, no more readings to pick");
}
if (userI == user.readings.length) {
return true;
}
else if (systemI == system.readings.length) {
return false;
}
let userReading = user.readings[userI];
let systemReading = system.readings[systemI];
if (userReading.id < systemReading.id) {
return false;
}
else {
return true;
}
}
insertReading(merged, offset, timestamp, stream, value, readingID) {
let reading = iotile_common_1.packArrayBuffer('HHLLL', stream, 0, readingID, timestamp, value);
iotile_common_1.copyArrayBuffer(merged, reading, 0, offset, reading.byteLength);
}
insertMergedFooter(merged, lowest, highest) {
let footerStart = merged.byteLength - 24;
let idRange = iotile_common_1.packArrayBuffer("LL", lowest, highest);
iotile_common_1.copyArrayBuffer(merged, idRange, 0, footerStart, idRange.byteLength);
let calc = new iotile_common_1.SHA256Calculator();
let signedData = merged.slice(0, merged.byteLength - 16);
let signature = calc.calculateSignature(signedData);
iotile_common_1.copyArrayBuffer(merged, signature, 0, merged.byteLength - 16, 16);
}
}
exports.SignedListReportMerger = SignedListReportMerger;
//# sourceMappingURL=report-merger.js.map