Skip to content

Commit

Permalink
Update README.md
Browse files Browse the repository at this point in the history
  • Loading branch information
longzheng authored Oct 20, 2024
1 parent 021fb52 commit a2d7920
Showing 1 changed file with 13 additions and 255 deletions.
268 changes: 13 additions & 255 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,261 +9,8 @@ This project aims to implement dynamic export control/solar curtailment of inver
- two-way tariffs (e.g.time based) export limitation
- negative feed-in (e.g. Amber) export limitation

![frame_generic_dark](https://github.com/user-attachments/assets/cd8e1bca-14e5-46ce-a845-917eb7744ec4)
> [!NOTE]
> The dashboard UI is not part of this open-source reprository and will be available as a licensed product along with a hardware package.
```mermaid
flowchart LR
ODE(("open-dynamic-export"))
I["Inverter(s)"]
M["Site meter"]
CSIP-AUS --> DC
DC & F & T & NFI & MQTTL --> ODE
Configuration --> F
A["Amber API"] --> NFI
R["Tariff rules"] --> T
ODE <--> SunSpec & HTTP & Proprietary & MQTT
Protocols <--> I & M
subgraph Limiters
DC["Dynamic exports"]
F["Fixed/zero export"]
T["Two-way tariffs"]
NFI["Negative feed-in"]
MQTTL["MQTT"]
end
subgraph Protocols
SunSpec
HTTP
MQTT
Proprietary
end
```

## Supported inverters and site meter

Inverters:

| Name | `config.json` inverter type | Description | Tested models |
| ------- | --------------------------- | ------------------------------------------------------------------------------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| SunSpec | `sunspec` | SunSpec Modbus TCP compatible inverter<br>Must support models 1, 101/102/103, 120, 121, 122, 123 | <a href="https://github.com/longzheng/open-dynamic-export/wiki/Fronius-SunSpec-Modbus-configuration">Fronius Primo</a><br><a href="https://github.com/longzheng/open-dynamic-export/wiki/Fronius-SunSpec-Modbus-configuration">Fronius Symo</a> |

Site meter:

| Name | `config.json` meter type | Description | Tested models |
|-------------------|--------------------|---------------------------------------------------------------------------------|---------------------------------------------------------------------------------|
| SunSpec | `sunspec` | SunSpec Modbus TCP compatible smart meter<br>Must support models 1, 201/202/203 | Fronius Smart Meter 1 phase<br>Fronius Smart Meter 3 phase<br>Catch Power Relay |
| Tesla Powerwall 2 | `powerwall2` | | Backup Gateway 2 |

> [!IMPORTANT]
> Site meters installed in the consumption path with batteries are not supported due to the inability to measure battery power. The site meter must be installed in the feedin path.
## Configuration

The server uses a configuration JSON to configure how it works.

### Inverters and meters

To configure the inverter and meter connections, add the following property to `config.json`

```js
{
"inverters": [ // (array) required: list of inverters
{
"type": "sunspec", // (string) required: the type of inverter
"ip": "192.168.1.6", // (string) required: the IP address of the inverter
"port": 502, // (number) required: the Modbus TCP port of the inverter
"unitId": 1 // (number) required: the Modbus unit ID of the inverter
}
],
"inverterControl": {
"enabled": true // (true/false) optional: whether the inverters should be controlled based on limits, turn off to simulate
},
"meter": {
"type": "sunspec", // (string) required: the type of meter
"ip": "192.168.1.6", // (string) required: the IP address of the meter
"port": 502, // (number) required: the SunSpec Modbus TCP port of the meter
"unitId": 240 // (number) required: the SunSpec unit ID of the meter
"location": "feedin" // (string) optional: the location of the meter (feedin or consumption)
}
...
}
```

### Limiters

All limiters are restrictive, that is a combination of multiple limiters will evaluate all limiters and enforce the most prohibitive value of each control type at any one time.

Currently there are four control surfaces, mapped to the CSIP-AUS modes

| Mode | Description | Overlap resolution | Default value |
|-----------------|----------------------------------------------------------------------------------------------|------------------------|---------------|
| opModConnect | Connection to the grid | Prioritize disconnect | Connect |
| opModEnergize | Generate or consume energy (in practice for most inverters this is the same as opModConnect) | Prioritize de-energize | Energized |
| opModExportLimW | Maximum export limit (in watts) | Lower limit | Unlimited |
| opModGenLimW | Maximum inverter generation limit (in watts) | Lower limit | Unlimited |

#### Fixed limit

To set fixed limits (such as for fixed export limits), add the following property to `config.json`

```js
{
"limiters": {
"fixed": {
"connect": true, // (true/false) optional: whether the inverters should be connected to the grid
"exportLimitWatts": 5000, // (number) optional: the maximum export limit in watts
"generationLimitWatts": 10000 // (number) optional: the maximum generation limit in watts
}
}
...
}
```

#### Negative feed-in

To set a zero export limit based on negative feed-in, add the following property to `config.json`

For Amber Electric:
```js
{
"limiters": {
"negativeFeedIn": {
"type": "amber", // (string) required: the source of the negative feed-in data
"apiKey": "asdf", // (string) required: the Amber API key
"siteId": "12345" // (string) required: the Amber site ID
}
}
...
}
```

#### Two-way tariffs

To set a zero export limit based on two-way tariffs, add the following property to `config.json`

For Ausgrid EA029 tariff:
```js
{
"limiters": {
"twoWayTariff": {
"type": "ausgridEA029"
}
}
...
}
```

For SAPN RELE2W tariff:
```js
{
"limiters": {
"twoWayTariff": {
"type": "sapnRELE2W"
}
}
...
}
```

#### CSIP-AUS

> [!IMPORTANT]
> This CSIP-AUS client cannot run without device certificates (and manufacturer certificates issued by the utility server which must be manually registered) and is not provided in this repository. A future version of this application will support a self-service device registration process.
To use CSIP-AUS, add following property to `config.json`

```js
{
"limiters": {
"sep2": {
"host": "https://sep2-test.energyq.com.au", // (string) required: the SEP2 server host
"dcapUri": "/api/v2/dcap" // (string) required: the device capability discovery URI
}
}
...
}
```

#### MQTT

To set limits based on a MQTT topic, add the following property to `config.json`

```js
{
"limiters": {
"mqtt": {
"host": "mqtt://192.168.1.123",
"topic": "limits"
}
}
...
}
```

The MQTT topic must contain a JSON message that meets the following schema

```js
z.object({
opModConnect: z.boolean().optional(),
opModEnergize: z.boolean().optional(),
opModExpLimW: z.number().optional(),
opModGenLimW: z.number().optional(),
});
```

## Run server

### Docker compose

1. Clone repo

1. Copy `.env.example` and rename it to `.env` and change the values to suit

1. Create a `/config` folder and copy the [`config.example.json` file from the repo](https://github.com/longzheng/open-dynamic-export/blob/main/config/config.example.json) and rename it to `config.json`. Set it with the required values.

1. Run `docker compose up -d` (or run `docker compose up -d --build`)

## CSIP-AUS client

The project implements a CSIP-AUS compatible 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).

```mermaid
sequenceDiagram
participant U as Utility<br>(CSIP-AUS server)
participant SC as CSIP-AUS client
participant C as Coordinator
participant D as DER
loop
SC->>U: Discovery
U->>SC: Devices, programs, DER controls
SC->>U: Acknowledge DER controls
end
SC->>C: Control schedules<br> and limits
loop
D->>C: Metrics
Note over C: Get current schedule<br>Calculate target power level<br>to meet limits
C->>D: Inverter controls
end
loop
SC->>U: Send DER status/capability/settings
SC->>U: Send site and DER telemetry
end
box rgb(198,239,210) open-dynamic-export
participant SC
participant C
end
```

The initial plan is to implement a direct gateway client that interacts directly with the utility server and the DER (solar inverters). The downside of a direct client approach is the registration process is manual and requires generating keys and certificates for each site/NMI. If the project is successful, a future version will allow self-service registration or a cloud-hosted aggregator proxy.
## Documentation
[View documentation](https://opendynamicexport.com/guide/)

## Features

Expand All @@ -288,6 +35,17 @@ The initial plan is to implement a direct gateway client that interacts directly
- [x] Software-based limit ramping (`setGradW` or `rampTms`)
- [x] Metrics logging in InfluxDB

## Build
### Docker compose

1. Clone repo

1. Copy `.env.example` and rename it to `.env` and change the values to suit

1. Create a `/config` folder and copy the [`config.example.json` file from the repo](https://github.com/longzheng/open-dynamic-export/blob/main/config/config.example.json) and rename it to `config.json`. Set it with the required values.

1. Run `docker compose up -d` (or run `docker compose up -d --build`)

## CSIP-AUS Private key and CSR

CSIP-AUS uses PKI certificates to authorise and identify clients.
Expand Down

0 comments on commit a2d7920

Please sign in to comment.