Skip to content

Commit c5d0cbd

Browse files
committed
feat(plc4go/bacnetip): ReadBroadcastDistributionTableAck
1 parent 6e237f2 commit c5d0cbd

File tree

3 files changed

+144
-14
lines changed

3 files changed

+144
-14
lines changed

plc4go/internal/bacnetip/bvll.go

Lines changed: 84 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -286,7 +286,7 @@ func NewWriteBroadcastDistributionTable(opts ...func(*WriteBroadcastDistribution
286286
return b, nil
287287
}
288288

289-
func WithWriteBroadcastDistributionTable(bdt ...*Address) func(*WriteBroadcastDistributionTable) {
289+
func WithWriteBroadcastDistributionTableBDT(bdt ...*Address) func(*WriteBroadcastDistributionTable) {
290290
return func(b *WriteBroadcastDistributionTable) {
291291
b.bvlciBDT = bdt
292292
}
@@ -417,27 +417,101 @@ func (w *ReadBroadcastDistributionTable) String() string {
417417
return fmt.Sprintf("ReadBroadcastDistributionTable{%v}", w._BVLPDU)
418418
}
419419

420-
// TODO: finish
421420
type ReadBroadcastDistributionTableAck struct {
422421
*_BVLPDU
422+
bvlciBDT []*Address
423423
}
424424

425425
var _ BVLPDU = (*ReadBroadcastDistributionTableAck)(nil)
426426

427-
func NewReadBroadcastDistributionTableAck() (BVLPDU, error) {
427+
func NewReadBroadcastDistributionTableAck(opts ...func(*ReadBroadcastDistributionTableAck)) (*ReadBroadcastDistributionTableAck, error) {
428428
b := &ReadBroadcastDistributionTableAck{}
429-
b._BVLPDU = NewBVLPDU(nil).(*_BVLPDU)
429+
for _, opt := range opts {
430+
opt(b)
431+
}
432+
b._BVLPDU = NewBVLPDU(readWriteModel.NewBVLCReadBroadcastDistributionTableAck(b.produceBroadcastDistributionTable(), 0)).(*_BVLPDU)
430433
return b, nil
431434
}
432435

433-
func (b *ReadBroadcastDistributionTableAck) Encode(pdu Arg) error {
434-
// TODO: finish
435-
return nil
436+
func WithReadBroadcastDistributionTableAckBDT(bdt ...*Address) func(*ReadBroadcastDistributionTableAck) {
437+
return func(b *ReadBroadcastDistributionTableAck) {
438+
b.bvlciBDT = bdt
439+
}
436440
}
437441

438-
func (b *ReadBroadcastDistributionTableAck) Decode(pdu Arg) error {
439-
// TODO: finish
440-
return nil
442+
func (w *ReadBroadcastDistributionTableAck) GetBvlciBDT() []*Address {
443+
return w.bvlciBDT
444+
}
445+
446+
func (w *ReadBroadcastDistributionTableAck) produceBroadcastDistributionTable() (entries []readWriteModel.BVLCBroadcastDistributionTableEntry) {
447+
for _, address := range w.bvlciBDT {
448+
addr := address.AddrAddress[:4]
449+
port := uint16(47808)
450+
if address.AddrPort != nil {
451+
port = *address.AddrPort
452+
}
453+
mask := make([]byte, 4)
454+
if address.AddrMask != nil {
455+
binary.BigEndian.PutUint32(mask, *address.AddrMask)
456+
}
457+
entries = append(entries, readWriteModel.NewBVLCBroadcastDistributionTableEntry(addr, port, mask))
458+
}
459+
return
460+
}
461+
462+
func (w *ReadBroadcastDistributionTableAck) produceBvlciBDT(entries []readWriteModel.BVLCBroadcastDistributionTableEntry) (bvlciBDT []*Address) {
463+
for _, entry := range entries {
464+
addr := entry.GetIp()
465+
port := entry.GetPort()
466+
var portArray = make([]byte, 2)
467+
binary.BigEndian.PutUint16(portArray, port)
468+
address, _ := NewAddress(zerolog.Nop(), append(addr, portArray...))
469+
mask := binary.BigEndian.Uint32(entry.GetBroadcastDistributionMap())
470+
address.AddrMask = &mask
471+
bvlciBDT = append(bvlciBDT, address)
472+
}
473+
return
474+
}
475+
476+
func (w *ReadBroadcastDistributionTableAck) Encode(bvlpdu Arg) error {
477+
switch bvlpdu := bvlpdu.(type) {
478+
case BVLPDU:
479+
if err := bvlpdu.Update(w); err != nil {
480+
return errors.Wrap(err, "error updating BVLPDU")
481+
}
482+
for _, bdte := range w.bvlciBDT {
483+
bvlpdu.PutData(bdte.AddrAddress...)
484+
bvlpdu.PutLong(*bdte.AddrMask)
485+
}
486+
bvlpdu.setBVLC(w.bvlc)
487+
return nil
488+
default:
489+
return errors.Errorf("invalid BVLPDU type %T", bvlpdu)
490+
}
491+
}
492+
493+
func (w *ReadBroadcastDistributionTableAck) Decode(bvlpdu Arg) error {
494+
switch bvlpdu := bvlpdu.(type) {
495+
case BVLPDU:
496+
if err := w.Update(bvlpdu); err != nil {
497+
return errors.Wrap(err, "error updating BVLPDU")
498+
}
499+
switch pduUserData := bvlpdu.GetPDUUserData().(type) {
500+
case readWriteModel.BVLCReadBroadcastDistributionTableAckExactly:
501+
switch bvlc := pduUserData.(type) {
502+
case readWriteModel.BVLCReadBroadcastDistributionTableAck:
503+
w.setBVLC(bvlc)
504+
w.bvlciBDT = w.produceBvlciBDT(bvlc.GetTable())
505+
}
506+
}
507+
return nil
508+
default:
509+
return errors.Errorf("invalid BVLPDU type %T", bvlpdu)
510+
}
511+
}
512+
513+
func (w *ReadBroadcastDistributionTableAck) String() string {
514+
return fmt.Sprintf("ReadBroadcastDistributionTableAck{%v, bvlciBDT: %v}", w._BVLPDU, w.bvlciBDT)
441515
}
442516

443517
// TODO: finish

plc4go/internal/bacnetip/tests/state_machine.go

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -282,11 +282,15 @@ func MatchPdu(localLog zerolog.Logger, pdu bacnetip.PDU, pduType any, pduAttrs m
282282
}
283283
return r.GetBvlciResultCode() == attrValue
284284
case bacnetip.KWBvlciBDT:
285-
wbdt, ok := pdu.(*bacnetip.WriteBroadcastDistributionTable)
286-
if !ok {
285+
var iwbdt []*bacnetip.Address
286+
switch pdu := pdu.(type) {
287+
case *bacnetip.WriteBroadcastDistributionTable:
288+
iwbdt = pdu.GetBvlciBDT()
289+
case *bacnetip.ReadBroadcastDistributionTableAck:
290+
iwbdt = pdu.GetBvlciBDT()
291+
default:
287292
return false
288293
}
289-
iwbdt := wbdt.GetBvlciBDT()
290294
owbdt, ok := attrValue.([]*bacnetip.Address)
291295
if !ok {
292296
return false

plc4go/internal/bacnetip/tests/test_bvll/test_codec_test.go

Lines changed: 53 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ func Result(i uint16) *bacnetip.Result {
4040
}
4141

4242
func WriteBroadcastDistributionTable(bdt ...*bacnetip.Address) *bacnetip.WriteBroadcastDistributionTable {
43-
writeBroadcastDistributionTable, err := bacnetip.NewWriteBroadcastDistributionTable(bacnetip.WithWriteBroadcastDistributionTable(bdt...))
43+
writeBroadcastDistributionTable, err := bacnetip.NewWriteBroadcastDistributionTable(bacnetip.WithWriteBroadcastDistributionTableBDT(bdt...))
4444
if err != nil {
4545
panic(err)
4646
}
@@ -55,6 +55,14 @@ func ReadBroadcastDistributionTable() *bacnetip.ReadBroadcastDistributionTable {
5555
return readBroadcastDistributionTable
5656
}
5757

58+
func ReadBroadcastDistributionTableAck(bdt ...*bacnetip.Address) *bacnetip.ReadBroadcastDistributionTableAck {
59+
readBroadcastDistributionTable, err := bacnetip.NewReadBroadcastDistributionTableAck(bacnetip.WithReadBroadcastDistributionTableAckBDT(bdt...))
60+
if err != nil {
61+
panic(err)
62+
}
63+
return readBroadcastDistributionTable
64+
}
65+
5866
type TestAnnexJCodecSuite struct {
5967
suite.Suite
6068

@@ -227,6 +235,50 @@ func (suite *TestAnnexJCodecSuite) TestReadBroadcastDistributionTable() {
227235
err = suite.Confirmation(bacnetip.NewArgs((*bacnetip.ReadBroadcastDistributionTable)(nil)), bacnetip.NoKWArgs)
228236
}
229237

238+
func (suite *TestAnnexJCodecSuite) TestReadBroadcastDistributionTableAck() {
239+
// Read an empty TableAck
240+
pduBytes, err := bacnetip.Xtob("81.03.0004")
241+
suite.Require().NoError(err)
242+
{ // Parse with plc4x parser to validate
243+
parse, err := readWriteModel.BVLCParse(testutils.TestContext(suite.T()), pduBytes)
244+
suite.Assert().NoError(err)
245+
if parse != nil {
246+
suite.T().Log("\n" + parse.String())
247+
}
248+
}
249+
250+
err = suite.Request(bacnetip.NewArgs(ReadBroadcastDistributionTableAck()), bacnetip.NoKWArgs)
251+
suite.Assert().NoError(err)
252+
err = suite.Indication(bacnetip.NoArgs, bacnetip.NewKWArgs(bacnetip.KWPDUData, pduBytes))
253+
suite.Assert().NoError(err)
254+
255+
err = suite.Response(bacnetip.NewArgs(bacnetip.NewPDU(&bacnetip.MessageBridge{Bytes: pduBytes})), bacnetip.NoKWArgs)
256+
suite.Assert().NoError(err)
257+
err = suite.Confirmation(bacnetip.NewArgs((*bacnetip.ReadBroadcastDistributionTableAck)(nil)), bacnetip.NewKWArgs(bacnetip.KWBvlciBDT, []*bacnetip.Address{}))
258+
259+
// Read TableAck with an element
260+
addr, _ := bacnetip.NewAddress(zerolog.Nop(), "192.168.0.254/24")
261+
pduBytes, err = bacnetip.Xtob("81.03.000e" + //bvlci
262+
"c0.a8.00.fe.ba.c0 ff.ff.ff.00") // address and mask
263+
suite.Require().NoError(err)
264+
{ // Parse with plc4x parser to validate
265+
parse, err := readWriteModel.BVLCParse(testutils.TestContext(suite.T()), pduBytes)
266+
suite.Assert().NoError(err)
267+
if parse != nil {
268+
suite.T().Log("\n" + parse.String())
269+
}
270+
}
271+
272+
err = suite.Request(bacnetip.NewArgs(ReadBroadcastDistributionTableAck(addr)), bacnetip.NoKWArgs)
273+
suite.Assert().NoError(err)
274+
err = suite.Indication(bacnetip.NoArgs, bacnetip.NewKWArgs(bacnetip.KWPDUData, pduBytes))
275+
suite.Assert().NoError(err)
276+
277+
err = suite.Response(bacnetip.NewArgs(bacnetip.NewPDU(&bacnetip.MessageBridge{Bytes: pduBytes})), bacnetip.NoKWArgs)
278+
suite.Assert().NoError(err)
279+
err = suite.Confirmation(bacnetip.NewArgs((*bacnetip.ReadBroadcastDistributionTableAck)(nil)), bacnetip.NewKWArgs(bacnetip.KWBvlciBDT, []*bacnetip.Address{addr}))
280+
}
281+
230282
func TestAnnexJCodec(t *testing.T) {
231283
suite.Run(t, new(TestAnnexJCodecSuite))
232284
}

0 commit comments

Comments
 (0)