Skip to content

Commit

Permalink
Merge pull request #71 from longzheng/limiter-csipaus
Browse files Browse the repository at this point in the history
Rename SEP2 limiter to CSIP-AUS
  • Loading branch information
longzheng authored Dec 20, 2024
2 parents 2e26d16 + 717c4cb commit 14742fa
Show file tree
Hide file tree
Showing 19 changed files with 55 additions and 68 deletions.
6 changes: 3 additions & 3 deletions config.schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,13 @@
"limiters": {
"type": "object",
"properties": {
"sep2": {
"csipAus": {
"type": "object",
"properties": {
"host": {
"type": "string",
"format": "uri",
"description": "The host of the SEP2 server"
"description": "The host of the CSIP-AUS server"
},
"dcapUri": {
"type": "string",
Expand All @@ -31,7 +31,7 @@
"dcapUri"
],
"additionalProperties": false,
"description": "If defined, limit by CSIP-AUS/SEP2 server"
"description": "If defined, limit by CSIP-AUS server"
},
"fixed": {
"type": "object",
Expand Down
6 changes: 3 additions & 3 deletions docs/configuration/limiters.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ The software supports 6 control modes mapped to the CSIP-AUS Dynamic Operating E

## CSIP-AUS dynamic connection

Apply dynamic limits from an Australian energy utility CSIP-AUS/SEP2 server.
Apply dynamic limits from an Australian energy utility CSIP-AUS server.

> [!IMPORTANT]
> This CSIP-AUS client cannot run without device certificates (and manufacturer certificates). See the [CSIP-AUS section](/csip-aus) for more information.
Expand All @@ -33,8 +33,8 @@ To use the CSIP-AUS limiter, add following property to `config.json`
```js
{
"limiters": {
"sep2": {
"host": "https://sep2-test.energyq.com.au", // (string) required: the SEP2 server host
"csipAus": {
"host": "https://sep2-test.energyq.com.au", // (string) required: the CSIP-AUS server host
"dcapUri": "/api/v2/dcap", // (string) required: the device capability discovery URI
"nmi": "1234567890" // (string) optional: for utilities that require in-band registration, the NMI of the site
}
Expand Down
12 changes: 6 additions & 6 deletions docs/configuration/publish.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,11 +28,11 @@ The MQTT topic will contain a JSON message that meets the following Zod schema

```ts
const inverterControlTypesSchema = z.union([
z.literal("csipAus"),
z.literal("fixed"),
z.literal("mqtt"),
z.literal("sep2"),
z.literal("twoWayTariff"),
z.literal("negativeFeedIn")
z.literal("twoWayTariff"),
])

const activeInverterControlLimitSchema = z.object({
Expand Down Expand Up @@ -86,19 +86,19 @@ For example
```js
{
"opModEnergize": {
"source": "sep2",
"source": "csipAus",
"value": true
},
"opModConnect": {
"source": "sep2",
"source": "csipAus",
"value": true
},
"opModExpLimW": {
"source": "sep2",
"source": "csipAus",
"value": 1500
},
"opModImpLimW": {
"source": "sep2",
"source": "csipAus",
"value": 1500
}
}
Expand Down
2 changes: 1 addition & 1 deletion docs/csip-aus/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

It is based on the [IEEE 2030.5](https://standards.ieee.org/ieee/2030.5/5897/) standard and is used by Australian electricity utilities/DNSPs (Distributed Network Service Providers) to dyamically control site import and exports for dynamic/flexible connections. It is also referenced as SEP2 (Smart Energy Profile 2).

The project implements a CSIP-AUS compatible gateway client that interacts with the utility server (CSIP-AUS/SEP2 server). The initial implementation focuses on the [SA Power Networks requirements](https://www.talkingpower.com.au/71619/widgets/376925/documents/239205) and [Energy Queensland requirements](https://www.energex.com.au/__data/assets/pdf_file/0007/1072618/SEP2-Client-Handbook-13436740.pdf).
The project implements a CSIP-AUS compatible gateway client that interacts with the utility CSIP-AUS server. The initial implementation focuses on the [SA Power Networks requirements](https://www.talkingpower.com.au/71619/widgets/376925/documents/239205) and [Energy Queensland requirements](https://www.energex.com.au/__data/assets/pdf_file/0007/1072618/SEP2-Client-Handbook-13436740.pdf).

```mermaid
sequenceDiagram
Expand Down
6 changes: 3 additions & 3 deletions src/coordinator/helpers/inverterController.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -163,7 +163,7 @@ describe('getActiveInverterControlLimit', () => {
opModLoadLimW: 5000,
},
{
source: 'sep2',
source: 'csipAus',
opModConnect: true,
opModEnergize: false,
opModExpLimW: 2000,
Expand All @@ -179,11 +179,11 @@ describe('getActiveInverterControlLimit', () => {
value: false,
},
opModEnergize: {
source: 'sep2',
source: 'csipAus',
value: false,
},
opModExpLimW: {
source: 'sep2',
source: 'csipAus',
value: 2000,
},
opModGenLimW: {
Expand Down
2 changes: 1 addition & 1 deletion src/coordinator/helpers/inverterController.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ export type SupportedControlTypes = Extract<
export type InverterControlTypes =
| 'fixed'
| 'mqtt'
| 'sep2'
| 'csipAus'
| 'twoWayTariff'
| 'negativeFeedIn';

Expand Down
6 changes: 3 additions & 3 deletions src/helpers/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,12 +46,12 @@ export type ModbusSchema = z.infer<typeof modbusSchema>;
export const configSchema = z.object({
limiters: z
.object({
sep2: z
csipAus: z
.object({
host: z
.string()
.url()
.describe('The host of the SEP2 server'),
.describe('The host of the CSIP-AUS server'),
dcapUri: z
.string()
.describe('The URI of the DeviceCapability resource'),
Expand All @@ -65,7 +65,7 @@ export const configSchema = z.object({
),
})
.optional()
.describe('If defined, limit by CSIP-AUS/SEP2 server'),
.describe('If defined, limit by CSIP-AUS server'),
fixed: z
.object({
connect: z
Expand Down
4 changes: 2 additions & 2 deletions src/limiters/sep2/index.ts → src/limiters/csipAus/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import { numberWithPow10 } from '../../helpers/number.js';
import { writeControlLimit } from '../../helpers/influxdb.js';
import { ControlLimitRampHelper } from '../../sep2/helpers/controlLimitRamp.js';

export class Sep2Limiter implements LimiterType {
export class CsipAusLimiter implements LimiterType {
private schedulerByControlType: {
[T in SupportedControlTypes]: ControlSchedulerHelper<T>;
};
Expand Down Expand Up @@ -188,7 +188,7 @@ export class Sep2Limiter implements LimiterType {
);

const limit: InverterControlLimit = {
source: 'sep2',
source: 'csipAus',
opModExpLimW: this.opModExpLimWRampRateHelper.getRampedValue(),
opModGenLimW: this.opModGenLimWRampRateHelper.getRampedValue(),
opModEnergize:
Expand Down
2 changes: 1 addition & 1 deletion src/limiters/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ export function getLimiters({
sep2Instance: Sep2Instance | null;
}): Limiters {
return {
sep2: sep2Instance?.limiter ?? null,
csipAus: sep2Instance?.limiter ?? null,
fixed: config.limiters.fixed
? new FixedLimiter({ config: config.limiters.fixed })
: null,
Expand Down
6 changes: 2 additions & 4 deletions src/sep2/client.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,8 @@ beforeAll(() => {
server.listen();

sep2Client = new SEP2Client({
sep2Config: {
host: 'http://example.com',
dcapUri: '/dcap',
},
host: 'http://example.com',
dcapUri: '/dcap',
cert: mockCert,
key: mockKey,
pen: '12345',
Expand Down
14 changes: 6 additions & 8 deletions src/sep2/client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ import {
getCertificateLfdi,
getCertificateSfdi,
} from './helpers/cert.js';
import { type Config } from '../helpers/config.js';
import { type RoleFlagsType } from './models/roleFlagsType.js';
import { numberToHex } from '../helpers/number.js';
import { createHash } from 'node:crypto';
Expand All @@ -29,21 +28,20 @@ export class SEP2Client {
private readonly axiosInstance: AxiosInstance;

constructor({
sep2Config,
host,
dcapUri,
cert,
key,
pen,
}: {
sep2Config: Pick<
NonNullable<Config['limiters']['sep2']>,
'host' | 'dcapUri'
>;
host: string;
dcapUri: string;
cert: string;
key: string;
pen: string;
}) {
this.host = sep2Config.host;
this.dcapUri = sep2Config.dcapUri;
this.host = host;
this.dcapUri = dcapUri;
this.pen = pen.padStart(8, '0');

const certificateFingerprint = getCertificateFingerprint(cert);
Expand Down
6 changes: 2 additions & 4 deletions src/sep2/helpers/derControls.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,8 @@ import { setupServer } from 'msw/node';
import { CurrentStatus } from '../models/currentStatus.js';

const sep2Client = new SEP2Client({
sep2Config: {
host: 'http://example.com',
dcapUri: '/dcap',
},
host: 'http://example.com',
dcapUri: '/dcap',
cert: mockCert,
key: mockKey,
pen: '12345',
Expand Down
6 changes: 2 additions & 4 deletions src/sep2/helpers/deviceCapability.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,8 @@ import { setupServer } from 'msw/node';

describe('DeviceCapabilityHelper', () => {
const sep2Client = new SEP2Client({
sep2Config: {
host: 'http://example.com',
dcapUri: '/dcap',
},
host: 'http://example.com',
dcapUri: '/dcap',
cert: mockCert,
key: mockKey,
pen: '12345',
Expand Down
6 changes: 2 additions & 4 deletions src/sep2/helpers/pagination.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,8 @@ let sep2Client: SEP2Client;

beforeAll(() => {
sep2Client = new SEP2Client({
sep2Config: {
host: 'http://example.com',
dcapUri: '/dcap',
},
host: 'http://example.com',
dcapUri: '/dcap',
cert: mockCert,
key: mockKey,
pen: '12345',
Expand Down
6 changes: 2 additions & 4 deletions src/sep2/helpers/pollableResource.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,8 @@ type MockResponse = {
};

const sep2Client = new SEP2Client({
sep2Config: {
host: 'http://example.com',
dcapUri: '/dcap',
},
host: 'http://example.com',
dcapUri: '/dcap',
cert: mockCert,
key: mockKey,
pen: '12345',
Expand Down
6 changes: 2 additions & 4 deletions src/sep2/helpers/time.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,8 @@ import { setupServer } from 'msw/node';

describe('TimeHelper', () => {
const sep2Client = new SEP2Client({
sep2Config: {
host: 'http://example.com',
dcapUri: '/dcap',
},
host: 'http://example.com',
dcapUri: '/dcap',
cert: mockCert,
key: mockKey,
pen: '12345',
Expand Down
13 changes: 7 additions & 6 deletions src/sep2/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { type Config } from '../helpers/config.js';
import { env } from '../helpers/env.js';
import { pinoLogger } from '../helpers/logger.js';
import { SEP2Client } from './client.js';
import { Sep2Limiter } from '../limiters/sep2/index.js';
import { CsipAusLimiter } from '../limiters/csipAus/index.js';
import { DerHelper } from './helpers/der.js';
import { DerControlsHelper } from './helpers/derControls.js';
import { DerListHelper } from './helpers/derList.js';
Expand All @@ -25,7 +25,7 @@ export type Sep2Instance = {
sep2Client: SEP2Client;
derHelper: DerHelper;
mirrorUsagePointListHelper: MirrorUsagePointListHelper;
limiter: Sep2Limiter;
limiter: CsipAusLimiter;
};

export function getSep2Instance({
Expand All @@ -35,14 +35,15 @@ export function getSep2Instance({
config: Config;
rampRateHelper: RampRateHelper;
}): Sep2Instance | null {
if (!config.limiters.sep2) {
if (!config.limiters.csipAus) {
return null;
}

const sep2Certificate = getSep2Certificate();

const sep2Client = new SEP2Client({
sep2Config: config.limiters.sep2,
host: config.limiters.csipAus.host,
dcapUri: config.limiters.csipAus.dcapUri,
cert: sep2Certificate.cert,
key: sep2Certificate.key,
pen: env.SEP2_PEN,
Expand Down Expand Up @@ -78,7 +79,7 @@ export function getSep2Instance({
client: sep2Client,
});

const limiter = new Sep2Limiter({
const limiter = new CsipAusLimiter({
client: sep2Client,
rampRateHelper,
});
Expand Down Expand Up @@ -243,7 +244,7 @@ export function getSep2Instance({
}: {
connectionPointHref: string;
}) {
const nmi = config.limiters.sep2?.nmi;
const nmi = config.limiters.csipAus?.nmi;

if (!nmi) {
throw new Error(
Expand Down
2 changes: 1 addition & 1 deletion src/server/services/coordinatorService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,6 @@ type SiteSample = {
};

type ControlLimitsByLimiter = Record<
'sep2' | 'fixed' | 'negativeFeedIn' | 'twoWayTariff' | 'mqtt',
'csipAus' | 'fixed' | 'negativeFeedIn' | 'twoWayTariff' | 'mqtt',
InverterControlLimit | null
>;
12 changes: 6 additions & 6 deletions src/server/services/csipAusService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import {
getCertificateLfdi,
getCertificateSfdi,
} from '../../sep2/helpers/cert.js';
import { type Sep2Limiter } from '../../limiters/sep2/index.js';
import { type CsipAusLimiter } from '../../limiters/csipAus/index.js';
import { type ResponseRequiredType } from '../../sep2/models/responseRequired.js';
import { coordinatorService } from './coordinatorService.js';
import { type SupportedControlTypes } from '../../coordinator/helpers/inverterController.js';
Expand All @@ -30,15 +30,15 @@ export function getCertificateIds(): CertificateIds {
export function getCsipLimitSchedule(
type: SupportedControlTypes,
): RandomizedControlSchedule[] {
const sep2Limiter = coordinatorService.getLimiters().sep2;
const csipAusLimiter = coordinatorService.getLimiters().csipAus;

if (!sep2Limiter) {
throw new Error('SEP2 limiter is not running');
if (!csipAusLimiter) {
throw new Error('CSIP-AUS limiter is not running');
}

const sep2LimiterClass = sep2Limiter as Sep2Limiter;
const csipAusLimiterClass = csipAusLimiter as CsipAusLimiter;

return sep2LimiterClass
return csipAusLimiterClass
.getSchedulerByControlType()
[type].getControlSchedules();
}
Expand Down

0 comments on commit 14742fa

Please sign in to comment.