This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

CCS/EK-TM4C1294XL: How to Use "A device locator server using UDP in lwIP", Set A Device Application Title, And Read Same

Part Number: EK-TM4C1294XL

Tool/software: Code Composer Studio

I am becoming familiar with the EK-TM4C1294 ethernet interface by reading code in the example: enet_io.

Anticipating that I will need a way to find my device on a network, I see the possible solution with "A device locator server using UDP in lwIP" in the file locator.c / locator.h files.

Searching the project it does not appear that this code is used much. For example "Set A Device Application Title" is never called to set the string with a title (that I can see.)

Also is there a software for windows that would find devices announcing their pretense in the network using this locator?

I would assume something like arp -a but which returns not only the IP address, MAC but also the rest of the fields in the locator.

Thanks,

(Forrest) Lee Erickson

  • Puzzling over this more I found with a <ctrl>H search on "LocatorAppTitleSet" code in enet_io.c which is setting the title.
    Starting at line 644:
    // Setup the device locator service.
    //
    LocatorInit();
    LocatorMACAddrSet(pui8MACArray);
    LocatorAppTitleSet("EK-TM4C1294XL enet_io");


    I still need a way to read this information from a client PC.
  • Hi Forrest,

    Not really an expert here. But I think the LocatorInit() is setting up an UDP discovery response in anticipation of a client trying to find the server. The client will send out its own multicast message in search of the server, which the server then responds to. The client can repeat sending this multicast message in regular intervals until the server responds.

    You might want to check your local IT department on what Windows network query commands are possible to locate services on the network. I did some Google searching and didn't really come across commands. I found the command dns -sd but it didn't really work for me. I will suggest you find out from your IT network expert about this.
  • Hello Charles,

    Thanks for getting back to me. I think we are on the same page.
    Yes, I think another way to phrase my question would be, I am looking for just what client can FIND the server and read the information set up in the UDP on the TM4C1294XL server.

    The files in the folder named utility> locator.h make mention of ....

    // This function is called by the lwIP TCP/IP stack when it receives a UDP
    // packet from the discovery port. It produces the response packet, which is
    // sent back to the querying client.

    But I have not figured out that "querying client".

    I would think that just about every user application for the TM4C1294XL as a web server has the problem of finding the server.

    Thanks,
    Forrest Erickson
  • Hi Forrest,
    The comment you are referring to refers to the LocatorReceive() function.

    Please refer to the locator.c where the LocatorReceive() is defined. The LocatorReceive() is a callback function which is invoked when an UDP datagram is received. Please see how the LocatorReceive() callback is registered using udp_recv() in the LocatorInit() function. As you can see the server is waiting for some query from the clients. Upon receiving an UDP datagram the LocatorReceive is called, it then evaluate if the datagram is of a discovery packet. If the received packet is of a discovery packet, it will then send a response.
  • Regarding,

    Charles Tsai said:
    Hi Forrest,
    The comment you are referring to refers to the LocatorReceive() function.

    Please refer to the locator.c where the LocatorReceive() is defined. The LocatorReceive() is a callback function which is invoked when an UDP datagram is received. Please see how the LocatorReceive() callback is registered using udp_recv() in the LocatorInit() function. As you can see the server is waiting for some query from the clients. Upon receiving an UDP datagram the LocatorReceive is called, it then evaluate if the datagram is of a discovery packet. If the received packet is of a discovery packet, it will then send a response.



    Thanks Charles this helps.

    My stream of thought follows.

    The file locator.c has code setting up the listener on port 23.  I infer the port number from the udp_bind statement which follows the set up of the udp_rec Protocol Control Block.
        // Create a new UDP port for listening to device locator requests.
        //
        pcb = udp_new();
        udp_recv(pcb, LocatorReceive, NULL);
        udp_bind(pcb, IP_ADDR_ANY, 23);

    The LocatorReceive function tests the UDP packet and if it passes returns a response.  From the same file:
    //*****************************************************************************
    //
    // This function is called by the lwIP TCP/IP stack when it receives a UDP
    // packet from the discovery port.  It produces the response packet, which is
    // sent back to the querying client.
    //
    //*****************************************************************************
    static void
    LocatorReceive(void *arg, struct udp_pcb *pcb, struct pbuf *p,
                   struct ip_addr *addr, u16_t port)
    {
        uint8_t *pui8Data;
        uint32_t ui32Idx;

        //
        // Validate the contents of the datagram.
        //
        pui8Data = p->payload;
        if((p->len != 4) || (pui8Data[0] != TAG_CMD) || (pui8Data[1] != 4) ||
           (pui8Data[2] != CMD_DISCOVER_TARGET) ||
           (pui8Data[3] != ((0 - TAG_CMD - 4 - CMD_DISCOVER_TARGET) & 0xff)))
        {
            pbuf_free(p);
            return;
        }

     //
        // The incoming pbuf is no longer needed, so free it.
        //
        pbuf_free(p);

        //
        // Allocate a new pbuf for sending the response.
        //
        p = pbuf_alloc(PBUF_TRANSPORT, sizeof(g_pui8LocatorData), PBUF_RAM);
        if(p == NULL)
        {
            return;
        }

        //
        // Calculate and fill in the checksum on the response packet.
        //
        for(ui32Idx = 0, g_pui8LocatorData[sizeof(g_pui8LocatorData) - 1] = 0;
            ui32Idx < (sizeof(g_pui8LocatorData) - 1); ui32Idx++)
        {
            g_pui8LocatorData[sizeof(g_pui8LocatorData) - 1] -=
                g_pui8LocatorData[ui32Idx];
        }

        //
        // Copy the response packet data into the pbuf.
        //
        pui8Data = p->payload;
        for(ui32Idx = 0; ui32Idx < sizeof(g_pui8LocatorData); ui32Idx++)
        {
            pui8Data[ui32Idx] = g_pui8LocatorData[ui32Idx];
        }

        //
        // Send the response.
        //
        udp_sendto(pcb, p, addr, port);



        //
        // Free the pbuf.
        //
        pbuf_free(p);
    }

    So what I want is a client which sends the appropriate UDP datagram to meet the conditional tests and receive back the formulated response and tell me success (the server was found).

    Any idea, Is the queering UDP datagram a well defined industry standard (comes from a library some where?) with a name or written case by case?


    And of course, thanks for reading this far.

  • Hi Forrest,
    I'm not an expert on the UDP discovery. However, I found below links that may be helpful in your understanding.

    support.biamp.com/.../TCP_and_UDP_discovery_methods
    michieldemey.be/.../
    en.wikipedia.org/.../Simple_Service_Discovery_Protocol
  • I created a program in Processing to send a UDP Broadcast and receive a unicast reply with the data from the Locator server on the TIVA.

    Here is a working version.

    I am putting some more polish on this and will upload to github when I figure out the upload process.

    /**
     * udp_broadcast. Created by modifying the Proccessing udp_multicast example.
     *Lee Erickson
     * Date: 20180527
     * Trying to broad cast to a TIVI Launchpad device
     * The TIVA device UDP port apears to be on 23.
     * The ti file locator.c defines a sequence of four bytes it wants to receive.
     * These defines are used to describe the device locator protocol.
     #define TAG_CMD                 0xff
     #define TAG_STATUS              0xfe
     #define CMD_DISCOVER_TARGET     0x02
     */

    // TAG_CHECK_BYTE formula as per locator.c in LocatorReceive function.
    byte TAG_CMD = byte(0xFF);
    byte TAG_STATUS = byte(0xFE);
    byte CMD_DISCOVER_TARGET = byte(0x02);
    byte TAG_CHECK_BYTE = byte((0 - TAG_CMD - 4 - CMD_DISCOVER_TARGET) & 0xff);

    // IP addresses and UDP port numbers.
    String BROADCAST_IP_ADDRESS = "255.255.255.255";
    String MULTICAST_IP_ADDRESS = "224.0.0.1";
    String MY_IP_ADDRESS = "192.168.1.29";
    int UDP_PORT = 23;

    // import UDP library
    import hypermedia.net.*;

    UDP udp;  // the UDP object

    /**
     * init the frame and the UDP object.
     */
     
    void setup() {
    // Setup Broadcast by setting up multicast????
      size( 255, 255 );
      background( 32 );  // dark gray backround
     
      udp = new UDP( this, UDP_PORT, MULTICAST_IP_ADDRESS );
      udp.loopback(false);  // Suppress our own broadcast.
      udp.log(true);  //This will show the UDP trafic out and into the PC running this software.

    //  udp.setReceiveHandler(this.myCustomReceiveHandler);
      udp.setReceiveHandler("myCustomReceiveHandler");

      // Setup listen and wait constantly for incomming data
      udp.listen( true );
      println("We are listening");

      // Turn on broadcast
      udp.broadcast(true);
      // ... well, just verifies if it's really a multicast socket and blablabla
      println( "init as Multicast socket ... " + udp.isMulticast() );
    //  println( "init as Broadcast socket ... " + udp.isBroadcast() );
      println( "UDP joins a group  ... "+udp.isJoined() );
    //  println( "UDP Broadcast on?  ... " + udp.broadcast(true) );
      println("Click mouse in window to send broadcast and locate devices.");
     
    }

    // process events
    void draw() {
    }


    /**
     * on mouse click :
     * send the TI UDP data on mouse click.
     */
    void mouseClicked() {
      println ("Moused clicked.\n");

     // Tivia Locator UDP string creation.
     // This works with the full Launchpad conditional test  
      byte[] bdata = new byte[4];
      bdata[0] = TAG_CMD;
      bdata[1] = byte(0x04);
      bdata[2] = CMD_DISCOVER_TARGET;
      bdata[3] = byte(TAG_CHECK_BYTE);

      //String sLocator
      String sLocator = str(bdata[0] + bdata[1] + bdata[2] + bdata[3]);
      println( "Sending TI Locator Broadcast. " );
      udp.send( bdata, BROADCAST_IP_ADDRESS, UDP_PORT ); // = send( data, group_ip, port );
    } // mouseClicked

     
    // Custom receiver handler to get data from the client which responded to the broadcast.
    void myCustomReceiveHandler( byte[] data, String ip, int port ) {
      String removeMAC = "";
      String remoteAppTitle = "";
      String remoteIPaddress = ip;
      byte tempdata[] = new byte[255];

    // Write to the drawing window
      textSize(32);
      text("Got:  ", 0,20);
      for (int i =0; i< data.length ; i++){
        text(hex(data[i]), i*32,41);
        print(hex(data[i]));
      }

    //The broadcast to find the Locator is 4 byets so lets ignore them.
      if (data.length >4) {
      // Write to console.
        println("\n\nNew Device Located! ");
        println("The device address is: " + ip + " and port: " + port);
        //print("myReceived data: ");
        //println(" ");

        print("Hungry for devices boys and girls? ");

        // Lets parse out some data!
        print("Here is your big mac: ");
        for (int i = 9; i<=14; i++){
           print(hex(data[i]));
        } 
     
        print("\nWhat is your name? (What is your quest?): ");
        //Parse out the "AppTitleSet" locator service field.
        for (int i = 19; (i<64 && data[i]!=0) ; i++){
           print(char(data[i]));
           tempdata[i-19] = data[i];     

        }// parsing.
    //    String str2 = new String(tempdata);
        String str2 = new String(data,19,63);
        println("\nAs a string: " +str2);

      }//If data > 4

    } //  myCustomReceiveHandler(byte[] message, String ip, int port)
     
    //End.

  • Screen shot of result of locating two TM4C1294XL devices on a network.

  • Hi Forrest,
    Glad that you got it working. Will you send the screenshot again? It is not view-able.
  • There is mention of a locator service in this application note

    www.ti.com/lit/ug/tidu951/tidu951.pdf
    and this
    
    www.ti.com/lit/ug/tidu951/tidu951.pdf

    This second document explain how to locate in the TivaWare folder and use the "finder" program TI has provided for this Locator Server function in the example code.
    See:  C:\ti\TivaWare_C_Series-2.1.4.178\tools\bin\finder.exe
    The source code is at:  C:\ti\TivaWare_C_Series-2.1.4.178\tools\finder





  • My Processing solution is now pushed to github.

    See: github.com/.../master
  • Thank you Forrest for sharing.

    The finder application is another tool to find the Tiva device on the network.