Skip to content

Commit

Permalink
Add nullable to models to reflect SunSpec mandatory/optional fields
Browse files Browse the repository at this point in the history
  • Loading branch information
longzheng committed Jul 24, 2024
1 parent 02b0560 commit 7d859c8
Show file tree
Hide file tree
Showing 8 changed files with 343 additions and 203 deletions.
68 changes: 63 additions & 5 deletions src/sunspec/helpers/converters.test.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,19 @@
import { expect, it } from 'vitest';
import { describe, expect, it } from 'vitest';
import {
int16NullableToRegisters,
int16ToRegisters,
registersToAcc32,
registersToAcc64BigInt,
registersToInt16,
registersToInt16Nullable,
registersToString,
registersToStringNullable,
registersToSunssf,
registersToUint16,
registersToUint16Nullable,
registersToUint32,
registersToUint32Nullable,
uint16NullableToRegisters,
uint16ToRegisters,
} from './converters';

Expand All @@ -17,10 +23,38 @@ it('registersToUint32 should convert registers to a 32-bit unsigned integer', ()
expect(result).toBe(305419896);
});

it('registersToString should convert registers to a string', () => {
const registers = [0x4672, 0x6f6e, 0x6975, 0x7300];
const result = registersToString(registers);
expect(result).toBe('Fronius');
it('registersToUint32Nullabe should convert registers to null', () => {
const registers = [0xffff, 0xffff];
const result = registersToUint32Nullable(registers);
expect(result).toBe(null);
});

describe('registersToString', () => {
it('should convert registers to a string', () => {
const registers = [0x4672, 0x6f6e, 0x6975, 0x7300];
const result = registersToString(registers);
expect(result).toBe('Fronius');
});

it('should convert different size registers to a string', () => {
const registers = [0x4672];
const result = registersToString(registers);
expect(result).toBe('Fr');
});
});

describe('registersToString', () => {
it('should convert all registers with 0x0000 to null', () => {
const registers = [0x0000, 0x0000, 0x0000, 0x0000];
const result = registersToStringNullable(registers);
expect(result).toBe(null);
});

it('should convert some registers with 0x0000 to value', () => {
const registers = [0x0000, 0x4600, 0x0000, 0x0000];
const result = registersToStringNullable(registers);
expect(result).toBe('F');
});
});

it('registersToUint16 should convert registers to a 16-bit unsigned integer', () => {
Expand All @@ -29,12 +63,24 @@ it('registersToUint16 should convert registers to a 16-bit unsigned integer', ()
expect(result).toBe(4660);
});

it('registersToUint16Nullable should convert registers to null', () => {
const registers = [0xffff];
const result = registersToUint16Nullable(registers);
expect(result).toBe(null);
});

it('registersToInt16 should convert registers to a 16-bit signed integer', () => {
const registers = [0x8001];
const result = registersToInt16(registers);
expect(result).toBe(-32767);
});

it('registersToInt16Nullable should convert null to a 16-bit signed integer', () => {
const registers = [0x8000];
const result = registersToInt16Nullable(registers);
expect(result).toBe(null);
});

it('registersToSunssf should convert registers to a 16-bit signed integer', () => {
const registers = [0x8001];
const result = registersToSunssf(registers);
Expand All @@ -59,8 +105,20 @@ it('uint16ToRegisters should convert a 16-bit unsigned integer to registers', ()
expect(result).toEqual([0x1234]);
});

it('uint16ToRegisters should convert null to registers', () => {
const value = null;
const result = uint16NullableToRegisters(value);
expect(result).toEqual([0xffff]);
});

it('int16ToRegisters should convert a 16-bit signed integer to registers', () => {
const value = -20;
const result = int16ToRegisters(value);
expect(result).toEqual([0xffec]);
});

it('int16ToRegistersNullable should convert null to registers', () => {
const value = null;
const result = int16NullableToRegisters(value);
expect(result).toEqual([0x8000]);
});
63 changes: 62 additions & 1 deletion src/sunspec/helpers/converters.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
export function registersToString(registers: number[]): string {
export function registersToString(registers: number[]) {
const buffer = Buffer.from(
registers.flatMap((register) => [
(register >> 8) & 0xff,
Expand All @@ -13,6 +13,14 @@ export function registersToString(registers: number[]): string {
);
}

export function registersToStringNullable(registers: number[]) {
if (registers.every((register) => register === 0)) {
return null;
}

return registersToString(registers);
}

export function registersToUint32(registers: number[]) {
if (registers.length !== 2) {
throw new Error('Invalid register length');
Expand All @@ -21,6 +29,14 @@ export function registersToUint32(registers: number[]) {
return (registers[0]! << 16) | registers[1]!;
}

export function registersToUint32Nullable(registers: number[]) {
if (registers.every((register) => register === 0xffff)) {
return null;
}

return registersToUint32(registers);
}

export function registersToUint16(registers: number[]) {
if (registers.length !== 1) {
throw new Error('Invalid register length');
Expand All @@ -29,6 +45,18 @@ export function registersToUint16(registers: number[]) {
return registers[0]!;
}

export function registersToUint16Nullable(registers: number[]) {
if (registers.length !== 1) {
throw new Error('Invalid register length');
}

if (registers[0] === 0xffff) {
return null;
}

return registersToUint16(registers);
}

export function uint16ToRegisters(value: number): number[] {
if (value < 0 || value > 0xffff) {
throw new Error('Value out of range for uint16');
Expand All @@ -37,6 +65,14 @@ export function uint16ToRegisters(value: number): number[] {
return [value];
}

export function uint16NullableToRegisters(value: number | null): number[] {
if (value === null) {
return [0xffff];
}

return uint16ToRegisters(value);
}

export function registersToInt16(registers: number[]) {
if (registers.length !== 1) {
throw new Error('Invalid register length');
Expand All @@ -45,6 +81,18 @@ export function registersToInt16(registers: number[]) {
return (registers[0]! << 16) >> 16;
}

export function registersToInt16Nullable(registers: number[]) {
if (registers.length !== 1) {
throw new Error('Invalid register length');
}

if (registers[0] === 0x8000) {
return null;
}

return registersToInt16(registers);
}

export function int16ToRegisters(value: number): number[] {
if (value < -32768 || value > 32767) {
throw new Error('Value out of range for int16');
Expand All @@ -54,10 +102,23 @@ export function int16ToRegisters(value: number): number[] {
return [value & 0xffff];
}

export function int16NullableToRegisters(value: number | null): number[] {
if (value === null) {
return [0x8000];
}

// Ensure the value is treated as a 16-bit signed integer
return [value & 0xffff];
}

export function registersToSunssf(registers: number[]) {
return registersToInt16(registers);
}

export function registersToSunssfNullable(registers: number[]) {
return registersToInt16Nullable(registers);
}

export function registersToAcc32(registers: number[]) {
if (registers.length !== 2) {
throw new Error('Invalid register length');
Expand Down
14 changes: 8 additions & 6 deletions src/sunspec/models/commonModel.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import {
registersToString,
registersToStringNullable,
registersToUint16,
registersToUint16Nullable,
registersToUint32,
} from '../helpers/converters';
import { sunSpecModelFactory } from './sunSpecModelFactory';
Expand All @@ -18,13 +20,13 @@ export type CommonModel = {
// Device model
Md: string;
// Options
Opt: string;
Opt: string | null;
// SW version of inverter
Vr: string;
Vr: string | null;
// Serialnumber of the inverter
SN: string;
// Modbus Device Address
DA: number;
DA: number | null;
};

export const commonModel = sunSpecModelFactory<CommonModel>({
Expand Down Expand Up @@ -57,12 +59,12 @@ export const commonModel = sunSpecModelFactory<CommonModel>({
Opt: {
start: 36,
end: 44,
readConverter: registersToString,
readConverter: registersToStringNullable,
},
Vr: {
start: 44,
end: 52,
readConverter: registersToString,
readConverter: registersToStringNullable,
},
SN: {
start: 52,
Expand All @@ -72,7 +74,7 @@ export const commonModel = sunSpecModelFactory<CommonModel>({
DA: {
start: 68,
end: 69,
readConverter: registersToUint16,
readConverter: registersToUint16Nullable,
},
},
});
Loading

0 comments on commit 7d859c8

Please sign in to comment.