feat(config): externalize runtime paths and script settings for local setup
This commit is contained in:
parent
2a12f5aaa5
commit
16bcf7f06d
@ -14,17 +14,34 @@ Application settings are loaded from classpath properties files in `src/main/res
|
||||
| `mqtt.topic` | MQTT topic to subscribe to | `PREDICTION` |
|
||||
| `mqtt_sim.enabled` | Enables simulator startup | `false` |
|
||||
| `mqtt_sim.script` | Simulator script path | `src/main/resources/scripts/mqtt_simulator.py` |
|
||||
| `mqtt_sim.broker` | Simulator broker override (env passthrough) | `localhost` |
|
||||
| `mqtt_sim.port` | Simulator broker port override | `1883` |
|
||||
| `mqtt_sim.topic` | Simulator publish topic override | `PREDICTION` |
|
||||
| `mqtt_sim.qos` | Simulator QoS override | `0` |
|
||||
| `mqtt_sim.interval_seconds` | Simulator publish interval override | `5` |
|
||||
| `mqtt_sim.username` | Optional simulator auth username | empty |
|
||||
| `mqtt_sim.password` | Optional simulator auth password | empty |
|
||||
| `mqtt_sim.start_id` | Optional simulator initial payload id | `1` |
|
||||
| `mqtt_sim.client_id` | Optional simulator MQTT client id | `mqtt-simulator` |
|
||||
| `mqtt_sim.log_file` | Optional simulator log file path | `logs/mqtt_simulator.log` |
|
||||
| `animation.output.path` | Generated animation state file path | `data/animation.json` |
|
||||
| `unreal.enabled` | Enables Unreal startup flow | `true` |
|
||||
| `unreal.executable` | PowerShell script to start Unreal process | absolute path |
|
||||
| `unreal.signalling_server.script` | Signalling server BAT file path | absolute path |
|
||||
| `unreal.pid.file` | Unreal PID file for shutdown cleanup | absolute path |
|
||||
| `unreal.signalling.pid.file` | Signalling PID file for shutdown cleanup | absolute path |
|
||||
| `unreal.pid.dir` | Script-side PID directory override | absolute path |
|
||||
| `unreal.target.executable` | Script-side Unreal executable override | absolute path |
|
||||
| `unreal.target.args` | Script-side Unreal argument string override | command string |
|
||||
| `unreal.target.working_dir` | Script-side Unreal working dir override | absolute path |
|
||||
| `unreal.startup.delay.seconds` | Script-side signalling warmup delay override | `5` |
|
||||
|
||||
Notes:
|
||||
|
||||
- Paths can be provided with or without wrapping quotes; startup sanitizes surrounding quotes.
|
||||
- Unreal-related defaults are environment-specific and should be replaced per machine.
|
||||
- `mqtt_sim.*` overrides are forwarded as environment variables to `mqtt_simulator.py`.
|
||||
- `unreal.target.*` and `unreal.pid.dir` are forwarded as environment variables to `start_avatar.ps1`.
|
||||
|
||||
## `logger.properties`
|
||||
|
||||
@ -39,3 +56,27 @@ Notes:
|
||||
|
||||
- `src/main/resources/scripts/mqtt_simulator.py`
|
||||
- `src/main/resources/scripts/start_avatar.ps1`
|
||||
|
||||
## Script Runtime Inputs
|
||||
|
||||
`mqtt_simulator.py` supports CLI options and equivalent env vars:
|
||||
|
||||
- `--broker` / `MQTT_SIM_BROKER`
|
||||
- `--port` / `MQTT_SIM_PORT`
|
||||
- `--topic` / `MQTT_SIM_TOPIC`
|
||||
- `--username` / `MQTT_SIM_USERNAME`
|
||||
- `--password` / `MQTT_SIM_PASSWORD`
|
||||
- `--qos` / `MQTT_SIM_QOS`
|
||||
- `--interval-seconds` / `MQTT_SIM_INTERVAL_SECONDS`
|
||||
- `--start-id` / `MQTT_SIM_START_ID`
|
||||
- `--client-id` / `MQTT_SIM_CLIENT_ID`
|
||||
- `--log-file` / `MQTT_SIM_LOG_FILE`
|
||||
|
||||
`start_avatar.ps1` supports parameters and equivalent env vars:
|
||||
|
||||
- `-PidDir` / `VGA_PID_DIR`
|
||||
- `-UeExe` / `VGA_UE_EXE`
|
||||
- `-UeArgs` / `VGA_UE_ARGS`
|
||||
- `-SignallingBat` / `VGA_SIGNALLING_BAT`
|
||||
- `-UeWorkingDir` / `VGA_UE_WORKDIR`
|
||||
- `-SignallingStartupDelaySeconds` / `VGA_SIGNALLING_DELAY`
|
||||
|
||||
@ -85,12 +85,14 @@ Main config: `src/main/resources/config/application.properties`
|
||||
- `mqtt.topic`: subscribed topic (default `PREDICTION`)
|
||||
- `mqtt_sim.enabled`: start simulator process on app startup
|
||||
- `mqtt_sim.script`: simulator script path
|
||||
- `mqtt_sim.broker` / `mqtt_sim.port` / `mqtt_sim.topic`: simulator runtime overrides
|
||||
- `animation.output.path`: path for generated animation JSON file
|
||||
- `unreal.enabled`: start Unreal-related processes
|
||||
- `unreal.executable`: PowerShell script path for Unreal start
|
||||
- `unreal.signalling_server.script`: signalling server batch path
|
||||
- `unreal.pid.file`: PID file used for Unreal shutdown cleanup
|
||||
- `unreal.signalling.pid.file`: PID file used for signalling shutdown cleanup
|
||||
- `unreal.target.executable` / `unreal.target.args` / `unreal.target.working_dir`: optional overrides passed into `start_avatar.ps1`
|
||||
|
||||
Logger config: `src/main/resources/config/logger.properties`
|
||||
|
||||
@ -161,5 +163,6 @@ src/main/resources
|
||||
- Animation output path is now config-driven (`animation.output.path`).
|
||||
- MQTT broker URL/client id are config-driven (`mqtt.broker.url`, `mqtt.client.id`).
|
||||
- Unreal PID cleanup paths are config-driven (`unreal.pid.file`, `unreal.signalling.pid.file`).
|
||||
- Script runtime values can be passed from config into `mqtt_simulator.py` and `start_avatar.ps1`.
|
||||
- On app shutdown, `data/health.db` is deleted by `App.deleteDatabase()`.
|
||||
- The signalling server process startup in `ProcessManagerService` is prepared but currently not launched (`pb.start()` commented).
|
||||
|
||||
@ -104,6 +104,7 @@ public class ProcessManagerService {
|
||||
|
||||
ProcessBuilder pb = new ProcessBuilder(python, script);
|
||||
pb.redirectErrorStream(true);
|
||||
configureMqttSimulatorEnvironment(pb);
|
||||
|
||||
pythonProcess = processLauncher.launch(pb);
|
||||
|
||||
@ -176,6 +177,8 @@ public class ProcessManagerService {
|
||||
unrealPsScript
|
||||
);
|
||||
|
||||
configureUnrealScriptEnvironment(pb);
|
||||
|
||||
unrealProcess = processLauncher.launch(pb);
|
||||
|
||||
//pb.directory(new File(exe).getParentFile());
|
||||
@ -311,4 +314,69 @@ public class ProcessManagerService {
|
||||
|
||||
return trimmed;
|
||||
}
|
||||
|
||||
/**
|
||||
* Passes optional simulator settings from app config to the Python process environment.
|
||||
*
|
||||
* @param processBuilder simulator process builder
|
||||
*/
|
||||
private void configureMqttSimulatorEnvironment(ProcessBuilder processBuilder) {
|
||||
putEnvFromConfig(processBuilder, "mqtt_sim.broker", "MQTT_SIM_BROKER");
|
||||
putEnvFromConfig(processBuilder, "mqtt_sim.port", "MQTT_SIM_PORT");
|
||||
putEnvFromConfig(processBuilder, "mqtt_sim.topic", "MQTT_SIM_TOPIC");
|
||||
putEnvFromConfig(processBuilder, "mqtt_sim.username", "MQTT_SIM_USERNAME");
|
||||
putEnvFromConfig(processBuilder, "mqtt_sim.password", "MQTT_SIM_PASSWORD");
|
||||
putEnvFromConfig(processBuilder, "mqtt_sim.qos", "MQTT_SIM_QOS");
|
||||
putEnvFromConfig(processBuilder, "mqtt_sim.interval_seconds", "MQTT_SIM_INTERVAL_SECONDS");
|
||||
putEnvFromConfig(processBuilder, "mqtt_sim.start_id", "MQTT_SIM_START_ID");
|
||||
putEnvFromConfig(processBuilder, "mqtt_sim.client_id", "MQTT_SIM_CLIENT_ID");
|
||||
putEnvFromConfig(processBuilder, "mqtt_sim.log_file", "MQTT_SIM_LOG_FILE");
|
||||
}
|
||||
|
||||
/**
|
||||
* Passes optional Unreal launcher settings from app config to the PowerShell process environment.
|
||||
*
|
||||
* @param processBuilder Unreal process builder
|
||||
*/
|
||||
private void configureUnrealScriptEnvironment(ProcessBuilder processBuilder) {
|
||||
putEnvFromConfig(processBuilder, "unreal.target.executable", "VGA_UE_EXE");
|
||||
putEnvFromConfig(processBuilder, "unreal.target.args", "VGA_UE_ARGS");
|
||||
putEnvFromConfig(processBuilder, "unreal.target.working_dir", "VGA_UE_WORKDIR");
|
||||
putEnvFromConfig(processBuilder, "unreal.signalling_server.script", "VGA_SIGNALLING_BAT");
|
||||
putEnvFromConfig(processBuilder, "unreal.startup.delay.seconds", "VGA_SIGNALLING_DELAY");
|
||||
|
||||
String pidDir = cleanConfigValue(config.getProperty("unreal.pid.dir"));
|
||||
if (pidDir == null || pidDir.isBlank()) {
|
||||
try {
|
||||
Path parent = Path.of(unrealPidFile).getParent();
|
||||
if (parent != null) {
|
||||
pidDir = parent.toString();
|
||||
}
|
||||
} catch (Exception ignored) {
|
||||
pidDir = null;
|
||||
}
|
||||
}
|
||||
|
||||
if (pidDir != null && !pidDir.isBlank()) {
|
||||
processBuilder.environment().put("VGA_PID_DIR", pidDir);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a config value to process environment when present.
|
||||
*
|
||||
* @param processBuilder target process builder
|
||||
* @param configKey application properties key
|
||||
* @param envName environment variable name
|
||||
*/
|
||||
private void putEnvFromConfig(
|
||||
ProcessBuilder processBuilder,
|
||||
String configKey,
|
||||
String envName
|
||||
) {
|
||||
String value = cleanConfigValue(config.getProperty(configKey));
|
||||
if (value != null && !value.isBlank()) {
|
||||
processBuilder.environment().put(envName, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -15,6 +15,16 @@ mqtt.topic=PREDICTION
|
||||
# ===== MQTT SIMULATOR =====
|
||||
mqtt_sim.enabled=false
|
||||
mqtt_sim.script=src/main/resources/scripts/mqtt_simulator.py
|
||||
mqtt_sim.broker=localhost
|
||||
mqtt_sim.port=1883
|
||||
mqtt_sim.topic=PREDICTION
|
||||
mqtt_sim.qos=0
|
||||
mqtt_sim.interval_seconds=5
|
||||
# mqtt_sim.username=
|
||||
# mqtt_sim.password=
|
||||
# mqtt_sim.start_id=1
|
||||
# mqtt_sim.client_id=mqtt-simulator
|
||||
# mqtt_sim.log_file=logs/mqtt_simulator.log
|
||||
|
||||
# ===== ANIMATION =====
|
||||
animation.output.path=data/animation.json
|
||||
@ -25,3 +35,8 @@ unreal.executable=C:\\Users\\Student\\Documents\\Dannick\\avatar\\start_avatar.p
|
||||
unreal.signalling_server.script=C:\\Users\\Student\\Documents\\Dannick\\avatar\\Windows\\Prototyp1\\Samples\\PixelStreaming\\WebServers\\SignallingWebServer\\platform_scripts\\cmd\\start_with_stun.bat
|
||||
unreal.pid.file=C:\\Users\\Student\\Documents\\Dannick\\avatar\\unreal.pid
|
||||
unreal.signalling.pid.file=C:\\Users\\Student\\Documents\\Dannick\\avatar\\signalling.pid
|
||||
# unreal.pid.dir=C:\\Users\\Student\\Documents\\Dannick\\avatar
|
||||
# unreal.target.executable=C:\\Users\\Student\\Documents\\Dannick\\avatar\\Windows\\Prototyp1.exe
|
||||
# unreal.target.args=-PixelStreamingURL=ws://127.0.0.1 -RenderOffscreen -PixelStreamingWebRTCDisableTransmitAudio
|
||||
# unreal.target.working_dir=C:\\Users\\Student\\Documents\\Dannick\\avatar\\Windows
|
||||
# unreal.startup.delay.seconds=5
|
||||
|
||||
@ -1,85 +1,151 @@
|
||||
import argparse
|
||||
import json
|
||||
import logging
|
||||
import os
|
||||
import random
|
||||
import sys
|
||||
import time
|
||||
|
||||
import paho.mqtt.client as mqtt
|
||||
import sys
|
||||
import random
|
||||
import time
|
||||
import logging
|
||||
|
||||
# ===== KONFIGURATION =====
|
||||
BROKER = "141.75.223.13"
|
||||
PORT = 1883
|
||||
TOPIC = "PREDICTION"
|
||||
USERNAME = None
|
||||
PASSWORD = None
|
||||
QOS = 0
|
||||
INTERVAL_SECONDS = 5
|
||||
# ==========================
|
||||
|
||||
# Logging konfigurieren (Console + Datei)
|
||||
logging.basicConfig(
|
||||
DEFAULT_BROKER = "141.75.223.13"
|
||||
DEFAULT_PORT = 1883
|
||||
DEFAULT_TOPIC = "PREDICTION"
|
||||
DEFAULT_QOS = 0
|
||||
DEFAULT_INTERVAL_SECONDS = 5.0
|
||||
DEFAULT_START_ID = 1
|
||||
DEFAULT_CLIENT_ID = "mqtt-simulator"
|
||||
DEFAULT_LOG_FILE = "logs/mqtt_simulator.log"
|
||||
|
||||
|
||||
def env_int(name, default):
|
||||
value = os.getenv(name)
|
||||
if value is None or value.strip() == "":
|
||||
return default
|
||||
|
||||
try:
|
||||
return int(value)
|
||||
except ValueError:
|
||||
return default
|
||||
|
||||
|
||||
def env_float(name, default):
|
||||
value = os.getenv(name)
|
||||
if value is None or value.strip() == "":
|
||||
return default
|
||||
|
||||
try:
|
||||
return float(value)
|
||||
except ValueError:
|
||||
return default
|
||||
|
||||
|
||||
def build_args():
|
||||
parser = argparse.ArgumentParser(
|
||||
description="MQTT simulator for binary prediction events."
|
||||
)
|
||||
|
||||
parser.add_argument("--broker", default=os.getenv("MQTT_SIM_BROKER", DEFAULT_BROKER))
|
||||
parser.add_argument("--port", type=int, default=env_int("MQTT_SIM_PORT", DEFAULT_PORT))
|
||||
parser.add_argument("--topic", default=os.getenv("MQTT_SIM_TOPIC", DEFAULT_TOPIC))
|
||||
parser.add_argument("--username", default=os.getenv("MQTT_SIM_USERNAME"))
|
||||
parser.add_argument("--password", default=os.getenv("MQTT_SIM_PASSWORD"))
|
||||
parser.add_argument("--qos", type=int, choices=[0, 1, 2], default=env_int("MQTT_SIM_QOS", DEFAULT_QOS))
|
||||
parser.add_argument(
|
||||
"--interval-seconds",
|
||||
type=float,
|
||||
default=env_float("MQTT_SIM_INTERVAL_SECONDS", DEFAULT_INTERVAL_SECONDS),
|
||||
)
|
||||
parser.add_argument("--start-id", type=int, default=env_int("MQTT_SIM_START_ID", DEFAULT_START_ID))
|
||||
parser.add_argument("--client-id", default=os.getenv("MQTT_SIM_CLIENT_ID", DEFAULT_CLIENT_ID))
|
||||
parser.add_argument("--log-file", default=os.getenv("MQTT_SIM_LOG_FILE", DEFAULT_LOG_FILE))
|
||||
|
||||
return parser.parse_args()
|
||||
|
||||
|
||||
def configure_logging(log_file):
|
||||
log_dir = os.path.dirname(log_file)
|
||||
if log_dir:
|
||||
os.makedirs(log_dir, exist_ok=True)
|
||||
|
||||
logging.basicConfig(
|
||||
level=logging.INFO,
|
||||
format="%(asctime)s - %(levelname)s - %(message)s",
|
||||
handlers=[
|
||||
logging.FileHandler("logs/mqtt_simulator.log"),
|
||||
logging.StreamHandler(sys.stdout)
|
||||
]
|
||||
)
|
||||
logging.FileHandler(log_file),
|
||||
logging.StreamHandler(sys.stdout),
|
||||
],
|
||||
force=True,
|
||||
)
|
||||
|
||||
|
||||
def on_connect(client, userdata, flags, rc):
|
||||
if rc == 0:
|
||||
logging.info("Erfolgreich mit Broker verbunden")
|
||||
else:
|
||||
logging.error(f"Verbindung fehlgeschlagen mit Code {rc}")
|
||||
logging.error("Verbindung fehlgeschlagen mit Code %s", rc)
|
||||
|
||||
|
||||
def main():
|
||||
args = build_args()
|
||||
configure_logging(args.log_file)
|
||||
|
||||
logging.info("Python script gestartet")
|
||||
logging.info(
|
||||
"Konfiguration: broker=%s port=%s topic=%s qos=%s interval=%s",
|
||||
args.broker,
|
||||
args.port,
|
||||
args.topic,
|
||||
args.qos,
|
||||
args.interval_seconds,
|
||||
)
|
||||
|
||||
client = mqtt.Client()
|
||||
client = mqtt.Client(client_id=args.client_id)
|
||||
|
||||
if USERNAME and PASSWORD:
|
||||
client.username_pw_set(USERNAME, PASSWORD)
|
||||
if args.username:
|
||||
client.username_pw_set(args.username, args.password)
|
||||
|
||||
client.on_connect = on_connect
|
||||
|
||||
try:
|
||||
logging.info(f"Verbinde mit Broker {BROKER}:{PORT}")
|
||||
client.connect(BROKER, PORT, 60)
|
||||
logging.info("Verbinde mit Broker %s:%s", args.broker, args.port)
|
||||
client.connect(args.broker, args.port, 60)
|
||||
client.loop_start()
|
||||
|
||||
logging.info("Starte kontinuierliches Senden...")
|
||||
|
||||
current_id = 1
|
||||
current_id = args.start_id
|
||||
|
||||
while True:
|
||||
payload = {
|
||||
"valid": True,
|
||||
"_id": current_id,
|
||||
"prediction": random.randint(0, 1)
|
||||
"prediction": random.randint(0, 1),
|
||||
}
|
||||
|
||||
json_payload = json.dumps(payload)
|
||||
|
||||
client.publish(TOPIC, json_payload, qos=QOS)
|
||||
logging.info(f"Gesendet an '{TOPIC}': {json_payload}")
|
||||
client.publish(args.topic, json_payload, qos=args.qos)
|
||||
logging.info("Gesendet an '%s': %s", args.topic, json_payload)
|
||||
|
||||
current_id += 1
|
||||
|
||||
time.sleep(INTERVAL_SECONDS)
|
||||
time.sleep(args.interval_seconds)
|
||||
|
||||
except KeyboardInterrupt:
|
||||
logging.info("Publisher manuell beendet")
|
||||
|
||||
client.loop_stop()
|
||||
client.disconnect()
|
||||
sys.exit(0)
|
||||
|
||||
except Exception as e:
|
||||
except Exception:
|
||||
logging.exception("Unerwarteter Fehler")
|
||||
sys.exit(1)
|
||||
|
||||
finally:
|
||||
try:
|
||||
client.loop_stop()
|
||||
client.disconnect()
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
@ -1,22 +1,64 @@
|
||||
$pidDir = "C:\Users\Student\Documents\Dannick\avatar"
|
||||
param(
|
||||
[string]$PidDir = $env:VGA_PID_DIR,
|
||||
[string]$UeExe = $env:VGA_UE_EXE,
|
||||
[string]$UeArgs = $env:VGA_UE_ARGS,
|
||||
[string]$SignallingBat = $env:VGA_SIGNALLING_BAT,
|
||||
[string]$UeWorkingDir = $env:VGA_UE_WORKDIR,
|
||||
[int]$SignallingStartupDelaySeconds = $(if ($env:VGA_SIGNALLING_DELAY) { [int]$env:VGA_SIGNALLING_DELAY } else { 5 }),
|
||||
[switch]$ShowSignallingWindow
|
||||
)
|
||||
|
||||
$ueExe = "C:\Users\Student\Documents\Dannick\avatar\Windows\Prototyp1.exe"
|
||||
$ueArgs = "-PixelStreamingURL=ws://127.0.0.1 -RenderOffscreen -PixelStreamingWebRTCDisableTransmitAudio"
|
||||
if (-not $PidDir) {
|
||||
$PidDir = "C:\Users\Student\Documents\Dannick\avatar"
|
||||
}
|
||||
|
||||
$signallingBat = "C:\Users\Student\Documents\Dannick\avatar\Windows\Prototyp1\Samples\PixelStreaming\WebServers\SignallingWebServer\platform_scripts\cmd\start_with_stun.bat"
|
||||
if (-not $UeExe) {
|
||||
$UeExe = "C:\Users\Student\Documents\Dannick\avatar\Windows\Prototyp1.exe"
|
||||
}
|
||||
|
||||
$ueWorkingDir = "C:\Users\Student\Documents\Dannick\avatar\Windows"
|
||||
if (-not $UeArgs) {
|
||||
$UeArgs = "-PixelStreamingURL=ws://127.0.0.1 -RenderOffscreen -PixelStreamingWebRTCDisableTransmitAudio"
|
||||
}
|
||||
|
||||
$signalling = Start-Process -FilePath $signallingBat -PassThru -WindowStyle Hidden
|
||||
if (-not $SignallingBat) {
|
||||
$SignallingBat = "C:\Users\Student\Documents\Dannick\avatar\Windows\Prototyp1\Samples\PixelStreaming\WebServers\SignallingWebServer\platform_scripts\cmd\start_with_stun.bat"
|
||||
}
|
||||
|
||||
Start-Sleep -Seconds 5
|
||||
if (-not $UeWorkingDir) {
|
||||
$UeWorkingDir = Split-Path -Path $UeExe -Parent
|
||||
}
|
||||
|
||||
$ue = Start-Process `
|
||||
-FilePath $ueExe `
|
||||
-ArgumentList $ueArgs `
|
||||
-WorkingDirectory $ueWorkingDir `
|
||||
-PassThru
|
||||
if (-not (Test-Path -LiteralPath $SignallingBat)) {
|
||||
throw "Signalling script not found: $SignallingBat"
|
||||
}
|
||||
|
||||
$ue.Id | Out-File "$pidDir\unreal.pid" -Encoding ascii
|
||||
$signalling.Id | Out-File "$pidDir\signalling.pid" -Encoding ascii
|
||||
if (-not (Test-Path -LiteralPath $UeExe)) {
|
||||
throw "Unreal executable not found: $UeExe"
|
||||
}
|
||||
|
||||
if (-not (Test-Path -LiteralPath $UeWorkingDir)) {
|
||||
throw "Unreal working directory not found: $UeWorkingDir"
|
||||
}
|
||||
|
||||
New-Item -ItemType Directory -Path $PidDir -Force | Out-Null
|
||||
|
||||
$signallingWindowStyle = if ($ShowSignallingWindow.IsPresent) { "Normal" } else { "Hidden" }
|
||||
$signalling = Start-Process -FilePath $SignallingBat -PassThru -WindowStyle $signallingWindowStyle
|
||||
|
||||
Start-Sleep -Seconds $SignallingStartupDelaySeconds
|
||||
|
||||
$ueStartParams = @{
|
||||
FilePath = $UeExe
|
||||
WorkingDirectory = $UeWorkingDir
|
||||
PassThru = $true
|
||||
}
|
||||
|
||||
if ($UeArgs) {
|
||||
$ueStartParams["ArgumentList"] = $UeArgs
|
||||
}
|
||||
|
||||
$ue = Start-Process @ueStartParams
|
||||
|
||||
$ue.Id | Out-File (Join-Path $PidDir "unreal.pid") -Encoding ascii
|
||||
$signalling.Id | Out-File (Join-Path $PidDir "signalling.pid") -Encoding ascii
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user