Skip to content

Commit

Permalink
fix!: Fix always use number for reportableChange (#1190)
Browse files Browse the repository at this point in the history
* fix: Fix `int40`, `uint48` and `uint40` parsing

* Remove all sb

* Process feedback
  • Loading branch information
Koenkk authored Sep 17, 2024
1 parent 741b9c8 commit e30d7b7
Show file tree
Hide file tree
Showing 9 changed files with 169 additions and 242 deletions.
12 changes: 6 additions & 6 deletions src/adapter/zboss/uart.ts
Original file line number Diff line number Diff line change
Expand Up @@ -392,15 +392,15 @@ export class ZBOSSUart extends EventEmitter {
/* Construct a package */
const packLen = 5 + (data ? data.length + 2 : 0);
const header = Buffer.alloc(7);
header.writeUint16BE(SIGNATURE);
header.writeUint16LE(packLen, 2);
header.writeUint8(ZBOSS_NCP_API_HL, 4);
header.writeUint8(flags, 5);
header.writeUInt16BE(SIGNATURE);
header.writeUInt16LE(packLen, 2);
header.writeUInt8(ZBOSS_NCP_API_HL, 4);
header.writeUInt8(flags, 5);
const hCRC8 = crc8(header.subarray(2, 6));
header.writeUint8(hCRC8, 6);
header.writeUInt8(hCRC8, 6);
if (data) {
const pCRC16 = Buffer.alloc(2);
pCRC16.writeUint16LE(crc16(data));
pCRC16.writeUInt16LE(crc16(data));
return Buffer.concat([header, pCRC16, data]);
} else {
return header;
Expand Down
53 changes: 53 additions & 0 deletions src/buffalo/buffalo.ts
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,30 @@ class Buffalo {
return value;
}

public writeUInt56(value: bigint): void {
this.buffer.writeUIntLE(Number(value & 0xffffffffffffn), this.position, 6);
this.buffer.writeUInt8(Number(value >> 48n), this.position + 6);
this.position += 7;
}

public readUInt56(): bigint {
const low = this.buffer.readUIntLE(this.position, 6);
const high = this.buffer.readUInt8(this.position + 6);
this.position += 7;
return (BigInt(high) << 48n) | BigInt(low);
}

public writeUInt64(value: bigint): void {
this.buffer.writeBigUInt64LE(value, this.position);
this.position += 8;
}

public readUInt64(): bigint {
const value = this.buffer.readBigUInt64LE(this.position);
this.position += 8;
return value;
}

public writeInt8(value: number): void {
this.buffer.writeInt8(value, this.position);
this.position++;
Expand Down Expand Up @@ -157,6 +181,35 @@ class Buffalo {
return value;
}

public writeInt56(value: bigint): void {
const unsignedValue = value < 0n ? (1n << 56n) + value : value;
this.buffer.writeUIntLE(Number(unsignedValue & 0xffffffffffffn), this.position, 6);
this.buffer.writeUInt8(Number(unsignedValue >> 48n), this.position + 6);
this.position += 7;
}

public readInt56(): bigint {
const low = BigInt(this.buffer.readUIntLE(this.position, 6));
const high = BigInt(this.buffer.readUInt8(this.position + 6));
let result = (high << 48n) | low;
if (high & 0x80n) {
result -= 1n << 56n;
}
this.position += 7;
return result;
}

public writeInt64(value: bigint): void {
this.buffer.writeBigInt64LE(value, this.position);
this.position += 8;
}

public readInt64(): bigint {
const value = this.buffer.readBigInt64LE(this.position);
this.position += 8;
return value;
}

public writeFloatLE(value: number): void {
this.buffer.writeFloatLE(value, this.position);
this.position += 4;
Expand Down
2 changes: 1 addition & 1 deletion src/controller/model/endpoint.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ export interface ConfigureReportingItem {
attribute: string | number | {ID: number; type: number};
minimumReportInterval: number;
maximumReportInterval: number;
reportableChange: number | [number, number];
reportableChange: number;
}

interface Options {
Expand Down
116 changes: 14 additions & 102 deletions src/zspec/zcl/buffaloZcl.ts
Original file line number Diff line number Diff line change
Expand Up @@ -125,94 +125,6 @@ interface MiboxerZone {
}

export class BuffaloZcl extends Buffalo {
// TODO: remove read/write int "SB" versions in favor of plain numbers, implemented in buffalo.ts

private writeUInt40SB(value: number[]): void {
this.writeUInt32(value[1]);
this.writeUInt8(value[0]);
}

private readUInt40SB(): [number, number] {
const lsb = this.readUInt32();
const msb = this.readUInt8();
return [msb, lsb];
}

private writeUInt48SB(value: number[]): void {
this.writeUInt32(value[1]);
this.writeUInt16(value[0]);
}

private readUInt48SB(): [number, number] {
const lsb = this.readUInt32();
const msb = this.readUInt16();
return [msb, lsb];
}

private writeUInt56SB(value: number[]): void {
// XXX: [uint32, uint32] param not following read return pattern [uint32, uint16, uint8]
const temp = Buffer.alloc(8);
temp.writeUInt32LE(value[1], 0);
temp.writeUInt32LE(value[0], 4);
this.writeBuffer(temp.subarray(0, 7), 7);
}

private readUInt56SB(): [number, number, number] {
const lsb = this.readUInt32();
const xsb = this.readUInt16();
const msb = this.readUInt8();
return [msb, xsb, lsb];
}

private readUInt64SB(): string {
// XXX: not following pattern, should return as [msb, lsb]
return this.readIeeeAddr();
}

private writeUInt64SB(value: string): void {
// XXX: not following pattern, should pass as number[uint32, uint32]
const msb = parseInt(value.slice(2, 10), 16);
const lsb = parseInt(value.slice(10), 16);
this.writeUInt32(lsb);
this.writeUInt32(msb);
}

private writeInt40SB(value: number[]): void {
this.writeInt32(value[1]);
this.writeInt8(value[0]);
}

private readInt40SB(): [number, number] {
const lsb = this.readInt32();
const msb = this.readInt8();
return [msb, lsb];
}

private writeInt56SB(value: number[]): void {
const temp = Buffer.alloc(8);
temp.writeInt32LE(value[1], 0);
temp.writeInt32LE(value[0], 4);
this.writeBuffer(temp.subarray(0, 7), 7);
}

private readInt56SB(): [number, number, number] {
const lsb = this.readInt32();
const xsb = this.readInt16();
const msb = this.readInt8();
return [msb, xsb, lsb];
}

private writeInt64SB(value: number[]): void {
this.writeInt32(value[1]);
this.writeInt32(value[0]);
}

private readInt64SB(): [number, number] {
const lsb = this.readInt32();
const msb = this.readInt32();
return [msb, lsb];
}

private writeOctetStr(value: number[]): void {
// TODO: this does not allow "non-value" 0xFF
this.writeUInt8(value.length);
Expand Down Expand Up @@ -773,22 +685,22 @@ export class BuffaloZcl extends Buffalo {
case DataType.DATA40:
case DataType.BITMAP40:
case DataType.UINT40: {
return this.writeUInt40SB(value);
return this.writeUInt40(value);
}
case DataType.DATA48:
case DataType.BITMAP48:
case DataType.UINT48: {
return this.writeUInt48SB(value);
return this.writeUInt48(value);
}
case DataType.DATA56:
case DataType.BITMAP56:
case DataType.UINT56: {
return this.writeUInt56SB(value);
return this.writeUInt56(value);
}
case DataType.DATA64:
case DataType.BITMAP64:
case DataType.UINT64: {
return this.writeUInt64SB(value);
return this.writeUInt64(value);
}
case DataType.INT8: {
return this.writeInt8(value);
Expand All @@ -803,16 +715,16 @@ export class BuffaloZcl extends Buffalo {
return this.writeInt32(value);
}
case DataType.INT40: {
return this.writeInt40SB(value);
return this.writeInt40(value);
}
case DataType.INT48: {
return this.writeInt48(value);
}
case DataType.INT56: {
return this.writeInt56SB(value);
return this.writeInt56(value);
}
case DataType.INT64: {
return this.writeInt64SB(value);
return this.writeInt64(value);
}
// case DataType.SEMI_PREC: {
// // https://tc39.es/proposal-float16array/
Expand Down Expand Up @@ -957,22 +869,22 @@ export class BuffaloZcl extends Buffalo {
case DataType.DATA40:
case DataType.BITMAP40:
case DataType.UINT40: {
return this.readUInt40SB();
return this.readUInt40();
}
case DataType.DATA48:
case DataType.BITMAP48:
case DataType.UINT48: {
return this.readUInt48SB();
return this.readUInt48();
}
case DataType.DATA56:
case DataType.BITMAP56:
case DataType.UINT56: {
return this.readUInt56SB();
return this.readUInt56();
}
case DataType.DATA64:
case DataType.BITMAP64:
case DataType.UINT64: {
return this.readUInt64SB();
return this.readUInt64();
}
case DataType.INT8: {
return this.readInt8();
Expand All @@ -987,16 +899,16 @@ export class BuffaloZcl extends Buffalo {
return this.readInt32();
}
case DataType.INT40: {
return this.readInt40SB();
return this.readInt40();
}
case DataType.INT48: {
return this.readInt48();
}
case DataType.INT56: {
return this.readInt56SB();
return this.readInt56();
}
case DataType.INT64: {
return this.readInt64SB();
return this.readInt64();
}
// case DataType.SEMI_PREC: {
// // https://tc39.es/proposal-float16array/
Expand Down
62 changes: 62 additions & 0 deletions test/buffalo.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,68 @@ describe('Buffalo', () => {
expect(value).toStrictEqual(6618611909121);
});

it('UINT56 write', () => {
const buffalo = new Buffalo(Buffer.alloc(9), 2);
buffalo.writeUInt56(72057594037927934n);
expect(buffalo.getPosition()).toEqual(9);
expect(buffalo.getBuffer()).toStrictEqual(Buffer.from([0, 0, 254, 255, 255, 255, 255, 255, 255]));
});

it('UINT56 read', () => {
const buffalo = new Buffalo(Buffer.from([254, 255, 255, 255, 255, 255, 255]));
const value = buffalo.readUInt56();
expect(buffalo.getPosition()).toEqual(7);
expect(value).toStrictEqual(72057594037927934n);
});

it.each([
[36028797018963964n, [0, 0, 252, 255, 255, 255, 255, 255, 127]],
[-36028797018963964n, [0, 0, 4, 0, 0, 0, 0, 0, 128]],
])('INT56 write', (value: bigint, expectedValues: number[]) => {
const buffalo = new Buffalo(Buffer.alloc(9), 2);
buffalo.writeInt56(value);
expect(buffalo.getPosition()).toEqual(9);
expect(buffalo.getBuffer()).toStrictEqual(Buffer.from(expectedValues));
});

it.each([
[36028797018963964n, [252, 255, 255, 255, 255, 255, 127]],
[-36028797018963964n, [4, 0, 0, 0, 0, 0, 128]],
])('INT56 read', (expectedValue: bigint, values: number[]) => {
const buffalo = new Buffalo(Buffer.from(values));
const value = buffalo.readInt56();
expect(buffalo.getPosition()).toEqual(7);
expect(value).toStrictEqual(expectedValue);
});

it('UINT64 write', () => {
const buffalo = new Buffalo(Buffer.alloc(10), 2);
buffalo.writeUInt64(18446744073709551613n);
expect(buffalo.getPosition()).toEqual(10);
expect(buffalo.getBuffer()).toStrictEqual(Buffer.from([0, 0, 253, 255, 255, 255, 255, 255, 255, 255]));
});

it('UINT64 read', () => {
const buffalo = new Buffalo(Buffer.from([253, 255, 255, 255, 255, 255, 255, 255]));
const value = buffalo.readUInt64();
expect(buffalo.getPosition()).toEqual(8);
expect(value).toStrictEqual(18446744073709551613n);
});

it('INT64 write', () => {
const buffalo = new Buffalo(Buffer.alloc(10), 2);
buffalo.writeInt64(9223372036854775806n);
expect(buffalo.getPosition()).toEqual(10);
expect(buffalo.getBuffer()).toStrictEqual(Buffer.from([0, 0, 254, 255, 255, 255, 255, 255, 255, 127]));
});

it('INT64 read', () => {
const buffalo = new Buffalo(Buffer.from([254, 255, 255, 255, 255, 255, 255, 127]));
const value = buffalo.readInt64();
expect(buffalo.getPosition()).toEqual(8);
expect(value).toStrictEqual(9223372036854775806n);
});

it('IEEEADDR write', () => {
const buffalo = new Buffalo(Buffer.alloc(8));
buffalo.writeIeeeAddr(ieeeaAddr1.string);
Expand Down
6 changes: 3 additions & 3 deletions test/controller.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4019,7 +4019,7 @@ describe('Controller', () => {
'3': 33,
'4': 5032,
'5': 43,
'6': [0, 327680],
'6': 327680,
'8': 516,
},
modelId: 'lumi.sensor_wleak.aq1',
Expand Down Expand Up @@ -4080,7 +4080,7 @@ describe('Controller', () => {
'3': 33,
'4': 5032,
'5': 43,
'6': [0, 327680],
'6': 327680,
'8': 516,
},
modelId: 'lumi.sensor_wleak.aq1',
Expand All @@ -4094,7 +4094,7 @@ describe('Controller', () => {
'3': 33,
'4': 5032,
'5': 43,
'6': [0, 327680],
'6': 327680,
'8': 516,
'10': 0,
'100': 0,
Expand Down
Loading

0 comments on commit e30d7b7

Please sign in to comment.