plc4x-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Julian Feinauer <>
Subject Re: Reconnect of driver 2
Date Fri, 29 Mar 2019 08:42:09 GMT

first, I created a issue for this ( and second,
yes, I agree.
I want to prepare a Branch where I implement the snippets from Gunter with the things bespoken.

But, thinking again about it, I dislike the contract of the method as "either completes or
This is okay for a "write" operation but not for a question.
If we would do scala, I would suggest to use a Either[Boolean, Exception] or so.
Personally, I would prefer to return a "PingResponse" which is either Successful (.isSuccessfull())
or contains some kind of exception or error message (.getException()).
Can we all agree on that?


PS.: The branch is

Am 29.03.19, 09:35 schrieb "Christofer Dutz" <>:

    Hi guys,
    Just a question, as I'm currently traveling and haven't had my computer open for the past
few days.
    On the API side we were thinking of a no-args void method in the PlcConnection that fires
exceptions ... Correct? The up, port and stuff like that should be provided by the connection
itself. Cause not all protocols and drivers have to be TCP or UDP based.
    Outlook für Android<> herunterladen
    From: Julian Feinauer <>
    Sent: Friday, March 29, 2019 9:17:35 AM
    Subject: Re: Reconnect of driver 2
    Hi Gunter,
    I am currently looking through your code and wanted to prepare a commit, so just a question
about the s7 implementation.
    Is the M1.2 a generally available bit or is this something more specific to your use cases?
    I know that the M are the Markers and generally all Boolean, but can there be a situation
where this bit does not exist?
    Am 28.03.19, 15:16 schrieb "Gunther Gruber" <>:
        Hi Julian,
        somhow my github account got flagged.
        I append the two functions below, i think it will take some time for github to respond
on the mail i wrote.
        public boolean ping(String host, int port, int timeout) {
          Socket s = null;
          try {
            s = new Socket();
            s.connect(new InetSocketAddress(host, port), timeout);
            return true;
          } catch (Exception e) {
            return false;
          } finally {
            if (s != null) {
              try {
              } catch (Exception e) {
        private boolean channelPingCheck(int timeout) {
                String variable = "%M1.2:BOOL";
                return channelPingCheck(timeout, variable);
            private boolean channelPingCheck(int timeout, String variable) {
        //      String variable = "%M1.2:BOOL";
        //      boolean expectedResult = true;
                try {
                    plcConnection = getPlcConnection();
                } catch (PlcConnectionException e) {
                    return false;
                PlcReadRequest.Builder builder = plcConnection.readRequestBuilder();
                builder.addItem(variable, variable);
                PlcReadRequest readRequest =;
                PlcReadResponse result = null;
                try {
                    result = readRequest.execute().get(timeout, TimeUnit.MILLISECONDS);
                } catch (InterruptedException e) {
                } catch (ExecutionException | TimeoutException e) {
                    return false;
                if (result == null) {
                    return false;
                Object content;
                content = result.getObject(variable);
                if (content == null) {
                    return false;
                //we could compare against the real value of the object here, but then we
need to be more specific about the variable type
                return true;
        On 28.03.19 14:49, Julian Feinauer wrote:
        Hi Gunter,
        very cool to hear... and I like your idea with the port... this is so simple and robust…
        I wanted to check and review (and MERGE) your code but I did not find the PR.
        Are you sure you made the PR towards apache/incubator-plc4x?
        Von: Gunther Gruber <><>
        Antworten an: ""<> <><>
        Datum: Donnerstag, 28. März 2019 um 14:44
        An: ""<> <><>
        Betreff: Re: Reconnect of driver 2
        Hi All,
        i implemented two simple ping checks one specifically for s7 and one in generall to
check reachability of a port. Which can simply be copied.
        I also wrote a connection-manager which checks the connection and recreates it if
        Our szenario is that we want to read data in a loop and the higher the sampling frequency
the better. I do not want to waste that on the "liveness" check of the connection. Best S7
could do is every 100ms i heared.
        Also i load the driver for the s7 directly because in osgi the classloader stuff does
not work.
        I put my working code into examples/connection-manager and created a pull request.
i did not grasp the code of PooledDriverManager in this short time to integrate. Feel free
to adapt/change pieces of my code or give me feedback.
        Gunther Gruber
        On 26.03.19 15:24, Christofer Dutz wrote:
        Hi All,
        I would agree that a void type and exceptions would allow a more fine-grained reporting
of what's going on.
        Sort of:
        - "Yeah ... I am a S7 400, but I don't support the S7-TIA protocol"
        - "No connection under this number" (no connection possible)
        - "You're not allowed to connect"
        - "Invalid credentials"
        - ...
        Maybe we should do that ASAP, adding it to the API, but have it report "Not Implemented"
for now and to create JIRA tickets for the individual drivers ping implementations.
        Am 26.03.19, 14:44 schrieb "Julian Feinauer" <><><><>:
            Hi Gunther,
            thats really great to hear : )
            When I remember correctly the idea was...
            1. Extend the PlcConnection interface with a "ping()" method (Boolean? Throw Exception
if not possible?)
            2. Implement the Ping functionality for each plc with a sensible "operation" (not
sure what this could be for S7... read the SLZ or something?)
            3. Use this feature as "keep alive" e.g. for the PooledDriverManager
            does that make sense?
            Am 26.03.19, 13:55 schrieb "Gunther Gruber" <><><><>:
                Sure I like to contribute. I guess by that you mean checking out the
                code and create a pull request with something working.
                I like your idear with the ping check. I will focus on implementing a
                function for the ping check, which can be reused later.
                > Hi Gunther,
                > good catch : )
                > In fact, the isConnected() implementation is currently not soo god.
                > In fact it checks if the underlying communication channel from netty
is connected (which does not know that it is disconnected yet, in your case).
                > We already had discussions to introduce a real "request" based implementation
like "ping()" which sends a request.
                > Furthermore, for your use case there is the PooledDriverManager which
does implicitly what you do... throws away a not working connection and issues a new one,
if needed, but that’s a separate topic.
                > I think we should spend some effort into this "ping" functionality.
                > Perhaps you can even assist with the implementation Gunther, what do
you think?
                > Julian
                > Am 26.03.19, 11:19 schrieb "Gunther Gruber" <><><><>:
                >      Put it another way, isConnected does not work as i expect it
                >      plcConnection.isConnected() returns true even when i disconnect
the vpn (maybe of some tcp/ip keepalive?)
                >      this is the snippet of code which i expect to work (instead of the
thread which reconnects ever 10 minutes)
                >      while (doCollect) {
                >        try {
                >          if (plcConnection == null || plcConnection.isConnected() ==
false) {
                >            plcConnection = initPLC(config.get(CONNECTION_KEY));
                >          }
                >        } catch (PlcConnectionException e) {
                >          logger.log(Level.WARNING, "error connecting with driver", e);
                >          plcConnection = null;
                >          incrementalSleep();
                >          break;
                >        }
                >        // Create a new read request:
                >        // - Give the single item requested the alias name "value"
                >        PlcReadRequest.Builder builder = plcConnection.readRequestBuilder();
                >      Gunther Gruber

View raw message