UNPKG

knxultimate

Version:

KNX IP protocol implementation for Node. This is the ENGINE of Node-Red KNX-Ultimate node.

107 lines (98 loc) 3.22 kB
export function hasProp(obj: any, prop: string): boolean { return Object.prototype.hasOwnProperty.call(obj, prop) } export function hex2bin(hex: string) { return parseInt(hex, 16).toString(2).padStart(8, '0') } export function hexToDec(hex: string) { let result = 0 let digitValue: number hex = hex.toLowerCase() for (let i = 0; i < hex.length; i++) { digitValue = '0123456789abcdefgh'.indexOf(hex[i]) result = result * 16 + digitValue } return result } /** * Convert `mantissa` and `exponent` into a float32 number *kudos to http://croquetweak.blogspot.gr/2014/08/deconstructing-floats-frexp-and-ldexp.html */ export function ldexp(mantissa: number, exponent: number) { // eslint-disable-next-line no-nested-ternary return exponent > 1023 // avoid multiplying by infinity ? mantissa * 2 ** 1023 * 2 ** (exponent - 1023) : exponent < -1074 // avoid multiplying by zero ? mantissa * 2 ** -1074 * 2 ** (exponent + 1074) : mantissa * 2 ** exponent } /** * Decompose a float32 number into [mantissa, exponent] */ export function frexp(value: number) { if (value === 0) return [value, 0] const data = new DataView(new ArrayBuffer(8)) data.setFloat64(0, value) let bits = (data.getUint32(0) >>> 20) & 0x7ff if (bits === 0) { data.setFloat64(0, value * 2 ** 64) bits = ((data.getUint32(0) >>> 20) & 0x7ff) - 64 } const exponent = bits - 1022 const mantissa = ldexp(value, -exponent) return [mantissa, exponent] } /** * Convert a float32 number into a 2-byte array */ export function getHex(_value: number) { try { const arr = frexp(_value) const mantissa = arr[0] const exponent = arr[1] // find the minimum exponent that will upsize the normalized mantissa (0,5 to 1 range) // in order to fit in 11 bits ([-2048, 2047]) let max_mantissa = 0 let e: number for (e = exponent; e >= -15; e--) { max_mantissa = ldexp(100 * mantissa, e) if (max_mantissa > -2048 && max_mantissa < 2047) break } const sign = mantissa < 0 ? 1 : 0 const mant = mantissa < 0 ? ~(max_mantissa ^ 2047) : max_mantissa const exp = exponent - e return [(sign << 7) + (exp << 3) + (mant >> 8), mant % 256] } catch (error) { return null } } /** * Convert a 2-byte array into a float32 number */ export function getFloat(_value0: number, _value1: number) { const sign = _value0 >> 7 const exponent = (_value0 & 0b01111000) >> 3 let mantissa = 256 * (_value0 & 0b00000111) + _value1 mantissa = sign === 1 ? ~(mantissa ^ 2047) : mantissa return parseFloat(ldexp(0.01 * mantissa, exponent).toPrecision(15)) } /** * Round a number to a given number of decimals */ export function round(value: number, decimals: number) { return Number(`${Math.round(Number(`${value}e${decimals}`))}e-${decimals}`) } /** * Get current timestamp. Used for debug level logging, at telegram's level. */ export function getTimestamp() { const now = new Date() const seconds = now.getSeconds().toString().padStart(2, '0') // Secondi con due cifre const milliseconds = now.getMilliseconds().toString().padStart(3, '0') // Millisecondi con tre cifre return `${seconds}.${milliseconds}` } export function wait(ms: number) { return new Promise<void>((r) => { setTimeout(r, ms) }) }