//
//  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
//
//      https://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/users/protocols
:icons: font

= CtrlX

NOTE: No language implementation of this driver is usable yet. See the
xref:protocols/index.adoc[protocol support matrix] for what each implementation
currently does.

WARNING: This driver is unfinished and not usable yet. Pinging is the only thing that works;
discovery is an unimplemented stub, there is no tag address syntax, so reading and writing are not
available, and the browse implementation does not work yet either. This page describes the current
state for anyone continuing the work - it is not linked from the navigation.

The CtrlX driver talks to Bosch Rexroth ctrlX CORE devices through their REST/Data-Layer API over
HTTPS, rather than over an industrial fieldbus protocol.

== Supported Operations

[cols="2,5a"]
|===
|Operation |Description

|`ping`
|Checks that the device is reachable and the credentials are accepted.

|`discover`
|*Not implemented.* The driver hands out a discovery request builder, but
`CtrlXPlcDiscoverer.discoverWithHandler` is a TODO that returns `null` instead of a future, so
executing a discovery request fails instead of finding devices.

|`browse`
|*Does not work yet.* The connection carries an implementation that is meant to enumerate the
device's Data Layer nodes, and it is the furthest along of the unfinished operations, but it does
not produce usable results.

|`read` / `write` / `subscribe`
|*Not implemented.* The corresponding request builders return `null`, so attempting one fails.
|===

The connection reports read, write, subscribe and browse as unsupported in its metadata, so a
caller that checks `getMetadata()` before deciding what to do gets an honest answer rather than
being sent into a request that cannot succeed.

== Connection String

----
ctrlx:https://{host}
ctrlx://{host}
----

`https` is the only supported transport, and it is also the default - so the transport part can be
omitted. Any other transport is rejected with
`Only 'https' transport is supported by this driver`.

== Authentication

IMPORTANT: A CtrlX connection *always* requires a username and password. Obtaining a connection
without authentication throws `CtrlX connections require authentication.`, and an authentication
object that is not a username/password pair is rejected as well.

[source,java]
----
PlcConnection connection = new DefaultPlcDriverManager()
    .getConnection("ctrlx://192.168.1.1",
        new PlcUsernamePasswordAuthentication("boschrexroth", "boschrexroth"));
----

== Connection Options

[cols="3,1,2,5a"]
|===
|Name |Type |Default |Description

|`tls.trust-store`
|STRING
|
|Key store of certificates to trust, instead of the JVM's public authorities.

|`tls.trust-store-password`
|STRING
|
|Password of the trust store named by `tls.trust-store`.

|`tls.trust-store-type`
|STRING
|`PKCS12`
|Type of the trust store named by `tls.trust-store`.

|`server-certificate-file`
|STRING
|
|PEM certificate of the device to trust, for a device carrying its own certificate rather than one
issued by an authority the JVM already knows.

|`allow-factory-default-certificate`
|BOOLEAN
|`false`
|Trust the factory default certificate that ships inside this driver's jar, for any host. See the
warning below. Setting it logs a warning.

|`ignore-common-name`
|BOOLEAN
|`false`
|Accept a device certificate issued for a different host than the one connected to.

|`browse-max-total-nodes`
|INT
|`1000000`
|Largest number of nodes a single browse will read; `0` for no limit.

|`browse-max-depth`
|INT
|`64`
|How deep a browse will follow children; `0` for no limit.
|===

WARNING: The driver used to trust the Bosch factory default certificate bundled in its own jar, and
to trust it *instead of* the platform's authorities rather than in addition to them. That
certificate identifies nobody - anything holding it and its key was trusted, for any host - and the
username and password travel over that channel. Because it was also the only trust anchor, a device
with a properly issued certificate could not be reached at all. A device still on its factory
certificate now needs `allow-factory-default-certificate=true`, and the better answer is to give the
device a certificate of its own and name it with `server-certificate-file` or a trust store.

A browse walks whatever tree the device describes, and nothing in the answer says how large that
tree is or that it ends, so `browse-max-total-nodes` and `browse-max-depth` bound it. Reaching
either one warns and returns what was found rather than failing.

== Browsing

NOTE: Browsing does not work yet. What follows describes how the existing implementation is meant
to be used, for whoever picks the work up.

Browse queries are glob patterns matched against the Data Layer node paths, not tag addresses.
`**` matches everything and is intended as the simplest way to see what a device exposes:

[source,java]
----
PlcBrowseResponse response = connection.browseRequestBuilder()
    .addQuery("all", "**")
    .build().execute().get();
----

The driver has no tag address syntax of its own - `parseTag` is not implemented - which is the
reason read and write are unavailable.

== Discovery

NOTE: Discovery does not work yet. `CtrlXDriver.discoveryRequestBuilder()` returns a builder backed
by `CtrlXPlcDiscoverer`, whose `discoverWithHandler` is still an empty TODO returning `null`, so no
ctrlX CORE device is ever located.

== Maven Dependency

The driver is not part of the `plc4j-driver-all` meta package while it is unfinished, so it has to
be added explicitly:

[source,xml,subs=attributes+]
----
<dependency>
  <groupId>org.apache.plc4x</groupId>
  <artifactId>plc4j-driver-ctrlx</artifactId>
  <version>{page-component-version}</version>
</dependency>
----

NOTE: The driver declares no connection-string parameters of its own, which is why this page has no
generated options table like the other protocols. Everything it needs comes from the host in the
connection string plus the credentials.
