==============================================================
Apache PLC4X 1.0.0
==============================================================

New Features
------------

- Java Configurations of drivers now support a "FILE" type
  of configuration parameter.
- Subscription of change-of-state values now supports
  providing a min time interval to prevent excessive
  notifications.
- Added a new PlcCertificateAuthentication to the API module.
- Initial version of a new Java UMAS driver.
- Initial version of a new Java SLMP (Mitsubishi MELSEC) driver:
  read and write access to word devices (D/W/R) using binary 3E
  frames over TCP (including Batch Write).
- The 'plc4x' proxy driver now supports TLS as a transport and
  requires mandatory username/password authentication
  (configured via the new "username" and "password" connection
  parameters).
- The Go serial transport now supports the full set of serial
  options in the connection string: data-bits, stop-bits, parity,
  flow-control, dtr, rts, read-timeout and write-timeout.
- The Go serial transport supports sharing one physical serial port
  between multiple connections ("reuse-port", e.g. multi-slave Modbus
  RTU) with broadcast reads and serialized writes, plus inter-frame
  write pacing ("interframe-delay") on both shared and dedicated ports.
- The Java serial transport's shared-port mode ("reuse-port") now uses a
  single broadcast reader per physical port, fixing responses being split
  between connections, and "interframe-delay" write pacing works on both
  shared and dedicated ports (gap measured from the last write or
  received data).
- The Java Modbus RTU codec now frames responses by function code with
  CRC validation and byte-wise resynchronization: batched deliveries
  (e.g. on shared serial ports) yield every frame instead of only the
  first, and partial or corrupted frames no longer discard buffered data.
- Java Modbus serial connections (RTU/ASCII) now serialize their requests
  per connection (single outstanding transaction, matching the protocol),
  fixing concurrent same-unit requests receiving each other's responses;
  unknown Modbus exception codes map to REMOTE_ERROR instead of failing;
  shared serial ports dispatch each connection's callbacks on their own
  thread, so one blocked callback no longer stalls the whole port.
  Responses are additionally validated against the pending request's
  function code (late responses from timed-out requests are discarded
  instead of completing the wrong caller), and the request timeout now
  covers the full time from submission, including queueing.
- Drivers that don't natively support subscriptions (Modbus,
  EtherNet/IP, AB-ETH, SLMP, UMAS) now provide subscriptions
  through a polling-based emulation layer, supporting CYCLIC and
  CHANGE_OF_STATE subscriptions.
- Added a new remote-data-fetching component (event-pump)
  replacing the old scraper.
- Re-implemented the connection-cache with more reliable resource
  handling and transparent re-subscription after a connection was
  lost and re-established.
- New TCP transport implementation using per-connection
  virtual-thread blocking I/O (replacing the NIO selector),
  scaling better on Java 21.
- OPC-UA: Added reading and writing of structured values
  (PlcStruct) and corrected array handling.
- OPC-UA: Tag data types are now derived from the server's type
  model instead of being guessed from the input data.
- OPC-UA: Added browse support, resolving server-side types and
  access rights.
- Simulated driver: Added STRING support.
- CANopen: Added NMT command support.
- Go: Added a production-grade BACnet/IP driver (segmentation,
  write priority, directed/multi-target WhoIs, routed addressing,
  array/bit-string property decoding).
- Go: The connection-cache now supports a configurable max idle
  time, and connections carrying subscriptions are exempt from the
  idle TTL.
- The Object-PLC-Mapping (OPM) module was ported to SPI3.
- PlcBrowseItem now reports which subscription types each item
  supports via a new getSupportedSubscriptionTypes() method, so
  browse results carry subscription capability information.
- OPC-UA: Improved Siemens S7-1500 support, including reading and
  writing of (almost) all variant types.
- Updated the bundled KNX manufacturer data and the BACnet/KNX
  vendor IDs for broader device recognition.
- Go: Connections can now be invalidated (Invalidate()) to mark
  themselves irrecoverably failed for lease management, and
  transport errors are now classified and propagated through
  codecs/transports (TransportErrorKind).
- Performance: Sped up byte-aligned integer read/write in the Java
  byte-based SPI buffers.
- EtherNet/IP: The CIP bit-string types (BYTE, WORD, DWORD, LWORD)
  and unsigned integer types (USINT, UINT, UDINT, ULINT) can now be
  read and written, in both the Java and the Go drivers. They were
  accepted by the address parser but not decoded, so reading such a
  tag returned INTERNAL_ERROR. All eight are unsigned over their
  full range: a DWORD reads as 0 to 4294967295 and an LWORD as 0 to
  18446744073709551615. Their signed counterparts are unchanged - a
  DINT of 0xFFFFFFFF still reads as -1.
- Modbus: STRING and WSTRING values can now be read and written, in
  PLC4J, PLC4Go and PLC4C. The length of one string is written in
  parentheses the way the S7 driver spells it, so
  "holding-register:1[0..2]:STRING(20)" is three 20-character
  strings.
- OPC-UA: A new "subscription-queue-size" parameter (default 1) keeps
  the values a server queues between publishes. With a depth above
  one, change-of-state items are sampled at the server's fastest rate
  and every queued value is delivered instead of only the last. At the
  default nothing changes, and event and cyclic items keep a queue of
  one either way.
- OPC-UA: A new "min-channel-lifetime-ms" parameter (default 5000)
  bounds a channel lifetime the server revises downwards. Channel
  renewals run on one executor shared by every OPC UA connection in
  the JVM, so a single server answering with a very short - or zero -
  lifetime used to set the pace for all of them.
- OPC-UA: Added authentication with an X509 user certificate
  (GH-1845).
- EtherNet/IP: The driver falls back to "Get Attribute Single" where a
  device does not answer "Get Attribute All", so the Connection
  Manager and the Message Router are detected on devices that only
  support the single-attribute form.
- S7: A connection reports what the device says about itself.
  "readDeviceIdentification()" reads the module type, order number,
  serial number, firmware version and protection level out of the SZL
  lists, following a list the CPU splits across several PDUs.
- The event-pump accepts a trigger interval in milliseconds
  ("intervalMillis" / "initialDelayMillis") beside the existing
  whole-second form. Giving the same setting in both units fails at
  startup rather than silently picking one.
- Go: PLC4Go gained five drivers - AB-Ethernet, Firmata,
  IEC 60870-5-104, SLMP (MELSEC) and UMAS - taking it from nine
  drivers to fourteen. AB-Ethernet and Firmata are as partial as they
  are in Java (one does not write, the other does not read),
  IEC 60870-5-104 subscribes and nothing else because the protocol is
  push driven, and SLMP addresses the word devices D, W and R.
- Go: The EtherNet/IP driver was brought up to the Java driver's
  level: all three read and write paths (sequential, message-router
  and connected), the plc4j connect handshake, UDP broadcast discovery
  (ListIdentity) over per-interface sockets, a "logix" driver alias
  forcing little-endian encapsulation, and the "bigEndian",
  "forceUnconnectedOperation", "communicationPath" and
  "connectionSerialNumber" options.
- Go: The S7 driver gained browse (static areas and DB block
  enumeration), alarm and cyclic subscriptions with alarm query and
  push dispatch, a real round-trip ping, and parsing of S5TIME,
  variable-length strings and alarm tag addresses.
- Go: Modbus RTU and Modbus ASCII have codecs of their own, including
  the RTU CRC and the ASCII LRC, and the tag, value and configuration
  gaps to the Java driver are closed.
- Go: The KNXnet/IP driver writes group addresses, and its
  subscriptions work.
- Go: A polling-subscription base is part of the default connection
  set, so a driver whose protocol has no subscriptions can offer them
  the way the Java drivers do.
- Go: PlcDATE and PlcTIME_OF_DAY expose their components rather than
  only the whole value.
- Go: Every timeout is named (utils.WithNamedTimeout), so an expiry
  says which timeout it was.
- The API's "Option" type reports whether a configuration option
  carries a secret ("isSecret()"), which is what redaction now asks
  instead of guessing from the parameter's name. It is a default
  method returning false, so existing implementations keep compiling.

Incompatible changes
--------------------

- Configuration parameters now use one vocabulary across PLC4J and PLC4Go.
  A duration in milliseconds ends in "-ms", TLS settings live under "tls.",
  and a parameter aimed at a transport no longer repeats that transport's
  code. Old names are removed rather than deprecated: supplying one is
  reported as an unknown parameter, naming the replacement, and the setting
  does not apply. The full table is below.

  Durations:

    request-timeout           -> request-timeout-ms
    timeout-request (ads)     -> request-timeout-ms
    connect-timeout           -> connect-timeout-ms
    read-timeout              -> read-timeout-ms
    write-timeout             -> write-timeout-ms
    session-timeout           -> session-timeout-ms
    channel-lifetime          -> channel-lifetime-ms
    min-channel-lifetime      -> min-channel-lifetime-ms
    ha-heartbeat-interval     -> ha-heartbeat-interval-ms
    ha-failover-timeout       -> ha-failover-timeout-ms

  Establishing a socket and completing a protocol handshake are two
  settings, not one, so they now have two names. "connect-timeout-ms" is
  the socket connect; the COTP handshake and the OPC UA negotiation steps
  are "handshake-timeout-ms":

    cotp.cotp-connection-timeout -> cotp.handshake-timeout-ms
    negotiation-timeout (opcua)  -> handshake-timeout-ms

  Transport parameters no longer repeat their transport's code, which the
  prefix already supplies:

    tcp.tcp-no-delay          -> tcp.no-delay
    cotp.cotp-tpdu-size       -> cotp.tpdu-size
    tls.tls-version           -> tls.version

  TLS settings are addressed under "tls.":

    tls.verify-ssl            -> tls.verify
    key-store-file (opcua)    -> tls.keystore
    key-store-password        -> tls.keystore-password
    key-store-type            -> tls.keystore-type
    trust-store-file          -> tls.trust-store
    trust-store-password      -> tls.trust-store-password
    trust-store-type          -> tls.trust-store-type

  The trust store drops "-file" for the same reason the key store does:
  every one of these names a store, so saying so adds nothing. The TLS
  transport already spelled them "tls.trust-store-file"; that becomes
  "tls.trust-store" too, so the opcua and ctrlx drivers, which declare
  their own, now agree with it.

  A name a protocol specification fixes keeps its own spelling and units:
  SLMP's "monitoring-timer" is a field of the 3E request frame in the
  protocol's own units, not a value in milliseconds, so it is unchanged and
  carries a comment at its declaration saying why.

- The OPC UA driver's "insecure-certificate-verification" became
  "tls.verify", with the opposite sense. A connection that set
  "insecure-certificate-verification=true" must now set "tls.verify=false".
  This one is not just a rename: if it is missed, the new default applies,
  which is to verify the server certificate. That fails loudly against a
  server whose certificate does not validate rather than connecting
  insecurely, but it is a behaviour change and not a silent one.

- An unrecognised connection-string parameter is now reported in PLC4Go as
  well as PLC4J, naming the parameter and, where it can, the nearest known
  one. It remains a warning: a stray parameter does not fail a connection
  that would otherwise work. PLC4Go's OPC UA driver previously *refused*
  the connection on an unknown option; it now warns like every other
  driver, so a connection string accepted by PLC4J is no longer rejected
  there.

  In PLC4Go this covers the drivers that parse their configuration in one
  place: ab-eth, bacnet-ip, c-bus, EtherNet/IP, firmata, IEC 60870-5-104,
  Modbus, OPC UA, S7, SLMP and UMAS. The ADS, KNXnet/IP and simulated
  drivers read their options where they are used rather than parsing a
  configuration, so there is no point at which the leftovers are known;
  they are unchanged and still report nothing.

  The report also knows which transport the connection actually uses, so a
  parameter that belongs to a different transport - "serial.baud-rate" on a
  TCP connection - is called out as misdirected instead of being silently
  excused as "some transport's".

  A suggestion is offered only among the names the consumer that reported
  actually read, so a parameter belonging to a transport is named as
  unknown with nothing to suggest. PLC4J does better here: it draws the
  known names from the driver, the transport, the audit log and the
  connection-control options, and matches on the last segment, so a
  missing prefix is recognised for what it is.

- Configuration values carrying secrets are marked at their declaration -
  "@Secret" in PLC4J, a `secret:"true"` struct tag in PLC4Go - and render
  as "<redacted>" wherever a configuration is rendered. This replaces
  guessing from parameter names, which could only ever be one parameter
  behind: a pre-shared key was logged in clear until its name was added to
  the list by hand. A name-based check remains for parameters no
  configuration declares, since a credential passed under an unknown name
  is still a credential.

- PLC4Go's S7 driver reads the rack and slot as "cotp.local-rack",
  "cotp.local-slot", "cotp.remote-rack" and "cotp.remote-slot". It read
  them unprefixed, while PLC4J declares them on the COTP transport's
  configuration and every S7 example in the documentation spells them with
  the prefix - so the documented connection string set nothing in PLC4Go
  and said so nowhere. The unprefixed names are now reported as unknown.

- Fixed PLC4Go logging connection strings verbatim. A password in a Go
  connection string reached the log in clear at debug level, at twenty
  call sites across the driver manager and the connection cache. They are
  redacted now, along with credentials in a URI's userinfo. The parsed
  URL and the connection container render redacted too - both reached the
  same log lines by another route, so a redacted field sat beside the
  credential it was hiding.

- PLC4Go addresses a transport's connection-string options under the
  transport's own code, as PLC4J does and as the documentation has always
  said: "tcp.connect-timeout-ms", "serial.baud-rate", "udp.so-reuse",
  "pcap.speed-factor". They were read unprefixed, so every documented
  transport setting was ignored in PLC4Go and left at its default. The
  unprefixed names are now reported as unknown rather than silently
  doing nothing. Options a driver injects into the map itself
  ("defaultTcpPort") are not addressed by anyone and keep their bare
  names.

- PLC4Go's OPC UA driver reads the parameter names PLC4J declares and the
  documentation lists - "tls.keystore", "tls.keystore-password",
  "security-policy", "allow-unverified-security-policies" - rather than
  names derived from its own Go struct fields ("keyStoreFile",
  "securityPolicy"). The documented connection string reached it as a
  set of unknown options and was ignored.

- A secret marking in PLC4Go applies whatever the field's type is. The
  generator honoured "secret:\"true\"" only where it rendered a string, so
  the tag on any other kind of field was accepted and silently did
  nothing. The OPC UA key pair now carries the marking in both the
  configuration and the secure channel.

- Redaction decides from the parameter name the driver will read, not the
  name as written: "?%70assword=hunter2" is the password parameter once
  the query is decoded, and was previously logged in clear. A connection
  string nested inside another (the PLC4X proxy driver's
  "remote-connection-string") is redacted as a connection string in its
  own right, so its credentials no longer travel through the outer one -
  while which PLC the proxy talks to stays visible.

- A BACnet/IP connection reported each unknown option once rather than
  twice. Its options are parsed both by the driver, for the discovery
  timeout, and by the connection; both reported, so one mistake read as
  two.
- The connection-creating methods of the API moved from
  "PlcConnectionManager" to a new "PlcConnectionFactory"
  interface, which the "PlcDriverManager" hands out via
  "getConnectionFactory()" (formerly "getConnectionManager()").
  "PlcConnectionManager" now extends "PlcConnectionFactory" and
  adds the "close()" method, and is only implemented by managers
  that keep the connections they hand out, such as the connection
  cache.
- The connection cache was renamed from
  "CachedPlcConnectionManager" to "PlcConnectionCache", matching
  the name the concept already has in PLC4Go. Its builder method
  "withConnectionManager()" became "withConnectionFactory()", and
  "PlcConnectionManagerClosedException" became
  "PlcConnectionCacheClosedException". The Maven artifactId
  ("plc4j-tools-connection-cache") and the package are
  unchanged.
- All drivers were migrated to a new shared SPI ("SPI3"):
  dependency-free Read/Write buffers, an updated code-generation
  framework, a pluggable-transport system and a layered
  protocol-driver model.
- Drivers now reject connection strings using an unsupported
  transport with an exception. The check can be force-disabled
  via a configuration parameter.
- Several Maven artifactIds changed (tools, transports, scraper);
  see the "Changed Maven Coordinates" section below for the full
  mapping. Consumers must update their coordinates.
- The PlcBrowseItem interface gained a
  getSupportedSubscriptionTypes() method that custom
  implementations must now provide.
- Dropped support for Java 11, new baseline Java version is
  Java 21.
- Migrated the build to Apache Maven 4.
- The Go serial transport's default baud-rate changed from 115200
  to 9600 (aligning with common serial defaults and the Java
  transport). Specify baud-rate explicitly if you relied on the
  previous default.
- Go serial reads/writes without an explicit context deadline are
  now bounded by the new read-timeout/write-timeout options
  (default 1000 ms; set to 0 for the previous blocking behavior),
  and invalid serial option values now fail connection creation
  instead of being silently ignored.
- The Java serial transport removed the unused options
  "break-enabled", "receive-buffer-size" and "send-buffer-size",
  removed the combined "RTS_CTS_XON_XOFF" flow-control mode, and now
  rejects invalid parity/flow-control values instead of silently
  falling back to defaults. Option values are case-insensitive and
  accept "-" or "_" as separator (canonical forms: none, odd, even,
  mark, space; none, rts-cts, xon-xoff).
- Acquiring a shared Java serial port ("reuse-port") with a configuration
  differing from the first connection's now fails with an error instead
  of silently reusing the first configuration.
- The 'plc4x' proxy driver now defaults to the TLS transport
  instead of plaintext TCP. Existing plaintext connections must
  switch to an explicit transport prefix (e.g. "plc4x:tcp://...").
  When using TLS against a server with a self-signed certificate,
  set "tls.verify-ssl=false" (or pin the certificate).
- The 'plc4x' proxy driver now requires username/password
  authentication on connect; connecting without credentials, or
  with invalid ones, is rejected with an ACCESS_DENIED handshake.
- The PLC4J-API module however is intentionally held at
  Java 17 to allow alternate driver implementations to support
  Java 17.
- Updated the signature of the PlcBrowseRequestInterceptor to
  also accept a queryName, query and item instead of just an
  item.
- The ConnectionStateListener interface was updated to no longer
  have a connected() and disconnected() method, but use a
  onConnectionStateChanged method instead that accepts
  PlcConnectionStateChangedEvent events which have many more
  state change options beyond a simple connected and disconnected
  event.
- The OPC UA driver's "security-policy" now defaults to
  Basic256Sha256 instead of NONE. NONE means the channel is
  neither signed nor encrypted, so anything on the network path
  can read and alter what is exchanged, and the server is not
  authenticated at all.
  A protected channel needs the server's certificate to be known
  before the channel is opened. The discovery phase that would
  otherwise fetch it runs unprotected by necessity, and a
  certificate learned from the peer it is meant to authenticate
  establishes nothing - so the driver no longer proceeds from
  discovery onto a channel weaker than the one configured. It used
  to do exactly that, silently: a connection asking for
  Basic256Sha256 got a session with neither signing nor encryption
  and no indication of it.
  Together this means a connection that names no certificate now
  fails where it previously came up unprotected. Name one with
  "server-certificate-file", or a trust store with
  "tls.trust-store"; or set "discovery=false" if the endpoint needs
  no discovery; or ask for "security-policy=NONE" to accept an
  unprotected channel as before.
  Note that a protected channel also needs a client key pair:
  supply one with "key-store-file", or the driver generates a
  throwaway self-signed certificate, which a server that
  authenticates its clients will not accept.
- The OPC UA driver refuses to send a username and password over a
  channel that neither signs nor encrypts, because the password is
  then readable by anything on the path and stays useful long after
  it is read. The new "allow-insecure-credentials" parameter sends
  them anyway, with a warning.
- The OPC UA driver now requires an endpoint to match both the
  requested security policy and the requested message security
  mode, and selects the strongest endpoint that matches rather than
  the weakest. It previously accepted an endpoint matching either
  one and then chose the lowest security level on offer, so a
  server publishing a wide-open endpoint beside a protected one was
  usually reached over the wide-open one. Where two endpoints are
  equally strong, one whose user token policy protects the token is
  preferred.
- The ctrlX driver no longer trusts the Bosch factory default
  certificate that ships inside the driver jar, and no longer
  accepts a certificate for any host regardless of the name it was
  issued for. It also asks for a TLS context rather than the
  legacy "SSL" one. That certificate identifies nobody - anything
  presenting it and its key was trusted - and because it was the
  only trust anchor, a device carrying a properly issued
  certificate could not be reached at all. The credentials for the
  connection travel over that channel.
  Connections to a device still on its factory certificate will
  now fail. The new "allow-factory-default-certificate" parameter
  restores the old behaviour, with a warning; alternatively
  "server-certificate-file" names a single PEM certificate to
  trust, or "tls.trust-store" (with "tls.trust-store-password" and
  "tls.trust-store-type") a key store of them, matching the names used
  by the OPC UA driver and the TLS transport.
  "ignore-common-name" is also available if the certificate is
  trusted but names a different host.
- The TLS transport now checks that the server's certificate was
  issued for the host it connected to. The "ignore-common-name"
  parameter was declared but never consulted, so this check did
  not happen at all: with "verify-ssl" on, any certificate from a
  trusted issuer was accepted for any host, which is what a
  machine in the middle needs. Setting "ignore-common-name=true"
  restores the old behaviour and logs a warning saying so.
  A connection to a device whose certificate names something other
  than the address it is reached at will now fail where it
  previously succeeded.
  Two new parameters make the check usable where a device carries
  its own certificate: "tls.trust-store" (with
  "tls.trust-store-password" and "tls.trust-store-type") names the
  certificates to trust instead of the public authorities the JVM
  ships with. Previously the only way past a private CA was
  "verify-ssl=false", which turns off both the chain check and
  this one.
- The IEC 60870-5-104 driver now derives its S-format
  acknowledgements from the send sequence number of the frames it
  received, counted modulo 2^15 and encoded in the upper fifteen
  bits of the control field, as the standard requires. It
  previously sent the received frame's receive sequence number
  plus one, which is the station reporting how much of our traffic
  it had taken in - a different number, and one that said nothing
  about how far we had read. This changes what the driver puts on
  the wire in response to received telemetry, so a station that
  checks acknowledgements will see different (correct) values, and
  one that had adapted to the old behaviour may need attention.
  The frame format itself is unchanged.
- Tag addresses naming an implausible number of elements are now
  rejected as invalid addresses rather than acted on. An element
  count is a request to allocate, and it was taken at face value:
  in the s7 driver a count is now measured against the 2097151
  bytes an S7 address can reach (for the string forms, against
  what one string of the declared length costs, which is the same
  arithmetic the optimizer does in an int and where an unbounded
  count overflowed); in the ads driver an index group, index
  offset and element count must each fit the four bytes ADS
  carries them in; in the firmata driver a digital tag must stay
  within the 256 pins the protocol can name, having previously
  turned its count into that many set bits at parse time. In all
  three, a count too wide to be a number used to escape as a
  NumberFormatException instead of the PlcInvalidTagException the
  tag parsers promise.
- The OPC UA driver bounds a browse, which previously walked
  whatever tree the server described for as long as it described
  one. "browse-max-references-per-node" (default 65536) limits the
  references collected for one node and is now also asked of the
  server, "browse-max-total-nodes" (default 1000000) limits how
  many nodes one browse expands, and "browse-max-depth" (default
  64) limits how deep it recurses. Set any of them to 0 for no
  limit. Reaching one warns and returns what was found rather
  than failing, so an address space within these sizes is
  unaffected.
- The ctrlX driver bounds a browse the same way, with
  "browse-max-total-nodes" (default 1000000) and
  "browse-max-depth" (default 64). Its browse also now always
  completes its future: a node answering with no child list used
  to throw inside the executor's task, where nothing caught it and
  the caller was left waiting on a future that was never
  completed. Such a node is now read as the leaf it says it is.
- The simulated driver bounds how much data one tag may ask it to
  make up. The count in the address was multiplied by the size of
  one element in an int to size the array it fills, so a large
  enough count asked for a negative array rather than a large one,
  and anything below that got what it asked for - three hundred
  million doubles being 2.4 GB. The product is now measured
  against a budget of 16 MiB per tag.
  The Go driver carries that count as a uint16, where a count
  above it used to be truncated to its low two bytes rather than
  refused - a request for 70000 elements handing back a tag of
  4464, and one for 65536 handing back a tag of none. Both are
  now invalid addresses, as is a count of zero, which the Java
  driver already refused.
- The modbus, profinet and profinet-ng tag parsers now report a
  count, address or slot too wide to be a number as an invalid
  tag. All three already bounded these values, but the checks ran
  after the number was read, so anything too wide to read left as
  a NumberFormatException instead. The digit widths are capped in
  the address patterns, at what each field can hold.
- Every generated parser now refuses a message that nests its
  types deeper than 1024 levels, in both the Java and the Go
  bindings. Several types contain themselves - BACnet constructed
  data holds further constructed data, an OPC UA variant of type
  24 holds further variants - so the depth of the value tree is
  the sender's to choose and one level costs a single byte on the
  wire. Deep enough, that ran the parser out of stack: in Java a
  StackOverflowError, which is neither a parse failure the driver
  can report nor an error the receive path contains, so a frame
  that should have cost one frame ended the connection; in Go a
  goroutine out of stack takes the process with it rather than
  the request. Set PLC4X_MAX_NESTING_DEPTH for a device whose
  messages genuinely nest deeper - it means the same thing in
  both bindings, and a value that is not a positive number leaves
  the default in place with a warning. The deepest message in the
  project's own testsuites nests 36 levels, so this bounds only
  what no real device sends. Note for Go consumers that the
  default rose from 255 to 1024 in the process, so one setting of
  the variable now means one depth whichever binding reads it.
- plc4go now requires Go 1.27. The uuid package it used to take
  from github.com/google/uuid now comes from the standard library,
  which drops that dependency outright - it is gone from go.mod and
  go.sum - at the cost of the version floor.
- EtherNet/IP: Two CIP data type codes were wrong and are
  corrected. LWORD moves from 0x00D3 to 0x00D4 and STRINGI from
  0x00DD to 0x00DE. Each had been sharing its value with another
  type (DWORD and ENGUNIT respectively), and a duplicate key is
  silently dropped from the generated lookup tables, so LWORD and
  STRINGI could not be resolved by name or by value at all. Anyone
  who hardcoded the old LWORD value was addressing a DWORD.
- EtherNet/IP: A string write now emits the structure the read path
  parses - a 2-byte structure handle, a 4-byte length and then the
  characters - so what the driver writes reads back as the same
  value. Previously it wrote a bare length followed by the
  characters, which no read could decode. The length is now the
  number of UTF-8 bytes rather than of characters; the two differ
  for any non-ASCII text, which used to read back truncated. Text
  that does not fit the type's fixed payload is reported instead of
  overflowing. Because CIPDataTypeCode.STRING declares a size of 0,
  the serializer emits no payload for it at all, so a write
  addressed as ":STRING" is now rejected rather than silently sent
  empty - write strings as ":STRUCTURED".
- Go: Several values now serialize under their own names and in
  their canonical forms, which changes the output anything parsing
  it will see. PlcDWORD, PlcSINT, PlcULINT and PlcWSTRING were
  serialized as PlcDINT, PlcINT, PlcUINT and PlcSTRING; PlcTIME and
  PlcLTIME render ISO-8601 with hours/minutes/seconds and a
  sub-second fraction instead of truncating to whole seconds;
  PlcDATE_AND_TIME renders the UTC wall time in ISO-8601 rather
  than Go's local-zone default; and PlcStruct keeps a deterministic
  member order. String-ish values now carry encoding="UTF-8".
- Java: The unsigned bit-string values WORD, DWORD and LWORD now
  serialize as dataType="uint" rather than through the signed
  writers, PlcBYTE serializes as a bit string, and PlcTIME renders
  as an ISO-8601 string like PlcLTIME. This aligns the Java and Go
  renderings of the same value.
- EtherNet/IP: EipTag is now immutable, matching every other
  driver's tag in both bindings - it was the only tag class in
  plc4j that exposed setters. setType(...) and setElementNb(...)
  are gone; give the type and the element count to the
  constructor instead. An element count below one is normalised
  to one rather than kept, so a tag built as ":INT:0", or through
  the (tag, type) constructor which used to leave the count at
  zero, now reads one element instead of none.
- All Java drivers now select array elements with one shared notation, written
  before the data type: `[n]` for a single element, `[lo..hi]` for an
  inclusive range, an optional `;base` for an array the PLC declares as
  starting somewhere other than zero, and one bracket per dimension. The
  dimensions of one array may also be written comma-separated inside a single
  bracket - `[1..2,3..4]` is the same as `[1..2][3..4]` - which is the form
  Allen-Bradley and others use; addresses are always rendered back in the
  one-bracket-per-dimension form. See the "Addressing arrays" page.

  This replaces four incompatible spellings. `[4]` meant "four elements" in
  seven tag classes and "the fifth element" in two; it now means one element
  everywhere, and a count is written as a range. Addresses in the old form no
  longer parse, and the error names the address to write instead - so an
  upgrade reports the change rather than quietly returning different data.
  The affected forms, by driver:

    S7           %DB42:28.0:BYTE[4]        -> %DB42:28.0[0..3]:BYTE
    S7 (string)  %DB1:0:STRING(20)[4]      -> %DB1:0[0..3]:STRING(20)
    Modbus       holding-register:1:INT[4] -> holding-register:1[0..3]:INT
    SLMP         D100:INT[4]               -> D100[0..3]:INT
    ADS (direct) 0x4020/0:DINT[4]          -> 0x4020/0[0..3]:DINT
    EtherNet/IP  myArray[0]:DINT:4         -> myArray[0..3]:DINT
    Profinet     tag:INT[4]                -> tag[0..3]:INT
    Profinet-NG  1.2.INPUT.0:INT[4]        -> 1.2.INPUT.0[0..3]:INT
    Simulated    RANDOM/foo:INT[4]         -> RANDOM/foo[0..3]:INT

  OPC-UA addresses are unchanged - its implementation is the one the shared
  notation was extracted from - and ADS and UMAS symbolic addresses keep
  their existing form while gaining ranges.
- Firmata is the one driver whose addresses change meaning silently. They
  carry no data type (`3[4]`), so the brackets did not move and there is
  nothing to reject: `3[4]` used to read four pins starting at pin 3 and now
  reads one pin, the fifth. Rewrite these as `3[0..3]`.
- An address that selects nothing now asks for the whole value rather than a
  single element. For a scalar that is unchanged; for an array it is every
  element, on the drivers that can determine the extent from the device
  (OPC-UA, ADS, UMAS). The others read one element as before, because their
  addresses are memory offsets with no declared array at them.
- A single index and a one-element range are no longer the same thing.
  `myTag[4]` selects one element and yields a scalar, while `myTag[4..4]`
  yields a list of one. `PlcTag.getArrayInfo()` reports the shape of the
  value received - empty for a scalar, one entry per dimension for an array -
  so a consumer can tell the two apart without knowing the protocol.
- `ArrayInfo` gains `getBase()` and `isRange()`, both as default methods, so
  existing implementations keep compiling. Its javadoc described `[6]` as a
  six-element array, which was never what the drivers did and is not what the
  notation means.
- EtherNet/IP rejects an array index above 255 while parsing the address; a
  CIP MemberID carries a `uint 8`. A range may run past it, since the request
  carries a start and a count, but it cannot begin there.
- ADS and UMAS verify a `;base` written in the address against the bounds the
  device declares, and report a disagreement. The device is authoritative; a
  base that differs means the address was written against a different layout,
  which would otherwise read silently shifted data.
- ADS rejects an address that names a member of an array without saying which
  element - `MAIN.g_arr.member` on an array `g_arr`. It previously resolved
  against the first element and reported the result as though it were the
  whole path.
- Selecting array elements over UMAS is reported as UNSUPPORTED rather than
  returning the whole variable. The driver has no per-element arithmetic yet;
  the address parses, and the refusal is explicit.
- Fixed `getArrayInfo()` reporting one element too many on the ADS direct and
  Firmata drivers, whose inclusive bounds were built from the element count
  rather than the last index.
- Fixed a direct ADS array selection transferring every element it asked for
  and decoding only the first, in both PLC4J and PLC4Go. The size of the
  request was multiplied by the element count while the decoder was given no
  shape, so `0x4020/0[0..3]:DINT` returned one value for four elements' worth
  of bytes - a well-formed answer to a question nobody asked.
- Fixed a symbolic ADS selection being ignored in PLC4Go. `MAIN.arr[1..4]`
  resolved like `MAIN.arr`: the whole array, from its original offset. The
  selection now moves the read to the first selected element and transfers
  only what it spans, across as many dimensions as the address names
  (`MAIN.grid[3,1..3]`), and a selection outside what the device declares is
  refused rather than approximated.
- Fixed the shape of a partly selected multi-dimensional ADS array in PLC4J.
  `MAIN.grid[1..2]` on an `ARRAY [0..9,0..4]` reported two elements rather
  than two rows of five: the dimensions the selection did not name were
  dropped from the shape while their bytes were still transferred. They are
  selected whole, and are part of the value.
- A dimension of an ADS selection written as a bare index now collapses,
  where before every named dimension added a level of list. `grid[3,1..3]` is
  a list of three, not a list of one list of three, and `grid[3,2]` is a
  scalar. This is the same rule the notation states for a single dimension.
- Fixed SLMP reporting a one-element range as a scalar in PLC4J. `D100[4..4]`
  now returns a list of one, as `D100[4]` returns a scalar and as PLC4Go's
  SLMP driver already did. Its shape came from the element count, which
  cannot express the difference.
- PLC4Go now uses the same array notation as PLC4J, so one address means one
  thing in either language. The grammar, the rules and the rendering are the
  ones described above; the two share a specification rather than code, and
  the Go parser is tested against the Java cases directly.

  The forms that changed, by driver:

    S7           %M100:INT[10]             -> %M100[0..9]:INT
    S7 (string)  %DB69.DBX68:WSTRING[3]    -> %DB69.DBX68[0..2]:WSTRING
    Modbus       holding-register:1:INT[4] -> holding-register:1[0..3]:INT
    SLMP         D100:INT[4]               -> D100[0..3]:INT
    EtherNet/IP  %rate:DINT:4              -> %rate[0..3]:DINT
    Simulated    RANDOM/foo:INT[4]         -> RANDOM/foo[0..3]:INT
    KNXnet/IP    1.2.3#4B1C:UINT[4]        -> 1.2.3#4B1C[0..3]:UINT
    KNXnet/IP    1.2.3#11/1/1[4]           -> 1.2.3#11/1/1[0..3]

  Addresses in the old form no longer parse, and the error names the address
  to write instead - with two exceptions, below, where the address parses
  either way and only its meaning moves.
- Two Go drivers change the meaning of addresses that still parse, so there is
  nothing to reject and nothing to warn about at runtime:

    * ADS `[n]` was a *count* of n elements and is now the element at index n.
      `MAIN.g_arr[3]` read three elements and now reads one. Rewrite as
      `MAIN.g_arr[0..2]`. This also means Go and Java ADS now agree about the
      same address; they did not before.
    * Firmata `[n]` was a run of n pins and is now the pin at index n, exactly
      as in PLC4J. `digital:2[3]` read three pins from pin 2 and now reads
      pin 5. Rewrite as `digital:2[0..2]`.
- ADS also drops the `[a:b]` start-and-count form, which had no counterpart in
  PLC4J. `MAIN.g_arr[2:4]` is written `MAIN.g_arr[2..5]`.
- A count of zero no longer has a spelling. Several Go drivers accepted `[0]`
  and rejected it as "quantity must be greater than zero"; a range is written
  with the indices it covers, so there is no way to ask for none, and `[0]`
  now selects the first element.
- `ArrayInfo` bounds are inclusive in PLC4Go, as they are in PLC4J:
  `GetSize()` returns `UpperBound - LowerBound + 1`. They were exclusive,
  documented as a deliberate divergence, so `[0..7]` reported eight elements
  in Java and seven in Go - the same disagreement about the same address that
  this change exists to remove. Code reading `GetUpperBound()` directly must
  be revisited.
- `ArrayInfo` gains `GetBase()` and `IsRange()`. Go has no default methods, so
  any implementation outside PLC4Go must add them.
- Addresses that a driver rendered back are now spelled the way its parser
  reads them. Several never round-tripped: BACnet/IP rendered `:` where the
  syntax wants `,`, gave every property a leading `:`, and printed the address
  of the pointer holding an array index rather than the index; KNXnet/IP
  device addresses rendered `/` where the syntax wants `.`; the ADS direct
  form printed its index group as decimal digits behind an `0x` prefix, so
  16416 came back as `0x16416` - a different address; and the S7 tag rendered
  as "0:INT[8]", naming neither the memory area nor the offset it read.
- Fixed the Go BACnet/IP driver asking for one element fewer than requested
  when a read carried an element count, which followed from the bounds
  becoming inclusive.
- C-Bus addresses are unchanged. Its brackets carry the arguments of a CAL
  command (`recall=[param, count]`), not a selection appended to an address.
- KNXnet/IP group addresses are unchanged. Their brackets hold a set of group
  addresses to match (`[1-3,5]`), not an array selection. Only the two device
  address forms, which carry a real element count, moved to the new notation.
- BACnet/IP addresses are unchanged. Its bracket is a property array index,
  which already meant what the notation says an index means.
- A connection reports the operations its driver actually implements.
  ConnectionBase answered "true" to isReadSupported(),
  isWriteSupported(), isSubscribeSupported() and isBrowseSupported()
  for every driver built on it, whatever that driver implemented, so
  the metadata a tool uses to decide what to offer was not worth
  reading. In PLC4Go the EtherNet/IP and Modbus connections left
  ProvidesSubscribing and ProvidesBrowsing at their zero value,
  reporting "false" by accident rather than by decision. Both now
  state what they support, so code branching on these flags will see
  different - and correct - answers.
- S7: The day-of-week nibble of a DATE_AND_TIME is numbered the way an
  S7 numbers it, counting from Sunday as 1 to Saturday as 7. Both
  bindings filled it from their date library, which counts from
  Monday, so every DATE_AND_TIME written to a PLC carried a day of
  week one short. Parsing rotates back, so the value still round-trips
  through PlcDATE_AND_TIME, whose getter keeps the ISO-8601 numbering
  that KNX DPT 19.001 needs. Only IEC61131_DATE_AND_TIME is affected;
  the DTL variant already carried the Siemens numbering.
- Go: PlcDATE_AND_TIME's GetDayOfWeek() returns the numbering PLC4J
  returns - 1 for Monday through 7 for Sunday - rather than Go's
  time.Weekday, which counts Sunday as 0. A zero there means "no day
  given" in KNX DPT 19.001 and is simply invalid for S7.
- Go: A request that runs out of time is reported as a timeout rather
  than as an INTERNAL_ERROR. This covers both the driver's own
  request timeout and a deadline the caller set on the context it
  passed in - the idiomatic way to call this - so code telling a
  timeout from a real failure to know whether retrying makes sense
  will now see the timeout it was looking for.

Changed Maven Coordinates
-------------------------

The Maven groupId of all modules is unchanged ("org.apache.plc4x").
The following artifactIds changed; consumers must update their
dependency coordinates accordingly:

- The "tools" modules were renamed to the "plc4j-tools-*" pattern:
    plc4j-capture-replay    -> plc4j-tools-capture-replay
    plc4j-connection-cache  -> plc4j-tools-connection-cache
    plc4j-opm               -> plc4j-tools-opm
- The transport modules were renamed from the singular
  "plc4j-transport-*" to the plural "plc4j-transports-*":
    plc4j-transport-can         -> plc4j-transports-can
    plc4j-transport-pcap-replay -> plc4j-transports-pcap-replay
    plc4j-transport-raw-socket  -> plc4j-transports-raw-socket
    plc4j-transport-serial      -> plc4j-transports-serial
    plc4j-transport-tcp         -> plc4j-transports-tcp
    plc4j-transport-test        -> plc4j-transports-test
    plc4j-transport-udp         -> plc4j-transports-udp
    plc4j-transport-socketcan   -> plc4j-transports-can-socketcan
    plc4j-transport-virtualcan  -> plc4j-transports-can-virtualcan
- The scraper was replaced by the new event-pump component:
    plc4j-scraper               -> plc4j-tools-event-pump
- Removed modules (no direct replacement):
    plc4j-scraper-ng            (experimental, dropped)
    plc4j-transport-pcap-shared (obsolete)

Note: this release also adds a number of new SPI3 modules (e.g.
the "plc4j-spi-*" buffers/config/drivers/values split, the new
"plc4j-transports-api"/"-cotp"/"-tls" transports, the
"plc4j-utils-audit-log*" and "plc4j-utils-subscription-emulation"
utilities). These are new artifacts, not renames.

Bug Fixes
---------

- Fixed the Java S7 driver's tags reporting no address at all:
  "getAddressString()" returned null, so anything carrying a tag as a string -
  a log line, a browse result, a serialized request - got nothing from an S7
  tag. It now spells the address the way the parser reads it back, including
  the declared length of a fixed-length string and the counter number of a
  COUNTER address, which is stored split across the byte and bit offsets.
- The Open Protocol driver's tag class now reports that it has no tag
  addressing yet instead of returning null. "OpenProtocolTag.of()" handed a
  null tag to callers of "prepareTag()", so the failure surfaced later as a
  NullPointerException; it now throws PlcInvalidTagException, matching the
  driver's tag handler, which already rejected every address.
- Fixed the Go S7 driver reading a fixed-length string from the wrong data
  block. The long-form address ("%DB69.DBX68:STRING(10)") built its tag with
  a hard-coded block number of zero, so it read DB0 and reported the result
  as though it had come from DB69. The short form ("%DB69:68:STRING(10)")
  and every non-string address were unaffected, as is PLC4J, which parses
  the block number for all of them.
- Fixed serialization in the 'plc4x' proxy driver's message
  codec, which did not configure the buffer integer/string
  encodings under SPI3 and failed to serialize any message.
- OPC-UA: Fixed several issues: a hang during discovery /
  encrypted-policy negotiation, a divide-by-zero when the server
  provided no certificate, and hardened parsing of corrupt or
  malicious responses that could previously cause an
  OutOfMemoryError.
- ADS: The connect handshake now honors the configured AMS ports
  instead of hardcoding RUNTIME_SYSTEM_01/851.
- ADS: Fixed an invalid size calculation in AdsDataTypeArrayInfo.
- ADS: Fixed serialization of STRING/WSTRING values.
- S7: Fixed duplicate TSAP information at the COTP and S7 level.
- Connection-cache: Fixed a deadlock when obtaining a connection,
  plus a race condition and idle-timer/cleanup issues.
- The base driver now redacts password information from console
  logs.
- TCP transport: Close the SocketChannel on a failed bind /
  socket-option setup.
- Request objects were made more null-safe (#2280).
- OPC-UA: All consumers registered on a shared subscription now
  receive notifications (previously only one consumer was
  registered).
- AB-ETH: Fixed reading a tag after the SPI3 refactoring.
- The socket is now disconnected when the handshake fails instead
  of being left hanging (#2290).
- Go Modbus: Hardened frame parsing against truncated/extended
  frames, trailing CRCs from misbehaving gateways and TCP
  keep-alive padding, with stream resynchronization on desync.
- Go: Numerous stability and resource-leak fixes (connection cache
  no longer hands out dead connections, goroutine and codec-worker
  leaks on Modbus reconnect, robust Modbus receive with
  desync/resync, TCP/UDP transport deadline and reset races, codec
  disconnect deadlock).
- Go: Generated code ignored the string encoding declared in the
  mspec and read and wrote every string as UTF-8. A WSTRING, which
  ADS declares as UTF-16LE, stopped at the first NUL byte, so
  "wolf" decoded as "w". The generated code now carries the real
  encodings (UTF-16LE, UTF-16BE, ASCII, ISO-8859-1, Windows-1252),
  and the byte-based write buffer passes the single-byte encodings
  through instead of zero-filling anything it did not recognise.
  Reading a string likewise honors the requested encoding, decoding
  UTF-16 per code unit rather than per byte.
- Java: The XML buffer could not read back everything its own
  writer produced. A field discriminating on a typed enum was
  written under the enum's name but read under the field's, and a
  text node larger than the parser's chunk size - the ADS symbol
  and data-type tables run to 70-80k characters - failed with
  "Expected end element" because the reader was not coalescing.
- ADS (Go): Several fixes. The connection accepts the same
  kebab-case parameters as the Java driver (source-ams-net-id and
  friends), and a missing targetAmsNetId is now reported as such
  rather than as sourceAmsNetId. The device-info request uses the
  configured AMS ports instead of a hardcoded 851/800. Multi-tag
  subscriptions run in request order rather than in map order,
  honor the requested interval as the notification cycle time, and
  no longer panic when a data type is missing from the table. The
  data type table is keyed by the name symbols actually reference.
- ADS (Go): Direct-address reads and writes all failed with
  "invalid tag item type" - the request paths expected a pointer
  where the tag handler produced a value - and never filled in the
  tag's data type. Hex address parts with an odd number of digits
  (0x8) were rejected, though the Java driver accepts them.
- EtherNet/IP: A reply carrying fewer bytes than a single-element
  tag declares no longer throws out of the response handler; it is
  reported as INTERNAL_ERROR for that tag, which is what a
  truncated multi-element reply already did.
- Modbus (Java): Several fixes to the read optimizer. The unit-id was
  dropped while a request was being optimized, so an optimized read
  went out with the default unit-id instead of the one the tag named
  (#2686); a read of coils returned only the first value (#2060); a
  non-BOOL tag pointed at coils is reported instead of being misread;
  and the trailing register pad was sized from a string length of one,
  so an odd number of STRING or WSTRING values picked up a pad byte
  the registers did not need.
- EtherNet/IP: Fixed reading arrays, which generally did not work
  (#1008). A response is no longer handed to a request it does not
  belong to, and a tag address that cannot be parsed is reported for
  that tag rather than failing the request.
- Tag addresses that cannot be parsed are reported per tag in the
  EtherNet/IP, Modbus, OPC UA, S7 and simulated drivers, as the API
  promises. One unparseable address used to fail the whole request,
  including the tags that were fine.
- S7: A controller refusing a request because PUT/GET communication is
  disabled is reported as ACCESS_DENIED. Only two of the three header
  forms were mapped, so the 0x83/0x04 an S7-300 sends read as
  INTERNAL_ERROR and a refused write could not be told from a failed
  one (GH-599). Also fixed an asymmetry between the tags a request
  accepts and the tags it hands back (#2388), and a timestamp for the
  year 2000, which parsed but could not be serialized again.
- SPI: A request waiting for a permit no longer blocks the thread it
  was submitted on. A driver chaining requests runs the follow-up on
  whichever thread completed the previous one, typically the
  connection's receive thread, which then parked waiting for a permit
  that only it could have freed - the connection recovered when an
  unrelated request timed out. Negotiated max-amq is often 1 to 3 on
  an S7-300, which makes this easy to reach. Requests are queued and
  started in submission order as permits free up.
- SPI: An unchecked exception out of a generated parser is reported as
  the parse failure it is instead of ending the thread that owns the
  channel, which left the transport claiming to be open with nobody
  reading it.
- A message that stops short is refused rather than half-believed, in
  both the Java and the Go bindings: a manual array whose reader
  cannot make progress ends instead of looping (a firmata sysex
  message ending mid-string was an endless supply of items), an
  optional field the message announces has to actually be present, a
  BACnet tag header length is derived only from fields that were read,
  an S7 payload is read only when its parameter was, and the cast of a
  parsed complex field is checked. plc4c and plc4py carry the same
  nesting-depth bound as Java and Go.
- OPC-UA: The self-signed certificate the driver generates when no key
  store is configured - the one most servers see on a first connect -
  is now one a modern server accepts: signed with SHA-256 rather than
  SHA1withRSA, a positive serial of sixteen octets rather than forty
  random bytes, marked as an end entity rather than as a certificate
  authority, and carrying a subject key identifier.
- OPC-UA: The client identity is the first key store entry that holds
  a private key, not whatever alias comes first. The tutorial's own
  set-up has "ca" sorting before "client", so the driver could hand
  the server the CA entry, or carry on with a null private key; the
  server just closed the connection. A store with no private key, an
  entry that cannot be read (which is what a wrong key-store password
  looks like) and a non-RSA key each now fail naming the entry and the
  reason.
- OPC-UA: The certificate chain is sent in the asymmetric security
  header, not the client certificate alone, so a server that trusts
  the issuing CA rather than the certificate itself can build a path
  to its trust anchor. The thumbprint still covers the client
  certificate, as the specification requires.
- OPC-UA: A username token is encrypted with the algorithm the
  server's user token policy names, instead of always RSA-OAEP, so
  username and password authentication works against a server asking
  for RSA-PKCS1.5 (#2154).
- OPC-UA: A subscription hands out one PlcSubscriptionHandle rather
  than an identical one per tag (#1896) - corrected for every driver
  that supports subscriptions - and tags registered with
  addCyclicField(...) produce events again, through the same
  cyclic-subscription emulation the other drivers use, since OPC UA
  itself has no cyclic subscriptions (#1102).
- OPC-UA: The stream a key store is read from is closed, as is the
  reader a BACnet EDE file is parsed from.
- ADS: With "load-symbol-and-data-type-tables=false" a symbolic
  address is refused with a message saying the tables were not loaded,
  rather than failing as an unknown symbol or, when browsing, as
  nothing at all. Reading and writing are limited to direct addresses
  in that mode; subscriptions are unaffected, since they resolve
  symbol handles on the device (#1626).
- OPM: The PlcEntityManager caches the proxy classes it generates
  rather than generating a new one on every connect, which used to
  grow the metaspace of an application connecting repeatedly (#1935),
  and List and array fields are mapped instead of mishandled (#1947).
- NiFi: The connection-string validator closes the connection it opens
  to test the string. NiFi validates on every configuration change and
  while the dialog is open, so each round left a connection behind -
  for OPC UA a secure channel and a session the device holds until
  they time out, which on hardware with a small connection limit locks
  everyone else out. It also catches an unchecked rejection, which is
  how some drivers report a bad connection string.
- KNXnet/IP: A browse answers the query it was asked rather than every
  query in the request, and reading a knxproj cleans up what it
  unpacked.
- Go: A future publishes its error before the flag that releases
  whoever is waiting on it, a blocking subscription consumer no longer
  wedges the poller for everyone else, the codec survives a reconnect
  and a late expectation, and the KNXnet/IP discoverer no longer leaks
  a goroutine and a socket per discovery.

==============================================================
Apache PLC4X 0.13.1
==============================================================

New Features
------------

- Extended the PlcRawByteArray to provide access to a List of
  USINT objects.

Incompatible changes
--------------------

Bug Fixes
---------

- When reading an array of bits, the old s7 driver seems to hang.
- The s7 driver causes issues when writing arrays of bits.
- The block optimizer used in s7-light causes errors, if a tag
  references the same byte multiple times.
- When using the new block-optimizer in the s7-light driver,
  when reading multiple BOOL values located in the same byte
  produces errors

==============================================================
Apache PLC4X 0.13.0
==============================================================

New Features
------------

- The CachedPlcConnectionManager now has a maxIdleTimeout time
  which defaults to 5 minutes. If a connection is not being
  used for that amount of time, the connection is closed and
  removed from the cache.
- The CachedPlcConnectionManager now has a close method, which
  shuts down all connections.
- The CachedPlcConnection now implements the EventPlcConnection
  interface which forwards listener registrations to the
  connection.
- The S7 driver is now able to automatically split up large
  array requests into multiple ones and transparently merge
  them back together. It is now possible to read arrays of
  almost unlimited size.
- Added an Optimizer to the Modbus driver, that improves read
  performance of multi-item read requests by more than 10 times.
- Added an optimizer to the Modbus protocol, that allows reading
  multiple fields in one request.
- Added support for Modbus encodings of BIG_ENDIAN_WORD_SWAP
  and LITTLE_ENDIAN_WORD_SWAP.
- Modbus tags allow specifying the unit-id in order to address
  multiple devices using one serial modbus connection.
- Added a new optimizer to the S7 protocol, that ready chunks
  of data instead of individual fields, which allows reading
  a lot more fields in one request.
- Added a new variant of the S7 driver, called s7-light, which
  doesn't have support for subscriptions, but is less likely
  to cause connection problems.
- Added auto-discovery to the KNX Driver in PLC4J.
- Added auto-discovery to EIP in PLC4J.
- Added auto-discovery to S7 in PLC4J.
- Improved some things in the SPI, that caused issues with
  drivers under heavy load.
- The Modbus driver uses the "Single Register Request" if a
  tag fits into one register. This can help communicating with
  devices that don't support "Multi Register Requests".

Incompatible changes
--------------------

- When reading byte arrays with the s7 driver, now the more
  efficient PlcRawByteArray type is used, that gives users
  direct access to the bytes returned from the PLC instead of
  a list of PlcValues.
- The builders for read-, write- ans subscription.requests now
  process tags and values on a per-field level. If one field
  has an invalid address it will now only fail the one item
  related to that. Same applies to values. Only the tag who's
  value was invalid will be considered failed and no longer an
  exception should be thrown.
- Subscription-requests now allow registering a handler for
  all fields in the subscription.
- The addPreRegisteredConsumer method was removed and versions
  of the "addXYZ" methods were added, that allow providing
  individual consumers for each tag.


Bug Fixes
---------

==============================================================
Apache PLC4X 0.12.0
==============================================================

New Features
------------

- API: Made several bits of information available via the API
  allowing tools to provide more content assist when dealing
  with PLC4X connections.
- S7: The S7 driver now supports reading of STRING and
  WSTRING data-types without providing a maximum length.
- Build: Worked on making PLC4X provide reproducible builds.
- Added "Ping" functionality to: ADS, EIP, KNX, Mock, Modbus
  and Simulated drivers.
- The OPC-UA Java driver now support certificate-based
  authentication and encryption.

Incompatible changes
--------------------

- Java 8 is no longer officially supported and Java 11 is the
  new base-line.
- Renamed the PlcDriverManager method `listDrivers` to
  `getProtocolCodes`
- Renamed the PlcDriverMetadata method `canDiscover` to
  `isDiscoverySupported`
- Renamed the PlcConnectionMetadata methods `canRead`, `canWrite`
  `canSubscribe` and `canBrowse` to `isReadSupported`,
  `isWriteSupported`, `isSubscribeSupported` and `isBrowseSupported`
- The configuration syntax for configuring transport-related
  config options in the connection-string was updated to be
  now prefixed with the transport name the option belongs to.

Bug Fixes
---------

- S7: Several bugs and issues regarding supporting various
  duration, date and time data-types.
- S7: Implemented the missing 64bit (L-) types.
- KNX: Fixed an issue with decoding 16 bit floating point
  numbers.
- NiFi-Integration: The NiFi integration module was greatly
  improved.
- Core: Fixed several leaks of open threads.

==============================================================
Apache PLC4X 0.11.0
==============================================================

New Features
------------

- IEC-60870-5-104 driver
- Completely rewritten EIP driver that should now support
  Allen-Bradley controllers
- Completely rewritten the ADS driver that now supports
  Auto-Discovery, Browse, UDOs and auto-configuration of
  remote AMS routes
- Support for S7 200 subscriptions
- Added a docker-compose setup in a preparation for reproducible
  builds
- Added SBOM generation
- Improved Apache NiFi support
- Added support for the latest ETS version in KNX
- Started implementing the ping() method for some drivers
- Greatly updated Apache NiFi integration

Incompatible changes
--------------------

- Java 1.8 is no longer supported and Java 11 is now the new
  baseline version we support.
- We've updated the APIs of both PLC4J and PLC4Go to be more in
  sync. We also refined some of the terminology.
- We've also re-written the `connection-cache`, which now replaces
  both the old `connection-pool` and the old `connection-cache`.
- The UI module has been removed as it relied on JavaFX, which is
  no longer bundled with the JDK and therefore the LGPL license
  renders is dad for Apache projects.
- The Apache Camel integration was moved over to the Apache Camel
  project.
- The prototype-driver for PROFINET was completely updated
- Due to the extreme refactoring of S7, ADS and EIP, the Go versions
  of these drivers are currently not going to work as well as before
  (We're going to address these issues in the next phase after the
  release)
- Changed the return type of the PLC4J Ping method to return more
  information on if the ping was successful

Bug Fixes
---------

Fixed issues with memory leaks in the ConnectionManager

Fixed multiple issues reported for the handling of data-types in
S7, Modbus and ADS protocols when reading and writing.

==============================================================
Apache PLC4X 0.10.0
==============================================================

A lot of the work in this version went into refactoring and
cleaning up our code generation. The code generation itself is
now a lot cleaner and simpler as well as the code generated
for Java. We also added a number of new field-types to allow
implementing more sophisticated protocols. PLC4C now should
also support all of the constructs mspec has to offer.

New Features
------------

- Implemented a `PLC4X-Server` and `PLC4X-Driver` that allows
  using the server as a proxy for communicating with PLCs.

- The Modbus driver is now also available in the variants:
  "modbus-rtu" and "modbus-ascii" (Both using Serial
  communication, which however can be tunneled through a
  "tcp" and "udp" transport)

- The KNX driver in Java now supports reading "knxproj" files
  exported from the new ETS version 6.

Incompatible changes
--------------------

- The name of the Modbus TCP driver was changed from "modbus"
  to "modbus-tcp".

- Removed the Apache Edgent (incubating) integration and
  examples related, as Edgent is abandoned and there were
  CVEs reported, which will not be fixed.

- We have replaced the BitString types with BYTE, WORD, DWORD,
  and LWORD which generally match their unsigned integer
  counterparts. So we are no longer returning lists of boolean
  values for any of these types.

Bug Fixes
---------

- Fixed a big bug in the KNX Datapoint decoding, which caused
  byte-aligned data types to parse with an offset of 8 bit.
  (This bug affected both the Java and the Go driver)

==============================================================
Apache PLC4X 0.9.0
==============================================================

New Features
------------

- The OPC UA driver has been replaced with a native driver. Previously
  Eclipse Milo was being used.

- Permit customized package names for code generation

- Added an initial draft of a Discover and Browse API to PLC4J

- PLC4Go now supports many more drivers

- PLC4Go received a huge internal refactoring and cleanup

- Major cleanup of PLC4C

- S7 Driver now supports event and alarm handling on some S7 models

Incompatible changes
--------------------

Bug Fixes
---------

PLC4X-200   OPC-UA Driver not connecting if params string is not provided
PLC4X-201   OPC-UA PlcList underlying type not compatible with Eclipse Milo
PLC4X-202   OPC-UA Driver cannot write Unsigned Types
PLC4X-276   [S7] The most of the supported types don't work correctly
PLC4X-278   Double Reading Error
PLC4X-279   nioEventLoopGroup thread proliferation
PLC4X-280   ADS route request swapped positions of route name and address
PLC4X-291   DefaultPlcSubscriptionField cannot be cast to class OpcuaField
PLC4X-298   [S7] When writing REAL values the Write
            operation fails with an internal error
PLC4X-299   Modbus - Kafka Connect Configuration
PLC4X-312   CAN NOT READ STRING FROM S7 PLC
PLC4X-314   CAN NOT WRITING MANY DATA TO S7 ONE TIME

==============================================================
Apache PLC4X 0.8.0
==============================================================

This is an ordinary PLC4X release, containing changes that
accumulated over time. It doesn't have an explicit focus on
a particular topic.

New Features
------------

- The KNXnet/IP Driver now supports writing of values.

- The Modbus driver now supports more common notations of
  Modbus addresses using a pure-numeric notation.

- The ADS, KNX, Modbus, S7 and simulated drivers have been
  updated to support the IEC 61131-3 data-types.

- We are now including PLC4Go as PLC4X implementation in
  the programming language Go(lang)

- Integration with the Milo OPC UA Server is now available.

- Kafka Connect workers have been updated source and sink connectors
  are now included.

Incompatible changes
--------------------

- The syntax of the S7 addresses changed slightly allowing to
  provide a string length. Without this, a STRING datatype will
  read 254 characters, by adding the size in round brackets to
  the type name will use the specified number.

  Examples:

  Read one String which is max 10 chars long:
  %DB2:30:STRING(10)

  Read an array of 3 Strings where each is max 10 chars long:
  %DB2:30:STRING(10)[3]

- The PLCValue types have been refactored to align with the types
  defined in IEC 61131-3 (https://en.wikipedia.org/wiki/IEC_61131-3)
  directly using the older Java types (PlcBoolean) is no longer
  possible.

Bug Fixes
---------

A lot of testing was done regarding the IEC 61131-3 data-types.
This resulted in numerous bugfixes in many protocols.

PLC4X-132   [S7] Communication to S7 PLC dies in some situations
PLC4X-206   When writing short values exceptions are thrown
            while preparing the write request.
PLC4X-207   No registered handler found for message TPKTPacket[],
            using default decode method - Communication with S7
            and Modbus device hangs
PLC4X-209   [S7] When writing INT and DINT values the Write
            operation fails with an internal error
PLC4X-210   [KNX] When running a KNX Tunneling Subscription
            for a longer time there are packets that kill
            the connection
PLC4X-211   PlcValues seem to always return "true" on the
            isXYZ" checks.
PLC4X-212   When writing multiple values in one request the
            item status is not correctly set
PLC4X-213   [Modbus] The Modbus driver doesn't handle error
            responses gracefully
PLC4X-214   [Modbus] Holding register addresses have an offset
            of 1 (Not reading the correct address)
PLC4X-215   Drivers using the BaseOptimizer
            (SingleFieldOptimizer) don't handle error responses
            gracefully
PLC4X-218   [Scraper] After stopping the scraper still the
            statistics are logged and the application doesn't
            terminate
PLC4X-239   Read DTL (Date and Time)
PLC4X-240   Protocol error in reading string
PLC4X-246	S7 driver hangs on read
PLC4X-245   [Modbus] Apache NiFi processor throws
            java.io.IOException after a while
PLC4X-255   Kafka Connector Source Task doesn't block within poll()
            resulting in high CPU usage.
PLC4X-261   Pooled connection manager returns a connection that isn't
            connected in some situations.
PLC4X-272   When splitting up large requests, too big sub-requests
            are generated (S7)
PLC4X-256	ReadBuffer truncate last byte of even small payloads
PLC4X-262	Error in reading Array
PLC4X-270	Ads driver does not accept double-digit array indexes

==============================================================
Apache PLC4X 0.7.0
==============================================================

This version is the first after a major refactoring of the driver
core. All previous driver versions are now considered deprecated
and have been replaced by versions using the new driver structure
and generated driver codebase.

New Features
------------

- Drivers now support structured types using PlcValues
- The EIP (EtherNet/IP) driver no longer requires an external
  library and is implemented fully in the PLC4X project
- The Modbus driver no longer requires an external library
  and is implemented fully in the PLC4X project
- The new S7 Driver supports writing multiple entries in one
  request (The API allowed this from the beginning now not
  every item is wrapped in a single request. It should bring
  significant performance gains when writing multiple values)
- S7 Driver now supports String datatypes.
- OSGi : Implementation of Drivers/Transports as OSGi services
  to be able to use them in an OSGi container.
- New Firmata protocol driver

Incompatible changes
--------------------

- Due to the refactoring of the driver core there might be issues
  running drivers built against older core versions.
- This version doesn't provide a Beckhoff AMS/ADS driver as this
  driver is still being ported to the new mspec format.
- All drivers connection strings now follow the same pattern:
  {protocol-code:(transport-code:)?//{transport-config}(?{params})?
  Please check the drivers documentation on our website:
  https://plc4x.apache.org/users/protocols/s7.html
- The karaf-feature modules are removed as the drivers now all
  provide both a feature.xml as well as a `kar` bundled archive

Bug Fixes
---------

PLC4X-174	UDP Transport does not accept ports containing 0
PLC4X-134   S7 is terminating the connection during handshake
PLC4X-192   Support for conversion of complex connection string
            parameters

==============================================================
Apache PLC4X 0.6.0
==============================================================

This is the last release of PLC4X with the "handwritten" drivers.
This Minor release will thus receive updates and fixes until
most users have switched to 0.7 and above (with generated drivers).

If you are using the S7 Driver you should update to this Version
as the critical (memory leak) bug PLC4X-163 is fixed.

New Features
------------
- PLC4X-168 A shorter S7 Field Syntax is Introduced.
This release contains no further features and mostly stabilization.

Incompatible changes
--------------------
- Moved the C++, C# and Python drivers into the `sandbox`

Bug Fixes
---------
- Fixed Promise Chain for InternalPlcWriteRequest
- PLC4X-45 Add float support to Modbus Protocol
- PLC4X-164 Fix wrong NOT FOUND exception in OPC UA Driver
- PLC4X-166 Fixed Download Page
- PLC4X-163 Fixed Netty ByteBuf Leaks for S7 Driver
- PLC4X-158 Added Warning if no Pooled Driver is used for Scraper

==============================================================
Apache PLC4X 0.5.0
==============================================================

This is the first release containing our new generated drivers (AB-ETH)

New Features
------------

- Implemented a new Apache Kafka Connect integration module
- Implemented a new Apache NiFi integration module
- Implemented a new Logstash integration module
- Implemented a driver for the AB-ETH protocol
- Implemented Apache Karaf features for S7 OSGI drivers
- PLC4X-121	Develop Code Generation to allow Generated Drivers in multiple Languages

Sandbox (Beta-Features)
- Implemented a new BACnet/IP passive mode driver
- Implemented a new Serial DF1 driver

Incompatible changes
--------------------

Bug Fixes
---------

- PLC4X-104	S7 Driver Datatype TIME_OF_DAY causes ArrayOutOfBoundException
- PLC4X-134	S7 is terminating the connection during handshake
- PLC4X-139	PLC4X leaks sockets in case of connection problems
- PLC4X-141	String with real length of greater 127 throw an exception
- PLC4X-144	When requesting invalid addresses, the DefaultS7MessageProcessor produces errors

==============================================================
Apache PLC4X 0.4.0
==============================================================

This is the first release of Apache PLC4X as top-level project.

New Features
------------

- The PlcConnection now supports a `ping` method to allow checking if an existing connection is still alive.
- Support of the OPC-UA protocol with the `opc-ua-driver`.
- Other Languages Support:
-- Added first versions of a C# .Net PLC4X API (`plc4net`)
-- Added first versions of a Python PLC4X API (`plc4py`)
- Added an Interop server which allows to relay requests from other languages to a Java Server

Incompatible changes
--------------------

- ElasticSearch example was updated to use ElasticSearch 7.0.1, this might cause problems with older Kibana versions.

Bug Fixes
---------


==============================================================
Apache PLC4X (incubating) 0.3.1
==============================================================

This is a bugfix-release, that fixes some problems with S7 driver.

Bug Fixes
---------

- The S7 driver didn't correctly handle "fill-bytes" in multi-item read-responses and multi-item write-requests
- PLC4X-83: fixed NPE when reading odd-length array of one-byte base types
- PLC4X-82: renamed flags "F" to Siemens Standard "M" (Marker)
- PLC4X-84: Fixed a bug in the DefaultS7MessageProcessor which didn't correctly merge together split up items


==============================================================
Apache PLC4X (incubating) 0.3.0
==============================================================

This is the third official release of Apache PLC4X.

Some new features have been added (e.g. plc-scraper) multiple
new integrations are included (apache-karaf, apache-calcite)
and a lot of (technical) refactoring has been done to prepare
future work on adapters in different languages.

New Features
------------

- Object PLC Mapping (OPM) now has a Alias Registry to allow
  variable substitution at runtime and write support
- New module `plc-scraper` for applications that have to
  scrape a lot of sps fields with high frequency
- New integration `apache-karaf` to enable plc4j in a karaf
  runtime environment

Incompatible changes
--------------------
- The 'plc4j-core' module has been merged into 'plc4j-api'.
  So there is no 'plc4j-core' module anymore. Just remove that
  dependency.
- The driver artifact names have changed so if you were using
  a `plc4j-protocol-{name}` you now need to change this to
  `plc4j-driver-{name}`

Bug Fixes
---------

PLC4X-75    Fixing dependency to the wrap url-handler
PLC4X-76    When receiving responses with more than 512 byte,
            the IsoOnTcp protocol doesn't work
PLC4X-77    When the last item in a request is a DINT, the
            DefaultS7MessageProcessor dies
PLC4X-78    Write operations seem to fail
-           Fixed a Bug where S7 was not able to read arrays.


==============================================================
Apache PLC4X (incubating) 0.2.0
==============================================================

This is the second official release of Apache PLC4X.

Especially have we addressed all issues reported during
our first release, that were of non-technical nature.
These were tracked in:

PLC4X-60	Fix findings by the last release

New Features
------------
A new connection-pool was added, which allows automatic
pooling and reuse of PLC connections.

A new OPM module was added, which allows JPA like read-
communication using POJOs, very similar to JPA.

A stub of a new driver for the Emerson DeltaV protocol
has been added, but is not yet a fully functional PLC4X
driver. This is also a first test of our new `passive-
mode-driver` concept.

Incompatible changes
--------------------

We have refactored the API in order to eliminate the
need of passing `x-requests` to `x-methods` and added
an `execute` method to each request type. This greatly
simplifies the client code. However this requires
refactoring of applications using the direct PLC4X API.

Miscellaneous changes
---------------------

We have increased the test coverage greatly and fixed
a lot of little errors we found on the way.

Known Issues
------------

Bug Fixes
---------

PLC4X-56	[S7] S7Field does not recognize addresses
            with numElements present
PLC4X-57	[S7] Response for address with numElements
            contains only first item
PLC4X-61	Installation fails plc4j-protocoll-ethernetip
            needs license
PLC4X-62	Modbus results deliver null-Value due to missing
            implementation of getShort, getLong ...



==============================================================
Apache PLC4X (incubating) 0.1.0
==============================================================

This is the first official release of Apache PLC4X.
It contains drivers for the following protocols:
- Siemens S7comm (0x32)
- Beckhoff ADS
- Modbus
- EtherNet/IP

However the Siemens driver definitely is the most
mature driver, the rest should be treated experimental.

New Features
------------

PLC4X-29	[S7] Implement PDU Fragmentation
PLC4X-39	Extend the Edgent integration with the new Subscription features of PLC4X

Incompatible changes
--------------------

- NONE -

Miscellaneous changes
---------------------

- NONE -

Known Issues
------------

- NONE -

Most drivers should be treated experimental and are not near production ready.
The S7 driver is probably the furthest implemented and tested driver and hereby can be
considered to be the most mature.

Bug Fixes
---------

PLC4X-20	Jacoco doesn't seem to be working at all
PLC4X-21	Code coverage doesn't seem to work
PLC4X-47	S7 driver silently ignores surplus ReadRequestItems
PLC4X-48	S7 driver fails to parse response with multiple items
