Capture UDP Multicast

Posted on
Tue Mar 27, 2018 8:24 pm
mclass offline
Posts: 315
Joined: May 13, 2015
Location: Melbourne, Australia

Capture UDP Multicast

I have a Daikin SkyFi air conditioner that appears to send a UDP broadcast addressed to 255.255.255.255 on port 55222 at approximately 8 second intervals (thanks Wireshark!)

To avoid collision with scripts that I'm using to control and get the status of the air conditioner (so I can capture any changes made by the wall mounted Daikin control panel), I am attempting to use the Daikin UDP broadcast to trigger a status update. My first thought was to use the Cynical Network plugin, but discovered that this doesn't support UDP (clearly stated in the plugin documentation, thank you!).

After a bit of hunting on the internet, I have attempted the following script:
Code: Select all
import socket

UDP_IP = "XXX.XXX.XXX.XXX"  #tried both the sending IP and the 255.255.255.255 destination address
UDP_PORT = 55222

sock = socket.socket(socket.AF_INET, # Internet
                     socket.SOCK_DGRAM) # UDP
sock.bind((UDP_IP, UDP_PORT))

while True:
    data, addr = sock.recvfrom(1024) # buffer size is 1024 bytes
    indigo.server.log(data,"Received Message") ## interim code for testing purposes!


but get the following error:
Code: Select all
 Script Error                    embedded script: [Errno 49] Can't assign requested address
   Script Error                    Exception Traceback (most recent call shown last):

     embedded script, line 8, at top level
     File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/socket.py", line 228, in meth
       return getattr(self._sock,name)(*args)
error: [Errno 49] Can't assign requested address


Any suggestions as to how I can achieve this by improving the script or by other means of Indigo detecting the UDP broadcast (not really interested in the package contents, only the presence of the broadcast!)

Thanks in anticipation!

mclass

Posted on
Tue Mar 27, 2018 8:41 pm
FlyingDiver offline
User avatar
Posts: 7221
Joined: Jun 07, 2014
Location: Southwest Florida, USA

Re: Capture UDP Multicast

You're trying to listen on that port (not send to it), so you want to use your own IP address. Or use an empty string ('') and it'll bind to the localhost address.

See the echo server example: https://docs.python.org/2/library/socket.html#example

In this case, you're not echoing back to the client, but you're echoing to the log. :)

BTW - Multicast and Broadcast are not the same thing. This is a broadcast.

joe (aka FlyingDiver)
my plugins: http://forums.indigodomo.com/viewforum.php?f=177

Posted on
Sun Apr 01, 2018 10:58 am
MartinG offline
Posts: 116
Joined: Aug 19, 2016

Re: Capture UDP Multicast

I do something similar to monitor what my Rako lighting system controller does - this device sends UDP broadcasts on 255.255.255.255:9761 every time a lighting scene is executed. I haven't yet integrated it into Indigo, but feel free to copy & modify if it's helpful.

A python script to receive and decode the messages is pretty straightforward:

Code: Select all
import datetime
import socket

roomdescriptions = {
    9: 'Master Bedroom',
    10: 'Master Ensuite',
    17: 'First Floor Landing',
    25: 'Hall',
    33: 'Master Dressing Room',
    41: 'Kitchen',
    49: 'Upper Landing',
    57: 'Lounge',
    65: 'Outside',
    73: 'Dining Room',
    81: 'Family Room',
    89: 'Landing Blind',
    97: 'Lower Stairs',
    105: 'Upper Stairs'
}

instructiondescriptions = {
    0: 'Off',
    1: 'Fade Up',
    2: 'Fade Down',
    3: 'Scene 1',
    4: 'Scene 2',
    5: 'Scene 3',
    6: 'Scene 4',
    8: 'Ident',
    12: 'Level Set',
    13: 'Store',
    15: 'Stop',
    45: 'Custom 232',
    46: 'Event Control',
    47: 'Holiday',
    48: 'Run Macro',
    49: 'Set Scene',
    50: 'Fade',
    51: 'Toggle Channel',
    52: 'Set Level',
}

print("Started Rakobridge Listener")

# creates socket object
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)

print"Socket created",
host = ''
port = 9761

s.bind((host, port))
print "& connected."

# Find Rakobridge
RakobridgeIP = socket.gethostbyname('mybridge.local')
print "Found Rako Bridge on", RakobridgeIP, " Now waiting for data..."

while True:
    data, addr = s.recvfrom(1024)

    if (addr[0] == RakobridgeIP) & (data[0] == 'S'): # if from Rakobridge and initial character is 'S'
        print str(datetime.datetime.now()).split('.')[0], '(', # print a data stamp and prepare to display raw Hex data

            # print the raw packet data in hex
        for character in data:
            print character.encode('hex'),
        else:
            print ')',

        # decode packet and convert data string characters to int
        room = ord(data[3])
        channel = ord(data[4])
        instruction = ord(data[5])

        if room in roomdescriptions:
            roomdesc = roomdescriptions[room]
        else:
            roomdesc = 'UNKNOWN ROOM'

        if instruction in instructiondescriptions:
            instructiondesc = instructiondescriptions[instruction]
        else:
            instructiondesc = 'UNKNOWN INSTRUCTION'

        if channel == 0:
            channeldesc = 'All Channels'
        else:
            channeldesc = 'Channel ' + str(channel)

        print roomdesc, channeldesc, instructiondesc,

        if instructiondesc == 'Set Scene':
            scenenum = ord(data[7])
            print scenenum,

        if instructiondesc == 'Set Level':
            level = int(ord(data[7]) / 255)
            print level,

        if instructiondesc == 'Fade':
            if ord(data[6]) == 0x81:
                print 'Down',
            elif ord(data[6]) == 0x80:
                print 'Up',
            else:
                print 'Unknown',

        print

    #else:
        #print "Other status message.", addr

Posted on
Tue Apr 03, 2018 2:17 am
mclass offline
Posts: 315
Joined: May 13, 2015
Location: Melbourne, Australia

Re: Capture UDP Multicast

Thank you both for your contributions, and am making slow progress - both with this application and my knowledge of Python!!

mclass

Posted on
Wed Apr 04, 2018 8:33 pm
mclass offline
Posts: 315
Joined: May 13, 2015
Location: Melbourne, Australia

Re: Capture UDP Multicast

Thanks again for your input. In case there are others facing a similar problem, the code snippet I am using is as follows:

Code: Select all
## DEBUGGING
debug = 0 ## Set to 1 to print debug messages, to 0 for no debug

import socket

## Set variables to use in listening for UDP broadcast
UDP_IP = '' ## All destination IP's
UDP_PORT = 55222  ## Port on which UDP message sent
DaikinIP = "XXX.XXX.XXX.XXX"  ## Address from which UDP message sent )insert your own here!)

##  Wait for UDP broadcast before requesting status

# create socket object
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
## & log if debug enabled
if debug:
   indigo.server.log("Socket created")
   
#Set socket options to avoid "Address already in use" errors
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)

# Bind to the socket
s.bind((UDP_IP, UDP_PORT))
## & log if debug enabled
if debug:
   indigo.server.log("Socket connected""")

while True: ## Wait for UDP message
    data, addr = s.recvfrom(1024)
   
    if (addr[0] == DaikinIP): # if message is from Daikin     
       if debug:
          indigo.server.log ("UDP message received from SkyFi")
       s.close() # close the port
       if debug:
          indigo.server.log ("Socket closed")
       break # Break from the While loop and send the status request
if debug:
   indigo.server.log ("Completed test for UDP Message & requesting status")

## ... continue with code to request, receive and parse status



The setsockopt line was included to avoid "Address already in use" errors, but I am not convinced that it's yet successful :(

In preparing this post, I have realised that I need to add some form of error handling in the event that the UDP broadcast is not received, to log that and to bypass the remainder of the status request. This may happen if the Daikin AC unit is off line (eg powered off).

As a Python newbie, I would appreciate any feedback (be cruel :? ) on the code, and any suggestions on improvement welcome.

mclass

Posted on
Fri Apr 27, 2018 2:30 am
agame offline
Posts: 514
Joined: Jul 13, 2017
Location: Melbourne, Australia

Re: Capture UDP Multicast

would be so good if someone could cobble together a UDP multicast plugin with similar capabilities to what the Cynical Network plugin does for TCP (ie, manage the connection, and simplify creation of events based on the received data.)

my use case is listening for sensor changes on a Global Cache iTach Flex.

Posted on
Mon Apr 30, 2018 9:48 am
howartp offline
Posts: 4559
Joined: Jan 09, 2014
Location: West Yorkshire, UK

Re: Capture UDP Multicast

agame wrote:
would be so good if someone could cobble together a UDP multicast plugin with similar capabilities to what the Cynical Network plugin does for TCP (ie, manage the connection, and simplify creation of events based on the received data.)


Hear, hear.

I thought as much the other day, but it’s not an area I want to enter with my plugins.

Anyone?


Sent from my iPhone using Tapatalk Pro

Posted on
Mon Apr 30, 2018 12:11 pm
FlyingDiver offline
User avatar
Posts: 7221
Joined: Jun 07, 2014
Location: Southwest Florida, USA

Re: Capture UDP Multicast

I don't currently have a use (that I can think of), but it's right in line with a bunch of my other plugins. I'll see if I can whip something up.

joe (aka FlyingDiver)
my plugins: http://forums.indigodomo.com/viewforum.php?f=177

Posted on
Mon Apr 30, 2018 2:41 pm
FlyingDiver offline
User avatar
Posts: 7221
Joined: Jun 07, 2014
Location: Southwest Florida, USA

Re: Capture UDP Multicast

First test release: https://github.com/FlyingDiver/Indigo-U ... g/0.0.1-b1

Create a device specifying the port you want to listen for messages on. Create an event to trigger on state changes for that device.

joe (aka FlyingDiver)
my plugins: http://forums.indigodomo.com/viewforum.php?f=177

Posted on
Mon Apr 30, 2018 6:49 pm
mclass offline
Posts: 315
Joined: May 13, 2015
Location: Melbourne, Australia

Re: Capture UDP Multicast

Hi Joe!

I was delighted to see the arrival of this new plugin, as I have been wrestling since my last post with a script of my own - with limited success :(

I have trialled your plugin, and get the following error message:
Code: Select all
Traceback (most recent call last):
  File "plugin.py", line 99, in runConcurrentThread
UnicodeDecodeError: 'ascii' codec can't decode byte 0xc0 in position 0: ordinal not in range(128)

   UDL Listener Error              plugin runConcurrentThread function returned or failed (will attempt again in 10 seconds)

With my limited knowledge, I suggest that there's something in the UDP message that the plugin is having trouble with! The Daikin AC sends the message at approximately 8 second intervals (or so Wireshark tells me!) and as far as I can tell the message remains unchanged.

With detailed debugging turned on the log records:
Code: Select all
Started plugin "UDL Listener 0.0.1"
   UDL Listener                    Starting UDP Listener
   UDL Listener Debug              Called deviceStartComm(self, device): Daikin Listener (1033420646)
   UDL Listener Debug              Daikin Listener: Device Current Version = 0
   UDL Listener Debug              Daikin Listener: Device Version is up to date
   UDL Listener Debug              Daikin Listener: Starting device (udpListener)
   UDL Listener Threaddebug        Daikin Listener: UDP timeout
   UDL Listener Threaddebug        Daikin Listener: UDP timeout
   UDL Listener Threaddebug        Daikin Listener: UDP timeout
   UDL Listener Threaddebug        Daikin Listener: UDP timeout
   UDL Listener Threaddebug        Daikin Listener: UDP timeout
   UDL Listener Threaddebug        Daikin Listener: UDP timeout
   UDL Listener Threaddebug        Daikin Listener: UDP timeout
   UDL Listener Threaddebug        Daikin Listener: UDP timeout
   UDL Listener Threaddebug        Daikin Listener: UDP timeout
   UDL Listener Threaddebug        Daikin Listener: UDP timeout
   UDL Listener Threaddebug        Daikin Listener: UDP timeout
   UDL Listener Threaddebug        Daikin Listener: UDP timeout
   UDL Listener Threaddebug        Daikin Listener: UDP timeout
   UDL Listener Threaddebug        Daikin Listener: UDP timeout
   UDL Listener Threaddebug        Daikin Listener: UDP timeout
   UDL Listener Threaddebug        Daikin Listener: UDP timeout
   UDL Listener Threaddebug        Daikin Listener: UDP timeout
   UDL Listener Threaddebug        Daikin Listener: UDP timeout
   UDL Listener Threaddebug        Daikin Listener: UDP timeout
   UDL Listener Threaddebug        Daikin Listener: UDP timeout
   UDL Listener Threaddebug        Daikin Listener: UDP timeout
   UDL Listener Error              Error in plugin execution runConcurrentThread:

Traceback (most recent call last):
  File "plugin.py", line 99, in runConcurrentThread
UnicodeDecodeError: 'ascii' codec can't decode byte 0xc0 in position 0: ordinal not in range(128)

   UDL Listener Error              plugin runConcurrentThread function returned or failed (will attempt again in 10 seconds)
   UDL Listener Error              Error in plugin execution runConcurrentThread:



Would love to get this working properly!! And in true "Oliver Twist style" could I request MORE, and include means to optionally log the UDP messages received?
Thanks and keep up the good work!!
mclass

Posted on
Mon Apr 30, 2018 6:52 pm
FlyingDiver offline
User avatar
Posts: 7221
Joined: Jun 07, 2014
Location: Southwest Florida, USA

Re: Capture UDP Multicast

I suspect it's crashing on the log message. The few tests I was doing had all-ASCII in the message data. Hmm. Give me a minute.

joe (aka FlyingDiver)
my plugins: http://forums.indigodomo.com/viewforum.php?f=177

Posted on
Mon Apr 30, 2018 6:55 pm
FlyingDiver offline
User avatar
Posts: 7221
Joined: Jun 07, 2014
Location: Southwest Florida, USA

Re: Capture UDP Multicast


joe (aka FlyingDiver)
my plugins: http://forums.indigodomo.com/viewforum.php?f=177

Posted on
Tue May 01, 2018 12:57 am
mclass offline
Posts: 315
Joined: May 13, 2015
Location: Melbourne, Australia

Re: Capture UDP Multicast

Thanks for the speedy response!

I downloaded the Beta2 file, but it appears it contains b1 still.

Would you check and make sure that I'm not mistaken?

Thanks
mclass

Posted on
Tue May 01, 2018 4:49 am
agame offline
Posts: 514
Joined: Jul 13, 2017
Location: Melbourne, Australia

Re: Capture UDP Multicast

oh wow! thanks so much!!!
I'm experimenting with the beta2 download.
no error messages.... but also no sign of inbound events yet. will continue to fiddle.

Posted on
Tue May 01, 2018 5:29 am
agame offline
Posts: 514
Joined: Jul 13, 2017
Location: Melbourne, Australia

Re: Capture UDP Multicast

hmm. still no joy processing any messages...so far as I can tell.

I'm trying to monitor a Global Cache Flex Sensor/Relay 'cable' accessory. It allows a multicast broadcast of sensor status on a configurable port. Have tried a few such as 9131 and 9132.

Also have tried listening for a periodic beacon message that device broadcasts as follows:

The iTach Flex periodic UDP beacon message allows discovery of iTach Flex units on the network. The beacon is sent as a UDP packet to the multicast IP address 239.255.250.250, multicast group destination MAC 01:00:5E:7F:FA:FA, and destination port 9131
.

in all likelihood its a problem at my end but waiting to see if anyone else has success??

Who is online

Users browsing this forum: No registered users and 4 guests