[Minor] Code cleanup

This commit is contained in:
Robert von Burg 2024-04-12 13:20:48 +02:00
parent d9f6f9daca
commit 5e2e139fcf
Signed by: eitch
GPG Key ID: 75DB9C85C74331F7
41 changed files with 1138 additions and 1157 deletions

View File

@ -212,7 +212,7 @@ public class DefaultPlcHandler extends StrolchComponent implements PlcHandler, P
if (this.globalListener != null)
this.plc.setGlobalListener(this.globalListener);
logger.info("Reconfigured PLC with " + this.plcAddresses.size() + " addresses");
logger.info("Reconfigured PLC with {} addresses", this.plcAddresses.size());
return true;
} catch (Exception e) {
@ -239,7 +239,7 @@ public class DefaultPlcHandler extends StrolchComponent implements PlcHandler, P
if (tx.getConfiguration().hasParameter(PARAM_VERBOSE)) {
boolean verboseOverride = tx.getConfiguration().getBoolean(PARAM_VERBOSE);
logger.info("Overriding XML verbose property from configuration resource to " + verboseOverride);
logger.info("Overriding XML verbose property from configuration resource to {}", verboseOverride);
this.verbose = verboseOverride;
}
@ -257,8 +257,8 @@ public class DefaultPlcHandler extends StrolchComponent implements PlcHandler, P
try {
getContainer().getPrivilegeHandler().validateSystemSession(this.ctx);
} catch (Exception e) {
logger.error("PrivilegeContext for session " + this.ctx.getCertificate().getSessionId() +
" is not valid, reopening.", e);
logger.error("PrivilegeContext for session {} is not valid, reopening.",
this.ctx.getCertificate().getSessionId(), e);
this.ctx = getContainer().getPrivilegeHandler().openAgentSystemUserContext();
}
}
@ -284,7 +284,7 @@ public class DefaultPlcHandler extends StrolchComponent implements PlcHandler, P
public void unregister(String resource, String action, PlcListener listener) {
PlcAddress plcAddress = this.plcAddresses.getElement(resource, action);
if (plcAddress == null) {
logger.warn("No PlcAddress exists for " + resource + "-" + action);
logger.warn("No PlcAddress exists for {}-{}", resource, action);
} else {
this.plc.unregister(plcAddress, listener);
}
@ -353,7 +353,7 @@ public class DefaultPlcHandler extends StrolchComponent implements PlcHandler, P
String addressId = this.addressesToResourceId.get(address);
if (addressId == null) {
logger.error("No PlcAddress mapping for " + address);
logger.error("No PlcAddress mapping for {}", address);
return;
}
@ -377,11 +377,11 @@ public class DefaultPlcHandler extends StrolchComponent implements PlcHandler, P
tx.update(addressRes);
tx.commitOnClose();
} catch (Exception e) {
logger.error("Failed to update PlcAddress " + addressId + " with new value " + value, e);
logger.error("Failed to update PlcAddress {} with new value {}", addressId, value, e);
}
if (this.verbose && (nanoTime() - s > MILLISECONDS.toNanos(SILENT_THRESHOLD)))
logger.info("async update " + address.toKey() + " took " + (formatNanoDuration(nanoTime() - s)));
logger.info("async update {} took {}", address.toKey(), formatNanoDuration(nanoTime() - s));
}
private void updateConnectionState(String id, ConnectionState state, String stateMsg) {
@ -405,11 +405,11 @@ public class DefaultPlcHandler extends StrolchComponent implements PlcHandler, P
tx.commitOnClose();
} catch (Exception e) {
logger.error("Failed to update state for connection " + id, e);
logger.error("Failed to update state for connection {}", id, e);
}
if (this.verbose)
logger.info("updateConnectionState took " + (formatNanoDuration(nanoTime() - s)));
logger.info("updateConnectionState took {}", formatNanoDuration(nanoTime() - s));
}
@Override

View File

@ -28,7 +28,7 @@ class PlcConfigurator {
Map<PlcAddress, String> addressesToResourceId) throws Exception {
// instantiate Plc
logger.info("Configuring PLC " + plcClassName + "...");
logger.info("Configuring PLC {}...", plcClassName);
Plc plc = ClassHelper.instantiateClass(plcClassName);
// instantiate all PlcConnections
@ -44,10 +44,10 @@ class PlcConfigurator {
// first all addresses
for (Resource resource : logicalDevices) {
logger.info("Configuring PlcAddresses for PlcLogicalDevice " + resource.getId() + "...");
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());
logger.warn("\tNo PlcAddresses for {}", resource.getId());
} else {
for (Resource addressRes : addresses) {
buildPlcAddress(plc, plcAddresses, addressesToResourceId, plcAddressesByHwAddress, addressRes);
@ -57,10 +57,10 @@ class PlcConfigurator {
// now telegrams
for (Resource logicalDevice : logicalDevices) {
logger.info("Configuring PlcTelegrams for PlcLogicalDevice " + logicalDevice.getId() + "...");
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());
logger.warn("\tNo PlcTelegrams for {}", logicalDevice.getId());
} else {
for (Resource telegramRes : telegrams) {
buildTelegramPlcAddress(plcAddresses, plcTelegrams, addressesToResourceId, plcAddressesByHwAddress,
@ -74,9 +74,9 @@ class PlcConfigurator {
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() });
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);
}
@ -121,14 +121,18 @@ class PlcConfigurator {
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);
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 + "...");
logger.info("Adding {}...", telegramAddress);
PlcAddress replaced = plcTelegrams.addElement(resource, action, telegramAddress);
if (replaced != null)
@ -139,9 +143,12 @@ class PlcConfigurator {
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);
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(

View File

@ -10,6 +10,8 @@ import li.strolch.policy.ReloadPrivilegeHandlerJob;
import li.strolch.runtime.configuration.RuntimeConfiguration;
import li.strolch.utils.helper.ExceptionHelper;
import static java.text.MessageFormat.format;
public class PlcPostInitializer extends SimplePostInitializer {
public PlcPostInitializer(ComponentContainer container, String componentName) {
@ -49,8 +51,9 @@ public class PlcPostInitializer extends SimplePostInitializer {
protected void notifyStart() {
if (!(getConfiguration().getBoolean("notifyStart", Boolean.FALSE) && getContainer()
.hasComponent(MailHandler.class)))
if (!(
getConfiguration().getBoolean("notifyStart", Boolean.FALSE) && getContainer().hasComponent(
MailHandler.class)))
return;
String recipients = getConfiguration().getString("notifyStartRecipients", "");
@ -61,20 +64,18 @@ public class PlcPostInitializer extends SimplePostInitializer {
StrolchAgent agent = getContainer().getAgent();
RuntimeConfiguration runtimeConfiguration = agent.getStrolchConfiguration().getRuntimeConfiguration();
String subject = runtimeConfiguration.getApplicationName() + ":" + runtimeConfiguration.getEnvironment()
+ " Startup Complete!";
String subject = format("{0}:{1} Startup Complete!", runtimeConfiguration.getApplicationName(),
runtimeConfiguration.getEnvironment());
String body = "Dear User\n\n" //
+ "The " + getConfiguration().getRuntimeConfiguration().getApplicationName()
+ " Server has just completed startup with version " //
+ agent.getVersion().getAppVersion().getArtifactVersion() //
+ "\n\n" //
+ "\tYour Server.";
String body = format(
"Dear User\n\nThe {0} Server has just completed startup with version {1}\n\n\tYour Server.",
getConfiguration().getRuntimeConfiguration().getApplicationName(),
agent.getVersion().getAppVersion().getArtifactVersion());
try {
getContainer().getComponent(MailHandler.class).sendMailAsync(subject, body, recipients);
} catch (Exception e) {
logger.error("Notifying of server startup failed: " + ExceptionHelper.getRootCause(e), e);
logger.error("Notifying of server startup failed: {}", ExceptionHelper.getRootCause(e), e);
}
}
}

View File

@ -296,7 +296,7 @@ public abstract class PlcService implements PlcListener {
* @param locator the locator of the message
*/
protected void disableMsg(Locator locator) {
logger.info("Disabling message for locator " + locator);
logger.info("Disabling message for locator {}", locator);
this.plcHandler.disableMsg(locator);
}
@ -544,6 +544,6 @@ public abstract class PlcService implements PlcListener {
* @param e the exception which occurred
*/
protected void handleFailedAsync(Exception e) {
logger.error("Failed to execute " + getClass().getSimpleName(), e);
logger.error("Failed to execute {}", getClass().getSimpleName(), e);
}
}

View File

@ -31,12 +31,12 @@ public abstract class PlcServiceInitializer extends StrolchComponent {
try {
plcService.stop();
} catch (Exception e) {
logger.error("Failed to stop PlcService " + plcService.getClass().getName(), e);
logger.error("Failed to stop PlcService {}", plcService.getClass().getName(), e);
}
try {
plcService.unregister();
} catch (Exception e) {
logger.error("Failed to unregister PlcService " + plcService.getClass().getName(), e);
logger.error("Failed to unregister PlcService {}", plcService.getClass().getName(), e);
}
});
super.stop();
@ -45,7 +45,7 @@ public abstract class PlcServiceInitializer extends StrolchComponent {
protected void startPlcServices() {
PlcHandler plcHandler = getComponent(PlcHandler.class);
if (plcHandler.getPlcState() != PlcState.Started) {
logger.error("Can not start PlcServices as PlcState is " + plcHandler.getPlcState());
logger.error("Can not start PlcServices as PlcState is {}", plcHandler.getPlcState());
return;
}
@ -54,7 +54,7 @@ public abstract class PlcServiceInitializer extends StrolchComponent {
try {
plcService.register();
} catch (Exception e) {
logger.error("Failed to register PlcService " + plcService.getClass().getName(), e);
logger.error("Failed to register PlcService {}", plcService.getClass().getName(), e);
}
}
@ -68,7 +68,7 @@ public abstract class PlcServiceInitializer extends StrolchComponent {
try {
plcService.start(tx);
} catch (Exception e) {
logger.error("Failed to register PlcService " + plcService.getClass().getName(), e);
logger.error("Failed to register PlcService {}", plcService.getClass().getName(), e);
}
}
}

View File

@ -1,12 +1,5 @@
package li.strolch.plc.core.hw;
import static java.util.stream.Collectors.toSet;
import java.util.*;
import java.util.concurrent.Future;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.stream.Stream;
import li.strolch.plc.model.PlcAddress;
import li.strolch.plc.model.PlcAddressKey;
import li.strolch.plc.model.PlcAddressType;
@ -15,6 +8,13 @@ import li.strolch.utils.collections.MapOfLists;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.*;
import java.util.concurrent.Future;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.stream.Stream;
import static java.util.stream.Collectors.toSet;
public class DefaultPlc implements Plc {
private static final Logger logger = LoggerFactory.getLogger(DefaultPlc.class);
@ -79,15 +79,15 @@ public class DefaultPlc implements Plc {
@Override
public void register(PlcAddress address, PlcListener listener) {
this.listeners.addElement(address, listener);
logger.info(address.toKeyAddress() + ": " + listener.getClass().getSimpleName());
logger.info("{}: {}", address.toKeyAddress(), listener.getClass().getSimpleName());
}
@Override
public void unregister(PlcAddress address, PlcListener listener) {
if (this.listeners.removeElement(address, listener)) {
logger.info(address + ": " + listener.getClass().getName());
logger.info("{}: {}", address, listener.getClass().getName());
} else {
logger.warn("Listener not registered with key " + address.toKeyAddress() + ": " +
logger.warn("Listener not registered with key {}: {}", address.toKeyAddress(),
listener.getClass().getSimpleName());
}
}
@ -105,7 +105,7 @@ public class DefaultPlc implements Plc {
private void doNotify(String address, Object value) {
PlcAddress plcAddress = this.notificationMappings.get(address);
if (plcAddress == null) {
logger.warn("No mapping to PlcAddress for hwAddress " + address);
logger.warn("No mapping to PlcAddress for hwAddress {}", address);
return;
}
@ -113,7 +113,7 @@ public class DefaultPlc implements Plc {
if (value instanceof Boolean)
value = !((boolean) value);
else
logger.error(plcAddress + " is marked as inverted, but the value is not a boolean, but a " +
logger.error("{} is marked as inverted, but the value is not a boolean, but a {}", plcAddress,
value.getClass());
}
@ -130,11 +130,11 @@ public class DefaultPlc implements Plc {
for (PlcListener listener : listeners) {
try {
if (this.verbose)
logger.info("Notifying " + plcAddress.toKey() + ": " + value + " @ " + listener);
logger.info("Notifying {}: {} @ {}", plcAddress.toKey(), value, listener);
listener.handleNotification(plcAddress, value);
} catch (Exception e) {
if (catchExceptions) {
logger.error("Failed to notify listener " + listener + " for address " + plcAddress, e);
logger.error("Failed to notify listener {} for address {}", listener, plcAddress, e);
} else {
throw e;
}
@ -157,7 +157,7 @@ public class DefaultPlc implements Plc {
logger.error("Interrupted!");
} catch (Exception e) {
if (task != null)
logger.error("Failed to perform notification for " + task.address + ": " + task.value, e);
logger.error("Failed to perform notification for {}: {}", task.address, task.value, e);
else
logger.error("Failed to get notification task", e);
}
@ -209,10 +209,10 @@ public class DefaultPlc implements Plc {
public void addConnection(PlcConnection connection) {
this.connections.put(connection.getId(), connection);
Set<String> addresses = connection.getAddresses();
logger.info("Adding connection " + connection.getId() + " " + connection.getClass().getName() + " with " +
addresses.size() + " addresses...");
logger.info("Adding connection {} {} with {} addresses...", connection.getId(), connection.getClass().getName(),
addresses.size());
for (String address : addresses) {
logger.info(" Adding " + address + "...");
logger.info(" Adding {}...", address);
this.connectionsByAddress.put(address, connection);
}
}
@ -268,23 +268,13 @@ public class DefaultPlc implements Plc {
throw new IllegalArgumentException(
"Replaced mapping for address " + address.address + " for key " + replaced + " with " + address);
logger.info("Registered " + address);
logger.info("Registered {}", address);
}
private void validateVirtualAddress(PlcAddress address) {
if (address.address.equals(VIRTUAL_BOOLEAN) || address.address.equals(VIRTUAL_BOOLEAN + ".")) {
throw new IllegalStateException(
"Virtual address " + address.address + " is missing sub component for " + address);
}
if (address.address.equals(VIRTUAL_STRING) || address.address.equals(VIRTUAL_STRING + ".")) {
throw new IllegalStateException(
"Virtual address " + address.address + " is missing sub component for " + address);
}
if (address.address.equals(VIRTUAL_INTEGER) || address.address.equals(VIRTUAL_INTEGER + ".")) {
throw new IllegalStateException(
switch (address.address) {
case VIRTUAL_BOOLEAN, VIRTUAL_BOOLEAN + ".", VIRTUAL_STRING, VIRTUAL_STRING + ".", VIRTUAL_INTEGER,
VIRTUAL_INTEGER + "." -> throw new IllegalStateException(
"Virtual address " + address.address + " is missing sub component for " + address);
}
}

View File

@ -11,10 +11,8 @@ public interface PlcListener {
/**
* Notifies the listener of the new value at the given address
*
* @param address
* the address at which the event was detected
* @param value
* the new value at the address
* @param address the address at which the event was detected
* @param value the new value at the address
*/
void handleNotification(PlcAddress address, Object value);
}

View File

@ -1,7 +1,7 @@
package li.strolch.plc.core.hw.connections;
import static li.strolch.plc.model.PlcConstants.PARAM_SIMULATED;
import static li.strolch.utils.helper.ExceptionHelper.getExceptionMessageWithCauses;
import li.strolch.plc.core.hw.Plc;
import li.strolch.utils.helper.AsciiHelper;
import java.io.IOException;
import java.io.InputStream;
@ -15,8 +15,9 @@ import java.util.Set;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import li.strolch.plc.core.hw.Plc;
import li.strolch.utils.helper.AsciiHelper;
import static java.text.MessageFormat.format;
import static li.strolch.plc.model.PlcConstants.PARAM_SIMULATED;
import static li.strolch.utils.helper.ExceptionHelper.getExceptionMessageWithCauses;
public class DataLogicScannerConnection extends SimplePlcConnection {
@ -64,13 +65,13 @@ public class DataLogicScannerConnection extends SimplePlcConnection {
this.addresses.add(this.addressTrigger);
this.addresses.add(this.addressBarcode);
logger.info("Configured DataLogic Scanner connection to " + this.address + ":" + this.port);
logger.info("Configured DataLogic Scanner connection to {}:{}", this.address, this.port);
}
@Override
public boolean connect() {
if (this.simulated) {
logger.warn(this.id + ": Running SIMULATED, NOT CONNECTING!");
logger.warn("{}: Running SIMULATED, NOT CONNECTING!", this.id);
return super.connect();
}
@ -80,7 +81,7 @@ public class DataLogicScannerConnection extends SimplePlcConnection {
try {
this.socket = new Socket(this.address, this.port);
this.socket.setSoTimeout((int) TimeUnit.SECONDS.toMillis(this.readTimeout));
logger.info("Connected DataLogic Scanner connection to " + this.address + ":" + this.port);
logger.info("Connected DataLogic Scanner connection to {}:{}", this.address, this.port);
this.read = true;
this.readTask = this.plc.getExecutorPool().getSingleThreadExecutor(this.id).submit(this::read);
@ -98,7 +99,7 @@ public class DataLogicScannerConnection extends SimplePlcConnection {
@Override
public void disconnect() {
if (this.simulated) {
logger.warn(this.id + ": Running SIMULATED, NOT CONNECTING!");
logger.warn("{}: Running SIMULATED, NOT CONNECTING!", this.id);
super.disconnect();
return;
}
@ -114,7 +115,7 @@ public class DataLogicScannerConnection extends SimplePlcConnection {
}
if (this.socket != null) {
logger.warn("Closing socket to " + this.address + ":" + this.port);
logger.warn("Closing socket to {}:{}", this.address, this.port);
try {
this.socket.shutdownInput();
this.socket.shutdownOutput();
@ -150,7 +151,7 @@ public class DataLogicScannerConnection extends SimplePlcConnection {
throw new IllegalStateException("Illegal Address " + address);
if (this.simulated) {
logger.warn(this.id + ": Running SIMULATED, NOT CONNECTING!");
logger.warn("{}: Running SIMULATED, NOT CONNECTING!", this.id);
return;
}
@ -170,8 +171,8 @@ public class DataLogicScannerConnection extends SimplePlcConnection {
} catch (IOException e) {
handleBrokenConnection(
"Failed to handle address " + address + " for " + this.address + ":" + this.port + ": "
+ getExceptionMessageWithCauses(e), e);
format("Failed to handle address {0} for {1}:{2}: {3}", address, this.address, this.port,
getExceptionMessageWithCauses(e)), e);
throw new IllegalStateException(
"Failed to handle address " + address + " for " + this.address + ":" + this.port, e);
@ -180,7 +181,7 @@ public class DataLogicScannerConnection extends SimplePlcConnection {
private void read() {
logger.info("Reading from DataLogic Scanner at " + this.address + ":" + this.port + "...");
logger.info("Reading from DataLogic Scanner at {}:{}...", this.address, this.port);
while (this.read) {
try {
@ -215,7 +216,7 @@ public class DataLogicScannerConnection extends SimplePlcConnection {
}
String barcode = sb.toString();
logger.info("Received barcode " + barcode);
logger.info("Received barcode {}", barcode);
notify(this.addressBarcode, barcode);
}
@ -226,27 +227,27 @@ public class DataLogicScannerConnection extends SimplePlcConnection {
try {
sendStopTrigger();
} catch (IOException ex) {
logger.error("Failed to send stop during timeout exception: " + ex.getMessage());
logger.error("Failed to send stop during timeout exception: {}", ex.getMessage());
}
internalDisconnect();
handleBrokenConnection(
"Timeout while reading from scanner at " + this.address + ":" + this.port + ": "
+ getExceptionMessageWithCauses(e), e);
format("Timeout while reading from scanner at {0}:{1}: {2}", this.address, this.port,
getExceptionMessageWithCauses(e)), e);
} else {
logger.warn("Timeout while reading from scanner at " + this.address + ":" + this.port
+ ". Disconnected.");
logger.warn("Timeout while reading from scanner at {}:{}. Disconnected.", this.address,
this.port);
notify(this.addressBarcode, NO_CONNECTION);
disconnect();
}
} else {
notify(this.addressBarcode, NO_CONNECTION);
internalDisconnect();
handleBrokenConnection("Failed to connect to " + this.address + ":" + this.port + ": "
+ getExceptionMessageWithCauses(e), e);
handleBrokenConnection(format("Failed to connect to {0}:{1}: {2}", this.address, this.port,
getExceptionMessageWithCauses(e)), e);
}
}
}
logger.info("Stopped reading from " + this.address + ":" + this.port);
logger.info("Stopped reading from {}:{}", this.address, this.port);
}
}

View File

@ -11,6 +11,6 @@ public class LoggerOutConnection extends SimplePlcConnection {
@Override
public void send(String address, Object value) {
assertConnected();
logger.info(address + " -> " + value);
logger.info("{} -> {}", address, value);
}
}

View File

@ -15,11 +15,11 @@ public class RandomStringConnection extends SimplePlcConnection {
@Override
public void send(String address, Object value) {
assertConnected();
PlcConnection.logger.info("Sending " + address + " => " + value);
PlcConnection.logger.info("Sending {} => {}", address, value);
byte[] data = new byte[8];
new SecureRandom().nextBytes(data);
String newValue = StringHelper.toHexString(data);
PlcConnection.logger.info("Generated random value " + newValue);
PlcConnection.logger.info("Generated random value {}", newValue);
this.plc.syncNotify(address, newValue);
}
}

View File

@ -19,12 +19,12 @@ public abstract class SimplePlcConnection extends PlcConnection {
@Override
public void initialize(Map<String, Object> parameters) throws Exception {
logger.info("Configured " + getClass().getSimpleName() + " " + this.id);
logger.info("Configured {} {}", getClass().getSimpleName(), this.id);
}
@Override
public boolean connect() {
logger.info(this.id + ": Is now connected.");
logger.info("{}: Is now connected.", this.id);
if (this.simulated)
logger.info("Running SIMULATED");
this.connectionState = ConnectionState.Connected;
@ -35,7 +35,7 @@ public abstract class SimplePlcConnection extends PlcConnection {
@Override
public void disconnect() {
logger.info(this.id + ": Is now disconnected.");
logger.info("{}: Is now disconnected.", this.id);
this.connectionState = ConnectionState.Disconnected;
this.connectionStateMsg = "-";
this.plc.notifyConnectionStateChanged(this);

View File

@ -18,7 +18,6 @@ import li.strolch.plc.core.hw.connections.SimplePlcConnection;
public class RaspiBcmGpioInputConnection extends SimplePlcConnection {
private boolean verbose;
private List<Integer> inputBcmAddresses;
private Map<String, Pin> pinsByAddress;
private Map<GpioPin, String> addressesByPin;
@ -33,18 +32,16 @@ public class RaspiBcmGpioInputConnection extends SimplePlcConnection {
public void initialize(Map<String, Object> parameters) {
this.simulated = parameters.containsKey(PARAM_SIMULATED) && (boolean) parameters.get(PARAM_SIMULATED);
@SuppressWarnings("unchecked")
List<Integer> bcmInputPins = (List<Integer>) parameters.get("bcmInputPins");
this.inputBcmAddresses = bcmInputPins;
@SuppressWarnings("unchecked") List<Integer> bcmInputPins = (List<Integer>) parameters.get("bcmInputPins");
this.pinsByAddress = new HashMap<>();
for (Integer address : this.inputBcmAddresses) {
for (Integer address : bcmInputPins) {
Pin pin = RaspiBcmPin.getPinByAddress(address);
if (pin == null)
throw new IllegalArgumentException("RaspiBcmPin " + address + " does not exist!");
String key = this.id + "." + address;
this.pinsByAddress.put(key, pin);
logger.info("Registered address " + key + " for RaspiBcmPin " + pin);
logger.info("Registered address {} for RaspiBcmPin {}", key, pin);
}
if (parameters.containsKey("pinPullResistance")) {
@ -56,14 +53,14 @@ public class RaspiBcmGpioInputConnection extends SimplePlcConnection {
this.verbose = parameters.containsKey("verbose") && (Boolean) parameters.get("verbose");
this.inverted = parameters.containsKey("inverted") && (boolean) parameters.get("inverted");
logger.info("Configured Raspi BCM GPIO Input for Pins " + this.inputBcmAddresses.stream().map(Object::toString)
.collect(joining(", ")));
logger.info("Configured Raspi BCM GPIO Input for Pins {}",
bcmInputPins.stream().map(Object::toString).collect(joining(", ")));
}
@Override
public boolean connect() {
if (this.simulated) {
logger.warn(this.id + ": Running SIMULATED, NOT CONNECTING!");
logger.warn("{}: Running SIMULATED, NOT CONNECTING!", this.id);
return super.connect();
}
@ -82,7 +79,7 @@ public class RaspiBcmGpioInputConnection extends SimplePlcConnection {
inputPin.addListener((GpioPinListenerDigital) this::handleInterrupt);
this.addressesByPin.put(inputPin, address);
logger.info("Provisioned input pin " + inputPin + " for address " + address);
logger.info("Provisioned input pin {} for address {}", inputPin, address);
}
return super.connect();
@ -95,19 +92,19 @@ public class RaspiBcmGpioInputConnection extends SimplePlcConnection {
private void handleInterrupt(GpioPinDigitalStateChangeEvent event) {
if (this.verbose)
logger.info(event.getPin() + " " + event.getState() + " " + event.getEdge());
logger.info("{} {} {}", event.getPin(), event.getState(), event.getEdge());
String address = this.addressesByPin.get(event.getPin());
PinState state = event.getState();
if (this.verbose)
logger.info(address + " has new state " + state);
logger.info("{} has new state {}", address, state);
notify(address, this.inverted ? state.isLow() : state.isHigh());
}
@Override
public void disconnect() {
if (this.simulated) {
logger.warn(this.id + ": Running SIMULATED, NOT CONNECTING!");
logger.warn("{}: Running SIMULATED, NOT CONNECTING!", this.id);
super.disconnect();
return;
}
@ -119,7 +116,7 @@ public class RaspiBcmGpioInputConnection extends SimplePlcConnection {
}
this.addressesByPin.clear();
} catch (Error e) {
logger.error("Failed to disconnect " + this.id, e);
logger.error("Failed to disconnect {}", this.id, e);
}
super.disconnect();

View File

@ -16,7 +16,6 @@ import li.strolch.plc.core.hw.connections.SimplePlcConnection;
public class RaspiBcmGpioOutputConnection extends SimplePlcConnection {
private boolean verbose;
private List<Integer> outputBcmAddresses;
private Map<String, Pin> pinsByAddress;
private Map<String, GpioPinDigitalOutput> gpioPinsByAddress;
private boolean inverted;
@ -29,25 +28,22 @@ public class RaspiBcmGpioOutputConnection extends SimplePlcConnection {
public void initialize(Map<String, Object> parameters) {
this.simulated = parameters.containsKey(PARAM_SIMULATED) && (boolean) parameters.get(PARAM_SIMULATED);
@SuppressWarnings("unchecked")
List<Integer> bcmOutputPins = (List<Integer>) parameters.get("bcmOutputPins");
this.outputBcmAddresses = bcmOutputPins;
@SuppressWarnings("unchecked") List<Integer> bcmOutputPins = (List<Integer>) parameters.get("bcmOutputPins");
this.pinsByAddress = new HashMap<>();
for (Integer address : this.outputBcmAddresses) {
for (Integer address : bcmOutputPins) {
Pin pin = RaspiBcmPin.getPinByAddress(address);
if (pin == null)
throw new IllegalArgumentException("RaspiBcmPin " + address + " does not exist!");
String key = this.id + "." + address;
this.pinsByAddress.put(key, pin);
logger.info("Registered address " + key + " for RaspiBcmPin " + pin);
logger.info("Registered address {} for RaspiBcmPin {}", key, pin);
}
this.verbose = parameters.containsKey("verbose") && (Boolean) parameters.get("verbose");
this.inverted = parameters.containsKey("inverted") && (boolean) parameters.get("inverted");
logger.info(
"Configured Raspi BCM GPIO Output for Pins " + this.outputBcmAddresses.stream().map(Object::toString)
.collect(joining(", ")));
logger.info("Configured Raspi BCM GPIO Output for Pins {}",
bcmOutputPins.stream().map(Object::toString).collect(joining(", ")));
}
@Override
@ -65,7 +61,7 @@ public class RaspiBcmGpioOutputConnection extends SimplePlcConnection {
Pin pin = this.pinsByAddress.get(address);
GpioPinDigitalOutput outputPin = gpioController.provisionDigitalOutputPin(pin);
this.gpioPinsByAddress.put(address, outputPin);
logger.info("Provisioned output pin " + outputPin + " for address " + address);
logger.info("Provisioned output pin {} for address {}", outputPin, address);
}
return super.connect();
@ -79,7 +75,7 @@ public class RaspiBcmGpioOutputConnection extends SimplePlcConnection {
@Override
public void disconnect() {
if (this.simulated) {
logger.warn(this.id + ": Running SIMULATED, NOT CONNECTING!");
logger.warn("{}: Running SIMULATED, NOT CONNECTING!", this.id);
super.disconnect();
return;
}
@ -91,7 +87,7 @@ public class RaspiBcmGpioOutputConnection extends SimplePlcConnection {
}
this.gpioPinsByAddress.clear();
} catch (Error e) {
logger.error("Failed to disconnect " + this.id, e);
logger.error("Failed to disconnect {}", this.id, e);
}
super.disconnect();
@ -100,7 +96,7 @@ public class RaspiBcmGpioOutputConnection extends SimplePlcConnection {
@Override
public void send(String address, Object value) {
if (this.simulated) {
logger.warn(this.id + ": Running SIMULATED, NOT CONNECTING!");
logger.warn("{}: Running SIMULATED, NOT CONNECTING!", this.id);
return;
}
@ -114,7 +110,7 @@ public class RaspiBcmGpioOutputConnection extends SimplePlcConnection {
PinState newState = high ? PinState.HIGH : PinState.LOW;
if (this.verbose)
logger.info("Setting pin " + outputPin + " to new state " + newState);
logger.info("Setting pin {} to new state {}", outputPin, newState);
outputPin.setState(newState);
}

View File

@ -1,15 +1,15 @@
package li.strolch.plc.core.hw.i2c;
import static li.strolch.utils.helper.StringHelper.toHexString;
import static li.strolch.utils.helper.StringHelper.toPrettyHexString;
import java.io.IOException;
import com.pi4j.io.i2c.I2CDevice;
import li.strolch.utils.communication.PacketObserver;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.IOException;
import static li.strolch.utils.helper.StringHelper.toHexString;
import static li.strolch.utils.helper.StringHelper.toPrettyHexString;
public class LoggingI2cDevice {
private static final Logger logger = LoggerFactory.getLogger(LoggingI2cDevice.class);
@ -45,12 +45,12 @@ public class LoggingI2cDevice {
sleepIfNecessary();
if (log)
logger.info(this.i2cAddressS + ": Writing: " + toHexString(data));
logger.info("{}: Writing: {}", this.i2cAddressS, toHexString(data));
this.i2cDevice.write(data);
if (this.packetObserver != null)
this.packetObserver.notifySent(new byte[] { data });
this.packetObserver.notifySent(new byte[]{data});
this.lastWriteNanos = System.nanoTime();
}
@ -58,7 +58,7 @@ public class LoggingI2cDevice {
sleepIfNecessary();
if (log)
logger.info(this.i2cAddressS + ": Writing: " + toPrettyHexString(buffer));
logger.info("{}: Writing: {}", this.i2cAddressS, toPrettyHexString(buffer));
this.i2cDevice.write(buffer);
@ -68,7 +68,7 @@ public class LoggingI2cDevice {
}
public void write(boolean log, int address, byte b) throws IOException, InterruptedException {
write(log, new byte[] { (byte) address, b });
write(log, new byte[]{(byte) address, b});
}
public void write(boolean log, int address, byte[] buffer) throws IOException, InterruptedException {
@ -82,7 +82,7 @@ public class LoggingI2cDevice {
sleepIfNecessary();
if (log)
logger.info(this.i2cAddressS + ": Writing: " + toPrettyHexString(writeBuffer));
logger.info("{}: Writing: {}", this.i2cAddressS, toPrettyHexString(writeBuffer));
int read = this.i2cDevice.read(writeBuffer, 0, writeBuffer.length, readBuffer, 0, readBuffer.length);
if (read != readBuffer.length)
@ -95,31 +95,31 @@ public class LoggingI2cDevice {
this.lastWriteNanos = System.nanoTime();
if (log)
logger.info(this.i2cAddressS + ": Read: " + toPrettyHexString(readBuffer));
logger.info("{}: Read: {}", this.i2cAddressS, toPrettyHexString(readBuffer));
}
public int read(boolean log) throws IOException {
int read = this.i2cDevice.read();
if (log)
logger.info(this.i2cAddressS + ": Read: " + toHexString((byte) read));
logger.info("{}: Read: {}", this.i2cAddressS, toHexString((byte) read));
if (this.packetObserver != null)
this.packetObserver.notifyReceived(new byte[] { (byte) read });
this.packetObserver.notifyReceived(new byte[]{(byte) read});
return read;
}
public int read(boolean log, byte address) throws IOException {
if (log)
logger.info(this.i2cAddressS + ": Writing: " + toHexString(address));
logger.info("{}: Writing: {}", this.i2cAddressS, toHexString(address));
int read = this.i2cDevice.read(address);
if (log)
logger.info(this.i2cAddressS + ": Read: " + toHexString((byte) read));
logger.info("{}: Read: {}", this.i2cAddressS, toHexString((byte) read));
if (this.packetObserver != null) {
this.packetObserver.notifySent(new byte[] { address });
this.packetObserver.notifyReceived(new byte[] { (byte) read });
this.packetObserver.notifySent(new byte[]{address});
this.packetObserver.notifyReceived(new byte[]{(byte) read});
}
return read;
@ -127,31 +127,31 @@ public class LoggingI2cDevice {
public void read(boolean log, byte[] buffer) throws IOException {
if (log)
logger.info(this.i2cAddressS + ": Reading: " + buffer.length + " bytes from last set address...");
logger.info("{}: Reading: {} bytes from last set address...", this.i2cAddressS, buffer.length);
int read = this.i2cDevice.read(buffer, 0, buffer.length);
if (read != buffer.length)
throw new IllegalStateException("Expected to read " + buffer.length + " bytes, but read " + read);
if (log)
logger.info(this.i2cAddressS + ": Read: " + toPrettyHexString(buffer));
logger.info("{}: Read: {}", this.i2cAddressS, toPrettyHexString(buffer));
if (this.packetObserver != null)
this.packetObserver.notifyReceived(new byte[] { (byte) read });
this.packetObserver.notifyReceived(new byte[]{(byte) read});
}
public void read(boolean log, byte address, byte[] buffer) throws IOException {
if (log)
logger.info(
this.i2cAddressS + ": Reading: " + buffer.length + " bytes from address " + toHexString(address));
logger.info("{}: Reading: {} bytes from address {}", this.i2cAddressS, buffer.length,
toHexString(address));
int read = this.i2cDevice.read(address, buffer, 0, buffer.length);
if (read != buffer.length)
throw new IllegalStateException("Expected to read " + buffer.length + " bytes, but read " + read);
if (log)
logger.info(this.i2cAddressS + ": Read: " + toPrettyHexString(buffer));
logger.info("{}: Read: {}", this.i2cAddressS, toPrettyHexString(buffer));
if (this.packetObserver != null) {
this.packetObserver.notifySent(new byte[] { address });
this.packetObserver.notifySent(new byte[]{address});
this.packetObserver.notifyReceived(buffer);
}
}
@ -180,6 +180,6 @@ public class LoggingI2cDevice {
this.ioWait = ioWait;
this.ioWaitNanos = ioWaitNanos;
logger.info("Using " + ioWait + " ms and " + ioWaitNanos + " ns for write sleep");
logger.info("Using {} ms and {} ns for write sleep", ioWait, ioWaitNanos);
}
}

View File

@ -41,7 +41,8 @@ public abstract class Multi8BitI2cOutputConnection extends SimplePlcConnection {
public abstract String getName();
public String getDescription() {
return "I2C Output " + getName() + " @ " + byteStream(this.addresses).map(b -> "0x" + toHexString(b))
return "I2C Output " + getName() + " @ " + byteStream(this.addresses)
.map(b -> "0x" + toHexString(b))
.collect(joining(", "));
}
@ -65,12 +66,11 @@ public abstract class Multi8BitI2cOutputConnection extends SimplePlcConnection {
this.inverted = parameters.containsKey("inverted") && (boolean) parameters.get("inverted");
this.reversed = parameters.containsKey("reversed") && (boolean) parameters.get("reversed");
logger.info("inverted: " + this.inverted);
logger.info("reversed: " + this.reversed);
logger.info("nrOfBits: " + this.nrOfBits);
logger.info("inverted: {}", this.inverted);
logger.info("reversed: {}", this.reversed);
logger.info("nrOfBits: {}", this.nrOfBits);
@SuppressWarnings("unchecked")
List<Integer> addressList = (List<Integer>) parameters.get("addresses");
@SuppressWarnings("unchecked") List<Integer> addressList = (List<Integer>) parameters.get("addresses");
this.addresses = new byte[addressList.size()];
for (int i = 0; i < addressList.size(); i++) {
this.addresses[i] = addressList.get(i).byteValue();
@ -79,26 +79,26 @@ public abstract class Multi8BitI2cOutputConnection extends SimplePlcConnection {
Map<String, int[]> positionsByAddress = new HashMap<>();
for (int i = 0; i < this.addresses.length; i++) {
for (int j = 0; j < this.nrOfBits; j++)
positionsByAddress.put(this.id + "." + i + "." + j, new int[] { i, j });
positionsByAddress.put(this.id + "." + i + "." + j, new int[]{i, j});
}
this.positionsByAddress = Collections.unmodifiableMap(positionsByAddress);
logger.info("Configured " + getDescription());
logger.info("Configured {}", getDescription());
}
@Override
public boolean connect() {
if (this.simulated) {
logger.warn(getName() + ": " + this.id + ": Running SIMULATED, NOT CONNECTING!");
logger.warn("{}: {}: Running SIMULATED, NOT CONNECTING!", getName(), this.id);
return super.connect();
}
if (isConnected()) {
logger.warn(getName() + ": " + this.id + ": Already connected");
logger.warn("{}: {}: Already connected", getName(), this.id);
return true;
}
logger.info(getName() + ": " + this.id + ": Connecting...");
logger.info("{}: {}: Connecting...", getName(), this.id);
// initialize
try {
@ -114,7 +114,7 @@ public abstract class Multi8BitI2cOutputConnection extends SimplePlcConnection {
}
if (setup()) {
logger.info("Successfully connected " + this.outputDevices.length + " devices as " + getDescription());
logger.info("Successfully connected {} devices as {}", this.outputDevices.length, getDescription());
return super.connect();
}
@ -136,7 +136,7 @@ public abstract class Multi8BitI2cOutputConnection extends SimplePlcConnection {
byte address = this.addresses[index];
I2CDevice outputDevice = devices[index];
ok &= setup(address, index, outputDevice);
logger.info("Connected " + getDescription(address));
logger.info("Connected {}", getDescription(address));
}
if (ok)
@ -150,7 +150,7 @@ public abstract class Multi8BitI2cOutputConnection extends SimplePlcConnection {
@Override
public void disconnect() {
if (this.simulated) {
logger.warn(this.id + ": Running SIMULATED, NOT CONNECTING!");
logger.warn("{}: Running SIMULATED, NOT CONNECTING!", this.id);
super.disconnect();
return;
}
@ -169,7 +169,7 @@ public abstract class Multi8BitI2cOutputConnection extends SimplePlcConnection {
@Override
public void send(String address, Object value) {
if (this.simulated) {
logger.warn(this.id + ": Running SIMULATED, NOT CONNECTING!");
logger.warn("{}: Running SIMULATED, NOT CONNECTING!", this.id);
return;
}

View File

@ -1,19 +1,5 @@
package li.strolch.plc.core.hw.i2c;
import static com.pi4j.wiringpi.Gpio.HIGH;
import static com.pi4j.wiringpi.Gpio.LOW;
import static li.strolch.plc.model.PlcConstants.PARAM_SIMULATED;
import static li.strolch.utils.helper.ByteHelper.asBinary;
import static li.strolch.utils.helper.ByteHelper.isBitSet;
import static li.strolch.utils.helper.ExceptionHelper.getExceptionMessageWithCauses;
import static li.strolch.utils.helper.StringHelper.toHexString;
import static li.strolch.utils.helper.StringHelper.toPrettyHexString;
import java.io.IOException;
import java.util.*;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import com.pi4j.io.gpio.*;
import com.pi4j.io.gpio.event.GpioPinDigitalStateChangeEvent;
import com.pi4j.io.gpio.event.GpioPinListenerDigital;
@ -27,6 +13,21 @@ import li.strolch.plc.core.hw.gpio.PlcGpioController;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.IOException;
import java.util.*;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import static com.pi4j.wiringpi.Gpio.HIGH;
import static com.pi4j.wiringpi.Gpio.LOW;
import static java.text.MessageFormat.format;
import static li.strolch.plc.model.PlcConstants.PARAM_SIMULATED;
import static li.strolch.utils.helper.ByteHelper.asBinary;
import static li.strolch.utils.helper.ByteHelper.isBitSet;
import static li.strolch.utils.helper.ExceptionHelper.getExceptionMessageWithCauses;
import static li.strolch.utils.helper.StringHelper.toHexString;
import static li.strolch.utils.helper.StringHelper.toPrettyHexString;
public class PCF8574InputConnection extends SimplePlcConnection {
private static final Logger logger = LoggerFactory.getLogger(PCF8574InputConnection.class);
@ -71,8 +72,7 @@ public class PCF8574InputConnection extends SimplePlcConnection {
this.i2cBusNr = (int) parameters.get("i2cBus");
this.inverted = parameters.containsKey("inverted") && (boolean) parameters.get("inverted");
@SuppressWarnings("unchecked")
List<Integer> addressList = (List<Integer>) parameters.get("addresses");
@SuppressWarnings("unchecked") List<Integer> addressList = (List<Integer>) parameters.get("addresses");
this.addresses = new byte[addressList.size()];
for (int i = 0; i < addressList.size(); i++) {
this.addresses[i] = addressList.get(i).byteValue();
@ -81,36 +81,35 @@ public class PCF8574InputConnection extends SimplePlcConnection {
Map<String, int[]> positionsByAddress = new HashMap<>();
for (int i = 0; i < this.addresses.length; i++) {
for (int j = 0; j < 8; j++)
positionsByAddress.put(this.id + "." + i + "." + j, new int[] { i, j });
positionsByAddress.put(this.id + "." + i + "." + j, new int[]{i, j});
}
this.positionsByAddress = Collections.unmodifiableMap(positionsByAddress);
this.interruptResistance = PinPullResistance.valueOf((String) parameters.get("interruptPinPullResistance"));
this.interruptBcmPinAddress = (Integer) parameters.get("interruptBcmPinAddress");
this.interruptChangeState = PinState.valueOf((String) parameters.get("interruptChangeState"));
this.enableInterruptFix =
parameters.containsKey("enableInterruptFix") && (Boolean) parameters.get("enableInterruptFix");
this.enableInterruptFix = parameters.containsKey("enableInterruptFix") && (Boolean) parameters.get(
"enableInterruptFix");
logger.info(
"Configured " + this.id + " as PCF8574 Input on I2C addresses 0x " + toPrettyHexString(this.addresses)
+ " on BCM Pin interrupt trigger " + this.interruptBcmPinAddress);
logger.info("Configured {} as PCF8574 Input on I2C addresses 0x {} on BCM Pin interrupt trigger {}", this.id,
toPrettyHexString(this.addresses), this.interruptBcmPinAddress);
if (this.verbose)
logger.info("Verbose enabled for connection " + this.id);
logger.info("Verbose enabled for connection {}", this.id);
}
@Override
public boolean connect() {
if (this.simulated) {
logger.warn(this.id + ": Running SIMULATED, NOT CONNECTING!");
logger.warn("{}: Running SIMULATED, NOT CONNECTING!", this.id);
return super.connect();
}
if (isConnected()) {
logger.warn(this.id + ": Already connected");
logger.warn("{}: Already connected", this.id);
return true;
}
logger.info(this.id + ": Connecting...");
logger.info("{}: Connecting...", this.id);
// initialize
try {
@ -119,8 +118,8 @@ public class PCF8574InputConnection extends SimplePlcConnection {
this.inputDevices = new I2CDevice[this.addresses.length];
for (int i = 0; i < this.addresses.length; i++) {
this.inputDevices[i] = i2cBus.getDevice(this.addresses[i]);
logger.info("Connected to I2C Device " + this.id + " at 0x" + toHexString(this.addresses[i])
+ " on I2C Bus " + this.i2cBusNr);
logger.info("Connected to I2C Device {} at 0x{} on I2C Bus {}", this.id, toHexString(this.addresses[i]),
this.i2cBusNr);
}
} catch (Throwable e) {
@ -132,8 +131,9 @@ public class PCF8574InputConnection extends SimplePlcConnection {
boolean ok = readInitialState();
if (!ok) {
handleBrokenConnection("Failed to read initial values from I2C Bus " + this.i2cBusNr + " and addresses 0x "
+ toPrettyHexString(this.addresses), null);
handleBrokenConnection(
format("Failed to read initial values from I2C Bus {0} and addresses 0x {1}", this.i2cBusNr,
toPrettyHexString(this.addresses)), null);
}
// register interrupt listener
@ -148,15 +148,17 @@ public class PCF8574InputConnection extends SimplePlcConnection {
if (gpioController.getProvisionedPins().stream().map(GpioPin::getPin).anyMatch(interruptPin::equals))
throw new IllegalStateException("Pin " + interruptPin + " is already provisioned!");
this.interruptGpioPin = gpioController.provisionDigitalInputPin(interruptPin, this.interruptResistance);
logger.info("Provisioned GPIO Input pin " + this.interruptGpioPin + " with PinPullResistance "
+ this.interruptResistance);
logger.info("Provisioned GPIO Input pin {} with PinPullResistance {}", this.interruptGpioPin,
this.interruptResistance);
this.interruptGpioPin.removeAllListeners();
this.interruptGpioPin.addListener((GpioPinListenerDigital) this::handleInterrupt);
logger.info("Registered GPIO interrupt handler for BCM " + interruptPin);
logger.info("Registered GPIO interrupt handler for BCM {}", interruptPin);
if (this.enableInterruptFix) {
this.interruptFixTask = this.plc.getExecutorPool().getScheduledExecutor("InterruptFix")
this.interruptFixTask = this.plc
.getExecutorPool()
.getScheduledExecutor("InterruptFix")
.scheduleWithFixedDelay(this::checkInterruptPin, 1, 1, TimeUnit.SECONDS);
logger.info("Enabled Interrupt Fix Task.");
}
@ -164,8 +166,9 @@ public class PCF8574InputConnection extends SimplePlcConnection {
return ok && super.connect();
} catch (Throwable e) {
handleBrokenConnection("Failed to register GPIO listener for BCM pin " + this.interruptBcmPinAddress + ": "
+ getExceptionMessageWithCauses(e), e);
handleBrokenConnection(
format("Failed to register GPIO listener for BCM pin {0}: {1}", this.interruptBcmPinAddress,
getExceptionMessageWithCauses(e)), e);
return false;
}
@ -175,7 +178,7 @@ public class PCF8574InputConnection extends SimplePlcConnection {
public void disconnect() {
if (this.simulated) {
super.disconnect();
logger.warn(this.id + ": Running SIMULATED, NOT CONNECTING!");
logger.warn("{}: Running SIMULATED, NOT CONNECTING!", this.id);
return;
}
@ -186,9 +189,9 @@ public class PCF8574InputConnection extends SimplePlcConnection {
try {
this.interruptGpioPin.removeAllListeners();
PlcGpioController.getInstance().unprovisionPin(this.interruptGpioPin);
logger.info("Provisioned GPIO Input pin " + this.interruptGpioPin);
logger.info("Provisioned GPIO Input pin {}", this.interruptGpioPin);
} catch (Exception e) {
logger.error("Failed to unprovision pin " + this.interruptGpioPin, e);
logger.error("Failed to unprovision pin {}", this.interruptGpioPin, e);
}
}
@ -207,8 +210,9 @@ public class PCF8574InputConnection extends SimplePlcConnection {
if ((this.interruptChangeState == PinState.HIGH && currentState == HIGH) //
|| (this.interruptChangeState == PinState.LOW && currentState == LOW)) {
logger.error("Missed interrupt for pin " + this.interruptGpioPin + " as current state is " + currentState
+ " and expected change state is " + this.interruptChangeState + ", forcing update...");
logger.error(
"Missed interrupt for pin {} as current state is {} and expected change state is {}, forcing update...",
this.interruptGpioPin, currentState, this.interruptChangeState);
try {
handleNewState("interruptFix");
@ -217,13 +221,13 @@ public class PCF8574InputConnection extends SimplePlcConnection {
}
this.interruptFixes++;
logger.error("Performed " + this.interruptFixes + " interrupt fixes.");
logger.error("Performed {} interrupt fixes.", this.interruptFixes);
}
}
private void handleInterrupt(GpioPinDigitalStateChangeEvent event) {
if (this.verbose)
logger.info(event.getPin() + " " + event.getState() + " " + event.getEdge());
logger.info("{} {} {}", event.getPin(), event.getState(), event.getEdge());
try {
if (event.getState() == this.interruptChangeState)
@ -238,16 +242,15 @@ public class PCF8574InputConnection extends SimplePlcConnection {
for (int i = 0; i < this.inputDevices.length; i++) {
I2CDevice i2CDevice = this.inputDevices[i];
if (i2CDevice == null) {
logger.warn("Ignoring invalid I2C Device 0x" + toHexString(this.addresses[i]) + " " + ctx);
logger.warn("Ignoring invalid I2C Device 0x{} {}", toHexString(this.addresses[i]), ctx);
continue;
}
byte data = (byte) i2CDevice.read();
if (this.verbose)
logger.info(
this.id + " at 0x" + toHexString((byte) i2CDevice.getAddress()) + " has new state " + asBinary(
data) + " " + ctx);
logger.info("{} at 0x{} has new state {} {}", this.id, toHexString((byte) i2CDevice.getAddress()),
asBinary(data), ctx);
for (int j = 0; j < 8; j++) {
boolean newState = isBitSet(data, j);
@ -257,9 +260,8 @@ public class PCF8574InputConnection extends SimplePlcConnection {
if (this.states[i][j] != newState) {
this.states[i][j] = newState;
String address = this.id + "." + i + "." + j;
logger.info("Detected " + address + " = " + (newState ? 1 : 0) + (this.inverted ?
" (inverted) " :
" (normal) ") + asBinary(data) + " " + ctx);
logger.info("Detected {} = {}{}{} {}", address, newState ? 1 : 0,
this.inverted ? " (inverted) " : " (normal) ", asBinary(data), ctx);
this.plc.queueNotify(address, newState);
}
}
@ -278,9 +280,8 @@ public class PCF8574InputConnection extends SimplePlcConnection {
I2CDevice i2CDevice = this.inputDevices[i];
try {
byte data = (byte) i2CDevice.read();
logger.info(
"Initial Value for " + this.id + " at 0x" + toHexString(this.addresses[i]) + " is " + asBinary(
data));
logger.info("Initial Value for {} at 0x{} is {}", this.id, toHexString(this.addresses[i]),
asBinary(data));
this.states[i] = new boolean[8];
for (int j = 0; j < 8; j++) {
@ -295,8 +296,8 @@ public class PCF8574InputConnection extends SimplePlcConnection {
} catch (Exception e) {
ok = false;
this.inputDevices[i] = null;
logger.error("Failed to read initial state for " + this.id + " at 0x" + toHexString(
(byte) i2CDevice.getAddress()), e);
logger.error("Failed to read initial state for {} at 0x{}", this.id,
toHexString((byte) i2CDevice.getAddress()), e);
}
}

View File

@ -40,17 +40,17 @@ public class PCF8574OutputConnection extends Multi8BitI2cOutputConnection {
this.states[index] = (byte) 0xff;
try {
i2cDev.write(this.states[index]);
logger.info(this.id + ": set initial value to " + asBinary((byte) 0xff) + " for " + getDescription(
address));
logger.info("{}: set initial value to {} for {}", this.id, asBinary((byte) 0xff),
getDescription(address));
} catch (Exception e) {
ok = false;
logger.error(this.id + ": Failed to set initial value to " + asBinary((byte) 0xff) + " for "
+ getDescription(address), e);
logger.error("{}: Failed to set initial value to {} for {}", this.id, asBinary((byte) 0xff),
getDescription(address), e);
}
} else {
this.states[index] = (byte) i2cDev.read();
logger.info(
this.id + ": Initial value is " + asBinary(this.states[index]) + " for " + getDescription(address));
logger.info("{}: Initial value is {} for {}", this.id, asBinary(this.states[index]),
getDescription(address));
}
return ok;
@ -64,8 +64,7 @@ public class PCF8574OutputConnection extends Multi8BitI2cOutputConnection {
else
newState = setBit(this.states[device], pin);
logger.info("Setting " + this.id + "." + device + "." + pin + " = " + (high ? 0 : 1) + " (" + asBinary(newState)
+ ")");
logger.info("Setting {}.{}.{} = {} ({})", this.id, device, pin, high ? 0 : 1, asBinary(newState));
outputDevice.write(newState);
this.states[device] = newState;

View File

@ -1,13 +1,5 @@
package li.strolch.plc.core.hw.i2c;
import static li.strolch.plc.model.PlcConstants.PARAM_SIMULATED;
import static li.strolch.utils.helper.ExceptionHelper.getExceptionMessageWithCauses;
import static li.strolch.utils.helper.StringHelper.toHexString;
import java.io.IOException;
import java.util.*;
import java.util.concurrent.Callable;
import com.pi4j.io.i2c.I2CFactory;
import com.pi4j.io.i2c.impl.I2CBusImpl;
import li.strolch.plc.core.hw.Plc;
@ -15,6 +7,15 @@ import li.strolch.plc.core.hw.connections.SimplePlcConnection;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.IOException;
import java.util.*;
import java.util.concurrent.Callable;
import static java.text.MessageFormat.format;
import static li.strolch.plc.model.PlcConstants.PARAM_SIMULATED;
import static li.strolch.utils.helper.ExceptionHelper.getExceptionMessageWithCauses;
import static li.strolch.utils.helper.StringHelper.toHexString;
public class RSL366OverHorterI2c extends SimplePlcConnection {
// https://www.horter.de/doku/i2c-hs-433MHz_Beschreibung.pdf
@ -84,11 +85,11 @@ public class RSL366OverHorterI2c extends SimplePlcConnection {
Map<String, byte[]> positionsByAddress = new HashMap<>();
for (byte i = 1; i < 5; i++) {
for (byte j = 1; j < 5; j++)
positionsByAddress.put(this.id + "." + i + "." + j, new byte[] { i, j });
positionsByAddress.put(this.id + "." + i + "." + j, new byte[]{i, j});
}
this.positionsByAddress = Collections.unmodifiableMap(positionsByAddress);
logger.info("Configured RSL366 over Horter I2c on address 0x" + toHexString(this.address));
logger.info("Configured RSL366 over Horter I2c on address 0x{}", toHexString(this.address));
}
public <T> T runBusLockedDeviceAction(final Callable<T> action) throws IOException {
@ -98,16 +99,16 @@ public class RSL366OverHorterI2c extends SimplePlcConnection {
@Override
public synchronized boolean connect() {
if (this.simulated) {
logger.warn(this.id + ": Running SIMULATED, NOT CONNECTING!");
logger.warn("{}: Running SIMULATED, NOT CONNECTING!", this.id);
return super.connect();
}
if (isConnected()) {
logger.warn(this.id + ": Already connected");
logger.warn("{}: Already connected", this.id);
return true;
}
logger.info(this.id + ": Connecting...");
logger.info("{}: Connecting...", this.id);
try {
if (this.i2cBus == null) {
@ -119,18 +120,18 @@ public class RSL366OverHorterI2c extends SimplePlcConnection {
byte[] status = runBusLockedDeviceAction(this::configure);
String version = status[ADDR_INFO_VER_MAJOR] + "." + status[ADDR_INFO_VER_MINOR];
logger.info("Connected to 433MHz RSL366 over HorterI2C version " + version + " supporting "
+ status[ADDR_INFO_NR_OF_KNOWN_PROTOCOLS] + " protocols");
logger.info("Connected to 433MHz RSL366 over HorterI2C version {} supporting {} protocols", version,
status[ADDR_INFO_NR_OF_KNOWN_PROTOCOLS]);
logger.info("Connected to I2C device at address 0x" + toHexString(this.address) + " on I2C Bus "
+ this.i2cBusNr);
logger.info("Connected to I2C device at address 0x{} on I2C Bus {}", toHexString(this.address),
this.i2cBusNr);
return super.connect();
} catch (Throwable e) {
handleBrokenConnection(
"Failed to connect to 433MHz RSL366 over HorterI2C at address 0x" + toHexString(this.address)
+ " on I2C Bus " + this.i2cBusNr + ": " + getExceptionMessageWithCauses(e), e);
format("Failed to connect to 433MHz RSL366 over HorterI2C at address 0x{0} on I2C Bus {1}: {2}",
toHexString(this.address), this.i2cBusNr, getExceptionMessageWithCauses(e)), e);
return false;
}
@ -144,7 +145,7 @@ public class RSL366OverHorterI2c extends SimplePlcConnection {
@Override
public synchronized void send(String address, Object value) {
if (this.simulated) {
logger.warn(this.id + ": Running SIMULATED, NOT CONNECTING!");
logger.warn("{}: Running SIMULATED, NOT CONNECTING!", this.id);
return;
}
@ -165,8 +166,8 @@ public class RSL366OverHorterI2c extends SimplePlcConnection {
} catch (Exception e) {
if (e instanceof IllegalStateException)
throw (IllegalStateException) e;
String msg = "Failed to send " + (on ? "on" : "off") + " to system " + system + " device " + device
+ " at address 0x" + toHexString(this.address) + " on I2C Bus " + this.i2cBusNr;
String msg = format("Failed to send {0} to system {1} device {2} at address 0x{3} on I2C Bus {4}",
on ? "on" : "off", system, device, toHexString(this.address), this.i2cBusNr);
handleBrokenConnection(msg + ": " + getExceptionMessageWithCauses(e), e);
throw new IllegalStateException(msg, e);
}
@ -175,7 +176,7 @@ public class RSL366OverHorterI2c extends SimplePlcConnection {
private byte[] configure() throws IOException, InterruptedException {
logger.info("Configuring...");
byte[] data = { CONF_PROTOCOL, repeats };
byte[] data = {CONF_PROTOCOL, repeats};
this.dev.write(this.verbose, ADDR_REG_CONF_CODE, data);
Thread.sleep(20L);
@ -191,14 +192,14 @@ public class RSL366OverHorterI2c extends SimplePlcConnection {
if (status[ADDR_INFO_REPEATS] != repeats)
throw new IllegalStateException("Repeats could not bet set to " + repeats);
logger.info("Configured with protocol " + CONF_PROTOCOL + " and " + repeats + " repeats.");
logger.info("Configured with protocol " + CONF_PROTOCOL + " and {} repeats.", repeats);
return status;
}
private void setState(byte system, byte device, boolean state) throws Exception {
logger.info("System: " + toHexString(system));
logger.info("Device: " + toHexString(device));
logger.info("System: {}", toHexString(system));
logger.info("Device: {}", toHexString(device));
byte[] status = readInfo(false);
if (isDeviceTransmitting(status)) {
@ -233,8 +234,7 @@ public class RSL366OverHorterI2c extends SimplePlcConnection {
}
showInfoRegister(status);
logger.info("Successfully sent state change to " + (state ? "on" : "off") + " for device " + system + ", "
+ device);
logger.info("Successfully sent state change to {} for device {}, {}", state ? "on" : "off", system, device);
}
private void waitForDeviceIdle() throws Exception {
@ -269,12 +269,12 @@ public class RSL366OverHorterI2c extends SimplePlcConnection {
}
private static void showInfoRegister(byte[] status) {
logger.info(" Pointer : " + toHexString(status[ADDR_INFO_PTR]));
logger.info(" Status : " + toHexString(status[ADDR_INFO_STATUS]) + " " + parseStatus(
status[ADDR_INFO_STATUS]));
logger.info(" TX : " + toHexString(status[ADDR_INFO_TRANSMITTING]));
logger.info(" Protocol : " + toHexString(status[ADDR_INFO_PROTOCOL]));
logger.info(" Repeats : " + toHexString(status[ADDR_INFO_REPEATS]));
logger.info(" Pointer : {}", toHexString(status[ADDR_INFO_PTR]));
logger.info(" Status : {} {}", toHexString(status[ADDR_INFO_STATUS]),
parseStatus(status[ADDR_INFO_STATUS]));
logger.info(" TX : {}", toHexString(status[ADDR_INFO_TRANSMITTING]));
logger.info(" Protocol : {}", toHexString(status[ADDR_INFO_PROTOCOL]));
logger.info(" Repeats : {}", toHexString(status[ADDR_INFO_REPEATS]));
}
private static boolean isDeviceTransmitting(byte[] status) {

View File

@ -1,13 +1,13 @@
package li.strolch.plc.core.hw.i2c;
import static li.strolch.utils.helper.ByteHelper.*;
import static li.strolch.utils.helper.StringHelper.toHexString;
import java.io.IOException;
import com.pi4j.io.i2c.I2CDevice;
import li.strolch.plc.core.hw.Plc;
import java.io.IOException;
import static li.strolch.utils.helper.ByteHelper.*;
import static li.strolch.utils.helper.StringHelper.toHexString;
public class TCA9534OutputConnection extends Multi8BitI2cOutputConnection {
private static final byte TCA9534_REG_ADDR_OUT_PORT = 0x01;
@ -44,8 +44,8 @@ public class TCA9534OutputConnection extends Multi8BitI2cOutputConnection {
"Failed to read configuration from address 0x" + toHexString(TCA9534_REG_ADDR_CFG));
if (config != 0x00) {
logger.warn(getDescription(address) + " is not configured as OUTPUT, setting register 0x" + toHexString(
TCA9534_REG_ADDR_CFG) + " to 0x00");
logger.warn("{} is not configured as OUTPUT, setting register 0x{} to 0x00", getDescription(address),
toHexString(TCA9534_REG_ADDR_CFG));
i2cDev.write(TCA9534_REG_ADDR_OUT_PORT, (byte) 0x00);
i2cDev.write(TCA9534_REG_ADDR_CFG, (byte) 0x00);
}
@ -56,11 +56,10 @@ public class TCA9534OutputConnection extends Multi8BitI2cOutputConnection {
this.states[index] = (byte) 0x00;
try {
i2cDev.write(TCA9534_REG_ADDR_OUT_PORT, this.states[index]);
logger.info("Set initial value to " + asBinary((byte) 0x00) + " for " + getDescription(address));
logger.info("Set initial value to {} for {}", asBinary((byte) 0x00), getDescription(address));
} catch (Exception e) {
ok = false;
logger.error(
"Failed to set initial value to " + asBinary((byte) 0x00) + " for " + getDescription(address),
logger.error("Failed to set initial value to {} for {}", asBinary((byte) 0x00), getDescription(address),
e);
}
} else {
@ -70,7 +69,7 @@ public class TCA9534OutputConnection extends Multi8BitI2cOutputConnection {
currentState = reverse(currentState);
this.states[index] = currentState;
logger.info("Initial value is " + asBinary(this.states[index]) + " for " + getDescription(address));
logger.info("Initial value is {} for {}", asBinary(this.states[index]), getDescription(address));
}
return ok;
@ -87,8 +86,8 @@ public class TCA9534OutputConnection extends Multi8BitI2cOutputConnection {
byte writeState = this.reversed ? reverse(newState) : newState;
if (this.verbose)
logger.info("Setting " + getDescription((byte) outputDevice.getAddress()) + " to new state " + asBinary(
writeState));
logger.info("Setting {} to new state {}", getDescription((byte) outputDevice.getAddress()),
asBinary(writeState));
outputDevice.write(TCA9534_REG_ADDR_OUT_PORT, writeState);
this.states[device] = newState;

View File

@ -36,10 +36,10 @@ public class SendPlcAddressActionService extends AbstractService<JsonServiceArgu
if (jsonObject.has(PARAM_VALUE)) {
String valueS = jsonObject.get(PARAM_VALUE).getAsString();
Object value = plcAddress.valueType.parseValue(valueS);
logger.info("PLC Send " + resource + "-" + action + " with " + valueS);
logger.info("PLC Send {}-{} with {}", resource, action, valueS);
plcHandler.send(resource, action, value);
} else {
logger.info("PLC Send " + resource + "-" + action + " with default value " + plcAddress.defaultValue);
logger.info("PLC Send {}-{} with default value {}", resource, action, plcAddress.defaultValue);
plcHandler.send(resource, action);
}
} else if (addressType == PlcAddressType.Notification) {
@ -49,7 +49,7 @@ public class SendPlcAddressActionService extends AbstractService<JsonServiceArgu
String valueS = jsonObject.get(PARAM_VALUE).getAsString();
Object value = plcAddress.valueType.parseValue(valueS);
logger.info("PLC Notification " + resource + "-" + action + " with " + valueS);
logger.info("PLC Notification {}-{} with {}", resource, action, valueS);
plcHandler.notify(resource, action, value);
} else {

View File

@ -30,24 +30,23 @@ public class SetPlcStateService extends AbstractService<StringMapArgument, Servi
PlcServiceInitializer plcServiceInitializer = getComponent(PlcServiceInitializer.class);
switch (newState) {
case Stopped:
if (plcHandler.getPlcState() == PlcState.Stopped)
return ServiceResult.error("Already stopped");
plcServiceInitializer.stop();
plcHandler.stopPlc();
break;
case Started:
if (plcHandler.getPlcState() == PlcState.Started)
return ServiceResult.error("Already started");
plcHandler.startPlc();
plcServiceInitializer.start();
break;
case Configured:
if (!plcHandler.reconfigurePlc())
return ServiceResult.error(plcHandler.getPlcStateMsg());
break;
default:
throw new IllegalArgumentException("Can not switch to state " + newState);
case Stopped -> {
if (plcHandler.getPlcState() == PlcState.Stopped)
return ServiceResult.error("Already stopped");
plcServiceInitializer.stop();
plcHandler.stopPlc();
}
case Started -> {
if (plcHandler.getPlcState() == PlcState.Started)
return ServiceResult.error("Already started");
plcHandler.startPlc();
plcServiceInitializer.start();
}
case Configured -> {
if (!plcHandler.reconfigurePlc())
return ServiceResult.error(plcHandler.getPlcStateMsg());
}
default -> throw new IllegalArgumentException("Can not switch to state " + newState);
}
return ServiceResult.success();

View File

@ -30,9 +30,9 @@ public class ExamplePlcConveyorPlcService extends PlcService {
private AtomicBoolean conveyor3On;
private AtomicBoolean conveyor4On;
private AtomicBoolean conveyor1WaitingForTransfer;
private AtomicBoolean conveyor2WaitingForTransfer;
private AtomicBoolean conveyor3WaitingForTransfer;
private final AtomicBoolean conveyor1WaitingForTransfer;
private final AtomicBoolean conveyor2WaitingForTransfer;
private final AtomicBoolean conveyor3WaitingForTransfer;
public ExamplePlcConveyorPlcService(PlcHandler plcHandler) {
super(plcHandler);
@ -50,62 +50,54 @@ public class ExamplePlcConveyorPlcService extends PlcService {
boolean state = (boolean) value;
switch (resource) {
case R_CONVEYOR_01 -> {
case R_CONVEYOR_01:
if (action.equals(A_OCCUPIED)) {
conveyor1Occupied.set(state);
handleTransfer(null, R_CONVEYOR_01, R_CONVEYOR_02, //
null, conveyor1Occupied, conveyor2Occupied, //
null, conveyor1On, conveyor2On, //
null, conveyor1WaitingForTransfer);
} else {
logger.error("Unhandled action " + resource + "-" + action);
if (action.equals(A_OCCUPIED)) {
conveyor1Occupied.set(state);
handleTransfer(null, R_CONVEYOR_01, R_CONVEYOR_02, //
null, conveyor1Occupied, conveyor2Occupied, //
null, conveyor1On, conveyor2On, //
null, conveyor1WaitingForTransfer);
} else {
logger.error("Unhandled action {}-{}", resource, action);
}
}
case R_CONVEYOR_02 -> {
break;
case R_CONVEYOR_02:
if (action.equals(A_OCCUPIED)) {
conveyor2Occupied.set(state);
handleTransfer(R_CONVEYOR_01, R_CONVEYOR_02, R_CONVEYOR_03, //
conveyor1Occupied, conveyor2Occupied, conveyor3Occupied, //
conveyor1On, conveyor2On, conveyor3On, //
conveyor1WaitingForTransfer, conveyor2WaitingForTransfer);
} else {
logger.error("Unhandled action " + resource + "-" + action);
if (action.equals(A_OCCUPIED)) {
conveyor2Occupied.set(state);
handleTransfer(R_CONVEYOR_01, R_CONVEYOR_02, R_CONVEYOR_03, //
conveyor1Occupied, conveyor2Occupied, conveyor3Occupied, //
conveyor1On, conveyor2On, conveyor3On, //
conveyor1WaitingForTransfer, conveyor2WaitingForTransfer);
} else {
logger.error("Unhandled action {}-{}", resource, action);
}
}
case R_CONVEYOR_03 -> {
break;
case R_CONVEYOR_03:
if (action.equals(A_OCCUPIED)) {
conveyor3Occupied.set(state);
handleTransfer(R_CONVEYOR_02, R_CONVEYOR_03, R_CONVEYOR_04, //
conveyor2Occupied, conveyor3Occupied, conveyor4Occupied, //
conveyor2On, conveyor3On, conveyor4On, //
conveyor2WaitingForTransfer, conveyor3WaitingForTransfer);
} else {
logger.error("Unhandled action " + resource + "-" + action);
if (action.equals(A_OCCUPIED)) {
conveyor3Occupied.set(state);
handleTransfer(R_CONVEYOR_02, R_CONVEYOR_03, R_CONVEYOR_04, //
conveyor2Occupied, conveyor3Occupied, conveyor4Occupied, //
conveyor2On, conveyor3On, conveyor4On, //
conveyor2WaitingForTransfer, conveyor3WaitingForTransfer);
} else {
logger.error("Unhandled action {}-{}", resource, action);
}
}
case R_CONVEYOR_04 -> {
break;
case R_CONVEYOR_04:
if (action.equals(A_OCCUPIED)) {
conveyor4Occupied.set(state);
handleTransfer(R_CONVEYOR_03, R_CONVEYOR_04, null, //
conveyor3Occupied, conveyor4Occupied, null, //
conveyor3On, conveyor4On, null, //
conveyor3WaitingForTransfer, null);
} else {
logger.error("Unhandled action " + resource + "-" + action);
if (action.equals(A_OCCUPIED)) {
conveyor4Occupied.set(state);
handleTransfer(R_CONVEYOR_03, R_CONVEYOR_04, null, //
conveyor3Occupied, conveyor4Occupied, null, //
conveyor3On, conveyor4On, null, //
conveyor3WaitingForTransfer, null);
} else {
logger.error("Unhandled action {}-{}", resource, action);
}
}
break;
}
}
@ -119,37 +111,37 @@ public class ExamplePlcConveyorPlcService extends PlcService {
// handle current conveyor is now occupied
if (next == null) {
if (currentOn.get()) {
logger.info(current + " is now occupied without a next conveyor, stopping conveyor");
logger.info("{} is now occupied without a next conveyor, stopping conveyor", current);
send(current, A_MOTOR_OFF);
currentOn.set(false);
} else {
logger.info(current + " is now occupied, conveyor is off and no next conveyor: transfer complete.");
logger.info("{} is now occupied, conveyor is off and no next conveyor: transfer complete.",
current);
}
return;
}
if (nextOccupied.get()) {
logger.info(current + " is now occupied, next conveyor " + next + " is still occupied, so waiting...");
logger.info("{} is now occupied, next conveyor {} is still occupied, so waiting...", current, next);
if (currentWaitingForTransfer.get())
logger.error("What the hell, current " + current + " is already waiting for a transfer!");
logger.error("What the hell, current {} is already waiting for a transfer!", current);
currentWaitingForTransfer.set(true);
} else {
logger.info(
current + " is now occupied, next conveyor " + next + " is not occupied, so transferring...");
logger.info("{} is now occupied, next conveyor {} is not occupied, so transferring...", current, next);
if (nextOn.get()) {
logger.info("Next conveyor " + next + " is already running, waiting for transfer to complete...");
logger.info("Next conveyor {} is already running, waiting for transfer to complete...", next);
} else {
logger.info("Starting " + next + " and waiting for transfer to complete...");
logger.info("Starting {} and waiting for transfer to complete...", next);
send(next, A_MOTOR_ON);
nextOn.set(true);
}
if (currentOn.get()) {
logger.info(current + " is already running, waiting for transfer to complete...");
logger.info("{} is already running, waiting for transfer to complete...", current);
} else {
logger.info("Starting " + current + " and waiting for transfer to complete...");
logger.info("Starting {} and waiting for transfer to complete...", current);
send(current, A_MOTOR_ON);
currentOn.set(true);
}
@ -165,11 +157,11 @@ public class ExamplePlcConveyorPlcService extends PlcService {
// no previous conveyor, so just stop current, if still on
if (currentOn.get()) {
logger.info(current + " is now unoccupied, stopping conveyor");
logger.info("{} is now unoccupied, stopping conveyor", current);
send(current, A_MOTOR_OFF);
currentOn.set(false);
} else {
logger.info(current + " is now unoccupied, conveyor is already off");
logger.info("{} is now unoccupied, conveyor is already off", current);
}
return;
@ -178,16 +170,18 @@ public class ExamplePlcConveyorPlcService extends PlcService {
// handle transfer of previous to current
if (!previousOccupied.get()) {
logger.info(previous + " is not occupied, so no transfer required.");
logger.info("{} is not occupied, so no transfer required.", previous);
if (currentOn.get()) {
logger.info(current + " is now unoccupied and previous " + previous
+ " is not occupied, so no transfer required: Stopping conveyor");
logger.info(
"{} is now unoccupied and previous {} is not occupied, so no transfer required: Stopping conveyor",
current, previous);
send(current, A_MOTOR_OFF);
currentOn.set(false);
} else {
logger.info(current + " is now unoccupied and previous " + previous
+ " is not occupied, and conveyor not running. Nothing else to do");
logger.info(
"{} is now unoccupied and previous {} is not occupied, and conveyor not running. Nothing else to do",
current, previous);
}
return;
@ -195,23 +189,23 @@ public class ExamplePlcConveyorPlcService extends PlcService {
// previous is occupied, so transfer to current, but only if previous was waiting
if (!previousWaitingForTransfer.get()) {
logger.info(previous + " conveyor is not waiting for a transfer. Nothing else to do.");
logger.info("{} conveyor is not waiting for a transfer. Nothing else to do.", previous);
} else {
logger.info(previous + " conveyor is waiting for a transfer, so starting transfer");
logger.info("{} conveyor is waiting for a transfer, so starting transfer", previous);
if (currentOn.get()) {
logger.info(current + " is already on, waiting for transfer...");
logger.info("{} is already on, waiting for transfer...", current);
} else {
logger.info("Turning " + current + " on for transfer");
logger.info("Turning {} on for transfer", current);
send(current, A_MOTOR_ON);
currentOn.set(true);
}
if (previousOn.get()) {
logger.info(previous + " is already on, waiting for transfer...");
logger.info("{} is already on, waiting for transfer...", previous);
} else {
logger.info("Turning " + previous + " on for transfer");
logger.info("Turning {} on for transfer", previous);
send(previous, A_MOTOR_ON);
previousOn.set(true);
}

View File

@ -90,11 +90,11 @@ public class PlcHandlerTest {
assertFalse(value.get());
plcHandler.register("PLC", "Running", (address, v) -> {
logger.error("Setting " + address + " to " + v);
logger.error("Setting {} to {}", address, v);
value.set((Boolean) v);
});
plcHandler.register("PLC", "NotRunning", (address, v) -> {
logger.error("Setting " + address + " to " + v);
logger.error("Setting {} to {}", address, v);
value.set((Boolean) v);
});

View File

@ -35,7 +35,7 @@ public class DataLogicScannerConnectionTest {
logger.info("Connecting to scanner...");
scanner.connect();
logger.info("Connected to scanner " + scanner.getId());
logger.info("Connected to scanner {}", scanner.getId());
logger.info("Sending trigger...");
scanner.send("test.trigger", true);
logger.info("Trigger sent.");

View File

@ -1,15 +1,14 @@
package li.strolch.plc.core.hw.i2c;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.text.MessageFormat;
import com.pi4j.io.i2c.I2CBus;
import com.pi4j.io.i2c.I2CDevice;
import com.pi4j.io.i2c.I2CFactory;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.nio.charset.StandardCharsets;
/**
* <p>Compile:</p>
* <code>javac -cp pi4j-core-1.4-SNAPSHOT.jar:. RSL366OverHorterI2cTest.java</code>
@ -51,7 +50,7 @@ public class RSL366OverHorterI2cTest {
static final byte STATUS_BAD_PTR = 0x08;
static final byte STATUS_CONF_TOO_MUCH_DATA = 0x09;
static byte[] systemValues = new byte[] { 0, 0, 0, 0 };
static byte[] systemValues = new byte[]{0, 0, 0, 0};
static byte system;
static byte device;
@ -70,8 +69,11 @@ public class RSL366OverHorterI2cTest {
byte[] status = configure();
String version = status[ADDR_INFO_VER_MAJOR] + "." + status[ADDR_INFO_VER_MINOR];
System.out.println("Connected to Horter I2C to 433MHz version " + version + " supporting "
+ status[ADDR_INFO_NR_OF_KNOWN_PROTOCOLS] + " 433MHz protocols");
System.out.println("Connected to Horter I2C to 433MHz version "
+ version
+ " supporting "
+ status[ADDR_INFO_NR_OF_KNOWN_PROTOCOLS]
+ " 433MHz protocols");
System.out.println();
readCodes(input);
@ -86,21 +88,11 @@ public class RSL366OverHorterI2cTest {
String action = input.readLine();
switch (action) {
case "o":
setState(system, device, true);
break;
case "f":
setState(system, device, false);
break;
case "c":
configure();
break;
case "e":
readCodes(input);
break;
case "x":
run = false;
break;
case "o" -> setState(system, device, true);
case "f" -> setState(system, device, false);
case "c" -> configure();
case "e" -> readCodes(input);
case "x" -> run = false;
}
} catch (Exception e) {
@ -116,7 +108,7 @@ public class RSL366OverHorterI2cTest {
byte protocol = 2;
byte repeats = 1;
System.out.println("Configuring...");
byte[] data = { protocol, repeats };
byte[] data = {protocol, repeats};
System.out.println("=> " + toHexString(ADDR_REG_CONF_CODE) + " " + toHexString(data));
dev.write(ADDR_REG_CONF_CODE, data);
Thread.sleep(50L);
@ -164,14 +156,19 @@ public class RSL366OverHorterI2cTest {
throw new IllegalStateException(
"DeviceCode is invalid after sending deviceCode: " + parseStatus(status[ADDR_INFO_STATUS]));
if (!isDeviceTransmitting(status))
throw new IllegalStateException(
"Device is not transmitting after sending " + toHexString(system) + "." + toHexString(value)
+ "...");
throw new IllegalStateException("Device is not transmitting after sending "
+ toHexString(system)
+ "."
+ toHexString(value)
+ "...");
showInfoRegister(status);
System.out.println(
"Successfully sent state change to " + (state ? "on" : "off") + " for device " + system + ", "
+ device);
System.out.println("Successfully sent state change to "
+ (state ? "on" : "off")
+ " for device "
+ system
+ ", "
+ device);
}
private static void waitForDeviceIdle() throws Exception {
@ -229,30 +226,19 @@ public class RSL366OverHorterI2cTest {
}
private static String parseStatus(byte status) {
switch (status) {
case STATUS_OK:
return "OK";
case STATUS_SYS_TOO_MUCH_DATA:
return "Too much SystemCode data";
case STATUS_SYS_MISSING_DATA:
return "SystemCode missing data";
case STATUS_SYS_INVALID_DATA:
return "Invalid SystemCode";
case STATUS_SYS_MISSING:
return "SystemCode Missing";
case STATUS_DEV_TOO_MUCH_DATA:
return "Too much device data";
case STATUS_DEV_INVALID_DATA:
return "DeviceCode invalid";
case STATUS_PROTO_UNKNOWN:
return "Invalid protocol";
case STATUS_BAD_PTR:
return "Bad pointer";
case STATUS_CONF_TOO_MUCH_DATA:
return "Too much config data";
default:
return "Unknown status " + toHexString(status);
}
return switch (status) {
case STATUS_OK -> "OK";
case STATUS_SYS_TOO_MUCH_DATA -> "Too much SystemCode data";
case STATUS_SYS_MISSING_DATA -> "SystemCode missing data";
case STATUS_SYS_INVALID_DATA -> "Invalid SystemCode";
case STATUS_SYS_MISSING -> "SystemCode Missing";
case STATUS_DEV_TOO_MUCH_DATA -> "Too much device data";
case STATUS_DEV_INVALID_DATA -> "DeviceCode invalid";
case STATUS_PROTO_UNKNOWN -> "Invalid protocol";
case STATUS_BAD_PTR -> "Bad pointer";
case STATUS_CONF_TOO_MUCH_DATA -> "Too much config data";
default -> "Unknown status " + toHexString(status);
};
}
private static void readCodes(BufferedReader input) {
@ -288,44 +274,25 @@ public class RSL366OverHorterI2cTest {
}
public static String toHexString(byte[] raw, int offset, int length) throws RuntimeException {
try {
byte[] hex = new byte[2 * length];
int index = 0;
byte[] hex = new byte[2 * length];
int index = 0;
int pos = offset;
for (int i = 0; i < length; i++) {
byte b = raw[pos];
int v = b & 0xFF;
hex[index++] = HEX_CHAR_TABLE[v >>> 4];
hex[index++] = HEX_CHAR_TABLE[v & 0xF];
pos++;
}
return new String(hex, "ASCII");
} catch (UnsupportedEncodingException e) {
String msg = MessageFormat
.format("Something went wrong while converting to HEX: {0}", e.getMessage());
throw new RuntimeException(msg, e);
int pos = offset;
for (int i = 0; i < length; i++) {
byte b = raw[pos];
int v = b & 0xFF;
hex[index++] = HEX_CHAR_TABLE[v >>> 4];
hex[index++] = HEX_CHAR_TABLE[v & 0xF];
pos++;
}
return new String(hex, StandardCharsets.US_ASCII);
}
private static final byte[] HEX_CHAR_TABLE = { (byte) '0',
(byte) '1',
(byte) '2',
(byte) '3',
(byte) '4',
(byte) '5',
(byte) '6',
(byte) '7',
(byte) '8',
(byte) '9',
(byte) 'a',
(byte) 'b',
(byte) 'c',
(byte) 'd',
(byte) 'e',
(byte) 'f' };
private static final byte[] HEX_CHAR_TABLE = {(byte) '0', (byte) '1', (byte) '2', (byte) '3', (byte) '4',
(byte) '5', (byte) '6', (byte) '7', (byte) '8', (byte) '9', (byte) 'a', (byte) 'b', (byte) 'c', (byte) 'd',
(byte) 'e', (byte) 'f'};
public static String asBinary(byte b) {

View File

@ -1,33 +1,14 @@
package li.strolch.plc.gw.client;
import static java.net.NetworkInterface.getByInetAddress;
import static li.strolch.model.Tags.Json.*;
import static li.strolch.plc.core.DefaultPlcHandler.SILENT_THRESHOLD;
import static li.strolch.plc.model.ModelHelper.valueToJson;
import static li.strolch.plc.model.PlcConstants.*;
import static li.strolch.runtime.StrolchConstants.DEFAULT_REALM;
import static li.strolch.utils.helper.ExceptionHelper.*;
import static li.strolch.utils.helper.NetworkHelper.formatMacAddress;
import static li.strolch.utils.helper.StringHelper.isEmpty;
import java.io.IOException;
import java.net.SocketException;
import java.net.URI;
import java.nio.ByteBuffer;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.concurrent.Future;
import java.util.concurrent.LinkedBlockingDeque;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;
import com.google.gson.JsonArray;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import jakarta.websocket.*;
import jakarta.websocket.CloseReason.CloseCodes;
import li.strolch.agent.api.*;
import li.strolch.agent.api.ComponentContainer;
import li.strolch.agent.api.StrolchComponent;
import li.strolch.agent.api.StrolchRealm;
import li.strolch.agent.api.VersionQueryResult;
import li.strolch.model.Locator;
import li.strolch.model.Resource;
import li.strolch.model.log.LogMessage;
@ -42,6 +23,29 @@ import li.strolch.utils.CheckedRunnable;
import li.strolch.utils.helper.NetworkHelper;
import org.glassfish.tyrus.client.ClientManager;
import java.io.IOException;
import java.net.SocketException;
import java.net.URI;
import java.nio.ByteBuffer;
import java.text.MessageFormat;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.concurrent.Future;
import java.util.concurrent.LinkedBlockingDeque;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;
import static java.net.NetworkInterface.getByInetAddress;
import static li.strolch.model.Tags.Json.*;
import static li.strolch.plc.core.DefaultPlcHandler.SILENT_THRESHOLD;
import static li.strolch.plc.model.ModelHelper.valueToJson;
import static li.strolch.plc.model.PlcConstants.*;
import static li.strolch.runtime.StrolchConstants.DEFAULT_REALM;
import static li.strolch.utils.helper.ExceptionHelper.*;
import static li.strolch.utils.helper.NetworkHelper.formatMacAddress;
import static li.strolch.utils.helper.StringHelper.isEmpty;
public class PlcGwClientHandler extends StrolchComponent implements GlobalPlcListener {
public static final String PLC = "PLC";
@ -142,7 +146,7 @@ public class PlcGwClientHandler extends StrolchComponent implements GlobalPlcLis
try {
this.gwSession.close(new CloseReason(CloseCodes.GOING_AWAY, "Shutting down"));
} catch (Exception e) {
logger.error("Failed to close server session: " + e.getMessage());
logger.error("Failed to close server session: {}", e.getMessage());
}
}
@ -166,7 +170,7 @@ public class PlcGwClientHandler extends StrolchComponent implements GlobalPlcLis
private void connectToServer() {
// connect to Server
logger.info("Connecting to Server at " + this.gwServerUrl + "...");
logger.info("Connecting to Server at {}...", this.gwServerUrl);
try {
this.gwClient = ClientManager.createClient();
this.gwSession = this.gwClient.connectToServer(new PlcGwClientEndpoint(this), new URI(this.gwServerUrl));
@ -178,20 +182,23 @@ public class PlcGwClientHandler extends StrolchComponent implements GlobalPlcLis
}
if (rootCause.getMessage() != null && rootCause.getMessage().contains("Connection refused")) {
logger.error(
"Connection refused to connect to server. Will try to connect again in " + RETRY_DELAY + "s: " +
getExceptionMessageWithCauses(e));
} else if (rootCause.getMessage() != null &&
rootCause.getMessage().contains("Response code was not 101: 404.")) {
logger.error("Connection failed with 404 error code. Is URL " + this.gwServerUrl + " correct?");
logger.error("Connection refused to connect to server. Will try to connect again in "
+ RETRY_DELAY
+ "s: {}", getExceptionMessageWithCauses(e));
} else if (rootCause.getMessage() != null && rootCause
.getMessage()
.contains("Response code was not 101: 404.")) {
logger.error("Connection failed with 404 error code. Is URL {} correct?", this.gwServerUrl);
logger.error("Server not yet ready with 404 error. Will try again in " + RETRY_DELAY + "s");
} else {
logger.error("Failed to connect to server! Will try to connect again in " + RETRY_DELAY + "s", e);
}
closeBrokenGwSessionUpdateState("Failed to connect to server",
"Connection refused to connect to server. Will try to connect again in " + RETRY_DELAY + "s: " +
getExceptionMessageWithCauses(e));
"Connection refused to connect to server. Will try to connect again in "
+ RETRY_DELAY
+ "s: "
+ getExceptionMessageWithCauses(e));
delayConnect(RETRY_DELAY, TimeUnit.SECONDS);
return;
}
@ -225,7 +232,7 @@ public class PlcGwClientHandler extends StrolchComponent implements GlobalPlcLis
return;
}
logger.info(this.gwSession.getId() + ": Connected to Server.");
logger.info("{}: Connected to Server.", this.gwSession.getId());
// schedule the heart beat timer
if (this.serverConnectFuture != null)
@ -250,7 +257,7 @@ public class PlcGwClientHandler extends StrolchComponent implements GlobalPlcLis
}
private void closeGwSession(String msg) {
logger.info("Closing GW session: " + msg);
logger.info("Closing GW session: {}", msg);
this.authenticated = false;
if (this.serverConnectFuture != null)
@ -260,7 +267,7 @@ public class PlcGwClientHandler extends StrolchComponent implements GlobalPlcLis
try {
this.gwSession.close(new CloseReason(CloseCodes.UNEXPECTED_CONDITION, msg));
} catch (Exception e) {
logger.error("Failed to close server session due to " + e.getMessage());
logger.error("Failed to close server session due to {}", e.getMessage());
}
}
@ -284,7 +291,7 @@ public class PlcGwClientHandler extends StrolchComponent implements GlobalPlcLis
private boolean tryPingServer() {
try {
logger.info(this.gwSession.getId() + ": Pinging Server...");
logger.info("{}: Pinging Server...", this.gwSession.getId());
this.gwSession.getBasicRemote().sendPong(ByteBuffer.wrap(this.plcId.getBytes()));
long lastUpdate = System.currentTimeMillis() - this.lastSystemStateNotification;
@ -304,7 +311,7 @@ public class PlcGwClientHandler extends StrolchComponent implements GlobalPlcLis
return false;
} catch (Exception e) {
logger.error("Failed to send Ping to Server, closing server session due to: " + getExceptionMessage(e));
logger.error("Failed to send Ping to Server, closing server session due to: {}", getExceptionMessage(e));
return true;
}
}
@ -326,7 +333,7 @@ public class PlcGwClientHandler extends StrolchComponent implements GlobalPlcLis
sendDataToClient(messageJ);
if (this.verbose)
logger.info("Sent msg " + message.getLocator() + " to server");
logger.info("Sent msg {} to server", message.getLocator());
});
}
@ -342,7 +349,7 @@ public class PlcGwClientHandler extends StrolchComponent implements GlobalPlcLis
sendDataToClient(messageJ);
if (this.verbose)
logger.info("Sent msg " + locator + " to server");
logger.info("Sent disable msg {} to server", locator);
});
}
@ -362,7 +369,7 @@ public class PlcGwClientHandler extends StrolchComponent implements GlobalPlcLis
sendDataToClient(notificationJ);
if (this.verbose)
logger.info("Sent notification for " + plcAddress.toKey() + " to server");
logger.info("Sent notification for {} to server", plcAddress.toKey());
});
}
@ -377,14 +384,11 @@ public class PlcGwClientHandler extends StrolchComponent implements GlobalPlcLis
try {
runAsAgent(ctx -> {
if (MSG_TYPE_AUTHENTICATION.equals(messageType)) {
handleAuthResponse(ctx, jsonObject);
} else if (MSG_TYPE_PLC_TELEGRAM.equals(messageType)) {
async(() -> handleTelegram(jsonObject));
} else if (MSG_TYPE_PLC_GET_ADDRESS_STATE.equals(messageType)) {
async(() -> handleGetAddressState(ctx, jsonObject));
} else {
logger.error("Unhandled message type " + messageType);
switch (messageType) {
case MSG_TYPE_AUTHENTICATION -> handleAuthResponse(ctx, jsonObject);
case MSG_TYPE_PLC_TELEGRAM -> async(() -> handleTelegram(jsonObject));
case MSG_TYPE_PLC_GET_ADDRESS_STATE -> async(() -> handleGetAddressState(ctx, jsonObject));
case null, default -> logger.error("Unhandled message type {}", messageType);
}
});
} catch (Exception e) {
@ -406,7 +410,7 @@ public class PlcGwClientHandler extends StrolchComponent implements GlobalPlcLis
telegramJ.addProperty(PARAM_STATE, PlcResponseState.Done.name());
telegramJ.addProperty(PARAM_STATE_MSG, "");
logger.info("Sent address state for " + plcAddress.toKey() + " = " + value + " to server");
logger.info("Sent address state for {} = {} to server", plcAddress.toKey(), value);
} catch (Exception e) {
handleFailedTelegram(telegramJ, plcAddress, e);
@ -439,21 +443,28 @@ public class PlcGwClientHandler extends StrolchComponent implements GlobalPlcLis
sendDataToClient(telegramJ);
if (this.verbose)
logger.info("Sent Telegram response for " + (plcAddress == null ? "unknown" : plcAddress.toKey()) +
" to server");
logger.info("Sent Telegram response for {} to server", plcAddress == null ? "unknown" : plcAddress.toKey());
}
private void handleAuthResponse(PrivilegeContext ctx, JsonObject response) {
if (!response.has(PARAM_STATE) || !response.has(PARAM_STATE_MSG) || !response.has(PARAM_AUTH_TOKEN)) {
closeBrokenGwSessionUpdateState(ctx, "Auth failed!",
"Failed to authenticated with Server: At least one of " + PARAM_STATE + ", " + PARAM_STATE_MSG +
", " + PARAM_AUTH_TOKEN + " params is missing on Auth Response");
closeBrokenGwSessionUpdateState(ctx, "Auth failed!", "Failed to authenticated with Server: At least one of "
+ PARAM_STATE
+ ", "
+ PARAM_STATE_MSG
+ ", "
+ PARAM_AUTH_TOKEN
+ " params is missing on Auth Response");
throw new IllegalStateException(
"Failed to authenticated with Server: At least one of " + PARAM_STATE + ", " + PARAM_STATE_MSG +
", " + PARAM_AUTH_TOKEN + " params is missing on Auth Response");
throw new IllegalStateException("Failed to authenticated with Server: At least one of "
+ PARAM_STATE
+ ", "
+ PARAM_STATE_MSG
+ ", "
+ PARAM_AUTH_TOKEN
+ " params is missing on Auth Response");
}
if (PlcResponseState.valueOf(response.get(PARAM_STATE).getAsString()) != PlcResponseState.Sent) {
@ -468,7 +479,7 @@ public class PlcGwClientHandler extends StrolchComponent implements GlobalPlcLis
"Missing auth token on AUTH response!");
throw new IllegalStateException("Missing auth token on AUTH response!");
}
logger.info(this.gwSession.getId() + ": Successfully authenticated with Server!");
logger.info("{}: Successfully authenticated with Server!", this.gwSession.getId());
saveServerConnectionState(ctx, ConnectionState.Connected, "");
notifyPlcConnectionState(ConnectionState.Connected);
@ -483,29 +494,29 @@ public class PlcGwClientHandler extends StrolchComponent implements GlobalPlcLis
}
public void onWsPong(PongMessage message, Session session) {
logger.info(session.getId() + ": Received pong " + message.toString());
logger.info("{}: Received pong {}", session.getId(), message.toString());
}
public void onWsOpen(Session session) {
logger.info(session.getId() + ": New Session");
logger.info("{}: New Session", session.getId());
}
public void onWsClose(Session session, CloseReason closeReason) {
this.authenticated = false;
logger.info("Session closed with ID " + session.getId() + " due to " + closeReason.getCloseCode() + " " +
closeReason.getReasonPhrase() + ". Reconnecting in " + RETRY_DELAY + "s.");
logger.info("Session closed with ID {} due to {} {}. Reconnecting in " + RETRY_DELAY + "s.", session.getId(),
closeReason.getCloseCode(), closeReason.getReasonPhrase());
if (this.gwSession != null) {
closeBrokenGwSessionUpdateState(closeReason.getReasonPhrase(),
"Session closed with ID " + session.getId() + " due to " + closeReason.getCloseCode() + " " +
closeReason.getReasonPhrase() + ". Reconnecting in " + RETRY_DELAY + "s.");
MessageFormat.format("Session closed with ID {0} due to {1} {2}. Reconnecting in {3}s.",
session.getId(), closeReason.getCloseCode(), closeReason.getReasonPhrase(), RETRY_DELAY));
}
delayConnect(RETRY_DELAY, TimeUnit.SECONDS);
}
public void onWsError(Session session, Throwable throwable) {
logger.error(session.getId() + ": Received error: " + throwable.getMessage(), throwable);
logger.error("{}: Received error: {}", session.getId(), throwable.getMessage(), throwable);
}
@SuppressWarnings("SynchronizeOnNonFinalField")
@ -561,7 +572,8 @@ public class PlcGwClientHandler extends StrolchComponent implements GlobalPlcLis
private void saveServerConnectionState(PrivilegeContext ctx, ConnectionState state, String stateMsg) {
StrolchRealm realm = getContainer().getRealm(ctx.getCertificate());
try (StrolchTransaction tx = realm.openTx(ctx.getCertificate(), "saveServerConnectionState", false)
try (StrolchTransaction tx = realm
.openTx(ctx.getCertificate(), "saveServerConnectionState", false)
.silentThreshold(SILENT_THRESHOLD, TimeUnit.MILLISECONDS)) {
Resource plc = tx.getResourceBy(TYPE_PLC, this.plcId, true);
@ -582,24 +594,26 @@ public class PlcGwClientHandler extends StrolchComponent implements GlobalPlcLis
VersionQueryResult versionQueryResult = getContainer().getAgent().getVersion();
this.versions.add(AGENT_VERSION, versionQueryResult.getAgentVersion().toJson(true));
this.versions.add(APP_VERSION, versionQueryResult.getAppVersion().toJson(true));
this.versions.add(COMPONENT_VERSIONS,
versionQueryResult.getComponentVersions().stream().map(v -> v.toJson(true))
.collect(JsonArray::new, JsonArray::add, JsonArray::addAll));
this.versions.add(COMPONENT_VERSIONS, versionQueryResult
.getComponentVersions()
.stream()
.map(v -> v.toJson(true))
.collect(JsonArray::new, JsonArray::add, JsonArray::addAll));
}
return this.versions;
}
public JsonArray getIpAddresses() {
if (this.ipAddresses == null || this.ipAddresses.isEmpty() ||
(System.currentTimeMillis() - this.ipAddressesUpdateTime > 10000L)) {
if (this.ipAddresses == null || this.ipAddresses.isEmpty() || (
System.currentTimeMillis() - this.ipAddressesUpdateTime > 10000L)) {
try {
this.ipAddresses = NetworkHelper.findInet4Addresses().stream().map(add -> {
String mac;
try {
mac = formatMacAddress(getByInetAddress(add).getHardwareAddress());
} catch (SocketException e) {
logger.error("Failed to get HW address for " + add.getHostAddress(), e);
logger.error("Failed to get HW address for {}", add.getHostAddress(), e);
mac = "(unknown)";
}
@ -645,12 +659,12 @@ public class PlcGwClientHandler extends StrolchComponent implements GlobalPlcLis
private static void handleFailedTelegram(JsonObject telegramJ, PlcAddress plcAddress, Exception e) {
if (plcAddress == null) {
logger.error("Failed to handle telegram: " + telegramJ, e);
logger.error("Failed to handle telegram: {}", telegramJ, e);
telegramJ.addProperty(PARAM_STATE, PlcResponseState.Failed.name());
telegramJ.addProperty(PARAM_STATE_MSG,
"Could not evaluate PlcAddress: " + getExceptionMessage(getRootCause(e), false));
} else {
logger.error("Failed to execute telegram: " + plcAddress.toKeyAddress(), e);
logger.error("Failed to execute telegram: {}", plcAddress.toKeyAddress(), e);
telegramJ.addProperty(PARAM_STATE, PlcResponseState.Failed.name());
telegramJ.addProperty(PARAM_STATE_MSG,
"Failed to perform " + plcAddress.toKey() + ": " + getExceptionMessage(getRootCause(e), false));

View File

@ -1,20 +1,5 @@
package li.strolch.plc.gw.server;
import static java.util.stream.Collectors.toSet;
import static li.strolch.plc.model.ModelHelper.jsonToValue;
import static li.strolch.plc.model.ModelHelper.valueToJson;
import static li.strolch.plc.model.PlcConstants.*;
import static li.strolch.utils.collections.SynchronizedCollections.synchronizedMapOfLists;
import static li.strolch.utils.helper.ExceptionHelper.getExceptionMessageWithCauses;
import static li.strolch.websocket.WebSocketRemoteIp.get;
import java.io.IOException;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import com.google.gson.JsonPrimitive;
@ -34,13 +19,29 @@ import li.strolch.privilege.base.PrivilegeException;
import li.strolch.privilege.model.Certificate;
import li.strolch.privilege.model.Usage;
import li.strolch.privilege.model.UserRep;
import li.strolch.runtime.sessions.StrolchSessionHandler;
import li.strolch.runtime.configuration.ComponentConfiguration;
import li.strolch.runtime.privilege.PrivilegedRunnable;
import li.strolch.runtime.privilege.PrivilegedRunnableWithResult;
import li.strolch.runtime.sessions.StrolchSessionHandler;
import li.strolch.utils.collections.MapOfLists;
import li.strolch.utils.dbc.DBC;
import java.io.IOException;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;
import static java.text.MessageFormat.format;
import static java.util.stream.Collectors.toSet;
import static li.strolch.plc.model.ModelHelper.jsonToValue;
import static li.strolch.plc.model.ModelHelper.valueToJson;
import static li.strolch.plc.model.PlcConstants.*;
import static li.strolch.utils.collections.SynchronizedCollections.synchronizedMapOfLists;
import static li.strolch.utils.helper.ExceptionHelper.getExceptionMessageWithCauses;
import static li.strolch.websocket.WebSocketRemoteIp.get;
public class PlcGwServerHandler extends StrolchComponent {
public static final String MSG_DISCONNECTED_TIMED_OUT = "Disconnected / Timed out";
@ -77,7 +78,8 @@ public class PlcGwServerHandler extends StrolchComponent {
this.runAsUser = configuration.getString("runAsUser", "plc-server");
this.realm = getContainer().getRealmNames().iterator().next();
this.plcIds = runAsAgentWithResult(ctx -> getContainer().getPrivilegeHandler()
this.plcIds = runAsAgentWithResult(ctx -> getContainer()
.getPrivilegeHandler()
.getPrivilegeHandler()
.getUsers(ctx.getCertificate())
.stream() //
@ -96,7 +98,8 @@ public class PlcGwServerHandler extends StrolchComponent {
@Override
public void start() throws Exception {
this.clearDeadConnectionsTask = getAgent().getScheduledExecutor(getName())
this.clearDeadConnectionsTask = getAgent()
.getScheduledExecutor(getName())
.scheduleWithFixedDelay(this::clearDeadConnections, 10, 10, TimeUnit.SECONDS);
super.start();
}
@ -128,18 +131,14 @@ public class PlcGwServerHandler extends StrolchComponent {
public void register(String plcId, PlcAddressKey addressKey, PlcNotificationListener listener) {
DBC.PRE.assertNotNull("addressKey must not be null", addressKey);
DBC.PRE.assertNotEmpty("plcId must not be empty", plcId);
MapOfLists<PlcAddressKey, PlcNotificationListener> plcListeners = this.plcAddressListenersByPlcId.get(plcId);
if (plcListeners == null) {
plcListeners = new MapOfLists<>();
this.plcAddressListenersByPlcId.put(plcId, plcListeners);
}
MapOfLists<PlcAddressKey, PlcNotificationListener> plcListeners
= this.plcAddressListenersByPlcId.computeIfAbsent(plcId, k -> new MapOfLists<>());
//noinspection SynchronizationOnLocalVariableOrMethodParameter
synchronized (plcListeners) {
plcListeners.addElement(addressKey, listener);
}
logger.info("Registered listener on plc " + plcId + " key " + addressKey + ": " + listener);
logger.info("Registered listener on plc {} key {}: {}", plcId, addressKey, listener);
}
public void unregister(String plcId, PlcAddressKey addressKey, PlcNotificationListener listener) {
@ -149,12 +148,11 @@ public class PlcGwServerHandler extends StrolchComponent {
if (plcListeners == null)
return;
//noinspection SynchronizationOnLocalVariableOrMethodParameter
synchronized (plcListeners) {
plcListeners.removeElement(addressKey, listener);
}
logger.info("Unregistered listener from plc " + plcId + " key " + addressKey + ": " + listener);
logger.info("Unregistered listener from plc {} key {}: {}", plcId, addressKey, listener);
}
public void run(PrivilegedRunnable runnable) throws Exception {
@ -214,9 +212,9 @@ public class PlcGwServerHandler extends StrolchComponent {
PlcAddressResponseListener listener) {
if (valueJ == null)
logger.info("Sending " + plcAddressKey + " to " + plcSession.plcId + "...");
logger.info("Sending {} to {}...", plcAddressKey, plcSession.plcId);
else
logger.info("Sending " + plcAddressKey + " = " + valueJ + " to " + plcSession.plcId + "...");
logger.info("Sending {} = {} to {}...", plcAddressKey, valueJ, plcSession.plcId);
PlcAddressResponse plcResponse = new PlcAddressResponse(plcSession.plcId, plcAddressKey);
plcResponse.setListener(() -> listener.handleResponse(plcResponse));
@ -227,22 +225,22 @@ public class PlcGwServerHandler extends StrolchComponent {
sendDataToClient(data, plcSession.session);
} catch (Exception e) {
logger.error("Failed to send " + plcAddressKey + " to PLC " + plcSession.plcId, e);
logger.error("Failed to send {} to PLC {}", plcAddressKey, plcSession.plcId, e);
plcResponse.setState(PlcResponseState.Failed);
plcResponse.setStateMsg("Failed to send " + plcAddressKey + " to PLC " + plcSession.plcId + ": "
+ getExceptionMessageWithCauses(e));
plcResponse.setStateMsg(format("Failed to send {0} to PLC {1}: {2}", plcAddressKey, plcSession.plcId,
getExceptionMessageWithCauses(e)));
try {
listener.handleResponse(plcResponse);
} catch (Exception ex) {
logger.error("Failed to notify listener " + listener, ex);
logger.error("Failed to notify listener {}", listener, ex);
}
}
}
private void asyncGetAddressState(PlcSession plcSession, PlcAddressKey plcAddressKey,
PlcAddressResponseValueListener listener) {
logger.info("Requesting value for address " + plcAddressKey + " from PLC " + plcSession.plcId + "...");
logger.info("Requesting value for address {} from PLC {}...", plcAddressKey, plcSession.plcId);
PlcAddressValueResponse plcResponse = new PlcAddressValueResponse(plcSession.plcId, plcAddressKey);
plcResponse.setListener(() -> listener.handleResponse(plcResponse));
@ -253,28 +251,23 @@ public class PlcGwServerHandler extends StrolchComponent {
sendDataToClient(data, plcSession.session);
} catch (Exception e) {
logger.error("Failed to get address state for " + plcAddressKey + " from PLC " + plcSession.plcId, e);
logger.error("Failed to get address state for {} from PLC {}", plcAddressKey, plcSession.plcId, e);
plcResponse.setState(PlcResponseState.Failed);
plcResponse.setStateMsg(
"Failed to get address state for " + plcAddressKey + " from PLC " + plcSession.plcId + ": "
+ getExceptionMessageWithCauses(e));
format("Failed to get address state for {0} from PLC {1}: {2}", plcAddressKey, plcSession.plcId,
getExceptionMessageWithCauses(e)));
try {
listener.handleResponse(plcResponse);
} catch (Exception ex) {
logger.error("Failed to notify listener " + listener, ex);
logger.error("Failed to notify listener {}", listener, ex);
}
}
}
private static JsonObject buildJsonTelegram(String plcId, PlcAddressKey plcAddressKey, JsonPrimitive valueJ,
PlcAddressResponse plcResponse) {
JsonObject jsonObject = new JsonObject();
jsonObject.addProperty(PARAM_SEQUENCE_ID, plcResponse.getSequenceId());
jsonObject.addProperty(PARAM_MESSAGE_TYPE, MSG_TYPE_PLC_TELEGRAM);
jsonObject.addProperty(PARAM_PLC_ID, plcId);
jsonObject.addProperty(PARAM_RESOURCE, plcAddressKey.resource);
jsonObject.addProperty(PARAM_ACTION, plcAddressKey.action);
JsonObject jsonObject = buildJson(plcId, plcAddressKey, plcResponse, MSG_TYPE_PLC_TELEGRAM);
if (valueJ != null)
jsonObject.add(PARAM_VALUE, valueJ);
return jsonObject;
@ -282,9 +275,14 @@ public class PlcGwServerHandler extends StrolchComponent {
private static JsonObject buildJsonGetAddressStateTelegram(String plcId, PlcAddressKey plcAddressKey,
PlcAddressResponse plcResponse) {
return buildJson(plcId, plcAddressKey, plcResponse, MSG_TYPE_PLC_GET_ADDRESS_STATE);
}
private static JsonObject buildJson(String plcId, PlcAddressKey plcAddressKey, PlcAddressResponse plcResponse,
String msgTypePlcGetAddressState) {
JsonObject jsonObject = new JsonObject();
jsonObject.addProperty(PARAM_SEQUENCE_ID, plcResponse.getSequenceId());
jsonObject.addProperty(PARAM_MESSAGE_TYPE, MSG_TYPE_PLC_GET_ADDRESS_STATE);
jsonObject.addProperty(PARAM_MESSAGE_TYPE, msgTypePlcGetAddressState);
jsonObject.addProperty(PARAM_PLC_ID, plcId);
jsonObject.addProperty(PARAM_RESOURCE, plcAddressKey.resource);
jsonObject.addProperty(PARAM_ACTION, plcAddressKey.action);
@ -335,21 +333,21 @@ public class PlcGwServerHandler extends StrolchComponent {
String messageType = jsonObject.get(PARAM_MESSAGE_TYPE).getAsString();
switch (messageType) {
case MSG_TYPE_AUTHENTICATION -> handleAuth(session, jsonObject);
case MSG_TYPE_PLC_NOTIFICATION -> handleNotification(assertPlcAuthed(plcId, session.getId()), jsonObject);
case MSG_TYPE_PLC_TELEGRAM -> handleTelegramResponse(assertPlcAuthed(plcId, session.getId()), jsonObject);
case MSG_TYPE_PLC_GET_ADDRESS_STATE ->
handleGetAddressStateResponse(assertPlcAuthed(plcId, session.getId()), jsonObject);
case MSG_TYPE_STATE_NOTIFICATION -> handleStateMsg(assertPlcAuthed(plcId, session.getId()), jsonObject);
case MSG_TYPE_MESSAGE -> {
assertPlcAuthed(plcId, session.getId());
handleMessage(jsonObject);
}
case MSG_TYPE_DISABLE_MESSAGE -> {
assertPlcAuthed(plcId, session.getId());
handleDisableMessage(jsonObject);
}
default -> logger.error(plcId + ": Unhandled message type " + messageType);
case MSG_TYPE_AUTHENTICATION -> handleAuth(session, jsonObject);
case MSG_TYPE_PLC_NOTIFICATION -> handleNotification(assertPlcAuthed(plcId, session.getId()), jsonObject);
case MSG_TYPE_PLC_TELEGRAM -> handleTelegramResponse(assertPlcAuthed(plcId, session.getId()), jsonObject);
case MSG_TYPE_PLC_GET_ADDRESS_STATE ->
handleGetAddressStateResponse(assertPlcAuthed(plcId, session.getId()), jsonObject);
case MSG_TYPE_STATE_NOTIFICATION -> handleStateMsg(assertPlcAuthed(plcId, session.getId()), jsonObject);
case MSG_TYPE_MESSAGE -> {
assertPlcAuthed(plcId, session.getId());
handleMessage(jsonObject);
}
case MSG_TYPE_DISABLE_MESSAGE -> {
assertPlcAuthed(plcId, session.getId());
handleDisableMessage(jsonObject);
}
default -> logger.error("{}: Unhandled message type {}", plcId, messageType);
}
}
@ -369,21 +367,20 @@ public class PlcGwServerHandler extends StrolchComponent {
else
value = valueJ.getAsString();
logger.info(plcSession.plcId + ": Received notification for " + addressKey.toKey() + ": " + value);
logger.info("{}: Received notification for {}: {}", plcSession.plcId, addressKey.toKey(), value);
MapOfLists<PlcAddressKey, PlcNotificationListener> plcListeners = this.plcAddressListenersByPlcId.get(
plcSession.plcId);
if (plcListeners == null) {
logger.warn(plcSession.plcId + ": No listeners for PLC " + plcSession.plcId);
logger.warn("{}: No listeners for PLC {}", plcSession.plcId, plcSession.plcId);
return;
}
List<PlcNotificationListener> listeners;
//noinspection SynchronizationOnLocalVariableOrMethodParameter
synchronized (plcListeners) {
listeners = plcListeners.getList(addressKey);
if (listeners == null) {
logger.warn(plcSession.plcId + ": No listeners for " + addressKey.toKey());
logger.warn("{}: No listeners for {}", plcSession.plcId, addressKey.toKey());
return;
}
}
@ -393,8 +390,8 @@ public class PlcGwServerHandler extends StrolchComponent {
try {
listener.handleNotification(addressKey, value);
} catch (Exception e) {
logger.error(
plcSession.plcId + ": Failed to notify listener " + listener + " for " + addressKey.toKey(), e);
logger.error("{}: Failed to notify listener {} for {}", plcSession.plcId, listener, addressKey.toKey(),
e);
}
}
}
@ -403,7 +400,7 @@ public class PlcGwServerHandler extends StrolchComponent {
long sequenceId = responseJ.get(PARAM_SEQUENCE_ID).getAsLong();
PlcResponse plcResponse = this.plcResponses.remove(sequenceId);
if (plcResponse == null) {
logger.error(plcSession.plcId + ": PlcResponse does not exist for sequenceId " + sequenceId);
logger.error("{}: PlcResponse does not exist for sequenceId {}", plcSession.plcId, sequenceId);
return;
}
@ -415,8 +412,7 @@ public class PlcGwServerHandler extends StrolchComponent {
try {
plcResponse.getListener().run();
} catch (Exception e) {
logger.error("Failed to notify listener " + plcResponse.getListener() + " for response of " + plcResponse,
e);
logger.error("Failed to notify listener {} for response of {}", plcResponse.getListener(), plcResponse, e);
}
}
@ -424,7 +420,8 @@ public class PlcGwServerHandler extends StrolchComponent {
long sequenceId = responseJ.get(PARAM_SEQUENCE_ID).getAsLong();
PlcResponse response = this.plcResponses.remove(sequenceId);
if (response == null) {
logger.error(plcSession.plcId + ": PlcResponse does not exist for sequenceId " + sequenceId);
logger.error("{}: PlcResponse does not exist for GetAddressState message with sequenceId {}",
plcSession.plcId, sequenceId);
return;
}
@ -441,19 +438,18 @@ public class PlcGwServerHandler extends StrolchComponent {
try {
plcResponse.getListener().run();
} catch (Exception e) {
logger.error("Failed to notify listener " + plcResponse.getListener() + " for response of " + plcResponse,
e);
logger.error("Failed to notify listener {} for response of {}", plcResponse.getListener(), plcResponse, e);
}
}
private void handleMessage(JsonObject jsonObject) {
JsonObject msgJ = jsonObject.get(PARAM_MESSAGE).getAsJsonObject();
LogMessage logMessage = LogMessage.fromJson(msgJ);
logger.info("Received message " + logMessage.getLocator());
logger.info("Received message {}", logMessage.getLocator());
if (!logMessage.getRealm().equals(this.realm))
throw new IllegalStateException(
"Unexpected realm in message " + logMessage.getId() + " " + logMessage.getLocator() + " "
+ logMessage.getMessage());
format("Unexpected realm in message {0} {1} {2}", logMessage.getId(), logMessage.getLocator(),
logMessage.getMessage()));
OperationsLog log = getComponent(OperationsLog.class);
log.updateState(logMessage.getRealm(), logMessage.getLocator(), LogMessageState.Inactive);
@ -466,7 +462,7 @@ public class PlcGwServerHandler extends StrolchComponent {
if (!realm.equals(this.realm))
throw new IllegalStateException("Unexpected realm in disable message action for message " + locator);
logger.info("Received disable for messages with locator " + locator);
logger.info("Received disable for messages with locator {}", locator);
OperationsLog operationsLog = getComponent(OperationsLog.class);
operationsLog.updateState(realm, locator, LogMessageState.Inactive);
}
@ -475,8 +471,8 @@ public class PlcGwServerHandler extends StrolchComponent {
String sessionId = session.getId();
if (!authJ.has(PARAM_PLC_ID) || !authJ.has(PARAM_USERNAME) || !authJ.has(PARAM_PASSWORD))
throw new IllegalStateException(
sessionId + ": Auth Json is missing one of " + PARAM_PLC_ID + ", " + PARAM_USERNAME + ", "
+ PARAM_PASSWORD + ": " + authJ);
format("{0}: Auth Json is missing one of {1}, {2}, {3}: {4}", sessionId, PARAM_PLC_ID,
PARAM_USERNAME, PARAM_PASSWORD, authJ));
String plcId = authJ.get(PARAM_PLC_ID).getAsString();
String username = authJ.get(PARAM_USERNAME).getAsString();
@ -519,21 +515,21 @@ public class PlcGwServerHandler extends StrolchComponent {
private void sendAuthResponse(PlcSession plcSession, JsonObject jsonObject) {
try {
sendDataToClient(jsonObject.toString(), plcSession.session);
logger.info(plcSession.plcId + ": Sent " + MSG_TYPE_AUTHENTICATION + " response on Session "
+ plcSession.session.getId());
logger.info("{}: Sent " + MSG_TYPE_AUTHENTICATION + " response on Session {}", plcSession.plcId,
plcSession.session.getId());
} catch (Exception e) {
logger.error(plcSession.plcId + ": Failed to send data to PLC", e);
logger.error("{}: Failed to send data to PLC", plcSession.plcId, e);
try {
plcSession.session.close(
new CloseReason(CloseReason.CloseCodes.CLOSED_ABNORMALLY, "Failed to send auth response"));
} catch (IOException ex) {
logger.error(plcSession.plcId + ": Faild to close session to PLC");
logger.error("{}: Faild to close session to PLC", plcSession.plcId);
}
}
}
public void onWsOpen(Session session) {
logger.info(session.getId() + ": New Session");
logger.info("{}: New Session", session.getId());
}
public void onWsPong(PongMessage message, Session session) {
@ -546,8 +542,8 @@ public class PlcGwServerHandler extends StrolchComponent {
PlcSession existingPlcSession = this.plcSessionsByPlcId.put(plcId, plcSession);
if (existingPlcSession != null) {
logger.error("Old PLC session found for plc " + plcId + " under SessionId "
+ existingPlcSession.session.getId() + ". Closing that session.");
logger.error("Old PLC session found for plc {} under SessionId {}. Closing that session.", plcId,
existingPlcSession.session.getId());
this.plcSessionsBySessionId.remove(existingPlcSession.session.getId());
try {
@ -556,12 +552,12 @@ public class PlcGwServerHandler extends StrolchComponent {
new CloseReason(CloseReason.CloseCodes.NOT_CONSISTENT, "Stale session"));
}
} catch (Exception e) {
logger.error("Failed to close session " + existingPlcSession.session.getId(), e);
logger.error("Failed to close session {}", existingPlcSession.session.getId(), e);
}
}
this.plcSessionsBySessionId.put(session.getId(), plcSession);
logger.info("PLC connected with ID " + plcId + " and SessionId " + plcSession.session.getId());
logger.info("PLC connected with ID {} and SessionId {}", plcId, plcSession.session.getId());
}
if (plcSession.certificate != null) {
@ -570,14 +566,14 @@ public class PlcGwServerHandler extends StrolchComponent {
sessionHandler.validate(plcSession.certificate);
plcSession.lastUpdate = System.currentTimeMillis();
logger.info("PLC " + plcId + " with SessionId " + session.getId() + " is still alive on certificate "
+ plcSession.certificate.getSessionId());
logger.info("PLC {} with SessionId {} is still alive on certificate {}", plcId, session.getId(),
plcSession.certificate.getSessionId());
this.plcStateHandler.handleStillConnected(plcSession);
} catch (StrolchNotAuthenticatedException e) {
logger.error("PLC session " + session.getId() + " is not authenticated anymore for plc " + plcId
+ ". Closing session.");
logger.error("PLC session {} is not authenticated anymore for plc {}. Closing session.",
session.getId(), plcId);
this.plcSessionsBySessionId.remove(plcId);
PlcSession registeredSession = this.plcSessionsByPlcId.get(plcId);
@ -590,7 +586,7 @@ public class PlcGwServerHandler extends StrolchComponent {
session.close(new CloseReason(CloseReason.CloseCodes.NOT_CONSISTENT, "Stale session"));
}
} catch (Exception e1) {
logger.error("Failed to close session " + session.getId(), e1);
logger.error("Failed to close session {}", session.getId(), e1);
}
}
}
@ -599,14 +595,14 @@ public class PlcGwServerHandler extends StrolchComponent {
private void clearDeadConnections() {
// find all sessions which are timed out
List<PlcSession> expiredSessions = this.plcSessionsBySessionId.values()
List<PlcSession> expiredSessions = this.plcSessionsBySessionId
.values()
.stream()
.filter(this::hasExpired)
.toList();
for (PlcSession plcSession : expiredSessions) {
logger.warn("Session " + plcSession.session.getId() + " has expired for PLC " + plcSession.plcId
+ ". Closing.");
logger.warn("Session {} has expired for PLC {}. Closing.", plcSession.session.getId(), plcSession.plcId);
// close the session
try {
@ -615,13 +611,13 @@ public class PlcGwServerHandler extends StrolchComponent {
new CloseReason(CloseReason.CloseCodes.CLOSED_ABNORMALLY, "Session expired!"));
}
} catch (IOException e) {
logger.error("Closing session lead to exception: " + getExceptionMessageWithCauses(e));
logger.error("Closing session lead to exception: {}", getExceptionMessageWithCauses(e));
}
// invalidate the certificate
if (plcSession.certificate != null) {
logger.warn("Invalidating old Session " + plcSession.session.getId() + " for PLC " + plcSession.plcId
+ " with certificate " + plcSession.certificate.getSessionId());
logger.warn("Invalidating old Session {} for PLC {} with certificate {}", plcSession.session.getId(),
plcSession.plcId, plcSession.certificate.getSessionId());
StrolchSessionHandler sessionHandler = getContainer().getComponent(StrolchSessionHandler.class);
sessionHandler.invalidate(plcSession.certificate);
}
@ -645,22 +641,22 @@ public class PlcGwServerHandler extends StrolchComponent {
PlcSession plcSession = this.plcSessionsBySessionId.remove(session.getId());
if (plcSession == null) {
logger.warn(session.getId() + ": Connection to session " + session.getId() + " is lost due to "
+ closeReason.getCloseCode() + " " + closeReason.getReasonPhrase());
logger.warn("{}: Connection to session {} is lost due to {} {}", session.getId(), session.getId(),
closeReason.getCloseCode(), closeReason.getReasonPhrase());
return;
}
this.plcSessionsByPlcId.remove(plcSession.plcId);
String reason = closeReason.getCloseCode() + " " + closeReason.getReasonPhrase();
logger.warn(session.getId() + ": Connection to PLC " + plcSession.plcId + " is lost due to " + reason);
logger.warn("{}: Connection to PLC {} is lost due to {}", session.getId(), plcSession.plcId, reason);
if (plcSession.certificate != null) {
StrolchSessionHandler sessionHandler = getContainer().getComponent(StrolchSessionHandler.class);
try {
sessionHandler.invalidate(plcSession.certificate);
} catch (Exception e) {
logger.error(session.getId() + ": Failed to invalidate session for plc " + plcSession.plcId, e);
logger.error("{}: Failed to invalidate session for plc {}", session.getId(), plcSession.plcId, e);
}
this.plcStateHandler.handlePlcState(plcSession, ConnectionState.Disconnected, reason, null);
@ -675,7 +671,7 @@ public class PlcGwServerHandler extends StrolchComponent {
private void notifyObserversOfConnectionLost(String plcId) {
logger.info("Notifying observers of connection lost to plc " + plcId + "...");
logger.info("Notifying observers of connection lost to plc {}...", plcId);
// first notify and remove any response observers for disconnected PLCs
List<PlcResponse> keySet = new ArrayList<>(this.plcResponses.values());
@ -687,12 +683,11 @@ public class PlcGwServerHandler extends StrolchComponent {
plcResponse.setStateMsg(MSG_DISCONNECTED_TIMED_OUT);
plcResponse.setState(PlcResponseState.Failed);
try {
logger.warn("Notifying PlcResponse listener " + plcResponse + " of connection lost!");
logger.warn("Notifying PlcResponse listener {} of connection lost!", plcResponse);
plcResponse.getListener().run();
} catch (Exception e) {
logger.error(
"Failed to notify PlcResponse listener " + plcResponse + " of connection lost to PLC " + plcId,
e);
logger.error("Failed to notify PlcResponse listener {} of connection lost to PLC {}", plcResponse,
plcId, e);
}
}
@ -710,12 +705,11 @@ public class PlcGwServerHandler extends StrolchComponent {
List<PlcNotificationListener> listenersCopy = new ArrayList<>(listeners);
for (PlcNotificationListener listener : listenersCopy) {
logger.warn("Notifying PlcNotificationListener " + addressKey + " with " + listener
+ " of connection lost!");
logger.warn("Notifying PlcNotificationListener {} with {} of connection lost!", addressKey, listener);
try {
listener.handleConnectionLost();
} catch (Exception e) {
logger.error("Failed to notify listener " + listener + " of connection lost for PLC " + plcId, e);
logger.error("Failed to notify listener {} of connection lost for PLC {}", listener, plcId, e);
}
}
}
@ -730,14 +724,14 @@ public class PlcGwServerHandler extends StrolchComponent {
try {
listener.handleConnectionState(plcId, connectionState);
} catch (Exception e) {
logger.error("Failed to notify listener " + listener + " of new connection state " + connectionState
+ " for PLC " + plcId, e);
logger.error("Failed to notify listener {} of new connection state {} for PLC {}", listener,
connectionState, plcId, e);
}
}
}
public void onWsError(Session session, Throwable throwable) {
logger.error(session.getId() + ": Error: " + throwable.getMessage(), throwable);
logger.error("{}: Error: {}", session.getId(), throwable.getMessage(), throwable);
}
private PlcSession getPlcSession(String plcId) {

View File

@ -162,12 +162,13 @@ public abstract class PlcGwService implements PlcNotificationListener, PlcAddres
}
private void handleFailedRunnable(String runnable, Exception e) {
logger.error("Runnable " + runnable + " failed!", e);
logger.error("Runnable {} failed!", runnable, e);
if (hasOperationsLogs()) {
getOperationsLogs().addMessage(
new LogMessage(this.container.getRealmNames().iterator().next(), SYSTEM_USER_AGENT,
Resource.locatorFor(TYPE_PLC, this.plcId), LogSeverity.Exception,
LogMessageState.Information, PlcGwSrvI18n.bundle, "systemAction.failed").withException(e)
LogMessageState.Information, PlcGwSrvI18n.bundle, "systemAction.failed")
.withException(e)
.value("action", runnable));
}
}
@ -175,8 +176,7 @@ public abstract class PlcGwService implements PlcNotificationListener, PlcAddres
/**
* Executes the given consumer in a read-only transaction
*
* @param consumer
* the consumer to run in a read-only transaction
* @param consumer the consumer to run in a read-only transaction
*/
protected <T> T runReadOnlyTx(CheckedBiFunction<PrivilegeContext, StrolchTransaction, T> consumer) {
return run(ctx -> {
@ -193,8 +193,7 @@ public abstract class PlcGwService implements PlcNotificationListener, PlcAddres
* when the runnable is completed and the TX is dirty, i.e. {@link StrolchTransaction#needsCommit()} returns
* true</p>
*
* @param consumer
* the consumer to run in a writeable transaction
* @param consumer the consumer to run in a writeable transaction
*/
protected <T> T runWritableTx(CheckedBiFunction<PrivilegeContext, StrolchTransaction, T> consumer) {
return run(ctx -> {
@ -232,7 +231,8 @@ public abstract class PlcGwService implements PlcNotificationListener, PlcAddres
protected ScheduledFuture<?> scheduleAtFixedRate(PrivilegedRunnable runnable, long initialDelay, long period,
TimeUnit delayUnit) {
return this.container.getAgent()
return this.container
.getAgent()
.getScheduledExecutor(PlcGwService.class.getSimpleName())
.scheduleAtFixedRate(() -> {
try {
@ -245,7 +245,8 @@ public abstract class PlcGwService implements PlcNotificationListener, PlcAddres
protected ScheduledFuture<?> scheduleWithFixedDelay(PrivilegedRunnable runnable, long initialDelay, long period,
TimeUnit delayUnit) {
return this.container.getAgent()
return this.container
.getAgent()
.getScheduledExecutor(PlcGwService.class.getSimpleName())
.scheduleWithFixedDelay(() -> {
try {
@ -257,6 +258,6 @@ public abstract class PlcGwService implements PlcNotificationListener, PlcAddres
}
protected void handleFailedSchedule(Exception e) {
logger.error("Failed to execute " + getClass().getSimpleName(), e);
logger.error("Failed to execute {}", getClass().getSimpleName(), e);
}
}

View File

@ -103,9 +103,8 @@ public class PlcStateHandler {
plc.setString(PARAM_CONNECTION_STATE_MSG, connectionStateMsg);
tx.update(plc);
logger.info(
"Updated connection state for PLC " + plc.getId() + " to " + connectionState + (isEmpty(
connectionStateMsg) ? "" : ": " + connectionStateMsg));
logger.info("Updated connection state for PLC {} to {}{}", plc.getId(), connectionState,
isEmpty(connectionStateMsg) ? "" : ": " + connectionStateMsg);
}
if (stateJ != null) {
@ -145,7 +144,7 @@ public class PlcStateHandler {
}
private void saveGatewayIpAddresses(StrolchTransaction tx, Resource plc, JsonArray ipAddresses) {
if (ipAddresses.size() == 0)
if (ipAddresses.isEmpty())
return;
// update local IPs
@ -225,20 +224,20 @@ public class PlcStateHandler {
}
private Resource buildNewPlc(PlcGwServerHandler.PlcSession plcSession, StrolchTransaction tx) {
return new ResourceBuilder(plcSession.plcId, plcSession.plcId, TYPE_PLC) //
.defaultBag() //
return new ResourceBuilder(plcSession.plcId, plcSession.plcId, TYPE_PLC)
.defaultBag()
.string(PARAM_CONNECTION_STATE, buildParamName(PARAM_CONNECTION_STATE))
.enumeration(ConnectionState.Disconnected)
.end() //
.end()
.string(PARAM_CONNECTION_STATE_MSG, buildParamName(PARAM_CONNECTION_STATE_MSG))
.end() //
.end()
.stringList(PARAM_LOCAL_IP, buildParamName(PARAM_LOCAL_IP))
.end() //
.end()
.endBag() //
.endBag()
.build();
}
@ -246,18 +245,16 @@ public class PlcStateHandler {
if (systemState == null)
return;
new ResourceSystemStateFromJson().compactStates() //
new ResourceSystemStateFromJson().compactStates()
// os
.withSystemLoadAverageState() //
.withSystemLoadAverageState()
// memory
.withMemoryRounding(DataUnit.MegaBytes) //
.withFreePhysicalMemorySizeState() //
.withMemoryRounding(DataUnit.MegaBytes).withFreePhysicalMemorySizeState()
// storage
.withStorageSpaceRounding(DataUnit.GigaBytes) //
.withFreeSpaceState() //
.withStorageSpaceRounding(DataUnit.GigaBytes).withFreeSpaceState()
.fillElement(systemState, gateway);
}

View File

@ -1,29 +1,26 @@
package li.strolch.plc.gw.server.policy.execution;
import static li.strolch.model.StrolchModelConstants.BAG_PARAMETERS;
import static li.strolch.model.log.LogMessageState.*;
import static li.strolch.plc.gw.server.PlcGwSrvI18n.*;
import static li.strolch.plc.model.PlcConstants.PARAM_PLC_ID;
import static li.strolch.runtime.StrolchConstants.SYSTEM_USER_AGENT;
import java.util.HashSet;
import java.util.Set;
import li.strolch.execution.ExecutionHandler;
import li.strolch.execution.policy.SimpleExecution;
import li.strolch.model.activity.Action;
import li.strolch.model.log.LogMessage;
import li.strolch.model.log.LogMessageState;
import li.strolch.model.log.LogSeverity;
import li.strolch.model.parameter.StringParameter;
import li.strolch.persistence.api.StrolchTransaction;
import li.strolch.plc.gw.server.PlcAddressResponseListener;
import li.strolch.plc.gw.server.PlcGwServerHandler;
import li.strolch.plc.gw.server.PlcGwSrvI18n;
import li.strolch.plc.gw.server.PlcNotificationListener;
import li.strolch.plc.model.PlcAddressKey;
import li.strolch.plc.model.PlcAddressResponse;
import java.util.HashSet;
import java.util.Set;
import static li.strolch.model.StrolchModelConstants.BAG_PARAMETERS;
import static li.strolch.model.log.LogMessageState.Information;
import static li.strolch.plc.gw.server.PlcGwSrvI18n.bundle;
import static li.strolch.plc.model.PlcConstants.PARAM_PLC_ID;
import static li.strolch.runtime.StrolchConstants.SYSTEM_USER_AGENT;
public abstract class PlcExecutionPolicy extends SimpleExecution
implements PlcNotificationListener, PlcAddressResponseListener {
@ -85,12 +82,10 @@ public abstract class PlcExecutionPolicy extends SimpleExecution
}
protected boolean assertResponse(PlcAddressResponse response) {
if (response.getState().isFailed()) {
toError(msgFailedToSendMessage(response));
return false;
}
return true;
if (!response.getState().isFailed())
return true;
toError(msgFailedToSendMessage(response));
return false;
}
protected void send(PlcAddressKey key, boolean value) {

View File

@ -1,7 +1,5 @@
package li.strolch.plc.gw.server.service;
import static li.strolch.plc.model.PlcConstants.*;
import li.strolch.persistence.api.StrolchTransaction;
import li.strolch.plc.model.PlcAddressResponse;
import li.strolch.service.StringMapArgument;
@ -9,6 +7,8 @@ import li.strolch.service.api.AbstractService;
import li.strolch.service.api.ServiceResult;
import li.strolch.utils.dbc.DBC;
import static li.strolch.plc.model.PlcConstants.*;
public class SendPlcTelegramService extends AbstractService<StringMapArgument, ServiceResult> {
@Override

View File

@ -5,14 +5,13 @@ import com.google.gson.JsonPrimitive;
public class ModelHelper {
public static JsonPrimitive valueToJson(Object value) {
if (value instanceof Boolean)
return new JsonPrimitive((Boolean) value);
else if (value instanceof Number)
return new JsonPrimitive((Number) value);
else if (value instanceof String)
return new JsonPrimitive((String) value);
throw new IllegalArgumentException(
"Unhandled value type " + (value == null ? "(null)" : value.getClass().getName()));
return switch (value) {
case Boolean b -> new JsonPrimitive(b);
case Number number -> new JsonPrimitive(number);
case String s -> new JsonPrimitive(s);
case null, default -> throw new IllegalArgumentException(
"Unhandled value type " + (value == null ? "(null)" : value.getClass().getName()));
};
}
public static Object jsonToValue(JsonPrimitive valueJ) {

View File

@ -1,11 +1,14 @@
package li.strolch.plc.model;
import java.util.Objects;
import li.strolch.model.StrolchValueType;
import java.util.Objects;
import static java.text.MessageFormat.format;
/**
* <p>This represents the address on the PLC. Addresses always consists of a resource and action field. This address includes:</p>
* <p>This represents the address on the PLC. Addresses always consists of a resource and action field. This address
* includes:</p>
* <ul>
* <li>the type defined as {@link PlcAddressType}</li>
* <li>remote flag, denoting of this address should be sent to a remote listener</li>
@ -87,8 +90,8 @@ public class PlcAddress {
@Override
public String toString() {
return this.type + " " + this.resource + "-" + this.action + " " + this.valueType.getType() + " @ "
+ this.address;
return format("{0} {1}-{2} {3} @ {4}", this.type, this.resource, this.action, this.valueType.getType(),
this.address);
}
public String toKey() {

View File

@ -1,5 +1,7 @@
package li.strolch.plc.model;
import static java.text.MessageFormat.format;
public class PlcAddressResponse extends PlcResponse {
private final PlcAddressKey plcAddressKey;
@ -21,7 +23,7 @@ public class PlcAddressResponse extends PlcResponse {
@Override
public String toString() {
return "PlcAddressResponse{" + "plcId='" + plcId + '\'' + ", plcAddressKey=" + plcAddressKey + ", sequenceId="
+ sequenceId + ", state=" + state + '}';
return format("PlcAddressResponse'{'plcId=''{0}'', plcAddressKey={1}, sequenceId={2}, state={3}'}'", plcId,
plcAddressKey, sequenceId, state);
}
}

View File

@ -1,5 +1,7 @@
package li.strolch.plc.model;
import static java.text.MessageFormat.format;
public class PlcAddressValueResponse extends PlcAddressResponse {
private Object value;
@ -40,7 +42,8 @@ public class PlcAddressValueResponse extends PlcAddressResponse {
@Override
public String toString() {
return "PlcAddressValueResponse{" + "plcId='" + plcId + '\'' + ", sequenceId=" + sequenceId + ", state=" + state
+ ", stateMsg='" + stateMsg + '\'' + ", value=" + value + '}';
return format(
"PlcAddressValueResponse'{'plcId=''{0}'', sequenceId={1}, state={2}, stateMsg=''{3}'', value={4}'}'",
plcId, sequenceId, state, stateMsg, value);
}
}

View File

@ -38,11 +38,11 @@ public class PlcConnectionsResource {
Paging<JsonObject> paging;
try (StrolchTransaction tx = RestfulStrolchComponent.getInstance().openTx(cert, getContext())) {
paging = new PlcConnectionSearch() //
.stringQuery(query) //
.search(tx) //
.orderByName() //
.visitor(plcConnectionToJson()) //
paging = new PlcConnectionSearch()
.stringQuery(query)
.search(tx)
.orderByName()
.visitor(plcConnectionToJson())
.toPaging(offset, limit);
}

View File

@ -1,14 +1,5 @@
package li.strolch.plc.rest;
import static java.util.Comparator.comparing;
import static li.strolch.plc.model.PlcConstants.*;
import static li.strolch.plc.rest.PlcModelVisitor.*;
import static li.strolch.rest.StrolchRestfulConstants.DATA;
import java.util.List;
import java.util.Set;
import java.util.TreeSet;
import com.google.gson.JsonArray;
import com.google.gson.JsonObject;
import jakarta.servlet.http.HttpServletRequest;
@ -27,6 +18,15 @@ import li.strolch.rest.StrolchRestfulConstants;
import li.strolch.rest.helper.ResponseUtil;
import li.strolch.utils.collections.MapOfLists;
import java.util.List;
import java.util.Set;
import java.util.TreeSet;
import static java.util.Comparator.comparing;
import static li.strolch.plc.model.PlcConstants.*;
import static li.strolch.plc.rest.PlcModelVisitor.*;
import static li.strolch.rest.StrolchRestfulConstants.DATA;
@Path("plc/logicalDevices")
public class PlcLogicalDevicesResource {
@ -44,12 +44,11 @@ public class PlcLogicalDevicesResource {
JsonArray dataJ = new JsonArray();
try (StrolchTransaction tx = RestfulStrolchComponent.getInstance().openTx(cert, getContext())) {
MapOfLists<String, Resource> devicesByGroup = new PlcLogicalDeviceSearch() //
.stringQuery(query) //
.search(tx) //
.orderBy(comparing((Resource o) -> o.getParameter(PARAM_INDEX).getValue())) //
.toMapOfLists(r -> r.hasParameter(PARAM_GROUP) ?
r.getParameter(PARAM_GROUP).getValueAsString() :
MapOfLists<String, Resource> devicesByGroup = new PlcLogicalDeviceSearch()
.stringQuery(query)
.search(tx)
.orderBy(comparing((Resource o) -> o.getParameter(PARAM_INDEX).getValue()))
.toMapOfLists(r -> r.hasParameter(PARAM_GROUP) ? r.getParameter(PARAM_GROUP).getValueAsString() :
"default");
Set<String> groups = new TreeSet<>(devicesByGroup.keySet());
@ -57,7 +56,8 @@ public class PlcLogicalDevicesResource {
List<Resource> devices = devicesByGroup.getList(group);
JsonObject groupJ = new JsonObject();
groupJ.addProperty(Tags.Json.NAME, group);
groupJ.add(DATA, devices.stream()
groupJ.add(DATA, devices
.stream()
.map(e -> e.accept(plcLogicalDeviceToJson()))
.collect(JsonArray::new, JsonArray::add, JsonArray::addAll));
@ -81,7 +81,8 @@ public class PlcLogicalDevicesResource {
Resource plcLogicalDevice = tx.getResourceBy(TYPE_PLC_LOGICAL_DEVICE, id, true);
tx.assertHasPrivilege(Operation.GET, plcLogicalDevice);
dataJ = tx.getResourcesByRelation(plcLogicalDevice, PARAM_ADDRESSES, true)
dataJ = tx
.getResourcesByRelation(plcLogicalDevice, PARAM_ADDRESSES, true)
.stream()
.map(e -> e.accept(plcAddressToJson(simple)))
.collect(JsonArray::new, JsonArray::add, JsonArray::addAll);
@ -103,7 +104,8 @@ public class PlcLogicalDevicesResource {
Resource plcLogicalDevice = tx.getResourceBy(TYPE_PLC_LOGICAL_DEVICE, id, true);
tx.assertHasPrivilege(Operation.GET, plcLogicalDevice);
dataJ = tx.getResourcesByRelation(plcLogicalDevice, PARAM_ADDRESSES, true)
dataJ = tx
.getResourcesByRelation(plcLogicalDevice, PARAM_ADDRESSES, true)
.stream()
.map(e -> e.accept(plcAddressToJson(simple)))
.collect(JsonArray::new, JsonArray::add, JsonArray::addAll);
@ -125,7 +127,8 @@ public class PlcLogicalDevicesResource {
Resource plcLogicalDevice = tx.getResourceBy(TYPE_PLC_LOGICAL_DEVICE, id, true);
tx.assertHasPrivilege(Operation.GET, plcLogicalDevice);
dataJ = tx.getResourcesByRelation(plcLogicalDevice, PARAM_TELEGRAMS, true)
dataJ = tx
.getResourcesByRelation(plcLogicalDevice, PARAM_TELEGRAMS, true)
.stream()
.map(e -> e.accept(plcTelegramToJson(simple)))
.collect(JsonArray::new, JsonArray::add, JsonArray::addAll);

View File

@ -27,16 +27,22 @@ public class PlcModelVisitor {
// add the custom parameters with keys for the id, name and value, so we can show them on the UI
JsonArray parametersJ = new JsonArray();
connectionR.getParameterBag(BAG_PARAMETERS, true).getParameters().stream()
connectionR
.getParameterBag(BAG_PARAMETERS, true)
.getParameters()
.stream()
.sorted(comparing(Parameter::getIndex))
.filter(p -> !(p.getId().equals(PARAM_STATE) || p.getId().equals(PARAM_STATE_MSG) || p.getId()
.equals(PARAM_CLASS_NAME))).forEach(parameter -> {
JsonObject paramJ = new JsonObject();
paramJ.addProperty(Tags.Json.ID, parameter.getId());
paramJ.addProperty(Tags.Json.NAME, parameter.getName());
paramJ.addProperty(Tags.Json.VALUE, parameter.getValueAsString());
parametersJ.add(paramJ);
});
.filter(p -> !(
p.getId().equals(PARAM_STATE) || p.getId().equals(PARAM_STATE_MSG) || p
.getId()
.equals(PARAM_CLASS_NAME)))
.forEach(parameter -> {
JsonObject paramJ = new JsonObject();
paramJ.addProperty(Tags.Json.ID, parameter.getId());
paramJ.addProperty(Tags.Json.NAME, parameter.getName());
paramJ.addProperty(Tags.Json.VALUE, parameter.getValueAsString());
parametersJ.add(paramJ);
});
connectionJ.add(BAG_PARAMETERS, parametersJ);
});
}

View File

@ -1,8 +1,5 @@
package li.strolch.plc.rest;
import static li.strolch.plc.model.PlcConstants.*;
import static li.strolch.rest.StrolchRestfulConstants.DATA;
import com.google.gson.JsonObject;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.ws.rs.*;
@ -18,6 +15,10 @@ import li.strolch.rest.helper.ResponseUtil;
import li.strolch.service.StringMapArgument;
import li.strolch.service.api.ServiceHandler;
import li.strolch.service.api.ServiceResult;
import li.strolch.utils.dbc.DBC;
import static li.strolch.plc.model.PlcConstants.*;
import static li.strolch.rest.StrolchRestfulConstants.DATA;
@Path("plc")
public class PlcResource {
@ -27,6 +28,8 @@ public class PlcResource {
@Produces(MediaType.APPLICATION_JSON)
public Response getState(@Context HttpServletRequest request) {
PlcHandler plcHandler = RestfulStrolchComponent.getInstance().getComponent(PlcHandler.class);
Certificate cert = (Certificate) request.getAttribute(StrolchRestfulConstants.STROLCH_CERTIFICATE);
DBC.PRE.assertNotNull("No certificate available!", cert);
JsonObject jsonObject = new JsonObject();
jsonObject.addProperty(PARAM_STATE, plcHandler.getPlcState().name());

View File

@ -1,19 +1,5 @@
package li.strolch.plc.core.util;
import static java.lang.Integer.parseInt;
import static java.nio.charset.StandardCharsets.UTF_8;
import static li.strolch.model.xml.StrolchXmlHelper.parseToMap;
import static li.strolch.plc.model.PlcConstants.*;
import static li.strolch.utils.helper.StringHelper.*;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import li.strolch.model.Resource;
import li.strolch.model.StrolchRootElement;
import li.strolch.model.StrolchValueType;
@ -29,6 +15,20 @@ import org.apache.commons.csv.CSVRecord;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import static java.lang.Integer.parseInt;
import static java.nio.charset.StandardCharsets.UTF_8;
import static li.strolch.model.xml.StrolchXmlHelper.parseToMap;
import static li.strolch.plc.model.PlcConstants.*;
import static li.strolch.utils.helper.StringHelper.*;
public class PlcAddressGenerator {
private static final Logger logger = LoggerFactory.getLogger(PlcAddressGenerator.class);
@ -36,7 +36,8 @@ public class PlcAddressGenerator {
public static void main(String[] args) throws IOException {
if (args.length != 3)
throw new IllegalStateException("Usage: java " + PlcAddressGenerator.class.getName()
throw new IllegalStateException("Usage: java "
+ PlcAddressGenerator.class.getName()
+ " <templates.xml> <import.csv> <export.csv>");
File templatesF = new File(args[0]);
@ -79,9 +80,9 @@ public class PlcAddressGenerator {
Map<String, Resource> exportList = new LinkedHashMap<>();
CSVFormat csvFormat = CSVFormat.DEFAULT.withFirstRecordAsHeader();
CSVFormat csvFormat = CSVFormat.DEFAULT.builder().setHeader().setSkipHeaderRecord(true).build();
try (InputStream in = new FileInputStream(importFile);
CSVParser parser = CSVParser.parse(in, UTF_8, csvFormat)) {
CSVParser parser = CSVParser.parse(in, UTF_8, csvFormat)) {
int groupNr = 0;
int groupIndex = 10;
@ -94,7 +95,7 @@ public class PlcAddressGenerator {
String type = record.get("Type");
if (type.isEmpty()) {
logger.info("Ignoring empty type for " + record);
logger.info("Ignoring empty type for {}", record);
continue;
}
@ -107,145 +108,41 @@ public class PlcAddressGenerator {
String keyName = resource + " - " + action1;
switch (type) {
case "Group" -> {
groupNr++;
addressIndex = 10;
telegramIndex = 10;
String deviceId = record.get("DeviceId").trim();
if (isEmpty(deviceId))
throw new IllegalStateException("No device for new group: " + record);
logicalDevice = logicalDeviceT.getClone();
logicalDevice.setId("D_" + deviceId);
logicalDevice.setName(deviceId);
String groupNrS = normalizeLength(Integer.toString(groupNr), 2, true, '0');
logicalDevice.setString(PARAM_DESCRIPTION, description);
logicalDevice.setString(PARAM_GROUP, groupNrS + " " + description);
logicalDevice.setInteger(PARAM_INDEX, groupIndex);
add(exportList, logicalDevice);
groupIndex += 10;
logger.info("Added PlcLogicalDevice " + logicalDevice.getId());
}
case "Input" -> {
if (isEmpty(resource))
throw new IllegalStateException("resource missing for: " + record);
if (isEmpty(action1))
throw new IllegalStateException("action1 missing for: " + record);
if (isEmpty(connection))
throw new IllegalStateException("connection missing for: " + record);
if (logicalDevice == null)
throw new IllegalStateException(
"No PlcLogicalDevice exists for address with keys " + resource + "-" + action1);
String subType = record.get("SubType").trim();
if (isEmpty(connection))
throw new IllegalStateException("SubType missing for: " + record);
String address = evaluateAddress(subType, record, connection);
Resource addressR = addressT.getClone();
addressR.setId("A_" + key);
addressR.setName(keyName);
addressR.setString(PARAM_DESCRIPTION, description);
addressR.setString(PARAM_ADDRESS, address);
addressR.setString(PARAM_RESOURCE, resource);
addressR.setString(PARAM_ACTION, action1);
if (record.isSet("Inverted"))
addressR.setBoolean(PARAM_INVERTED, Boolean.parseBoolean(record.get("Inverted").trim()));
if (record.isSet("Remote"))
addressR.setBoolean(PARAM_REMOTE, Boolean.parseBoolean(record.get("Remote").trim()));
addressR.setInteger(PARAM_INDEX, addressIndex);
addressIndex += 10;
BooleanParameter valueP = new BooleanParameter(PARAM_VALUE, "Value", false);
valueP.setIndex(100);
addressR.addParameter(valueP);
add(exportList, addressR);
logicalDevice.addRelation(PARAM_ADDRESSES, addressR);
logger.info(
"Added Boolean PlcAddress " + addressR.getId() + " " + addressR.getName() + " for address "
+ address);
}
case "Output" -> {
if (isEmpty(resource))
throw new IllegalStateException("resource missing for: " + record);
if (isEmpty(action1))
throw new IllegalStateException("action1 missing for: " + record);
if (isEmpty(connection))
throw new IllegalStateException("connection missing for: " + record);
if (logicalDevice == null)
throw new IllegalStateException(
"No PlcLogicalDevice exists for address with keys " + resource + "-" + action1);
String subType = record.get("SubType").trim();
if (isEmpty(connection))
throw new IllegalStateException("SubType missing for: " + record);
String address = evaluateAddress(subType, record, connection);
Resource telegramR;
BooleanParameter valueP;
// action1 value
telegramR = telegramT.getClone();
telegramR.setId("T_" + key);
telegramR.setName(keyName);
telegramR.setString(PARAM_DESCRIPTION, description);
telegramR.setString(PARAM_ADDRESS, address);
telegramR.setString(PARAM_RESOURCE, resource);
telegramR.setString(PARAM_ACTION, action1);
if (record.isSet("Remote"))
telegramR.setBoolean(PARAM_REMOTE, Boolean.parseBoolean(record.get("Remote").trim()));
telegramR.setInteger(PARAM_INDEX, telegramIndex);
telegramIndex += 10;
valueP = new BooleanParameter(PARAM_VALUE, "Value", true);
valueP.setIndex(100);
telegramR.addParameter(valueP);
add(exportList, telegramR);
logicalDevice.addRelation(PARAM_TELEGRAMS, telegramR);
logger.info("Added Boolean PlcTelegram " + telegramR.getId() + " " + telegramR.getName()
+ " for address " + address);
// action2 value
if (record.isSet("Action2") && isNotEmpty(record.get("Action2").trim())) {
String action2 = record.get("Action2").trim();
telegramR = telegramT.getClone();
telegramR.setId("T_" + resource + "-" + action2);
telegramR.setName(resource + " - " + action2);
telegramR.setString(PARAM_DESCRIPTION, description);
telegramR.setString(PARAM_ADDRESS, address);
telegramR.setString(PARAM_RESOURCE, resource);
telegramR.setString(PARAM_ACTION, action2);
if (record.isSet("Remote"))
telegramR.setBoolean(PARAM_REMOTE, Boolean.parseBoolean(record.get("Remote").trim()));
telegramR.setInteger(PARAM_INDEX, telegramIndex);
telegramIndex += 10;
valueP = new BooleanParameter(PARAM_VALUE, "Value", false);
valueP.setIndex(100);
telegramR.addParameter(valueP);
add(exportList, telegramR);
logicalDevice.addRelation(PARAM_TELEGRAMS, telegramR);
logger.info("Added Boolean PlcTelegram " + telegramR.getId() + " " + telegramR.getName()
+ " for address " + address);
case "Group" -> {
groupNr++;
addressIndex = 10;
telegramIndex = 10;
String deviceId = record.get("DeviceId").trim();
if (isEmpty(deviceId))
throw new IllegalStateException("No device for new group: " + record);
logicalDevice = logicalDeviceT.getClone();
logicalDevice.setId("D_" + deviceId);
logicalDevice.setName(deviceId);
String groupNrS = normalizeLength(Integer.toString(groupNr), 2, true, '0');
logicalDevice.setString(PARAM_DESCRIPTION, description);
logicalDevice.setString(PARAM_GROUP, groupNrS + " " + description);
logicalDevice.setInteger(PARAM_INDEX, groupIndex);
add(exportList, logicalDevice);
groupIndex += 10;
logger.info("Added PlcLogicalDevice {}", logicalDevice.getId());
}
case "Input" -> {
// validate address exists for this address
if (exportList.values().stream().filter(e -> e.getType().equals(TYPE_PLC_ADDRESS))
.noneMatch(e -> e.getString(PARAM_ADDRESS).equals(address))) {
if (isEmpty(resource))
throw new IllegalStateException("resource missing for: " + record);
if (isEmpty(action1))
throw new IllegalStateException("action1 missing for: " + record);
if (isEmpty(connection))
throw new IllegalStateException("connection missing for: " + record);
if (logicalDevice == null)
throw new IllegalStateException(
"No PlcLogicalDevice exists for address with keys " + resource + "-" + action1);
String subType = record.get("SubType").trim();
if (isEmpty(connection))
throw new IllegalStateException("SubType missing for: " + record);
String address = evaluateAddress(subType, record, connection);
Resource addressR = addressT.getClone();
addressR.setId("A_" + key);
@ -255,76 +152,52 @@ public class PlcAddressGenerator {
addressR.setString(PARAM_ADDRESS, address);
addressR.setString(PARAM_RESOURCE, resource);
addressR.setString(PARAM_ACTION, action1);
if (record.isSet("Inverted"))
addressR.setBoolean(PARAM_INVERTED, Boolean.parseBoolean(record.get("Inverted").trim()));
if (record.isSet("Remote"))
addressR.setBoolean(PARAM_REMOTE, Boolean.parseBoolean(record.get("Remote").trim()));
addressR.setInteger(PARAM_INDEX, addressIndex);
addressIndex += 10;
valueP = new BooleanParameter(PARAM_VALUE, "Value", false);
BooleanParameter valueP = new BooleanParameter(PARAM_VALUE, "Value", false);
valueP.setIndex(100);
addressR.addParameter(valueP);
add(exportList, addressR);
logicalDevice.addRelation(PARAM_ADDRESSES, addressR);
logger.info("Added missing Boolean PlcAddress " + addressR.getId() + " " + addressR.getName()
+ " for address " + address);
logger.info("Added Boolean PlcAddress {} {} for address {}", addressR.getId(),
addressR.getName(), address);
}
}
case "Virtual" -> {
case "Output" -> {
if (isEmpty(resource))
throw new IllegalStateException("resource missing for: " + record);
if (isEmpty(action1))
throw new IllegalStateException("action1 missing for: " + record);
if (isEmpty(connection))
throw new IllegalStateException("connection missing for: " + record);
if (logicalDevice == null)
throw new IllegalStateException(
"No PlcLogicalDevice exists for address with keys " + resource + "-" + action1);
if (isEmpty(resource))
throw new IllegalStateException("resource missing for: " + record);
if (isEmpty(action1))
throw new IllegalStateException("action1 missing for: " + record);
if (isEmpty(connection))
throw new IllegalStateException("connection missing for: " + record);
if (logicalDevice == null)
throw new IllegalStateException(
"No PlcLogicalDevice exists for address with keys " + resource + "-" + action1);
String subType = record.get("SubType").trim();
if (isEmpty(connection))
throw new IllegalStateException("SubType missing for: " + record);
String subType = record.get("SubType").trim();
if (isEmpty(connection))
throw new IllegalStateException("SubType missing for: " + record);
Resource telegramR;
String address = evaluateAddress(subType, record, connection);
String value = record.isSet("Value") ? record.get("Value") : null;
Resource telegramR;
BooleanParameter valueP;
switch (subType) {
case "Boolean" -> {
// address for virtual boolean
Resource addressR = addressT.getClone();
addressR.setId("A_" + key);
addressR.setName(keyName);
addressR.setString(PARAM_DESCRIPTION, description);
addressR.setString(PARAM_ADDRESS, connection);
addressR.setString(PARAM_RESOURCE, resource);
addressR.setString(PARAM_ACTION, action1);
if (record.isSet("Remote"))
addressR.setBoolean(PARAM_REMOTE, Boolean.parseBoolean(record.get("Remote").trim()));
addressR.setInteger(PARAM_INDEX, addressIndex);
addressIndex += 10;
Parameter<?> valueP = new BooleanParameter(PARAM_VALUE, "Value", false);
valueP.setIndex(100);
addressR.addParameter(valueP);
add(exportList, addressR);
logicalDevice.addRelation(PARAM_ADDRESSES, addressR);
logger.info("Added Virtual Boolean PlcAddress " + addressR.getId() + " " + addressR.getName()
+ " for connection " + connection);
// telegram for action1
// action1 value
telegramR = telegramT.getClone();
telegramR.setId("T_" + key);
telegramR.setName(keyName);
telegramR.setString(PARAM_DESCRIPTION, description);
telegramR.setString(PARAM_ADDRESS, connection);
telegramR.setString(PARAM_ADDRESS, address);
telegramR.setString(PARAM_RESOURCE, resource);
telegramR.setString(PARAM_ACTION, action1);
if (record.isSet("Remote"))
@ -339,20 +212,19 @@ public class PlcAddressGenerator {
add(exportList, telegramR);
logicalDevice.addRelation(PARAM_TELEGRAMS, telegramR);
logger.info("Added Virtual Boolean PlcTelegram " + telegramR.getId() + " " + telegramR.getName()
+ " for connection " + connection);
logger.info("Added Boolean PlcTelegram {} {} for address {}", telegramR.getId(),
telegramR.getName(), address);
// telegram for action2
// action2 value
if (record.isSet("Action2") && isNotEmpty(record.get("Action2").trim())) {
String action2 = record.get("Action2").trim();
key = resource + "-" + action2;
keyName = resource + " - " + action2;
telegramR = telegramT.getClone();
telegramR.setId("T_" + key);
telegramR.setName(keyName);
telegramR.setId("T_" + resource + "-" + action2);
telegramR.setName(resource + " - " + action2);
telegramR.setString(PARAM_DESCRIPTION, description);
telegramR.setString(PARAM_ADDRESS, connection);
telegramR.setString(PARAM_ADDRESS, address);
telegramR.setString(PARAM_RESOURCE, resource);
telegramR.setString(PARAM_ACTION, action2);
if (record.isSet("Remote"))
@ -367,238 +239,378 @@ public class PlcAddressGenerator {
add(exportList, telegramR);
logicalDevice.addRelation(PARAM_TELEGRAMS, telegramR);
logger.info(
"Added Virtual Boolean PlcTelegram " + telegramR.getId() + " " + telegramR.getName()
+ " for connection " + connection);
logger.info("Added Boolean PlcTelegram {} {} for address {}", telegramR.getId(),
telegramR.getName(), address);
}
// validate address exists for this address
if (exportList
.values()
.stream()
.filter(e -> e.getType().equals(TYPE_PLC_ADDRESS))
.noneMatch(e -> e.getString(PARAM_ADDRESS).equals(address))) {
Resource addressR = addressT.getClone();
addressR.setId("A_" + key);
addressR.setName(keyName);
addressR.setString(PARAM_DESCRIPTION, description);
addressR.setString(PARAM_ADDRESS, address);
addressR.setString(PARAM_RESOURCE, resource);
addressR.setString(PARAM_ACTION, action1);
if (record.isSet("Remote"))
addressR.setBoolean(PARAM_REMOTE, Boolean.parseBoolean(record.get("Remote").trim()));
addressR.setInteger(PARAM_INDEX, addressIndex);
addressIndex += 10;
valueP = new BooleanParameter(PARAM_VALUE, "Value", false);
valueP.setIndex(100);
addressR.addParameter(valueP);
add(exportList, addressR);
logicalDevice.addRelation(PARAM_ADDRESSES, addressR);
logger.info("Added missing Boolean PlcAddress {} {} for address {}", addressR.getId(),
addressR.getName(), address);
}
}
case "String" -> {
case "Virtual" -> {
// address for virtual string
Resource addressR = addressT.getClone();
if (isEmpty(resource))
throw new IllegalStateException("resource missing for: " + record);
if (isEmpty(action1))
throw new IllegalStateException("action1 missing for: " + record);
if (isEmpty(connection))
throw new IllegalStateException("connection missing for: " + record);
if (logicalDevice == null)
throw new IllegalStateException(
"No PlcLogicalDevice exists for address with keys " + resource + "-" + action1);
String subType = record.get("SubType").trim();
if (isEmpty(connection))
throw new IllegalStateException("SubType missing for: " + record);
Resource telegramR;
String value = record.isSet("Value") ? record.get("Value") : null;
switch (subType) {
case "Boolean" -> {
// address for virtual boolean
Resource addressR = addressT.getClone();
addressR.setId("A_" + key);
addressR.setName(keyName);
addressR.setString(PARAM_DESCRIPTION, description);
addressR.setString(PARAM_ADDRESS, connection);
addressR.setString(PARAM_RESOURCE, resource);
addressR.setString(PARAM_ACTION, action1);
if (record.isSet("Remote"))
addressR.setBoolean(PARAM_REMOTE,
Boolean.parseBoolean(record.get("Remote").trim()));
addressR.setInteger(PARAM_INDEX, addressIndex);
addressIndex += 10;
Parameter<?> valueP = new BooleanParameter(PARAM_VALUE, "Value", false);
valueP.setIndex(100);
addressR.addParameter(valueP);
add(exportList, addressR);
logicalDevice.addRelation(PARAM_ADDRESSES, addressR);
logger.info("Added Virtual Boolean PlcAddress {} {} for connection {}",
addressR.getId(), addressR.getName(), connection);
// telegram for action1
telegramR = telegramT.getClone();
telegramR.setId("T_" + key);
telegramR.setName(keyName);
telegramR.setString(PARAM_DESCRIPTION, description);
telegramR.setString(PARAM_ADDRESS, connection);
telegramR.setString(PARAM_RESOURCE, resource);
telegramR.setString(PARAM_ACTION, action1);
if (record.isSet("Remote"))
telegramR.setBoolean(PARAM_REMOTE,
Boolean.parseBoolean(record.get("Remote").trim()));
telegramR.setInteger(PARAM_INDEX, telegramIndex);
telegramIndex += 10;
valueP = new BooleanParameter(PARAM_VALUE, "Value", true);
valueP.setIndex(100);
telegramR.addParameter(valueP);
add(exportList, telegramR);
logicalDevice.addRelation(PARAM_TELEGRAMS, telegramR);
logger.info("Added Virtual Boolean PlcTelegram {} {} for connection {}",
telegramR.getId(), telegramR.getName(), connection);
// telegram for action2
if (record.isSet("Action2") && isNotEmpty(record.get("Action2").trim())) {
String action2 = record.get("Action2").trim();
key = resource + "-" + action2;
keyName = resource + " - " + action2;
telegramR = telegramT.getClone();
telegramR.setId("T_" + key);
telegramR.setName(keyName);
telegramR.setString(PARAM_DESCRIPTION, description);
telegramR.setString(PARAM_ADDRESS, connection);
telegramR.setString(PARAM_RESOURCE, resource);
telegramR.setString(PARAM_ACTION, action2);
if (record.isSet("Remote"))
telegramR.setBoolean(PARAM_REMOTE,
Boolean.parseBoolean(record.get("Remote").trim()));
telegramR.setInteger(PARAM_INDEX, telegramIndex);
telegramIndex += 10;
valueP = new BooleanParameter(PARAM_VALUE, "Value", false);
valueP.setIndex(100);
telegramR.addParameter(valueP);
add(exportList, telegramR);
logicalDevice.addRelation(PARAM_TELEGRAMS, telegramR);
logger.info("Added Virtual Boolean PlcTelegram {} {} for connection {}",
telegramR.getId(), telegramR.getName(), connection);
}
}
case "String" -> {
// address for virtual string
Resource addressR = addressT.getClone();
addressR.setId("A_" + key);
addressR.setName(keyName);
addressR.setString(PARAM_DESCRIPTION, description);
addressR.setString(PARAM_ADDRESS, connection);
addressR.setString(PARAM_RESOURCE, resource);
addressR.setString(PARAM_ACTION, action1);
if (record.isSet("Remote"))
addressR.setBoolean(PARAM_REMOTE,
Boolean.parseBoolean(record.get("Remote").trim()));
addressR.setInteger(PARAM_INDEX, addressIndex);
addressIndex += 10;
Parameter<?> valueP = new StringParameter(PARAM_VALUE, "Value",
value == null ? "" : value);
valueP.setIndex(100);
addressR.addParameter(valueP);
add(exportList, addressR);
logicalDevice.addRelation(PARAM_ADDRESSES, addressR);
logger.info("Added Virtual String PlcAddress {} {} for connection {}", addressR.getId(),
addressR.getName(), connection);
// telegram for action1
telegramR = telegramT.getClone();
telegramR.setId("T_" + key);
telegramR.setName(keyName);
telegramR.setString(PARAM_DESCRIPTION, description);
telegramR.setString(PARAM_ADDRESS, connection);
telegramR.setString(PARAM_RESOURCE, resource);
telegramR.setString(PARAM_ACTION, action1);
if (record.isSet("Remote"))
telegramR.setBoolean(PARAM_REMOTE,
Boolean.parseBoolean(record.get("Remote").trim()));
telegramR.setInteger(PARAM_INDEX, telegramIndex);
telegramIndex += 10;
valueP = new StringParameter(PARAM_VALUE, "Value", "");
valueP.setIndex(100);
telegramR.addParameter(valueP);
add(exportList, telegramR);
logicalDevice.addRelation(PARAM_TELEGRAMS, telegramR);
logger.info("Added Virtual String PlcTelegram {} {} for connection {}",
telegramR.getId(), telegramR.getName(), connection);
}
case "Integer" -> {
// address for virtual integer
Resource addressR = addressT.getClone();
addressR.setId("A_" + key);
addressR.setName(keyName);
addressR.setString(PARAM_DESCRIPTION, description);
addressR.setString(PARAM_ADDRESS, connection);
addressR.setString(PARAM_RESOURCE, resource);
addressR.setString(PARAM_ACTION, action1);
if (record.isSet("Remote"))
addressR.setBoolean(PARAM_REMOTE,
Boolean.parseBoolean(record.get("Remote").trim()));
addressR.setInteger(PARAM_INDEX, addressIndex);
addressIndex += 10;
Parameter<?> valueP = new IntegerParameter(PARAM_VALUE, "Value",
value == null ? 0 : parseInt(record.get("Value")));
valueP.setIndex(100);
addressR.addParameter(valueP);
add(exportList, addressR);
logicalDevice.addRelation(PARAM_ADDRESSES, addressR);
logger.info("Added Virtual Integer PlcAddress {} {} for connection {}",
addressR.getId(), addressR.getName(), connection);
// telegram for action1
telegramR = telegramT.getClone();
telegramR.setId("T_" + key);
telegramR.setName(keyName);
telegramR.setString(PARAM_DESCRIPTION, description);
telegramR.setString(PARAM_ADDRESS, connection);
telegramR.setString(PARAM_RESOURCE, resource);
telegramR.setString(PARAM_ACTION, action1);
if (record.isSet("Remote"))
telegramR.setBoolean(PARAM_REMOTE,
Boolean.parseBoolean(record.get("Remote").trim()));
telegramR.setInteger(PARAM_INDEX, telegramIndex);
telegramIndex += 10;
valueP = new IntegerParameter(PARAM_VALUE, "Value",
value == null ? 0 : parseInt(record.get("Value")));
valueP.setIndex(100);
telegramR.addParameter(valueP);
add(exportList, telegramR);
logicalDevice.addRelation(PARAM_TELEGRAMS, telegramR);
logger.info("Added Virtual Integer PlcTelegram {} {} for connection {}",
telegramR.getId(), telegramR.getName(), connection);
}
default -> throw new IllegalArgumentException(
"Unhandled virtual connection " + connection + " for " + resource + "-" + action1);
}
}
case "DataLogicScanner" -> {
if (isEmpty(resource))
throw new IllegalStateException("resource missing for: " + record);
if (logicalDevice == null)
throw new IllegalStateException(
"No PlcLogicalDevice exists for address with keys " + resource + "-" + action1);
Resource addressR;
Resource telegramR;
// address for barcode
key = resource + "-Barcode";
keyName = resource + " - Barcode";
addressR = addressT.getClone();
addressR.setId("A_" + key);
addressR.setName(keyName);
addressR.setString(PARAM_DESCRIPTION, description);
addressR.setString(PARAM_ADDRESS, connection);
addressR.setString(PARAM_ADDRESS, connection + ".barcode");
addressR.setString(PARAM_RESOURCE, resource);
addressR.setString(PARAM_ACTION, action1);
addressR.setString(PARAM_ACTION, "Barcode");
if (record.isSet("Remote"))
addressR.setBoolean(PARAM_REMOTE, Boolean.parseBoolean(record.get("Remote").trim()));
addressR.setInteger(PARAM_INDEX, addressIndex);
addressIndex += 10;
Parameter<?> valueP = new StringParameter(PARAM_VALUE, "Value", value == null ? "" : value);
StringParameter valueP = new StringParameter(PARAM_VALUE, "Value", "");
valueP.setIndex(100);
addressR.addParameter(valueP);
add(exportList, addressR);
logicalDevice.addRelation(PARAM_ADDRESSES, addressR);
logger.info("Added Virtual String PlcAddress " + addressR.getId() + " " + addressR.getName()
+ " for connection " + connection);
logger.info("Added DataLogicScanner PlcAddress {} {} for connection {}", addressR.getId(),
addressR.getName(), connection);
// telegram for action1
telegramR = telegramT.getClone();
telegramR.setId("T_" + key);
telegramR.setName(keyName);
telegramR.setString(PARAM_DESCRIPTION, description);
telegramR.setString(PARAM_ADDRESS, connection);
telegramR.setString(PARAM_RESOURCE, resource);
telegramR.setString(PARAM_ACTION, action1);
if (record.isSet("Remote"))
telegramR.setBoolean(PARAM_REMOTE, Boolean.parseBoolean(record.get("Remote").trim()));
telegramR.setInteger(PARAM_INDEX, telegramIndex);
telegramIndex += 10;
valueP = new StringParameter(PARAM_VALUE, "Value", "");
valueP.setIndex(100);
telegramR.addParameter(valueP);
add(exportList, telegramR);
logicalDevice.addRelation(PARAM_TELEGRAMS, telegramR);
logger.info("Added Virtual String PlcTelegram " + telegramR.getId() + " " + telegramR.getName()
+ " for connection " + connection);
}
case "Integer" -> {
// address for virtual integer
Resource addressR = addressT.getClone();
// address for on
key = resource + "-On";
keyName = resource + " - On";
addressR = addressT.getClone();
addressR.setId("A_" + key);
addressR.setName(keyName);
addressR.setString(PARAM_DESCRIPTION, description);
addressR.setString(PARAM_ADDRESS, connection);
addressR.setString(PARAM_ADDRESS, connection + ".trigger");
addressR.setString(PARAM_RESOURCE, resource);
addressR.setString(PARAM_ACTION, action1);
addressR.setString(PARAM_ACTION, "On");
if (record.isSet("Remote"))
addressR.setBoolean(PARAM_REMOTE, Boolean.parseBoolean(record.get("Remote").trim()));
addressR.setInteger(PARAM_INDEX, addressIndex);
addressIndex += 10;
Parameter<?> valueP = new IntegerParameter(PARAM_VALUE, "Value",
value == null ? 0 : parseInt(record.get("Value")));
valueP.setIndex(100);
addressR.addParameter(valueP);
BooleanParameter booleanValueP = new BooleanParameter(PARAM_VALUE, "Value", false);
booleanValueP.setIndex(100);
addressR.addParameter(booleanValueP);
add(exportList, addressR);
logicalDevice.addRelation(PARAM_ADDRESSES, addressR);
logger.info("Added Virtual Integer PlcAddress " + addressR.getId() + " " + addressR.getName()
+ " for connection " + connection);
logger.info("Added DataLogicScanner PlcAddress {} {} for connection {}", addressR.getId(),
addressR.getName(), connection);
// telegram for action1
// telegram for trigger on
telegramR = telegramT.getClone();
telegramR.setId("T_" + key);
telegramR.setName(keyName);
telegramR.setString(PARAM_DESCRIPTION, description);
telegramR.setString(PARAM_ADDRESS, connection);
telegramR.setString(PARAM_ADDRESS, connection + ".trigger");
telegramR.setString(PARAM_RESOURCE, resource);
telegramR.setString(PARAM_ACTION, action1);
telegramR.setString(PARAM_ACTION, "On");
if (record.isSet("Remote"))
telegramR.setBoolean(PARAM_REMOTE, Boolean.parseBoolean(record.get("Remote").trim()));
telegramR.setInteger(PARAM_INDEX, telegramIndex);
telegramIndex += 10;
valueP = new IntegerParameter(PARAM_VALUE, "Value",
value == null ? 0 : parseInt(record.get("Value")));
valueP.setIndex(100);
telegramR.addParameter(valueP);
booleanValueP = new BooleanParameter(PARAM_VALUE, "Value", true);
booleanValueP.setIndex(100);
telegramR.addParameter(booleanValueP);
add(exportList, telegramR);
logicalDevice.addRelation(PARAM_TELEGRAMS, telegramR);
logger.info("Added Virtual Integer PlcTelegram " + telegramR.getId() + " " + telegramR.getName()
+ " for connection " + connection);
logger.info("Added DataLogicScanner PlcTelegram {} {} for connection {}", telegramR.getId(),
telegramR.getName(), connection);
// telegram for trigger off
key = resource + "-Off";
keyName = resource + " - Off";
telegramR = telegramT.getClone();
telegramR.setId("T_" + key);
telegramR.setName(keyName);
telegramR.setString(PARAM_DESCRIPTION, description);
telegramR.setString(PARAM_ADDRESS, connection + ".trigger");
telegramR.setString(PARAM_RESOURCE, resource);
telegramR.setString(PARAM_ACTION, "Off");
if (record.isSet("Remote"))
telegramR.setBoolean(PARAM_REMOTE, Boolean.parseBoolean(record.get("Remote").trim()));
telegramR.setInteger(PARAM_INDEX, telegramIndex);
telegramIndex += 10;
booleanValueP = new BooleanParameter(PARAM_VALUE, "Value", false);
booleanValueP.setIndex(100);
telegramR.addParameter(booleanValueP);
add(exportList, telegramR);
logicalDevice.addRelation(PARAM_TELEGRAMS, telegramR);
logger.info("Added DataLogicScanner PlcTelegram {} {} for connection {}", telegramR.getId(),
telegramR.getName(), connection);
}
default -> throw new IllegalArgumentException(
"Unhandled virtual connection " + connection + " for " + resource + "-" + action1);
}
}
case "DataLogicScanner" -> {
if (isEmpty(resource))
throw new IllegalStateException("resource missing for: " + record);
if (logicalDevice == null)
throw new IllegalStateException(
"No PlcLogicalDevice exists for address with keys " + resource + "-" + action1);
Resource addressR;
Resource telegramR;
// address for barcode
key = resource + "-Barcode";
keyName = resource + " - Barcode";
addressR = addressT.getClone();
addressR.setId("A_" + key);
addressR.setName(keyName);
addressR.setString(PARAM_DESCRIPTION, description);
addressR.setString(PARAM_ADDRESS, connection + ".barcode");
addressR.setString(PARAM_RESOURCE, resource);
addressR.setString(PARAM_ACTION, "Barcode");
if (record.isSet("Remote"))
addressR.setBoolean(PARAM_REMOTE, Boolean.parseBoolean(record.get("Remote").trim()));
addressR.setInteger(PARAM_INDEX, addressIndex);
addressIndex += 10;
StringParameter valueP = new StringParameter(PARAM_VALUE, "Value", "");
valueP.setIndex(100);
addressR.addParameter(valueP);
add(exportList, addressR);
logicalDevice.addRelation(PARAM_ADDRESSES, addressR);
logger.info("Added DataLogicScanner PlcAddress " + addressR.getId() + " " + addressR.getName()
+ " for connection " + connection);
// address for on
key = resource + "-On";
keyName = resource + " - On";
addressR = addressT.getClone();
addressR.setId("A_" + key);
addressR.setName(keyName);
addressR.setString(PARAM_DESCRIPTION, description);
addressR.setString(PARAM_ADDRESS, connection + ".trigger");
addressR.setString(PARAM_RESOURCE, resource);
addressR.setString(PARAM_ACTION, "On");
if (record.isSet("Remote"))
addressR.setBoolean(PARAM_REMOTE, Boolean.parseBoolean(record.get("Remote").trim()));
addressR.setInteger(PARAM_INDEX, addressIndex);
addressIndex += 10;
BooleanParameter booleanValueP = new BooleanParameter(PARAM_VALUE, "Value", false);
booleanValueP.setIndex(100);
addressR.addParameter(booleanValueP);
add(exportList, addressR);
logicalDevice.addRelation(PARAM_ADDRESSES, addressR);
logger.info("Added DataLogicScanner PlcAddress " + addressR.getId() + " " + addressR.getName()
+ " for connection " + connection);
// telegram for trigger on
telegramR = telegramT.getClone();
telegramR.setId("T_" + key);
telegramR.setName(keyName);
telegramR.setString(PARAM_DESCRIPTION, description);
telegramR.setString(PARAM_ADDRESS, connection + ".trigger");
telegramR.setString(PARAM_RESOURCE, resource);
telegramR.setString(PARAM_ACTION, "On");
if (record.isSet("Remote"))
telegramR.setBoolean(PARAM_REMOTE, Boolean.parseBoolean(record.get("Remote").trim()));
telegramR.setInteger(PARAM_INDEX, telegramIndex);
telegramIndex += 10;
booleanValueP = new BooleanParameter(PARAM_VALUE, "Value", true);
booleanValueP.setIndex(100);
telegramR.addParameter(booleanValueP);
add(exportList, telegramR);
logicalDevice.addRelation(PARAM_TELEGRAMS, telegramR);
logger.info("Added DataLogicScanner PlcTelegram " + telegramR.getId() + " " + telegramR.getName()
+ " for connection " + connection);
// telegram for trigger off
key = resource + "-Off";
keyName = resource + " - Off";
telegramR = telegramT.getClone();
telegramR.setId("T_" + key);
telegramR.setName(keyName);
telegramR.setString(PARAM_DESCRIPTION, description);
telegramR.setString(PARAM_ADDRESS, connection + ".trigger");
telegramR.setString(PARAM_RESOURCE, resource);
telegramR.setString(PARAM_ACTION, "Off");
if (record.isSet("Remote"))
telegramR.setBoolean(PARAM_REMOTE, Boolean.parseBoolean(record.get("Remote").trim()));
telegramR.setInteger(PARAM_INDEX, telegramIndex);
telegramIndex += 10;
booleanValueP = new BooleanParameter(PARAM_VALUE, "Value", false);
booleanValueP.setIndex(100);
telegramR.addParameter(booleanValueP);
add(exportList, telegramR);
logicalDevice.addRelation(PARAM_TELEGRAMS, telegramR);
logger.info("Added DataLogicScanner PlcTelegram " + telegramR.getId() + " " + telegramR.getName()
+ " for connection " + connection);
}
default -> throw new IllegalStateException("Unhandled type " + type + " for " + record);
default -> throw new IllegalStateException("Unhandled type " + type + " for " + record);
}
}
}
// validate
boolean valid = true;
MapOfLists<String, Resource> elementsByAddress = exportList.values().stream()
MapOfLists<String, Resource> elementsByAddress = exportList
.values()
.stream()
.filter(e -> !e.getType().equals(TYPE_PLC_LOGICAL_DEVICE))
.collect(MapOfLists::new, (m, e) -> m.addElement(e.getString(PARAM_ADDRESS), e), MapOfLists::addAll);
for (String address : elementsByAddress.keySet()) {
@ -608,21 +620,21 @@ public class PlcAddressGenerator {
List<Resource> addresses = elements.stream().filter(e -> e.getType().equals(TYPE_PLC_ADDRESS)).toList();
if (addresses.size() > 1) {
logger.warn("Multiple elements with address " + address);
logger.warn("Multiple elements with address {}", address);
for (Resource o : elements) {
logger.warn("\t" + o.getId() + " " + o.getName());
logger.warn("\t{} {}", o.getId(), o.getName());
}
valid = false;
}
List<Resource> telegrams = elements.stream().filter(e -> e.getType().equals(TYPE_PLC_TELEGRAM)).toList();
StrolchValueType valueType = addresses.get(0).getParameter(PARAM_VALUE, true).getValueType();
StrolchValueType valueType = addresses.getFirst().getParameter(PARAM_VALUE, true).getValueType();
if (valueType == StrolchValueType.BOOLEAN) {
if (telegrams.size() != 2) {
logger.error("Expected to have 2 telegrams for Boolean address " + address + ", but there are: "
+ telegrams.size());
logger.error("Expected to have 2 telegrams for Boolean address {}, but there are: {}", address,
telegrams.size());
for (Resource telegram : telegrams) {
logger.error("\t" + telegram.getId() + " " + telegram.getName());
logger.error("\t{} {}", telegram.getId(), telegram.getName());
}
valid = false;
} else {
@ -632,26 +644,26 @@ public class PlcAddressGenerator {
boolean value2 = telegram2.getBoolean(PARAM_VALUE);
if (!value1 || value2) {
logger.error("Unexpected values for telegrams: ");
logger.error("\t" + value1 + " for " + telegram1.getId() + " " + telegram1.getName());
logger.error("\t" + value2 + " for " + telegram2.getId() + " " + telegram2.getName());
logger.error("\t{} for {} {}", value1, telegram1.getId(), telegram1.getName());
logger.error("\t{} for {} {}", value2, telegram2.getId(), telegram2.getName());
valid = false;
}
}
} else {
logger.warn("No validation available for value type " + valueType + " and address " + address);
logger.warn("No validation available for value type {} and address {}", valueType, address);
for (Resource element : elements) {
logger.warn("\t" + element.getId() + " " + element.getName());
logger.warn("\t{} {}", element.getId(), element.getName());
}
}
}
if (valid)
logger.info("Validation ok of " + elementsByAddress.size() + " addresses");
logger.info("Validation ok of {} addresses", elementsByAddress.size());
else
logger.error("At least one address is invalid!");
StrolchXmlHelper.writeToFile(exportFile, exportList.values());
logger.info("Wrote " + exportList.size() + " elements to " + exportFile);
logger.info("Wrote {} elements to {}", exportList.size(), exportFile);
}
private String evaluateAddress(String subType, CSVRecord record, String connection) {

View File

@ -13,6 +13,6 @@ public class PlcAddressGeneratorTest {
String importFile = "../example/data/strolch-plc-example.csv";
String exportFile = "../example/data/strolch-plc-example.xml";
PlcAddressGenerator.main(new String[] { templatesFile, importFile, exportFile });
PlcAddressGenerator.main(new String[]{templatesFile, importFile, exportFile});
}
}