All files / src advertising.ts

93.55% Statements 29/31
90% Branches 9/10
100% Functions 2/2
96.67% Lines 29/30
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72                                  1x 3x 3x 3x 3x 3x 8x 8x 8x 3x 3x 3x   5x         1x       4x 3x     1x     4x 4x 4x 4x   4x 4x 12x 12x 12x 12x         4x   4x                
import {Buffer} from 'buffer/';
 
/** Hunter Douglas Shade Advertising Data*/
export interface HDAdvertisingData {
    modelID: number;
    capabilities: number;
    security: number;
    ptbes: PTBE[]
    shadeState: number;
}
 
/** Position & Tilt Byte Encoding*/
export interface PTBE {
    isTilt: boolean;
    value: number;
}
 
const findMfgData = (buffer: Buffer) : Buffer => {
    let index: number = 0;
    const mfgDataLen: number = 7;
    const advMfgDataPacketLen: number = mfgDataLen + 1;
    const mfgDataType = 0xff; // Ble spec
    while ( index < (buffer.length - advMfgDataPacketLen) ) {
        let fieldLength: number = buffer[index];
        let fieldType: number = buffer[index + 1];
        if ( (fieldType === mfgDataType) && (fieldLength === advMfgDataPacketLen) ) {
            let mfgDataIndex: number = index + 2;
            buffer = buffer.slice(mfgDataIndex, mfgDataIndex + mfgDataLen);
            return buffer;
        }
        index += fieldLength + 1;
    }
    return buffer;
}
 
export const parseAdvertisingData = (iBuffer: Buffer): HDAdvertisingData => {
    let buffer: Buffer;
    // IOS iBuffer is the manufacturer specific data only (7 bytes)
    // Other devices parse the entire BLE advertisement packet
    if(iBuffer.length > 7) {
        buffer = findMfgData(iBuffer);
    }
    else {
        buffer = iBuffer;
    }
 
    Iif ( buffer.length != 7 ) { throw new Error(`Received ${buffer.length} byte manuData, expected 7`) }
    const modelID = buffer.readUInt8(0);
    const capabilities = buffer.readUInt8(1);
    const security = buffer.readUInt8(2);
 
    const ptbes: PTBE[] = [];
    for ( let i=3; i<buffer.length-1; i++) {
        const byte = buffer.readUInt8(i);
        const isTilt = (byte & 128) === 128;
        const value = (isTilt ? byte - 128 : byte) / 100;
        ptbes.push({
            isTilt, value
        });
    }
 
    const shadeState = buffer.readUInt8(6);
 
    return {
        modelID,
        capabilities,
        security,
        ptbes,
        shadeState
    }
}