diff --git a/src/zspec/zcl/buffaloZcl.ts b/src/zspec/zcl/buffaloZcl.ts index 0d3c2314be..a8ed279299 100644 --- a/src/zspec/zcl/buffaloZcl.ts +++ b/src/zspec/zcl/buffaloZcl.ts @@ -623,10 +623,7 @@ export class BuffaloZcl extends Buffalo { return value; } - // private writeMiStruct(value: Record): { - // XXX: read only? - // } - + // NOTE: writeMiStruct is not supported. private readMiStruct(): Record { const length = this.readUInt8(); const value: Record = {}; @@ -640,7 +637,12 @@ export class BuffaloZcl extends Buffalo { const dataType = this.readUInt8(); value[index] = this.read(dataType, {}); - if (this.position === this.buffer.length) { + const remaining = this.buffer.length - this.position; + if (remaining <= 1) { + if (remaining == 1) { + // Some Xiaomi structs have a trailing byte, skip it. + this.position += 1; + } break; } } diff --git a/test/zcl.test.ts b/test/zcl.test.ts index b2a731b30d..a97c92446b 100644 --- a/test/zcl.test.ts +++ b/test/zcl.test.ts @@ -484,11 +484,51 @@ describe('Zcl', () => { expect(frame.payload).toStrictEqual(payload); }); - it('ZclFrame from buffer xiaomiStruct', () => { - const buffer = Buffer.from([ - 28, 95, 17, 3, 10, 5, 0, 66, 21, 108, 117, 109, 105, 46, 115, 101, 110, 115, 111, 114, 95, 119, 108, 101, 97, 107, 46, 97, 113, 49, 1, - 255, 66, 34, 1, 33, 213, 12, 3, 40, 33, 4, 33, 168, 19, 5, 33, 43, 0, 6, 36, 0, 0, 5, 0, 0, 8, 33, 4, 2, 10, 33, 0, 0, 100, 16, 0, - ]); + test.each([ + [ + [ + 28, 95, 17, 3, 10, 1, 255, 66, 68, 3, 40, 29, 5, 33, 190, 45, 8, 33, 47, 18, 9, 33, 2, 21, 100, 16, 1, 101, 16, 0, 110, 32, 255, 111, + 32, 255, 148, 32, 4, 149, 57, 184, 30, 21, 62, 150, 57, 211, 249, 17, 69, 151, 57, 0, 48, 104, 59, 152, 57, 0, 0, 0, 0, 155, 33, 1, 0, + 156, 32, 1, 10, 33, 56, 38, 12, 40, 0, 0, + ], + [ + { + attrId: 65281, + dataType: 66, + attrData: { + '3': 29, + '5': 11710, + '8': 4655, + '9': 5378, + '10': 9784, + '12': 0, + '100': 1, + '101': 0, + '110': 255, + '111': 255, + '148': 4, + '149': 0.14562499523162842, + '150': 2335.614013671875, + '151': 0.0035429000854492188, + '152': 0, + '155': 1, + '156': 1, + }, + }, + ], + ], + [ + [ + 28, 95, 17, 3, 10, 5, 0, 66, 21, 108, 117, 109, 105, 46, 115, 101, 110, 115, 111, 114, 95, 119, 108, 101, 97, 107, 46, 97, 113, 49, 1, + 255, 66, 34, 1, 33, 213, 12, 3, 40, 33, 4, 33, 168, 19, 5, 33, 43, 0, 6, 36, 0, 0, 5, 0, 0, 8, 33, 4, 2, 10, 33, 0, 0, 100, 16, 0, + ], + [ + {attrId: 5, dataType: 66, attrData: 'lumi.sensor_wleak.aq1'}, + {attrId: 65281, dataType: 66, attrData: {'1': 3285, '3': 33, '4': 5032, '5': 43, '6': 327680, '8': 516, '10': 0, '100': 0}}, + ], + ], + ])('ZclFrame from buffer xiaomiStruct', (data, payload) => { + const buffer = Buffer.from(data); const frame = Zcl.Frame.fromBuffer(Zcl.Clusters.genBasic.ID, Zcl.Header.fromBuffer(buffer)!, buffer, {}); const header = new Zcl.Header( { @@ -503,11 +543,6 @@ describe('Zcl', () => { 10, ); - const payload = [ - {attrId: 5, dataType: 66, attrData: 'lumi.sensor_wleak.aq1'}, - {attrId: 65281, dataType: 66, attrData: {'1': 3285, '3': 33, '4': 5032, '5': 43, '6': 327680, '8': 516, '10': 0, '100': 0}}, - ]; - expect(frame.header).toStrictEqual(header); expect(frame.payload).toStrictEqual(payload); });