fix(manager): isolate V4 active import sources from legacy counter

This commit is contained in:
ENELIX Agent
2026-10-01 16:56:39 +00:00
parent 640fe53720
commit 12174a59b4
9 changed files with 356 additions and 11 deletions
+17 -2
View File
@@ -17,6 +17,10 @@ final class NativeV4Scenarios
$m = ['NetzleistungVariableID' => 1, 'NetzbezugEnergieVariableID' => 9,
'Netzleistungsfaktor' => 1.0, 'MesswertMaxAlter' => 60, 'Lastspitzenmodus' => 1,
'Lastspitzengrenze' => 25000.0, 'EinspeisebegrenzungAktiv' => true, 'Einspeisegrenze' => 25000.0];
$m['V4BezugszaehlerQuellen'] = [
['VariableID' => 6, 'ElternID' => 99, 'Ident' => 'Energy_0', 'FaktorZuKWh' => 1.0, 'Messgroesse' => 'WirkenergieBezug'],
['VariableID' => 7, 'ElternID' => 99, 'Ident' => 'Energy_1', 'FaktorZuKWh' => 1.0, 'Messgroesse' => 'WirkenergieBezug'],
];
$a = [['ID' => 'ev', 'Nennkapazitaet_kWh' => 161.44, 'Nutzkapazitaet_kWh' => 161.44,
'MaxLadeleistung_kW' => 39.0, 'MaxEntladeleistung_kW' => 30.0, 'SOCVariableID' => 2, 'LeistungVariableID' => 5]];
$c = [['InstanzID' => 42, 'LadezustandVariableID' => 2, 'MaxLadeleistungVariableID' => 3,
@@ -24,7 +28,8 @@ final class NativeV4Scenarios
'ReserveLadezustand' => 15.0, 'MindestLadezustand' => 3.0, 'MesswertMaxAlter' => 30,
'Verfuegbar' => true, 'Batteriemanagement' => 2, 'EmpfangenAm' => $now]];
$read = static function (int $id) use ($now): array {
return ['value' => [1 => -5332.0, 2 => 19.0, 3 => 39000.0, 4 => 35000.0][$id], 'updated' => $now];
return ['value' => [1 => -5332.0, 2 => 19.0, 3 => 39000.0, 4 => 35000.0, 6 => 3992.203, 7 => 0.0][$id],
'updated' => $now, 'parentID' => 99, 'ident' => [6 => 'Energy_0', 7 => 'Energy_1'][$id] ?? 'other'];
};
$check = static function (bool $ok): void { if (!$ok) { throw new RuntimeException('Assertion failed'); } };
$fail = static function (callable $fn): void {
@@ -97,7 +102,7 @@ final class NativeV4Scenarios
$check($build()['operation']['batteries'][0]['gridCharging'] === false);
$m['NetzladenErlaubt'] = true; $check($build($m)['operation']['batteries'][0]['gridCharging'] === true);
};
$ev = ['version' => 1, 'meterId' => 'symcon:9', 'measuredAt' => gmdate('c', $now),
$ev = ['version' => 1, 'meterId' => \Belevo\EnelixEMS\NetzfahrplanV4Bezugszaehler::identitaet($m['V4BezugszaehlerQuellen']), 'measuredAt' => gmdate('c', $now),
'measuredPeaks' => ['2026-10' => ['kw' => 18.4, 'source' => 'meter_month_register']],
'quarterPast' => ['start' => '2026-10-01T12:00:00Z', 'measuredSeconds' => 300, 'importKwh' => 0.5]];
$cases['actual_meter_evidence_used'] = static function () use ($build, $ev, $check): void {
@@ -117,6 +122,16 @@ final class NativeV4Scenarios
$cases['deterministic_retry_event_id'] = static function () use ($build, $check): void {
$check($build()['operation']['eventId'] === $build()['operation']['eventId']);
};
$cases['legacy_meter_identity_not_accepted'] = static function () use ($build, $ev, $fail): void {
$ev['meterId'] = 'symcon:9'; $fail(static fn() => $build(null, null, null, null, $ev));
};
$cases['missing_v4_sources_never_use_legacy'] = static function () use ($build, $m, $fail): void {
unset($m['V4BezugszaehlerQuellen']); $fail(static fn() => $build($m));
};
$cases['counter_snapshot_is_not_billing_evidence'] = static function () use ($build, $check): void {
$v = $build(); $check($v['bezugszaehler']['totalKwh'] === 3992.203
&& !$v['bezugszaehler']['billingEvidence'] && (array) $v['operation']['measuredPeaks'] === []);
};
$passed = [];
foreach ($cases as $name => $fn) { $fn(); $passed[] = $name; }
return $passed;