Skip to content

Commit

Permalink
Implement SunSpec meter model
Browse files Browse the repository at this point in the history
  • Loading branch information
longzheng committed Jul 24, 2024
1 parent 042fcc7 commit 5c97462
Show file tree
Hide file tree
Showing 6 changed files with 626 additions and 34 deletions.
23 changes: 16 additions & 7 deletions config.json.example
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,20 @@
"keyPath": "key.pem",
"pen": 12345
},
"sunspecModbus": [
{
"ip": "192.168.1.6",
"port": 502,
"unitId": 1
}
]
"sunspec": {
"inverters": [
{
"ip": "192.168.1.6",
"port": 502,
"unitId": 1
}
],
"meters": [
{
"ip": "192.168.1.6",
"port": 502,
"unitId": 240
}
]
}
}
39 changes: 29 additions & 10 deletions scripts/debugModbusClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,26 +6,45 @@ import { getBrandByCommonModel } from '../src/sunspec/brand';
const config = getConfig();

void (async () => {
const modbusConnections = config.sunspecModbus.map(
const invertersConnections = config.sunspec.inverters.map(
({ ip, port, unitId }) => new ModbusConnection({ ip, port, unitId }),
);

const clientsData = await Promise.all(
modbusConnections.map(async (client) => {
const common = await client.getCommonModel();
const metersConnections = config.sunspec.meters.map(
({ ip, port, unitId }) => new ModbusConnection({ ip, port, unitId }),
);

const invertersData = await Promise.all(
invertersConnections.map(async (inverter) => {
const common = await inverter.getCommonModel();

const brand = getBrandByCommonModel(common);

return {
common,
inverter: await inverter.getInverterModel(brand),
nameplate: await inverter.getNameplateModel(brand),
settings: await inverter.getSettingsModel(brand),
status: await inverter.getStatusModel(brand),
controls: await inverter.getControlsModel(brand),
};
}),
);

console.dir(invertersData);

const metersData = await Promise.all(
metersConnections.map(async (meter) => {
const common = await meter.getCommonModel();

const brand = getBrandByCommonModel(common);

return {
common,
inverter: await client.getInverterModel(brand),
nameplate: await client.getNameplateModel(brand),
settings: await client.getSettingsModel(brand),
status: await client.getStatusModel(brand),
controls: await client.getControlsModel(brand),
meter: await meter.getMeterModel(brand),
};
}),
);

console.dir(clientsData);
console.dir(metersData);
})();
5 changes: 4 additions & 1 deletion src/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,10 @@ const configSchema = z.object({
keyPath: z.string(),
pen: z.number(),
}),
sunspecModbus: z.array(sunspecModbusSchema),
sunspec: z.object({
inverters: z.array(sunspecModbusSchema),
meters: z.array(sunspecModbusSchema),
}),
});

export type Config = z.infer<typeof configSchema>;
Expand Down
14 changes: 14 additions & 0 deletions src/sunspec/modbusConnection.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import {
controlsModel,
controlsModelAddressStartByBrand,
} from './models/controls';
import { meterModel, meterModelAddressStartByBrand } from './models/meter';

export class ModbusConnection {
public client: ModbusRTU;
Expand Down Expand Up @@ -189,4 +190,17 @@ export class ModbusConnection {
values,
});
}

async getMeterModel(brand: SunSpecBrand) {
const data = await meterModel.read({
modbusConnection: this,
addressStart: meterModelAddressStartByBrand(brand),
});

if (data.ID !== 201 && data.ID !== 202 && data.ID !== 203) {
throw new Error('Not a SunSpec meter model');
}

return data;
}
}
16 changes: 0 additions & 16 deletions src/sunspec/models/inverter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -357,22 +357,6 @@ export enum InverterState {
}

// SunSpec_Information_Model_Reference_20210302.xlsx
// GROUND_FAULT 0
// DC_OVER_VOLT 1
// AC_DISCONNECT 2
// DC_DISCONNECT 3
// GRID_DISCONNECT 4
// CABINET_OPEN 5
// MANUAL_SHUTDOWN 6
// OVER_TEMP 7
// OVER_FREQUENCY 8
// UNDER_FREQUENCY 9
// AC_OVER_VOLT 10
// AC_UNDER_VOLT 11
// BLOWN_STRING_FUSE 12
// UNDER_TEMP 13
// MEMORY_LOSS 14
// HW_TEST_FAILURE 15
export enum InverterEvent1 {
GROUND_FAULT = 1 << 0,
DC_OVER_VOLT = 1 << 1,
Expand Down
Loading

0 comments on commit 5c97462

Please sign in to comment.