feat(control): connect physical feedback to bounded V4 command and fallback paths
This commit is contained in:
@@ -7,6 +7,7 @@ namespace Belevo\EnelixEMS;
|
||||
use InvalidArgumentException;
|
||||
|
||||
require_once __DIR__ . '/NetzfahrplanV4Planpruefung.php';
|
||||
require_once __DIR__ . '/NetzfahrplanV4Rueckmeldung.php';
|
||||
|
||||
/** Separate, explicitly authorized commissioning commands. A preview is NEVER permission. */
|
||||
final class NetzfahrplanV4Regeltest
|
||||
@@ -87,6 +88,11 @@ final class NetzfahrplanV4Regeltest
|
||||
if (($a['controlContext'] ?? null) != $plan['controlContext']) {
|
||||
throw new InvalidArgumentException('Testkonfiguration stimmt nicht mehr.');
|
||||
}
|
||||
$feedback = $operation['localFeedback'][$a['assetId']] ?? [];
|
||||
NetzfahrplanV4Rueckmeldung::requireTrial($feedback, $local, $now);
|
||||
if (abs(self::number($actual[$a['assetId']] ?? null,'Batterie Ist',-1e9,1e9) - self::number($feedback['batteryW'],'Rueckmeldung',-1e9,1e9)) > 0.000001) throw new InvalidArgumentException('feedback_power_not_from_verified_snapshot');
|
||||
$otherDelta=self::number($operation['localPredictedOtherDeltaW']??0.0,'Andere Verbraucherabweichung',-1e9,1e9);
|
||||
if (abs($operation['gridW']-$feedback['gridW']-$otherDelta)>0.001) throw new InvalidArgumentException('feedback_grid_not_from_same_snapshot');
|
||||
$preview = NetzfahrplanV4Planpruefung::vorschau($checked, $operation, $actual, $now);
|
||||
$charge = min(self::number($a['maxChargeW'] ?? null, 'Server-Ladegrenze', 1, self::MAX_TEST_POWER_W),
|
||||
self::number($local['maxChargeW'] ?? null, 'Lokale Ladegrenze', 1, self::MAX_TEST_POWER_W));
|
||||
@@ -109,6 +115,9 @@ final class NetzfahrplanV4Regeltest
|
||||
'watts' => $watts, 'maxChargeW' => (int) $charge, 'maxDischargeW' => (int) $discharge,
|
||||
'sourceShadowPlanId' => $plan['planId'], 'sourceStep' => $p['time'],
|
||||
'revision' => $plan['configRevision'], 'expectedGridW' => $grid,
|
||||
'feedbackConfigHash' => $feedback['configHash'], 'feedbackEstimated' => $feedback['estimated'],
|
||||
'feedbackSourceOldestAt' => $feedback['sourceOldestAt'],
|
||||
'importLimitW' => $p['importLimitW'], 'exportLimitW' => $p['exportLimitW'],
|
||||
'executionMeaning' => 'separate_local_control_trial_not_shadow_plan_execution'];
|
||||
}
|
||||
|
||||
@@ -139,6 +148,23 @@ final class NetzfahrplanV4Regeltest
|
||||
if ($c > $session['maxChargeW'] || $d > $session['maxDischargeW'] || $w > $c || $w < -$d) {
|
||||
throw new InvalidArgumentException('Befehl ueberschreitet lokale Testgrenze.');
|
||||
}
|
||||
if (!is_string($command['feedbackConfigHash'] ?? null) || !preg_match('/^[a-f0-9]{64}$/D', $command['feedbackConfigHash'])
|
||||
|| $command['feedbackConfigHash'] !== ($session['feedbackConfigHash'] ?? null)) throw new InvalidArgumentException('feedback_command_binding_invalid');
|
||||
foreach (['importLimitW','exportLimitW'] as $limit) {
|
||||
if (!array_key_exists($limit,$command)) throw new InvalidArgumentException('feedback_command_limits_missing');
|
||||
if ($command[$limit] !== null) self::number($command[$limit],$limit,0,1e9);
|
||||
}
|
||||
$l=$session['gridLimits'] ?? null;
|
||||
if (!is_array($l) || !array_key_exists('importW',$l) || !array_key_exists('exportW',$l) || !is_array($l['managerMonthLimitsW']??null)) throw new InvalidArgumentException('session_grid_limits_missing');
|
||||
$month=(int)(new \DateTimeImmutable('@'.$now))->setTimezone(new \DateTimeZone('Europe/Zurich'))->format('n');
|
||||
$import=$l['importW'];$monthly=$l['managerMonthLimitsW'][$month]??null;
|
||||
if ($monthly!==null) $import=$import===null?$monthly:min($import,$monthly);
|
||||
foreach (['importLimitW'=>$import,'exportLimitW'=>$l['exportW']] as $key=>$limit) {
|
||||
if ($limit!==null) {
|
||||
self::number($limit,$key,0,1e9);
|
||||
if ($command[$key]===null || $command[$key]>$limit) throw new InvalidArgumentException('command_relaxes_local_grid_limit');
|
||||
}
|
||||
}
|
||||
self::uuid($command['sourceShadowPlanId'] ?? null);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user