feat(workflow): publish verified forecast controls and consolidated docs
Tests / test (push) Successful in 1m1s

Approved by Daniel Haefliger for develop and beta. Author dh_Agent, authenticated account dh. Preserve published battery, charging and overall Energy Pie changes. No deployment or plant control authorization.
This commit is contained in:
dh
2026-10-08 10:02:58 +00:00
parent af69151165
commit 74a2d6c685
82 changed files with 5054 additions and 617 deletions
+17 -6
View File
@@ -10,8 +10,8 @@ $GLOBALS['deviceCalls'] = 0;
$GLOBALS['testParent'] = 20;
function MBUS_UpdateValues(int $id): bool { ++$GLOBALS['deviceCalls']; throw new RuntimeException('Unexpected device I/O'); }
function ModBus_RequestRead(int $id): bool { ++$GLOBALS['deviceCalls']; throw new RuntimeException('Unexpected device I/O'); }
function IPS_VariableExists(int $id): bool { return $id === 10; }
function IPS_GetObject(int $id): array { return ['ParentID' => $GLOBALS['testParent'], 'ObjectIdent' => 'grid']; }
function IPS_VariableExists(int $id): bool { return in_array($id, [10, 11], true); }
function IPS_GetObject(int $id): array { return ['ParentID' => $GLOBALS['testParent'], 'ObjectIdent' => $id === 10 ? 'grid' : 'battery']; }
function IPS_GetInstanceListByModuleID(string $id): array { return [17004]; }
function IPS_GetProperty(int $id, string $key): mixed
{
@@ -93,15 +93,26 @@ foreach ($expected as $name => $call) {
check([$battery->properties, $battery->attributes, $battery->buffers] === $before,
'timer entrypoint does not change configuration, energy or buffers');
$config = ['batteryInstanceId' => 44234, 'managerId' => 17004,
'sources' => [['variableId' => 10, 'parentId' => 20, 'ident' => 'grid']]];
$config = ['version' => 1, 'installationId' => '11111111-2222-4333-8444-555555555555', 'assetId' => 'battery',
'batteryInstanceId' => 44234, 'managerId' => 17004, 'mode' => 'physical_sum', 'allowEstimatedForTrial' => false,
'maxSkewSeconds' => 30, 'maxAgeSeconds' => 60, 'idleToleranceW' => 0.0, 'trackingToleranceW' => 0.0,
'sources' => [
['key' => 'grid', 'role' => 'grid', 'variableId' => 10, 'parentId' => 20, 'ident' => 'grid', 'factorToW' => 1.0],
['key' => 'battery', 'role' => 'physical', 'variableId' => 11, 'parentId' => 20, 'ident' => 'battery', 'factorToW' => 1.0],
]];
$json = json_encode($config, JSON_THROW_ON_ERROR);
$battery->properties['NetzfahrplanV4RueckmeldungKonfiguration'] = $json;
$sample = ['kind' => 'local_physical_feedback', 'checkedAt' => time(),
'sourceOldestAt' => time() - 1, 'deviceReadConfirmed' => true, 'batteryW' => -123.0];
'sourceOldestAt' => time() - 1, 'deviceReadConfirmed' => true, 'batteryW' => -123.0,
'installationId' => $config['installationId'], 'assetId' => $config['assetId'],
'batteryInstanceId' => 44234, 'managerId' => 17004,
'configHash' => \Belevo\EnelixEMS\NetzfahrplanV4Rueckmeldung::fingerprint($config)];
$validBuffers = ['V4ConfirmedFeedback' => json_encode($sample, JSON_THROW_ON_ERROR),
'V4ConfirmedFeedbackConfig' => hash('sha256', $json),
'V4ConfirmedFeedbackMono' => (string) (hrtime(true) / 1e9)];
'V4ConfirmedFeedbackMono' => (string) (hrtime(true) / 1e9),
'V4ConfirmedFeedbackContext' => json_encode([
'configuration' => $json, 'propertyHash' => hash('sha256', $json), 'autoMode' => false,
], JSON_THROW_ON_ERROR)];
$battery->buffers = $validBuffers;
check($battery->GetV4BatterieRueckmeldungCache() === $validBuffers['V4ConfirmedFeedback'],
'cache-only API returns original confirmed sample and timestamps');