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/05/31 13:02:50 UTC
[plc4x] 01/01: chore(plc4j/profinet): Tried adjusting the code to provide more help in error messages and started working on handling the "ping" messages.
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 95a8648d03ab1bd0ec041f63ff424cbd42c7c1ff
Author: Christofer Dutz <cd...@apache.org>
AuthorDate: Wed May 31 15:02:37 2023 +0200
chore(plc4j/profinet): Tried adjusting the code to provide more help in error messages and started working on handling the "ping" messages.
---
.../protocols/eip/readwrite/model/CipIdentity.go | 636 +++++++++++++++++++++
.../eip/readwrite/model/CipSecurityInformation.go | 250 ++++++++
.../eip/readwrite/model/CommandSpecificDataItem.go | 196 +++++++
.../eip/readwrite/model/EipListIdentityRequest.go | 180 ++++++
.../eip/readwrite/model/EipListIdentityResponse.go | 270 +++++++++
.../java/profinet/readwrite/DceRpc_Packet.java | 26 +-
.../java/profinet/readwrite/PnIoCm_Packet.java | 2 +
.../profinet/readwrite/PnIoCm_Packet_Working.java | 122 ++++
.../java/profinet/device/ProfinetChannel.java | 31 +-
.../plc4x/java/profinet/device/ProfinetDevice.java | 5 +
.../profinet/discovery/ProfinetPlcDiscoverer.java | 1 +
.../profinet/protocol/ProfinetProtocolLogic.java | 11 +-
.../plc4x/java/profinet/ManualProfinetIoTest.java | 8 +-
.../plc4x/java/profinet/ProfinetCheckSumTests.java | 1 +
.../main/resources/protocols/profinet/dcerpc.mspec | 3 +-
.../main/resources/protocols/profinet/pnio.mspec | 2 +
16 files changed, 1723 insertions(+), 21 deletions(-)
diff --git a/plc4go/protocols/eip/readwrite/model/CipIdentity.go b/plc4go/protocols/eip/readwrite/model/CipIdentity.go
new file mode 100644
index 0000000000..29a2bc90ce
--- /dev/null
+++ b/plc4go/protocols/eip/readwrite/model/CipIdentity.go
@@ -0,0 +1,636 @@
+/*
+ * 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 model
+
+import (
+ "context"
+ "fmt"
+ "github.com/apache/plc4x/plc4go/spi/utils"
+ "github.com/pkg/errors"
+)
+
+// Code generated by code-generation. DO NOT EDIT.
+
+// Constant values.
+const CipIdentity_ZEROES1 uint32 = 0x00000000
+const CipIdentity_ZEROES2 uint32 = 0x00000000
+
+// CipIdentity is the corresponding interface of CipIdentity
+type CipIdentity interface {
+ fmt.Stringer
+ utils.LengthAware
+ utils.Serializable
+ CommandSpecificDataItem
+ // GetEncapsulationProtocolVersion returns EncapsulationProtocolVersion (property field)
+ GetEncapsulationProtocolVersion() uint16
+ // GetSocketAddressFamily returns SocketAddressFamily (property field)
+ GetSocketAddressFamily() uint16
+ // GetSocketAddressPort returns SocketAddressPort (property field)
+ GetSocketAddressPort() uint16
+ // GetSocketAddressAddress returns SocketAddressAddress (property field)
+ GetSocketAddressAddress() []uint8
+ // GetVendorId returns VendorId (property field)
+ GetVendorId() uint16
+ // GetDeviceType returns DeviceType (property field)
+ GetDeviceType() uint16
+ // GetProductCode returns ProductCode (property field)
+ GetProductCode() uint16
+ // GetRevisionMajor returns RevisionMajor (property field)
+ GetRevisionMajor() uint8
+ // GetRevisionMinor returns RevisionMinor (property field)
+ GetRevisionMinor() uint8
+ // GetStatus returns Status (property field)
+ GetStatus() uint16
+ // GetSerialNumber returns SerialNumber (property field)
+ GetSerialNumber() uint32
+ // GetProductName returns ProductName (property field)
+ GetProductName() string
+ // GetState returns State (property field)
+ GetState() uint8
+}
+
+// CipIdentityExactly can be used when we want exactly this type and not a type which fulfills CipIdentity.
+// This is useful for switch cases.
+type CipIdentityExactly interface {
+ CipIdentity
+ isCipIdentity() bool
+}
+
+// _CipIdentity is the data-structure of this message
+type _CipIdentity struct {
+ *_CommandSpecificDataItem
+ EncapsulationProtocolVersion uint16
+ SocketAddressFamily uint16
+ SocketAddressPort uint16
+ SocketAddressAddress []uint8
+ VendorId uint16
+ DeviceType uint16
+ ProductCode uint16
+ RevisionMajor uint8
+ RevisionMinor uint8
+ Status uint16
+ SerialNumber uint32
+ ProductName string
+ State uint8
+}
+
+///////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////
+/////////////////////// Accessors for discriminator values.
+///////////////////////
+
+func (m *_CipIdentity) GetItemType() uint16 {
+ return 0x000C
+}
+
+///////////////////////
+///////////////////////
+///////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////
+
+func (m *_CipIdentity) InitializeParent(parent CommandSpecificDataItem) {}
+
+func (m *_CipIdentity) GetParent() CommandSpecificDataItem {
+ return m._CommandSpecificDataItem
+}
+
+///////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////
+/////////////////////// Accessors for property fields.
+///////////////////////
+
+func (m *_CipIdentity) GetEncapsulationProtocolVersion() uint16 {
+ return m.EncapsulationProtocolVersion
+}
+
+func (m *_CipIdentity) GetSocketAddressFamily() uint16 {
+ return m.SocketAddressFamily
+}
+
+func (m *_CipIdentity) GetSocketAddressPort() uint16 {
+ return m.SocketAddressPort
+}
+
+func (m *_CipIdentity) GetSocketAddressAddress() []uint8 {
+ return m.SocketAddressAddress
+}
+
+func (m *_CipIdentity) GetVendorId() uint16 {
+ return m.VendorId
+}
+
+func (m *_CipIdentity) GetDeviceType() uint16 {
+ return m.DeviceType
+}
+
+func (m *_CipIdentity) GetProductCode() uint16 {
+ return m.ProductCode
+}
+
+func (m *_CipIdentity) GetRevisionMajor() uint8 {
+ return m.RevisionMajor
+}
+
+func (m *_CipIdentity) GetRevisionMinor() uint8 {
+ return m.RevisionMinor
+}
+
+func (m *_CipIdentity) GetStatus() uint16 {
+ return m.Status
+}
+
+func (m *_CipIdentity) GetSerialNumber() uint32 {
+ return m.SerialNumber
+}
+
+func (m *_CipIdentity) GetProductName() string {
+ return m.ProductName
+}
+
+func (m *_CipIdentity) GetState() uint8 {
+ return m.State
+}
+
+///////////////////////
+///////////////////////
+///////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////
+/////////////////////// Accessors for const fields.
+///////////////////////
+
+func (m *_CipIdentity) GetZeroes1() uint32 {
+ return CipIdentity_ZEROES1
+}
+
+func (m *_CipIdentity) GetZeroes2() uint32 {
+ return CipIdentity_ZEROES2
+}
+
+///////////////////////
+///////////////////////
+///////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////
+
+// NewCipIdentity factory function for _CipIdentity
+func NewCipIdentity(encapsulationProtocolVersion uint16, socketAddressFamily uint16, socketAddressPort uint16, socketAddressAddress []uint8, vendorId uint16, deviceType uint16, productCode uint16, revisionMajor uint8, revisionMinor uint8, status uint16, serialNumber uint32, productName string, state uint8) *_CipIdentity {
+ _result := &_CipIdentity{
+ EncapsulationProtocolVersion: encapsulationProtocolVersion,
+ SocketAddressFamily: socketAddressFamily,
+ SocketAddressPort: socketAddressPort,
+ SocketAddressAddress: socketAddressAddress,
+ VendorId: vendorId,
+ DeviceType: deviceType,
+ ProductCode: productCode,
+ RevisionMajor: revisionMajor,
+ RevisionMinor: revisionMinor,
+ Status: status,
+ SerialNumber: serialNumber,
+ ProductName: productName,
+ State: state,
+ _CommandSpecificDataItem: NewCommandSpecificDataItem(),
+ }
+ _result._CommandSpecificDataItem._CommandSpecificDataItemChildRequirements = _result
+ return _result
+}
+
+// Deprecated: use the interface for direct cast
+func CastCipIdentity(structType any) CipIdentity {
+ if casted, ok := structType.(CipIdentity); ok {
+ return casted
+ }
+ if casted, ok := structType.(*CipIdentity); ok {
+ return *casted
+ }
+ return nil
+}
+
+func (m *_CipIdentity) GetTypeName() string {
+ return "CipIdentity"
+}
+
+func (m *_CipIdentity) GetLengthInBits(ctx context.Context) uint16 {
+ lengthInBits := uint16(m.GetParentLengthInBits(ctx))
+
+ // Implicit Field (itemLength)
+ lengthInBits += 16
+
+ // Simple field (encapsulationProtocolVersion)
+ lengthInBits += 16
+
+ // Simple field (socketAddressFamily)
+ lengthInBits += 16
+
+ // Simple field (socketAddressPort)
+ lengthInBits += 16
+
+ // Array field
+ if len(m.SocketAddressAddress) > 0 {
+ lengthInBits += 8 * uint16(len(m.SocketAddressAddress))
+ }
+
+ // Const Field (zeroes1)
+ lengthInBits += 32
+
+ // Const Field (zeroes2)
+ lengthInBits += 32
+
+ // Simple field (vendorId)
+ lengthInBits += 16
+
+ // Simple field (deviceType)
+ lengthInBits += 16
+
+ // Simple field (productCode)
+ lengthInBits += 16
+
+ // Simple field (revisionMajor)
+ lengthInBits += 8
+
+ // Simple field (revisionMinor)
+ lengthInBits += 8
+
+ // Simple field (status)
+ lengthInBits += 16
+
+ // Simple field (serialNumber)
+ lengthInBits += 32
+
+ // Implicit Field (productNameLength)
+ lengthInBits += 8
+
+ // Simple field (productName)
+ lengthInBits += uint16(int32(uint8(len(m.GetProductName()))) * int32(int32(8)))
+
+ // Simple field (state)
+ lengthInBits += 8
+
+ return lengthInBits
+}
+
+func (m *_CipIdentity) GetLengthInBytes(ctx context.Context) uint16 {
+ return m.GetLengthInBits(ctx) / 8
+}
+
+func CipIdentityParse(theBytes []byte) (CipIdentity, error) {
+ return CipIdentityParseWithBuffer(context.Background(), utils.NewReadBufferByteBased(theBytes))
+}
+
+func CipIdentityParseWithBuffer(ctx context.Context, readBuffer utils.ReadBuffer) (CipIdentity, error) {
+ positionAware := readBuffer
+ _ = positionAware
+ if pullErr := readBuffer.PullContext("CipIdentity"); pullErr != nil {
+ return nil, errors.Wrap(pullErr, "Error pulling for CipIdentity")
+ }
+ currentPos := positionAware.GetPos()
+ _ = currentPos
+
+ // Implicit Field (itemLength) (Used for parsing, but its value is not stored as it's implicitly given by the objects content)
+ itemLength, _itemLengthErr := readBuffer.ReadUint16("itemLength", 16)
+ _ = itemLength
+ if _itemLengthErr != nil {
+ return nil, errors.Wrap(_itemLengthErr, "Error parsing 'itemLength' field of CipIdentity")
+ }
+
+ // Simple Field (encapsulationProtocolVersion)
+ _encapsulationProtocolVersion, _encapsulationProtocolVersionErr := readBuffer.ReadUint16("encapsulationProtocolVersion", 16)
+ if _encapsulationProtocolVersionErr != nil {
+ return nil, errors.Wrap(_encapsulationProtocolVersionErr, "Error parsing 'encapsulationProtocolVersion' field of CipIdentity")
+ }
+ encapsulationProtocolVersion := _encapsulationProtocolVersion
+
+ // Simple Field (socketAddressFamily)
+ _socketAddressFamily, _socketAddressFamilyErr := readBuffer.ReadUint16("socketAddressFamily", 16)
+ if _socketAddressFamilyErr != nil {
+ return nil, errors.Wrap(_socketAddressFamilyErr, "Error parsing 'socketAddressFamily' field of CipIdentity")
+ }
+ socketAddressFamily := _socketAddressFamily
+
+ // Simple Field (socketAddressPort)
+ _socketAddressPort, _socketAddressPortErr := readBuffer.ReadUint16("socketAddressPort", 16)
+ if _socketAddressPortErr != nil {
+ return nil, errors.Wrap(_socketAddressPortErr, "Error parsing 'socketAddressPort' field of CipIdentity")
+ }
+ socketAddressPort := _socketAddressPort
+
+ // Array field (socketAddressAddress)
+ if pullErr := readBuffer.PullContext("socketAddressAddress", utils.WithRenderAsList(true)); pullErr != nil {
+ return nil, errors.Wrap(pullErr, "Error pulling for socketAddressAddress")
+ }
+ // Count array
+ socketAddressAddress := make([]uint8, uint16(4))
+ // This happens when the size is set conditional to 0
+ if len(socketAddressAddress) == 0 {
+ socketAddressAddress = nil
+ }
+ {
+ _numItems := uint16(uint16(4))
+ for _curItem := uint16(0); _curItem < _numItems; _curItem++ {
+ arrayCtx := utils.CreateArrayContext(ctx, int(_numItems), int(_curItem))
+ _ = arrayCtx
+ _ = _curItem
+ _item, _err := readBuffer.ReadUint8("", 8)
+ if _err != nil {
+ return nil, errors.Wrap(_err, "Error parsing 'socketAddressAddress' field of CipIdentity")
+ }
+ socketAddressAddress[_curItem] = _item
+ }
+ }
+ if closeErr := readBuffer.CloseContext("socketAddressAddress", utils.WithRenderAsList(true)); closeErr != nil {
+ return nil, errors.Wrap(closeErr, "Error closing for socketAddressAddress")
+ }
+
+ // Const Field (zeroes1)
+ zeroes1, _zeroes1Err := readBuffer.ReadUint32("zeroes1", 32)
+ if _zeroes1Err != nil {
+ return nil, errors.Wrap(_zeroes1Err, "Error parsing 'zeroes1' field of CipIdentity")
+ }
+ if zeroes1 != CipIdentity_ZEROES1 {
+ return nil, errors.New("Expected constant value " + fmt.Sprintf("%d", CipIdentity_ZEROES1) + " but got " + fmt.Sprintf("%d", zeroes1))
+ }
+
+ // Const Field (zeroes2)
+ zeroes2, _zeroes2Err := readBuffer.ReadUint32("zeroes2", 32)
+ if _zeroes2Err != nil {
+ return nil, errors.Wrap(_zeroes2Err, "Error parsing 'zeroes2' field of CipIdentity")
+ }
+ if zeroes2 != CipIdentity_ZEROES2 {
+ return nil, errors.New("Expected constant value " + fmt.Sprintf("%d", CipIdentity_ZEROES2) + " but got " + fmt.Sprintf("%d", zeroes2))
+ }
+
+ // Simple Field (vendorId)
+ _vendorId, _vendorIdErr := readBuffer.ReadUint16("vendorId", 16)
+ if _vendorIdErr != nil {
+ return nil, errors.Wrap(_vendorIdErr, "Error parsing 'vendorId' field of CipIdentity")
+ }
+ vendorId := _vendorId
+
+ // Simple Field (deviceType)
+ _deviceType, _deviceTypeErr := readBuffer.ReadUint16("deviceType", 16)
+ if _deviceTypeErr != nil {
+ return nil, errors.Wrap(_deviceTypeErr, "Error parsing 'deviceType' field of CipIdentity")
+ }
+ deviceType := _deviceType
+
+ // Simple Field (productCode)
+ _productCode, _productCodeErr := readBuffer.ReadUint16("productCode", 16)
+ if _productCodeErr != nil {
+ return nil, errors.Wrap(_productCodeErr, "Error parsing 'productCode' field of CipIdentity")
+ }
+ productCode := _productCode
+
+ // Simple Field (revisionMajor)
+ _revisionMajor, _revisionMajorErr := readBuffer.ReadUint8("revisionMajor", 8)
+ if _revisionMajorErr != nil {
+ return nil, errors.Wrap(_revisionMajorErr, "Error parsing 'revisionMajor' field of CipIdentity")
+ }
+ revisionMajor := _revisionMajor
+
+ // Simple Field (revisionMinor)
+ _revisionMinor, _revisionMinorErr := readBuffer.ReadUint8("revisionMinor", 8)
+ if _revisionMinorErr != nil {
+ return nil, errors.Wrap(_revisionMinorErr, "Error parsing 'revisionMinor' field of CipIdentity")
+ }
+ revisionMinor := _revisionMinor
+
+ // Simple Field (status)
+ _status, _statusErr := readBuffer.ReadUint16("status", 16)
+ if _statusErr != nil {
+ return nil, errors.Wrap(_statusErr, "Error parsing 'status' field of CipIdentity")
+ }
+ status := _status
+
+ // Simple Field (serialNumber)
+ _serialNumber, _serialNumberErr := readBuffer.ReadUint32("serialNumber", 32)
+ if _serialNumberErr != nil {
+ return nil, errors.Wrap(_serialNumberErr, "Error parsing 'serialNumber' field of CipIdentity")
+ }
+ serialNumber := _serialNumber
+
+ // Implicit Field (productNameLength) (Used for parsing, but its value is not stored as it's implicitly given by the objects content)
+ productNameLength, _productNameLengthErr := readBuffer.ReadUint8("productNameLength", 8)
+ _ = productNameLength
+ if _productNameLengthErr != nil {
+ return nil, errors.Wrap(_productNameLengthErr, "Error parsing 'productNameLength' field of CipIdentity")
+ }
+
+ // Simple Field (productName)
+ _productName, _productNameErr := readBuffer.ReadString("productName", uint32((productNameLength)*(8)), "UTF-8")
+ if _productNameErr != nil {
+ return nil, errors.Wrap(_productNameErr, "Error parsing 'productName' field of CipIdentity")
+ }
+ productName := _productName
+
+ // Simple Field (state)
+ _state, _stateErr := readBuffer.ReadUint8("state", 8)
+ if _stateErr != nil {
+ return nil, errors.Wrap(_stateErr, "Error parsing 'state' field of CipIdentity")
+ }
+ state := _state
+
+ if closeErr := readBuffer.CloseContext("CipIdentity"); closeErr != nil {
+ return nil, errors.Wrap(closeErr, "Error closing for CipIdentity")
+ }
+
+ // Create a partially initialized instance
+ _child := &_CipIdentity{
+ _CommandSpecificDataItem: &_CommandSpecificDataItem{},
+ EncapsulationProtocolVersion: encapsulationProtocolVersion,
+ SocketAddressFamily: socketAddressFamily,
+ SocketAddressPort: socketAddressPort,
+ SocketAddressAddress: socketAddressAddress,
+ VendorId: vendorId,
+ DeviceType: deviceType,
+ ProductCode: productCode,
+ RevisionMajor: revisionMajor,
+ RevisionMinor: revisionMinor,
+ Status: status,
+ SerialNumber: serialNumber,
+ ProductName: productName,
+ State: state,
+ }
+ _child._CommandSpecificDataItem._CommandSpecificDataItemChildRequirements = _child
+ return _child, nil
+}
+
+func (m *_CipIdentity) Serialize() ([]byte, error) {
+ wb := utils.NewWriteBufferByteBased(utils.WithInitialSizeForByteBasedBuffer(int(m.GetLengthInBytes(context.Background()))))
+ if err := m.SerializeWithWriteBuffer(context.Background(), wb); err != nil {
+ return nil, err
+ }
+ return wb.GetBytes(), nil
+}
+
+func (m *_CipIdentity) SerializeWithWriteBuffer(ctx context.Context, writeBuffer utils.WriteBuffer) error {
+ positionAware := writeBuffer
+ _ = positionAware
+ ser := func() error {
+ if pushErr := writeBuffer.PushContext("CipIdentity"); pushErr != nil {
+ return errors.Wrap(pushErr, "Error pushing for CipIdentity")
+ }
+
+ // Implicit Field (itemLength) (Used for parsing, but it's value is not stored as it's implicitly given by the objects content)
+ itemLength := uint16(uint16(uint16(34)) + uint16(uint8(len(m.GetProductName()))))
+ _itemLengthErr := writeBuffer.WriteUint16("itemLength", 16, (itemLength))
+ if _itemLengthErr != nil {
+ return errors.Wrap(_itemLengthErr, "Error serializing 'itemLength' field")
+ }
+
+ // Simple Field (encapsulationProtocolVersion)
+ encapsulationProtocolVersion := uint16(m.GetEncapsulationProtocolVersion())
+ _encapsulationProtocolVersionErr := writeBuffer.WriteUint16("encapsulationProtocolVersion", 16, (encapsulationProtocolVersion))
+ if _encapsulationProtocolVersionErr != nil {
+ return errors.Wrap(_encapsulationProtocolVersionErr, "Error serializing 'encapsulationProtocolVersion' field")
+ }
+
+ // Simple Field (socketAddressFamily)
+ socketAddressFamily := uint16(m.GetSocketAddressFamily())
+ _socketAddressFamilyErr := writeBuffer.WriteUint16("socketAddressFamily", 16, (socketAddressFamily))
+ if _socketAddressFamilyErr != nil {
+ return errors.Wrap(_socketAddressFamilyErr, "Error serializing 'socketAddressFamily' field")
+ }
+
+ // Simple Field (socketAddressPort)
+ socketAddressPort := uint16(m.GetSocketAddressPort())
+ _socketAddressPortErr := writeBuffer.WriteUint16("socketAddressPort", 16, (socketAddressPort))
+ if _socketAddressPortErr != nil {
+ return errors.Wrap(_socketAddressPortErr, "Error serializing 'socketAddressPort' field")
+ }
+
+ // Array Field (socketAddressAddress)
+ if pushErr := writeBuffer.PushContext("socketAddressAddress", utils.WithRenderAsList(true)); pushErr != nil {
+ return errors.Wrap(pushErr, "Error pushing for socketAddressAddress")
+ }
+ for _curItem, _element := range m.GetSocketAddressAddress() {
+ _ = _curItem
+ _elementErr := writeBuffer.WriteUint8("", 8, _element)
+ if _elementErr != nil {
+ return errors.Wrap(_elementErr, "Error serializing 'socketAddressAddress' field")
+ }
+ }
+ if popErr := writeBuffer.PopContext("socketAddressAddress", utils.WithRenderAsList(true)); popErr != nil {
+ return errors.Wrap(popErr, "Error popping for socketAddressAddress")
+ }
+
+ // Const Field (zeroes1)
+ _zeroes1Err := writeBuffer.WriteUint32("zeroes1", 32, 0x00000000)
+ if _zeroes1Err != nil {
+ return errors.Wrap(_zeroes1Err, "Error serializing 'zeroes1' field")
+ }
+
+ // Const Field (zeroes2)
+ _zeroes2Err := writeBuffer.WriteUint32("zeroes2", 32, 0x00000000)
+ if _zeroes2Err != nil {
+ return errors.Wrap(_zeroes2Err, "Error serializing 'zeroes2' field")
+ }
+
+ // Simple Field (vendorId)
+ vendorId := uint16(m.GetVendorId())
+ _vendorIdErr := writeBuffer.WriteUint16("vendorId", 16, (vendorId))
+ if _vendorIdErr != nil {
+ return errors.Wrap(_vendorIdErr, "Error serializing 'vendorId' field")
+ }
+
+ // Simple Field (deviceType)
+ deviceType := uint16(m.GetDeviceType())
+ _deviceTypeErr := writeBuffer.WriteUint16("deviceType", 16, (deviceType))
+ if _deviceTypeErr != nil {
+ return errors.Wrap(_deviceTypeErr, "Error serializing 'deviceType' field")
+ }
+
+ // Simple Field (productCode)
+ productCode := uint16(m.GetProductCode())
+ _productCodeErr := writeBuffer.WriteUint16("productCode", 16, (productCode))
+ if _productCodeErr != nil {
+ return errors.Wrap(_productCodeErr, "Error serializing 'productCode' field")
+ }
+
+ // Simple Field (revisionMajor)
+ revisionMajor := uint8(m.GetRevisionMajor())
+ _revisionMajorErr := writeBuffer.WriteUint8("revisionMajor", 8, (revisionMajor))
+ if _revisionMajorErr != nil {
+ return errors.Wrap(_revisionMajorErr, "Error serializing 'revisionMajor' field")
+ }
+
+ // Simple Field (revisionMinor)
+ revisionMinor := uint8(m.GetRevisionMinor())
+ _revisionMinorErr := writeBuffer.WriteUint8("revisionMinor", 8, (revisionMinor))
+ if _revisionMinorErr != nil {
+ return errors.Wrap(_revisionMinorErr, "Error serializing 'revisionMinor' field")
+ }
+
+ // Simple Field (status)
+ status := uint16(m.GetStatus())
+ _statusErr := writeBuffer.WriteUint16("status", 16, (status))
+ if _statusErr != nil {
+ return errors.Wrap(_statusErr, "Error serializing 'status' field")
+ }
+
+ // Simple Field (serialNumber)
+ serialNumber := uint32(m.GetSerialNumber())
+ _serialNumberErr := writeBuffer.WriteUint32("serialNumber", 32, (serialNumber))
+ if _serialNumberErr != nil {
+ return errors.Wrap(_serialNumberErr, "Error serializing 'serialNumber' field")
+ }
+
+ // Implicit Field (productNameLength) (Used for parsing, but it's value is not stored as it's implicitly given by the objects content)
+ productNameLength := uint8(uint8(len(m.GetProductName())))
+ _productNameLengthErr := writeBuffer.WriteUint8("productNameLength", 8, (productNameLength))
+ if _productNameLengthErr != nil {
+ return errors.Wrap(_productNameLengthErr, "Error serializing 'productNameLength' field")
+ }
+
+ // Simple Field (productName)
+ productName := string(m.GetProductName())
+ _productNameErr := writeBuffer.WriteString("productName", uint32((uint8(len(m.GetProductName())))*(8)), "UTF-8", (productName))
+ if _productNameErr != nil {
+ return errors.Wrap(_productNameErr, "Error serializing 'productName' field")
+ }
+
+ // Simple Field (state)
+ state := uint8(m.GetState())
+ _stateErr := writeBuffer.WriteUint8("state", 8, (state))
+ if _stateErr != nil {
+ return errors.Wrap(_stateErr, "Error serializing 'state' field")
+ }
+
+ if popErr := writeBuffer.PopContext("CipIdentity"); popErr != nil {
+ return errors.Wrap(popErr, "Error popping for CipIdentity")
+ }
+ return nil
+ }
+ return m.SerializeParent(ctx, writeBuffer, m, ser)
+}
+
+func (m *_CipIdentity) isCipIdentity() bool {
+ return true
+}
+
+func (m *_CipIdentity) String() string {
+ if m == nil {
+ return "<nil>"
+ }
+ writeBuffer := utils.NewWriteBufferBoxBasedWithOptions(true, true)
+ if err := writeBuffer.WriteSerializable(context.Background(), m); err != nil {
+ return err.Error()
+ }
+ return writeBuffer.GetBox().String()
+}
diff --git a/plc4go/protocols/eip/readwrite/model/CipSecurityInformation.go b/plc4go/protocols/eip/readwrite/model/CipSecurityInformation.go
new file mode 100644
index 0000000000..739a638bf8
--- /dev/null
+++ b/plc4go/protocols/eip/readwrite/model/CipSecurityInformation.go
@@ -0,0 +1,250 @@
+/*
+ * 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 model
+
+import (
+ "context"
+ "fmt"
+ "github.com/apache/plc4x/plc4go/spi/utils"
+ "github.com/pkg/errors"
+)
+
+// Code generated by code-generation. DO NOT EDIT.
+
+// CipSecurityInformation is the corresponding interface of CipSecurityInformation
+type CipSecurityInformation interface {
+ fmt.Stringer
+ utils.LengthAware
+ utils.Serializable
+ CommandSpecificDataItem
+ // GetTodoImplement returns TodoImplement (property field)
+ GetTodoImplement() []uint8
+}
+
+// CipSecurityInformationExactly can be used when we want exactly this type and not a type which fulfills CipSecurityInformation.
+// This is useful for switch cases.
+type CipSecurityInformationExactly interface {
+ CipSecurityInformation
+ isCipSecurityInformation() bool
+}
+
+// _CipSecurityInformation is the data-structure of this message
+type _CipSecurityInformation struct {
+ *_CommandSpecificDataItem
+ TodoImplement []uint8
+}
+
+///////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////
+/////////////////////// Accessors for discriminator values.
+///////////////////////
+
+func (m *_CipSecurityInformation) GetItemType() uint16 {
+ return 0x0086
+}
+
+///////////////////////
+///////////////////////
+///////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////
+
+func (m *_CipSecurityInformation) InitializeParent(parent CommandSpecificDataItem) {}
+
+func (m *_CipSecurityInformation) GetParent() CommandSpecificDataItem {
+ return m._CommandSpecificDataItem
+}
+
+///////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////
+/////////////////////// Accessors for property fields.
+///////////////////////
+
+func (m *_CipSecurityInformation) GetTodoImplement() []uint8 {
+ return m.TodoImplement
+}
+
+///////////////////////
+///////////////////////
+///////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////
+
+// NewCipSecurityInformation factory function for _CipSecurityInformation
+func NewCipSecurityInformation(todoImplement []uint8) *_CipSecurityInformation {
+ _result := &_CipSecurityInformation{
+ TodoImplement: todoImplement,
+ _CommandSpecificDataItem: NewCommandSpecificDataItem(),
+ }
+ _result._CommandSpecificDataItem._CommandSpecificDataItemChildRequirements = _result
+ return _result
+}
+
+// Deprecated: use the interface for direct cast
+func CastCipSecurityInformation(structType any) CipSecurityInformation {
+ if casted, ok := structType.(CipSecurityInformation); ok {
+ return casted
+ }
+ if casted, ok := structType.(*CipSecurityInformation); ok {
+ return *casted
+ }
+ return nil
+}
+
+func (m *_CipSecurityInformation) GetTypeName() string {
+ return "CipSecurityInformation"
+}
+
+func (m *_CipSecurityInformation) GetLengthInBits(ctx context.Context) uint16 {
+ lengthInBits := uint16(m.GetParentLengthInBits(ctx))
+
+ // Implicit Field (itemLength)
+ lengthInBits += 16
+
+ // Array field
+ if len(m.TodoImplement) > 0 {
+ lengthInBits += 8 * uint16(len(m.TodoImplement))
+ }
+
+ return lengthInBits
+}
+
+func (m *_CipSecurityInformation) GetLengthInBytes(ctx context.Context) uint16 {
+ return m.GetLengthInBits(ctx) / 8
+}
+
+func CipSecurityInformationParse(theBytes []byte) (CipSecurityInformation, error) {
+ return CipSecurityInformationParseWithBuffer(context.Background(), utils.NewReadBufferByteBased(theBytes))
+}
+
+func CipSecurityInformationParseWithBuffer(ctx context.Context, readBuffer utils.ReadBuffer) (CipSecurityInformation, error) {
+ positionAware := readBuffer
+ _ = positionAware
+ if pullErr := readBuffer.PullContext("CipSecurityInformation"); pullErr != nil {
+ return nil, errors.Wrap(pullErr, "Error pulling for CipSecurityInformation")
+ }
+ currentPos := positionAware.GetPos()
+ _ = currentPos
+
+ // Implicit Field (itemLength) (Used for parsing, but its value is not stored as it's implicitly given by the objects content)
+ itemLength, _itemLengthErr := readBuffer.ReadUint16("itemLength", 16)
+ _ = itemLength
+ if _itemLengthErr != nil {
+ return nil, errors.Wrap(_itemLengthErr, "Error parsing 'itemLength' field of CipSecurityInformation")
+ }
+
+ // Array field (todoImplement)
+ if pullErr := readBuffer.PullContext("todoImplement", utils.WithRenderAsList(true)); pullErr != nil {
+ return nil, errors.Wrap(pullErr, "Error pulling for todoImplement")
+ }
+ // Count array
+ todoImplement := make([]uint8, itemLength)
+ // This happens when the size is set conditional to 0
+ if len(todoImplement) == 0 {
+ todoImplement = nil
+ }
+ {
+ _numItems := uint16(itemLength)
+ for _curItem := uint16(0); _curItem < _numItems; _curItem++ {
+ arrayCtx := utils.CreateArrayContext(ctx, int(_numItems), int(_curItem))
+ _ = arrayCtx
+ _ = _curItem
+ _item, _err := readBuffer.ReadUint8("", 8)
+ if _err != nil {
+ return nil, errors.Wrap(_err, "Error parsing 'todoImplement' field of CipSecurityInformation")
+ }
+ todoImplement[_curItem] = _item
+ }
+ }
+ if closeErr := readBuffer.CloseContext("todoImplement", utils.WithRenderAsList(true)); closeErr != nil {
+ return nil, errors.Wrap(closeErr, "Error closing for todoImplement")
+ }
+
+ if closeErr := readBuffer.CloseContext("CipSecurityInformation"); closeErr != nil {
+ return nil, errors.Wrap(closeErr, "Error closing for CipSecurityInformation")
+ }
+
+ // Create a partially initialized instance
+ _child := &_CipSecurityInformation{
+ _CommandSpecificDataItem: &_CommandSpecificDataItem{},
+ TodoImplement: todoImplement,
+ }
+ _child._CommandSpecificDataItem._CommandSpecificDataItemChildRequirements = _child
+ return _child, nil
+}
+
+func (m *_CipSecurityInformation) Serialize() ([]byte, error) {
+ wb := utils.NewWriteBufferByteBased(utils.WithInitialSizeForByteBasedBuffer(int(m.GetLengthInBytes(context.Background()))))
+ if err := m.SerializeWithWriteBuffer(context.Background(), wb); err != nil {
+ return nil, err
+ }
+ return wb.GetBytes(), nil
+}
+
+func (m *_CipSecurityInformation) SerializeWithWriteBuffer(ctx context.Context, writeBuffer utils.WriteBuffer) error {
+ positionAware := writeBuffer
+ _ = positionAware
+ ser := func() error {
+ if pushErr := writeBuffer.PushContext("CipSecurityInformation"); pushErr != nil {
+ return errors.Wrap(pushErr, "Error pushing for CipSecurityInformation")
+ }
+
+ // Implicit Field (itemLength) (Used for parsing, but it's value is not stored as it's implicitly given by the objects content)
+ itemLength := uint16(uint16(len(m.GetTodoImplement())))
+ _itemLengthErr := writeBuffer.WriteUint16("itemLength", 16, (itemLength))
+ if _itemLengthErr != nil {
+ return errors.Wrap(_itemLengthErr, "Error serializing 'itemLength' field")
+ }
+
+ // Array Field (todoImplement)
+ if pushErr := writeBuffer.PushContext("todoImplement", utils.WithRenderAsList(true)); pushErr != nil {
+ return errors.Wrap(pushErr, "Error pushing for todoImplement")
+ }
+ for _curItem, _element := range m.GetTodoImplement() {
+ _ = _curItem
+ _elementErr := writeBuffer.WriteUint8("", 8, _element)
+ if _elementErr != nil {
+ return errors.Wrap(_elementErr, "Error serializing 'todoImplement' field")
+ }
+ }
+ if popErr := writeBuffer.PopContext("todoImplement", utils.WithRenderAsList(true)); popErr != nil {
+ return errors.Wrap(popErr, "Error popping for todoImplement")
+ }
+
+ if popErr := writeBuffer.PopContext("CipSecurityInformation"); popErr != nil {
+ return errors.Wrap(popErr, "Error popping for CipSecurityInformation")
+ }
+ return nil
+ }
+ return m.SerializeParent(ctx, writeBuffer, m, ser)
+}
+
+func (m *_CipSecurityInformation) isCipSecurityInformation() bool {
+ return true
+}
+
+func (m *_CipSecurityInformation) String() string {
+ if m == nil {
+ return "<nil>"
+ }
+ writeBuffer := utils.NewWriteBufferBoxBasedWithOptions(true, true)
+ if err := writeBuffer.WriteSerializable(context.Background(), m); err != nil {
+ return err.Error()
+ }
+ return writeBuffer.GetBox().String()
+}
diff --git a/plc4go/protocols/eip/readwrite/model/CommandSpecificDataItem.go b/plc4go/protocols/eip/readwrite/model/CommandSpecificDataItem.go
new file mode 100644
index 0000000000..c2ad7b4761
--- /dev/null
+++ b/plc4go/protocols/eip/readwrite/model/CommandSpecificDataItem.go
@@ -0,0 +1,196 @@
+/*
+ * 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 model
+
+import (
+ "context"
+ "fmt"
+ "github.com/apache/plc4x/plc4go/spi/utils"
+ "github.com/pkg/errors"
+)
+
+// Code generated by code-generation. DO NOT EDIT.
+
+// CommandSpecificDataItem is the corresponding interface of CommandSpecificDataItem
+type CommandSpecificDataItem interface {
+ fmt.Stringer
+ utils.LengthAware
+ utils.Serializable
+ // GetItemType returns ItemType (discriminator field)
+ GetItemType() uint16
+}
+
+// CommandSpecificDataItemExactly can be used when we want exactly this type and not a type which fulfills CommandSpecificDataItem.
+// This is useful for switch cases.
+type CommandSpecificDataItemExactly interface {
+ CommandSpecificDataItem
+ isCommandSpecificDataItem() bool
+}
+
+// _CommandSpecificDataItem is the data-structure of this message
+type _CommandSpecificDataItem struct {
+ _CommandSpecificDataItemChildRequirements
+}
+
+type _CommandSpecificDataItemChildRequirements interface {
+ utils.Serializable
+ GetLengthInBits(ctx context.Context) uint16
+ GetItemType() uint16
+}
+
+type CommandSpecificDataItemParent interface {
+ SerializeParent(ctx context.Context, writeBuffer utils.WriteBuffer, child CommandSpecificDataItem, serializeChildFunction func() error) error
+ GetTypeName() string
+}
+
+type CommandSpecificDataItemChild interface {
+ utils.Serializable
+ InitializeParent(parent CommandSpecificDataItem)
+ GetParent() *CommandSpecificDataItem
+
+ GetTypeName() string
+ CommandSpecificDataItem
+}
+
+// NewCommandSpecificDataItem factory function for _CommandSpecificDataItem
+func NewCommandSpecificDataItem() *_CommandSpecificDataItem {
+ return &_CommandSpecificDataItem{}
+}
+
+// Deprecated: use the interface for direct cast
+func CastCommandSpecificDataItem(structType any) CommandSpecificDataItem {
+ if casted, ok := structType.(CommandSpecificDataItem); ok {
+ return casted
+ }
+ if casted, ok := structType.(*CommandSpecificDataItem); ok {
+ return *casted
+ }
+ return nil
+}
+
+func (m *_CommandSpecificDataItem) GetTypeName() string {
+ return "CommandSpecificDataItem"
+}
+
+func (m *_CommandSpecificDataItem) GetParentLengthInBits(ctx context.Context) uint16 {
+ lengthInBits := uint16(0)
+ // Discriminator Field (itemType)
+ lengthInBits += 16
+
+ return lengthInBits
+}
+
+func (m *_CommandSpecificDataItem) GetLengthInBytes(ctx context.Context) uint16 {
+ return m.GetLengthInBits(ctx) / 8
+}
+
+func CommandSpecificDataItemParse(theBytes []byte) (CommandSpecificDataItem, error) {
+ return CommandSpecificDataItemParseWithBuffer(context.Background(), utils.NewReadBufferByteBased(theBytes))
+}
+
+func CommandSpecificDataItemParseWithBuffer(ctx context.Context, readBuffer utils.ReadBuffer) (CommandSpecificDataItem, error) {
+ positionAware := readBuffer
+ _ = positionAware
+ if pullErr := readBuffer.PullContext("CommandSpecificDataItem"); pullErr != nil {
+ return nil, errors.Wrap(pullErr, "Error pulling for CommandSpecificDataItem")
+ }
+ currentPos := positionAware.GetPos()
+ _ = currentPos
+
+ // Discriminator Field (itemType) (Used as input to a switch field)
+ itemType, _itemTypeErr := readBuffer.ReadUint16("itemType", 16)
+ if _itemTypeErr != nil {
+ return nil, errors.Wrap(_itemTypeErr, "Error parsing 'itemType' field of CommandSpecificDataItem")
+ }
+
+ // Switch Field (Depending on the discriminator values, passes the instantiation to a sub-type)
+ type CommandSpecificDataItemChildSerializeRequirement interface {
+ CommandSpecificDataItem
+ InitializeParent(CommandSpecificDataItem)
+ GetParent() CommandSpecificDataItem
+ }
+ var _childTemp any
+ var _child CommandSpecificDataItemChildSerializeRequirement
+ var typeSwitchError error
+ switch {
+ case itemType == 0x000C: // CipIdentity
+ _childTemp, typeSwitchError = CipIdentityParseWithBuffer(ctx, readBuffer)
+ case itemType == 0x0086: // CipSecurityInformation
+ _childTemp, typeSwitchError = CipSecurityInformationParseWithBuffer(ctx, readBuffer)
+ default:
+ typeSwitchError = errors.Errorf("Unmapped type for parameters [itemType=%v]", itemType)
+ }
+ if typeSwitchError != nil {
+ return nil, errors.Wrap(typeSwitchError, "Error parsing sub-type for type-switch of CommandSpecificDataItem")
+ }
+ _child = _childTemp.(CommandSpecificDataItemChildSerializeRequirement)
+
+ if closeErr := readBuffer.CloseContext("CommandSpecificDataItem"); closeErr != nil {
+ return nil, errors.Wrap(closeErr, "Error closing for CommandSpecificDataItem")
+ }
+
+ // Finish initializing
+ _child.InitializeParent(_child)
+ return _child, nil
+}
+
+func (pm *_CommandSpecificDataItem) SerializeParent(ctx context.Context, writeBuffer utils.WriteBuffer, child CommandSpecificDataItem, serializeChildFunction func() error) error {
+ // We redirect all calls through client as some methods are only implemented there
+ m := child
+ _ = m
+ positionAware := writeBuffer
+ _ = positionAware
+ if pushErr := writeBuffer.PushContext("CommandSpecificDataItem"); pushErr != nil {
+ return errors.Wrap(pushErr, "Error pushing for CommandSpecificDataItem")
+ }
+
+ // Discriminator Field (itemType) (Used as input to a switch field)
+ itemType := uint16(child.GetItemType())
+ _itemTypeErr := writeBuffer.WriteUint16("itemType", 16, (itemType))
+
+ if _itemTypeErr != nil {
+ return errors.Wrap(_itemTypeErr, "Error serializing 'itemType' field")
+ }
+
+ // Switch field (Depending on the discriminator values, passes the serialization to a sub-type)
+ if _typeSwitchErr := serializeChildFunction(); _typeSwitchErr != nil {
+ return errors.Wrap(_typeSwitchErr, "Error serializing sub-type field")
+ }
+
+ if popErr := writeBuffer.PopContext("CommandSpecificDataItem"); popErr != nil {
+ return errors.Wrap(popErr, "Error popping for CommandSpecificDataItem")
+ }
+ return nil
+}
+
+func (m *_CommandSpecificDataItem) isCommandSpecificDataItem() bool {
+ return true
+}
+
+func (m *_CommandSpecificDataItem) String() string {
+ if m == nil {
+ return "<nil>"
+ }
+ writeBuffer := utils.NewWriteBufferBoxBasedWithOptions(true, true)
+ if err := writeBuffer.WriteSerializable(context.Background(), m); err != nil {
+ return err.Error()
+ }
+ return writeBuffer.GetBox().String()
+}
diff --git a/plc4go/protocols/eip/readwrite/model/EipListIdentityRequest.go b/plc4go/protocols/eip/readwrite/model/EipListIdentityRequest.go
new file mode 100644
index 0000000000..0197eeadf3
--- /dev/null
+++ b/plc4go/protocols/eip/readwrite/model/EipListIdentityRequest.go
@@ -0,0 +1,180 @@
+/*
+ * 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 model
+
+import (
+ "context"
+ "fmt"
+ "github.com/apache/plc4x/plc4go/spi/utils"
+ "github.com/pkg/errors"
+)
+
+// Code generated by code-generation. DO NOT EDIT.
+
+// EipListIdentityRequest is the corresponding interface of EipListIdentityRequest
+type EipListIdentityRequest interface {
+ fmt.Stringer
+ utils.LengthAware
+ utils.Serializable
+ EipPacket
+}
+
+// EipListIdentityRequestExactly can be used when we want exactly this type and not a type which fulfills EipListIdentityRequest.
+// This is useful for switch cases.
+type EipListIdentityRequestExactly interface {
+ EipListIdentityRequest
+ isEipListIdentityRequest() bool
+}
+
+// _EipListIdentityRequest is the data-structure of this message
+type _EipListIdentityRequest struct {
+ *_EipPacket
+}
+
+///////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////
+/////////////////////// Accessors for discriminator values.
+///////////////////////
+
+func (m *_EipListIdentityRequest) GetCommand() uint16 {
+ return 0x0063
+}
+
+func (m *_EipListIdentityRequest) GetResponse() bool {
+ return bool(false)
+}
+
+func (m *_EipListIdentityRequest) GetPacketLength() uint16 {
+ return 0
+}
+
+///////////////////////
+///////////////////////
+///////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////
+
+func (m *_EipListIdentityRequest) InitializeParent(parent EipPacket, sessionHandle uint32, status uint32, senderContext []byte, options uint32) {
+ m.SessionHandle = sessionHandle
+ m.Status = status
+ m.SenderContext = senderContext
+ m.Options = options
+}
+
+func (m *_EipListIdentityRequest) GetParent() EipPacket {
+ return m._EipPacket
+}
+
+// NewEipListIdentityRequest factory function for _EipListIdentityRequest
+func NewEipListIdentityRequest(sessionHandle uint32, status uint32, senderContext []byte, options uint32) *_EipListIdentityRequest {
+ _result := &_EipListIdentityRequest{
+ _EipPacket: NewEipPacket(sessionHandle, status, senderContext, options),
+ }
+ _result._EipPacket._EipPacketChildRequirements = _result
+ return _result
+}
+
+// Deprecated: use the interface for direct cast
+func CastEipListIdentityRequest(structType any) EipListIdentityRequest {
+ if casted, ok := structType.(EipListIdentityRequest); ok {
+ return casted
+ }
+ if casted, ok := structType.(*EipListIdentityRequest); ok {
+ return *casted
+ }
+ return nil
+}
+
+func (m *_EipListIdentityRequest) GetTypeName() string {
+ return "EipListIdentityRequest"
+}
+
+func (m *_EipListIdentityRequest) GetLengthInBits(ctx context.Context) uint16 {
+ lengthInBits := uint16(m.GetParentLengthInBits(ctx))
+
+ return lengthInBits
+}
+
+func (m *_EipListIdentityRequest) GetLengthInBytes(ctx context.Context) uint16 {
+ return m.GetLengthInBits(ctx) / 8
+}
+
+func EipListIdentityRequestParse(theBytes []byte, response bool) (EipListIdentityRequest, error) {
+ return EipListIdentityRequestParseWithBuffer(context.Background(), utils.NewReadBufferByteBased(theBytes), response)
+}
+
+func EipListIdentityRequestParseWithBuffer(ctx context.Context, readBuffer utils.ReadBuffer, response bool) (EipListIdentityRequest, error) {
+ positionAware := readBuffer
+ _ = positionAware
+ if pullErr := readBuffer.PullContext("EipListIdentityRequest"); pullErr != nil {
+ return nil, errors.Wrap(pullErr, "Error pulling for EipListIdentityRequest")
+ }
+ currentPos := positionAware.GetPos()
+ _ = currentPos
+
+ if closeErr := readBuffer.CloseContext("EipListIdentityRequest"); closeErr != nil {
+ return nil, errors.Wrap(closeErr, "Error closing for EipListIdentityRequest")
+ }
+
+ // Create a partially initialized instance
+ _child := &_EipListIdentityRequest{
+ _EipPacket: &_EipPacket{},
+ }
+ _child._EipPacket._EipPacketChildRequirements = _child
+ return _child, nil
+}
+
+func (m *_EipListIdentityRequest) Serialize() ([]byte, error) {
+ wb := utils.NewWriteBufferByteBased(utils.WithInitialSizeForByteBasedBuffer(int(m.GetLengthInBytes(context.Background()))))
+ if err := m.SerializeWithWriteBuffer(context.Background(), wb); err != nil {
+ return nil, err
+ }
+ return wb.GetBytes(), nil
+}
+
+func (m *_EipListIdentityRequest) SerializeWithWriteBuffer(ctx context.Context, writeBuffer utils.WriteBuffer) error {
+ positionAware := writeBuffer
+ _ = positionAware
+ ser := func() error {
+ if pushErr := writeBuffer.PushContext("EipListIdentityRequest"); pushErr != nil {
+ return errors.Wrap(pushErr, "Error pushing for EipListIdentityRequest")
+ }
+
+ if popErr := writeBuffer.PopContext("EipListIdentityRequest"); popErr != nil {
+ return errors.Wrap(popErr, "Error popping for EipListIdentityRequest")
+ }
+ return nil
+ }
+ return m.SerializeParent(ctx, writeBuffer, m, ser)
+}
+
+func (m *_EipListIdentityRequest) isEipListIdentityRequest() bool {
+ return true
+}
+
+func (m *_EipListIdentityRequest) String() string {
+ if m == nil {
+ return "<nil>"
+ }
+ writeBuffer := utils.NewWriteBufferBoxBasedWithOptions(true, true)
+ if err := writeBuffer.WriteSerializable(context.Background(), m); err != nil {
+ return err.Error()
+ }
+ return writeBuffer.GetBox().String()
+}
diff --git a/plc4go/protocols/eip/readwrite/model/EipListIdentityResponse.go b/plc4go/protocols/eip/readwrite/model/EipListIdentityResponse.go
new file mode 100644
index 0000000000..71e7d38b85
--- /dev/null
+++ b/plc4go/protocols/eip/readwrite/model/EipListIdentityResponse.go
@@ -0,0 +1,270 @@
+/*
+ * 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 model
+
+import (
+ "context"
+ "fmt"
+ "github.com/apache/plc4x/plc4go/spi/utils"
+ "github.com/pkg/errors"
+)
+
+// Code generated by code-generation. DO NOT EDIT.
+
+// EipListIdentityResponse is the corresponding interface of EipListIdentityResponse
+type EipListIdentityResponse interface {
+ fmt.Stringer
+ utils.LengthAware
+ utils.Serializable
+ EipPacket
+ // GetItems returns Items (property field)
+ GetItems() []CommandSpecificDataItem
+}
+
+// EipListIdentityResponseExactly can be used when we want exactly this type and not a type which fulfills EipListIdentityResponse.
+// This is useful for switch cases.
+type EipListIdentityResponseExactly interface {
+ EipListIdentityResponse
+ isEipListIdentityResponse() bool
+}
+
+// _EipListIdentityResponse is the data-structure of this message
+type _EipListIdentityResponse struct {
+ *_EipPacket
+ Items []CommandSpecificDataItem
+}
+
+///////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////
+/////////////////////// Accessors for discriminator values.
+///////////////////////
+
+func (m *_EipListIdentityResponse) GetCommand() uint16 {
+ return 0x0063
+}
+
+func (m *_EipListIdentityResponse) GetResponse() bool {
+ return bool(true)
+}
+
+func (m *_EipListIdentityResponse) GetPacketLength() uint16 {
+ return 0
+}
+
+///////////////////////
+///////////////////////
+///////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////
+
+func (m *_EipListIdentityResponse) InitializeParent(parent EipPacket, sessionHandle uint32, status uint32, senderContext []byte, options uint32) {
+ m.SessionHandle = sessionHandle
+ m.Status = status
+ m.SenderContext = senderContext
+ m.Options = options
+}
+
+func (m *_EipListIdentityResponse) GetParent() EipPacket {
+ return m._EipPacket
+}
+
+///////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////
+/////////////////////// Accessors for property fields.
+///////////////////////
+
+func (m *_EipListIdentityResponse) GetItems() []CommandSpecificDataItem {
+ return m.Items
+}
+
+///////////////////////
+///////////////////////
+///////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////
+
+// NewEipListIdentityResponse factory function for _EipListIdentityResponse
+func NewEipListIdentityResponse(items []CommandSpecificDataItem, sessionHandle uint32, status uint32, senderContext []byte, options uint32) *_EipListIdentityResponse {
+ _result := &_EipListIdentityResponse{
+ Items: items,
+ _EipPacket: NewEipPacket(sessionHandle, status, senderContext, options),
+ }
+ _result._EipPacket._EipPacketChildRequirements = _result
+ return _result
+}
+
+// Deprecated: use the interface for direct cast
+func CastEipListIdentityResponse(structType any) EipListIdentityResponse {
+ if casted, ok := structType.(EipListIdentityResponse); ok {
+ return casted
+ }
+ if casted, ok := structType.(*EipListIdentityResponse); ok {
+ return *casted
+ }
+ return nil
+}
+
+func (m *_EipListIdentityResponse) GetTypeName() string {
+ return "EipListIdentityResponse"
+}
+
+func (m *_EipListIdentityResponse) GetLengthInBits(ctx context.Context) uint16 {
+ lengthInBits := uint16(m.GetParentLengthInBits(ctx))
+
+ // Implicit Field (itemCount)
+ lengthInBits += 16
+
+ // Array field
+ if len(m.Items) > 0 {
+ for _curItem, element := range m.Items {
+ arrayCtx := utils.CreateArrayContext(ctx, len(m.Items), _curItem)
+ _ = arrayCtx
+ _ = _curItem
+ lengthInBits += element.(interface{ GetLengthInBits(context.Context) uint16 }).GetLengthInBits(arrayCtx)
+ }
+ }
+
+ return lengthInBits
+}
+
+func (m *_EipListIdentityResponse) GetLengthInBytes(ctx context.Context) uint16 {
+ return m.GetLengthInBits(ctx) / 8
+}
+
+func EipListIdentityResponseParse(theBytes []byte, response bool) (EipListIdentityResponse, error) {
+ return EipListIdentityResponseParseWithBuffer(context.Background(), utils.NewReadBufferByteBased(theBytes), response)
+}
+
+func EipListIdentityResponseParseWithBuffer(ctx context.Context, readBuffer utils.ReadBuffer, response bool) (EipListIdentityResponse, error) {
+ positionAware := readBuffer
+ _ = positionAware
+ if pullErr := readBuffer.PullContext("EipListIdentityResponse"); pullErr != nil {
+ return nil, errors.Wrap(pullErr, "Error pulling for EipListIdentityResponse")
+ }
+ currentPos := positionAware.GetPos()
+ _ = currentPos
+
+ // Implicit Field (itemCount) (Used for parsing, but its value is not stored as it's implicitly given by the objects content)
+ itemCount, _itemCountErr := readBuffer.ReadUint16("itemCount", 16)
+ _ = itemCount
+ if _itemCountErr != nil {
+ return nil, errors.Wrap(_itemCountErr, "Error parsing 'itemCount' field of EipListIdentityResponse")
+ }
+
+ // Array field (items)
+ if pullErr := readBuffer.PullContext("items", utils.WithRenderAsList(true)); pullErr != nil {
+ return nil, errors.Wrap(pullErr, "Error pulling for items")
+ }
+ // Count array
+ items := make([]CommandSpecificDataItem, itemCount)
+ // This happens when the size is set conditional to 0
+ if len(items) == 0 {
+ items = nil
+ }
+ {
+ _numItems := uint16(itemCount)
+ for _curItem := uint16(0); _curItem < _numItems; _curItem++ {
+ arrayCtx := utils.CreateArrayContext(ctx, int(_numItems), int(_curItem))
+ _ = arrayCtx
+ _ = _curItem
+ _item, _err := CommandSpecificDataItemParseWithBuffer(arrayCtx, readBuffer)
+ if _err != nil {
+ return nil, errors.Wrap(_err, "Error parsing 'items' field of EipListIdentityResponse")
+ }
+ items[_curItem] = _item.(CommandSpecificDataItem)
+ }
+ }
+ if closeErr := readBuffer.CloseContext("items", utils.WithRenderAsList(true)); closeErr != nil {
+ return nil, errors.Wrap(closeErr, "Error closing for items")
+ }
+
+ if closeErr := readBuffer.CloseContext("EipListIdentityResponse"); closeErr != nil {
+ return nil, errors.Wrap(closeErr, "Error closing for EipListIdentityResponse")
+ }
+
+ // Create a partially initialized instance
+ _child := &_EipListIdentityResponse{
+ _EipPacket: &_EipPacket{},
+ Items: items,
+ }
+ _child._EipPacket._EipPacketChildRequirements = _child
+ return _child, nil
+}
+
+func (m *_EipListIdentityResponse) Serialize() ([]byte, error) {
+ wb := utils.NewWriteBufferByteBased(utils.WithInitialSizeForByteBasedBuffer(int(m.GetLengthInBytes(context.Background()))))
+ if err := m.SerializeWithWriteBuffer(context.Background(), wb); err != nil {
+ return nil, err
+ }
+ return wb.GetBytes(), nil
+}
+
+func (m *_EipListIdentityResponse) SerializeWithWriteBuffer(ctx context.Context, writeBuffer utils.WriteBuffer) error {
+ positionAware := writeBuffer
+ _ = positionAware
+ ser := func() error {
+ if pushErr := writeBuffer.PushContext("EipListIdentityResponse"); pushErr != nil {
+ return errors.Wrap(pushErr, "Error pushing for EipListIdentityResponse")
+ }
+
+ // Implicit Field (itemCount) (Used for parsing, but it's value is not stored as it's implicitly given by the objects content)
+ itemCount := uint16(uint16(len(m.GetItems())))
+ _itemCountErr := writeBuffer.WriteUint16("itemCount", 16, (itemCount))
+ if _itemCountErr != nil {
+ return errors.Wrap(_itemCountErr, "Error serializing 'itemCount' field")
+ }
+
+ // Array Field (items)
+ if pushErr := writeBuffer.PushContext("items", utils.WithRenderAsList(true)); pushErr != nil {
+ return errors.Wrap(pushErr, "Error pushing for items")
+ }
+ for _curItem, _element := range m.GetItems() {
+ _ = _curItem
+ arrayCtx := utils.CreateArrayContext(ctx, len(m.GetItems()), _curItem)
+ _ = arrayCtx
+ _elementErr := writeBuffer.WriteSerializable(arrayCtx, _element)
+ if _elementErr != nil {
+ return errors.Wrap(_elementErr, "Error serializing 'items' field")
+ }
+ }
+ if popErr := writeBuffer.PopContext("items", utils.WithRenderAsList(true)); popErr != nil {
+ return errors.Wrap(popErr, "Error popping for items")
+ }
+
+ if popErr := writeBuffer.PopContext("EipListIdentityResponse"); popErr != nil {
+ return errors.Wrap(popErr, "Error popping for EipListIdentityResponse")
+ }
+ return nil
+ }
+ return m.SerializeParent(ctx, writeBuffer, m, ser)
+}
+
+func (m *_EipListIdentityResponse) isEipListIdentityResponse() bool {
+ return true
+}
+
+func (m *_EipListIdentityResponse) String() string {
+ if m == nil {
+ return "<nil>"
+ }
+ writeBuffer := utils.NewWriteBufferBoxBasedWithOptions(true, true)
+ if err := writeBuffer.WriteSerializable(context.Background(), m); err != nil {
+ return err.Error()
+ }
+ return writeBuffer.GetBox().String()
+}
diff --git a/plc4j/drivers/profinet/src/main/generated/org/apache/plc4x/java/profinet/readwrite/DceRpc_Packet.java b/plc4j/drivers/profinet/src/main/generated/org/apache/plc4x/java/profinet/readwrite/DceRpc_Packet.java
index fba7a81c69..bea66c6550 100644
--- a/plc4j/drivers/profinet/src/main/generated/org/apache/plc4x/java/profinet/readwrite/DceRpc_Packet.java
+++ b/plc4j/drivers/profinet/src/main/generated/org/apache/plc4x/java/profinet/readwrite/DceRpc_Packet.java
@@ -49,7 +49,6 @@ public class DceRpc_Packet implements Message {
public static final Integer ACTIVITYHINT = 0xFFFF;
public static final Integer FRAGMENTNUM = 0x0000;
public static final Short AUTHPROTO = 0x00;
- public static final Short SERIALLOW = 0x00;
// Properties.
protected final DceRpc_PacketType packetType;
@@ -65,6 +64,7 @@ public class DceRpc_Packet implements Message {
protected final long serverBootTime;
protected final long sequenceNumber;
protected final DceRpc_Operation operation;
+ protected final short serialLow;
protected final PnIoCm_Packet payload;
// Reserved Fields
@@ -88,6 +88,7 @@ public class DceRpc_Packet implements Message {
long serverBootTime,
long sequenceNumber,
DceRpc_Operation operation,
+ short serialLow,
PnIoCm_Packet payload) {
super();
this.packetType = packetType;
@@ -103,6 +104,7 @@ public class DceRpc_Packet implements Message {
this.serverBootTime = serverBootTime;
this.sequenceNumber = sequenceNumber;
this.operation = operation;
+ this.serialLow = serialLow;
this.payload = payload;
}
@@ -158,6 +160,10 @@ public class DceRpc_Packet implements Message {
return operation;
}
+ public short getSerialLow() {
+ return serialLow;
+ }
+
public PnIoCm_Packet getPayload() {
return payload;
}
@@ -206,10 +212,6 @@ public class DceRpc_Packet implements Message {
return AUTHPROTO;
}
- public short getSerialLow() {
- return SERIALLOW;
- }
-
public void serialize(WriteBuffer writeBuffer) throws SerializationException {
PositionAware positionAware = writeBuffer;
boolean _lastItem = ThreadLocalHelper.lastItemThreadLocal.get();
@@ -476,10 +478,10 @@ public class DceRpc_Packet implements Message {
? ByteOrder.BIG_ENDIAN
: ByteOrder.LITTLE_ENDIAN)));
- // Const Field (serialLow)
- writeConstField(
+ // Simple Field (serialLow)
+ writeSimpleField(
"serialLow",
- SERIALLOW,
+ serialLow,
writeUnsignedShort(writeBuffer, 8),
WithOption.WithByteOrder(ByteOrder.BIG_ENDIAN));
@@ -597,7 +599,7 @@ public class DceRpc_Packet implements Message {
// Const Field (authProto)
lengthInBits += 8;
- // Const Field (serialLow)
+ // Simple field (serialLow)
lengthInBits += 8;
// Simple field (payload)
@@ -861,10 +863,9 @@ public class DceRpc_Packet implements Message {
: ByteOrder.LITTLE_ENDIAN)));
short serialLow =
- readConstField(
+ readSimpleField(
"serialLow",
readUnsignedShort(readBuffer, 8),
- DceRpc_Packet.SERIALLOW,
WithOption.WithByteOrder(ByteOrder.BIG_ENDIAN));
PnIoCm_Packet payload =
@@ -896,6 +897,7 @@ public class DceRpc_Packet implements Message {
serverBootTime,
sequenceNumber,
operation,
+ serialLow,
payload);
_dceRpc_Packet.reservedField0 = reservedField0;
_dceRpc_Packet.reservedField1 = reservedField1;
@@ -927,6 +929,7 @@ public class DceRpc_Packet implements Message {
&& (getServerBootTime() == that.getServerBootTime())
&& (getSequenceNumber() == that.getSequenceNumber())
&& (getOperation() == that.getOperation())
+ && (getSerialLow() == that.getSerialLow())
&& (getPayload() == that.getPayload())
&& true;
}
@@ -947,6 +950,7 @@ public class DceRpc_Packet implements Message {
getServerBootTime(),
getSequenceNumber(),
getOperation(),
+ getSerialLow(),
getPayload());
}
diff --git a/plc4j/drivers/profinet/src/main/generated/org/apache/plc4x/java/profinet/readwrite/PnIoCm_Packet.java b/plc4j/drivers/profinet/src/main/generated/org/apache/plc4x/java/profinet/readwrite/PnIoCm_Packet.java
index 5d80b35886..7ede523d3d 100644
--- a/plc4j/drivers/profinet/src/main/generated/org/apache/plc4x/java/profinet/readwrite/PnIoCm_Packet.java
+++ b/plc4j/drivers/profinet/src/main/generated/org/apache/plc4x/java/profinet/readwrite/PnIoCm_Packet.java
@@ -115,6 +115,8 @@ public abstract class PnIoCm_Packet implements Message {
builder = PnIoCm_Packet_NoCall.staticParsePnIoCm_PacketBuilder(readBuffer, packetType);
} else if (EvaluationHelper.equals(packetType, DceRpc_PacketType.REJECT)) {
builder = PnIoCm_Packet_Rej.staticParsePnIoCm_PacketBuilder(readBuffer, packetType);
+ } else if (EvaluationHelper.equals(packetType, DceRpc_PacketType.WORKING)) {
+ builder = PnIoCm_Packet_Working.staticParsePnIoCm_PacketBuilder(readBuffer, packetType);
}
if (builder == null) {
throw new ParseException(
diff --git a/plc4j/drivers/profinet/src/main/generated/org/apache/plc4x/java/profinet/readwrite/PnIoCm_Packet_Working.java b/plc4j/drivers/profinet/src/main/generated/org/apache/plc4x/java/profinet/readwrite/PnIoCm_Packet_Working.java
new file mode 100644
index 0000000000..9384c89322
--- /dev/null
+++ b/plc4j/drivers/profinet/src/main/generated/org/apache/plc4x/java/profinet/readwrite/PnIoCm_Packet_Working.java
@@ -0,0 +1,122 @@
+/*
+ * 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 org.apache.plc4x.java.profinet.readwrite;
+
+import static org.apache.plc4x.java.spi.codegen.fields.FieldReaderFactory.*;
+import static org.apache.plc4x.java.spi.codegen.fields.FieldWriterFactory.*;
+import static org.apache.plc4x.java.spi.codegen.io.DataReaderFactory.*;
+import static org.apache.plc4x.java.spi.codegen.io.DataWriterFactory.*;
+import static org.apache.plc4x.java.spi.generation.StaticHelper.*;
+
+import java.time.*;
+import java.util.*;
+import org.apache.plc4x.java.api.exceptions.*;
+import org.apache.plc4x.java.api.value.*;
+import org.apache.plc4x.java.spi.codegen.*;
+import org.apache.plc4x.java.spi.codegen.fields.*;
+import org.apache.plc4x.java.spi.codegen.io.*;
+import org.apache.plc4x.java.spi.generation.*;
+
+// Code generated by code-generation. DO NOT EDIT.
+
+public class PnIoCm_Packet_Working extends PnIoCm_Packet implements Message {
+
+ // Accessors for discriminator values.
+ public DceRpc_PacketType getPacketType() {
+ return DceRpc_PacketType.WORKING;
+ }
+
+ public PnIoCm_Packet_Working() {
+ super();
+ }
+
+ @Override
+ protected void serializePnIoCm_PacketChild(WriteBuffer writeBuffer)
+ throws SerializationException {
+ PositionAware positionAware = writeBuffer;
+ boolean _lastItem = ThreadLocalHelper.lastItemThreadLocal.get();
+ writeBuffer.pushContext("PnIoCm_Packet_Working");
+
+ writeBuffer.popContext("PnIoCm_Packet_Working");
+ }
+
+ @Override
+ public int getLengthInBytes() {
+ return (int) Math.ceil((float) getLengthInBits() / 8.0);
+ }
+
+ @Override
+ public int getLengthInBits() {
+ int lengthInBits = super.getLengthInBits();
+ PnIoCm_Packet_Working _value = this;
+ boolean _lastItem = ThreadLocalHelper.lastItemThreadLocal.get();
+
+ return lengthInBits;
+ }
+
+ public static PnIoCm_PacketBuilder staticParsePnIoCm_PacketBuilder(
+ ReadBuffer readBuffer, DceRpc_PacketType packetType) throws ParseException {
+ readBuffer.pullContext("PnIoCm_Packet_Working");
+ PositionAware positionAware = readBuffer;
+ boolean _lastItem = ThreadLocalHelper.lastItemThreadLocal.get();
+
+ readBuffer.closeContext("PnIoCm_Packet_Working");
+ // Create the instance
+ return new PnIoCm_Packet_WorkingBuilderImpl();
+ }
+
+ public static class PnIoCm_Packet_WorkingBuilderImpl
+ implements PnIoCm_Packet.PnIoCm_PacketBuilder {
+
+ public PnIoCm_Packet_WorkingBuilderImpl() {}
+
+ public PnIoCm_Packet_Working build() {
+ PnIoCm_Packet_Working pnIoCm_Packet_Working = new PnIoCm_Packet_Working();
+ return pnIoCm_Packet_Working;
+ }
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (!(o instanceof PnIoCm_Packet_Working)) {
+ return false;
+ }
+ PnIoCm_Packet_Working that = (PnIoCm_Packet_Working) o;
+ return super.equals(that) && true;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(super.hashCode());
+ }
+
+ @Override
+ public String toString() {
+ WriteBufferBoxBased writeBufferBoxBased = new WriteBufferBoxBased(true, true);
+ try {
+ writeBufferBoxBased.writeSerializable(this);
+ } catch (SerializationException e) {
+ throw new RuntimeException(e);
+ }
+ return "\n" + writeBufferBoxBased.getBox().toString() + "\n";
+ }
+}
diff --git a/plc4j/drivers/profinet/src/main/java/org/apache/plc4x/java/profinet/device/ProfinetChannel.java b/plc4j/drivers/profinet/src/main/java/org/apache/plc4x/java/profinet/device/ProfinetChannel.java
index d9ed9f0db2..01a87ff3d1 100644
--- a/plc4j/drivers/profinet/src/main/java/org/apache/plc4x/java/profinet/device/ProfinetChannel.java
+++ b/plc4j/drivers/profinet/src/main/java/org/apache/plc4x/java/profinet/device/ProfinetChannel.java
@@ -138,7 +138,9 @@ public class ProfinetChannel {
}
else if (pdu.getFrameId() == PnDcp_FrameId.RT_CLASS_1) {
for (Map.Entry<String, ProfinetDevice> device : devices.entrySet()) {
- if (Arrays.equals(device.getValue().getDeviceContext().getMacAddress().getAddress(), ethernetFrame.getSource().getAddress())) {
+ if (device.getValue().getDeviceContext().getMacAddress() == null) {
+ logger.info("Hurz");
+ } else if (Arrays.equals(device.getValue().getDeviceContext().getMacAddress().getAddress(), ethernetFrame.getSource().getAddress())) {
PnDcp_Pdu_RealTimeCyclic cyclicPdu = (PnDcp_Pdu_RealTimeCyclic) pdu;
device.getValue().handleRealTimeResponse(cyclicPdu);
}
@@ -150,9 +152,30 @@ public class ProfinetChannel {
discoverer.processLldp(pdu);
}
} else if (payload instanceof Ethernet_FramePayload_IPv4) {
- for (Map.Entry<String, ProfinetDevice> device : devices.entrySet()) {
- if (Arrays.equals(device.getValue().getDeviceContext().getMacAddress().getAddress(), ethernetFrame.getSource().getAddress())) {
- device.getValue().handleResponse((Ethernet_FramePayload_IPv4) payload);
+ Ethernet_FramePayload_IPv4 payloadIPv4 = (Ethernet_FramePayload_IPv4) payload;
+ if (payloadIPv4.getPayload().getPacketType() == DceRpc_PacketType.PING) {
+ DceRpc_Packet pingRequest = payloadIPv4.getPayload();
+ // Intercept ping packets that originated from the PN device itself.
+ // TODO: Find out how to react to PING messages.
+ // According to https://pubs.opengroup.org/onlinepubs/9629399/chap12.htm the correct response for us to such a ping message would be a "working" response
+ Ethernet_Frame pingResponse = new Ethernet_Frame(ethernetFrame.getSource(), ethernetFrame.getDestination(),
+ new Ethernet_FramePayload_IPv4(payloadIPv4.getIdentification(), false, false,
+ payloadIPv4.getTimeToLive(), payloadIPv4.getDestinationAddress(),
+ payloadIPv4.getSourceAddress(), payloadIPv4.getDestinationPort(),
+ payloadIPv4.getSourcePort(), new DceRpc_Packet(DceRpc_PacketType.WORKING,
+ false, false, false,
+ IntegerEncoding.BIG_ENDIAN, CharacterEncoding.ASCII, FloatingPointEncoding.IEEE,
+ pingRequest.getObjectUuid(), pingRequest.getInterfaceUuid(), pingRequest.getActivityUuid(),
+ 0L, 0L, DceRpc_Operation.CONNECT, (short) 0, new PnIoCm_Packet_Working())
+ ));
+ this.send(pingResponse);
+
+ logger.info("Received PING packet: {}", packet);
+ } else {
+ for (Map.Entry<String, ProfinetDevice> device : devices.entrySet()) {
+ if (Arrays.equals(device.getValue().getDeviceContext().getMacAddress().getAddress(), ethernetFrame.getSource().getAddress())) {
+ device.getValue().handleResponse(payloadIPv4);
+ }
}
}
}
diff --git a/plc4j/drivers/profinet/src/main/java/org/apache/plc4x/java/profinet/device/ProfinetDevice.java b/plc4j/drivers/profinet/src/main/java/org/apache/plc4x/java/profinet/device/ProfinetDevice.java
index 5b12a524a0..e05df3b958 100644
--- a/plc4j/drivers/profinet/src/main/java/org/apache/plc4x/java/profinet/device/ProfinetDevice.java
+++ b/plc4j/drivers/profinet/src/main/java/org/apache/plc4x/java/profinet/device/ProfinetDevice.java
@@ -596,6 +596,7 @@ public class ProfinetDevice implements PlcSubscriber {
0,
id,
DceRpc_Operation.CONNECT,
+ (short) 0,
new PnIoCm_Packet_Req(ProfinetDeviceContext.DEFAULT_ARGS_MAXIMUM, ProfinetDeviceContext.DEFAULT_MAX_ARRAY_COUNT, 0, blocks)
);
}
@@ -738,6 +739,7 @@ public class ProfinetDevice implements PlcSubscriber {
0,
id,
DceRpc_Operation.WRITE,
+ (short) 0,
new PnIoCm_Packet_Req(16696, 16696, 0,
requests)
);
@@ -798,6 +800,7 @@ public class ProfinetDevice implements PlcSubscriber {
0,
id,
DceRpc_Operation.CONTROL,
+ (short) 0,
new PnIoCm_Packet_Req(16696, 16696, 0,
Collections.singletonList(
new PnIoCm_Control_Request(
@@ -873,6 +876,7 @@ public class ProfinetDevice implements PlcSubscriber {
0,
id,
DceRpc_Operation.CONTROL,
+ (short) 0,
new PnIoCm_Packet_Res(
(short) 0,
(short) 0,
@@ -932,6 +936,7 @@ public class ProfinetDevice implements PlcSubscriber {
0,
id,
DceRpc_Operation.CONTROL,
+ (short) 0,
new PnIoCm_Packet_NoCall()
);
}
diff --git a/plc4j/drivers/profinet/src/main/java/org/apache/plc4x/java/profinet/discovery/ProfinetPlcDiscoverer.java b/plc4j/drivers/profinet/src/main/java/org/apache/plc4x/java/profinet/discovery/ProfinetPlcDiscoverer.java
index e7b414a662..84b95a2196 100644
--- a/plc4j/drivers/profinet/src/main/java/org/apache/plc4x/java/profinet/discovery/ProfinetPlcDiscoverer.java
+++ b/plc4j/drivers/profinet/src/main/java/org/apache/plc4x/java/profinet/discovery/ProfinetPlcDiscoverer.java
@@ -393,6 +393,7 @@ public class ProfinetPlcDiscoverer implements PlcDiscoverer {
new TlvManagementAddress(
12,
ManagementAddressSubType.IPV4,
+ // 192.168.90.110
new IpAddress(Hex.decodeHex("c0a85a6e")),
(short) 0x03,
0x01L,
diff --git a/plc4j/drivers/profinet/src/main/java/org/apache/plc4x/java/profinet/protocol/ProfinetProtocolLogic.java b/plc4j/drivers/profinet/src/main/java/org/apache/plc4x/java/profinet/protocol/ProfinetProtocolLogic.java
index 44e7ff4b2f..05697cada1 100644
--- a/plc4j/drivers/profinet/src/main/java/org/apache/plc4x/java/profinet/protocol/ProfinetProtocolLogic.java
+++ b/plc4j/drivers/profinet/src/main/java/org/apache/plc4x/java/profinet/protocol/ProfinetProtocolLogic.java
@@ -130,15 +130,24 @@ public class ProfinetProtocolLogic extends Plc4xProtocolBase<Ethernet_Frame> imp
boolean discovered = false;
int count = 0;
while (!discovered) {
+ List<ProfinetDevice> missingDevices = new ArrayList<>();
discovered = true;
- // Check for each device, if there was an incoming response for an LLDP or DCP search request.
+ // Check for each device, if there was an incoming response for an LLDP and DCP search request.
+ // It seems that we need information from both the LLDP and the DCP response, so we need
+ // to check if both have been received.
for (Map.Entry<String, ProfinetDevice> device : devices.entrySet()) {
if (!device.getValue().hasLldpPdu() || !device.getValue().hasDcpPdu()) {
discovered = false;
+ missingDevices.add(device.getValue());
}
}
// If we've come past this more than 5 times (15 seconds), give up.
if (count > 5) {
+ for (ProfinetDevice missingDevice : missingDevices) {
+ if(missingDevice.hasDcpPdu() && !missingDevice.hasLldpPdu()) {
+ LOGGER.info("- For device {} we only managed to get a DCP discovery response, is the device possibly not connected via an LLDP enables switch?", missingDevice.getDeviceId());
+ }
+ }
throw new PlcConnectionException("One device failed to respond to discovery packet");
}
// If at least one device hasn't responded yet, we'll wait for 3 more seconds and then check again.
diff --git a/plc4j/drivers/profinet/src/test/java/org/apache/plc4x/java/profinet/ManualProfinetIoTest.java b/plc4j/drivers/profinet/src/test/java/org/apache/plc4x/java/profinet/ManualProfinetIoTest.java
index 082b4e27de..9e5b0784cf 100644
--- a/plc4j/drivers/profinet/src/test/java/org/apache/plc4x/java/profinet/ManualProfinetIoTest.java
+++ b/plc4j/drivers/profinet/src/test/java/org/apache/plc4x/java/profinet/ManualProfinetIoTest.java
@@ -39,16 +39,16 @@ public class ManualProfinetIoTest {
//final PlcConnection connection = new DefaultPlcDriverManager().getConnection("profinet://192.168.54.2?gsddirectory=~/.gsd&devices=[[simocodexbpn156e,DAP%201,(1,),192.168.54.23]]&reductionratio=16&sendclockfactor=32&dataholdfactor=3&watchdogfactor=3");
// REMARK: The driver would use the local network device with the given IP address and to an auto-discovery, trying to find any devices returned with the matching name.
// If this device is then found and an IP address is provided, it would use PN-DCP to set the IP address of that device to the given value.
- final PlcConnection connection = new DefaultPlcDriverManager().getConnection("profinet://192.168.24.220?gsddirectory=~/.gsd&devices=[[simocodexbpn156e,DAP%201,(1,),192.168.24.31]]&reductionratio=16&sendclockfactor=32&dataholdfactor=3&watchdogfactor=3");
+ final PlcConnection connection = new DefaultPlcDriverManager().getConnection("profinet://192.168.24.220?gsddirectory=~/.gsd&devices=[[cdxb195b3,DAP%201,(1,)]]&reductionratio=16&sendclockfactor=32&dataholdfactor=3&watchdogfactor=3");
// Wireshark filters:
// - S7 1200: eth.addr == 001c0605bcdc
// - Simocode: eth.addr == 883f990006ef
// - Adam Analog Input: eth.addr == 74fe4863f6c2
// - Adam Digital I/O: eth.addr == 74fe48824a7c
- PlcBrowseRequest browseRequest = connection.browseRequestBuilder().addQuery("Browse", "").build();
- final PlcBrowseResponse browseResponse = browseRequest.execute().get();
+ //PlcBrowseRequest browseRequest = connection.browseRequestBuilder().addQuery("Browse", "").build();
+ //final PlcBrowseResponse browseResponse = browseRequest.execute().get();
PlcSubscriptionRequest.Builder builder = connection.subscriptionRequestBuilder();
- builder.addChangeOfStateTag("Input 4", ProfinetTag.of("simocodexbpn156e.1.1.Inputs.2:BOOL"));
+ builder.addChangeOfStateTag("Input 4", ProfinetTag.of("cdxb195b3.1.1.Inputs.2:BOOL"));
PlcSubscriptionRequest request = builder.build();
final PlcSubscriptionResponse response = request.execute().get();
diff --git a/plc4j/drivers/profinet/src/test/java/org/apache/plc4x/java/profinet/ProfinetCheckSumTests.java b/plc4j/drivers/profinet/src/test/java/org/apache/plc4x/java/profinet/ProfinetCheckSumTests.java
index 8eef7cbc66..7fe7bbf652 100644
--- a/plc4j/drivers/profinet/src/test/java/org/apache/plc4x/java/profinet/ProfinetCheckSumTests.java
+++ b/plc4j/drivers/profinet/src/test/java/org/apache/plc4x/java/profinet/ProfinetCheckSumTests.java
@@ -49,6 +49,7 @@ public class ProfinetCheckSumTests {
0,
0,
DceRpc_Operation.CONNECT,
+ (short) 0,
new PnIoCm_Packet_Req(
16696,
16696,
diff --git a/protocols/profinet/src/main/resources/protocols/profinet/dcerpc.mspec b/protocols/profinet/src/main/resources/protocols/profinet/dcerpc.mspec
index bed0d5c9bb..53064f2ac8 100644
--- a/protocols/profinet/src/main/resources/protocols/profinet/dcerpc.mspec
+++ b/protocols/profinet/src/main/resources/protocols/profinet/dcerpc.mspec
@@ -73,7 +73,8 @@
[const uint 8 authProto 0x00 ]
]
// RPCSerialLow 4.10.3.2.7
- [const uint 8 serialLow 0x00 ]
+ // REMARK: In general this would be a constant value of 0, but it seems that the PN device sends back PING packets which have non 0 values.
+ [simple uint 8 serialLow ]
// RPC Header }
// RPC Payload {
[simple PnIoCm_Packet('packetType') payload byteOrder='integerEncoding == IntegerEncoding.BIG_ENDIAN ? BIG_ENDIAN : LITTLE_ENDIAN' ]
diff --git a/protocols/profinet/src/main/resources/protocols/profinet/pnio.mspec b/protocols/profinet/src/main/resources/protocols/profinet/pnio.mspec
index d693830581..91e527e71b 100644
--- a/protocols/profinet/src/main/resources/protocols/profinet/pnio.mspec
+++ b/protocols/profinet/src/main/resources/protocols/profinet/pnio.mspec
@@ -59,6 +59,8 @@
['REJECT' PnIoCm_Packet_Rej
[simple uint 32 status ]
]
+ ['WORKING' PnIoCm_Packet_Working
+ ]
]
]