strolch-plc/plc-core/src/main/java/li/strolch/plc/core/PlcConfigurator.java

152 lines
6.4 KiB
Java

package li.strolch.plc.core;
import static li.strolch.plc.model.PlcConstants.*;
import static li.strolch.model.StrolchModelConstants.BAG_PARAMETERS;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import li.strolch.model.parameter.Parameter;
import li.strolch.plc.core.hw.*;
import li.strolch.model.Resource;
import li.strolch.persistence.api.StrolchTransaction;
import li.strolch.plc.model.PlcAddress;
import li.strolch.plc.model.PlcAddressType;
import li.strolch.search.ResourceSearch;
import li.strolch.utils.collections.MapOfMaps;
import li.strolch.utils.helper.ClassHelper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
class PlcConfigurator {
private static final Logger logger = LoggerFactory.getLogger(PlcConfigurator.class);
static Plc configurePlc(StrolchTransaction tx, String plcClassName,
MapOfMaps<String, String, PlcAddress> plcAddresses, MapOfMaps<String, String, PlcAddress> plcTelegrams,
Map<PlcAddress, String> addressesToResourceId) throws Exception {
// instantiate Plc
logger.info("Configuring PLC " + plcClassName + "...");
Plc plc = ClassHelper.instantiateClass(plcClassName);
// instantiate all PlcConnections
List<Resource> connections = new ResourceSearch().types(TYPE_PLC_CONNECTION).search(tx).toList();
for (Resource c : connections) {
configureConnection(plc, c);
}
Map<String, PlcAddress> plcAddressesByHwAddress = new HashMap<>();
// query PlcLogicalDevices
List<Resource> logicalDevices = new ResourceSearch().types(TYPE_PLC_LOGICAL_DEVICE).search(tx).toList();
// first all addresses
for (Resource resource : logicalDevices) {
logger.info("Configuring PlcAddresses for PlcLogicalDevice " + resource.getId() + "...");
List<Resource> addresses = tx.getResourcesByRelation(resource, PARAM_ADDRESSES, true);
if (addresses.isEmpty()) {
logger.warn("\tNo PlcAddresses for " + resource.getId());
} else {
for (Resource addressRes : addresses) {
buildPlcAddress(plc, plcAddresses, addressesToResourceId, plcAddressesByHwAddress, addressRes);
}
}
}
// now telegrams
for (Resource logicalDevice : logicalDevices) {
logger.info("Configuring PlcTelegrams for PlcLogicalDevice " + logicalDevice.getId() + "...");
List<Resource> telegrams = tx.getResourcesByRelation(logicalDevice, PARAM_TELEGRAMS, true);
if (telegrams.isEmpty()) {
logger.warn("\tNo PlcTelegrams for " + logicalDevice.getId());
} else {
for (Resource telegramRes : telegrams) {
buildTelegramPlcAddress(plcAddresses, plcTelegrams, addressesToResourceId, plcAddressesByHwAddress,
telegramRes);
}
}
}
return plc;
}
private static void configureConnection(Plc plc, Resource connection) throws Exception {
String className = connection.getParameter(BAG_PARAMETERS, PARAM_CLASS_NAME, true).getValue();
logger.info("Configuring PLC Connection " + className + "...");
PlcConnection plcConnection = ClassHelper.instantiateClass(className,
new Class<?>[] { Plc.class, String.class }, new Object[] { plc, connection.getId() });
plcConnection.initialize(connection.getParameterBag(BAG_PARAMETERS, true).toObjectMap());
plc.addConnection(plcConnection);
}
private static void buildPlcAddress(Plc plc, MapOfMaps<String, String, PlcAddress> plcAddresses,
Map<PlcAddress, String> addressesToResourceId, Map<String, PlcAddress> plcAddressesByHwAddress,
Resource addressRes) {
String address = addressRes.getString(PARAM_ADDRESS);
String resource = addressRes.getString(PARAM_RESOURCE);
String action = addressRes.getString(PARAM_ACTION);
Parameter<?> valueP = addressRes.getParameter(PARAM_VALUE, true);
boolean inverted = addressRes.getBoolean(PARAM_INVERTED);
boolean remote = addressRes.getBoolean(PARAM_REMOTE);
PlcAddress plcAddress = new PlcAddress(PlcAddressType.Notification, resource, action, address,
valueP.getValueType(), valueP.getValue(), inverted, remote);
plc.registerNotificationMapping(plcAddress);
PlcAddress replaced = plcAddresses.addElement(resource, action, plcAddress);
if (replaced != null)
throw new IllegalStateException(
"Duplicate " + resource + "-" + action + ". Replaced: " + replaced + " with " + plcAddress);
addressesToResourceId.put(plcAddress, addressRes.getId());
plcAddressesByHwAddress.put(plcAddress.address, plcAddress);
}
private static void buildTelegramPlcAddress(MapOfMaps<String, String, PlcAddress> plcAddresses,
MapOfMaps<String, String, PlcAddress> plcTelegrams, Map<PlcAddress, String> addressesToResourceId,
Map<String, PlcAddress> plcAddressesByHwAddress, Resource telegramRes) {
String address = telegramRes.getString(PARAM_ADDRESS);
String resource = telegramRes.getString(PARAM_RESOURCE);
String action = telegramRes.getString(PARAM_ACTION);
Parameter<?> valueP = telegramRes.getParameter(PARAM_VALUE, true);
boolean remote = telegramRes.getBoolean(PARAM_REMOTE);
PlcAddress existingAddress = plcAddressesByHwAddress.get(address);
if (existingAddress == null)
throw new IllegalStateException(
telegramRes.getLocator() + " is referencing non-existing address " + address);
if (valueP.getValueType() != existingAddress.valueType) {
throw new IllegalStateException(
telegramRes.getLocator() + " has valueType " + valueP.getValueType() + " but address "
+ existingAddress.address + " has type " + existingAddress.valueType);
}
PlcAddress telegramAddress = new PlcAddress(PlcAddressType.Telegram, resource, action, address,
valueP.getValueType(), valueP.getValue(), false, remote);
logger.info("Adding " + telegramAddress + "...");
PlcAddress replaced = plcTelegrams.addElement(resource, action, telegramAddress);
if (replaced != null)
throw new IllegalStateException(
"Duplicate " + resource + "-" + action + ". Replaced: " + replaced + " with " + telegramAddress);
if (!plcAddresses.containsElement(resource, action))
plcAddresses.addElement(resource, action, telegramAddress);
PlcAddress plcAddress = plcAddresses.getElement(existingAddress.resource, existingAddress.action);
if (plcAddress == null)
throw new IllegalStateException(
"PlcAddress for " + resource + "-" + action + " does not exist, so can not connect PlcTelegram "
+ telegramAddress);
String addressId = addressesToResourceId.get(plcAddress);
if (addressId == null)
throw new IllegalStateException(
"PlcAddress mapping ID for " + resource + "-" + action + " does not exist!");
addressesToResourceId.put(telegramAddress, addressId);
}
}