feat(control): connect physical feedback to bounded V4 command and fallback paths

This commit is contained in:
ENELIX Agent
2026-10-03 11:40:54 +00:00
parent 8eb9688942
commit 9878197aea
24 changed files with 891 additions and 7 deletions
+13
View File
@@ -8,12 +8,15 @@ use RuntimeException;
use Throwable;
require_once __DIR__ . '/NetzfahrplanV4Regeltest.php';
require_once __DIR__ . '/BatterieNetzfahrplanV4RueckmeldungTrait.php';
/** Dedicated short-lease battery input. Disabled until explicitly armed on BOTH modules. */
trait BatterieNetzfahrplanV4TestTrait
{
use BatterieNetzfahrplanV4RueckmeldungTrait;
private function registriereV4BatterieTest(): void
{
$this->registriereV4Rueckmeldung();
$this->RegisterPropertyBoolean('NetzfahrplanV4RegeltestErlaubt', false);
$this->RegisterAttributeString('NetzfahrplanV4LetzteTestsitzung', '');
$this->RegisterPropertyString('NetzfahrplanV4GeraeteWatchdogNachweis', '');
@@ -69,6 +72,7 @@ trait BatterieNetzfahrplanV4TestTrait
if (!$this->GetValue('Aktiv') || $this->ReadPropertyInteger('Batteriemanagement') !== 2) {
throw new RuntimeException('Batterie nicht unter ENELIX-Regelung.');
}
NetzfahrplanV4Rueckmeldung::requireTrial($this->v4BatterieRueckmeldung(), $s, $now);
$this->WriteAttributeString('NetzfahrplanV4LetzteTestsitzung', $s['sessionId']);
$s['active'] = true;$s['lastSequence'] = 0;$s['lastWallClockAt'] = $now;
$s['monotonicDeadline'] = hrtime(true) / 1e9 + $end - $now;
@@ -157,6 +161,8 @@ trait BatterieNetzfahrplanV4TestTrait
$s = $this->v4BatterieTestSitzung();$mono = hrtime(true) / 1e9;
try {
if (!$this->ReadPropertyBoolean('NetzfahrplanV4RegeltestErlaubt')) throw new RuntimeException('Lokale Testfreigabe entzogen.');
$feedback = $this->v4BatterieRueckmeldung();
NetzfahrplanV4Rueckmeldung::requireTrial($feedback, $s, $now);
$c = json_decode($this->GetBuffer('V4BatteryTrialCommand') ?: '{}', true);
if ($now >= $s['expiresAt'] || $mono >= $s['monotonicDeadline'] || $now < $s['lastWallClockAt']) throw new RuntimeException('Testsitzung abgelaufen/Zeitsprung.');
if (!$c) {
@@ -175,6 +181,13 @@ trait BatterieNetzfahrplanV4TestTrait
if ($last * $w < 0) $w = 0;
elseif (abs($w) > abs($last)) $w = $last;
}
// Final hardware-policy/ramp clipping must not invalidate the binding or grid limits.
if (($c['feedbackConfigHash'] ?? null) !== $feedback['configHash']) throw new RuntimeException('feedback_configuration_changed');
$expectedGrid = $feedback['gridW'] - $feedback['batteryW'] + $w;
if (($c['importLimitW'] !== null && $expectedGrid > $c['importLimitW'] + 1)
|| ($c['exportLimitW'] !== null && -$expectedGrid > $c['exportLimitW'] + 1)) {
throw new RuntimeException('final_battery_clamp_cannot_meet_grid_limit');
}
$s['lastWallClockAt'] = $now;
$this->SetBuffer('V4BatteryTrialSession', json_encode($s, JSON_THROW_ON_ERROR));
return $w;