opcua-service/main/java/de/opcua/app/service/ActionPersistenceService.java
2026-05-11 19:40:18 +02:00

158 lines
5.8 KiB
Java

package de.opcua.app.service;
import de.opcua.app.model.NodeAction;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Timer;
import java.util.TimerTask;
/**
* Persists Actions to JSON file.
*/
public class ActionPersistenceService {
private static final String CONFIG_DIR = System.getProperty("user.home") + "/.opcua-gui";
private static final String ACTIONS_FILE = CONFIG_DIR + "/actions.json";
private final ObjectMapper mapper;
public ActionPersistenceService() {
this.mapper = new ObjectMapper();
this.mapper.enable(SerializationFeature.INDENT_OUTPUT);
ensureConfigDir();
}
private void ensureConfigDir() {
try {
Path dir = Paths.get(CONFIG_DIR);
if (!Files.exists(dir)) {
Files.createDirectories(dir);
System.out.println("[Persistence] Created config directory: " + CONFIG_DIR);
}
} catch (IOException e) {
System.err.println("[Persistence] Failed to create config directory: " + e.getMessage());
}
}
public void saveActions(Map<String, List<NodeAction>> actions) {
try {
List<ActionData> dataList = new ArrayList<>();
for (Map.Entry<String, List<NodeAction>> entry : actions.entrySet()) {
String nodeId = entry.getKey();
for (NodeAction action : entry.getValue()) {
ActionData data = new ActionData(
nodeId,
action.getActionName(),
action.getTriggerType().name(),
action.getScript(),
action.getTriggerValue(),
action.getIntervalMs(),
action.isEnabled()
);
data.conditionEnabled = action.isConditionEnabled();
data.conditionScript = action.getConditionScript();
data.conditionNodeIds = new ArrayList<>(action.getConditionNodeIds());
data.nodeAliases = new LinkedHashMap<>(action.getNodeAliases());
dataList.add(data);
}
}
mapper.writeValue(new File(ACTIONS_FILE), dataList);
System.out.println("[Persistence] Saved " + dataList.size() + " actions to " + ACTIONS_FILE);
} catch (IOException e) {
System.err.println("[Persistence] Failed to save actions: " + e.getMessage());
}
}
public Map<String, List<NodeAction>> loadActions() {
Map<String, List<NodeAction>> result = new HashMap<>();
File file = new File(ACTIONS_FILE);
if (!file.exists()) {
System.out.println("[Persistence] No saved actions found");
return result;
}
try {
ActionData[] dataArray = mapper.readValue(file, ActionData[].class);
for (ActionData data : dataArray) {
NodeAction action = new NodeAction();
action.setNodeId(data.nodeId);
action.setActionName(data.actionName);
action.setTriggerType(NodeAction.TriggerType.valueOf(data.triggerType));
action.setScript(data.script);
action.setTriggerValue(data.triggerValue);
action.setIntervalMs(data.intervalMs);
action.setEnabled(data.enabled);
action.setConditionEnabled(data.conditionEnabled);
action.setConditionScript(data.conditionScript);
action.setConditionNodeIds(data.conditionNodeIds);
action.setNodeAliases(data.nodeAliases);
result.computeIfAbsent(data.nodeId, k -> new ArrayList<>()).add(action);
}
System.out.println("[Persistence] Loaded " + dataArray.length + " actions from " + ACTIONS_FILE);
} catch (IOException e) {
System.err.println("[Persistence] Failed to load actions: " + e.getMessage());
}
return result;
}
public void startAutoSave(ActionService actionService, int intervalSeconds) {
Timer timer = new Timer("ActionAutoSave", true);
timer.scheduleAtFixedRate(new TimerTask() {
@Override
public void run() {
saveActions(actionService.getAllActions());
}
}, intervalSeconds * 1000L, intervalSeconds * 1000L);
System.out.println("[Persistence] Auto-save enabled (every " + intervalSeconds + "s)");
}
public static class ActionData {
public String nodeId;
public String actionName;
public String triggerType;
public String script;
public String triggerValue;
public int intervalMs;
public boolean enabled;
public boolean conditionEnabled;
public String conditionScript;
public List<String> conditionNodeIds = new ArrayList<>();
public Map<String, String> nodeAliases = new LinkedHashMap<>();
public ActionData() {}
public ActionData(String nodeId, String actionName, String triggerType,
String script, String triggerValue, int intervalMs, boolean enabled) {
this.nodeId = nodeId;
this.actionName = actionName;
this.triggerType = triggerType;
this.script = script;
this.triggerValue = triggerValue;
this.intervalMs = intervalMs;
this.enabled = enabled;
}
}
}