UDP broadcast support


#21

going live??

Back in September as far as I know.

Chuck pasted some code showing the basics 9 days ago.


#22

Thanks.

Does anyone have answer to the second question. Again, currently I use Node.js (on a pc). Each command sends a net.connect, the actual data on the socket, and a socket.close. I need to try to port this to Hubitat to eliminate the pc Hub and also the alternative Kasa Cloud connection.

Ideas?


#23

It would be great to see a slightly more fully worked example of an App that uses UDP, including processing the response.

I'm not sure if I'm missing something, but I think I'm sending a correct GetService packet to LIFX on 255.255.255.255:56700, but I'm not seeing any responses in the parse method, it doesn't look like that method is being called at all. I'm not ruling out mistakes on my part though, obviously.

Any thoughts on how to debug this? Here's the initialize and parse methods - not really ready to share the rest of the code in public yet

def initialize() {
  state.sequence = 1
  def buffer = []
  def getServiceSequence = makePacket(buffer, 0, messageTypes().DEVICE.GET_SERVICE, false, false, [])
  def rawBytes = asByteArray(buffer)
  log.debug "raw bytes: ${rawBytes}"
  String stringBytes = hubitat.helper.HexUtils.byteArrayToHexString(rawBytes)
  log.debug "sending bytes: ${stringBytes}"
  def myHubAction = new hubitat.device.HubAction(
        stringBytes,
        hubitat.device.Protocol.LAN,
        [
                type              : hubitat.device.HubAction.Type.LAN_TYPE_UDPCLIENT,
                destinationAddress: "255.255.255.255:56700",
                encoding          : hubitat.device.HubAction.Encoding.HEX_STRING
        ]
  )
  def response = sendHubCommand(myHubAction)
  log.debug "response from sendHubCommand ${response}"
}
 
def parse(String description) {
  log.debug "parse description: ${description}"
}

#24

For what it's worth, I'm not seeing any errors in the logs. I'm trying to monitor UDP activity on port 56700 with Wireshark but not seeing anything showing up, but then I could have misconfigured it due to a lack of familiarity.


#25

A bit more progress...
Now that I've got a slightly better understanding of Wireshark I can see that I'm broadcasting (I think) a UDP packet, but I'm just not getting any response. If I send the packet using PacketSender then I'm getting responses from my LIFX devices! The only apparent differences (apart from the IP/MAC address of the sender) is that HE is setting the don't fragment flag in the datagram, and also setting a header checksum, the TTL is different (64 from packet sender and 128 from HE). The payload for LIFX looks to be the same apart from the sequence number

This is very puzzling.


#26

My current conjecture is that the socket on the hub has been closed before the LIFX devices have responded, not sure whether Wireshark would see any messages in that case. Is there another parameter that needs specifying to ensure that the socket stays open?


#27

Or do I need to specify a callback handler given that this is inside an App rather than a Device Handler?


#28

Hmm, the callback does seem to have sort of worked, I am getting back a response, but just the one when I would have expected a response from each LIFX device - still, I can probably get to work on parsing the response.


#29

I've now switched to creating a device handler instead of an app. This works more consistently, and the parse() method is getting data each time, but unfortunately only from the first LIFX device that responds to the broadcast, so I don't think I can make much more progress using a UDP broadcast.

I may have to look into the new websockets support, but it's tricky without any documentation.


#30

Instead of using an automatic discovery, could you simply write a Driver that allows the user to specify the TCP/IP address of a specific LIFX bulb? Have the users use DHCP Reservations in their router to make sure the LIFX bulbs' IP addresses do not change.

I simplify a lot of my LAN connected drivers by forgoing the automatic discovery process and having users manually enter IP addresses. While not as convenient, it does work very very and is much simpler and very reliable.

Just an idea... :slight_smile:


#31

I'm not sure if it will work, but it might.

I did attempt to talk to a bulb that way by using the EchoRequest message, but that was in the app rather than in a device handler. Not sure if I need to specify the MAC address with a unicast message, the docs imply that it might be necessary, but that's possibly only the case with a broadcast message.

I may give that another go - if that works then I may be able to loop through the whole local subnet requesting a response.


#32

That's a shame, I can use the EchoRequest, but it definitely seems to need the MAC as well as the IP address, so, the question is whether there's a way to get the MAC from an IP address.


#33

In fact I can use the broadcast address in conjunction with the MAC to talk to a bulb, so that might well work if I follow your suggestion @ogiewon just using the MAC instead of IP, at least for the time being.


#34

Rob, It works. I am doing a similar to a TP-Link Installation Application using UDP. What I do:

Determine the network address for the hub and parse out the final address portion. Gives a string like;

"192.168.2."

I then run an if statement from 1 to 255 and poll for the devices one at a time (using a command that returns the system command). Since it is so fast, I collect this data into a repository (state.responseData).

I will then parse the results one at a time. Good news: The return string has the MAC and IP address for the devices in plain text. Just have to change the IP from Hex code then populate. The characteristics (alias, model, etc) for the device is in the polled message. Sample output from the log for two devices (it takes < 2 seconds to run the entire gauntlet of 255 IPs):

app:8202018-12-29 09:11:42.063 am debug[deviceNetworkId:null, description:index:00, mac:50C7BFAB4884, ip:c0a80065, port:270f, type:LAN_TYPE_UDPCLIENT, payload:D0F28F889D4]

app:8202018-12-29 09:11:42.190 am debug[deviceNetworkId:null, description:index:00, mac:50C7BF177E24, ip:c0a80067, port:270f, type:LAN_TYPE_UDPCLIENT, payload:D0F281AADF8]


#35

I just need to find a command that LIFX devices will respond to without the packet already containing the MAC address


#36

Thanks to a nudge from @chuck.schwer I now have successful communication :smiley:


#37

Any chance you have that nudge (and or code) somewhere for the rest of us @rob ?


#38

Receiving all replies. Is there any secret in broadcast to be able to receive ALL of the responses. Currently, I only receive the first response receive then the port shuts down. Hope is there is some setting to keep the port open for 5 or so seconds.

I have a kluge that is working to find all my devices; however, I do not like it. Essentially, I extract the hub IP and parse for the segment (XXX.XXX.XXX). Then send get status command to all of the 254 possible addresses. Sub-optimal, but it works.


#39

The nudge was mostly reassurance that it does actually work talking to LIFX bulbs, which led me to find the mistake in my code.


#40

I'm doing the same thing as you (and thanks again for the idea), it would be great if the port could be made to stay open, e.g. by returning something from the parse method. But it seems fast enough.