You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@plc4x.apache.org by sr...@apache.org on 2022/11/14 10:51:58 UTC

[plc4x] branch develop updated: feat(plc4go/bacnet): added building structure to BIPSimpleApplication

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

sruehl pushed a commit to branch develop
in repository https://gitbox.apache.org/repos/asf/plc4x.git


The following commit(s) were added to refs/heads/develop by this push:
     new e43a48f12e feat(plc4go/bacnet): added building structure to BIPSimpleApplication
e43a48f12e is described below

commit e43a48f12eb40b911522feffbc6547c9fb4a27c2
Author: Sebastian Rühl <sr...@apache.org>
AuthorDate: Mon Nov 14 11:17:40 2022 +0100

    feat(plc4go/bacnet): added building structure to BIPSimpleApplication
---
 plc4go/internal/bacnetip/ApplicationModule.go      |  56 ++++++--
 .../bacnetip/BACnetVirtualLinkLayerService.go      | 142 +++++++++++++++++++++
 plc4go/internal/bacnetip/NetworkService.go         |   4 +
 3 files changed, 189 insertions(+), 13 deletions(-)

diff --git a/plc4go/internal/bacnetip/ApplicationModule.go b/plc4go/internal/bacnetip/ApplicationModule.go
index 0371c83bbe..17aba59782 100644
--- a/plc4go/internal/bacnetip/ApplicationModule.go
+++ b/plc4go/internal/bacnetip/ApplicationModule.go
@@ -19,7 +19,10 @@
 
 package bacnetip
 
-import "github.com/pkg/errors"
+import (
+	"github.com/pkg/errors"
+	"github.com/rs/zerolog/log"
+)
 
 // TODO: implement
 type Application struct {
@@ -50,48 +53,47 @@ type BIPSimpleApplication struct {
 	smap         *StateMachineAccessPoint
 	nsap         *NetworkServiceAccessPoint
 	nse          *NetworkServiceElement
+	bip          *BIPSimple
+	annexj       *AnnexJCodec
+	mux          *UDPMultiplexer
 }
 
 func NewBIPSimpleApplication(localDevice DeviceEntry, localAddress, deviceInfoCache *DeviceInventory, aseID *int) (*BIPSimpleApplication, error) {
 	b := &BIPSimpleApplication{}
-	controller, err := NewApplicationIOController(localDevice, localAddress, deviceInfoCache, aseID)
+	var err error
+	b.ApplicationIOController, err = NewApplicationIOController(localDevice, localAddress, deviceInfoCache, aseID)
 	if err != nil {
 		return nil, errors.Wrap(err, "error creating io controller")
 	}
-	b.ApplicationIOController = controller
 
 	b.localAddress = localAddress
 
 	// include a application decoder
-	applicationServiceAccessPoint, err := NewApplicationServiceAccessPoint(nil, nil)
+	b.asap, err = NewApplicationServiceAccessPoint(nil, nil)
 	if err != nil {
 		return nil, errors.Wrap(err, "error creating application service access point")
 	}
-	b.asap = applicationServiceAccessPoint
 
 	// pass the device object to the state machine access point, so it can know if it should support segmentation
-	stateMachineAccessPoint, err := NewStateMachineAccessPoint(localDevice, deviceInfoCache, nil, nil)
+	b.smap, err = NewStateMachineAccessPoint(localDevice, deviceInfoCache, nil, nil)
 	if err != nil {
 		return nil, errors.Wrap(err, "error creating state machine access point")
 	}
-	b.smap = stateMachineAccessPoint
 
 	// pass the device object to the state machine access point so it # can know if it should support segmentation
-	// Note: deviceInfoCache already passed above so we don't need to do it again here
+	// Note: deviceInfoCache already passed above, so we don't need to do it again here
 
 	// a network service access point will be needed
-	networkServiceAccessPoint, err := NewNetworkServiceAccessPoint()
+	b.nsap, err = NewNetworkServiceAccessPoint()
 	if err != nil {
 		return nil, errors.Wrap(err, "error creating network service access point")
 	}
-	b.nsap = networkServiceAccessPoint
 
 	// give the NSAP a generic network layer service element
-	networkServiceElement, err := NewNetworkServiceElement()
+	b.nse, err = NewNetworkServiceElement()
 	if err != nil {
 		return nil, errors.Wrap(err, "error creating new network service element")
 	}
-	b.nse = networkServiceElement
 	if err := bind(b.nse, b.nsap); err != nil {
 		return nil, errors.New("error binding network stack")
 	}
@@ -101,7 +103,35 @@ func NewBIPSimpleApplication(localDevice DeviceEntry, localAddress, deviceInfoCa
 		return nil, errors.New("error binding top layers")
 	}
 
-	// TODO: BIP, etc... udp stack binding here
+	// create a generic BIP stack, bound to the Annex J server on the UDP multiplexer
+	b.bip, err = NewBIPSimple(nil, nil, nil)
+	if err != nil {
+		return nil, errors.Wrap(err, "error creating new bip")
+	}
+	b.annexj, err = NewAnnexJCodec(nil, nil)
+	if err != nil {
+		return nil, errors.Wrap(err, "error creating new annex j codec")
+	}
+	b.mux, err = NewUDPMultiplexer(b.localAddress, false)
+	if err != nil {
+		return nil, errors.Wrap(err, "error creating new udp multiplexer")
+	}
+
+	// bind the bottom layers
+	if err := bind(b.bip, b.annexj, b.mux.annexJ); err != nil {
+		return nil, errors.New("error binding bottom layers")
+	}
+
+	// bind the BIP stack to the network, no network number
+	if err := b.nsap.bind(b.bip, nil, b.localAddress); err != nil {
+		return nil, err
+	}
 
 	return b, nil
 }
+
+func (b *BIPSimpleApplication) Close() error {
+	log.Debug().Msg("close socket")
+	// pass to the multiplexer, then down to the sockets
+	return b.mux.Close()
+}
diff --git a/plc4go/internal/bacnetip/BACnetVirtualLinkLayerService.go b/plc4go/internal/bacnetip/BACnetVirtualLinkLayerService.go
new file mode 100644
index 0000000000..959ab1b074
--- /dev/null
+++ b/plc4go/internal/bacnetip/BACnetVirtualLinkLayerService.go
@@ -0,0 +1,142 @@
+/*
+ * 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.
+ */
+
+package bacnetip
+
+import (
+	readWriteModel "github.com/apache/plc4x/plc4go/protocols/bacnetip/readwrite/model"
+	"github.com/pkg/errors"
+	"github.com/rs/zerolog/log"
+)
+
+type UDPMultiplexer struct {
+	annexJ interface{}
+}
+
+func (m *UDPMultiplexer) Close() error {
+	panic("implement me")
+}
+
+func NewUDPMultiplexer(address interface{}, noBroadcast bool) (*UDPMultiplexer, error) {
+	log.Debug().Msgf("NewUDPMultiplexer %v noBroadcast=%t", address, noBroadcast)
+	u := &UDPMultiplexer{}
+
+	// TODO: plumb later
+	return u, nil
+}
+
+type AnnexJCodec struct {
+	*Client
+	*Server
+}
+
+func NewAnnexJCodec(cid *int, sid *int) (*AnnexJCodec, error) {
+	log.Debug().Msgf("NewAnnexJCodec cid=%d sid=%d", cid, sid)
+	a := &AnnexJCodec{}
+	client, err := NewClient(cid, a)
+	if err != nil {
+		return nil, errors.Wrap(err, "error creating client")
+	}
+	a.Client = client
+	server, err := NewServer(sid, a)
+	if err != nil {
+		return nil, errors.Wrap(err, "error creating server")
+	}
+	a.Server = server
+	return a, nil
+}
+
+func (b *AnnexJCodec) Indication(apdu readWriteModel.APDU) error {
+	panic("we need to implement this with  generics as we handle npdu not apdu here")
+}
+
+func (b *AnnexJCodec) Confirmation(apdu readWriteModel.APDU) error {
+	panic("we need to implement this with  generics as we handle npdu not apdu here")
+}
+
+type _BIPSAP interface {
+	_ServiceAccessPoint
+	_Client
+}
+
+type BIPSAP struct {
+	*ServiceAccessPoint
+	rootStruct _BIPSAP
+}
+
+func NewBIPSAP(sapID *int, rootStruct _BIPSAP) (*BIPSAP, error) {
+	log.Debug().Msgf("NewBIPSAP sapID=%d", sapID)
+	b := &BIPSAP{}
+	serviceAccessPoint, err := NewServiceAccessPoint(sapID, rootStruct)
+	if err != nil {
+		return nil, errors.Wrap(err, "Error creating service access point")
+	}
+	b.ServiceAccessPoint = serviceAccessPoint
+	b.rootStruct = rootStruct
+	return b, nil
+}
+
+func (b *BIPSAP) SapIndication(apdu readWriteModel.APDU, pduDestination []byte) error {
+	log.Debug().Msgf("SapIndication\n%s\n%s", apdu, pduDestination)
+	// TODO: what to do with the destination?
+	// this is a request initiated by the ASE, send this downstream
+	return b.rootStruct.Request(apdu)
+}
+
+func (b *BIPSAP) SapConfirmation(apdu readWriteModel.APDU, pduDestination []byte) error {
+	log.Debug().Msgf("SapConfirmation\n%s\n%s", apdu, pduDestination)
+	// TODO: what to do with the destination?
+	// this is a response from the ASE, send this downstream
+	return b.rootStruct.Request(apdu)
+}
+
+type BIPSimple struct {
+	*BIPSAP
+	*Client
+	*Server
+}
+
+func NewBIPSimple(sapID *int, cid *int, sid *int) (*BIPSimple, error) {
+	log.Debug().Msgf("NewBIPSimple sapID=%d cid=%d sid=%d", sapID, cid, sid)
+	b := &BIPSimple{}
+	bipsap, err := NewBIPSAP(sapID, b)
+	if err != nil {
+		return nil, errors.Wrap(err, "error creating bisap")
+	}
+	b.BIPSAP = bipsap
+	client, err := NewClient(cid, b)
+	if err != nil {
+		return nil, errors.Wrap(err, "error creating client")
+	}
+	b.Client = client
+	server, err := NewServer(sid, b)
+	if err != nil {
+		return nil, errors.Wrap(err, "error creating server")
+	}
+	b.Server = server
+	return b, nil
+}
+
+func (b *BIPSimple) Indication(apdu readWriteModel.APDU) error {
+	panic("we need to implement this with  generics as we handle npdu not apdu here")
+}
+
+func (b *BIPSimple) Response(apdu readWriteModel.APDU) error {
+	panic("we need to implement this with  generics as we handle npdu not apdu here")
+}
diff --git a/plc4go/internal/bacnetip/NetworkService.go b/plc4go/internal/bacnetip/NetworkService.go
index b9c9b120a0..a92045d037 100644
--- a/plc4go/internal/bacnetip/NetworkService.go
+++ b/plc4go/internal/bacnetip/NetworkService.go
@@ -28,6 +28,10 @@ func NewNetworkServiceAccessPoint() (*NetworkServiceAccessPoint, error) {
 	return nil, nil
 }
 
+func (n *NetworkServiceAccessPoint) bind(server _Server, net interface{}, address interface{}) error {
+	panic("not implemented yet")
+}
+
 type NetworkServiceElement struct {
 	// TODO: implement me
 }