nieuwe versie

This commit is contained in:
2025-10-09 16:15:21 +02:00
parent 9e544fcdc1
commit d090c8e645
9 changed files with 358 additions and 322 deletions

View File

@@ -1,14 +1,9 @@
<?php <?php
include '../../include/include_header.php';
include '../../include/include_functions.php';
$templatePath = __DIR__ . '/template.json.tpl'; $templatePath = __DIR__ . '/template.json.tpl';
$deployDir = __DIR__; $deployDir = __DIR__;
// --- Node-RED omgevingen ophalen --- include __DIR__ . '/../../include/include_header.php';
$envFile = __DIR__ . '/../../environments.json'; // Pas eventueel pad aan include __DIR__ . '/../../include/include_functions.php';
$environments = getNodeRedEnvironments($envFile);
$selectedEnv = $_POST['environment'] ?? '';
// --- Parameters ophalen of defaults --- // --- Parameters ophalen of defaults ---
$parameters = [ $parameters = [
@@ -18,68 +13,35 @@ $parameters = [
'param2' => $_POST['param2'] ?? '' 'param2' => $_POST['param2'] ?? ''
]; ];
// Node-RED omgevingen
$envFile = __DIR__ . '/../../settings/environments.json';
$environments = getNodeRedEnvironments($envFile);
$selectedEnv = $_POST['environment'] ?? '';
// Alert template-versie
$newVersionAlert = checkNewTemplateVersionAlert($templatePath, $deployDir);
// Overzicht deploys
$deploys = getDeploysWithVersions($deployDir);
$deployResponse = ''; $deployResponse = '';
$newFileName = ''; $newFileName = '';
$envUrl = ''; $envUrl = '';
$successMessage = '';
// Alert tonen als template versie hoger is dan laatste deploy // Deploy verwerken
$newVersionAlert = checkNewTemplateVersionAlert($templatePath, $deployDir); if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['deploy'])) {
$deployResult = deployFlow($parameters, $templatePath, $deployDir, $environments, $selectedEnv);
// Deploy knop verwerken if ($deployResult['success']) {
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['deploy']) && $selectedEnv) { $deployResponse = $deployResult['response'];
$templateVersion = getVersionFromTemplate($templatePath); $newFileName = $deployResult['file'];
$envUrl = $deployResult['envUrl'];
$placeholders = [ $successMessage = renderAlert($deployResult['message'], 'success');
'id' => $parameters['assetId'],
'name' => $parameters['assetName'],
'version' => $templateVersion,
'param1' => $parameters['param1'],
'param2' => $parameters['param2']
];
$flowJson = renderTemplate($templatePath, $placeholders);
$newFileName = generateNextDeployFileName($templateVersion);
file_put_contents($deployDir.'/'.$newFileName, $flowJson);
// Zoek de URL van de geselecteerde omgeving
foreach ($environments as $env) {
if (($env['ip'] ?? '') === $selectedEnv) {
$envUrl = $env['url'] ?? '';
break;
}
}
if ($envUrl) {
$deployResponse = deployFlowToUrl($deployDir.'/'.$newFileName, $envUrl);
} else { } else {
$deployResponse = 'Geselecteerde omgeving niet gevonden of URL ontbreekt!'; $successMessage = renderAlert($deployResult['message'], 'danger');
} }
} }
// Overzicht van deploys met versies
$deploys = getDeploysWithVersions($deployDir);
/**
* Deploy naar specifieke Node-RED URL
*/
function deployFlowToUrl(string $flowPath, string $url): string {
if (!file_exists($flowPath)) return "Flowbestand niet gevonden: $flowPath";
$flowJson = file_get_contents($flowPath);
$ch = curl_init(rtrim($url, '/') . '/flows'); // Zorg dat er geen dubbele slashes komen
curl_setopt_array($ch, [
CURLOPT_POST => true,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => ['Content-Type: application/json'],
CURLOPT_POSTFIELDS => $flowJson,
]);
$response = curl_exec($ch);
$error = curl_error($ch);
curl_close($ch);
return $error ?: $response;
}
?> ?>
<main class="container py-5"> <main class="container py-5">
@@ -88,22 +50,13 @@ function deployFlowToUrl(string $flowPath, string $url): string {
<h1 class="h3 text-dark">Pomp flow</h1> <h1 class="h3 text-dark">Pomp flow</h1>
</div> </div>
<!-- Alert nieuwe template-versie --> <?php if ($newVersionAlert) echo $newVersionAlert; ?>
<?php if ($newVersionAlert): ?> <?php if ($successMessage) echo $successMessage; ?>
<?= $newVersionAlert ?> <?php if ($deployResponse) echo "<pre class='bg-light border p-2 rounded small'>".htmlspecialchars($deployResponse)."</pre>"; ?>
<?php endif; ?>
<!-- Deploy response -->
<?php if ($deployResponse): ?>
<?= renderAlert("Nieuwe versie <strong>$newFileName</strong> gedeployed naar <strong>$envUrl</strong>!", 'success') ?>
<pre class="bg-light border p-2 rounded small"><?= htmlspecialchars($deployResponse) ?></pre>
<?php endif; ?>
<!-- Parameters form + deploy knop -->
<div class="card shadow-sm mb-4"> <div class="card shadow-sm mb-4">
<div class="card-body"> <div class="card-body">
<h5 class="card-title mb-3">Parameters voor deploy</h5> <h5 class="card-title mb-3">Parameters voor deploy</h5>
<form method="post"> <form method="post">
<div class="mb-3"> <div class="mb-3">
<label for="assetId" class="form-label">Asset ID</label> <label for="assetId" class="form-label">Asset ID</label>
@@ -129,15 +82,11 @@ function deployFlowToUrl(string $flowPath, string $url): string {
<label for="environment" class="form-label">Selecteer Node-RED omgeving</label> <label for="environment" class="form-label">Selecteer Node-RED omgeving</label>
<select class="form-select" id="environment" name="environment" required> <select class="form-select" id="environment" name="environment" required>
<option value="">-- Kies een omgeving --</option> <option value="">-- Kies een omgeving --</option>
<?php if (!empty($environments)): ?>
<?php foreach ($environments as $env): ?> <?php foreach ($environments as $env): ?>
<option value="<?= htmlspecialchars($env['ip'] ?? '') ?>" <?= $selectedEnv === ($env['ip'] ?? '') ? 'selected' : '' ?>> <option value="<?= htmlspecialchars($env['ip']) ?>" <?= $selectedEnv === $env['ip'] ? 'selected' : '' ?>>
<?= htmlspecialchars($env['name'] ?? 'Onbekend') ?> (<?= htmlspecialchars($env['ip'] ?? '') ?>) <?= htmlspecialchars($env['name'] ?? 'Onbekend') ?> (<?= htmlspecialchars($env['ip']) ?>)
</option> </option>
<?php endforeach; ?> <?php endforeach; ?>
<?php else: ?>
<option value="">Geen omgevingen gevonden</option>
<?php endif; ?>
</select> </select>
</div> </div>
@@ -146,7 +95,6 @@ function deployFlowToUrl(string $flowPath, string $url): string {
</div> </div>
</div> </div>
<!-- Overzicht deploys -->
<div class="card shadow-sm"> <div class="card shadow-sm">
<div class="card-body"> <div class="card-body">
<h5 class="card-title mb-3">Overzicht van deploys</h5> <h5 class="card-title mb-3">Overzicht van deploys</h5>
@@ -178,4 +126,5 @@ function deployFlowToUrl(string $flowPath, string $url): string {
<?php endif; ?> <?php endif; ?>
</div> </div>
</div> </div>
</main> </main>

View File

@@ -12,7 +12,8 @@
"payload": "{{id}}", "payload": "{{id}}",
"payloadType": "str", "payloadType": "str",
"wires": [["function1"]], "wires": [["function1"]],
"version": 9 "version": 1,
"url": "http://{{ip}}:3000/api/asset"
}, },
{ {
"id": "function1", "id": "function1",
@@ -35,7 +36,7 @@
"name": "Stuur naar API v{{version}}", "name": "Stuur naar API v{{version}}",
"method": "POST", "method": "POST",
"ret": "txt", "ret": "txt",
"url": "http://localhost:3000/api/asset", "url": "http://{{ip}}:3000/api/asset",
"tls": "", "tls": "",
"persist": false, "persist": false,
"proxy": "", "proxy": "",

View File

@@ -1,59 +0,0 @@
[
{
"id": "inject1",
"type": "inject",
"name": "Start 1234 v8",
"props": [ { "p": "payload" } ],
"repeat": "",
"crontab": "",
"once": false,
"onceDelay": 0.1,
"topic": "",
"payload": "123",
"payloadType": "str",
"wires": [["function1"]],
"version": 8
},
{
"id": "function1",
"type": "function",
"name": "Verwerk asset data v8",
"func": "msg.payload = { \"asset_id\": \"123\", \"asset_name\": \"1234\", \"version\": 8, \"timestamp\": Date.now() }; return msg;",
"outputs": 1,
"wires": [["change1","debug1","http1"]]
},
{
"id": "change1",
"type": "change",
"name": "Voeg status toe v8",
"rules": [ { "t": "set", "p": "payload.status", "pt": "msg", "to": "active", "tot": "str" } ],
"wires": [["debug1"]]
},
{
"id": "http1",
"type": "http request",
"name": "Stuur naar API v8",
"method": "POST",
"ret": "txt",
"url": "http://localhost:3000/api/asset",
"tls": "",
"persist": false,
"proxy": "",
"authType": "",
"wires": [["debug1"]]
},
{
"id": "debug1",
"type": "debug",
"name": "Output debug v8",
"active": true,
"tosidebar": true,
"console": false,
"tostatus": false,
"complete": "payload",
"targetType": "msg",
"statusVal": "",
"statusType": "auto",
"wires": []
}
]

View File

@@ -1,30 +1,38 @@
<?php <?php
/** /**
* FlowManager helper functies * FlowManager Helper Functions
*
* Bevat functies en standaardinstellingen voor het beheren van Node-RED flows.
* Inclusief:
* - Deploy van flows
* - Versiebeheer
* - Template rendering
* - Omgevingen ophalen
*/ */
// Deploy een JSON-flow naar Node-RED // ------------------------------------------------------
function deployFlow(string $flowPath): string { // *** DEFAULT SETTINGS FLOW ***
if (!file_exists($flowPath)) return "Flowbestand niet gevonden: $flowPath"; // ------------------------------------------------------
$flowJson = file_get_contents($flowPath); /**
$url = "http://localhost:1880/flows"; * Verkrijg een overzicht van alle Node-RED omgevingen
*
$ch = curl_init($url); * @param string $envFile Pad naar JSON-bestand met omgevingen
curl_setopt_array($ch, [ * @return array
CURLOPT_POST => true, */
CURLOPT_RETURNTRANSFER => true, function getNodeRedEnvironments(string $envFile): array {
CURLOPT_HTTPHEADER => ['Content-Type: application/json'], $json = @file_get_contents($envFile);
CURLOPT_POSTFIELDS => $flowJson, if (!$json) return [];
]); $data = json_decode($json, true);
$response = curl_exec($ch); return is_array($data) ? $data : [];
$error = curl_error($ch);
curl_close($ch);
return $error ?: $response;
} }
// Haal alle versie-bestanden op in een map /**
* Vind alle versioned JSON-bestanden in een directory
*
* @param string $dir
* @return array
*/
function findVersionedJsonFilesInDir(string $dir): array { function findVersionedJsonFilesInDir(string $dir): array {
$matches = []; $matches = [];
foreach (scandir($dir) as $file) { foreach (scandir($dir) as $file) {
@@ -36,27 +44,48 @@ function findVersionedJsonFilesInDir(string $dir): array {
return $matches; return $matches;
} }
// Vind het laatst gedeployde bestand /**
* Vind het laatst gedeployde bestand
*
* @param string $dir
* @return string|null
*/
function findLatestDeployFile(string $dir): ?string { function findLatestDeployFile(string $dir): ?string {
$files = findVersionedJsonFilesInDir($dir); $files = findVersionedJsonFilesInDir($dir);
return !empty($files) ? end($files)['name'] : null; return !empty($files) ? end($files)['name'] : null;
} }
// Haal versie uit een JSON-bestand /**
* Haal versie uit een JSON-bestand
*
* @param string $filePath
* @return int
*/
function getVersionFromJson(string $filePath): int { function getVersionFromJson(string $filePath): int {
if (!file_exists($filePath)) return 0; if (!file_exists($filePath)) return 0;
$json = json_decode(file_get_contents($filePath), true); $json = json_decode(file_get_contents($filePath), true);
return $json[0]['version'] ?? 0; return $json[0]['version'] ?? 0;
} }
// Haal versie uit een template /**
* Haal versie uit een template
*
* @param string $templatePath
* @return int
*/
function getVersionFromTemplate(string $templatePath): int { function getVersionFromTemplate(string $templatePath): int {
if (!file_exists($templatePath)) return 0; if (!file_exists($templatePath)) return 0;
preg_match('/"version"\s*:\s*(\d+)/', file_get_contents($templatePath), $m); preg_match('/"version"\s*:\s*(\d+)/', file_get_contents($templatePath), $m);
return $m[1] ?? 0; return $m[1] ?? 0;
} }
// Controleer of de template een hogere versie heeft dan de laatste deploy /**
* Controleer of de template een hogere versie heeft dan de laatste deploy
*
* @param string $templatePath
* @param string $deployDir
* @return string|null
*/
function checkNewTemplateVersionAlert(string $templatePath, string $deployDir): ?string { function checkNewTemplateVersionAlert(string $templatePath, string $deployDir): ?string {
$templateVersion = getVersionFromTemplate($templatePath); $templateVersion = getVersionFromTemplate($templatePath);
$latestDeployFile = findLatestDeployFile($deployDir); $latestDeployFile = findLatestDeployFile($deployDir);
@@ -71,12 +100,23 @@ function checkNewTemplateVersionAlert(string $templatePath, string $deployDir):
return null; return null;
} }
// Genereer de bestandsnaam voor een nieuwe deploy /**
* Genereer de bestandsnaam voor een nieuwe deploy
*
* @param int $version
* @return string
*/
function generateNextDeployFileName(int $version): string { function generateNextDeployFileName(int $version): string {
return "version{$version}_".date('YmdHi').".json"; return "version{$version}_".date('YmdHi').".json";
} }
// Template renderen met placeholders /**
* Render een template met placeholders
*
* @param string $templatePath
* @param array $placeholders
* @return string
*/
function renderTemplate(string $templatePath, array $placeholders): string { function renderTemplate(string $templatePath, array $placeholders): string {
$content = file_get_contents($templatePath); $content = file_get_contents($templatePath);
foreach ($placeholders as $key => $value) { foreach ($placeholders as $key => $value) {
@@ -85,12 +125,23 @@ function renderTemplate(string $templatePath, array $placeholders): string {
return $content; return $content;
} }
// Render een standaard alert /**
* Render een standaard alert
*
* @param string $message
* @param string $type
* @return string
*/
function renderAlert(string $message, string $type = 'info'): string { function renderAlert(string $message, string $type = 'info'): string {
return "<div class='alert alert-{$type}'>$message</div>"; return "<div class='alert alert-{$type}'>$message</div>";
} }
// Verkrijg een overzicht van alle deploys inclusief versies /**
* Verkrijg een overzicht van alle deploys inclusief versies
*
* @param string $dir
* @return array
*/
function getDeploysWithVersions(string $dir): array { function getDeploysWithVersions(string $dir): array {
$files = findVersionedJsonFilesInDir($dir); $files = findVersionedJsonFilesInDir($dir);
return array_map(function($f) use ($dir) { return array_map(function($f) use ($dir) {
@@ -101,10 +152,106 @@ function getDeploysWithVersions(string $dir): array {
}, array_reverse($files)); }, array_reverse($files));
} }
function getNodeRedEnvironments(string $envFile = '/environments.json'): array { // ------------------------------------------------------
$json = @file_get_contents($envFile); // @ om warnings te onderdrukken // *** DEPLOY FUNCTIES ***
if (!$json) return []; // ------------------------------------------------------
$data = json_decode($json, true);
return is_array($data) ? $data : []; /**
* Deploy een JSON-flowbestand naar een Node-RED URL via POST
*
* @param string $flowPath Pad naar flow JSON
* @param string $url Node-RED URL
* @return string HTTP status code of foutmelding
*/
function deployFlowToUrl(string $flowPath, string $url): string {
if (!file_exists($flowPath)) {
return '<div class="alert alert-danger" role="alert">
<strong>Fout:</strong> Flowbestand niet gevonden: ' . htmlspecialchars($flowPath) . '
</div>';
} }
$flowJson = file_get_contents($flowPath);
$ch = curl_init(rtrim($url, '/') . '/flows');
curl_setopt_array($ch, [
CURLOPT_POST => true,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => ['Content-Type: application/json'],
CURLOPT_POSTFIELDS => $flowJson,
]);
$response = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
return $httpCode;
}
/**
* Deploy een flow naar een geselecteerde Node-RED omgeving
*
* @param array $parameters Asset parameters
* @param string $templatePath Pad naar template JSON
* @param string $deployDir Deploy directory
* @param array $environments Beschikbare Node-RED omgevingen
* @param string $selectedEnv Geselecteerde omgeving (IP)
* @return array Resultaat van de deploy
*/
function deployFlow(array $parameters, string $templatePath, string $deployDir, array $environments, string $selectedEnv): array {
$result = [
'success' => false,
'message' => '',
'file' => null,
'envUrl' => null,
'response' => null
];
if (empty($selectedEnv)) {
$result['message'] = 'Geen omgeving geselecteerd!';
return $result;
}
// Template-versie ophalen
$templateVersion = getVersionFromTemplate($templatePath);
// URL van geselecteerde omgeving
$envUrl = '';
foreach ($environments as $env) {
if (($env['ip'] ?? '') === $selectedEnv) {
$envUrl = $env['ip'];
break;
}
}
if (!$envUrl) {
$result['message'] = 'Omgeving niet gevonden of URL ontbreekt!';
return $result;
}
// Placeholders invullen
$placeholders = [
'id' => $parameters['assetId'] ?? '',
'name' => $parameters['assetName'] ?? '',
'version' => $templateVersion,
'param1' => $parameters['param1'] ?? '',
'param2' => $parameters['param2'] ?? '',
'ip' => $envUrl
];
// Template renderen en deploy-bestand schrijven
$flowJson = renderTemplate($templatePath, $placeholders);
$newFileName = generateNextDeployFileName($templateVersion);
$deployFile = $deployDir . '/' . $newFileName;
file_put_contents($deployFile, $flowJson);
// Deploy naar Node-RED uitvoeren
$deployResponse = deployFlowToUrl($deployFile, $envUrl);
$result['success'] = true;
$result['message'] = "Nieuwe versie <strong>$newFileName</strong> gedeployed naar <strong>$envUrl</strong>!";
$result['file'] = $newFileName;
$result['envUrl'] = $envUrl;
$result['response'] = $deployResponse;
return $result;
}

View File

@@ -1,5 +1,5 @@
<?php <?php
$base_url = 'http://localhost:8888/rdlab/flowmanager_app/v1.0'; $base_url = 'http://localhost:63342/flowmanager';
?> ?>
@@ -34,7 +34,7 @@
<div class="collapse navbar-collapse" id="navbarMenu"> <div class="collapse navbar-collapse" id="navbarMenu">
<ul class="navbar-nav ms-auto"> <ul class="navbar-nav ms-auto">
<li class="nav-item"> <li class="nav-item">
<a class="nav-link" href="<?php echo $base_url ?>/settings.php"> <a class="nav-link" href="/settings">
<i class="bi bi-gear-fill"></i> Instellingen <i class="bi bi-gear-fill"></i> Instellingen
</a> </a>
</li> </li>

View File

@@ -2,8 +2,6 @@
include 'include/include_header.php'; include 'include/include_header.php';
?> ?>
To-do: zorgen dat je juiste flow naar de juiste omgeving gaat
<div class="container my-5"> <div class="container my-5">
<div class="row row-cols-1 row-cols-md-3 g-4"> <div class="row row-cols-1 row-cols-md-3 g-4">

View File

@@ -1,6 +1,6 @@
[ [
{ {
"name": "localhost", "name": "localhost",
"ip": "127.0.0.1" "ip": "127.0.0.1:1880"
} }
] ]

View File

@@ -1,5 +1,5 @@
<?php <?php
include 'include/include_header.php'; include '../include/include_header.php';
// Laad opgeslagen omgevingen (optioneel uit een JSON-bestand) // Laad opgeslagen omgevingen (optioneel uit een JSON-bestand)
$env_file = 'environments.json'; $env_file = 'environments.json';