Read Property

Help
meh
2009-08-15
2013-04-18
  • meh

    meh - 2009-08-15

    I think I'm close....has anyone got a read property to work yet?

    Here is my attempt

    public static void ReadProperties(BACnetmanager bnm)
            {
                byte[] data = new byte[1024];
                int optr = 0;
                //--- this is the sender -----------------------------------
                //IPEndPoint ipep = new IPEndPoint(IPAddress.Parse(segIP), bnm.BACnetManagerPort);
                // hard coded for now is my devices IP address
                IPEndPoint ipep = new IPEndPoint(IPAddress.Parse("192.168.1.30"), bnm.BACnetManagerPort);
                //--- this is the listener ------------------------------------
                IPEndPoint local_ipep = new IPEndPoint(0, bnm.BACnetManagerPort);
                //
                Socket bacnet_master_socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
                ////
                bacnet_master_socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.Broadcast, true);
                bacnet_master_socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
                //
                // bind the local end of the connection to BACnet port number
                bacnet_master_socket.Bind(local_ipep);
                //ANNEX J - BACnet/IP (NORMATIVE)
                /*The format of the BACnet-Confirmed-Request-PDU is:
                Bit Number:   7   6   5   4   3   2   1   0
                            |---|---|---|---|---|---|---|---|
                            | PDU Type  |   |SEG|MOR| SA| 0 |
                            |---|---|---|---|---|---|---|---|
                            | 0 |  Max Segs |  Max Resp     |
                            |---|---|---|---|---|---|---|---|
                            |             Invoke ID         |
                            |---|---|---|---|---|---|---|---|
                            |       Sequence Number         |    Only present if SEG = 1
                            |---|---|---|---|---|---|---|---|
                            |      Proposed Window Size     |    Only present if SEG = 1
                            |---|---|---|---|---|---|---|---|
                            |        Service Choice         |
                            |---|---|---|---|---|---|---|---|
                            |       Service Request         |
                            |               .               |
                            |               .               |
                            |               .               |
                            |---|---|---|---|---|---|---|---|
                           The PDU fields have the following values:
                 *
                           PDU Type =       0 (BACnet-Confirmed-Service-Request-PDU)
                                SEG =       0 (Unsegmented Request)
                                            1 (Segmented Request)
                                MOR =       0 (No More Segments Follow)
                                            1 (More Segments Follow)
                                 SA =       0 (Segmented Response not accepted)
                                            1 (Segmented Response accepted)
                           Max Segs =       (0..7) (Number of response segments accepted per 20.1.2.4)
                           Max Resp =       (0..15) (Size of Maximum APDU accepted per 20.1.2.5)
                          Invoke ID =       (0..255)
                    Sequence Number =       (0..255) Only present if SEG = 1
               Proposed Window Size =       (1..127) Only present if SEG = 1
                     Service Choice =       BACnetConfirmedServiceChoice
                    Service Request =       Variable Encoding per 20.2.
                 *
               Bits shown in the diagram as '0' shall be set to zero. These bits are currently unused and are reserved by ASHRAE.
               */
                //Version    1 octet
                //Control    1 octet
                //DNET    2 octet
                //DLEN    1 octet
                //DADR    Variable
                //SNET    2 octets
                //SLEN    1 octet
                //SADR    variable
                //Hop Count    1 octet
                //Message Type    1 octet
                //Vendor ID    2 octet
                //APDU    variable

                // BVLC Part
                // http://www.bacnetwiki.com/wiki/index.php?title=BACnet_Virtual_Link_Control

                data[optr++] = BACnetEnums.BACNET_BVLC_TYPE_BIP;  // 81
                data[optr++] = (byte)BACnetEnums.BACNET_BVLC_FUNCTION.BVLC_ORIGINAL_UNICAST_NPDU;  //0a
                data[optr++] = 0x00;        // Length (2 octets)
                data[optr++] = 0x1b;

                // Start of NPDU
                // http://www.bacnetwiki.com/wiki/index.php?title=NPDU

                data[optr++] = 0x01;            //
                data[optr++] = 0x24;            //

                data[optr++] = 0x03;            //
                data[optr++] = 0xea;
                data[optr++] = 0x06;            //
                data[optr++] = 0xc0;            //

                // APDU start
                // http://www.bacnetwiki.com/wiki/index.php?title=APDU

                data[optr++] = 0xa8;            // Encoded APDU type == 01 == Unconfirmed Request
                data[optr++] = 0x01;            // Unconfirmed Service Choice: Who-Is  //  Service Choice: readProperty (12)

                data[optr++] = 0xcb;            //
                data[optr++] = 0xba;            //

                data[optr++] = 0xc0;            //
                data[optr++] = 0xff;            //
                data[optr++] = 0x02;            //
                data[optr++] = 0x04;            //
                data[optr++] = 0x01;            //  Invoke ID
                data[optr++] = 0x0c;            //
                data[optr++] = 0x0c;            //
                data[optr++] = 0x02;            //

                data[optr++] = 0x00;            //
                data[optr++] = 0x01;            //  this = 256    000000001
                data[optr++] = 0xf4;            //  this = 128    111110100  // this is my devices instance

                data[optr++] = 0x19;            //  19  Context Tag: 1, Length/Value/Type: 1
                data[optr++] = 0x4c;            //  4c  Property Identifier: object-list (76)

                // if there is no available adapter, this try will throw
                try
                {
                    bacnet_master_socket.SendTo(data, optr, SocketFlags.None, ipep);
                }
                catch (SocketException)
                {
                    System.Windows.Forms.MessageBox.Show("Either the network cable is unplugged, or there is no configured Ethernet Port on this computer");
                    return;
                }
               //  sending another who-is, this time with SNET, SADR present..

                optr = 0;

                bacnet_master_socket.Close();

            }

    mike

     
    • Edward Hague

      Edward Hague - 2009-08-15

      Thanks Mike
      I have added your code to the BACnetLibrary module, and added a button on the mainform to test and checked this into the repository. I am going to make more modifications today, but for now, pressing the "Read Property Test" button sends your packet, and this checks out in Wireshark.
      Ed

       
      • meh

        meh - 2009-08-16

        Apparently still needs work.  Wireshark shows...
        Network Layer Message Type: 03 (Reject-Message-To-Network)
        Reject Reason: 1 (The router is not directly connected to DNET and cannot find a router to DNET on any directly connected network using Who-Is-Router-To-Network messages.)

        In addition with the new code It's not finding Network 0  anymore....will have to investigate.

        mike

         
        • meh

          meh - 2009-08-17

          Actually if I 1 line through then network 0 gets added to the tree???

          If I let it run it does not...?

           
          • meh

            meh - 2009-08-17

            Got it working for Object list.....

            I think I now realize the enormity of this project...there are numerous read property types but at least this is working for now.....

            Try this.....I have hard coded my device IP for now....

            public static void ReadProperties(BACnetmanager bnm)
                    {
                        byte[] data = new byte[1024];
                        int optr = 0;
                        //--- this is the sender -----------------------------------
                        IPEndPoint ipep = new IPEndPoint(IPAddress.Parse(segIP), bnm.BACnetManagerPort);
                        // hard coded for now is my devices IP address
                        //IPEndPoint ipep = new IPEndPoint(IPAddress.Parse("192.168.1.30"), bnm.BACnetManagerPort);
                        //--- this is the listener ------------------------------------
                        IPEndPoint local_ipep = new IPEndPoint(0, bnm.BACnetManagerPort);
                        //
                        Socket bacnet_master_socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
                        ////
                        bacnet_master_socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.Broadcast, true);
                        bacnet_master_socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
                        //
                        // bind the local end of the connection to BACnet port number
                        bacnet_master_socket.Bind(local_ipep);
                        //ANNEX J - BACnet/IP (NORMATIVE)
                        /*The format of the BACnet-Confirmed-Request-PDU is:
                        Bit Number:   7   6   5   4   3   2   1   0
                                    |---|---|---|---|---|---|---|---|
                                    | PDU Type  |   |SEG|MOR| SA| 0 |
                                    |---|---|---|---|---|---|---|---|
                                    | 0 |  Max Segs |  Max Resp     |
                                    |---|---|---|---|---|---|---|---|
                                    |             Invoke ID         |
                                    |---|---|---|---|---|---|---|---|
                                    |       Sequence Number         |    Only present if SEG = 1
                                    |---|---|---|---|---|---|---|---|
                                    |      Proposed Window Size     |    Only present if SEG = 1
                                    |---|---|---|---|---|---|---|---|
                                    |        Service Choice         |
                                    |---|---|---|---|---|---|---|---|
                                    |       Service Request         |
                                    |               .               |
                                    |               .               |
                                    |               .               |
                                    |---|---|---|---|---|---|---|---|
                                   The PDU fields have the following values:
                         *
                                   PDU Type =       0 (BACnet-Confirmed-Service-Request-PDU)
                                        SEG =       0 (Unsegmented Request)
                                                    1 (Segmented Request)
                                        MOR =       0 (No More Segments Follow)
                                                    1 (More Segments Follow)
                                         SA =       0 (Segmented Response not accepted)
                                                    1 (Segmented Response accepted)
                                   Max Segs =       (0..7) (Number of response segments accepted per 20.1.2.4)
                                   Max Resp =       (0..15) (Size of Maximum APDU accepted per 20.1.2.5)
                                  Invoke ID =       (0..255)
                            Sequence Number =       (0..255) Only present if SEG = 1
                       Proposed Window Size =       (1..127) Only present if SEG = 1
                             Service Choice =       BACnetConfirmedServiceChoice
                            Service Request =       Variable Encoding per 20.2.
                         *
                       Bits shown in the diagram as '0' shall be set to zero. These bits are currently unused and are reserved by ASHRAE.
                       */
                        //Version    1 octet
                        //Control    1 octet
                        //DNET    2 octet
                        //DLEN    1 octet
                        //DADR    Variable
                        //SNET    2 octets
                        //SLEN    1 octet
                        //SADR    variable
                        //Hop Count    1 octet
                        //Message Type    1 octet
                        //Vendor ID    2 octet
                        //APDU    variable

                        // BVLC Part
                        // http://www.bacnetwiki.com/wiki/index.php?title=BACnet_Virtual_Link_Control
                        /*
                            J.2.11 Original-Unicast-NPDU: Purpose
                            This message is used to send directed NPDUs to another B/IP device or router.
                            J.2.11.1 Original-Unicast-NPDU: Format
                            The Original-Unicast-NPDU message consists of four fields:
                         *
                            BVLC Type: 1-octet X'81' BVLL for BACnet/IP
                            BVLC Function: 1-octet X'0A' Original-Unicast-NPDU
                            BVLC Length: 2-octets L Length L, in octets, of the BVLL message
                            BACnet NPDU: Variable length
                         */
                        data[optr++] = BACnetEnums.BACNET_BVLC_TYPE_BIP;  // 81
                        data[optr++] = (byte)BACnetEnums.BACNET_BVLC_FUNCTION.BVLC_ORIGINAL_UNICAST_NPDU;  //0a
                        data[optr++] = 0x00;        // Length (2 octets)
                        data[optr++] = 0x1b;

                        // Start of NPDU
                        // http://www.bacnetwiki.com/wiki/index.php?title=NPDU

                        data[optr++] = 0x01;            // Version: 0x01 (ASHRAE 135-1995)
                        data[optr++] = 0x04;            // Destination: 192.168.1.255 (192.168.1.255)

                        //data[optr++] = 0x03;            // Destination Network Address: 03 1002
                        //data[optr++] = 0xea;            // Destination Network Address: ea 1002
                        //data[optr++] = 0x06;            // Length
                        //data[optr++] = 0xc0;            // Destination ISO 8802-3 MAC Address:
                        //data[optr++] = 0xa8;            // Destination ISO 8802-3 MAC Address:
                        //data[optr++] = 0x01;            // Destination ISO 8802-3 MAC Address:
                        //data[optr++] = 0xcb;            // Destination ISO 8802-3 MAC Address:
                        //data[optr++] = 0xba;            // Destination ISO 8802-3 MAC Address:
                        ///data[optr++] = 0xc0;            // Destination ISO 8802-3 MAC Address:
                        //data[optr++] = 0xff;            // Hop Count: 255

                        // APDU start
                        // http://www.bacnetwiki.com/wiki/index.php?title=APDU

                        data[optr++] = 0x02;            // 0000 .... = APDU Type: Confirmed-Request  (0)
                        data[optr++] = 0x04;            //.000 .... = Max Response Segments accepted: Unspecified (0)
                                                        //.... 0100 = Size of Maximum ADPU accepted: Up to 1024 octets (4)
                        data[optr++] = 0x01;            //  Invoke ID
                        data[optr++] = 0x0c;            // Service Choice: readProperty (12)
                        data[optr++] = 0x0c;            // ObjectIdentifier: device object, 500
                        data[optr++] = 0x02;            // ObjectIdentifier: device object, 500

                        data[optr++] = 0x00;            // ObjectIdentifier: device object, 500
                        data[optr++] = 0x01;            // this = 256    000000001
                        data[optr++] = 0xf4;            // this = 128    111110100  // this is my devices instance

                                                        // Property Identifier: object-list (76)
                        data[optr++] = 0x19;            // 19  Context Tag: 1, Length/Value/Type: 1
                        data[optr++] = 0x4c;            // 4c  Property Identifier: object-list (76)

                        // if there is no available adapter, this try will throw
                        try
                        {
                            bacnet_master_socket.SendTo(data, optr, SocketFlags.None, ipep);
                        }
                        catch (SocketException)
                        {
                            System.Windows.Forms.MessageBox.Show("Either the network cable is unplugged, or there is no configured Ethernet Port on this computer");
                            return;
                        }
                       //  sending another who-is, this time with SNET, SADR present..

                        optr = 0;

                        bacnet_master_socket.Close();

                    }

             
            • Edward Hague

              Edward Hague - 2009-08-19

              Mike
              I have added your code to the project. In addition I have made a number of changes to encoding and decoding to make the program more 'object oriented'. Furthermore, if you browse the treeview, and right-click an DEVICE, you should get a menu of commands you can send to that DEVICE, one of which is a read-property based on your code. Have at it.

              PS, remember to check your code into the 'mike' branch of the subversion repository next time.

              Ed

               
              • meh

                meh - 2009-08-26

                I still do not have this working.  I'm wondering if  I'm getting a checksum error when I send the message.
                Also wondering if the Device class need to have an array property to handle the invoke ID's for the messages sent to a given device?  It seems like potentially there may be a number of messages sent.
                Maybe I'm over thinking it....

                thanks for any help

                mike

                 
                • meh

                  meh - 2009-09-02

                  Well I can send from the rt-click menu but not sure how to read it.
                  Can not get the checkin - checkout of the code to work so here is the read property for firmware version.  I thought it would be simpler but for me it was not.  It has taken 2 weeks to get this bad code to work.
                  I'm not sure I understand the "big picture" of how this is all suppose to work...

                          #region Send Read Properties

                          public static void ReadProperties(BACnetmanager bnm, Device device )
                          {
                              byte[] data = new byte[1024];
                              uint optr = 0;
                              //*********************************************************************************************
                              // BVLC Part
                              // http://www.bacnetwiki.com/wiki/index.php?title=BACnet_Virtual_Link_Control

                              data[optr++] = BACnetEnums.BACNET_BVLC_TYPE_BIP;  // 81
                              data[optr++] = (byte)BACnetEnums.BACNET_BVLC_FUNCTION.BVLC_ORIGINAL_UNICAST_NPDU;  //0a

                              uint store_length_here = optr;
                              optr += 2;
                              //*********************************************************************************************
                              // Start of NPDU
                              // http://www.bacnetwiki.com/wiki/index.php?title=NPDU
                              //6.2.1 Protocol Version Number
                              //Each NPDU shall begin with a single octet that indicates the version number of the BACnet protocol,
                              //encoded as an 8 bit unsigned integer. The present version number of the BACnet protocol is one (1).
                              //------------------------------- Version ----------------------------------------------------------
                              data[optr++] = (byte)BACnetEnums.BACNET_PROTOCOL_VERSION;
                              //The second octet in an NPDU shall be a control octet that indicates the presence or absence of
                              //particular NPCI fields.
                              //
                              if (device.adr.networkNumber != 0)
                              {
                                  data[optr++] = 0x24;            //  NCPI - Dest present, expecting reply
                                  device.adr.Encode(data, ref optr);
                                  data[optr++] = 0xff;            // Hopcount
                              }
                              else
                              {
                                  data[optr++] = 0x00;            //  NCPI - Dest present, expecting reply
                              }
                              //data[optr++] = 0xff;            // Hopcount

                              //************************************************************************************************
                              // APDU start
                              // http://www.bacnetwiki.com/wiki/index.php?title=APDU
                              // Unconfirmed Request
                              // Structure described here http://www.bacnetwiki.com/wiki/index.php?title=BACnet-Confirmed-Request-PDU

                              //data[optr++] = 0x02;            //  PDU Type=0 and SA=1
                              data[optr++] = (byte)BACnetEnums.BACNET_PDU_TYPE.PDU_TYPE_CONFIRMED_SERVICE_REQUEST;
                              //
                              data[optr++] = 0x04;            //  Max Resp (Encoded)
                              //
                              data[optr++] = 0x01;            //  Invoke ID
                              //
                              //  Service Choice 12 = ReadProperty
                              data[optr++] = (byte)BACnetEnums.BACNET_CONFIRMED_SERVICE.SERVICE_CONFIRMED_READ_PROPERTY;
                              // Service Request
                              // Object type, instance (Device Object)
                  #if false
                              data[optr++] = 0x0c;            //
                              data[optr++] = 0x02;            //
                              data[optr++] = 0x01;            //
                              data[optr++] = 0x1d;            //
                              data[optr++] = 0x2c;            // 
                  #else
                              device.deviceID.Encode(data, ref optr);
                  #endif

                              // Property Identifier (FIRMWARE_REVISION)
                              data[optr++] = 0x19;            //  19  Context Tag: 1, Length/Value/Type: 1
                              data[optr++] = (byte)BACnetEnums.BACNET_PROPERTY_ID.PROP_FIRMWARE_REVISION;
                              //
                              data[store_length_here] = (byte)((optr >> 8) & 0xff);
                              data[store_length_here + 1] = (byte)(optr & 0xff);
                              //
                              // if there is no available adapter, this try will throw
                              try
                              {
                                  bnm.insidesocket.SendTo(data, (int)optr, SocketFlags.None, device.packet.FromAddress);
                              }
                              catch (SocketException)
                              {
                                  System.Windows.Forms.MessageBox.Show("Either the network cable is unplugged, or there is no configured Ethernet Port on this computer");
                                  return;
                              }

                          }

                          #endregion

                  meh

                   

Log in to post a comment.