Not able to receive response of the sent UDP packets using GCDAsyncSocket
Asked Answered
C

2

21

I am making an app to send UDP packets in order to switch on a LED bulb. I have been able to perform all the actions when I am connecting to the Ad-hoc created by the Wifi bridge.

Now, I want to configure the Wifi bridge so that it can connect to my main router. I have the AT command set to perform this procedure but somehow I am not able to receive the response form the Wifi bridge for the commands which I am sending to it.

The procedure is as follows:-

  • Step 1 : Send UDP message to the LAN broadcast IP address of "10.10.100.255" and port of 48899 => "Link_Wi-Fi"
    All Wifi bridges on the LAN will respond with their details. Response is "10.10.100.254, ACCF232483E8"

  • Step 2 : (optional for changing settings on the wifi bridge): Then send "+ok" to the LimitlessLED Wifi Bridge. Send UDP message to the response IP address returned from step 1 "10.10.100.254" => "+ok"

  • Step 3 : (optional for changing settings on the wifi bridge): After that you may send AT commands (ending with \r\n) to the module.

The code for sending the UDP packets is as follows

-(void)configureWifi{

    counter++;
    NSString *host = @"10.10.100.255";
    if ([host length] == 0)
    {
        [self logError:@"Address required"];
        return;
    }

    int port = 48899; //[portField.text intValue];
    if (port <= 0 || port > 65535)
    {
        [self logError:@"Valid port required"];
        return;
    }
    NSString *msg = @"Link_Wi-Fi";
    NSData *data = [msg dataUsingEncoding:NSUTF8StringEncoding];
    NSLog(@"the message sent is %@", data);
    [udpSocket sendData:data toHost:host port:port withTimeout:-1 tag:tag];

}

Now in order to setup the socket and to receive the data I am using these two delegate methods:

 - (void)setupSocket
{
    // Setup our socket.
    // The socket will invoke our delegate methods using the usual delegate paradigm.
    // However, it will invoke the delegate methods on a specified GCD delegate dispatch queue.
    // 
    // Now we can configure the delegate dispatch queues however we want.
    // We could simply use the main dispatc queue, so the delegate methods are invoked on the main thread.
    // Or we could use a dedicated dispatch queue, which could be helpful if we were doing a lot of processing.
    // 
    // The best approach for your application will depend upon convenience, requirements and performance.
    // 
    // For this simple example, we're just going to use the main thread.

    udpSocket = [[GCDAsyncUdpSocket alloc] initWithDelegate:self delegateQueue:dispatch_get_main_queue()];

    NSError *error = nil;

    if (![udpSocket bindToPort:0 error:&error])
    {
        [self logError:FORMAT(@"Error binding: %@", error)];
        return;
    }
    if (![udpSocket beginReceiving:&error])
    {
        [self logError:FORMAT(@"Error receiving: %@", error)];
        return;
    }

    [self logInfo:@"Ready"];
}

and to Receive data this is the method which is note getting called after sending the UDP packets. This is the delegate method of the GCDAsyncUdpSocket class which I have used in my project in order to send and receive the UDP packets.

- (void)udpSocket:(GCDAsyncUdpSocket *)sock didReceiveData:(NSData *)data
                                               fromAddress:(NSData *)address
                                         withFilterContext:(id)filterContext
{
    NSString *msg = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
    if (msg)
    {
        [self logMessage:FORMAT(@"RECV: %@", msg)];
    }
    else
    {
        NSString *host = nil;
        uint16_t port = 0;
        [GCDAsyncUdpSocket getHost:&host port:&port fromAddress:address];

        [self logInfo:FORMAT(@"RECV: Unknown message from: %@:%hu", host, port)];
    }
}

Once I am able to receive the response I will be able to send the next AT commands in order to configure the Bridge.

Thanks. Any help will be appreciated.

Coppola answered 18/4, 2015 at 6:2 Comment(7)
The first question I always ask when someone says they are sending a broadcast packet is "How do you know that this is your broadcast address?" Especially within the 10. class A address space. You are sending to 10.10.100.255, but that is only your broadcast address if everyone else on your segment thinks it is the broadcast address. IP stacks on plenty of devices have been written to think that 10.255.255.255 is the broadcast address for a 10.x.x.x network. Can you send a ping to the .255 address and observe as many responses as you would expect?Jongjongleur
In your setup method you bind to port 0, allowing the OS to pick a free port and then you begin listening on the socket. How did you communicate this socket number to those who want to contact your app?Jongjongleur
@Jongjongleur We are trying to send the UDP packet to "10.10.100.255" or 255.255.255.255 in order to receive that how many Wi-Fi Bridges are active. Once we will be able to receive the response of that then we have to send all the UDP packets to "10.10.100.254" or whatever Wi-Fi bridge we want to access.Succinate
@Jongjongleur for the Second comment I am not able to understand the importance of Port binding. Which Port I should usually choose to bind in the Setup method.Succinate
My advice is to trust your code, and not trust the device. Instead, use a separate tool to check that the devices are actually receiving and responding to you. Use Terminal.app to ping the 10.10.100.255 address - If a bunch of light bulbs don't respond that tells you either they are unreachable from your location or they don't think 10.10.100.255 is an address they should be listening to. If they do respond then the problem is indeed within your application.Jongjongleur
A fairly complete description of a socket is that it is the combination of the IP address and the port. 10.10.100.153:44172 would be a "socket" if a device with IP address 10.10.100.153 was listening for traffic on port 44172. It is not so important what port you use on your end, but it is very important that your IP address and port number are somehow conveyed to the device that wants to talk back to you. Usually the partner learns of your socket address when you contact them, but broadcast packets can get tricky.Jongjongleur
You said at the end of your writeup "Once I am able to receive the response..." Is that the response described in Step 1? If so, you need to use Terminal.app like this, without quotes of course: "ping -c3 10.10.100.255" You should a bunch of "duplicate" responses that equal the number of light bulbs on your network. If not, your computer isn't able to reach the light bulbs for some reason. Troubleshoot your network until the ping response is full of lightbulbs responding to your pings.Jongjongleur
D
2

Here are the troubleshooting steps I recommend that you use :

1- I'm assuming you are using ARC so make sure that your udpSocket variable has a strong reference throughout the asynchronous communication. If it is being freed, then that could explain the absence of a callback.

2- Make sure the communication is really happening the way you think it is. Use a software such as Wireshark to capture the packets being exchanged on the network. This should allow you to confirm that your packets do get sent upon calling sendData: and it will also allow you to confirm whether or not you are getting a reply back.

3- Make sure you are using the GCDAsyncUdpSocket properly. Considering you want to broadcast a message, you shouldn't be calling bindToPort:error: in your setupSocket method. Instead you should be calling enableBroadcast:error:. Considering you also want to receive packets after broadcasting, you should use the connectToHost:onPort:error: method to change the state of the socket to allow for bidirectional communication. After that is done, you can replace your usage of sendData:toHost:port:withTimeout:tag: by sendData:withTimeout:tag:. Finally, you can call beginReceiving: so that the delegate gets called for any incoming packets.

4- If this still doesn't get you through it, I recommend that you read throughly the documentation of the GCDAsyncUdpSocket which is very well documented.

Decastro answered 24/4, 2015 at 5:43 Comment(0)
K
1

You can trouble shoot the problem using Wireshark or any network capture tool. We use to work in similar kind of project where we used Wireshark extensively. If packet has reached device(Z-Wave ) it will send out some sort of Ack. this will help to make sure packets are getting out.

Kanazawa answered 6/5, 2015 at 21:34 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.