public override int Send(byte[] buffer, int offset, int dataLength, BacnetAddress address, bool waitForTransmission,
                                 int timeout)
        {
            var frameType = BacnetPtpFrameTypes.FRAME_TYPE_DATA0;

            if (_sequenceCounter)
            {
                frameType = BacnetPtpFrameTypes.FRAME_TYPE_DATA1;
            }
            _sequenceCounter = !_sequenceCounter;

            //add header
            var fullLength = PTP.Encode(buffer, offset - PTP.PTP_HEADER_LENGTH, frameType, dataLength);

            //wait for send allowed
            if (!_maySend.WaitOne(timeout))
            {
                return(-BacnetMstpProtocolTransport.ETIMEDOUT);
            }

            Log.AddCustomEvent(LagoVista.Core.PlatformSupport.LogLevel.Message, "BacnetPtpProtocol", frameType.ToString());

            //send
            SendWithXonXoff(buffer, offset - HeaderLength, fullLength);
            return(dataLength);
        }
        public override int Send(byte[] buffer, int offset, int dataLength, BacnetAddress address, bool waitForTransmission, int timeout)
        {
            if (_exclusiveConn == null)
            {
                return(0);
            }

            //add header
            var fullLength = dataLength + HeaderLength;

            Bvlc.Encode(buffer, offset - BVLC.BVLC_HEADER_LENGTH, address.net == 0xFFFF
                ? BacnetBvlcFunctions.BVLC_ORIGINAL_BROADCAST_NPDU
                : BacnetBvlcFunctions.BVLC_ORIGINAL_UNICAST_NPDU, fullLength);

            //create end point
            Convert(address, out var ep);

            try
            {
                // broadcasts are transported from our local unicast socket also
                return(_exclusiveConn.Send(buffer, fullLength, ep));
            }
            catch
            {
                return(0);
            }
        }
Пример #3
0
        public override int Send(byte[] buffer, int offset, int dataLength, BacnetAddress address,
                                 bool waitForTransmission, int timeout)
        {
            var hdrOffset = 0;

            for (var i = 0; i < 6; i++)
            {
                buffer[hdrOffset++] = address.adr[i];
            }

            // write the source mac address bytes
            for (var i = 0; i < 6; i++)
            {
                buffer[hdrOffset++] = _deviceMac[i];
            }

            // the next 2 bytes are used for the packet length
            buffer[hdrOffset++] = (byte)(((dataLength + 3) & 0xFF00) >> 8);
            buffer[hdrOffset++] = (byte)((dataLength + 3) & 0xFF);

            // DSAP and SSAP
            buffer[hdrOffset++] = 0x82;
            buffer[hdrOffset++] = 0x82;

            // LLC control field
            buffer[hdrOffset] = 0x03;

            lock (_device)
            {
                _device.SendPacket(buffer, dataLength + HeaderLength);
            }

            return(dataLength + HeaderLength);
        }
        public static void Convert(BacnetAddress address, out IPEndPoint ep)
        {
            long ipAddress = BitConverter.ToUInt32(address.adr, 0);
            var  port      = (ushort)((address.adr[4] << 8) | (address.adr[5] << 0));

            ep = new IPEndPoint(ipAddress, port);
        }
Пример #5
0
        public BVLCV6(BacnetIpV6UdpProtocolTransport transport, int vMac)
        {
            _myTransport  = transport;
            _broadcastAdd = _myTransport.GetBroadcastAddress();

            if (vMac == -1)
            {
                RandomVmac = true;
                new Random().NextBytes(VMAC);
                VMAC[0] = (byte)((VMAC[0] & 0x7F) | 0x40); // ensure 01xxxxxx on the High byte

                // Open with default interface specified, cannot send it or
                // it will generate an uncheckable continuous local loopback
                if (!_myTransport.LocalEndPoint.ToString().Contains("[::]"))
                {
                    SendAddressResolutionRequest(VMAC);
                }
                else
                {
                    RandomVmac = false; // back to false avoiding loop back
                }
            }
            else // Device Id is the Vmac Id
            {
                VMAC[0] = (byte)((vMac >> 16) & 0x3F); // ensure the 2 high bits are 0 on the High byte
                VMAC[1] = (byte)((vMac >> 8) & 0xFF);
                VMAC[2] = (byte)(vMac & 0xFF);
                // unicity is guaranteed by the end user !
            }
        }
        public static void Convert(BacnetAddress address, out IPEndPoint ep)
        {
            var port = (ushort)((address.adr[16] << 8) | (address.adr[17] << 0));
            var ipv6 = new byte[16];

            Array.Copy(address.adr, ipv6, 16);
            ep = new IPEndPoint(new IPAddress(ipv6), port);
        }
Пример #7
0
        private StateChanges WaitForReply()
        {
            //fetch message
            var status = GetNextMessage(T_REPLY_TIMEOUT, out var frameType, out var destinationAddress,
                                        out var sourceAddress, out var msgLength);

            if (status == GetMessageStatus.Good)
            {
                try
                {
                    if (destinationAddress == (byte)SourceAddress &&
                        (frameType == BacnetMstpFrameTypes.FRAME_TYPE_TEST_RESPONSE ||
                         frameType == BacnetMstpFrameTypes.FRAME_TYPE_BACNET_DATA_NOT_EXPECTING_REPLY))
                    {
                        //signal upper layer
                        if (frameType != BacnetMstpFrameTypes.FRAME_TYPE_TEST_RESPONSE)
                        {
                            var remoteAddress = new BacnetAddress(BacnetAddressTypes.MSTP, 0, new[] { sourceAddress });
                            try
                            {
                                InvokeMessageRecieved(_localBuffer, MSTP.MSTP_HEADER_LENGTH, msgLength, remoteAddress);
                            }
                            catch (Exception ex)
                            {
                                Log.AddException("Exception in MessageRecieved event", ex);
                            }
                        }

                        /* ReceivedReply */
                        return(StateChanges.ReceivedReply);
                    }
                    else if (frameType == BacnetMstpFrameTypes.FRAME_TYPE_REPLY_POSTPONED)
                    {
                        /* ReceivedPostpone */
                        return(StateChanges.ReceivedPostpone);
                    }
                    else
                    {
                        /* ReceivedUnexpectedFrame */
                        return(StateChanges.ReceivedUnexpectedFrame);
                    }
                }
                finally
                {
                    RemoveCurrentMessage(msgLength);
                }
            }

            if (status != GetMessageStatus.Timeout)
            {
                return(StateChanges.InvalidFrame);
            }

            /* ReplyTimeout */
            _frameCount = MaxInfoFrames;
            return(StateChanges.ReplyTimeOut);
            /* InvalidFrame */
        }
        public static void Convert(IPEndPoint ep, out BacnetAddress address)
        {
            var tmp1 = ep.Address.GetAddressBytes();
            var tmp2 = BitConverter.GetBytes((ushort)ep.Port);

            Array.Reverse(tmp2);
            Array.Resize(ref tmp1, tmp1.Length + tmp2.Length);
            Array.Copy(tmp2, 0, tmp1, tmp1.Length - tmp2.Length, tmp2.Length);
            address = new BacnetAddress(BacnetAddressTypes.IP, 0, tmp1);
        }
Пример #9
0
 public DeviceReportingRecipient(BacnetBitString weekofDay, DateTime fromTime, DateTime toTime, BacnetAddress adr, uint processIdentifier, bool ackRequired, BacnetBitString evenType)
 {
     Id                     = new BacnetObjectId();
     WeekofDay              = weekofDay;
     this.toTime            = toTime;
     this.fromTime          = fromTime;
     this.adr               = adr;
     this.processIdentifier = processIdentifier;
     Ack_Required           = ackRequired;
     this.evenType          = evenType;
 }
Пример #10
0
        // checked if device is routed by curent equipement
        public bool IsMyRouter(BacnetAddress device)
        {
            if (device.RoutedSource == null || RoutedSource != null)
            {
                return(false);
            }

            if (adr.Length != device.adr.Length)
            {
                return(false);
            }

            return(!adr.Where((t, i) => t != device.adr[i]).Any());
        }
Пример #11
0
        private void OnPacketArrival(RawCapture packet)
        {
            // don't process any packet too short to not be valid
            if (packet.Data.Length <= 17)
            {
                return;
            }

            var buffer = packet.Data;
            var offset = 0;

            // Got frames send by me, not for me, not broadcast
            var dest = Mac(buffer, offset);

            if (!_isOutboundPacket(dest, 0) && dest[0] != 255)
            {
                return;
            }

            offset += 6;

            // source address
            var bacSource = new BacnetAddress(BacnetAddressTypes.Ethernet, 0, Mac(buffer, offset));

            offset += 6;

            // len
            var length = buffer[offset] * 256 + buffer[offset + 1];

            offset += 2;

            // 3 bytes LLC hearder
            var dsap    = buffer[offset++];
            var ssap    = buffer[offset++];
            var control = buffer[offset++];

            length -= 3; // Bacnet content length eq. ethernet lenght minus LLC header length

            // don't process non-BACnet packets
            if (dsap != 0x82 || ssap != 0x82 || control != 0x03)
            {
                return;
            }

            InvokeMessageRecieved(buffer, HeaderLength, length, bacSource);
        }
        public override int Send(byte[] buffer, int offset, int dataLength, BacnetAddress address,
                                 bool waitForTransmission, int timeout)
        {
            if (_exclusiveConn == null)
            {
                return(0);
            }

            //add header
            var fullLength = dataLength + HeaderLength;

            if (address.net == 0xFFFF)
            {
                var newBuffer = new byte[fullLength - 3];
                Array.Copy(buffer, 3, newBuffer, 0, fullLength - 3);
                fullLength -= 3;
                buffer      = newBuffer;
                Bvlc.Encode(buffer, offset - BVLCV6.BVLC_HEADER_LENGTH,
                            BacnetBvlcV6Functions.BVLC_ORIGINAL_BROADCAST_NPDU, fullLength, address);
            }
            else
            {
                Bvlc.Encode(buffer, offset - BVLCV6.BVLC_HEADER_LENGTH, BacnetBvlcV6Functions.BVLC_ORIGINAL_UNICAST_NPDU,
                            fullLength, address);
            }

            // create end point
            Convert(address, out var ep);

            try
            {
                // send
                // multicast are transported from our local unicast socket also
                return(_exclusiveConn.Send(buffer, fullLength, ep));
            }
            catch
            {
                return(0);
            }
        }
Пример #13
0
        public override int Send(byte[] buffer, int offset, int dataLength, BacnetAddress address,
                                 bool waitForTransmission, int timeout)
        {
            if (SourceAddress == -1)
            {
                throw new Exception("Source address must be set up before sending messages");
            }

            //add to queue
            var function  = NPDU.DecodeFunction(buffer, offset);
            var frameType = (function & BacnetNpduControls.ExpectingReply) == BacnetNpduControls.ExpectingReply
                ? BacnetMstpFrameTypes.FRAME_TYPE_BACNET_DATA_EXPECTING_REPLY
                : BacnetMstpFrameTypes.FRAME_TYPE_BACNET_DATA_NOT_EXPECTING_REPLY;
            var copy = new byte[dataLength + MSTP.MSTP_HEADER_LENGTH + 2];

            Array.Copy(buffer, offset, copy, MSTP.MSTP_HEADER_LENGTH, dataLength);
            var f = new MessageFrame(frameType, address.adr[0], copy, dataLength);

            lock (_sendQueue)
                _sendQueue.AddLast(f);
            if (_reply == null)
            {
                _reply = f;
                _replyMutex.Set();
            }

            if (!waitForTransmission)
            {
                return(dataLength);
            }

            //wait for message to be sent
            if (!f.SendMutex.WaitOne(timeout))
            {
                return(-ETIMEDOUT);
            }

            return(dataLength);
        }
Пример #14
0
        public DeviceReportingRecipient(BacnetValue v0, BacnetValue v1, BacnetValue v2, BacnetValue v3, BacnetValue v4, BacnetValue v5, BacnetValue v6)
        {
            Id  = new BacnetObjectId();
            adr = null;

            WeekofDay = (BacnetBitString)v0.Value;
            fromTime  = (DateTime)v1.Value;
            toTime    = (DateTime)v2.Value;
            if (v3.Value is BacnetObjectId)
            {
                Id = (BacnetObjectId)v3.Value;
            }
            else
            {
                var netdescr = (BacnetValue[])v3.Value;
                var s        = (ushort)(uint)netdescr[0].Value;
                var b        = (byte[])netdescr[1].Value;
                adr = new BacnetAddress(BacnetAddressTypes.IP, s, b);
            }
            processIdentifier = (uint)v4.Value;
            Ack_Required      = (bool)v5.Value;
            evenType          = (BacnetBitString)v6.Value;
        }
Пример #15
0
        // Decode is called each time an Udp Frame is received
        public int Decode(byte[] buffer, int offset, out BacnetBvlcV6Functions function, out int msgLength,
                          IPEndPoint sender, BacnetAddress remoteAddress)
        {
            // offset always 0, we are the first after udp
            // and a previous test by the caller guaranteed at least 4 bytes into the buffer

            function  = (BacnetBvlcV6Functions)buffer[1];
            msgLength = (buffer[2] << 8) | (buffer[3] << 0);
            if (buffer[0] != BVLL_TYPE_BACNET_IPV6 || buffer.Length != msgLength)
            {
                return(-1);
            }

            Array.Copy(buffer, 4, remoteAddress.VMac, 0, 3);

            switch (function)
            {
            case BacnetBvlcV6Functions.BVLC_RESULT:
                return(9);    // only for the upper layers

            case BacnetBvlcV6Functions.BVLC_ORIGINAL_UNICAST_NPDU:
                return(10);    // only for the upper layers

            case BacnetBvlcV6Functions.BVLC_ORIGINAL_BROADCAST_NPDU:
                // Send to FDs & BBMDs, not broadcast or it will be made twice !
                if (_bbmdFdServiceActivated)
                {
                    Forward_NPDU(buffer, msgLength, false, sender, remoteAddress);
                }
                return(7);    // also for the upper layers

            case BacnetBvlcV6Functions.BVLC_ADDRESS_RESOLUTION:
                // need to verify that the VMAC is mine
                if (VMAC[0] == buffer[7] && VMAC[1] == buffer[8] && VMAC[2] == buffer[9])
                {
                    // coming from myself ? avoid loopback
                    if (!_myTransport.LocalEndPoint.Equals(sender))
                    {
                        SendAddressResolutionAck(sender, remoteAddress.VMac,
                                                 BacnetBvlcV6Functions.BVLC_ADDRESS_RESOLUTION_ACK);
                    }
                }
                return(0);    // not for the upper layers

            case BacnetBvlcV6Functions.BVLC_FORWARDED_ADDRESS_RESOLUTION:
                // no need to verify the target VMAC, should be OK
                SendAddressResolutionAck(sender, remoteAddress.VMac,
                                         BacnetBvlcV6Functions.BVLC_ADDRESS_RESOLUTION_ACK);
                return(0);                                          // not for the upper layers

            case BacnetBvlcV6Functions.BVLC_ADDRESS_RESOLUTION_ACK: // adresse conflict
                if (VMAC[0] == buffer[4] && VMAC[1] == buffer[5] && VMAC[2] == buffer[6] && RandomVmac)
                {
                    new Random().NextBytes(VMAC);
                    VMAC[0] = (byte)((VMAC[0] & 0x7F) | 0x40);
                    SendAddressResolutionRequest(VMAC);
                }
                return(0);    // not for the upper layers

            case BacnetBvlcV6Functions.BVLC_VIRTUAL_ADDRESS_RESOLUTION:
                SendAddressResolutionAck(sender, remoteAddress.VMac,
                                         BacnetBvlcV6Functions.BVLC_VIRTUAL_ADDRESS_RESOLUTION_ACK);
                return(0);    // not for the upper layers

            case BacnetBvlcV6Functions.BVLC_VIRTUAL_ADDRESS_RESOLUTION_ACK:
                return(0);    // not for the upper layers

            case BacnetBvlcV6Functions.BVLC_FORWARDED_NPDU:
                if (_myTransport.LocalEndPoint.Equals(sender))
                {
                    return(0);
                }

                // certainly TODO the same code I've put in the IPV4 implementation
                if (_bbmdFdServiceActivated && msgLength >= 25)
                {
                    bool ret;
                    lock (_bbmds)
                        ret = _bbmds.Exists(items => items.Equals(sender));     // verify sender presence in the table
                    // avoid also loopback

                    if (ret)                          // message from a know BBMD address, sent to all FDs and broadcast
                    {
                        SendToFDs(buffer, msgLength); // send without modification
                        // Assume all BVLC_FORWARDED_NPDU are directly sent to me in the
                        // unicast mode and not by the way of the multicast address
                        // If not, it's not really a big problem, devices on the local net will
                        // receive two times the message (after all it's just WhoIs, Iam, ...)
                        IPEndPoint ep;
                        BacnetIpV6UdpProtocolTransport.Convert(_broadcastAdd, out ep);
                        _myTransport.Send(buffer, msgLength, ep);
                    }
                }
                return(25);    // for the upper layers

            case BacnetBvlcV6Functions.BVLC_REGISTER_FOREIGN_DEVICE:
                if (_bbmdFdServiceActivated && msgLength == 9)
                {
                    var TTL = (buffer[7] << 8) + buffer[8];                        // unit is second
                    RegisterForeignDevice(sender, TTL);
                    SendResult(sender, BacnetBvlcV6Results.SUCCESSFUL_COMPLETION); // ack
                }
                return(0);                                                         // not for the upper layers

            case BacnetBvlcV6Functions.BVLC_DELETE_FOREIGN_DEVICE_TABLE_ENTRY:
                return(0);    // not for the upper layers

            case BacnetBvlcV6Functions.BVLC_SECURE_BVLC:
                return(0);                                                   // not for the upper layers

            case BacnetBvlcV6Functions.BVLC_DISTRIBUTE_BROADCAST_TO_NETWORK: // Sent by a Foreign Device, not a BBMD
                if (_bbmdFdServiceActivated)
                {
                    // Send to FDs except the sender, BBMDs and broadcast
                    lock (_foreignDevices)
                    {
                        if (_foreignDevices.Exists(item => item.Key.Equals(sender)))     // verify previous registration
                        {
                            Forward_NPDU(buffer, msgLength, true, sender, remoteAddress);
                        }
                        else
                        {
                            SendResult(sender, BacnetBvlcV6Results.DISTRIBUTE_BROADCAST_TO_NETWORK_NAK);
                        }
                    }
                }
                return(0);    // not for the upper layers

            // error encoding function or experimental one
            default:
                return(-1);
            }
        }
Пример #16
0
        // Encode is called by internal services if the BBMD is also an active device
        public int Encode(byte[] buffer, int offset, BacnetBvlcV6Functions function, int msgLength, BacnetAddress address)
        {
            // offset always 0, we are the first after udp
            First7BytesHeaderEncode(buffer, function, msgLength);

            // BBMD service
            if (function == BacnetBvlcV6Functions.BVLC_ORIGINAL_BROADCAST_NPDU && _bbmdFdServiceActivated)
            {
                var me = _myTransport.LocalEndPoint;
                BacnetIpV6UdpProtocolTransport.Convert(me, out var bacme);
                Array.Copy(VMAC, bacme.VMac, 3);

                Forward_NPDU(buffer, msgLength, false, me, bacme); // send to all BBMDs and FDs

                return(7);                                         // ready to send
            }

            if (function != BacnetBvlcV6Functions.BVLC_ORIGINAL_UNICAST_NPDU)
            {
                return(0); // ?
            }
            buffer[7] = address.VMac[0];
            buffer[8] = address.VMac[1];
            buffer[9] = address.VMac[2];
            return(10); // ready to send
        }
Пример #17
0
        // Never tested
        private void Forward_NPDU(byte[] buffer, int msgLength, bool toGlobalBroadcast, IPEndPoint epSender, BacnetAddress bacSender)
        {
            // Forms the forwarded NPDU from the original (broadcast npdu), and send it to all

            // copy, 18 bytes shifted (orignal bvlc header : 7 bytes, new one : 25 bytes)
            var b = new byte[msgLength + 18];

            // normaly only 'small' frames are present here, so no need to check if it's to big for Udp
            Array.Copy(buffer, 0, b, 18, msgLength);

            // 7 bytes for the BVLC Header, with the embedded 6 bytes IP:Port of the original sender
            First7BytesHeaderEncode(b, BacnetBvlcV6Functions.BVLC_FORWARDED_NPDU, msgLength + 18);
            // replace my Vmac by the orignal source vMac
            Array.Copy(bacSender.VMac, 0, b, 4, 3);
            // Add IpV6 endpoint
            Array.Copy(bacSender.adr, 0, b, 7, 18);
            // Send To BBMD
            SendToBBMDs(b, msgLength + 18);
            // Send To FD, except the sender
            SendToFDs(b, msgLength + 18, epSender);
            // Broadcast if required
            if (toGlobalBroadcast)
            {
                IPEndPoint ep;
                BacnetIpV6UdpProtocolTransport.Convert(_broadcastAdd, out ep);
                _myTransport.Send(b, msgLength + 18, ep);
            }
        }
 public override BacnetAddress GetBroadcastAddress()
 {
     return(_broadcastAddress ?? (_broadcastAddress = _GetBroadcastAddress()));
 }
Пример #19
0
        private StateChanges Idle()
        {
            var noTokenTimeout = T_NO_TOKEN + 10 * SourceAddress;

            while (_port != null)
            {
                //get message
                var status = GetNextMessage(noTokenTimeout, out var frameType, out var destinationAddress,
                                            out var sourceAddress, out var msgLength);

                if (status == GetMessageStatus.Good)
                {
                    try
                    {
                        if (destinationAddress == SourceAddress || destinationAddress == 0xFF)
                        {
                            switch (frameType)
                            {
                            case BacnetMstpFrameTypes.FRAME_TYPE_POLL_FOR_MASTER:
                                if (destinationAddress == 0xFF)
                                {
                                    QueueFrame(BacnetMstpFrameTypes.FRAME_TYPE_REPLY_TO_POLL_FOR_MASTER,
                                               sourceAddress);
                                }
                                else
                                {
                                    //respond to PFM
                                    SendFrame(BacnetMstpFrameTypes.FRAME_TYPE_REPLY_TO_POLL_FOR_MASTER,
                                              sourceAddress);
                                }
                                break;

                            case BacnetMstpFrameTypes.FRAME_TYPE_TOKEN:
                                if (destinationAddress != 0xFF)
                                {
                                    _frameCount = 0;
                                    _soleMaster = false;
                                    return(StateChanges.ReceivedToken);
                                }
                                break;

                            case BacnetMstpFrameTypes.FRAME_TYPE_TEST_REQUEST:
                                if (destinationAddress == 0xFF)
                                {
                                    QueueFrame(BacnetMstpFrameTypes.FRAME_TYPE_TEST_RESPONSE, sourceAddress);
                                }
                                else
                                {
                                    //respond to test
                                    SendFrame(BacnetMstpFrameTypes.FRAME_TYPE_TEST_RESPONSE, sourceAddress);
                                }
                                break;

                            case BacnetMstpFrameTypes.FRAME_TYPE_BACNET_DATA_NOT_EXPECTING_REPLY:
                            case BacnetMstpFrameTypes.FRAME_TYPE_BACNET_DATA_EXPECTING_REPLY:
                                try
                                {
                                    //signal upper layer
                                    var remoteAddress = new BacnetAddress(BacnetAddressTypes.MSTP, 0, new[] { sourceAddress });
                                    InvokeMessageRecieved(_localBuffer, MSTP.MSTP_HEADER_LENGTH, msgLength, remoteAddress);
                                }
                                catch (Exception ex)
                                {
                                    Log.AddException("Exception in MessageRecieved event", ex);
                                }
                                if (frameType == BacnetMstpFrameTypes.FRAME_TYPE_BACNET_DATA_EXPECTING_REPLY)
                                {
                                    _replySource = sourceAddress;
                                    _reply       = null;
                                    _replyMutex.Reset();
                                    return(StateChanges.ReceivedDataNeedingReply);
                                }
                                break;
                            }
                        }
                    }
                    finally
                    {
                        RemoveCurrentMessage(msgLength);
                    }
                }
                else if (status == GetMessageStatus.Timeout)
                {
                    /* GenerateToken */
                    _ps         = (byte)((SourceAddress + 1) % (MaxMaster + 1));
                    _ns         = (byte)SourceAddress;
                    _tokenCount = 0;
                    return(StateChanges.GenerateToken);
                }
                else if (status == GetMessageStatus.ConnectionClose)
                {
                    Log.AddCustomEvent(LagoVista.Core.PlatformSupport.LogLevel.Message, "BacnetMstpProtocol", "No connection");
                }
                else if (status == GetMessageStatus.ConnectionError)
                {
                    Log.AddCustomEvent(LagoVista.Core.PlatformSupport.LogLevel.Message, "BacnetMstpProtocol", "Connection Error");
                }
                else
                {
                    Log.AddCustomEvent(LagoVista.Core.PlatformSupport.LogLevel.Message, "BacnetMstpProtocol", "Garbage");
                }
            }

            return(StateChanges.Reset);
        }