docs(optimiseur): liens vers le moteur sur Gitea, plus de renvoi à INTERFACE.md, « optimizer » en anglais
Le miroir GitHub n'est pas encore synchronisé : les liens pointent sur git.etm-powersync.fr. INTERFACE.md n'est plus dans le dépôt public : la forme des méthodes NymeaEnergy.* se lit sur la box (JSONRPC.Introspect) ; GetOptimizerStatus n'est pas réservée à l'administrateur. Orthographe anglaise unifiée : optimizer, optimization. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Ry3vBrJT1tHdxAaXdCWi6L
This commit is contained in:
parent
0b8ccc6c9d
commit
eb7d727d17
@ -14,11 +14,11 @@ app. That is an architectural decision, not an option.
|
|||||||
## Is the project open source?
|
## Is the project open source?
|
||||||
|
|
||||||
The energy engine (`etm-powersync-energy-plugin-etm`) and the plugins are under
|
The energy engine (`etm-powersync-energy-plugin-etm`) and the plugins are under
|
||||||
GPL-3.0, including the optimiser client built into the engine — everything linked against
|
GPL-3.0, including the optimizer client built into the engine — everything linked against
|
||||||
nymea is. The engine works on its own, without an optimiser. The
|
nymea is. The engine works on its own, without an optimizer. The
|
||||||
[protocol between the engine and an optimiser](optimiseur/index.md) is open and
|
[protocol between the engine and an optimizer](optimiseur/index.md) is open and
|
||||||
published, with a free reference optimiser and a conformance suite: anyone can write their
|
published, with a free reference optimizer and a conformance suite: anyone can write their
|
||||||
own. The **ETM optimiser** and its business logic (tariff arbitration, forecasts learned
|
own. The **ETM optimizer** and its business logic (tariff arbitration, forecasts learned
|
||||||
from your installation), however, are proprietary: they run in a separate process, reached
|
from your installation), however, are proprietary: they run in a separate process, reached
|
||||||
through that protocol, at your place — on the box or on a machine in your local network.
|
through that protocol, at your place — on the box or on a machine in your local network.
|
||||||
That process boundary is the heart of the Open Core model — the engine stays free, the
|
That process boundary is the heart of the Open Core model — the engine stays free, the
|
||||||
|
|||||||
@ -12,7 +12,7 @@ An overview of the HEMS features and their real state.
|
|||||||
| Baseload forecast | <span class="badge nightly">COMING</span> |
|
| Baseload forecast | <span class="badge nightly">COMING</span> |
|
||||||
| [JSON-RPC API](../integrations/jsonrpc-api.md) / [MQTT](../integrations/mqtt.md) | <span class="badge stable">AVAILABLE</span> |
|
| [JSON-RPC API](../integrations/jsonrpc-api.md) / [MQTT](../integrations/mqtt.md) | <span class="badge stable">AVAILABLE</span> |
|
||||||
| Dynamic tariffs — FR: Tempo, off-peak · DE: §14a EnWG, EPEX spot | <span class="badge nightly">ROADMAP</span> |
|
| Dynamic tariffs — FR: Tempo, off-peak · DE: §14a EnWG, EPEX spot | <span class="badge nightly">ROADMAP</span> |
|
||||||
| CO₂ optimisation — RTE (FR) / SMARD (DE) | <span class="badge nightly">ROADMAP</span> |
|
| CO₂ optimization — RTE (FR) / SMARD (DE) | <span class="badge nightly">ROADMAP</span> |
|
||||||
| Charge planner | <span class="badge nightly">ROADMAP</span> |
|
| Charge planner | <span class="badge nightly">ROADMAP</span> |
|
||||||
| Heat pump | <span class="badge nightly">ROADMAP</span> |
|
| Heat pump | <span class="badge nightly">ROADMAP</span> |
|
||||||
|
|
||||||
|
|||||||
@ -18,7 +18,7 @@ different rates and with different priorities.
|
|||||||
there is headroom again. It does not wait for the cycle and overrides everything else.
|
there is headroom again. It does not wait for the cycle and overrides everything else.
|
||||||
- **The allocation cycle, about once a minute.** It shares the available power between
|
- **The allocation cycle, about once a minute.** It shares the available power between
|
||||||
the loads. This is the only place a strategy acts: the built-in rules, or an
|
the loads. This is the only place a strategy acts: the built-in rules, or an
|
||||||
[optimiser](../optimiseur/index.md) if one is connected.
|
[optimizer](../optimiseur/index.md) if one is connected.
|
||||||
|
|
||||||
If the grid meter stops answering, the engine suspends allocation and falls back to safety
|
If the grid meter stops answering, the engine suspends allocation and falls back to safety
|
||||||
mode: no measurement, no decision.
|
mode: no measurement, no decision.
|
||||||
@ -60,7 +60,7 @@ whatever the strategy:
|
|||||||
The engine takes no decision without stating why. Every decision carries a non-empty
|
The engine takes no decision without stating why. Every decision carries a non-empty
|
||||||
**reason** (`decisionReason`): a stable code and its parameters, which the app displays in
|
**reason** (`decisionReason`): a stable code and its parameters, which the app displays in
|
||||||
your language — "surplus insufficient", "below minimum power", "charging deadline"… The
|
your language — "surplus insufficient", "below minimum power", "charging deadline"… The
|
||||||
list of codes is published with the [optimiser protocol](../optimiseur/protocole.md#reponse).
|
list of codes is published with the [optimizer protocol](../optimiseur/protocole.md#reponse).
|
||||||
|
|
||||||
## The measurement, never the result of control
|
## The measurement, never the result of control
|
||||||
|
|
||||||
@ -75,8 +75,8 @@ enforces safety and answers the app on your local network. Only the
|
|||||||
edition, any more than the [entered tariff](../tarifs.md): both are displayed and
|
edition, any more than the [entered tariff](../tarifs.md): both are displayed and
|
||||||
recorded, never used by the rules.
|
recorded, never used by the rules.
|
||||||
|
|
||||||
## What about an optimiser?
|
## What about an optimizer?
|
||||||
|
|
||||||
An optimiser can propose a plan over several hours, based on the forecasts. It replaces
|
An optimizer can propose a plan over several hours, based on the forecasts. It replaces
|
||||||
the allocation step, **never** the safety loop or the bounds. See the
|
the allocation step, **never** the safety loop or the bounds. See the
|
||||||
[Optimizer](../optimiseur/index.md) section.
|
[Optimizer](../optimiseur/index.md) section.
|
||||||
|
|||||||
@ -71,7 +71,7 @@ therefore neither an "expected error" nor a "confidence interval".
|
|||||||
|
|
||||||
## What the forecast does not do
|
## What the forecast does not do
|
||||||
|
|
||||||
This is the central rule of the Community edition: **without an optimiser, control is
|
This is the central rule of the Community edition: **without an optimizer, control is
|
||||||
rule-based** (solar surplus, load shedding, priorities). The PV forecast, the
|
rule-based** (solar surplus, load shedding, priorities). The PV forecast, the
|
||||||
[entered tariff](../tarifs.md) and the baseload are **displayed** and **recorded
|
[entered tariff](../tarifs.md) and the baseload are **displayed** and **recorded
|
||||||
locally**, but never used to decide. An automated test checks this: the engine makes
|
locally**, but never used to decide. An automated test checks this: the engine makes
|
||||||
@ -95,12 +95,12 @@ coordinates** (rounded to about 1 km in the plugin versions that carry this feat
|
|||||||
tariff and consumption stay on the box. Remote access is disabled by default: it opens
|
tariff and consumption stay on the box. Remote access is disabled by default: it opens
|
||||||
only if you enable it yourself in the app.
|
only if you enable it yourself in the app.
|
||||||
|
|
||||||
## What about an optimiser?
|
## What about an optimizer?
|
||||||
|
|
||||||
An optimiser, on the other hand, can use these forecasts to plan: the engine hands them
|
An optimizer, on the other hand, can use these forecasts to plan: the engine hands them
|
||||||
over, together with the entered tariff and the baseload, through an
|
over, together with the entered tariff and the baseload, through an
|
||||||
[open, published protocol](../optimiseur/protocole.md). The optimiser runs at your place,
|
[open, published protocol](../optimiseur/protocole.md). The optimizer runs at your place,
|
||||||
on the box or on a machine in your local network, and gets its data from the engine only;
|
on the box or on a machine in your local network, and gets its data from the engine only;
|
||||||
its setpoints stay capped by the engine's bounds and safety. Connecting an optimiser is
|
its setpoints stay capped by the engine's bounds and safety. Connecting an optimizer is
|
||||||
being tested; the Community edition works entirely without one. See the
|
being tested; the Community edition works entirely without one. See the
|
||||||
[Optimizer](../optimiseur/index.md) section.
|
[Optimizer](../optimiseur/index.md) section.
|
||||||
|
|||||||
@ -1,11 +1,11 @@
|
|||||||
# ETM PowerSync
|
# ETM PowerSync
|
||||||
|
|
||||||
**Local HEMS for solar PV, heat pump and EV charging installations.** ETM PowerSync
|
**Local HEMS for solar PV, heat pump and EV charging installations.** ETM PowerSync
|
||||||
coordinates photovoltaics, battery, heat pump and EV charger under a single optimisation
|
coordinates photovoltaics, battery, heat pump and EV charger under a single optimization
|
||||||
logic — running at your site, on your hardware, with no cloud dependency.
|
logic — running at your site, on your hardware, with no cloud dependency.
|
||||||
|
|
||||||
Built on [nymea.io](https://nymea.io), following an **Open Core** architecture: a free
|
Built on [nymea.io](https://nymea.io), following an **Open Core** architecture: a free
|
||||||
foundation (GPL-3.0) and a proprietary optimisation layer.
|
foundation (GPL-3.0) and a proprietary optimization layer.
|
||||||
|
|
||||||
!!! info "Honest statuses"
|
!!! info "Honest statuses"
|
||||||
Every feature shows its real state: <span class="badge stable">STABLE</span>
|
Every feature shows its real state: <span class="badge stable">STABLE</span>
|
||||||
@ -17,7 +17,7 @@ foundation (GPL-3.0) and a proprietary optimisation layer.
|
|||||||
- [Installation](installation/index.md) — deploy ETM PowerSync from the APT repository
|
- [Installation](installation/index.md) — deploy ETM PowerSync from the APT repository
|
||||||
- [Features](fonctionnalites/index.md) — what the HEMS does, and its real state;
|
- [Features](fonctionnalites/index.md) — what the HEMS does, and its real state;
|
||||||
[how the engine decides](fonctionnalites/moteur.md)
|
[how the engine decides](fonctionnalites/moteur.md)
|
||||||
- [Optimizer](optimiseur/index.md) — the open protocol between the engine and an optimiser
|
- [Optimizer](optimiseur/index.md) — the open protocol between the engine and an optimizer
|
||||||
- [Compatibility](appareils/compatibilite.md) — supported equipment
|
- [Compatibility](appareils/compatibilite.md) — supported equipment
|
||||||
- [Integrations](integrations/jsonrpc-api.md) — JSON-RPC API, MQTT, Home Assistant
|
- [Integrations](integrations/jsonrpc-api.md) — JSON-RPC API, MQTT, Home Assistant
|
||||||
|
|
||||||
|
|||||||
@ -42,10 +42,8 @@ Der hier veröffentlichte Vertrag folgt der Entwicklung der Engine; Ihre Box kan
|
|||||||
die Box: Die JSON-RPC-Methode `NymeaEnergy.GetOptimizerProtocol` liefert den, den sie
|
die Box: Die JSON-RPC-Methode `NymeaEnergy.GetOptimizerProtocol` liefert den, den sie
|
||||||
mitbringt. Dieser ist für einen an diese Box angebundenen Optimierer maßgeblich.
|
mitbringt. Dieser ist für einen an diese Box angebundenen Optimierer maßgeblich.
|
||||||
|
|
||||||
Die Methode ist in
|
Sie gehört zu den `NymeaEnergy.*`-Methoden des Optimierers (Verbindungspunkt, gemeinsames
|
||||||
[`INTERFACE.md`](https://github.com/etmschurig/etm-powersync-energy-plugin-etm/blob/main/INTERFACE.md)
|
Geheimnis, Zustand); ihre genaue Form liefert die Box selbst über `JSONRPC.Introspect`. Die Verbindung zur API
|
||||||
im Engine-Repository beschrieben, zusammen mit den übrigen `NymeaEnergy.*`-Methoden des
|
|
||||||
Optimierers (Verbindungspunkt, gemeinsames Geheimnis, Zustand). Die Verbindung zur API
|
|
||||||
beschreibt die Seite [JSON-RPC-API](../integrations/jsonrpc-api.md).
|
beschreibt die Seite [JSON-RPC-API](../integrations/jsonrpc-api.md).
|
||||||
|
|
||||||
## Nachrichten prüfen {#valider}
|
## Nachrichten prüfen {#valider}
|
||||||
|
|||||||
@ -39,12 +39,10 @@ repository. Its record:
|
|||||||
The contract published here follows the engine's development; your box may carry an
|
The contract published here follows the engine's development; your box may carry an
|
||||||
earlier version. To get **the** contract of the installed engine, ask the box: the
|
earlier version. To get **the** contract of the installed engine, ask the box: the
|
||||||
JSON-RPC method `NymeaEnergy.GetOptimizerProtocol` returns the one it embeds. That is the
|
JSON-RPC method `NymeaEnergy.GetOptimizerProtocol` returns the one it embeds. That is the
|
||||||
one that is authoritative for an optimiser connected to that box.
|
one that is authoritative for an optimizer connected to that box.
|
||||||
|
|
||||||
The method is described in
|
It belongs to the optimizer `NymeaEnergy.*` methods (endpoint, shared secret, status); the
|
||||||
[`INTERFACE.md`](https://github.com/etmschurig/etm-powersync-energy-plugin-etm/blob/main/INTERFACE.md),
|
box itself returns their exact form through `JSONRPC.Introspect`. Connecting to the API is described on the
|
||||||
in the engine repository, along with the other optimiser `NymeaEnergy.*` methods
|
|
||||||
(endpoint, shared secret, status). Connecting to the API is described on the
|
|
||||||
[JSON-RPC API](../integrations/jsonrpc-api.md) page.
|
[JSON-RPC API](../integrations/jsonrpc-api.md) page.
|
||||||
|
|
||||||
## Validating messages {#valider}
|
## Validating messages {#valider}
|
||||||
|
|||||||
@ -41,10 +41,8 @@ antérieure. Pour connaître **le** contrat du moteur installé, demandez-le à
|
|||||||
méthode JSON-RPC `NymeaEnergy.GetOptimizerProtocol` rend celui qu'elle embarque. C'est
|
méthode JSON-RPC `NymeaEnergy.GetOptimizerProtocol` rend celui qu'elle embarque. C'est
|
||||||
celui-là qui fait foi pour un optimiseur branché sur cette box.
|
celui-là qui fait foi pour un optimiseur branché sur cette box.
|
||||||
|
|
||||||
La méthode est décrite dans
|
Elle fait partie des méthodes `NymeaEnergy.*` de l'optimiseur (point de connexion, secret
|
||||||
[`INTERFACE.md`](https://github.com/etmschurig/etm-powersync-energy-plugin-etm/blob/main/INTERFACE.md),
|
partagé, état) ; la box en rend la forme exacte par `JSONRPC.Introspect`. La connexion à l'API est décrite sur la page
|
||||||
dans le dépôt du moteur, avec les autres méthodes `NymeaEnergy.*` de l'optimiseur
|
|
||||||
(point de connexion, secret partagé, état). La connexion à l'API est décrite sur la page
|
|
||||||
[API JSON-RPC](../integrations/jsonrpc-api.md).
|
[API JSON-RPC](../integrations/jsonrpc-api.md).
|
||||||
|
|
||||||
## Valider des messages {#valider}
|
## Valider des messages {#valider}
|
||||||
|
|||||||
@ -27,7 +27,7 @@ Drei Punkte, die man nicht übersehen sollte:
|
|||||||
|
|
||||||
Das Engine-Repository enthält einen freien Referenz-Optimierer (GPL-3.0) in Python, nur
|
Das Engine-Repository enthält einen freien Referenz-Optimierer (GPL-3.0) in Python, nur
|
||||||
mit der Standardbibliothek:
|
mit der Standardbibliothek:
|
||||||
[`tools/etm-powersync-ref-optimizer/`](https://github.com/etmschurig/etm-powersync-energy-plugin-etm/tree/main/tools/etm-powersync-ref-optimizer).
|
[`tools/etm-powersync-ref-optimizer/`](https://git.etm-powersync.fr/ETM-Schurig/etm-powersync-energy-plugin-etm/src/branch/main/tools/etm-powersync-ref-optimizer).
|
||||||
Er antwortet mit einem Plan aus einem Zeitfenster, der die Kaskade der Engine-Regeln
|
Er antwortet mit einem Plan aus einem Zeitfenster, der die Kaskade der Engine-Regeln
|
||||||
nachbildet, und liest dabei nur den Kontext. Beim Handshake meldet er sich als
|
nachbildet, und liest dabei nur den Kontext. Beim Handshake meldet er sich als
|
||||||
`powersync-optimizer`.
|
`powersync-optimizer`.
|
||||||
@ -36,12 +36,12 @@ Er ist Ausgangspunkt für einen eigenen Optimierer und Vergleichsmaßstab: Er la
|
|||||||
standardmäßig am lokalen Socket oder an `tcp://` mit einem gemeinsamen Geheimnis, das aus
|
standardmäßig am lokalen Socket oder an `tcp://` mit einem gemeinsamen Geheimnis, das aus
|
||||||
einer Datei gelesen wird. Er kann auch Fehler einspeisen (Enthaltung, Langsamkeit,
|
einer Datei gelesen wird. Er kann auch Fehler einspeisen (Enthaltung, Langsamkeit,
|
||||||
ungültiger Plan, andere Hauptversion…), um den Rückfall der Engine zu testen.
|
ungültiger Plan, andere Hauptversion…), um den Rückfall der Engine zu testen.
|
||||||
Anleitung: [seine `README.md`](https://github.com/etmschurig/etm-powersync-energy-plugin-etm/blob/main/tools/etm-powersync-ref-optimizer/README.md).
|
Anleitung: [seine `README.md`](https://git.etm-powersync.fr/ETM-Schurig/etm-powersync-energy-plugin-etm/src/branch/main/tools/etm-powersync-ref-optimizer/README.md).
|
||||||
|
|
||||||
## Die Engine an den eigenen Optimierer anbinden {#brancher}
|
## Die Engine an den eigenen Optimierer anbinden {#brancher}
|
||||||
|
|
||||||
Drei JSON-RPC-Methoden der Box, dem Administrator vorbehalten, beschrieben in
|
Drei JSON-RPC-Methoden der Box (die ersten beiden dem Administrator vorbehalten); ihre genaue
|
||||||
[`INTERFACE.md`](https://github.com/etmschurig/etm-powersync-energy-plugin-etm/blob/main/INTERFACE.md):
|
Form liefert die Box selbst über `JSONRPC.Introspect`:
|
||||||
|
|
||||||
- `NymeaEnergy.SetOptimizerEndpoint` — wohin verbinden (`unix:///…` oder `tcp://host:port`);
|
- `NymeaEnergy.SetOptimizerEndpoint` — wohin verbinden (`unix:///…` oder `tcp://host:port`);
|
||||||
- `NymeaEnergy.SetOptimizerToken` — das gemeinsame Geheimnis, dasselbe wie beim Optimierer;
|
- `NymeaEnergy.SetOptimizerToken` — das gemeinsame Geheimnis, dasselbe wie beim Optimierer;
|
||||||
@ -78,7 +78,7 @@ export ETM_POWERSYNC_CONFORMANCE_EXPECT=plan # oder abstain
|
|||||||
Jede Funktion läuft in einem eigenen Prozess. Der vollständige Befehl (Netzisolierung
|
Jede Funktion läuft in einem eigenen Prozess. Der vollständige Befehl (Netzisolierung
|
||||||
empfohlen), die übrigen Variablen (gemeinsames Geheimnis, Startfrist…) und das Lesen der
|
empfohlen), die übrigen Variablen (gemeinsames Geheimnis, Startfrist…) und das Lesen der
|
||||||
Fehlschläge stehen in der
|
Fehlschläge stehen in der
|
||||||
[`README.md` der Suite](https://github.com/etmschurig/etm-powersync-energy-plugin-etm/blob/main/tests/auto/conformance/README.md).
|
[`README.md` der Suite](https://git.etm-powersync.fr/ETM-Schurig/etm-powersync-energy-plugin-etm/src/branch/main/tests/auto/conformance/README.md).
|
||||||
|
|
||||||
### Erwarteter Modus: `plan` oder `abstain` {#mode-attendu}
|
### Erwarteter Modus: `plan` oder `abstain` {#mode-attendu}
|
||||||
|
|
||||||
|
|||||||
@ -1,14 +1,14 @@
|
|||||||
# Writing an optimizer
|
# Writing an optimizer
|
||||||
|
|
||||||
An optimiser is a **server** that speaks the [protocol](protocole.md): it answers the
|
An optimizer is a **server** that speaks the [protocol](protocole.md): it answers the
|
||||||
handshake, then every `GetPlan` with a plan of one or more slots, or with an abstention.
|
handshake, then every `GetPlan` with a plan of one or more slots, or with an abstention.
|
||||||
Any language will do. A minimal optimiser fits in about fifty lines of Python.
|
Any language will do. A minimal optimizer fits in about fifty lines of Python.
|
||||||
|
|
||||||
Minimal session, for illustration (the exact shape is in the [contract](contrat.md)):
|
Minimal session, for illustration (the exact shape is in the [contract](contrat.md)):
|
||||||
|
|
||||||
```text
|
```text
|
||||||
→ {"jsonrpc":"2.0","id":1,"method":"Handshake","params":{"protocolVersion":"1.1","engine":"etm-powersync-energy-plugin-etm/…"}}
|
→ {"jsonrpc":"2.0","id":1,"method":"Handshake","params":{"protocolVersion":"1.1","engine":"etm-powersync-energy-plugin-etm/…"}}
|
||||||
← {"jsonrpc":"2.0","id":1,"result":{"protocolVersion":"1.1","name":"my-optimiser","planning":false}}
|
← {"jsonrpc":"2.0","id":1,"result":{"protocolVersion":"1.1","name":"my-optimizer","planning":false}}
|
||||||
→ {"jsonrpc":"2.0","id":2,"method":"GetPlan","params":{ …context… }}
|
→ {"jsonrpc":"2.0","id":2,"method":"GetPlan","params":{ …context… }}
|
||||||
← {"jsonrpc":"2.0","id":2,"result":{"abstain":true,"reason":"premier calcul en cours"}}
|
← {"jsonrpc":"2.0","id":2,"result":{"abstain":true,"reason":"premier calcul en cours"}}
|
||||||
```
|
```
|
||||||
@ -19,14 +19,14 @@ Three things not to miss:
|
|||||||
text: otherwise the whole plan is rejected (the reason text is in French);
|
text: otherwise the whole plan is rejected (the reason text is in French);
|
||||||
- **answer quickly**: serve the last cached plan, or abstain, and compute in the
|
- **answer quickly**: serve the last cached plan, or abstain, and compute in the
|
||||||
background;
|
background;
|
||||||
- **fetch nothing elsewhere**: everything the optimiser needs, forecasts included, is in
|
- **fetch nothing elsewhere**: everything the optimizer needs, forecasts included, is in
|
||||||
the context.
|
the context.
|
||||||
|
|
||||||
## The reference optimiser {#reference}
|
## The reference optimizer {#reference}
|
||||||
|
|
||||||
The engine repository contains a free reference optimiser (GPL-3.0), in Python, standard
|
The engine repository contains a free reference optimizer (GPL-3.0), in Python, standard
|
||||||
library only:
|
library only:
|
||||||
[`tools/etm-powersync-ref-optimizer/`](https://github.com/etmschurig/etm-powersync-energy-plugin-etm/tree/main/tools/etm-powersync-ref-optimizer).
|
[`tools/etm-powersync-ref-optimizer/`](https://git.etm-powersync.fr/ETM-Schurig/etm-powersync-energy-plugin-etm/src/branch/main/tools/etm-powersync-ref-optimizer).
|
||||||
It answers a one-slot plan that reproduces the cascade of the engine's rules, reading only
|
It answers a one-slot plan that reproduces the cascade of the engine's rules, reading only
|
||||||
the context. At handshake it announces itself as `powersync-optimizer`.
|
the context. At handshake it announces itself as `powersync-optimizer`.
|
||||||
|
|
||||||
@ -34,52 +34,52 @@ It is a starting point for writing your own, and a point of comparison: it liste
|
|||||||
local socket by default, or on `tcp://` with a shared secret read from a file. It can also
|
local socket by default, or on `tcp://` with a shared secret read from a file. It can also
|
||||||
inject faults (abstention, slowness, invalid plan, different major version…) to test the
|
inject faults (abstention, slowness, invalid plan, different major version…) to test the
|
||||||
engine's fallback. Instructions:
|
engine's fallback. Instructions:
|
||||||
[its `README.md`](https://github.com/etmschurig/etm-powersync-energy-plugin-etm/blob/main/tools/etm-powersync-ref-optimizer/README.md).
|
[its `README.md`](https://git.etm-powersync.fr/ETM-Schurig/etm-powersync-energy-plugin-etm/src/branch/main/tools/etm-powersync-ref-optimizer/README.md).
|
||||||
|
|
||||||
## Pointing the engine at your optimiser {#brancher}
|
## Pointing the engine at your optimizer {#brancher}
|
||||||
|
|
||||||
Three JSON-RPC methods of the box, reserved to the administrator, described in
|
Three JSON-RPC methods of the box (the first two reserved to the administrator); the box itself
|
||||||
[`INTERFACE.md`](https://github.com/etmschurig/etm-powersync-energy-plugin-etm/blob/main/INTERFACE.md):
|
returns their exact form through `JSONRPC.Introspect`:
|
||||||
|
|
||||||
- `NymeaEnergy.SetOptimizerEndpoint` — where to connect (`unix:///…` or `tcp://host:port`);
|
- `NymeaEnergy.SetOptimizerEndpoint` — where to connect (`unix:///…` or `tcp://host:port`);
|
||||||
- `NymeaEnergy.SetOptimizerToken` — the shared secret, the same as the optimiser's;
|
- `NymeaEnergy.SetOptimizerToken` — the shared secret, the same as the optimizer's;
|
||||||
- `NymeaEnergy.GetOptimizerStatus` — connection status: optimiser alive, active strategy,
|
- `NymeaEnergy.GetOptimizerStatus` — connection status: optimizer alive, active strategy,
|
||||||
announced name, last error code.
|
announced name, last error code.
|
||||||
|
|
||||||
Over `tcp://` without encryption, the secret travels in clear text on the local network.
|
Over `tcp://` without encryption, the secret travels in clear text on the local network.
|
||||||
|
|
||||||
## The conformance suite {#conformite}
|
## The conformance suite {#conformite}
|
||||||
|
|
||||||
The `etm-powersync-optimizer-conformance` suite starts **your** optimiser and connects the
|
The `etm-powersync-optimizer-conformance` suite starts **your** optimizer and connects the
|
||||||
**real** engine to it, on simulated devices. It checks, one function per point:
|
**real** engine to it, on simulated devices. It checks, one function per point:
|
||||||
|
|
||||||
1. the handshake is accepted;
|
1. the handshake is accepted;
|
||||||
2. every `GetPlan` is answered within the engine's timeout;
|
2. every `GetPlan` is answered within the engine's timeout;
|
||||||
3. the whole session, both ways, conforms to the contract embedded in the engine,
|
3. the whole session, both ways, conforms to the contract embedded in the engine,
|
||||||
validation rules included;
|
validation rules included;
|
||||||
4. every plan is applied: the optimiser is in control;
|
4. every plan is applied: the optimizer is in control;
|
||||||
5. the safety loop stays on top: an out-of-bounds setpoint is clamped, a phase overload is
|
5. the safety loop stays on top: an out-of-bounds setpoint is clamped, a phase overload is
|
||||||
shed.
|
shed.
|
||||||
|
|
||||||
It does not judge the **quality** of the plans.
|
It does not judge the **quality** of the plans.
|
||||||
|
|
||||||
### Running it against your optimiser
|
### Running it against your optimizer
|
||||||
|
|
||||||
Build the engine with its tests, then give the command that starts your server;
|
Build the engine with its tests, then give the command that starts your server;
|
||||||
`{endpoint}` in it is replaced by the address to listen on:
|
`{endpoint}` in it is replaced by the address to listen on:
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
export ETM_POWERSYNC_OPTIMIZER_CMD='exec /path/to/my-optimiser --listen {endpoint}'
|
export ETM_POWERSYNC_OPTIMIZER_CMD='exec /path/to/my-optimizer --listen {endpoint}'
|
||||||
export ETM_POWERSYNC_CONFORMANCE_EXPECT=plan # or abstain
|
export ETM_POWERSYNC_CONFORMANCE_EXPECT=plan # or abstain
|
||||||
```
|
```
|
||||||
|
|
||||||
Each function runs in its own process. The full command (network isolation recommended),
|
Each function runs in its own process. The full command (network isolation recommended),
|
||||||
the other variables (shared secret, start-up delay…) and how to read failures are in the
|
the other variables (shared secret, start-up delay…) and how to read failures are in the
|
||||||
[suite's `README.md`](https://github.com/etmschurig/etm-powersync-energy-plugin-etm/blob/main/tests/auto/conformance/README.md).
|
[suite's `README.md`](https://git.etm-powersync.fr/ETM-Schurig/etm-powersync-energy-plugin-etm/src/branch/main/tests/auto/conformance/README.md).
|
||||||
|
|
||||||
### Expected mode: `plan` or `abstain` {#mode-attendu}
|
### Expected mode: `plan` or `abstain` {#mode-attendu}
|
||||||
|
|
||||||
`ETM_POWERSYNC_CONFORMANCE_EXPECT` tells the suite what your optimiser does:
|
`ETM_POWERSYNC_CONFORMANCE_EXPECT` tells the suite what your optimizer does:
|
||||||
|
|
||||||
- **`plan`** (default): it is in control. Every cycle must apply its plan.
|
- **`plan`** (default): it is in control. Every cycle must apply its plan.
|
||||||
- **`abstain`**: it abstains on every cycle — that is allowed, and conformant. The suite
|
- **`abstain`**: it abstains on every cycle — that is allowed, and conformant. The suite
|
||||||
@ -95,5 +95,5 @@ The mode is given, not guessed.
|
|||||||
|
|
||||||
The engine can record, on the box, a trace of every cycle (off by default,
|
The engine can record, on the box, a trace of every cycle (off by default,
|
||||||
`NymeaEnergy.SetOptimizerTrace`). The `tools/etm-powersync-trace-replay` tool replays these
|
`NymeaEnergy.SetOptimizerTrace`). The `tools/etm-powersync-trace-replay` tool replays these
|
||||||
traces against a candidate optimiser and summarises the differences from the recorded plan.
|
traces against a candidate optimizer and summarises the differences from the recorded plan.
|
||||||
Traces stay on site.
|
Traces stay on site.
|
||||||
|
|||||||
@ -27,7 +27,7 @@ Trois points à ne pas manquer :
|
|||||||
|
|
||||||
Le dépôt du moteur contient un optimiseur de référence libre (GPL-3.0), en Python,
|
Le dépôt du moteur contient un optimiseur de référence libre (GPL-3.0), en Python,
|
||||||
bibliothèque standard seule :
|
bibliothèque standard seule :
|
||||||
[`tools/etm-powersync-ref-optimizer/`](https://github.com/etmschurig/etm-powersync-energy-plugin-etm/tree/main/tools/etm-powersync-ref-optimizer).
|
[`tools/etm-powersync-ref-optimizer/`](https://git.etm-powersync.fr/ETM-Schurig/etm-powersync-energy-plugin-etm/src/branch/main/tools/etm-powersync-ref-optimizer).
|
||||||
Il répond un plan à un créneau qui reproduit la cascade des règles du moteur, en ne lisant
|
Il répond un plan à un créneau qui reproduit la cascade des règles du moteur, en ne lisant
|
||||||
que le contexte. Il s'annonce `powersync-optimizer` au handshake.
|
que le contexte. Il s'annonce `powersync-optimizer` au handshake.
|
||||||
|
|
||||||
@ -35,12 +35,12 @@ C'est un point de départ pour écrire le sien, et un point de comparaison : il
|
|||||||
le socket local par défaut, ou sur `tcp://` avec un secret partagé lu dans un fichier. Il
|
le socket local par défaut, ou sur `tcp://` avec un secret partagé lu dans un fichier. Il
|
||||||
sait aussi injecter des défauts (abstention, lenteur, plan invalide, majeure différente…)
|
sait aussi injecter des défauts (abstention, lenteur, plan invalide, majeure différente…)
|
||||||
pour tester le repli du moteur. Mode d'emploi :
|
pour tester le repli du moteur. Mode d'emploi :
|
||||||
[son `README.md`](https://github.com/etmschurig/etm-powersync-energy-plugin-etm/blob/main/tools/etm-powersync-ref-optimizer/README.md).
|
[son `README.md`](https://git.etm-powersync.fr/ETM-Schurig/etm-powersync-energy-plugin-etm/src/branch/main/tools/etm-powersync-ref-optimizer/README.md).
|
||||||
|
|
||||||
## Brancher le moteur sur son optimiseur {#brancher}
|
## Brancher le moteur sur son optimiseur {#brancher}
|
||||||
|
|
||||||
Trois méthodes JSON-RPC de la box, réservées à l'administrateur, décrites dans
|
Trois méthodes JSON-RPC de la box (les deux premières réservées à l'administrateur) ; la box
|
||||||
[`INTERFACE.md`](https://github.com/etmschurig/etm-powersync-energy-plugin-etm/blob/main/INTERFACE.md) :
|
en rend la forme exacte par `JSONRPC.Introspect` :
|
||||||
|
|
||||||
- `NymeaEnergy.SetOptimizerEndpoint` — où se connecter (`unix:///…` ou `tcp://hôte:port`) ;
|
- `NymeaEnergy.SetOptimizerEndpoint` — où se connecter (`unix:///…` ou `tcp://hôte:port`) ;
|
||||||
- `NymeaEnergy.SetOptimizerToken` — le secret partagé, le même que celui de l'optimiseur ;
|
- `NymeaEnergy.SetOptimizerToken` — le secret partagé, le même que celui de l'optimiseur ;
|
||||||
@ -77,7 +77,7 @@ export ETM_POWERSYNC_CONFORMANCE_EXPECT=plan # ou abstain
|
|||||||
Chaque fonction se lance dans son propre processus. La commande complète (isolement
|
Chaque fonction se lance dans son propre processus. La commande complète (isolement
|
||||||
réseau recommandé), les autres variables (secret partagé, délai de démarrage…) et la
|
réseau recommandé), les autres variables (secret partagé, délai de démarrage…) et la
|
||||||
lecture des échecs sont dans le
|
lecture des échecs sont dans le
|
||||||
[`README.md` de la suite](https://github.com/etmschurig/etm-powersync-energy-plugin-etm/blob/main/tests/auto/conformance/README.md).
|
[`README.md` de la suite](https://git.etm-powersync.fr/ETM-Schurig/etm-powersync-energy-plugin-etm/src/branch/main/tests/auto/conformance/README.md).
|
||||||
|
|
||||||
### Mode attendu : `plan` ou `abstain` {#mode-attendu}
|
### Mode attendu : `plan` ou `abstain` {#mode-attendu}
|
||||||
|
|
||||||
|
|||||||
@ -2,57 +2,57 @@
|
|||||||
|
|
||||||
<span class="badge testing">IN PROGRESS</span>
|
<span class="badge testing">IN PROGRESS</span>
|
||||||
|
|
||||||
The protocol between the engine and an optimiser is published (version 1.1). Connecting
|
The protocol between the engine and an optimizer is published (version 1.1). Connecting
|
||||||
an optimiser is being tested on our test installation; the box does not need one to work.
|
an optimizer is being tested on our test installation; the box does not need one to work.
|
||||||
|
|
||||||
## What an optimiser is for
|
## What an optimizer is for
|
||||||
|
|
||||||
The [engine's rules](../fonctionnalites/moteur.md) decide on the present: this minute's
|
The [engine's rules](../fonctionnalites/moteur.md) decide on the present: this minute's
|
||||||
surplus, shared according to your priorities. An optimiser looks further ahead. From the
|
surplus, shared according to your priorities. An optimizer looks further ahead. From the
|
||||||
forecasts the engine hands it — PV production, base consumption, entered tariff — it
|
forecasts the engine hands it — PV production, base consumption, entered tariff — it
|
||||||
proposes a **plan in time slots** over several hours: shift the water heater to the
|
proposes a **plan in time slots** over several hours: shift the water heater to the
|
||||||
expected production peak, keep headroom for evening charging, and so on.
|
expected production peak, keep headroom for evening charging, and so on.
|
||||||
|
|
||||||
## The optimiser advises, the engine decides
|
## The optimizer advises, the engine decides
|
||||||
|
|
||||||
- The engine only executes the **current slot** of the plan. The rest is shown as a
|
- The engine only executes the **current slot** of the plan. The rest is shown as a
|
||||||
forecast, and requested again on the next cycle.
|
forecast, and requested again on the next cycle.
|
||||||
- Every setpoint is **capped** by the load's bounds (floor, ceiling, anti-flapping locks)
|
- Every setpoint is **capped** by the load's bounds (floor, ceiling, anti-flapping locks)
|
||||||
and by the real-time **safety loop**, which stays with the engine and overrides
|
and by the real-time **safety loop**, which stays with the engine and overrides
|
||||||
everything. An optimiser cannot bypass a lock.
|
everything. An optimizer cannot bypass a lock.
|
||||||
- Every action must carry its **reason**. An action without one is rejected.
|
- Every action must carry its **reason**. An action without one is rejected.
|
||||||
- A malformed plan, or one that targets an unknown load, is rejected as a whole.
|
- A malformed plan, or one that targets an unknown load, is rejected as a whole.
|
||||||
|
|
||||||
At worst, a faulty optimiser can therefore only propose a poor allocation — bounded by the
|
At worst, a faulty optimizer can therefore only propose a poor allocation — bounded by the
|
||||||
engine.
|
engine.
|
||||||
|
|
||||||
## The box works without an optimiser
|
## The box works without an optimizer
|
||||||
|
|
||||||
Optimiser missing, silent, abstaining, plan expired or rejected: the engine returns to its
|
Optimizer missing, silent, abstaining, plan expired or rejected: the engine returns to its
|
||||||
**rules** (`rules`) for that cycle, with no interruption of control. The app shows at all
|
**rules** (`rules`) for that cycle, with no interruption of control. The app shows at all
|
||||||
times which strategy is in charge. The Community edition works entirely this way.
|
times which strategy is in charge. The Community edition works entirely this way.
|
||||||
|
|
||||||
## Its data come from the engine only
|
## Its data come from the engine only
|
||||||
|
|
||||||
- The engine connects to the optimiser, never the other way round: the box opens no port.
|
- The engine connects to the optimizer, never the other way round: the box opens no port.
|
||||||
- The optimiser runs on the box (local socket) or on a machine in your local network
|
- The optimizer runs on the box (local socket) or on a machine in your local network
|
||||||
(TCP). On the local network, a shared secret (token) is recommended.
|
(TCP). On the local network, a shared secret (token) is recommended.
|
||||||
- It receives **only** the context the engine sends, forecasts included: it calls neither
|
- It receives **only** the context the engine sends, forecasts included: it calls neither
|
||||||
a weather service nor a tariff provider, and opens no connection to the outside.
|
a weather service nor a tariff provider, and opens no connection to the outside.
|
||||||
- What it learns stays on site.
|
- What it learns stays on site.
|
||||||
|
|
||||||
## Who can write an optimiser
|
## Who can write an optimizer
|
||||||
|
|
||||||
Anyone. The protocol is open and described by a [machine-readable contract](contrat.md)
|
Anyone. The protocol is open and described by a [machine-readable contract](contrat.md)
|
||||||
published under GPL-3.0. A free **reference optimiser** and a **conformance suite** let you
|
published under GPL-3.0. A free **reference optimizer** and a **conformance suite** let you
|
||||||
write your own and check it against the real engine — see
|
write your own and check it against the real engine — see
|
||||||
[Writing an optimizer](ecrire.md).
|
[Writing an optimizer](ecrire.md).
|
||||||
|
|
||||||
## The ETM optimiser
|
## The ETM optimizer
|
||||||
|
|
||||||
ETM-Schurig offers its own proprietary optimiser, included in the Pro edition. It connects
|
ETM-Schurig offers its own proprietary optimizer, included in the Pro edition. It connects
|
||||||
through this same protocol, within the same limits: it advises, the engine decides. At
|
through this same protocol, within the same limits: it advises, the engine decides. At
|
||||||
handshake it announces itself as `etm-optimizer`; the reference optimiser announces itself
|
handshake it announces itself as `etm-optimizer`; the reference optimizer announces itself
|
||||||
as `powersync-optimizer`.
|
as `powersync-optimizer`.
|
||||||
|
|
||||||
## In this section
|
## In this section
|
||||||
@ -60,4 +60,4 @@ as `powersync-optimizer`.
|
|||||||
- [Protocol](protocole.md) — transport, handshake, context, plan, fallback, validation
|
- [Protocol](protocole.md) — transport, handshake, context, plan, fallback, validation
|
||||||
rules.
|
rules.
|
||||||
- [Contract](contrat.md) — the OpenRPC file that is authoritative on the shape of messages.
|
- [Contract](contrat.md) — the OpenRPC file that is authoritative on the shape of messages.
|
||||||
- [Writing an optimizer](ecrire.md) — reference optimiser and conformance suite.
|
- [Writing an optimizer](ecrire.md) — reference optimizer and conformance suite.
|
||||||
|
|||||||
@ -11,7 +11,7 @@ eigenen Kanal. Es ist nicht die API der App: Diese läuft über die
|
|||||||
Beschreibungen unverändert aus dem Vertrag, auf Französisch. Sie sind in allen drei
|
Beschreibungen unverändert aus dem Vertrag, auf Französisch. Sie sind in allen drei
|
||||||
Sprachen identisch.
|
Sprachen identisch.
|
||||||
- **Die Bedeutung** ist ausführlich, auf Französisch, in
|
- **Die Bedeutung** ist ausführlich, auf Französisch, in
|
||||||
[`OPTIMIZER_PROTOCOL.md`](https://github.com/etmschurig/etm-powersync-energy-plugin-etm/blob/main/docs/OPTIMIZER_PROTOCOL.md)
|
[`OPTIMIZER_PROTOCOL.md`](https://git.etm-powersync.fr/ETM-Schurig/etm-powersync-energy-plugin-etm/src/branch/main/docs/OPTIMIZER_PROTOCOL.md)
|
||||||
im Repository der Engine beschrieben. Diese Seite fasst das Wesentliche zusammen; bei
|
im Repository der Engine beschrieben. Diese Seite fasst das Wesentliche zusammen; bei
|
||||||
Abweichungen gelten die Dokumente der Engine.
|
Abweichungen gelten die Dokumente der Engine.
|
||||||
|
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
# Protocol
|
# Protocol
|
||||||
|
|
||||||
The protocol links the box's energy **engine** to an **optimiser**, over a dedicated
|
The protocol links the box's energy **engine** to an **optimizer**, over a dedicated
|
||||||
channel. It is not the app's API: the app goes through the
|
channel. It is not the app's API: the app goes through the
|
||||||
[JSON-RPC API](../integrations/jsonrpc-api.md).
|
[JSON-RPC API](../integrations/jsonrpc-api.md).
|
||||||
|
|
||||||
@ -10,13 +10,13 @@ channel. It is not the app's API: the app goes through the
|
|||||||
**generated** from it on every publication: framing in English, descriptions taken
|
**generated** from it on every publication: framing in English, descriptions taken
|
||||||
as-is from the contract, in French. They are identical in all three languages.
|
as-is from the contract, in French. They are identical in all three languages.
|
||||||
- **The meaning** is described in detail, in French, in
|
- **The meaning** is described in detail, in French, in
|
||||||
[`OPTIMIZER_PROTOCOL.md`](https://github.com/etmschurig/etm-powersync-energy-plugin-etm/blob/main/docs/OPTIMIZER_PROTOCOL.md),
|
[`OPTIMIZER_PROTOCOL.md`](https://git.etm-powersync.fr/ETM-Schurig/etm-powersync-energy-plugin-etm/src/branch/main/docs/OPTIMIZER_PROTOCOL.md),
|
||||||
in the engine repository. This page gives the essentials; where they differ, the
|
in the engine repository. This page gives the essentials; where they differ, the
|
||||||
engine's documents prevail.
|
engine's documents prevail.
|
||||||
|
|
||||||
## Transport and roles {#transport}
|
## Transport and roles {#transport}
|
||||||
|
|
||||||
- The optimiser is the **server**, the engine is the **client**: the engine connects and
|
- The optimizer is the **server**, the engine is the **client**: the engine connects and
|
||||||
asks the questions. The box opens no port.
|
asks the questions. The box opens no port.
|
||||||
- Two transports, same messages: `unix://` (local socket, default) and `tcp://` (machine
|
- Two transports, same messages: `unix://` (local socket, default) and `tcp://` (machine
|
||||||
on the local network).
|
on the local network).
|
||||||
@ -65,10 +65,10 @@ channel. It is not the app's API: the app goes through the
|
|||||||
## Handshake {#handshake}
|
## Handshake {#handshake}
|
||||||
|
|
||||||
On every connection, the engine sends `Handshake` with its protocol version and, if
|
On every connection, the engine sends `Handshake` with its protocol version and, if
|
||||||
configured, the shared secret. The optimiser answers with its version and, if it wishes,
|
configured, the shared secret. The optimizer answers with its version and, if it wishes,
|
||||||
its name and capabilities. A different **major** version, a refused secret or an
|
its name and capabilities. A different **major** version, a refused secret or an
|
||||||
unreadable answer: the connection is refused, and the engine drives by its rules. If the
|
unreadable answer: the connection is refused, and the engine drives by its rules. If the
|
||||||
optimiser announces the action kinds (`kinds`) it emits, the engine then rejects any action
|
optimizer announces the action kinds (`kinds`) it emits, the engine then rejects any action
|
||||||
of another kind.
|
of another kind.
|
||||||
|
|
||||||
<!-- BEGIN GENERATED: __optimizer_handshake__ -->
|
<!-- BEGIN GENERATED: __optimizer_handshake__ -->
|
||||||
@ -505,14 +505,14 @@ Undeclared fields: **rejected** (engine-emitted form, closed).
|
|||||||
|
|
||||||
## The answer: a plan or an abstention {#reponse}
|
## The answer: a plan or an abstention {#reponse}
|
||||||
|
|
||||||
The optimiser answers **quickly** — with its last cached plan if it computes for long —
|
The optimizer answers **quickly** — with its last cached plan if it computes for long —
|
||||||
and recomputes in the background. It answers either:
|
and recomputes in the background. It answers either:
|
||||||
|
|
||||||
- a **plan in time slots**: each slot carries one action per available load (setpoint in
|
- a **plan in time slots**: each slot carries one action per available load (setpoint in
|
||||||
watts or amps, or SG-Ready state), each with its reason; only the current slot is
|
watts or amps, or SG-Ready state), each with its reason; only the current slot is
|
||||||
executed, and `validUntil` bounds the plan's lifetime;
|
executed, and `validUntil` bounds the plan's lifetime;
|
||||||
- an **abstention** (`abstain: true`): "no plan right now". The engine drives by its rules
|
- an **abstention** (`abstain: true`): "no plan right now". The engine drives by its rules
|
||||||
for that cycle, without treating the optimiser as failed.
|
for that cycle, without treating the optimizer as failed.
|
||||||
|
|
||||||
An action's reason has two forms: a free text in French, **mandatory**, for the traces;
|
An action's reason has two forms: a free text in French, **mandatory**, for the traces;
|
||||||
and, optionally, a code from the catalogue (`reasonCode`) with its parameters. Only **the
|
and, optionally, a code from the catalogue (`reasonCode`) with its parameters. Only **the
|
||||||
@ -684,7 +684,7 @@ Type: map of number \| boolean \| string \| null
|
|||||||
|
|
||||||
## `UpdateLearned` {#updatelearned}
|
## `UpdateLearned` {#updatelearned}
|
||||||
|
|
||||||
Notification sent by the optimiser to the engine, with no answer, to pass on what it has
|
Notification sent by the optimizer to the engine, with no answer, to pass on what it has
|
||||||
learned about the loads. In version 1.1 of the engine, it is received and logged, but not
|
learned about the loads. In version 1.1 of the engine, it is received and logged, but not
|
||||||
yet used.
|
yet used.
|
||||||
|
|
||||||
@ -704,8 +704,8 @@ Envoyée par l'OPTIMISEUR (sens inverse des deux autres), sans id, sans réponse
|
|||||||
|
|
||||||
## Fallback state machine {#repli}
|
## Fallback state machine {#repli}
|
||||||
|
|
||||||
There is no separate heartbeat: a valid answer to `GetPlan` means the optimiser is alive.
|
There is no separate heartbeat: a valid answer to `GetPlan` means the optimizer is alive.
|
||||||
Failures are counted per request; after several consecutive failures, the optimiser is
|
Failures are counted per request; after several consecutive failures, the optimizer is
|
||||||
declared absent and the engine drives by its rules until the next valid plan. The app sees
|
declared absent and the engine drives by its rules until the next valid plan. The app sees
|
||||||
this state continuously (`optimizerAlive`, `activeStrategy`).
|
this state continuously (`optimizerAlive`, `activeStrategy`).
|
||||||
|
|
||||||
@ -763,7 +763,7 @@ Ce que le moteur refuse EN PLUS de la forme, dans l'ordre de ses contrôles (Opt
|
|||||||
|
|
||||||
### Tolerances {#tolerances}
|
### Tolerances {#tolerances}
|
||||||
|
|
||||||
What the engine accepts beyond the contract. A conformant optimiser does not rely on it.
|
What the engine accepts beyond the contract. A conformant optimizer does not rely on it.
|
||||||
|
|
||||||
<!-- BEGIN GENERATED: __optimizer_tolerances__ -->
|
<!-- BEGIN GENERATED: __optimizer_tolerances__ -->
|
||||||
|
|
||||||
|
|||||||
@ -9,7 +9,7 @@ dédié. Ce n'est pas l'API de l'application : celle-ci passe par l'[API JSON-RP
|
|||||||
**générés** à chaque publication : cadre en anglais, descriptions reprises telles
|
**générés** à chaque publication : cadre en anglais, descriptions reprises telles
|
||||||
quelles du contrat, en français. Ils sont identiques dans les trois langues.
|
quelles du contrat, en français. Ils sont identiques dans les trois langues.
|
||||||
- **Le sens** est décrit en détail, en français, dans
|
- **Le sens** est décrit en détail, en français, dans
|
||||||
[`OPTIMIZER_PROTOCOL.md`](https://github.com/etmschurig/etm-powersync-energy-plugin-etm/blob/main/docs/OPTIMIZER_PROTOCOL.md),
|
[`OPTIMIZER_PROTOCOL.md`](https://git.etm-powersync.fr/ETM-Schurig/etm-powersync-energy-plugin-etm/src/branch/main/docs/OPTIMIZER_PROTOCOL.md),
|
||||||
dans le dépôt du moteur. Cette page en donne l'essentiel ; en cas d'écart, les
|
dans le dépôt du moteur. Cette page en donne l'essentiel ; en cas d'écart, les
|
||||||
documents du moteur l'emportent.
|
documents du moteur l'emportent.
|
||||||
|
|
||||||
|
|||||||
@ -6,6 +6,6 @@ The box integrates with your tools through two local interfaces, on your network
|
|||||||
conventions — and its [full reference](api/index.md), generated from the box;
|
conventions — and its [full reference](api/index.md), generated from the box;
|
||||||
- [MQTT](integrations/mqtt.md).
|
- [MQTT](integrations/mqtt.md).
|
||||||
|
|
||||||
!!! note "What about the optimiser protocol?"
|
!!! note "What about the optimizer protocol?"
|
||||||
The channel between the engine and an optimiser is **not** an integration API: it
|
The channel between the engine and an optimizer is **not** an integration API: it
|
||||||
has its own protocol, described in the [Optimizer](optimiseur/protocole.md) section.
|
has its own protocol, described in the [Optimizer](optimiseur/protocole.md) section.
|
||||||
|
|||||||
@ -17,15 +17,15 @@ range. A tariff with several ranges is shown there read-only.
|
|||||||
|
|
||||||
!!! note "Exposed, not used to decide"
|
!!! note "Exposed, not used to decide"
|
||||||
The engine **exposes** the tariff (display, local recording); it does not decide
|
The engine **exposes** the tariff (display, local recording); it does not decide
|
||||||
with it. Without an optimiser, control stays rule-based — see
|
with it. Without an optimizer, control stays rule-based — see
|
||||||
[PV production forecast](fonctionnalites/prevision-pv.md#what-the-forecast-does-not-do).
|
[PV production forecast](fonctionnalites/prevision-pv.md#what-the-forecast-does-not-do).
|
||||||
|
|
||||||
## Dynamic tariffs <span class="badge nightly">ROADMAP</span>
|
## Dynamic tariffs <span class="badge nightly">ROADMAP</span>
|
||||||
|
|
||||||
Arbitration on national tariff signals — **France**: Tempo (blue/white/red), off-peak
|
Arbitration on national tariff signals — **France**: Tempo (blue/white/red), off-peak
|
||||||
and peak hours, dynamic offers; CO₂ optimisation from the RTE eco2mix signal.
|
and peak hours, dynamic offers; CO₂ optimization from the RTE eco2mix signal.
|
||||||
**Germany**: variable tariffs, spot offers (EPEX), grid-responsive control of
|
**Germany**: variable tariffs, spot offers (EPEX), grid-responsive control of
|
||||||
controllable loads under **§14a EnWG**; CO₂ optimisation from **SMARD**
|
controllable loads under **§14a EnWG**; CO₂ optimization from **SMARD**
|
||||||
(Bundesnetzagentur).
|
(Bundesnetzagentur).
|
||||||
|
|
||||||
!!! note "Roadmap"
|
!!! note "Roadmap"
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user