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 5c895a3004 feat(bacnet): refined BDT and FDT support
5c895a3004 is described below
commit 5c895a30046a96558a7dcefabab082ab303a7bf5
Author: Sebastian Rühl <[email protected]>
AuthorDate: Mon Apr 25 12:59:00 2022 +0200
feat(bacnet): refined BDT and FDT support
---
.../plc4go/bacnetip/readwrite/ParserHelper.go | 6 +-
.../plc4go/bacnetip/readwrite/XmlParserHelper.go | 6 +-
...y.go => BVLCBroadcastDistributionTableEntry.go} | 52 ++---
.../model/BVLCDeleteForeignDeviceTableEntry.go | 92 ++++++--
.../readwrite/model/BVLCForeignDeviceTableEntry.go | 240 +++++++++++++++++++++
.../model/BVLCReadBroadcastDistributionTableAck.go | 70 ++++--
.../model/BVLCReadForeignDeviceTableAck.go | 70 ++++--
.../model/BVLCWriteBroadcastDistributionTable.go | 12 +-
.../resources/protocols/bacnetip/bacnetip.mspec | 23 +-
9 files changed, 459 insertions(+), 112 deletions(-)
diff --git a/plc4go/internal/plc4go/bacnetip/readwrite/ParserHelper.go
b/plc4go/internal/plc4go/bacnetip/readwrite/ParserHelper.go
index c4da8997c2..7011aaa8cf 100644
--- a/plc4go/internal/plc4go/bacnetip/readwrite/ParserHelper.go
+++ b/plc4go/internal/plc4go/bacnetip/readwrite/ParserHelper.go
@@ -49,6 +49,8 @@ func (m BacnetipParserHelper) Parse(typeName string,
arguments []string, io util
return model.BACnetReadAccessPropertyErrorParse(io)
case "BACnetTagPayloadReal":
return model.BACnetTagPayloadRealParse(io)
+ case "BVLCForeignDeviceTableEntry":
+ return model.BVLCForeignDeviceTableEntryParse(io)
case "NLM":
apduLength, err := utils.StrToUint16(arguments[0])
if err != nil {
@@ -138,6 +140,8 @@ func (m BacnetipParserHelper) Parse(typeName string,
arguments []string, io util
return model.BVLCParse(io)
case "BACnetTagPayloadObjectIdentifier":
return model.BACnetTagPayloadObjectIdentifierParse(io)
+ case "BVLCBroadcastDistributionTableEntry":
+ return model.BVLCBroadcastDistributionTableEntryParse(io)
case "BACnetPropertyWriteDefinition":
objectType := model.BACnetObjectTypeByName(arguments[0])
return model.BACnetPropertyWriteDefinitionParse(io, objectType)
@@ -256,8 +260,6 @@ func (m BacnetipParserHelper) Parse(typeName string,
arguments []string, io util
return model.NPDUParse(io, npduLength)
case "BACnetPropertyReference":
return model.BACnetPropertyReferenceParse(io)
- case "BVLCWriteBroadcastDistributionTableEntry":
- return model.BVLCWriteBroadcastDistributionTableEntryParse(io)
}
return nil, errors.Errorf("Unsupported type %s", typeName)
}
diff --git a/plc4go/internal/plc4go/bacnetip/readwrite/XmlParserHelper.go
b/plc4go/internal/plc4go/bacnetip/readwrite/XmlParserHelper.go
index d500bbb87a..7e8c5b3364 100644
--- a/plc4go/internal/plc4go/bacnetip/readwrite/XmlParserHelper.go
+++ b/plc4go/internal/plc4go/bacnetip/readwrite/XmlParserHelper.go
@@ -61,6 +61,8 @@ func (m BacnetipXmlParserHelper) Parse(typeName string,
xmlString string, parser
return
model.BACnetReadAccessPropertyErrorParse(utils.NewXmlReadBuffer(strings.NewReader(xmlString)))
case "BACnetTagPayloadReal":
return
model.BACnetTagPayloadRealParse(utils.NewXmlReadBuffer(strings.NewReader(xmlString)))
+ case "BVLCForeignDeviceTableEntry":
+ return
model.BVLCForeignDeviceTableEntryParse(utils.NewXmlReadBuffer(strings.NewReader(xmlString)))
case "NLM":
parsedUint0, err := strconv.ParseUint(parserArguments[0], 10,
16)
if err != nil {
@@ -161,6 +163,8 @@ func (m BacnetipXmlParserHelper) Parse(typeName string,
xmlString string, parser
return
model.BVLCParse(utils.NewXmlReadBuffer(strings.NewReader(xmlString)))
case "BACnetTagPayloadObjectIdentifier":
return
model.BACnetTagPayloadObjectIdentifierParse(utils.NewXmlReadBuffer(strings.NewReader(xmlString)))
+ case "BVLCBroadcastDistributionTableEntry":
+ return
model.BVLCBroadcastDistributionTableEntryParse(utils.NewXmlReadBuffer(strings.NewReader(xmlString)))
case "BACnetPropertyWriteDefinition":
objectType := model.BACnetObjectTypeByName(parserArguments[0])
return
model.BACnetPropertyWriteDefinitionParse(utils.NewXmlReadBuffer(strings.NewReader(xmlString)),
objectType)
@@ -295,8 +299,6 @@ func (m BacnetipXmlParserHelper) Parse(typeName string,
xmlString string, parser
return
model.NPDUParse(utils.NewXmlReadBuffer(strings.NewReader(xmlString)),
npduLength)
case "BACnetPropertyReference":
return
model.BACnetPropertyReferenceParse(utils.NewXmlReadBuffer(strings.NewReader(xmlString)))
- case "BVLCWriteBroadcastDistributionTableEntry":
- return
model.BVLCWriteBroadcastDistributionTableEntryParse(utils.NewXmlReadBuffer(strings.NewReader(xmlString)))
}
return nil, errors.Errorf("Unsupported type %s", typeName)
}
diff --git
a/plc4go/internal/plc4go/bacnetip/readwrite/model/BVLCWriteBroadcastDistributionTableEntry.go
b/plc4go/internal/plc4go/bacnetip/readwrite/model/BVLCBroadcastDistributionTableEntry.go
similarity index 69%
rename from
plc4go/internal/plc4go/bacnetip/readwrite/model/BVLCWriteBroadcastDistributionTableEntry.go
rename to
plc4go/internal/plc4go/bacnetip/readwrite/model/BVLCBroadcastDistributionTableEntry.go
index 7eff557d3e..b54928d83a 100644
---
a/plc4go/internal/plc4go/bacnetip/readwrite/model/BVLCWriteBroadcastDistributionTableEntry.go
+++
b/plc4go/internal/plc4go/bacnetip/readwrite/model/BVLCBroadcastDistributionTableEntry.go
@@ -26,15 +26,15 @@ import (
// Code generated by code-generation. DO NOT EDIT.
-// BVLCWriteBroadcastDistributionTableEntry is the data-structure of this
message
-type BVLCWriteBroadcastDistributionTableEntry struct {
+// BVLCBroadcastDistributionTableEntry is the data-structure of this message
+type BVLCBroadcastDistributionTableEntry struct {
Ip []uint8
Port uint16
BroadcastDistributionMap []uint8
}
-// IBVLCWriteBroadcastDistributionTableEntry is the corresponding interface of
BVLCWriteBroadcastDistributionTableEntry
-type IBVLCWriteBroadcastDistributionTableEntry interface {
+// IBVLCBroadcastDistributionTableEntry is the corresponding interface of
BVLCBroadcastDistributionTableEntry
+type IBVLCBroadcastDistributionTableEntry interface {
// GetIp returns Ip (property field)
GetIp() []uint8
// GetPort returns Port (property field)
@@ -54,15 +54,15 @@ type IBVLCWriteBroadcastDistributionTableEntry interface {
/////////////////////// Accessors for property fields.
///////////////////////
-func (m *BVLCWriteBroadcastDistributionTableEntry) GetIp() []uint8 {
+func (m *BVLCBroadcastDistributionTableEntry) GetIp() []uint8 {
return m.Ip
}
-func (m *BVLCWriteBroadcastDistributionTableEntry) GetPort() uint16 {
+func (m *BVLCBroadcastDistributionTableEntry) GetPort() uint16 {
return m.Port
}
-func (m *BVLCWriteBroadcastDistributionTableEntry)
GetBroadcastDistributionMap() []uint8 {
+func (m *BVLCBroadcastDistributionTableEntry) GetBroadcastDistributionMap()
[]uint8 {
return m.BroadcastDistributionMap
}
@@ -71,30 +71,30 @@ func (m *BVLCWriteBroadcastDistributionTableEntry)
GetBroadcastDistributionMap()
///////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////
-// NewBVLCWriteBroadcastDistributionTableEntry factory function for
BVLCWriteBroadcastDistributionTableEntry
-func NewBVLCWriteBroadcastDistributionTableEntry(ip []uint8, port uint16,
broadcastDistributionMap []uint8) *BVLCWriteBroadcastDistributionTableEntry {
- return &BVLCWriteBroadcastDistributionTableEntry{Ip: ip, Port: port,
BroadcastDistributionMap: broadcastDistributionMap}
+// NewBVLCBroadcastDistributionTableEntry factory function for
BVLCBroadcastDistributionTableEntry
+func NewBVLCBroadcastDistributionTableEntry(ip []uint8, port uint16,
broadcastDistributionMap []uint8) *BVLCBroadcastDistributionTableEntry {
+ return &BVLCBroadcastDistributionTableEntry{Ip: ip, Port: port,
BroadcastDistributionMap: broadcastDistributionMap}
}
-func CastBVLCWriteBroadcastDistributionTableEntry(structType interface{})
*BVLCWriteBroadcastDistributionTableEntry {
- if casted, ok := structType.(BVLCWriteBroadcastDistributionTableEntry);
ok {
+func CastBVLCBroadcastDistributionTableEntry(structType interface{})
*BVLCBroadcastDistributionTableEntry {
+ if casted, ok := structType.(BVLCBroadcastDistributionTableEntry); ok {
return &casted
}
- if casted, ok :=
structType.(*BVLCWriteBroadcastDistributionTableEntry); ok {
+ if casted, ok := structType.(*BVLCBroadcastDistributionTableEntry); ok {
return casted
}
return nil
}
-func (m *BVLCWriteBroadcastDistributionTableEntry) GetTypeName() string {
- return "BVLCWriteBroadcastDistributionTableEntry"
+func (m *BVLCBroadcastDistributionTableEntry) GetTypeName() string {
+ return "BVLCBroadcastDistributionTableEntry"
}
-func (m *BVLCWriteBroadcastDistributionTableEntry) GetLengthInBits() uint16 {
+func (m *BVLCBroadcastDistributionTableEntry) GetLengthInBits() uint16 {
return m.GetLengthInBitsConditional(false)
}
-func (m *BVLCWriteBroadcastDistributionTableEntry)
GetLengthInBitsConditional(lastItem bool) uint16 {
+func (m *BVLCBroadcastDistributionTableEntry)
GetLengthInBitsConditional(lastItem bool) uint16 {
lengthInBits := uint16(0)
// Array field
@@ -113,12 +113,12 @@ func (m *BVLCWriteBroadcastDistributionTableEntry)
GetLengthInBitsConditional(la
return lengthInBits
}
-func (m *BVLCWriteBroadcastDistributionTableEntry) GetLengthInBytes() uint16 {
+func (m *BVLCBroadcastDistributionTableEntry) GetLengthInBytes() uint16 {
return m.GetLengthInBits() / 8
}
-func BVLCWriteBroadcastDistributionTableEntryParse(readBuffer
utils.ReadBuffer) (*BVLCWriteBroadcastDistributionTableEntry, error) {
- if pullErr :=
readBuffer.PullContext("BVLCWriteBroadcastDistributionTableEntry"); pullErr !=
nil {
+func BVLCBroadcastDistributionTableEntryParse(readBuffer utils.ReadBuffer)
(*BVLCBroadcastDistributionTableEntry, error) {
+ if pullErr :=
readBuffer.PullContext("BVLCBroadcastDistributionTableEntry"); pullErr != nil {
return nil, pullErr
}
currentPos := readBuffer.GetPos()
@@ -169,16 +169,16 @@ func
BVLCWriteBroadcastDistributionTableEntryParse(readBuffer utils.ReadBuffer)
return nil, closeErr
}
- if closeErr :=
readBuffer.CloseContext("BVLCWriteBroadcastDistributionTableEntry"); closeErr
!= nil {
+ if closeErr :=
readBuffer.CloseContext("BVLCBroadcastDistributionTableEntry"); closeErr != nil
{
return nil, closeErr
}
// Create the instance
- return NewBVLCWriteBroadcastDistributionTableEntry(ip, port,
broadcastDistributionMap), nil
+ return NewBVLCBroadcastDistributionTableEntry(ip, port,
broadcastDistributionMap), nil
}
-func (m *BVLCWriteBroadcastDistributionTableEntry) Serialize(writeBuffer
utils.WriteBuffer) error {
- if pushErr :=
writeBuffer.PushContext("BVLCWriteBroadcastDistributionTableEntry"); pushErr !=
nil {
+func (m *BVLCBroadcastDistributionTableEntry) Serialize(writeBuffer
utils.WriteBuffer) error {
+ if pushErr :=
writeBuffer.PushContext("BVLCBroadcastDistributionTableEntry"); pushErr != nil {
return pushErr
}
@@ -221,13 +221,13 @@ func (m *BVLCWriteBroadcastDistributionTableEntry)
Serialize(writeBuffer utils.W
}
}
- if popErr :=
writeBuffer.PopContext("BVLCWriteBroadcastDistributionTableEntry"); popErr !=
nil {
+ if popErr :=
writeBuffer.PopContext("BVLCBroadcastDistributionTableEntry"); popErr != nil {
return popErr
}
return nil
}
-func (m *BVLCWriteBroadcastDistributionTableEntry) String() string {
+func (m *BVLCBroadcastDistributionTableEntry) String() string {
if m == nil {
return "<nil>"
}
diff --git
a/plc4go/internal/plc4go/bacnetip/readwrite/model/BVLCDeleteForeignDeviceTableEntry.go
b/plc4go/internal/plc4go/bacnetip/readwrite/model/BVLCDeleteForeignDeviceTableEntry.go
index b4c15e2074..8261ef4794 100644
---
a/plc4go/internal/plc4go/bacnetip/readwrite/model/BVLCDeleteForeignDeviceTableEntry.go
+++
b/plc4go/internal/plc4go/bacnetip/readwrite/model/BVLCDeleteForeignDeviceTableEntry.go
@@ -29,14 +29,17 @@ import (
// BVLCDeleteForeignDeviceTableEntry is the data-structure of this message
type BVLCDeleteForeignDeviceTableEntry struct {
*BVLC
- FdtEntry []byte
+ Ip []uint8
+ Port uint16
}
// IBVLCDeleteForeignDeviceTableEntry is the corresponding interface of
BVLCDeleteForeignDeviceTableEntry
type IBVLCDeleteForeignDeviceTableEntry interface {
IBVLC
- // GetFdtEntry returns FdtEntry (property field)
- GetFdtEntry() []byte
+ // GetIp returns Ip (property field)
+ GetIp() []uint8
+ // GetPort returns Port (property field)
+ GetPort() uint16
// GetLengthInBytes returns the length in bytes
GetLengthInBytes() uint16
// GetLengthInBits returns the length in bits
@@ -70,8 +73,12 @@ func (m *BVLCDeleteForeignDeviceTableEntry) GetParent()
*BVLC {
/////////////////////// Accessors for property fields.
///////////////////////
-func (m *BVLCDeleteForeignDeviceTableEntry) GetFdtEntry() []byte {
- return m.FdtEntry
+func (m *BVLCDeleteForeignDeviceTableEntry) GetIp() []uint8 {
+ return m.Ip
+}
+
+func (m *BVLCDeleteForeignDeviceTableEntry) GetPort() uint16 {
+ return m.Port
}
///////////////////////
@@ -80,10 +87,11 @@ func (m *BVLCDeleteForeignDeviceTableEntry) GetFdtEntry()
[]byte {
///////////////////////////////////////////////////////////
// NewBVLCDeleteForeignDeviceTableEntry factory function for
BVLCDeleteForeignDeviceTableEntry
-func NewBVLCDeleteForeignDeviceTableEntry(fdtEntry []byte)
*BVLCDeleteForeignDeviceTableEntry {
+func NewBVLCDeleteForeignDeviceTableEntry(ip []uint8, port uint16)
*BVLCDeleteForeignDeviceTableEntry {
_result := &BVLCDeleteForeignDeviceTableEntry{
- FdtEntry: fdtEntry,
- BVLC: NewBVLC(),
+ Ip: ip,
+ Port: port,
+ BVLC: NewBVLC(),
}
_result.Child = _result
return _result
@@ -117,10 +125,13 @@ func (m *BVLCDeleteForeignDeviceTableEntry)
GetLengthInBitsConditional(lastItem
lengthInBits := uint16(m.GetParentLengthInBits())
// Array field
- if len(m.FdtEntry) > 0 {
- lengthInBits += 8 * uint16(len(m.FdtEntry))
+ if len(m.Ip) > 0 {
+ lengthInBits += 8 * uint16(len(m.Ip))
}
+ // Simple field (port)
+ lengthInBits += 16
+
return lengthInBits
}
@@ -134,12 +145,32 @@ func BVLCDeleteForeignDeviceTableEntryParse(readBuffer
utils.ReadBuffer) (*BVLCD
}
currentPos := readBuffer.GetPos()
_ = currentPos
- // Byte Array field (fdtEntry)
- numberOfBytesfdtEntry := int(uint16(6))
- fdtEntry, _readArrayErr := readBuffer.ReadByteArray("fdtEntry",
numberOfBytesfdtEntry)
- if _readArrayErr != nil {
- return nil, errors.Wrap(_readArrayErr, "Error parsing
'fdtEntry' field")
+
+ // Array field (ip)
+ if pullErr := readBuffer.PullContext("ip",
utils.WithRenderAsList(true)); pullErr != nil {
+ return nil, pullErr
+ }
+ // Count array
+ ip := make([]uint8, uint16(4))
+ {
+ for curItem := uint16(0); curItem < uint16(uint16(4));
curItem++ {
+ _item, _err := readBuffer.ReadUint8("", 8)
+ if _err != nil {
+ return nil, errors.Wrap(_err, "Error parsing
'ip' field")
+ }
+ ip[curItem] = _item
+ }
}
+ if closeErr := readBuffer.CloseContext("ip",
utils.WithRenderAsList(true)); closeErr != nil {
+ return nil, closeErr
+ }
+
+ // Simple Field (port)
+ _port, _portErr := readBuffer.ReadUint16("port", 16)
+ if _portErr != nil {
+ return nil, errors.Wrap(_portErr, "Error parsing 'port' field")
+ }
+ port := _port
if closeErr :=
readBuffer.CloseContext("BVLCDeleteForeignDeviceTableEntry"); closeErr != nil {
return nil, closeErr
@@ -147,8 +178,9 @@ func BVLCDeleteForeignDeviceTableEntryParse(readBuffer
utils.ReadBuffer) (*BVLCD
// Create a partially initialized instance
_child := &BVLCDeleteForeignDeviceTableEntry{
- FdtEntry: fdtEntry,
- BVLC: &BVLC{},
+ Ip: ip,
+ Port: port,
+ BVLC: &BVLC{},
}
_child.BVLC.Child = _child
return _child, nil
@@ -160,13 +192,27 @@ func (m *BVLCDeleteForeignDeviceTableEntry)
Serialize(writeBuffer utils.WriteBuf
return pushErr
}
- // Array Field (fdtEntry)
- if m.FdtEntry != nil {
- // Byte Array field (fdtEntry)
- _writeArrayErr :=
writeBuffer.WriteByteArray("fdtEntry", m.FdtEntry)
- if _writeArrayErr != nil {
- return errors.Wrap(_writeArrayErr, "Error
serializing 'fdtEntry' field")
+ // Array Field (ip)
+ if m.Ip != nil {
+ if pushErr := writeBuffer.PushContext("ip",
utils.WithRenderAsList(true)); pushErr != nil {
+ return pushErr
}
+ for _, _element := range m.Ip {
+ _elementErr := writeBuffer.WriteUint8("", 8,
_element)
+ if _elementErr != nil {
+ return errors.Wrap(_elementErr, "Error
serializing 'ip' field")
+ }
+ }
+ if popErr := writeBuffer.PopContext("ip",
utils.WithRenderAsList(true)); popErr != nil {
+ return popErr
+ }
+ }
+
+ // Simple Field (port)
+ port := uint16(m.Port)
+ _portErr := writeBuffer.WriteUint16("port", 16, (port))
+ if _portErr != nil {
+ return errors.Wrap(_portErr, "Error serializing 'port'
field")
}
if popErr :=
writeBuffer.PopContext("BVLCDeleteForeignDeviceTableEntry"); popErr != nil {
diff --git
a/plc4go/internal/plc4go/bacnetip/readwrite/model/BVLCForeignDeviceTableEntry.go
b/plc4go/internal/plc4go/bacnetip/readwrite/model/BVLCForeignDeviceTableEntry.go
new file mode 100644
index 0000000000..f737e0dd4f
--- /dev/null
+++
b/plc4go/internal/plc4go/bacnetip/readwrite/model/BVLCForeignDeviceTableEntry.go
@@ -0,0 +1,240 @@
+/*
+ * 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
+ *
+ * http://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 (
+ "github.com/apache/plc4x/plc4go/internal/plc4go/spi/utils"
+ "github.com/pkg/errors"
+)
+
+// Code generated by code-generation. DO NOT EDIT.
+
+// BVLCForeignDeviceTableEntry is the data-structure of this message
+type BVLCForeignDeviceTableEntry struct {
+ Ip []uint8
+ Port uint16
+ Ttl uint16
+ SecondRemainingBeforePurge uint16
+}
+
+// IBVLCForeignDeviceTableEntry is the corresponding interface of
BVLCForeignDeviceTableEntry
+type IBVLCForeignDeviceTableEntry interface {
+ // GetIp returns Ip (property field)
+ GetIp() []uint8
+ // GetPort returns Port (property field)
+ GetPort() uint16
+ // GetTtl returns Ttl (property field)
+ GetTtl() uint16
+ // GetSecondRemainingBeforePurge returns SecondRemainingBeforePurge
(property field)
+ GetSecondRemainingBeforePurge() uint16
+ // GetLengthInBytes returns the length in bytes
+ GetLengthInBytes() uint16
+ // GetLengthInBits returns the length in bits
+ GetLengthInBits() uint16
+ // Serialize serializes this type
+ Serialize(writeBuffer utils.WriteBuffer) error
+}
+
+///////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////
+/////////////////////// Accessors for property fields.
+///////////////////////
+
+func (m *BVLCForeignDeviceTableEntry) GetIp() []uint8 {
+ return m.Ip
+}
+
+func (m *BVLCForeignDeviceTableEntry) GetPort() uint16 {
+ return m.Port
+}
+
+func (m *BVLCForeignDeviceTableEntry) GetTtl() uint16 {
+ return m.Ttl
+}
+
+func (m *BVLCForeignDeviceTableEntry) GetSecondRemainingBeforePurge() uint16 {
+ return m.SecondRemainingBeforePurge
+}
+
+///////////////////////
+///////////////////////
+///////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////
+
+// NewBVLCForeignDeviceTableEntry factory function for
BVLCForeignDeviceTableEntry
+func NewBVLCForeignDeviceTableEntry(ip []uint8, port uint16, ttl uint16,
secondRemainingBeforePurge uint16) *BVLCForeignDeviceTableEntry {
+ return &BVLCForeignDeviceTableEntry{Ip: ip, Port: port, Ttl: ttl,
SecondRemainingBeforePurge: secondRemainingBeforePurge}
+}
+
+func CastBVLCForeignDeviceTableEntry(structType interface{})
*BVLCForeignDeviceTableEntry {
+ if casted, ok := structType.(BVLCForeignDeviceTableEntry); ok {
+ return &casted
+ }
+ if casted, ok := structType.(*BVLCForeignDeviceTableEntry); ok {
+ return casted
+ }
+ return nil
+}
+
+func (m *BVLCForeignDeviceTableEntry) GetTypeName() string {
+ return "BVLCForeignDeviceTableEntry"
+}
+
+func (m *BVLCForeignDeviceTableEntry) GetLengthInBits() uint16 {
+ return m.GetLengthInBitsConditional(false)
+}
+
+func (m *BVLCForeignDeviceTableEntry) GetLengthInBitsConditional(lastItem
bool) uint16 {
+ lengthInBits := uint16(0)
+
+ // Array field
+ if len(m.Ip) > 0 {
+ lengthInBits += 8 * uint16(len(m.Ip))
+ }
+
+ // Simple field (port)
+ lengthInBits += 16
+
+ // Simple field (ttl)
+ lengthInBits += 16
+
+ // Simple field (secondRemainingBeforePurge)
+ lengthInBits += 16
+
+ return lengthInBits
+}
+
+func (m *BVLCForeignDeviceTableEntry) GetLengthInBytes() uint16 {
+ return m.GetLengthInBits() / 8
+}
+
+func BVLCForeignDeviceTableEntryParse(readBuffer utils.ReadBuffer)
(*BVLCForeignDeviceTableEntry, error) {
+ if pullErr := readBuffer.PullContext("BVLCForeignDeviceTableEntry");
pullErr != nil {
+ return nil, pullErr
+ }
+ currentPos := readBuffer.GetPos()
+ _ = currentPos
+
+ // Array field (ip)
+ if pullErr := readBuffer.PullContext("ip",
utils.WithRenderAsList(true)); pullErr != nil {
+ return nil, pullErr
+ }
+ // Count array
+ ip := make([]uint8, uint16(4))
+ {
+ for curItem := uint16(0); curItem < uint16(uint16(4));
curItem++ {
+ _item, _err := readBuffer.ReadUint8("", 8)
+ if _err != nil {
+ return nil, errors.Wrap(_err, "Error parsing
'ip' field")
+ }
+ ip[curItem] = _item
+ }
+ }
+ if closeErr := readBuffer.CloseContext("ip",
utils.WithRenderAsList(true)); closeErr != nil {
+ return nil, closeErr
+ }
+
+ // Simple Field (port)
+ _port, _portErr := readBuffer.ReadUint16("port", 16)
+ if _portErr != nil {
+ return nil, errors.Wrap(_portErr, "Error parsing 'port' field")
+ }
+ port := _port
+
+ // Simple Field (ttl)
+ _ttl, _ttlErr := readBuffer.ReadUint16("ttl", 16)
+ if _ttlErr != nil {
+ return nil, errors.Wrap(_ttlErr, "Error parsing 'ttl' field")
+ }
+ ttl := _ttl
+
+ // Simple Field (secondRemainingBeforePurge)
+ _secondRemainingBeforePurge, _secondRemainingBeforePurgeErr :=
readBuffer.ReadUint16("secondRemainingBeforePurge", 16)
+ if _secondRemainingBeforePurgeErr != nil {
+ return nil, errors.Wrap(_secondRemainingBeforePurgeErr, "Error
parsing 'secondRemainingBeforePurge' field")
+ }
+ secondRemainingBeforePurge := _secondRemainingBeforePurge
+
+ if closeErr := readBuffer.CloseContext("BVLCForeignDeviceTableEntry");
closeErr != nil {
+ return nil, closeErr
+ }
+
+ // Create the instance
+ return NewBVLCForeignDeviceTableEntry(ip, port, ttl,
secondRemainingBeforePurge), nil
+}
+
+func (m *BVLCForeignDeviceTableEntry) Serialize(writeBuffer utils.WriteBuffer)
error {
+ if pushErr := writeBuffer.PushContext("BVLCForeignDeviceTableEntry");
pushErr != nil {
+ return pushErr
+ }
+
+ // Array Field (ip)
+ if m.Ip != nil {
+ if pushErr := writeBuffer.PushContext("ip",
utils.WithRenderAsList(true)); pushErr != nil {
+ return pushErr
+ }
+ for _, _element := range m.Ip {
+ _elementErr := writeBuffer.WriteUint8("", 8, _element)
+ if _elementErr != nil {
+ return errors.Wrap(_elementErr, "Error
serializing 'ip' field")
+ }
+ }
+ if popErr := writeBuffer.PopContext("ip",
utils.WithRenderAsList(true)); popErr != nil {
+ return popErr
+ }
+ }
+
+ // Simple Field (port)
+ port := uint16(m.Port)
+ _portErr := writeBuffer.WriteUint16("port", 16, (port))
+ if _portErr != nil {
+ return errors.Wrap(_portErr, "Error serializing 'port' field")
+ }
+
+ // Simple Field (ttl)
+ ttl := uint16(m.Ttl)
+ _ttlErr := writeBuffer.WriteUint16("ttl", 16, (ttl))
+ if _ttlErr != nil {
+ return errors.Wrap(_ttlErr, "Error serializing 'ttl' field")
+ }
+
+ // Simple Field (secondRemainingBeforePurge)
+ secondRemainingBeforePurge := uint16(m.SecondRemainingBeforePurge)
+ _secondRemainingBeforePurgeErr :=
writeBuffer.WriteUint16("secondRemainingBeforePurge", 16,
(secondRemainingBeforePurge))
+ if _secondRemainingBeforePurgeErr != nil {
+ return errors.Wrap(_secondRemainingBeforePurgeErr, "Error
serializing 'secondRemainingBeforePurge' field")
+ }
+
+ if popErr := writeBuffer.PopContext("BVLCForeignDeviceTableEntry");
popErr != nil {
+ return popErr
+ }
+ return nil
+}
+
+func (m *BVLCForeignDeviceTableEntry) String() string {
+ if m == nil {
+ return "<nil>"
+ }
+ buffer := utils.NewBoxedWriteBufferWithOptions(true, true)
+ if err := m.Serialize(buffer); err != nil {
+ return err.Error()
+ }
+ return buffer.GetBox().String()
+}
diff --git
a/plc4go/internal/plc4go/bacnetip/readwrite/model/BVLCReadBroadcastDistributionTableAck.go
b/plc4go/internal/plc4go/bacnetip/readwrite/model/BVLCReadBroadcastDistributionTableAck.go
index abc0aad10a..edc4b0bbf8 100644
---
a/plc4go/internal/plc4go/bacnetip/readwrite/model/BVLCReadBroadcastDistributionTableAck.go
+++
b/plc4go/internal/plc4go/bacnetip/readwrite/model/BVLCReadBroadcastDistributionTableAck.go
@@ -29,7 +29,7 @@ import (
// BVLCReadBroadcastDistributionTableAck is the data-structure of this message
type BVLCReadBroadcastDistributionTableAck struct {
*BVLC
- BdtEntries []byte
+ Table []*BVLCBroadcastDistributionTableEntry
// Arguments.
BvlcPayloadLength uint16
@@ -38,8 +38,8 @@ type BVLCReadBroadcastDistributionTableAck struct {
// IBVLCReadBroadcastDistributionTableAck is the corresponding interface of
BVLCReadBroadcastDistributionTableAck
type IBVLCReadBroadcastDistributionTableAck interface {
IBVLC
- // GetBdtEntries returns BdtEntries (property field)
- GetBdtEntries() []byte
+ // GetTable returns Table (property field)
+ GetTable() []*BVLCBroadcastDistributionTableEntry
// GetLengthInBytes returns the length in bytes
GetLengthInBytes() uint16
// GetLengthInBits returns the length in bits
@@ -73,8 +73,8 @@ func (m *BVLCReadBroadcastDistributionTableAck) GetParent()
*BVLC {
/////////////////////// Accessors for property fields.
///////////////////////
-func (m *BVLCReadBroadcastDistributionTableAck) GetBdtEntries() []byte {
- return m.BdtEntries
+func (m *BVLCReadBroadcastDistributionTableAck) GetTable()
[]*BVLCBroadcastDistributionTableEntry {
+ return m.Table
}
///////////////////////
@@ -83,10 +83,10 @@ func (m *BVLCReadBroadcastDistributionTableAck)
GetBdtEntries() []byte {
///////////////////////////////////////////////////////////
// NewBVLCReadBroadcastDistributionTableAck factory function for
BVLCReadBroadcastDistributionTableAck
-func NewBVLCReadBroadcastDistributionTableAck(bdtEntries []byte,
bvlcPayloadLength uint16) *BVLCReadBroadcastDistributionTableAck {
+func NewBVLCReadBroadcastDistributionTableAck(table
[]*BVLCBroadcastDistributionTableEntry, bvlcPayloadLength uint16)
*BVLCReadBroadcastDistributionTableAck {
_result := &BVLCReadBroadcastDistributionTableAck{
- BdtEntries: bdtEntries,
- BVLC: NewBVLC(),
+ Table: table,
+ BVLC: NewBVLC(),
}
_result.Child = _result
return _result
@@ -120,8 +120,10 @@ func (m *BVLCReadBroadcastDistributionTableAck)
GetLengthInBitsConditional(lastI
lengthInBits := uint16(m.GetParentLengthInBits())
// Array field
- if len(m.BdtEntries) > 0 {
- lengthInBits += 8 * uint16(len(m.BdtEntries))
+ if len(m.Table) > 0 {
+ for _, element := range m.Table {
+ lengthInBits += element.GetLengthInBits()
+ }
}
return lengthInBits
@@ -137,11 +139,26 @@ func
BVLCReadBroadcastDistributionTableAckParse(readBuffer utils.ReadBuffer, bvl
}
currentPos := readBuffer.GetPos()
_ = currentPos
- // Byte Array field (bdtEntries)
- numberOfBytesbdtEntries := int(bvlcPayloadLength)
- bdtEntries, _readArrayErr := readBuffer.ReadByteArray("bdtEntries",
numberOfBytesbdtEntries)
- if _readArrayErr != nil {
- return nil, errors.Wrap(_readArrayErr, "Error parsing
'bdtEntries' field")
+
+ // Array field (table)
+ if pullErr := readBuffer.PullContext("table",
utils.WithRenderAsList(true)); pullErr != nil {
+ return nil, pullErr
+ }
+ // Length array
+ table := make([]*BVLCBroadcastDistributionTableEntry, 0)
+ {
+ _tableLength := bvlcPayloadLength
+ _tableEndPos := readBuffer.GetPos() + uint16(_tableLength)
+ for readBuffer.GetPos() < _tableEndPos {
+ _item, _err :=
BVLCBroadcastDistributionTableEntryParse(readBuffer)
+ if _err != nil {
+ return nil, errors.Wrap(_err, "Error parsing
'table' field")
+ }
+ table = append(table, _item)
+ }
+ }
+ if closeErr := readBuffer.CloseContext("table",
utils.WithRenderAsList(true)); closeErr != nil {
+ return nil, closeErr
}
if closeErr :=
readBuffer.CloseContext("BVLCReadBroadcastDistributionTableAck"); closeErr !=
nil {
@@ -150,8 +167,8 @@ func BVLCReadBroadcastDistributionTableAckParse(readBuffer
utils.ReadBuffer, bvl
// Create a partially initialized instance
_child := &BVLCReadBroadcastDistributionTableAck{
- BdtEntries: bdtEntries,
- BVLC: &BVLC{},
+ Table: table,
+ BVLC: &BVLC{},
}
_child.BVLC.Child = _child
return _child, nil
@@ -163,12 +180,19 @@ func (m *BVLCReadBroadcastDistributionTableAck)
Serialize(writeBuffer utils.Writ
return pushErr
}
- // Array Field (bdtEntries)
- if m.BdtEntries != nil {
- // Byte Array field (bdtEntries)
- _writeArrayErr :=
writeBuffer.WriteByteArray("bdtEntries", m.BdtEntries)
- if _writeArrayErr != nil {
- return errors.Wrap(_writeArrayErr, "Error
serializing 'bdtEntries' field")
+ // Array Field (table)
+ if m.Table != nil {
+ if pushErr := writeBuffer.PushContext("table",
utils.WithRenderAsList(true)); pushErr != nil {
+ return pushErr
+ }
+ for _, _element := range m.Table {
+ _elementErr := _element.Serialize(writeBuffer)
+ if _elementErr != nil {
+ return errors.Wrap(_elementErr, "Error
serializing 'table' field")
+ }
+ }
+ if popErr := writeBuffer.PopContext("table",
utils.WithRenderAsList(true)); popErr != nil {
+ return popErr
}
}
diff --git
a/plc4go/internal/plc4go/bacnetip/readwrite/model/BVLCReadForeignDeviceTableAck.go
b/plc4go/internal/plc4go/bacnetip/readwrite/model/BVLCReadForeignDeviceTableAck.go
index 97229b5d9c..8722d60f3c 100644
---
a/plc4go/internal/plc4go/bacnetip/readwrite/model/BVLCReadForeignDeviceTableAck.go
+++
b/plc4go/internal/plc4go/bacnetip/readwrite/model/BVLCReadForeignDeviceTableAck.go
@@ -29,7 +29,7 @@ import (
// BVLCReadForeignDeviceTableAck is the data-structure of this message
type BVLCReadForeignDeviceTableAck struct {
*BVLC
- FdtEntries []byte
+ Table []*BVLCForeignDeviceTableEntry
// Arguments.
BvlcPayloadLength uint16
@@ -38,8 +38,8 @@ type BVLCReadForeignDeviceTableAck struct {
// IBVLCReadForeignDeviceTableAck is the corresponding interface of
BVLCReadForeignDeviceTableAck
type IBVLCReadForeignDeviceTableAck interface {
IBVLC
- // GetFdtEntries returns FdtEntries (property field)
- GetFdtEntries() []byte
+ // GetTable returns Table (property field)
+ GetTable() []*BVLCForeignDeviceTableEntry
// GetLengthInBytes returns the length in bytes
GetLengthInBytes() uint16
// GetLengthInBits returns the length in bits
@@ -73,8 +73,8 @@ func (m *BVLCReadForeignDeviceTableAck) GetParent() *BVLC {
/////////////////////// Accessors for property fields.
///////////////////////
-func (m *BVLCReadForeignDeviceTableAck) GetFdtEntries() []byte {
- return m.FdtEntries
+func (m *BVLCReadForeignDeviceTableAck) GetTable()
[]*BVLCForeignDeviceTableEntry {
+ return m.Table
}
///////////////////////
@@ -83,10 +83,10 @@ func (m *BVLCReadForeignDeviceTableAck) GetFdtEntries()
[]byte {
///////////////////////////////////////////////////////////
// NewBVLCReadForeignDeviceTableAck factory function for
BVLCReadForeignDeviceTableAck
-func NewBVLCReadForeignDeviceTableAck(fdtEntries []byte, bvlcPayloadLength
uint16) *BVLCReadForeignDeviceTableAck {
+func NewBVLCReadForeignDeviceTableAck(table []*BVLCForeignDeviceTableEntry,
bvlcPayloadLength uint16) *BVLCReadForeignDeviceTableAck {
_result := &BVLCReadForeignDeviceTableAck{
- FdtEntries: fdtEntries,
- BVLC: NewBVLC(),
+ Table: table,
+ BVLC: NewBVLC(),
}
_result.Child = _result
return _result
@@ -120,8 +120,10 @@ func (m *BVLCReadForeignDeviceTableAck)
GetLengthInBitsConditional(lastItem bool
lengthInBits := uint16(m.GetParentLengthInBits())
// Array field
- if len(m.FdtEntries) > 0 {
- lengthInBits += 8 * uint16(len(m.FdtEntries))
+ if len(m.Table) > 0 {
+ for _, element := range m.Table {
+ lengthInBits += element.GetLengthInBits()
+ }
}
return lengthInBits
@@ -137,11 +139,26 @@ func BVLCReadForeignDeviceTableAckParse(readBuffer
utils.ReadBuffer, bvlcPayload
}
currentPos := readBuffer.GetPos()
_ = currentPos
- // Byte Array field (fdtEntries)
- numberOfBytesfdtEntries := int(bvlcPayloadLength)
- fdtEntries, _readArrayErr := readBuffer.ReadByteArray("fdtEntries",
numberOfBytesfdtEntries)
- if _readArrayErr != nil {
- return nil, errors.Wrap(_readArrayErr, "Error parsing
'fdtEntries' field")
+
+ // Array field (table)
+ if pullErr := readBuffer.PullContext("table",
utils.WithRenderAsList(true)); pullErr != nil {
+ return nil, pullErr
+ }
+ // Length array
+ table := make([]*BVLCForeignDeviceTableEntry, 0)
+ {
+ _tableLength := bvlcPayloadLength
+ _tableEndPos := readBuffer.GetPos() + uint16(_tableLength)
+ for readBuffer.GetPos() < _tableEndPos {
+ _item, _err :=
BVLCForeignDeviceTableEntryParse(readBuffer)
+ if _err != nil {
+ return nil, errors.Wrap(_err, "Error parsing
'table' field")
+ }
+ table = append(table, _item)
+ }
+ }
+ if closeErr := readBuffer.CloseContext("table",
utils.WithRenderAsList(true)); closeErr != nil {
+ return nil, closeErr
}
if closeErr :=
readBuffer.CloseContext("BVLCReadForeignDeviceTableAck"); closeErr != nil {
@@ -150,8 +167,8 @@ func BVLCReadForeignDeviceTableAckParse(readBuffer
utils.ReadBuffer, bvlcPayload
// Create a partially initialized instance
_child := &BVLCReadForeignDeviceTableAck{
- FdtEntries: fdtEntries,
- BVLC: &BVLC{},
+ Table: table,
+ BVLC: &BVLC{},
}
_child.BVLC.Child = _child
return _child, nil
@@ -163,12 +180,19 @@ func (m *BVLCReadForeignDeviceTableAck)
Serialize(writeBuffer utils.WriteBuffer)
return pushErr
}
- // Array Field (fdtEntries)
- if m.FdtEntries != nil {
- // Byte Array field (fdtEntries)
- _writeArrayErr :=
writeBuffer.WriteByteArray("fdtEntries", m.FdtEntries)
- if _writeArrayErr != nil {
- return errors.Wrap(_writeArrayErr, "Error
serializing 'fdtEntries' field")
+ // Array Field (table)
+ if m.Table != nil {
+ if pushErr := writeBuffer.PushContext("table",
utils.WithRenderAsList(true)); pushErr != nil {
+ return pushErr
+ }
+ for _, _element := range m.Table {
+ _elementErr := _element.Serialize(writeBuffer)
+ if _elementErr != nil {
+ return errors.Wrap(_elementErr, "Error
serializing 'table' field")
+ }
+ }
+ if popErr := writeBuffer.PopContext("table",
utils.WithRenderAsList(true)); popErr != nil {
+ return popErr
}
}
diff --git
a/plc4go/internal/plc4go/bacnetip/readwrite/model/BVLCWriteBroadcastDistributionTable.go
b/plc4go/internal/plc4go/bacnetip/readwrite/model/BVLCWriteBroadcastDistributionTable.go
index 8673352acb..563ecf8420 100644
---
a/plc4go/internal/plc4go/bacnetip/readwrite/model/BVLCWriteBroadcastDistributionTable.go
+++
b/plc4go/internal/plc4go/bacnetip/readwrite/model/BVLCWriteBroadcastDistributionTable.go
@@ -29,7 +29,7 @@ import (
// BVLCWriteBroadcastDistributionTable is the data-structure of this message
type BVLCWriteBroadcastDistributionTable struct {
*BVLC
- Table []*BVLCWriteBroadcastDistributionTableEntry
+ Table []*BVLCBroadcastDistributionTableEntry
// Arguments.
BvlcPayloadLength uint16
@@ -39,7 +39,7 @@ type BVLCWriteBroadcastDistributionTable struct {
type IBVLCWriteBroadcastDistributionTable interface {
IBVLC
// GetTable returns Table (property field)
- GetTable() []*BVLCWriteBroadcastDistributionTableEntry
+ GetTable() []*BVLCBroadcastDistributionTableEntry
// GetLengthInBytes returns the length in bytes
GetLengthInBytes() uint16
// GetLengthInBits returns the length in bits
@@ -73,7 +73,7 @@ func (m *BVLCWriteBroadcastDistributionTable) GetParent()
*BVLC {
/////////////////////// Accessors for property fields.
///////////////////////
-func (m *BVLCWriteBroadcastDistributionTable) GetTable()
[]*BVLCWriteBroadcastDistributionTableEntry {
+func (m *BVLCWriteBroadcastDistributionTable) GetTable()
[]*BVLCBroadcastDistributionTableEntry {
return m.Table
}
@@ -83,7 +83,7 @@ func (m *BVLCWriteBroadcastDistributionTable) GetTable()
[]*BVLCWriteBroadcastDi
///////////////////////////////////////////////////////////
// NewBVLCWriteBroadcastDistributionTable factory function for
BVLCWriteBroadcastDistributionTable
-func NewBVLCWriteBroadcastDistributionTable(table
[]*BVLCWriteBroadcastDistributionTableEntry, bvlcPayloadLength uint16)
*BVLCWriteBroadcastDistributionTable {
+func NewBVLCWriteBroadcastDistributionTable(table
[]*BVLCBroadcastDistributionTableEntry, bvlcPayloadLength uint16)
*BVLCWriteBroadcastDistributionTable {
_result := &BVLCWriteBroadcastDistributionTable{
Table: table,
BVLC: NewBVLC(),
@@ -145,12 +145,12 @@ func BVLCWriteBroadcastDistributionTableParse(readBuffer
utils.ReadBuffer, bvlcP
return nil, pullErr
}
// Length array
- table := make([]*BVLCWriteBroadcastDistributionTableEntry, 0)
+ table := make([]*BVLCBroadcastDistributionTableEntry, 0)
{
_tableLength := bvlcPayloadLength
_tableEndPos := readBuffer.GetPos() + uint16(_tableLength)
for readBuffer.GetPos() < _tableEndPos {
- _item, _err :=
BVLCWriteBroadcastDistributionTableEntryParse(readBuffer)
+ _item, _err :=
BVLCBroadcastDistributionTableEntryParse(readBuffer)
if _err != nil {
return nil, errors.Wrap(_err, "Error parsing
'table' field")
}
diff --git
a/protocols/bacnetip/src/main/resources/protocols/bacnetip/bacnetip.mspec
b/protocols/bacnetip/src/main/resources/protocols/bacnetip/bacnetip.mspec
index 307fd3780c..4249dcc91f 100644
--- a/protocols/bacnetip/src/main/resources/protocols/bacnetip/bacnetip.mspec
+++ b/protocols/bacnetip/src/main/resources/protocols/bacnetip/bacnetip.mspec
@@ -28,14 +28,15 @@
code ]
]
['0x01' BVLCWriteBroadcastDistributionTable(uint 16 bvlcPayloadLength)
- [array BVLCWriteBroadcastDistributionTableEntry
+ [array BVLCBroadcastDistributionTableEntry
table
length 'bvlcPayloadLength' ]
]
['0x02' BVLCReadBroadcastDistributionTable
]
['0x03' BVLCReadBroadcastDistributionTableAck(uint 16
bvlcPayloadLength)
- [array byte bdtEntries
+ [array BVLCBroadcastDistributionTableEntry
+ table
length 'bvlcPayloadLength' ]
]
['0x04' BVLCForwardedNPDU(uint 16 bvlcPayloadLength)
@@ -50,12 +51,13 @@
['0x06' BVLCReadForeignDeviceTable
]
['0x07' BVLCReadForeignDeviceTableAck(uint 16 bvlcPayloadLength)
- [array byte fdtEntries
- length 'bvlcPayloadLength' ]
+ [array BVLCForeignDeviceTableEntry
+ table
+ length 'bvlcPayloadLength' ]
]
['0x08' BVLCDeleteForeignDeviceTableEntry
- [array byte fdtEntry
- count '6']
+ [array uint 8 ip count '4' ]
+ [simple uint 16 port ]
]
['0x09' BVLCDistributeBroadcastToNetwork(uint 16 bvlcPayloadLength)
[simple NPDU('bvlcPayloadLength')
@@ -76,12 +78,19 @@
]
]
-[type BVLCWriteBroadcastDistributionTableEntry
+[type BVLCBroadcastDistributionTableEntry
[array uint 8 ip count '4' ]
[simple uint 16 port ]
[array uint 8 broadcastDistributionMap count '4' ]
]
+[type BVLCForeignDeviceTableEntry
+ [array uint 8 ip count '4' ]
+ [simple uint 16 port ]
+ [simple uint 16 ttl ]
+ [simple uint 16 secondRemainingBeforePurge ]
+]
+
[type NPDU(uint 16 npduLength)
[simple uint 8 protocolVersionNumber
]
[simple NPDUControl control
]