[Project] Added JavaDoc to PlcListener, PlcService and PlcAddress

This commit is contained in:
Robert von Burg 2022-07-13 15:17:34 +02:00
parent d28da2163c
commit 56c1fa551e
Signed by: eitch
GPG Key ID: 75DB9C85C74331F7
3 changed files with 366 additions and 4 deletions

View File

@ -26,6 +26,22 @@ import li.strolch.runtime.privilege.PrivilegedRunnableWithResult;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* <p>This is an interface to implement short use cases in a plc.</p>
*
* <p>Each instance of a {@link PlcService} should correspond with one resource on a {@link PlcAddress#resource}.</p>
*
* <p>The service registers for changes on the hardware, e.g. button presses, light barriers, etc. and then performs a
* given action, e.g. turning a motor on or off.</p>
*
* <p>The PlcService has the following life cycle:</p>
* <ul>
* <li>{@link #register()}</li>
* <li>{@link #start(StrolchTransaction)}</li>
* <li>{@link #stop()}</li>
* <li>{@link #unregister()}</li>
* </ul>
*/
public abstract class PlcService implements PlcListener {
protected static final Logger logger = LoggerFactory.getLogger(PlcService.class);
@ -49,64 +65,193 @@ public abstract class PlcService implements PlcListener {
// no-op
}
/**
* Called to initialize this service, here one would read the model state of a given address using
* {@link #getAddressState(StrolchTransaction, String, String)}
*
* @param tx
* the transaction giving access to the model
*/
public void start(StrolchTransaction tx) {
this.state = PlcServiceState.Started;
}
/**
* Called to stop the plc service. Here you would cancel any scheduled tasks.
*/
public void stop() {
this.state = PlcServiceState.Stopped;
}
/**
* Called to register this service for all relevant {@link PlcAddress}
*/
public void register() {
this.state = PlcServiceState.Registered;
}
/**
* Called to unregister this service from previously registered addresses
*/
public void unregister() {
this.state = PlcServiceState.Unregistered;
}
/**
* Register this service with the given resource and action
*
* @param resource
* the resource ID
* @param action
* the action
*/
public void register(String resource, String action) {
this.plcHandler.register(resource, action, this);
}
/**
* Unregister this service with the given resource and action
*
* @param resource
* the resource ID
* @param action
* the action
*/
public void unregister(String resource, String action) {
this.plcHandler.unregister(resource, action, this);
}
/**
* Returns the {@link Resource} of type #TYPE_PLC_ADDRESS for the given resource and action
*
* @param tx
* the current TX
* @param resource
* the resource
* @param action
* the action
*
* @return the {@link Resource}
*/
protected Resource getPlcAddress(StrolchTransaction tx, String resource, String action) {
String plcAddressId = this.plcHandler.getPlcAddressId(resource, action);
return tx.getResourceBy(TYPE_PLC_ADDRESS, plcAddressId, true);
}
/**
* Returns the value of a plc address by calling {@link #getPlcAddress(StrolchTransaction, String, String)} for the
* given resource and action
*
* @param tx
* the current TX
* @param resource
* the resource
* @param action
* the action
* @param <T>
* the type of value to return
*
* @return the value of the given address
*/
protected <T> T getAddressState(StrolchTransaction tx, String resource, String action) {
Parameter<T> addressParam = getPlcAddress(tx, resource, action).getParameter(PARAM_VALUE, true);
return addressParam.getValue();
}
/**
* Enables an operations log message to be seen by a user
*
* @param addressKey
* the address for which the message is enabled
* @param bundle
* the resource bundle containing the message
* @param severity
* the severity of the message
*/
protected void enableMsg(PlcAddressKey addressKey, ResourceBundle bundle, LogSeverity severity) {
sendMsg(logMessageFor(addressKey, bundle, severity, LogMessageState.Active));
}
/**
* Disables an operations log message which was previously enabled
*
* @param addressKey
* the address for which the message was enabled
*/
protected void disableMsg(PlcAddressKey addressKey) {
disableMsg(Locator.valueOf("Plc", this.plcHandler.getPlcId(), addressKey.resource, addressKey.action));
}
/**
* Enables an operations log message to be seen by a user
*
* @param i18nKey
* the key of the message in the resource bundle
* @param bundle
* the resource bundle containing the message
* @param severity
* the severity of the message
*/
protected void enableMsg(String i18nKey, ResourceBundle bundle, LogSeverity severity) {
sendMsg(logMessageFor(i18nKey, bundle, severity, LogMessageState.Active));
}
/**
* Disables an operations log message which was previously enabled
*
* @param i18nKey
* the key of the message in the resource bundle for which the message was enabled
* @param bundle
* the resource bundle containing the message
*/
protected void disableMsg(String i18nKey, ResourceBundle bundle) {
disableMsg(Locator.valueOf("Plc", this.plcHandler.getPlcId(), bundle.getBaseBundleName(), i18nKey));
}
/**
* Sends a message created for the given properties to a remote listener
*
* @param i18nKey
* the key of the message
* @param bundle
* the bundle containing the key
* @param severity
* the severity of the message
*/
protected void sendMsg(String i18nKey, ResourceBundle bundle, LogSeverity severity) {
sendMsg(logMessageFor(i18nKey, bundle, severity));
}
/**
* Creates a {@link LogMessage} for the given fields
*
* @param addressKey
* the address for the key
* @param bundle
* the bundle containing the message
* @param severity
* the severity of the message
*
* @return the {@link LogMessage} instance
*/
protected LogMessage logMessageFor(PlcAddressKey addressKey, ResourceBundle bundle, LogSeverity severity) {
return logMessageFor(addressKey, bundle, severity, LogMessageState.Information);
}
/**
* Creates a {@link LogMessage} for the given fields
*
* @param addressKey
* the address for the key
* @param bundle
* the bundle containing the message
* @param severity
* the severity of the message
* @param state
* the state of the message
*
* @return the {@link LogMessage} instance
*/
protected LogMessage logMessageFor(PlcAddressKey addressKey, ResourceBundle bundle, LogSeverity severity,
LogMessageState state) {
return new LogMessage(DEFAULT_REALM, this.plcHandler.getPlcId(),
@ -114,10 +259,36 @@ public abstract class PlcService implements PlcListener {
state, bundle, addressKey.toKey());
}
/**
* Creates a {@link LogMessage} for the given fields
*
* @param i18nKey
* the key of the message
* @param bundle
* the bundle containing the message
* @param severity
* the severity of the message
*
* @return the {@link LogMessage} instance
*/
protected LogMessage logMessageFor(String i18nKey, ResourceBundle bundle, LogSeverity severity) {
return logMessageFor(i18nKey, bundle, severity, LogMessageState.Information);
}
/**
* Creates a {@link LogMessage} for the given fields
*
* @param i18nKey
* the key of the message
* @param bundle
* the bundle containing the message
* @param severity
* the severity of the message
* @param state
* the state of the message
*
* @return the {@link LogMessage} instance
*/
protected LogMessage logMessageFor(String i18nKey, ResourceBundle bundle, LogSeverity severity,
LogMessageState state) {
return new LogMessage(DEFAULT_REALM, this.plcHandler.getPlcId(),
@ -125,6 +296,12 @@ public abstract class PlcService implements PlcListener {
state, bundle, i18nKey);
}
/**
* Sends the given {@link LogMessage} to the remote listener
*
* @param logMessage
* the message to send
*/
protected void sendMsg(LogMessage logMessage) {
switch (logMessage.getSeverity()) {
case Info, Notification -> logger.info(logMessage.toString());
@ -134,47 +311,119 @@ public abstract class PlcService implements PlcListener {
this.plcHandler.sendMsg(logMessage);
}
/**
* Disables a message with the given {@link Locator}
*
* @param locator
* the locator of the message
*/
protected void disableMsg(Locator locator) {
logger.info("Disabling message for locator " + locator);
this.plcHandler.disableMsg(locator);
}
/**
* Causes the {@link PlcAddress} for the given resource and action to be sent as a telegram with its default value
*
* @param resource
* the resource
* @param action
* the action
*/
protected void send(String resource, String action) {
this.plcHandler.send(resource, action);
}
/**
* Causes the {@link PlcAddress} for the given resource and action to be sent as a telegram with the given value
*
* @param resource
* the resource
* @param action
* the action
* @param value
* the value to send with the {@link PlcAddress}
*/
protected void send(String resource, String action, Object value) {
this.plcHandler.send(resource, action, value);
}
/**
* Notifies listeners on the {@link PlcAddress} for the given resource and action, of the new value
*
* @param resource
* the resource
* @param action
* the action
* @param value
* the value to notify the listeners with
*/
protected void notify(String resource, String action, Object value) {
this.plcHandler.notify(resource, action, value);
}
protected PlcAddressKey keyFor(String resource, String action) {
return PlcAddressKey.keyFor(resource, action);
}
/**
* Runs the given {@link PrivilegedRunnable} as the agent user
*
* @param runnable
* the runnable to run
*/
protected void run(PrivilegedRunnable runnable) throws Exception {
this.container.getPrivilegeHandler().runAsAgent(runnable);
}
/**
* Runs the given {@link PrivilegedRunnableWithResult} as the agent user, returning a value as the result
*
* @param runnable
* the runnable to run
* @param <T>
* the type of object being returned in the runnable
*
* @return the result of the runnable
*/
protected <T> T runWithResult(PrivilegedRunnableWithResult<T> runnable) throws Exception {
return this.container.getPrivilegeHandler().runAsAgentWithResult(runnable);
}
/**
* Opens a new {@link StrolchTransaction} with the given {@link PrivilegeContext}
*
* @param ctx
* the {@link PrivilegeContext}
* @param readOnly
* true for the TX to be read only
*
* @return the new TX to be used in a try-with-resource block
*/
protected StrolchTransaction openTx(PrivilegeContext ctx, boolean readOnly) {
return this.container.getRealm(ctx.getCertificate()).openTx(ctx.getCertificate(), getCallerMethod(2), readOnly);
}
/**
* Returns the {@link ExecutorService} for this class
*
* @return the executor
*/
private ExecutorService getExecutor() {
return this.container.getAgent().getExecutor(getClass().getSimpleName());
}
/**
* Returns the {@link ScheduledExecutorService} for this class
*
* @return the scheduled executor
*/
private ScheduledExecutorService getScheduledExecutor() {
return this.container.getAgent().getScheduledExecutor(getClass().getSimpleName());
}
/**
* Submits the given runnable for asynchronous execution
*
* @param runnable
* the runnable to execute asynchronously
*/
protected void async(Runnable runnable) {
getExecutor().submit(() -> {
try {
@ -185,6 +434,18 @@ public abstract class PlcService implements PlcListener {
});
}
/**
* Delay the execution of the given {@link Runnable} by the given delay
*
* @param runnable
* the runnable to delay
* @param delay
* the time to delay
* @param delayUnit
* the unit of the time to delay
*
* @return a future to cancel the executor before execution
*/
protected ScheduledFuture<?> schedule(Runnable runnable, long delay, TimeUnit delayUnit) {
return getScheduledExecutor().schedule(() -> {
try {
@ -195,6 +456,18 @@ public abstract class PlcService implements PlcListener {
}, delay, delayUnit);
}
/**
* Delay the execution of the given {@link PrivilegedRunnable} by the given delay
*
* @param runnable
* the runnable to delay
* @param delay
* the time to delay
* @param delayUnit
* the unit of the time to delay
*
* @return a future to cancel the executor before execution
*/
protected ScheduledFuture<?> schedule(PrivilegedRunnable runnable, long delay, TimeUnit delayUnit) {
return getScheduledExecutor().schedule(() -> {
try {
@ -205,6 +478,20 @@ public abstract class PlcService implements PlcListener {
}, delay, delayUnit);
}
/**
* Submit the given {@link Runnable} for repeated execution
*
* @param runnable
* the runnable to delay
* @param initialDelay
* the initial delay
* @param period
* the delay between subsequent executions
* @param delayUnit
* the unit of the time to delay
*
* @return a future to cancel the executor before execution
*/
protected ScheduledFuture<?> scheduleAtFixedRate(Runnable runnable, long initialDelay, long period,
TimeUnit delayUnit) {
return getScheduledExecutor().scheduleAtFixedRate(() -> {
@ -216,6 +503,20 @@ public abstract class PlcService implements PlcListener {
}, initialDelay, period, delayUnit);
}
/**
* Submit the given {@link PrivilegedRunnable} for repeated execution
*
* @param runnable
* the runnable to delay
* @param initialDelay
* the initial delay
* @param period
* the delay between subsequent executions
* @param delayUnit
* the unit of the time to delay
*
* @return a future to cancel the executor before execution
*/
protected ScheduledFuture<?> scheduleAtFixedRate(PrivilegedRunnable runnable, long initialDelay, long period,
TimeUnit delayUnit) {
return getScheduledExecutor().scheduleAtFixedRate(() -> {
@ -227,6 +528,20 @@ public abstract class PlcService implements PlcListener {
}, initialDelay, period, delayUnit);
}
/**
* Submit the given {@link Runnable} for repeated execution
*
* @param runnable
* the runnable to delay
* @param initialDelay
* the initial delay
* @param period
* the delay between subsequent executions
* @param delayUnit
* the unit of the time to delay
*
* @return a future to cancel the executor before execution
*/
protected ScheduledFuture<?> scheduleWithFixedDelay(Runnable runnable, long initialDelay, long period,
TimeUnit delayUnit) {
return getScheduledExecutor().scheduleWithFixedDelay(() -> {
@ -238,6 +553,20 @@ public abstract class PlcService implements PlcListener {
}, initialDelay, period, delayUnit);
}
/**
* Submit the given {@link PrivilegedRunnable} for repeated execution
*
* @param runnable
* the runnable to delay
* @param initialDelay
* the initial delay
* @param period
* the delay between subsequent executions
* @param delayUnit
* the unit of the time to delay
*
* @return a future to cancel the executor before execution
*/
protected ScheduledFuture<?> scheduleWithFixedDelay(PrivilegedRunnable runnable, long initialDelay, long period,
TimeUnit delayUnit) {
return getScheduledExecutor().scheduleWithFixedDelay(() -> {
@ -249,6 +578,12 @@ public abstract class PlcService implements PlcListener {
}, initialDelay, period, delayUnit);
}
/**
* Notifies the caller of one of the async, or schedule methods that the execution of a runnable failed
*
* @param e
* the exception which occurred
*/
protected void handleFailedSchedule(Exception e) {
logger.error("Failed to execute " + getClass().getSimpleName(), e);
}

View File

@ -1,8 +1,20 @@
package li.strolch.plc.core.hw;
import li.strolch.plc.core.PlcHandler;
import li.strolch.plc.model.PlcAddress;
/**
* The interface which can be notified by the {@link PlcHandler} when an event is detected from the hardware.
*/
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
*/
void handleNotification(PlcAddress address, Object value);
}

View File

@ -4,6 +4,21 @@ import java.util.Objects;
import li.strolch.model.StrolchValueType;
/**
* <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>
* <li>key field as a standard concatenation of resource and action</li>
* <li>key address as a standard representation for logging</li>
* <li>address being the hardware address of this address. I.e. the hardware address to which the resource and action fields are pointing</li>
* <li>{@link StrolchValueType} for this address</li>
* <li>the default value for the action and resource for when sending and notifying</li>
* <li>inverted flag to define if a boolean value should be inverted. This is done by the system and the user need not invert as well</li>
* </ul>
*
* @see PlcAddressKey
*/
public class PlcAddress {
public final PlcAddressType type;