[New] Added virtual string and boolean connectors

This commit is contained in:
Robert von Burg 2020-01-28 14:35:21 +01:00
parent 96eef75f8c
commit a1429b8d7b
6 changed files with 63 additions and 44 deletions

View File

@ -76,6 +76,10 @@ public abstract class PlcService implements PlcListener {
this.plcHandler.send(resource, action, value); this.plcHandler.send(resource, action, value);
} }
protected void notify(String resource, String action, Object value) {
this.plcHandler.notify(resource, action, value);
}
protected StrolchTransaction openTx(PrivilegeContext ctx, boolean readOnly) { protected StrolchTransaction openTx(PrivilegeContext ctx, boolean readOnly) {
return this.plcHandler.openTx(ctx.getCertificate(), readOnly); return this.plcHandler.openTx(ctx.getCertificate(), readOnly);
} }

View File

@ -2,9 +2,9 @@ package li.strolch.plc.core.hw.connections;
import li.strolch.plc.core.hw.Plc; import li.strolch.plc.core.hw.Plc;
public class InMemoryBooleanConnection extends SimplePlcConnection { public class VirtualBooleanValueConnection extends SimplePlcConnection {
public InMemoryBooleanConnection(Plc plc, String id) { public VirtualBooleanValueConnection(Plc plc, String id) {
super(plc, id); super(plc, id);
} }

View File

@ -0,0 +1,17 @@
package li.strolch.plc.core.hw.connections;
import li.strolch.plc.core.hw.Plc;
public class VirtualStringValueConnection extends SimplePlcConnection {
public VirtualStringValueConnection(Plc plc, String id) {
super(plc, id);
}
@Override
public void send(String address, Object value) {
String string = (String) value;
logger.info("Setting address " + this.id + " to " + string);
this.plc.notify(this.id, string);
}
}

View File

@ -9,7 +9,6 @@ public class StartupPlcService extends PlcService {
public static final String PLC = "PLC"; public static final String PLC = "PLC";
public static final String STARTED = "Started"; public static final String STARTED = "Started";
public static final String STOPPED = "Stopped";
public StartupPlcService(ComponentContainer container, PlcHandler plcHandler) { public StartupPlcService(ComponentContainer container, PlcHandler plcHandler) {
super(container, plcHandler); super(container, plcHandler);
@ -17,13 +16,13 @@ public class StartupPlcService extends PlcService {
@Override @Override
public void start(StrolchTransaction tx) { public void start(StrolchTransaction tx) {
send(PLC, STARTED); notify(PLC, STARTED, true);
super.start(tx); super.start(tx);
} }
@Override @Override
public void stop() { public void stop() {
send(PLC, STOPPED); notify(PLC, STARTED, false);
super.stop(); super.stop();
} }
} }

View File

@ -17,9 +17,17 @@
<!-- <!--
Simple Boolean connection Simple Boolean connection
--> -->
<Resource Id="booleanConnection" Name="Single Boolean PLC Connection" Type="PlcConnection"> <Resource Id="virtualString" Name="Virtual String PLC Connection" Type="PlcConnection">
<ParameterBag Id="parameters" Name="Parameters" Type="Parameters"> <ParameterBag Id="parameters" Name="Parameters" Type="Parameters">
<Parameter Id="className" Name="Connection Class" Type="String" Value="li.strolch.plc.core.hw.connections.InMemoryBooleanConnection"/> <Parameter Id="className" Name="Connection Class" Type="String" Value="li.strolch.plc.core.hw.connections.VirtualStringValueConnection"/>
<Parameter Id="state" Name="Connection State" Type="String" Interpretation="Enumeration" Uom="ConnectionState" Value="Disconnected"/>
<Parameter Id="stateMsg" Name="Connection State Msg" Type="String" Interpretation="Enumeration" Uom="ConnectionState"
Value=""/>
</ParameterBag>
</Resource>
<Resource Id="virtualBoolean" Name="Virtual Boolean PLC Connection" Type="PlcConnection">
<ParameterBag Id="parameters" Name="Parameters" Type="Parameters">
<Parameter Id="className" Name="Connection Class" Type="String" Value="li.strolch.plc.core.hw.connections.VirtualBooleanValueConnection"/>
<Parameter Id="state" Name="Connection State" Type="String" Interpretation="Enumeration" Uom="ConnectionState" Value="Disconnected"/> <Parameter Id="state" Name="Connection State" Type="String" Interpretation="Enumeration" Uom="ConnectionState" Value="Disconnected"/>
<Parameter Id="stateMsg" Name="Connection State Msg" Type="String" Interpretation="Enumeration" Uom="ConnectionState" <Parameter Id="stateMsg" Name="Connection State Msg" Type="String" Interpretation="Enumeration" Uom="ConnectionState"
Value=""/> Value=""/>
@ -95,12 +103,12 @@
<Parameter Id="addresses" Name="Addresses" Type="StringList" Interpretation="Resource-Ref" Uom="PlcAddress" <Parameter Id="addresses" Name="Addresses" Type="StringList" Interpretation="Resource-Ref" Uom="PlcAddress"
Value="addrPlcStarted"/> Value="addrPlcStarted"/>
<Parameter Id="telegrams" Name="Telegrams" Type="StringList" Interpretation="Resource-Ref" Uom="PlcTelegram" <Parameter Id="telegrams" Name="Telegrams" Type="StringList" Interpretation="Resource-Ref" Uom="PlcTelegram"
Value="telPlcStarted, telPlcStopped"/> Value=""/>
</ParameterBag> </ParameterBag>
</Resource> </Resource>
<Resource Id="addrPlcStarted" Name="PLC - Started" Type="PlcAddress"> <Resource Id="addrPlcStarted" Name="PLC - Started" Type="PlcAddress">
<ParameterBag Id="parameters" Name="Parameters" Type="Parameters"> <ParameterBag Id="parameters" Name="Parameters" Type="Parameters">
<Parameter Id="address" Name="HW Address" Type="String" Interpretation="PlcConnection" Value="booleanConnection"/> <Parameter Id="address" Name="HW Address" Type="String" Interpretation="PlcConnection" Value="virtualBoolean"/>
<Parameter Id="resource" Name="Resource ID for PlcAddress" Type="String" Value="PLC"/> <Parameter Id="resource" Name="Resource ID for PlcAddress" Type="String" Value="PLC"/>
<Parameter Id="action" Name="Action ID for PlcAddress" Type="String" Value="Started"/> <Parameter Id="action" Name="Action ID for PlcAddress" Type="String" Value="Started"/>
<Parameter Id="valueType" Name="Value Type" Type="String" Interpretation="Interpretation" Uom="PlcValueType" Value="Boolean"/> <Parameter Id="valueType" Name="Value Type" Type="String" Interpretation="Interpretation" Uom="PlcValueType" Value="Boolean"/>
@ -108,26 +116,6 @@
<Parameter Id="index" Name="Index" Type="Integer" Value="10"/> <Parameter Id="index" Name="Index" Type="Integer" Value="10"/>
</ParameterBag> </ParameterBag>
</Resource> </Resource>
<Resource Id="telPlcStarted" Name="PLC - Started" Type="PlcTelegram">
<ParameterBag Id="parameters" Name="Parameters" Type="Parameters">
<Parameter Id="address" Name="HW Address" Type="String" Interpretation="PlcConnection" Value="booleanConnection"/>
<Parameter Id="resource" Name="Resource ID for PlcAddress" Type="String" Value="PLC"/>
<Parameter Id="action" Name="Action ID for PlcAddress" Type="String" Value="Started"/>
<Parameter Id="valueType" Name="Value Type" Type="String" Interpretation="Interpretation" Uom="PlcValueType" Value="Boolean"/>
<Parameter Id="value" Name="Value" Type="Boolean" Value="true"/>
<Parameter Id="index" Name="Index" Type="Integer" Value="10"/>
</ParameterBag>
</Resource>
<Resource Id="telPlcStopped" Name="PLC - Stopped" Type="PlcTelegram">
<ParameterBag Id="parameters" Name="Parameters" Type="Parameters">
<Parameter Id="address" Name="HW Address" Type="String" Interpretation="PlcConnection" Value="booleanConnection"/>
<Parameter Id="resource" Name="Resource ID for PlcAddress" Type="String" Value="PLC"/>
<Parameter Id="action" Name="Action ID for PlcAddress" Type="String" Value="Stopped"/>
<Parameter Id="valueType" Name="Value Type" Type="String" Interpretation="Interpretation" Uom="PlcValueType" Value="Boolean"/>
<Parameter Id="value" Name="Value" Type="Boolean" Value="false"/>
<Parameter Id="index" Name="Index" Type="Integer" Value="20"/>
</ParameterBag>
</Resource>
<!-- <!--
BarcodeReader BarcodeReader

View File

@ -27,6 +27,7 @@ import li.strolch.agent.api.*;
import li.strolch.model.Resource; import li.strolch.model.Resource;
import li.strolch.model.parameter.StringParameter; import li.strolch.model.parameter.StringParameter;
import li.strolch.persistence.api.StrolchTransaction; import li.strolch.persistence.api.StrolchTransaction;
import li.strolch.plc.core.PlcHandler;
import li.strolch.plc.model.ConnectionState; import li.strolch.plc.model.ConnectionState;
import li.strolch.privilege.model.PrivilegeContext; import li.strolch.privilege.model.PrivilegeContext;
import li.strolch.runtime.configuration.ComponentConfiguration; import li.strolch.runtime.configuration.ComponentConfiguration;
@ -71,13 +72,24 @@ public class PlcGwHandler extends StrolchComponent {
@Override @Override
public void start() throws Exception { public void start() throws Exception {
notifyPlcConnectionState(ConnectionState.Disconnected);
delayConnect(INITIAL_DELAY, TimeUnit.SECONDS); delayConnect(INITIAL_DELAY, TimeUnit.SECONDS);
super.start(); super.start();
} }
private void notifyPlcConnectionState(ConnectionState disconnected) {
try {
getComponent(PlcHandler.class).notify("PLC", "ServerConnected", disconnected.name());
} catch (Exception e) {
logger.error("Failed to notify PLC of connection state", e);
}
}
@Override @Override
public void stop() throws Exception { public void stop() throws Exception {
notifyPlcConnectionState(ConnectionState.Disconnected);
if (this.gwSession != null) { if (this.gwSession != null) {
try { try {
this.gwSession.close(new CloseReason(CloseCodes.GOING_AWAY, "Shutting down")); this.gwSession.close(new CloseReason(CloseCodes.GOING_AWAY, "Shutting down"));
@ -120,7 +132,7 @@ public class PlcGwHandler extends StrolchComponent {
logger.error("Failed to connect to server! Will try to connect again in " + RETRY_DELAY + "s", e); logger.error("Failed to connect to server! Will try to connect again in " + RETRY_DELAY + "s", e);
} }
closeGwSessionUpdateState("Failed to connect to server", ConnectionState.Failed, closeBrokenGwSessionUpdateState("Failed to connect to server",
"Connection refused to connect to server. Will try to connect again in " + RETRY_DELAY + "s: " "Connection refused to connect to server. Will try to connect again in " + RETRY_DELAY + "s: "
+ getExceptionMessageWithCauses(e)); + getExceptionMessageWithCauses(e));
delayConnect(RETRY_DELAY, TimeUnit.SECONDS); delayConnect(RETRY_DELAY, TimeUnit.SECONDS);
@ -131,7 +143,7 @@ public class PlcGwHandler extends StrolchComponent {
this.lastSystemStateNotification = System.currentTimeMillis(); this.lastSystemStateNotification = System.currentTimeMillis();
if (tryPingServer()) { if (tryPingServer()) {
logger.error("Failed to ping server. Will try to connect again in " + RETRY_DELAY + "s"); logger.error("Failed to ping server. Will try to connect again in " + RETRY_DELAY + "s");
closeGwSessionUpdateState("Ping failed", ConnectionState.Failed, closeBrokenGwSessionUpdateState("Ping failed",
"Failed to ping server. Will try to connect again in " + RETRY_DELAY + "s"); "Failed to ping server. Will try to connect again in " + RETRY_DELAY + "s");
delayConnect(RETRY_DELAY, TimeUnit.SECONDS); delayConnect(RETRY_DELAY, TimeUnit.SECONDS);
return; return;
@ -151,7 +163,7 @@ public class PlcGwHandler extends StrolchComponent {
} catch (IOException e) { } catch (IOException e) {
String msg = "Failed to send Auth to server"; String msg = "Failed to send Auth to server";
logger.error(msg, e); logger.error(msg, e);
closeGwSessionUpdateState(msg, ConnectionState.Failed, msg); closeBrokenGwSessionUpdateState(msg, msg);
delayConnect(RETRY_DELAY, TimeUnit.SECONDS); delayConnect(RETRY_DELAY, TimeUnit.SECONDS);
return; return;
} }
@ -165,20 +177,18 @@ public class PlcGwHandler extends StrolchComponent {
.scheduleWithFixedDelay(this::pingServer, 1, RETRY_DELAY, TimeUnit.SECONDS); .scheduleWithFixedDelay(this::pingServer, 1, RETRY_DELAY, TimeUnit.SECONDS);
} }
private void closeGwSessionUpdateState(String closeReason, ConnectionState connectionState, private void closeBrokenGwSessionUpdateState(String closeReason, String connectionStateMsg) {
String connectionStateMsg) {
try { try {
runAsAgent(ctx -> { runAsAgent(ctx -> closeBrokenGwSessionUpdateState(ctx, closeReason, connectionStateMsg));
closeGwSessionUpdateState(ctx, closeReason, connectionState, connectionStateMsg);
});
} catch (Exception e) { } catch (Exception e) {
logger.error("Failed to close GW Session!", e); logger.error("Failed to close GW Session!", e);
} }
notifyPlcConnectionState(ConnectionState.Failed);
} }
private void closeGwSessionUpdateState(PrivilegeContext ctx, String closeReason, ConnectionState connectionState, private void closeBrokenGwSessionUpdateState(PrivilegeContext ctx, String closeReason, String connectionStateMsg) {
String connectionStateMsg) { saveServerConnectionState(ctx, ConnectionState.Failed, connectionStateMsg);
saveServerConnectionState(ctx, connectionState, connectionStateMsg);
closeGwSession(closeReason); closeGwSession(closeReason);
} }
@ -206,7 +216,7 @@ public class PlcGwHandler extends StrolchComponent {
private void pingServer() { private void pingServer() {
if (tryPingServer()) { if (tryPingServer()) {
logger.error("Failed to ping server. Reconnecting..."); logger.error("Failed to ping server. Reconnecting...");
closeGwSessionUpdateState("Ping failed", ConnectionState.Failed, closeBrokenGwSessionUpdateState("Ping failed",
"Failed to ping server. Will try to connect again in " + RETRY_DELAY + "s"); "Failed to ping server. Will try to connect again in " + RETRY_DELAY + "s");
delayConnect(RETRY_DELAY, TimeUnit.MILLISECONDS); delayConnect(RETRY_DELAY, TimeUnit.MILLISECONDS);
} }
@ -268,7 +278,7 @@ public class PlcGwHandler extends StrolchComponent {
if (!response.has(PARAM_STATE) || !response.has(PARAM_STATE_MSG) || !response.has(PARAM_AUTH_TOKEN)) { if (!response.has(PARAM_STATE) || !response.has(PARAM_STATE_MSG) || !response.has(PARAM_AUTH_TOKEN)) {
closeGwSessionUpdateState(ctx, "Auth failed!", ConnectionState.Failed, closeBrokenGwSessionUpdateState(ctx, "Auth failed!",
"Failed to authenticated with Server: At least one of " + PARAM_STATE + ", " + PARAM_STATE_MSG "Failed to authenticated with Server: At least one of " + PARAM_STATE + ", " + PARAM_STATE_MSG
+ ", " + PARAM_AUTH_TOKEN + " params is missing on Auth Response"); + ", " + PARAM_AUTH_TOKEN + " params is missing on Auth Response");
@ -277,20 +287,21 @@ public class PlcGwHandler extends StrolchComponent {
} }
if (!response.get(PARAM_STATE).getAsBoolean()) { if (!response.get(PARAM_STATE).getAsBoolean()) {
closeGwSessionUpdateState(ctx, "Failed to authenticated with server!", ConnectionState.Failed, closeBrokenGwSessionUpdateState(ctx, "Failed to authenticated with server!",
"Failed to authenticated with Server: " + response.get(PARAM_STATE_MSG).getAsString()); "Failed to authenticated with Server: " + response.get(PARAM_STATE_MSG).getAsString());
throw new IllegalStateException("Auth failed to Server: " + response.get(PARAM_STATE_MSG).getAsString()); throw new IllegalStateException("Auth failed to Server: " + response.get(PARAM_STATE_MSG).getAsString());
} }
String serverAuthToken = response.get(PARAM_AUTH_TOKEN).getAsString(); String serverAuthToken = response.get(PARAM_AUTH_TOKEN).getAsString();
if (isEmpty(serverAuthToken)) { if (isEmpty(serverAuthToken)) {
closeGwSessionUpdateState(ctx, "Missing auth token on AUTH response!", ConnectionState.Failed, closeBrokenGwSessionUpdateState(ctx, "Missing auth token on AUTH response!",
"Missing auth token on AUTH response!"); "Missing auth token on AUTH response!");
throw new IllegalStateException("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(this.gwSession.getId() + ": Successfully authenticated with Server!");
saveServerConnectionState(ctx, ConnectionState.Connected, ""); saveServerConnectionState(ctx, ConnectionState.Connected, "");
notifyPlcConnectionState(ConnectionState.Connected);
} }
public void pong(PongMessage message, Session session) { public void pong(PongMessage message, Session session) {