UNPKG

@iotile/iotile-device

Version:

A typescript library for interfacing with IOTile BLE devices

184 lines 6.49 kB
"use strict"; 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