You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@plc4x.apache.org by cd...@apache.org on 2023/06/07 07:32:52 UTC

[plc4x] 01/02: docs(plc4go/bacnet): Added some comments

This is an automated email from the ASF dual-hosted git repository.

cdutz pushed a commit to branch chore/profinet-phase-3
in repository https://gitbox.apache.org/repos/asf/plc4x.git

commit 7628e1f4d8ec2f746f02734728bde784ce6e1832
Author: Christofer Dutz <cd...@apache.org>
AuthorDate: Wed Jun 7 09:10:26 2023 +0200

    docs(plc4go/bacnet): Added some comments
---
 plc4go/internal/bacnetip/Driver.go             |   2 +
 src/site/asciidoc/developers/architecture.adoc | 162 +++++++++++++++++++++++++
 2 files changed, 164 insertions(+)

diff --git a/plc4go/internal/bacnetip/Driver.go b/plc4go/internal/bacnetip/Driver.go
index d5d2a57f2f..a14b40324b 100644
--- a/plc4go/internal/bacnetip/Driver.go
+++ b/plc4go/internal/bacnetip/Driver.go
@@ -123,6 +123,7 @@ type ApplicationManager struct {
 func (a *ApplicationManager) getApplicationLayerMessageCodec(transport *udp.Transport, transportUrl url.URL, options map[string][]string) (*ApplicationLayerMessageCodec, error) {
 	var localAddress *net.UDPAddr
 	var remoteAddr *net.UDPAddr
+	// Find out the remote and the local ip address by opening an UPD port (which is instantly closed)
 	{
 		host := transportUrl.Host
 		port := transportUrl.Port()
@@ -134,6 +135,7 @@ func (a *ApplicationManager) getApplicationLayerMessageCodec(transport *udp.Tran
 		} else {
 			remoteAddr = resolvedRemoteAddr
 		}
+		// TODO: Possibly do with with ip-address matching similar to the raw-socket impl in Java.
 		if dial, err := net.DialUDP("udp", nil, remoteAddr); err != nil {
 			return nil, errors.Errorf("couldn't dial to host %#v", transportUrl.Host)
 		} else {
diff --git a/src/site/asciidoc/developers/architecture.adoc b/src/site/asciidoc/developers/architecture.adoc
new file mode 100644
index 0000000000..0e95ebf201
--- /dev/null
+++ b/src/site/asciidoc/developers/architecture.adoc
@@ -0,0 +1,162 @@
+//
+//  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.
+//
+
+== Architecture of PLC4X Connections
+
+=== Simple case
+
+In this simple case, an application asks the DriverManager to forward a connection creation to the corresponding Driver implementation, which then creates both a Connection and a MessageCodec instance. The Connection is the logical link between the connection state and the MessageCodec.
+A MessageCodec uses a TransportInstance to communicate with the target device.
+
+[plantuml, target=no-restrictions-simple, format=png]
+....
+
+package Connection1 {
+Plc4xConnection1 : s7:tcp://192.168.23.30
+TcpPort1 : local-ip          192.168.23.200
+TcpPort1 : local-port      48479
+TcpPort1 : remote-ip     192.168.23.30
+TcpPort1 : remote-port 102
+}
+
+package Connection2 {
+Plc4xConnection2 : s7:tcp://192.168.23.30
+TcpPort2 : local-ip          192.168.23.200
+TcpPort2 : local-port      34555
+TcpPort2 : remote-ip     192.168.23.30
+TcpPort2 : remote-port 102
+}
+
+S7Device : local-ip     192.168.23.30
+S7Device : local-port 102
+
+Plc4xConnection1 -> TcpPort1
+Plc4xConnection2 -> TcpPort2
+TcpPort1 -> S7Device : tcp
+TcpPort2 -> S7Device : tcp
+
+....
+
+[plantuml, target=no-restrictions, format=png]
+....
+
+package "Application" {
+  [APP]
+}
+
+package "PLC4X" {
+    [Connection]
+    [ReaderWriter]
+    [MessageCodec]
+    [Transport]
+    [TransportInstance]
+    [Driver]
+}
+
+package "PLC" {
+    [Device]
+}
+
+APP -> Connection : n:1
+Connection - MessageCodec : 1:1
+Connection -- Driver : n:1
+Connection -- ReaderWriter : 1:1
+MessageCodec -- TransportInstance : 1:1
+Transport - TransportInstance : 1:1
+MessageCodec - Driver : n:1
+TransportInstance -> Device : 1:1
+
+note top of [Connection] : logical
+
+....
+
+=== Problems
+
+Serial transports based on RS475 and UDP Transports currently don't allow sharing. That means only one connection instance can have access to one RS485 or one shared local UDP Port (Multiple UDP transport instances with different local ports however are possible). As soon as one connection is established and a second connection would try to access this, this would result in errors.
+
+However, multiple devices could be attached to the same RS458 port (Modbus RTU and Modbus ASCII explicitly supports this, however using different devices using different protocols over the same port is not possible) and in BACnet connecting to multiple remote BACnet devices would require one local UDP port to be used by multiple connections.
+
+=== Protocols requiring us to use a fixed port on a non-broadcast address
+
+Some protocols, such as BACnet require remotes to send data to a fixed udp port on a non-broadcast address. This causes problems as soon as we want to connect to multiple BACnet devices from the same host as only one instance can get access to that port.
+
+[plantuml, target=shared-local-port-simple, format=png]
+....
+
+package Connection1 {
+Plc4xConnection1 : bacnet:udp://192.168.23.30
+UdpPort1 : local-ip          192.168.23.200
+UdpPort1 : local-port      47808
+UdpPort1 : remote-ip     192.168.23.30
+UdpPort1 : remote-port 47808
+}
+
+package Connection2 #red {
+Plc4xConnection2 : bacnet:udp://192.168.23.20
+UdpPort2 : local-ip          192.168.23.200
+UdpPort2 : local-port      47808
+UdpPort2 : remote-ip     192.168.23.20
+UdpPort2 : remote-port 47808
+}
+note right of UdpPort2: This local port is already owned by Connection1
+
+BACnetDevice : local-ip     192.168.23.30
+BACnetDevice : local-port 102
+
+Plc4xConnection1 -> UdpPort1
+Plc4xConnection2 -> UdpPort2
+UdpPort1 -> BACnetDevice : udp
+UdpPort2 -> BACnetDevice : udp
+
+....
+
+[plantuml, target=shared-local-port, format=png]
+....
+
+package "Application" {
+  [APP]
+}
+
+package "PLC4X" {
+    [Connection]
+    [ReaderWriter]
+    [MessageCodec]
+    [Transport]
+    [TransportInstance]
+    [Driver]
+}
+
+package "PLC" {
+    [Device]
+}
+
+APP -> Connection : n:1
+Connection - MessageCodec : n:1
+Connection -- Driver : n:1
+Connection -- ReaderWriter : 1:1
+MessageCodec -- TransportInstance : 1:1
+Transport - TransportInstance : 1:1
+MessageCodec - Driver : n:1
+TransportInstance -> Device : 1:n
+
+note top of [Connection] : logical
+
+....
+
+=== Protocols only allowing one connection at a time
+
+