//
//  Licensed to the Apache Software Foundation (ASF) under one or more
//  contributor license agreements.  See the NOTICE file distributed with
//  this work for additional information regarding copyright ownership.
//  The ASF licenses this file to You under the Apache License, Version 2.0
//  (the "License"); you may not use this file except in compliance with
//  the License.  You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
//  Unless required by applicable law or agreed to in writing, software
//  distributed under the License is distributed on an "AS IS" BASIS,
//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//  See the License for the specific language governing permissions and
//  limitations under the License.
//
:imagesdir: ./images/

== ADS Protocol Java Implementation

// TODO: change this copy&paste from S7... document me

The current version of the ADS protocol java driver is based upon Netty 4 (http://netty.io/).

As the ADS protocol running on TCP is a hierarchy of protocols, the ADS driver is implemented by providing several Protocol implementations, each encoding one layer of the protocol stack.

The complete pipeline for the ADS protocol looks like this:

[blockdiag,ads-netty-pipeline]
....
{
    Application -> ADSPlcConnection;
    Socket -> PLC;

    group {
        label = "PLC4X ADS Driver"
        color = "#77FF77";

        ADSPlcConnection -> Plc4XADSProtocol -> ADSProtocol -> Socket

        group {
            Plc4XADSProtocol; ADSProtocol;
        }
    }
}
....

Each protocol layer implementation extends the class `MessageToMessageCodec` and is configured to consume/encode messages in the current format into messages of the next lower layer.

The highest layer hereby consumes PLC4X messages, which are defined in the `plc4j-api` module, and the lowest layer produces a simple byte output.

In order to implement the ADS Protocol as described in link:../../../protocols/ads/index.html[ADS Protocol] internally this is what happens inside the driver as soon as a connection is requested:

[seqdiag,ads-netty-setup-communication]
....
{
    Application; ADSPlcConnection; Plc4XADSProtocol; ADSProtocol; Socket; PLC;

    group Pipeline {
       "Plc4XADSProtocol";
        "ADSProtocol";
    }

    Application -> ADSPlcConnection [label = "Calls 'connect'"]
    ADSPlcConnection -->  Socket [label = "Creates the byte array\ncontaining the TCP on ISO\nmessage"]
    Socket -> PLC [label = "Sends the raw byte data to\nthe PLC"]

    Socket <-- PLC [label = "Sends the response to the\nSocket"]
    Socket -> ADSProtocol [label = "Passes the binary data to\nthe pipeline"]
    ADSPlcConnection <- ADSProtocol [label = "Sends ADSConnectionEvent(SETUP_COMPLETE) event to the\npipeline", note = "ADSPlcConnection listens for ADSConnectionEvent(SETUP_COMPLETE) events"]

}
....

Above picture is a simplification. The communication of the outside with the pipeline is not implemented in a way that one component directly addresses the other.
It is more that all communication is done with the `pipeline` and Netty then takes care of calling the right component at the right time.

When writing to the pipeline from an application Netty starts at the `top` of the pipeline and asks each pipeline level if it is able and willing to handle the current message.
If it does, the message is passed in to the `encode` method and the next component is supplied with the output of this.
If the component can't process the message the next level is checked with the unmodified message.

When reading from the Socket the Netty processes the pipeline elements the same way, but in the opposite direction and a pipeline elements `decode` method is called instead of `encode`.

In addition to the normal flow of messages, a Netty pipeline also provides a messaging system. Every component can fire so-called `user events` and every component can react on them by implementing a `userEventTriggered` method.

This functionality is mainly used during connection setup to synchronize the sending of messages on the different layers of the protocol stack.