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
}
}
|