[Major] Implemented basic PlcExecutionPolicy with PlcGwService for activity execution
This commit is contained in:
parent
8d5b7dc4c2
commit
b28e8ad4d8
|
@ -25,6 +25,7 @@ import li.strolch.privilege.model.Certificate;
|
|||
import li.strolch.privilege.model.PrivilegeContext;
|
||||
import li.strolch.runtime.configuration.ComponentConfiguration;
|
||||
import li.strolch.utils.collections.MapOfMaps;
|
||||
import li.strolch.utils.dbc.DBC;
|
||||
|
||||
public class DefaultPlcHandler extends StrolchComponent implements PlcHandler, PlcConnectionStateChangeListener {
|
||||
|
||||
|
@ -59,6 +60,8 @@ public class DefaultPlcHandler extends StrolchComponent implements PlcHandler, P
|
|||
|
||||
@Override
|
||||
public PlcAddress getPlcAddress(String resource, String action) {
|
||||
DBC.PRE.assertNotNull("resource must not be null", resource);
|
||||
DBC.PRE.assertNotEmpty("action must not be empty", action);
|
||||
PlcAddress plcAddress = this.plcAddresses.getElement(resource, action);
|
||||
if (plcAddress == null)
|
||||
throw new IllegalStateException("PlcAddress for " + resource + "-" + action + " does not exist!");
|
||||
|
@ -67,6 +70,8 @@ public class DefaultPlcHandler extends StrolchComponent implements PlcHandler, P
|
|||
|
||||
@Override
|
||||
public String getPlcAddressId(String resource, String action) {
|
||||
DBC.PRE.assertNotNull("resource must not be null", resource);
|
||||
DBC.PRE.assertNotEmpty("action must not be empty", action);
|
||||
PlcAddress plcAddress = getPlcAddress(resource, action);
|
||||
String addressId = this.addressesToResourceId.get(plcAddress);
|
||||
if (addressId == null)
|
||||
|
|
|
@ -81,7 +81,7 @@ public abstract class PlcService implements PlcListener {
|
|||
}
|
||||
|
||||
protected StrolchTransaction openTx(PrivilegeContext ctx, boolean readOnly) {
|
||||
return this.plcHandler.openTx(ctx.getCertificate(), readOnly);
|
||||
return this.container.getRealm(ctx.getCertificate()).openTx(ctx.getCertificate(), getClass(), readOnly);
|
||||
}
|
||||
|
||||
protected void runAsAgent(PrivilegedRunnable runnable) throws Exception {
|
||||
|
|
|
@ -24,6 +24,7 @@ import li.strolch.privilege.model.Certificate;
|
|||
import li.strolch.rest.StrolchSessionHandler;
|
||||
import li.strolch.runtime.configuration.ComponentConfiguration;
|
||||
import li.strolch.utils.collections.MapOfLists;
|
||||
import li.strolch.utils.dbc.DBC;
|
||||
import li.strolch.websocket.WebSocketRemoteIp;
|
||||
|
||||
public class PlcGwServerHandler extends StrolchComponent {
|
||||
|
@ -54,10 +55,13 @@ public class PlcGwServerHandler extends StrolchComponent {
|
|||
}
|
||||
|
||||
public boolean isPlcConnected(String plcId) {
|
||||
DBC.PRE.assertNotEmpty("plcId must not be empty", plcId);
|
||||
return this.plcSessionsByPlcId.containsKey(plcId);
|
||||
}
|
||||
|
||||
public void register(PlcAddressKey addressKey, String plcId, 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<>();
|
||||
|
@ -67,9 +71,13 @@ public class PlcGwServerHandler extends StrolchComponent {
|
|||
synchronized (plcListeners) {
|
||||
plcListeners.addElement(addressKey, listener);
|
||||
}
|
||||
|
||||
logger.info("Registered listener on plc " + plcId + " key " + addressKey + ": " + listener);
|
||||
}
|
||||
|
||||
public void unregister(PlcAddressKey addressKey, String plcId, 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)
|
||||
return;
|
||||
|
@ -77,6 +85,8 @@ public class PlcGwServerHandler extends StrolchComponent {
|
|||
synchronized (plcListeners) {
|
||||
plcListeners.removeElement(addressKey, listener);
|
||||
}
|
||||
|
||||
logger.info("Unregistered listener from plc " + plcId + " key " + addressKey + ": " + listener);
|
||||
}
|
||||
|
||||
public void sendMessage(PlcAddressKey addressKey, String plcId, boolean value,
|
||||
|
|
|
@ -0,0 +1,140 @@
|
|||
package li.strolch.plc.gw.server;
|
||||
|
||||
import java.util.concurrent.ScheduledFuture;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import li.strolch.agent.api.ComponentContainer;
|
||||
import li.strolch.execution.ExecutionHandler;
|
||||
import li.strolch.persistence.api.StrolchTransaction;
|
||||
import li.strolch.plc.model.PlcAddressKey;
|
||||
import li.strolch.plc.model.PlcNotificationListener;
|
||||
import li.strolch.plc.model.PlcServiceState;
|
||||
import li.strolch.privilege.model.PrivilegeContext;
|
||||
import li.strolch.runtime.privilege.PrivilegedRunnable;
|
||||
import li.strolch.runtime.privilege.PrivilegedRunnableWithResult;
|
||||
import li.strolch.utils.dbc.DBC;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public abstract class PlcGwService implements PlcNotificationListener, PlcAddressResponseListener {
|
||||
|
||||
protected static final Logger logger = LoggerFactory.getLogger(PlcGwService.class);
|
||||
protected final String plcId;
|
||||
protected final ComponentContainer container;
|
||||
protected final PlcGwServerHandler plcHandler;
|
||||
|
||||
private PlcServiceState state;
|
||||
|
||||
public PlcGwService(String plcId, ComponentContainer container, PlcGwServerHandler plcHandler) {
|
||||
DBC.PRE.assertNotEmpty("plcId must be set!", plcId);
|
||||
DBC.PRE.assertNotNull("container must be set!", container);
|
||||
DBC.PRE.assertNotNull("plcHandler must be set!", plcHandler);
|
||||
this.plcId = plcId;
|
||||
this.container = container;
|
||||
this.plcHandler = plcHandler;
|
||||
this.state = PlcServiceState.Unregistered;
|
||||
}
|
||||
|
||||
public PlcServiceState getState() {
|
||||
return this.state;
|
||||
}
|
||||
|
||||
public void start(StrolchTransaction tx) {
|
||||
this.state = PlcServiceState.Started;
|
||||
}
|
||||
|
||||
public void stop() {
|
||||
this.state = PlcServiceState.Stopped;
|
||||
}
|
||||
|
||||
public void register() {
|
||||
this.state = PlcServiceState.Registered;
|
||||
}
|
||||
|
||||
public void unregister() {
|
||||
this.state = PlcServiceState.Unregistered;
|
||||
}
|
||||
|
||||
protected void register(PlcAddressKey key) {
|
||||
this.plcHandler.register(key, this.plcId, this);
|
||||
}
|
||||
|
||||
protected void unregister(PlcAddressKey key) {
|
||||
this.plcHandler.unregister(key, this.plcId, this);
|
||||
}
|
||||
|
||||
public void sendMessage(PlcAddressKey addressKey, String plcId, boolean value,
|
||||
PlcAddressResponseListener listener) {
|
||||
this.plcHandler.sendMessage(addressKey, plcId, value, this);
|
||||
}
|
||||
|
||||
public void sendMessage(PlcAddressKey addressKey, String plcId, int value, PlcAddressResponseListener listener) {
|
||||
this.plcHandler.sendMessage(addressKey, plcId, value, this);
|
||||
}
|
||||
|
||||
public void sendMessage(PlcAddressKey addressKey, String plcId, double value, PlcAddressResponseListener listener) {
|
||||
this.plcHandler.sendMessage(addressKey, plcId, value, this);
|
||||
}
|
||||
|
||||
public void sendMessage(PlcAddressKey addressKey, String plcId, String value, PlcAddressResponseListener listener) {
|
||||
this.plcHandler.sendMessage(addressKey, plcId, value, this);
|
||||
}
|
||||
|
||||
public void sendMessage(PlcAddressKey addressKey, String plcId, PlcAddressResponseListener listener) {
|
||||
this.plcHandler.sendMessage(addressKey, plcId, this);
|
||||
}
|
||||
|
||||
protected StrolchTransaction openTx(PrivilegeContext ctx, boolean readOnly) {
|
||||
return this.container.getRealm(ctx.getCertificate()).openTx(ctx.getCertificate(), getClass(), readOnly);
|
||||
}
|
||||
|
||||
protected void runAsAgent(PrivilegedRunnable runnable) throws Exception {
|
||||
this.container.getPrivilegeHandler().runAsAgent(runnable);
|
||||
}
|
||||
|
||||
protected ExecutionHandler getExecutionHandler() {
|
||||
return this.container.getComponent(ExecutionHandler.class);
|
||||
}
|
||||
|
||||
protected <T> T runAsAgentWithResult(PrivilegedRunnableWithResult<T> runnable) throws Exception {
|
||||
return this.container.getPrivilegeHandler().runAsAgentWithResult(runnable);
|
||||
}
|
||||
|
||||
protected ScheduledFuture<?> schedule(PrivilegedRunnable runnable, long delay, TimeUnit delayUnit) {
|
||||
return this.container.getAgent().getScheduledExecutor(PlcGwService.class.getSimpleName()).schedule(() -> {
|
||||
try {
|
||||
this.container.getPrivilegeHandler().runAsAgent(runnable);
|
||||
} catch (Exception e) {
|
||||
handleFailedSchedule(e);
|
||||
}
|
||||
}, delay, delayUnit);
|
||||
}
|
||||
|
||||
protected ScheduledFuture<?> scheduleAtFixedRate(PrivilegedRunnable runnable, long initialDelay, long period,
|
||||
TimeUnit delayUnit) {
|
||||
return this.container.getAgent().getScheduledExecutor(PlcGwService.class.getSimpleName())
|
||||
.scheduleAtFixedRate(() -> {
|
||||
try {
|
||||
this.container.getPrivilegeHandler().runAsAgent(runnable);
|
||||
} catch (Exception e) {
|
||||
handleFailedSchedule(e);
|
||||
}
|
||||
}, initialDelay, period, delayUnit);
|
||||
}
|
||||
|
||||
protected ScheduledFuture<?> scheduleWithFixedDelay(PrivilegedRunnable runnable, long initialDelay, long period,
|
||||
TimeUnit delayUnit) {
|
||||
return this.container.getAgent().getScheduledExecutor(PlcGwService.class.getSimpleName())
|
||||
.scheduleWithFixedDelay(() -> {
|
||||
try {
|
||||
this.container.getPrivilegeHandler().runAsAgent(runnable);
|
||||
} catch (Exception e) {
|
||||
handleFailedSchedule(e);
|
||||
}
|
||||
}, initialDelay, period, delayUnit);
|
||||
}
|
||||
|
||||
protected void handleFailedSchedule(Exception e) {
|
||||
logger.error("Failed to execute " + getClass().getSimpleName(), e);
|
||||
}
|
||||
}
|
|
@ -1,8 +1,6 @@
|
|||
package li.strolch.plc.gw.server.policy.execution;
|
||||
|
||||
import static li.strolch.model.StrolchModelConstants.BAG_PARAMETERS;
|
||||
import static li.strolch.plc.gw.server.PlcServerContants.BUNDLE_STROLCH_PLC_GW_SERVER;
|
||||
import static li.strolch.plc.model.PlcConstants.PARAM_PLC_ID;
|
||||
import static li.strolch.runtime.StrolchConstants.SYSTEM_USER_AGENT;
|
||||
|
||||
import li.strolch.execution.policy.SimpleExecution;
|
||||
|
@ -10,70 +8,62 @@ import li.strolch.handler.operationslog.LogMessage;
|
|||
import li.strolch.handler.operationslog.LogSeverity;
|
||||
import li.strolch.model.Locator;
|
||||
import li.strolch.model.activity.Action;
|
||||
import li.strolch.model.parameter.StringParameter;
|
||||
import li.strolch.persistence.api.StrolchTransaction;
|
||||
import li.strolch.plc.gw.server.PlcGwServerHandler;
|
||||
import li.strolch.plc.model.PlcAddressKey;
|
||||
import li.strolch.plc.model.PlcNotificationListener;
|
||||
import li.strolch.utils.helper.StringHelper;
|
||||
|
||||
public abstract class PlcExecutionPolicy extends SimpleExecution implements PlcNotificationListener {
|
||||
|
||||
private String realm;
|
||||
protected String realm;
|
||||
|
||||
private Locator actionLoc;
|
||||
private String plcId;
|
||||
private PlcGwServerHandler plcHandler;
|
||||
private PlcAddressKey addressKey;
|
||||
protected String actionType;
|
||||
protected Locator actionLoc;
|
||||
|
||||
protected PlcGwServerHandler plcHandler;
|
||||
|
||||
public PlcExecutionPolicy(StrolchTransaction tx) {
|
||||
super(tx);
|
||||
this.realm = tx.getRealmName();
|
||||
}
|
||||
|
||||
protected void initialize(Action action) {
|
||||
this.actionLoc = action.getLocator();
|
||||
protected abstract String getPlcId();
|
||||
|
||||
// set all fields
|
||||
getPlcId(action);
|
||||
getPlcHandler();
|
||||
getAddressKey(action);
|
||||
protected void initialize(Action action) {
|
||||
this.actionType = action.getType();
|
||||
this.actionLoc = action.getLocator();
|
||||
this.plcHandler = getComponent(PlcGwServerHandler.class);
|
||||
}
|
||||
|
||||
protected void toExecuted() {
|
||||
|
||||
unregister();
|
||||
|
||||
long delay = 5L;
|
||||
logger.info(
|
||||
"Delaying toExecuted of " + getActionLoc() + " by " + StringHelper.formatMillisecondsDuration(delay));
|
||||
getDelayedExecutionTimer().execute(this.realm, getContainer(), getActionLoc(), delay);
|
||||
}
|
||||
|
||||
public String getActionType() {
|
||||
return this.actionType;
|
||||
}
|
||||
|
||||
public Locator getActionLoc() {
|
||||
return this.actionLoc;
|
||||
}
|
||||
|
||||
protected String getPlcId(Action action) {
|
||||
if (this.plcId == null) {
|
||||
StringParameter plcIdP = action.findParameter(BAG_PARAMETERS, PARAM_PLC_ID, true);
|
||||
this.plcId = plcIdP.getValue();
|
||||
protected void register() {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
return this.plcId;
|
||||
protected void unregister() {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
protected PlcAddressKey getAddressKey(Action action) {
|
||||
if (this.addressKey == null)
|
||||
this.addressKey = PlcAddressKey.valueOf(action.getResourceId(), action.getType());
|
||||
return this.addressKey;
|
||||
}
|
||||
|
||||
protected PlcGwServerHandler getPlcHandler() {
|
||||
if (this.plcHandler == null)
|
||||
this.plcHandler = getComponent(PlcGwServerHandler.class);
|
||||
return this.plcHandler;
|
||||
}
|
||||
|
||||
protected void register(Action action) {
|
||||
getPlcHandler().register(getAddressKey(action), getPlcId(action), this);
|
||||
}
|
||||
|
||||
protected void unregister(Action action) {
|
||||
getPlcHandler().unregister(getAddressKey(action), getPlcId(action), this);
|
||||
}
|
||||
|
||||
protected boolean assertPlcConnected(Action action) {
|
||||
if (getPlcHandler().isPlcConnected(getPlcId(action)))
|
||||
protected boolean assertPlcConnected() {
|
||||
if (this.plcHandler.isPlcConnected(getPlcId()))
|
||||
return true;
|
||||
|
||||
toError(msgPlcNotConnected(this.realm));
|
||||
|
@ -90,11 +80,11 @@ public abstract class PlcExecutionPolicy extends SimpleExecution implements PlcN
|
|||
|
||||
protected LogMessage msgPlcNotConnected(String realm) {
|
||||
return new LogMessage(realm, SYSTEM_USER_AGENT, getActionLoc(), LogSeverity.Warning,
|
||||
BUNDLE_STROLCH_PLC_GW_SERVER, "execution.plc.notConnected").value("plc", this.plcId);
|
||||
BUNDLE_STROLCH_PLC_GW_SERVER, "execution.plc.notConnected").value("plc", getPlcId());
|
||||
}
|
||||
|
||||
protected LogMessage msgConnectionLostToPlc(String realm) {
|
||||
return new LogMessage(realm, SYSTEM_USER_AGENT, getActionLoc(), LogSeverity.Error, BUNDLE_STROLCH_PLC_GW_SERVER,
|
||||
"execution.plc.connectionLost").value("plc", this.plcId);
|
||||
"execution.plc.connectionLost").value("plc", getPlcId());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,5 +4,7 @@ public interface PlcNotificationListener {
|
|||
|
||||
void handleNotification(PlcAddressKey addressKey, Object value);
|
||||
|
||||
void handleConnectionLost();
|
||||
default void handleConnectionLost() {
|
||||
// no-op
|
||||
}
|
||||
}
|
||||
|
|
|
@ -34,6 +34,14 @@ public class PlcResponse {
|
|||
this.state = state;
|
||||
}
|
||||
|
||||
public boolean isSent() {
|
||||
return this.state == PlcResponseState.Sent;
|
||||
}
|
||||
|
||||
public boolean isFailed() {
|
||||
return this.state == PlcResponseState.Failed;
|
||||
}
|
||||
|
||||
public String getStateMsg() {
|
||||
return this.stateMsg;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue