UNPKG

@iotize/tap

Version:

IoTize Device client for Javascript

185 lines (178 loc) 6.32 kB
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