UDP Broadcast/Device Discovery on iOS?
Asked Answered
C

1

6

I am working on trying develop a means of discovering Logitech Harmony Hub devices on my local network, from an iOS app. The concept is inspired by this NODE.JS project, which seems to send out a UDP broadcast to the 255.255.255.255 address, and then procures the Logitech's IP address (which is all I'm after). When testing the NODE.JS project on my home network from my Mac, it successfully finds the Logitech Harmony Hub.

I am using CocoaASyncSocket, and must admit, my understanding of how UDP broadcast/discovery works may be askew here. Here's what I'm doing;

import UIKit
import CocoaAsyncSocket

class ViewController: UIViewController, GCDAsyncUdpSocketDelegate {

var address = "255.255.255.255"
var port:UInt16 = 5224
var socket:GCDAsyncUdpSocket!
var socketReceive:GCDAsyncUdpSocket!
var error : NSError?

override func viewDidLoad() {
    super.viewDidLoad()

    let message = "_logitech-reverse-bonjour._tcp.local.\n61991".dataUsingEncoding(NSUTF8StringEncoding)

    socket = GCDAsyncUdpSocket(delegate: self, delegateQueue: dispatch_get_main_queue())
    socket.sendData(message, toHost: address, port: port, withTimeout: 1000, tag: 0)

    do {
        try socket.bindToPort(port)
    } catch {
        print(error)
    }

    do {
        try socket.enableBroadcast(true)
    } catch {
        print(error)
    }

    do {
        try socket.beginReceiving()
    } catch {
        print(error)
    }

}

    func udpSocket(sock: GCDAsyncUdpSocket!, didConnectToAddress address: NSData!) {
        print("didConnectToAddress");
    }

    func udpSocket(sock: GCDAsyncUdpSocket!, didNotConnect error: NSError!) {
        print("didNotConnect \(error)")
    }

    func udpSocket(sock: GCDAsyncUdpSocket!, didSendDataWithTag tag: Int) {
        print("didSendDataWithTag")
    } 

    func udpSocket(sock: GCDAsyncUdpSocket!, didNotSendDataWithTag tag: Int, dueToError error: NSError!) {
        print("didNotSendDataWithTag")
    }

func udpSocket(sock: GCDAsyncUdpSocket!, didReceiveData data: NSData!, fromAddress address: NSData!, withFilterContext filterContext: AnyObject!) {

    var host: NSString?
    var port1: UInt16 = 0
    GCDAsyncUdpSocket.getHost(&host, port: &port1, fromAddress: address)
    print("From \(host!)")

    let gotdata: NSString = NSString(data: data!, encoding: NSUTF8StringEncoding)!
    print(gotdata)

}

}

When I compile this, the only response I get is the message I just sent out;

didSendDataWithTag
From ::ffff:192.168.1.101
_logitech-reverse-bonjour._tcp.local.
61991
From 192.168.1.101
_logitech-reverse-bonjour._tcp.local.
61991

I fear that I have a conceptual understanding issue with the broadcast here, and am sincerely hoping that someone may be able to point me to a resource or help to understand why I'm not getting any response from the device in my code.

Thanks!

Chong answered 11/2, 2016 at 23:1 Comment(0)
S
3

From the looks of the code it seems that you have only implemented half of the solution. The way it works is:

  • A broadcast message is sent to port 5224. This message includes the string logitech-reverse-bonjour._tcp.local. plus the port number that the Harmony should connect back to - in your case you have hardcoded 61991.
  • Presumably the Harmony receives this packet, recognises the message and then initiates a connection back to the device that sent the broadcast on the nominated port (61991 in this case).

Since your app is not listening on this port you don't get any response. This is implemented in the responseCollector.js file in the node.js project

Sindysine answered 12/2, 2016 at 0:38 Comment(3)
Thanks for clarifying, @Paulw11. That was extremely helpful. To further fulfill this, do I need to implement some sort of a socket.connectToHost function to listen on the host as you specify? I'm researching how to implement that function in my code.Chong
It won't be connectToHost but rather a listen function - the Harmony hub will connect to your deviceSindysine
Thanks @Paulw11. I'm marking your answer correct as your answer definitely clarifies how the UDP broadcast works, though please do not be offended as I may need to open another question about how to actually achieve your suggestion using CocoaASyncSocket, as I've yet to figure out how to simultaneously broadcast and listen for the response.Chong

© 2022 - 2024 — McMap. All rights reserved.