raddec
Version:
Protocol-agnostic RADio DECoding packet library. We believe in an open Internet of Things.
463 lines (429 loc) • 16.5 kB
JavaScript
/**
* Copyright reelyActive 2018-2024
* We believe in an open Internet of Things
*/
const Raddec = require("../../lib/raddec.js");
const assert = require ('assert');
// Inputs for the scenario
const INPUT_DATA_TRANSMITTER = {
transmitterId: "aa:bb:cc:dd:ee:ff",
transmitterIdType: 2
};
const INPUT_DATA_FIRST_DECODING = {
receiverId: "00-1b-c5-09-40-81-00-00",
receiverIdType: 1,
rssi: -69,
timestamp: 1420075425678
};
const INPUT_DATA_SECOND_DECODING = {
receiverId: "001BC50940810000",
receiverIdType: 1,
rssi: -72,
timestamp: 1420075424567
};
const INPUT_DATA_THIRD_DECODING = {
receiverId: "001bc50940810001",
receiverIdType: 1,
rssi: -42,
timestamp: 1420075426789
};
const INPUT_DATA_FIRST_PACKET =
'061bffeeddccbbaa02010611074449555520657669746341796c656572';
const INPUT_DATA_SECOND_PACKET =
'061bffeeddccbbaa02010611074449555520657669746341796c65656c';
const INPUT_DATA_THIRD_PACKET =
'061bffeeddccbbaa02010611074449555520657669746341796c656572';
const INPUT_DATA_FIRST_EVENT = Raddec.events.DISPLACEMENT;
const INPUT_DATA_SECOND_EVENT = Raddec.events.PACKETS;
const INPUT_DATA_THIRD_EVENT = Raddec.events.DISPLACEMENT;
const INPUT_DATA_MERGE_RADDEC = {
transmitterId: "aa:bb:cc:dd:ee:ff",
transmitterIdType: 2,
packets: [ '061bffeeddccbbaa02010611074449555520657669746341796c656576' ],
rssiSignature: [{
receiverId: "001bc50940810000",
receiverIdType: 1,
rssi: -77,
rssiSum: -154,
numberOfDecodings: 2
}],
earliestDecodingTime: 1420075424000
};
const INPUT_DATA_POSITION_RADDEC = {
transmitterId: "3074257bf7194e4000001a85",
transmitterIdType: 5,
rssiSignature: [{
receiverId: "00:11:22:33:44:55",
receiverIdType: 2,
rssi: -80,
numberOfDecodings: 1
}],
position: [ -73.57122, 45.50887 ],
timestamp: 1645568542000
};
const INPUT_DATA_HEX_STRING_RADDEC =
'10002202aabbccddeeff02350401001bc50940810000550101001bc5094081000117';
const INPUT_DATA_HEX_STRING_RADDEC_OPTIONS =
'1000a002aabbccddeeff02550101001bc50940810001350401001bc50940810000f0014aa3175900f1031d061bffeeddccbbaa02010611074449555520657669746341796c6565721d061bffeeddccbbaa02010611074449555520657669746341796c65656c1d061bffeeddccbbaa02010611074449555520657669746341796c656576f206f3c052648ede54b48d4046c122a6f3f5307fffffffffffffff60'
const INPUT_DATA_BUFFER_RADDEC =
Buffer.from(INPUT_DATA_HEX_STRING_RADDEC, 'hex');
const INPUT_DATA_FLATTENED_RADDEC = {
transmitterId: "aabbccddeeff",
transmitterIdType: 2,
rssiSignature: [{
receiverId: "001bc50940810000",
receiverIdType: 1,
rssi: -77,
numberOfDecodings: 2
},
{
receiverId: "001bc50940810001",
receiverIdType: 1,
rssi: -80,
numberOfDecodings: 2
}],
packets: [ '061bffeeddccbbaa02010611074449555520657669746341796c656576' ],
timestamp: 1420075424000,
events: [ 0 ]
};
const INPUT_DATA_FLATTENED_MINIMAL_RADDEC = {
transmitterId: "aabbccddeeff",
transmitterIdType: 2,
timestamp: 1420075424000
};
const INPUT_OPTIONS_FLATTENED = {
includePackets: false,
includeRssiSignature: true,
maxNumberOfReceivers: 1,
rssiThreshold: -77
};
const INPUT_DATA_TRIM_RADDEC = {
transmitterId: "aa:bb:cc:dd:ee:ff",
transmitterIdType: 2,
packets: [ '061bffeeddccbbaa02010611074449555520657669746341796c656576' ],
rssiSignature: [{
receiverId: "001bc50940810000",
receiverIdType: 1,
receiverAntenna: 1,
rssi: -77,
rssiSum: -154,
numberOfDecodings: 2,
aoa: [ 180, -45 ]
}],
position: [ -73.57122, 45.50887, 69 ],
protocolSpecificData: {},
earliestDecodingTime: 1420075424000
};
// Expected outputs for the scenario
const EXPECTED_DATA_TRANSMITTER_ID = "aabbccddeeff";
const EXPECTED_DATA_TRANSMITTER_ID_TYPE = 2;
const EXPECTED_DATA_BARE_RSSI_SIGNATURE = [];
const EXPECTED_DATA_BARE_ENCODING = '10000c02aabbccddeeff0019';
const EXPECTED_DATA_FIRST_RSSI_SIGNATURE = [{
receiverId: "001bc50940810000",
receiverIdType: 1,
rssi: -69,
rssiSum: -69,
numberOfDecodings: 1
}];
const EXPECTED_DATA_FIRST_EARLIEST_TIME = 1420075425678;
const EXPECTED_DATA_FIRST_ENCODING =
'10001702aabbccddeeff013a0101001bc509408100000b';
const EXPECTED_DATA_SECOND_RSSI_SIGNATURE = [{
receiverId: "001bc50940810000",
receiverIdType: 1,
rssi: -70,
rssiSum: -141,
numberOfDecodings: 2
}];
const EXPECTED_DATA_SECOND_EARLIEST_TIME = 1420075424567;
const EXPECTED_DATA_THIRD_RSSI_SIGNATURE = [{
receiverId: "001bc50940810000",
receiverIdType: 1,
rssi: -70,
rssiSum: -141,
numberOfDecodings: 2
},{
receiverId: "001bc50940810001",
receiverIdType: 1,
rssi: -42,
rssiSum: -42,
numberOfDecodings: 1
}];
const EXPECTED_DATA_THIRD_EARLIEST_TIME = 1420075424567;
const EXPECTED_DATA_THIRD_ENCODING =
'10002202aabbccddeeff02390201001bc50940810000550101001bc5094081000119';
const EXPECTED_DATA_FIRST_PACKET = [
'061bffeeddccbbaa02010611074449555520657669746341796c656572'
];
const EXPECTED_DATA_SECOND_PACKET = [
'061bffeeddccbbaa02010611074449555520657669746341796c656572',
'061bffeeddccbbaa02010611074449555520657669746341796c65656c'
];
const EXPECTED_DATA_THIRD_PACKET = [
'061bffeeddccbbaa02010611074449555520657669746341796c656572',
'061bffeeddccbbaa02010611074449555520657669746341796c65656c'
];
const EXPECTED_DATA_FIRST_EVENT = [ Raddec.events.DISPLACEMENT ];
const EXPECTED_DATA_SECOND_EVENT = [ Raddec.events.DISPLACEMENT,
Raddec.events.PACKETS ];
const EXPECTED_DATA_THIRD_EVENT = [ Raddec.events.DISPLACEMENT,
Raddec.events.PACKETS ];
const EXPECTED_DATA_TIMESTAMP_ENCODING = '10002902aabbccddeeff02550101001bc50940810001350401001bc50940810000f0014aa31759006c';
const EXPECTED_DATA_PACKET_ENCODING = '10007e02aabbccddeeff02550101001bc50940810001350401001bc50940810000f1031d061bffeeddccbbaa02010611074449555520657669746341796c6565721d061bffeeddccbbaa02010611074449555520657669746341796c65656c1d061bffeeddccbbaa02010611074449555520657669746341796c656576ef';
const EXPECTED_DATA_EVENTS_ENCODING = '10002402aabbccddeeff02550101001bc50940810001350401001bc50940810000f20611';
const EXPECTED_DATA_POSITION_ENCODING = '100034053074257bf7194e4000001a85012f0102001122334455f3c052648ede54b48d4046c122a6f3f5307fffffffffffffff05';
const EXPECTED_DATA_MERGE_RSSI_SIGNATURE = [{
receiverId: "001bc50940810001",
receiverIdType: 1,
rssi: -42,
rssiSum: -42,
numberOfDecodings: 1
},{
receiverId: "001bc50940810000",
receiverIdType: 1,
rssi: -74,
rssiSum: -295,
numberOfDecodings: 4
}];
const EXPECTED_DATA_MERGE_PACKET = [
'061bffeeddccbbaa02010611074449555520657669746341796c656572',
'061bffeeddccbbaa02010611074449555520657669746341796c65656c',
'061bffeeddccbbaa02010611074449555520657669746341796c656576'
];
const EXPECTED_DATA_MERGE_EARLIEST_DECODING_TIME = 1420075424000;
const EXPECTED_DATA_HEX_STRING_RADDEC = {
transmitterId: "aabbccddeeff",
transmitterIdType: 2,
rssiSignature: [{
receiverId: "001bc50940810000",
receiverIdType: 1,
rssi: -74,
numberOfDecodings: 4
},{
receiverId: "001bc50940810001",
receiverIdType: 1,
rssi: -42,
numberOfDecodings: 1
}]
};
const EXPECTED_DATA_HEX_STRING_RADDEC_OPTIONS = {
transmitterId: "aabbccddeeff",
transmitterIdType: 2,
rssiSignature: [{
receiverId: "001bc50940810001",
receiverIdType: 1,
rssi: -42,
numberOfDecodings: 1
},{
receiverId: "001bc50940810000",
receiverIdType: 1,
rssi: -74,
numberOfDecodings: 4
}],
timestamp: 1420075424000,
packets: [
"061bffeeddccbbaa02010611074449555520657669746341796c656572",
"061bffeeddccbbaa02010611074449555520657669746341796c65656c",
"061bffeeddccbbaa02010611074449555520657669746341796c656576"
],
events: [ Raddec.events.DISPLACEMENT, Raddec.events.PACKETS ],
position: [ -73.57122, 45.50887 ]
};
const EXPECTED_DATA_BUFFER_RADDEC = EXPECTED_DATA_HEX_STRING_RADDEC;
const EXPECTED_DATA_FLATTENED_RADDEC = {
transmitterId: "aabbccddeeff",
transmitterIdType: 2,
receiverId: "001bc50940810000",
receiverIdType: 1,
rssi: -77,
numberOfDecodings: 2,
numberOfReceivers: 2,
packets: [ '061bffeeddccbbaa02010611074449555520657669746341796c656576' ],
numberOfDistinctPackets: 1,
timestamp: 1420075424000,
events: [ 0 ]
};
const EXPECTED_DATA_FLATTENED_MINIMAL_RADDEC = {
transmitterId: "aabbccddeeff",
transmitterIdType: 2,
timestamp: 1420075424000
};
const EXPECTED_DATA_FLATTENED_RADDEC_WITH_OPTIONS = {
transmitterId: "aabbccddeeff",
transmitterIdType: 2,
receiverId: "001bc50940810000",
receiverIdType: 1,
rssi: -77,
rssiSignature: [{
receiverId: "001bc50940810000",
receiverIdType: 1,
rssi: -77,
numberOfDecodings: 2
}],
numberOfDecodings: 2,
numberOfReceivers: 2,
numberOfDistinctPackets: 1,
timestamp: 1420075424000,
events: [ 0 ]
};
const EXPECTED_DATA_TRIM_RADDEC = {
transmitterId: "aabbccddeeff",
transmitterIdType: 2,
packets: [ '061bffeeddccbbaa02010611074449555520657669746341796c656576' ],
rssiSignature: [{
receiverId: "001bc50940810000",
receiverIdType: 1,
receiverAntenna: 1,
rssi: -77,
numberOfDecodings: 2,
aoa: [ 180, -45 ]
}],
position: [ -73.57122, 45.50887, 69 ],
protocolSpecificData: {},
timestamp: 1420075424000
};
// Describe the scenario
describe('raddec', function() {
let raddec = new Raddec(INPUT_DATA_TRANSMITTER);
// Test the constructor
it('should construct a bare Raddec', function() {
assert.equal(raddec.transmitterId, EXPECTED_DATA_TRANSMITTER_ID);
assert.equal(raddec.transmitterIdType, EXPECTED_DATA_TRANSMITTER_ID_TYPE);
assert.deepEqual(raddec.rssiSignature, EXPECTED_DATA_BARE_RSSI_SIGNATURE);
});
// Test the encoder with rssiSignature length 0
it('should encode a bare Raddec', function() {
assert.equal(raddec.encodeAsHexString(), EXPECTED_DATA_BARE_ENCODING);
});
// Test the addDecoding function
it('should add a decoding', function() {
raddec.addDecoding(INPUT_DATA_FIRST_DECODING);
assert.deepEqual(raddec.rssiSignature, EXPECTED_DATA_FIRST_RSSI_SIGNATURE);
assert.equal(raddec.earliestDecodingTime,
EXPECTED_DATA_FIRST_EARLIEST_TIME);
});
// Test the encoder with rssiSignature length 1
it('should encode a Raddec with one rssiSignature element', function() {
assert.equal(raddec.encodeAsHexString(), EXPECTED_DATA_FIRST_ENCODING);
});
// Test the addDecoding function for a same receiver
it('should add a decoding for an existing receiver', function() {
raddec.addDecoding(INPUT_DATA_SECOND_DECODING);
assert.deepEqual(raddec.rssiSignature, EXPECTED_DATA_SECOND_RSSI_SIGNATURE);
assert.equal(raddec.earliestDecodingTime,
EXPECTED_DATA_SECOND_EARLIEST_TIME);
});
// Test the addDecoding function for a new receiver
it('should add a decoding for a new receiver', function() {
raddec.addDecoding(INPUT_DATA_THIRD_DECODING);
assert.deepEqual(raddec.rssiSignature, EXPECTED_DATA_THIRD_RSSI_SIGNATURE);
assert.equal(raddec.earliestDecodingTime,
EXPECTED_DATA_THIRD_EARLIEST_TIME);
});
// Test the encoder with rssiSignature length 2
it('should encode a Raddec with two rssiSignature elements', function() {
assert.equal(raddec.encodeAsHexString(), EXPECTED_DATA_THIRD_ENCODING);
});
// Test the addPacket function
it('should add a packet', function() {
raddec.addPacket(INPUT_DATA_FIRST_PACKET);
assert.deepEqual(raddec.packets, EXPECTED_DATA_FIRST_PACKET);
});
// Test the addPacket function with a new packet
it('should add a new packet', function() {
raddec.addPacket(INPUT_DATA_SECOND_PACKET);
assert.deepEqual(raddec.packets, EXPECTED_DATA_SECOND_PACKET);
});
// Test the addPacket function with an existing packet
it('should not add an existing packet again', function() {
raddec.addPacket(INPUT_DATA_THIRD_PACKET);
assert.deepEqual(raddec.packets, EXPECTED_DATA_THIRD_PACKET);
});
// Test the addEvent function
it('should add an event', function() {
raddec.addEvent(INPUT_DATA_FIRST_EVENT);
assert.deepEqual(raddec.events, EXPECTED_DATA_FIRST_EVENT);
});
// Test the addEvent function with a new event
it('should add another event', function() {
raddec.addEvent(INPUT_DATA_SECOND_EVENT);
assert.deepEqual(raddec.events, EXPECTED_DATA_SECOND_EVENT);
});
// Test the addEvent function with an existing event
it('should not add an existing event again', function() {
raddec.addEvent(INPUT_DATA_THIRD_EVENT);
assert.deepEqual(raddec.events, EXPECTED_DATA_THIRD_EVENT);
});
// Test the merge function with another raddec
it('should merge the given raddec into the current', function() {
raddec.merge(new Raddec(INPUT_DATA_MERGE_RADDEC));
assert.deepEqual(raddec.rssiSignature, EXPECTED_DATA_MERGE_RSSI_SIGNATURE);
assert.deepEqual(raddec.packets, EXPECTED_DATA_MERGE_PACKET);
assert.equal(raddec.earliestDecodingTime,
EXPECTED_DATA_MERGE_EARLIEST_DECODING_TIME);
});
// Test the encoder with optional timestamp
it('should encode a Raddec with optional timestamp', function() {
assert.equal(raddec.encodeAsHexString({ includeTimestamp: true }),
EXPECTED_DATA_TIMESTAMP_ENCODING);
});
// Test the encoder with optional packets
it('should encode a Raddec with optional packets', function() {
assert.equal(raddec.encodeAsHexString({ includePackets: true }),
EXPECTED_DATA_PACKET_ENCODING);
});
// Test the encoder with optional events
it('should encode a Raddec with optional events', function() {
assert.equal(raddec.encodeAsHexString({ includeEvents: true }),
EXPECTED_DATA_EVENTS_ENCODING);
});
// Test the encoder with optional position
it('should encode a Raddec with optional position', function() {
raddec = new Raddec(INPUT_DATA_POSITION_RADDEC);
assert.equal(raddec.encodeAsHexString({ includePosition: true }),
EXPECTED_DATA_POSITION_ENCODING);
});
// Test the constructor from hexadecimal string
it('should construct a Raddec from hexadecimal string', function() {
raddec = new Raddec(INPUT_DATA_HEX_STRING_RADDEC);
delete raddec['creationTime'];
assert.deepEqual(raddec, EXPECTED_DATA_HEX_STRING_RADDEC);
});
// Test the constructor from hexadecimal string with optional properties
it('should construct a Raddec from hexadecimal string', function() {
raddec = new Raddec(INPUT_DATA_HEX_STRING_RADDEC_OPTIONS);
delete raddec['creationTime'];
assert.deepEqual(raddec, EXPECTED_DATA_HEX_STRING_RADDEC_OPTIONS);
});
// Test the constructor from Buffer
it('should construct a Raddec from Buffer', function() {
raddec = new Raddec(INPUT_DATA_BUFFER_RADDEC);
delete raddec['creationTime'];
assert.deepEqual(raddec, EXPECTED_DATA_BUFFER_RADDEC);
});
// Test the toFlattened function
it('should create a flattened representation of the Raddec', function() {
raddec = new Raddec(INPUT_DATA_FLATTENED_RADDEC);
assert.deepEqual(raddec.toFlattened(), EXPECTED_DATA_FLATTENED_RADDEC);
});
// Test the toFlattened function with options
it('should create a flattened Raddec with options', function() {
raddec = new Raddec(INPUT_DATA_FLATTENED_RADDEC);
assert.deepEqual(raddec.toFlattened(INPUT_OPTIONS_FLATTENED),
EXPECTED_DATA_FLATTENED_RADDEC_WITH_OPTIONS);
});
// Test the toFlattened function with a minimal raddec
it('should create a flattened representation of the min Raddec', function() {
raddec = new Raddec(INPUT_DATA_FLATTENED_MINIMAL_RADDEC);
assert.deepEqual(raddec.toFlattened(),
EXPECTED_DATA_FLATTENED_MINIMAL_RADDEC);
});
// Test the trim function
it('should trim non-standard properties from the Raddec', function() {
raddec = new Raddec(INPUT_DATA_TRIM_RADDEC);
raddec.isNonStandardProperty = true;
raddec.trim();
assert.deepEqual(raddec, EXPECTED_DATA_TRIM_RADDEC);
});
});