@iotile/iotile-device
Version:
A typescript library for interfacing with IOTile BLE devices
184 lines • 6.49 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
const iotile_common_1 = require("@iotile/iotile-common");
const heatshrink_ts_1 = require("heatshrink-ts");
const constants_1 = require("./constants");
const flexible_dict_report_1 = require("../../common/flexible-dict-report");
function timeAboveThreshold(data, threshold, samplingRate) {
let maxCount = 0;
let currCount = 0;
let above = false;
let lastSample = 0.0;
for (let sample of data) {
if (above === false && Math.abs(sample) >= threshold) {
above = true;
currCount = 0;
}
else if (above) {
currCount += 1;
if (Math.abs(sample) < threshold || lastSample * sample < 0.0) {
above = false;
if (currCount > maxCount)
maxCount = currCount;
}
}
lastSample = sample;
}
if (above && currCount > maxCount)
maxCount = currCount;
return maxCount / samplingRate * 1000.0;
}
exports.timeAboveThreshold = timeAboveThreshold;
function calculateDeltaV(data, threshold, samplingRate) {
let maxDV = 0;
let currDV = 0;
let above = false;
let lastSample = 0.0;
const G_CONST = 9.80665;
for (let sample of data) {
if (above === false && Math.abs(sample) >= threshold) {
above = true;
currDV = sample;
}
else if (above) {
currDV += sample;
if (Math.abs(sample) < threshold || lastSample * sample < 0.0) {
above = false;
if (Math.abs(currDV) > Math.abs(maxDV))
maxDV = currDV;
}
}
lastSample = sample;
}
if (above && Math.abs(currDV) > Math.abs(maxDV))
maxDV = currDV;
return maxDV / samplingRate * G_CONST;
}
exports.calculateDeltaV = calculateDeltaV;
function maxAbs(data) {
let max = 0.0;
for (let value of data) {
if (Math.abs(value) > max) {
max = Math.abs(value);
}
}
return max;
}
exports.maxAbs = maxAbs;
function summarizeAxis(data, threshold, samplingRate) {
return {
deltaV: calculateDeltaV(data, threshold, samplingRate),
peak: maxAbs(data),
timeAboveThreshold: timeAboveThreshold(data, threshold, samplingRate)
};
}
exports.summarizeAxis = summarizeAxis;
function summarizeWaveform(wave) {
let xSummary = summarizeAxis(wave.acceleration_data.x, 1.0, wave.sampling_rate);
let ySummary = summarizeAxis(wave.acceleration_data.y, 1.0, wave.sampling_rate);
let zSummary = summarizeAxis(wave.acceleration_data.z, 1.0, wave.sampling_rate);
let peakAxis = 'x';
let peak = xSummary.peak;
let duration = xSummary.timeAboveThreshold;
if (ySummary.peak > peak) {
peakAxis = 'y';
peak = ySummary.peak;
duration = ySummary.timeAboveThreshold;
}
if (zSummary.peak > peak) {
peakAxis = 'z';
peak = zSummary.peak;
duration = zSummary.timeAboveThreshold;
}
return {
peak: peak,
axis: peakAxis,
duration: duration,
delta_v_x: xSummary.deltaV,
delta_v_y: ySummary.deltaV,
delta_v_z: zSummary.deltaV
};
}
exports.summarizeWaveform = summarizeWaveform;
function unpackVLEIntegerList(input) {
let inputBytes = new Uint8Array(input);
let outputNumbers = [];
let accum = 0;
let shift = 0;
for (let i = 0; i < inputBytes.byteLength; ++i) {
let val = inputBytes[i];
if (val & (1 << 7)) {
accum |= (val & (0x7f));
shift = 7;
}
else {
accum |= ((val & 0x7f) << shift);
let zigzag = ((accum >>> 1)) ^ -(accum & 1);
accum = 0;
shift = 0;
outputNumbers.push(zigzag);
}
}
for (let i = 1; i < outputNumbers.length; ++i) {
outputNumbers[i] += outputNumbers[i - 1];
}
return outputNumbers;
}
exports.unpackVLEIntegerList = unpackVLEIntegerList;
function decompressWaveforms(rawWaveforms) {
let decoder = new heatshrink_ts_1.HeatshrinkDecoder(constants_1.WINDOW_BITS, constants_1.LOOKAHEAD_BITS, constants_1.INPUT_BUFFER_LENGTH);
let accelerationData = [];
let waveforms = {};
for (let wave in rawWaveforms) {
let rawWaveform = rawWaveforms[wave];
accelerationData = [];
decoder.reset();
decoder.process(rawWaveforms[wave].rawWaveform);
let expanded = decoder.getOutput();
let vleDecoded = unpackVLEIntegerList(expanded.buffer);
if (vleDecoded.length != 3072) {
throw new iotile_common_1.InvalidDataError('Waveform Decompression Error', `Received number of data points is incorrect; parsed ${vleDecoded.length} of 3072`);
}
for (let v of vleDecoded) {
accelerationData.push(v * .049);
}
let waveformData = { acceleration_data: { x: accelerationData.slice(0, 1024),
y: accelerationData.slice(1024, 2048),
z: accelerationData.slice(2048) },
sampling_rate: constants_1.SAMPLING_RATE,
crc_code: rawWaveform.crcCode
};
waveforms[wave] = {
deviceTimestamp: rawWaveform.timestamp,
utcTimestamp: tryConvertUTCTimestamp(rawWaveform.timestamp),
summary: summarizeWaveform(waveformData),
waveform: waveformData
};
}
return waveforms;
}
exports.decompressWaveforms = decompressWaveforms;
function tryConvertUTCTimestamp(deviceTimestamp) {
if (deviceTimestamp === 0xFFFFFFFF)
return null;
if (!(deviceTimestamp & (1 << 31)))
return null;
let y2kDelta = deviceTimestamp & ((1 << 31) - 1);
let y2k = new Date('2000-01-01T00:00:00Z');
let timestamp = y2k.getTime() + y2kDelta * 1000;
let utcDate = new Date(timestamp);
return utcDate;
}
exports.tryConvertUTCTimestamp = tryConvertUTCTimestamp;
function createWaveformEvents(waveforms) {
let events = [];
let streamID = 0x5020;
for (let uniqueId in waveforms) {
let waveform = waveforms[uniqueId];
let event = new flexible_dict_report_1.IOTileEvent(streamID, waveform.deviceTimestamp, waveform.summary, waveform.waveform, +uniqueId, waveform.utcTimestamp);
events.push(event);
}
return events;
}
exports.createWaveformEvents = createWaveformEvents;
//# sourceMappingURL=utilities.js.map