Files
Enelix-EMS/examples/V4DataCapture/install.php
T

90 lines
5.6 KiB
PHP

<?php
declare(strict_types=1);
require_once __DIR__ . '/runtime.php';
/** Creates ONLY dedicated capture objects. No module reload, device settings or archives. */
function v4captureEnsure(int $parent, string $ident, int $type, string $name, string $marker, array &$created): int
{
$existing = v4captureChild($parent, $ident);
if ($existing !== null) {
v4captureAssertObject($existing, $parent, $ident, $type, $marker);
return $existing;
}
$id = match ($type) { 0 => IPS_CreateCategory(), 2 => IPS_CreateVariable(3), 3 => IPS_CreateScript(0) };
if (!is_int($id) || $id <= 0) throw new RuntimeException('Cannot create capture object');
$created[] = $id;
if (!IPS_SetParent($id, $parent) || !IPS_SetIdent($id, $ident) || !IPS_SetName($id, $name) || !IPS_SetInfo($id, $marker)) {
throw new RuntimeException('Cannot label capture object');
}
return $id;
}
function v4captureScript(int $id, string $content, array $created): void
{
$current = IPS_GetScriptContent($id);
if ($current === $content) return;
if (!in_array($id, $created, true)) throw new RuntimeException('Existing capture script changed; not overwritten');
if (!IPS_SetScriptContent($id, $content) || IPS_GetScriptContent($id) !== $content) throw new RuntimeException('Cannot store capture script');
}
function v4captureInstall(string $stage): array
{
if (!function_exists('IPS_GetKernelVersion') || version_compare(IPS_GetKernelVersion(),'8.0','<')) {
throw new RuntimeException('Nur im IP-Symcon-Skripteditor der Testanlage ausfuehren.');
}
$c = v4captureConfig($stage); $marker = v4captureMarker($c);
if (!IPS_InstanceExists($c['managerId'])
|| IPS_GetInstance($c['managerId'])['ModuleInfo']['ModuleID'] !== '{6F771B18-59D4-4C8A-B951-3B2FE9F6A2C4}') {
throw new RuntimeException('Expected manager not found');
}
// Verify layout only; stale/missing sensor updates remain diagnostic raw data, not fake zeros.
foreach (array_merge($c['accounting']['sources'], $c['extraSources']) as $s) {
if (!IPS_VariableExists($s['variableId'])) throw new RuntimeException('Expected source missing: ' . $s['key']);
$o = IPS_GetObject($s['variableId']); $v = IPS_GetVariable($s['variableId']);
if ($o['ParentID'] !== $s['parentId'] || $o['ObjectIdent'] !== $s['ident'] || !in_array($v['VariableType'],[1,2],true)) {
throw new RuntimeException('Source identity changed: ' . $s['key']);
}
}
$data = $stage . '/data';
if (is_link($data) || !is_dir($data) || !is_writable($data)) throw new RuntimeException('Dedicated capture directory not writable');
$key = 'ENELIX.V4.CaptureInstall.' . $c['installationId'];
if (!IPS_SemaphoreEnter($key, 3000)) throw new RuntimeException('Capture installation busy');
$created = []; $script = null; $timerSet = false;
$report = ['startedAt' => gmdate('c'), 'scope' => 'passive_raw_capture_only', 'controlEnabled' => false,
'existingModulesChanged' => false, 'archivesChanged' => false, 'existingHistoriesChanged' => false];
try {
$category = v4captureEnsure(0,'ENELIX_V4_PASSIVE_CAPTURE',0,'V4 - separate Messaufnahme (keine Steuerung)',$marker,$created);
v4captureEnsure($category,'CaptureStatus',2,'Aufzeichnungsstatus (nur lesen)',$marker,$created);
$script = v4captureEnsure($category,'RawCapture',3,'Messwerte alle 30 Sekunden erfassen',$marker,$created);
$stop = v4captureEnsure($category,'StopCapture',3,'Nur diese Messaufnahme stoppen',$marker,$created);
$include = '<?php' . "\n" . 'require_once ' . var_export($stage . '/source/examples/V4DataCapture/runtime.php',true) . ';' . "\n";
v4captureScript($script, $include . 'v4captureRun(' . var_export($stage,true) . ', ' . $category . ');' . "\n", $created);
v4captureScript($stop, $include . 'v4captureStop(' . var_export($stage,true) . ', ' . $category . ');' . "\n", $created);
$first = v4captureRun($stage, $category);
if ($first['status'] !== 'recorded') throw new RuntimeException('Capture not stored: ' . ($first['reason'] ?? $first['status']));
// This new timer never invokes a manager, gateway, battery or Modbus function.
if (!IPS_SetScriptTimer($script, 30)) throw new RuntimeException('Cannot start dedicated capture timer');
$timerSet = true;
$report += ['status' => 'capture_installed', 'categoryId' => $category, 'scriptId' => $script,
'stopScriptId' => $stop, 'intervalSeconds' => 30, 'firstCapture' => $first,
'futureTimerExecutionVerified' => false];
echo "OK: Separate Rohdatenaufnahme eingerichtet, alle 30 Sekunden.\n";
echo 'Erste Aufnahme: ' . $first['capturedAt'] . '; Quellen: ' . $first['sourceCount'] . ".\n";
echo 'Bilanzqualitaet: ' . $first['accountingQuality'] . " (noch keine Trainings-/Stellfreigabe).\n";
echo "Bestehende Manager-, Batterie-, Archiv- und Pollingkonfiguration unveraendert.\n";
} catch (Throwable $e) {
$report['status'] = 'needs_review'; $report['reason'] = substr($e->getMessage(),0,300);
if ($timerSet && $script !== null) IPS_SetScriptTimer($script,0);
// Never delete unrelated objects or stored data during recovery.
echo 'FEHLER: ' . $report['reason'] . "\n";
} finally {
$report['createdObjects'] = $created; $report['finishedAt'] = gmdate('c');
try { v4captureAtomicJson($stage . '/INSTALL_RESULT.json', $report); }
finally { IPS_SemaphoreLeave($key); }
echo 'CAPTURE REPORT: ' . $stage . "/INSTALL_RESULT.json\n";
}
return $report;
}