@iotize/tap
Version:
IoTize Device client for Javascript
185 lines (178 loc) • 6.32 kB
JavaScript
import { bitWiseAnd, bitWiseOr } from '@iotize/common/byte-stream';
import { TapStreamWriter, TapStreamReader } from '@iotize/tap/client/impl';
var CanSignal;
(function (CanSignal) {
let Endianess;
(function (Endianess) {
Endianess["BIG_ENDIAN"] = "BIG_ENDIAN";
Endianess["LITTLE_ENDIAN"] = "LITTLE_ENDIAN";
})(Endianess = CanSignal.Endianess || (CanSignal.Endianess = {}));
})(CanSignal || (CanSignal = {}));
const DBC_DATA_FRAME_LENGTH = 8;
function encodeCanMessage(input, signals) {
const result = TapStreamWriter.create(DBC_DATA_FRAME_LENGTH);
for (const [attrName, signal] of Object.entries(signals)) {
// TODO improve exception with try catch to know with field fail
tapStreamWriteCanSignal(input[attrName], signal, result);
}
result.pos = DBC_DATA_FRAME_LENGTH;
return result.toBytes;
}
function decodeCanMessage(stream, signals) {
if (stream instanceof Uint8Array) {
stream = new TapStreamReader(stream);
}
const result = {};
for (const [attrName, signal] of Object.entries(signals)) {
result[attrName] = tapStreamReadCanSignal(stream, signal);
}
return result;
}
function dbcBitPositionToDataFrameIndex(start) {
const index = Math.abs((start % 8) - 7); // Equivalent de [-7, -5, -3, -1, 1, 3, 5, 7]
return start + (-7 + 2 * index);
}
function tapStreamReadCanSignal(stream, signal) {
const { bitLength } = signal;
checkMaxLength(bitLength);
if (stream instanceof Uint8Array) {
stream = new TapStreamReader(stream);
}
const result = readBitsFromDbcSignalStream(stream, signal);
return decodeSignalValueNumber(result, signal);
}
function readBitsFromDbcSignalStream(stream, { endianess, startBit, bitLength }) {
const startIndex = dbcBitPositionToDataFrameIndex(startBit);
let result;
if (endianess === CanSignal.Endianess.LITTLE_ENDIAN) {
result = 0 >>> 0;
for (let dbcPosition = startBit + bitLength - 1; dbcPosition >= startBit; dbcPosition--) {
let frameIndex = dbcBitPositionToDataFrameIndex(dbcPosition);
stream.setBitPosition(frameIndex);
result = result * 2 + stream.readBits(1);
}
}
else {
stream.pos = 0;
stream.forwardBits(startIndex);
result = stream.readBitsInt(bitLength);
}
return result;
}
function decodeSignalValueNumber(result, { offset, scaling, signed, bitLength: length }) {
if (signed) {
result = fromSignedOnNBits(result, length);
}
if (scaling !== undefined) {
result = result * scaling;
}
if (offset !== undefined) {
result = result + offset;
}
return result;
}
function encodeSignalValueNumber(value, { offset, scaling, signed, bitLength: length }) {
if (offset !== undefined) {
value = value - offset;
}
if (scaling !== 0 && scaling !== undefined) {
value = Math.round(value / scaling);
}
if (signed) {
value = toSignedOnNBits(value, length);
}
return value;
}
function tapStreamWriteCanSignal(value, signal, stream) {
const { bitLength: length } = signal;
checkMaxLength(length);
value = encodeSignalValueNumber(value, signal);
writeBitsToDbcMessageStream(stream, value, signal);
}
function writeBitsToDbcMessageStream(stream, value, { endianess, startBit, bitLength, }) {
if (endianess === CanSignal.Endianess.LITTLE_ENDIAN) {
let mask = bitShift1(bitLength - 1);
for (let dbcPosition = startBit + bitLength - 1; dbcPosition >= startBit; dbcPosition--) {
let frameIndex = dbcBitPositionToDataFrameIndex(dbcPosition);
stream.setBitPosition(frameIndex);
const bitValue = bitWiseAnd(value, mask);
stream.writeBoolean(bitValue, 1);
mask = mask / 2;
}
}
else {
const startIndex = dbcBitPositionToDataFrameIndex(startBit);
stream.pos = 0;
stream.forwardBits(startIndex);
stream.writeBits(value, bitLength);
}
}
function checkMaxLength(length) {
if (length > 52) {
// TODO proper error
throw new Error(`CAN signal with bit length > 52 bits are not supported`);
}
}
function fromSignedOnNBits(value, length) {
checkMaxLength(length);
const signedMask = bitShift1(length - 1);
const negative = bitWiseAnd(value, signedMask) != 0;
if (negative) {
const valueMask = signedMask - 1;
const cp2 = bitWiseAnd(valueMask, value);
return cp2 - signedMask;
}
else {
return value;
}
}
function toSignedOnNBits(value, length) {
checkMaxLength(length);
if (value < 0) {
if (value < -Math.pow(2, length)) {
throw new Error(`Value ${value} is too small to be encoded as a signed on ${length} bits`);
}
const signedMask = bitShift1(length - 1);
const valueMask = signedMask - 1;
const cp2 = bitWiseAnd(valueMask, value >>> 0);
const result = bitWiseOr(cp2, signedMask);
return result;
}
else {
if (value >= Math.pow(2, length)) {
throw new Error(`Value ${value} is too big to be encoded as a signed on ${length} bits`);
}
return value;
}
}
function bitShift1(size) {
return Math.pow(2, size);
}
class CanSignalStreamConverter {
constructor(options) {
this.options = options;
}
encode(value, stream) {
tapStreamWriteCanSignal(value, this.options.signal, stream);
}
decode(value) {
return tapStreamReadCanSignal(value, this.options.signal);
}
}
class CanMessageConverter {
constructor(options) {
this.options = options;
}
encode(msg) {
return encodeCanMessage(msg, this.options.signals);
}
decode(data) {
const stream = new TapStreamReader(data);
return decodeCanMessage(stream, this.options.signals);
}
}
/**
* Generated bundle index. Do not edit.
*/
export { CanMessageConverter, CanSignal, CanSignalStreamConverter, decodeCanMessage, encodeCanMessage };
//# sourceMappingURL=iotize-tap-target-can-dbc.js.map