Skip to content

UdpSocket

Overview

UdpSocket is a global table that allows communication to other devices via UDP. The UdpSocket API works using the control or audio network. This API is commonly used to communicate with a device using the devices custom UDP control protocol.

Generally, a UdpSocket must be created and opened before data can be sent to and read from the socket.

UdpSocket.

Return Type Comment
UdpSocket.New() UdpSocket object Creates new UdpSocket object.

UdpSocket.New()

New() creates a UdpSocket object as a global table.

MyUdp = UdpSocket.New()

Up to 8 UdpSocket objects can be simultaneously requested with separate calls. When a socket is closed (see below), it is available for use again with another New call.

UdpSocketName.

The following methods and properties are available for a UdpSocket object with name UdpSocketName.

Return Type Comment
UdpSocketName.ID Integer The 1-8 number of the socket in the script.
UdpSocketName:Open(ip, port) Method Called by the script to bind the socket to an IP address (string or 32-bit integer) and port number (integer, zero for automatic).
UdpSocketName:Close() Method Closes the socket, making it available for another allocation. The existing object must not be reused.
UdpSocketName:Send(ip, port, data) Method Sends the specified table of data to a specific IP and port.
UdpSocketName:GetSockName() Method Called by the script to return the current IP address and port.
UdpSocketName.Data(socket, packet) Callback Function that will be called when data is available.
UdpSocketName.MulticastTtl Integer the number of hops allowed when transmitting multicast, default 1.
UdpSocketName.MulticastLoop Bool Indicates if sent multicast should be looped to self, default true.
UdpSocketName.JoinMulticast(multicastIp, interfaceIp) Method Used to Join a Multicast

UdpSocketName.ID

The 1-8 number of the socket in the script.

print(MyUdp.ID)                     >> 1

Up to 8 UdpSocket objects can be simultaneously requested with separate calls. When a socket is closed (see below), it is available for use again with another New call.

UdpSocketName:Open(ip, port)

Called by the script to bind the socket to the IP address (string or 32-bit integer) and port (0-65535) of the source Control or Audio network, and source port number (integer, zero for automatic).

MyUdp:Open("192.168.1.20", 48631)

For online usage, if the script specifies anything other than the control network IP address or audio IP address, the port will not open properly. The script should specify the IP of the audio or control network as reported by the Device API.

MyUdp:Open(Device.LocalUnit.ControlIP, 48631)
MyOtherUdp:Open(Device.LocalUnit.AudioIP, 48631)

Alternately, if the script specifies “0.0.0.0” for the IP address, then the control network will be used automatically.

MyUdp:Open("0.0.0.0", 48631)

This automatic option allows binding before an IP address has been obtained during power on. Otherwise, the script should wait until there is a valid IP address in the Device table before opening the numbered port.

If a specific port number is not needed, the port may be selected automatically by the device by specifying port 0.

MyUdp:Open("192.168.1.20", 0)

Remember that some devices will respond to any port that called them while others will only send to a specific port. This may prevent the usage of automatic port selection with some devices.

If multiple sockets are needed, for example to control two different devices keeping their responses separate, ensure that two different ports are used or let the device assign ports automatically.

--Bad
MyUdp:Open(Device.LocalUnit.ControlIP, 48631)
MyOtherUdp:Open(Device.LocalUnit.ControlIP, 48631)

--Good
MyUdp:Open(Device.LocalUnit.ControlIP, 48631)
MyOtherUdp:Open(Device.LocalUnit.ControlIP, 4001)

--Good
MyUdp:Open(Device.LocalUnit.ControlIP, 0)
MyOtherUdp:Open(Device.LocalUnit.ControlIP, 0)

Finally, this method returns “true” if it is able to create a port at the provided IP and port number. This would require valid IP, port number, that there was not one already created at that port and IP and that there are not too many UDP ports. This can be used to test that the Opening was successful.

udpOpen = StationUdp:Open(Device.LocalUnit.AudioIP, 0)
if udpOpen then
    --do some stuff
end

UdpSocketName:Close()

Closes the socket, making it available for another allocation. The existing object must not be reused.

MyUdp = UdpSocket.New()
--do a bunch of stuff

MyUdp:Close()
MyNewUdp = UdpSocket.New()

UdpSocketName:Send(ip, port, data)

Sends to a specific IP and port (0-65535) the specified table of data (must fit in a packet).

MyUdp:Send("192.168.1.101", 48631, "CS 1 0\r\n")

Information from the device table can be used to ensure the correct IP address is used.

MyUdp:Send(Device.RemoteUnit.DanteIP, 48631, "CS 1 0\r\n")

While you can Open a IP Socket using 0.0.0.0 or Device.LocalUnit.ControlIP as described above, you need to check Device.LocalUnit.ControlIP for non-zero to know it is assigned before you send any date. See the example below.

UdpSocketName:GetSockName()

Returns the current IP address and port. This is useful to get the port information being used if the socket was bound to an automatic port. Sending will not work until a valid IP has been assigned so this can be used as a check.

receivedIP, receivedPort = MyUdp:GetSockName()
print("IP: " .. receivedIP .. " Port: " .. receivedPort)

UdpSocketName.Data(socket, packet)

Callback function that will be called when data is available. It should accept two arguments: the socket object and the data packet table.

function HandleData(socket, packet)
    -- Do Stuff
end

MyUdp.Data = HandleData

The socket object provides information about the socket on which the message was received.

The data packet table has three elements making up the received data:

Description
.Address Source IP Address of received packet
.Port Source Port of received packet
.Data Data payload of received packet

UdpSocketName.MulticastTtl

Used to set the Multicast Time To Live, the number of hops allowed when transmitting multicast:

MyUdp.MulticastTtl = 10

The default is 1. If non default values are desired, they must be set prior to Open() to be recognized. Applied to the sending UDP port.

UdpSocketName.MulticastLoop

Indicates if sent multicast should be looped to self:

MyUdp.MulticastLoop = false

The default is true. If non default values are desired, they must be set prior to Open() to be recognized. Applied to the sending UDP port.

UdpSocketName.JoinMulticast(multicastIp, interfaceIp)

  • multicastIp must be 224.0.0.0 through 239.255.255.255

  • interfaceIp is optional, specifies which interface IP will receive multicast traffic.

If UdpPort:Open(bindIp, bindPort) specified a non-zero bindIp, then interfaceIp can specify the NIC to receive on. Otherwise, interfaceIp can just be the same as bindIp or absent.

Any UDP port can send multicast just by specifying the multicast address, though setting the MulticastTtl and MulticastLoop values should be considered.

To receive multicast, call JoinMulticast() after calling Open(). If the same port is used to send multicast, setting MulticastTtl and MulticastLoop values should be considered prior to the Open() call.

JoinMulticast() will return a success/fail boolean. It will fail if the multicast IP is not specified, invalid, or out of range. It will fail if the interface IP is specified and does not match the non-zero IP in the successful Open() call. It will fail if the sockets interface can’t add the specified multicast address.

Usage Examples

The following examples illustrate how these can be used:

Example 1 – Putting it all together

This example shows how UdpSocket is typically used

function HandleData(socket, packet)
    --Info about receiving socket and packet
    print("Socket ID: " .. socket.ID)
    receivedIP, receivedPort = socket:GetSockName()
    print("Socket IP: " .. receivedIP)
    print("Socket Port: " .. receivedPort)
    print("Packet IP: " .. packet.Address)
    print("Packet Port: " .. packet.Port)

    --Do stuff with the received packet
    print("Packet Data: \r" .. packet.Data)
end

MyUdp = UdpSocket.New()
MyUdp:Open(Device.LocalUnit.ControlIP, 0)
MyUdp.Data = HandleData
MyUdp:Send("192.168.1.101", 48631, "CS 1 0\r\n")

Example 2 - Waiting until the Device.LocalUnit.IP has been assigned before sending any data.

The above example can be improved by testing that Device.LocalUnit.ControlIP is valid before using it. This needed because at powerup, the IP address can take some time to be assigned depending on the configuration. Therefore, we do these checks within a Timer EventHandler to repeatedly check and only begin sending UDP messages once the IP address is ready.

udpInitialized = false
MyUdp = UdpSocket.New()

function UDPStartTimerClick ()

    --check if initialized, i.e. IP valid and UDP port open
    if udpInitialized == false then

        --before can send message need to determine IP address is valid IP address
        if Device.LocalUnit.ControlIP ~= nil then

            --have an IP Address
            print("Valid IP: " .. tostring(Device.LocalUnit.ControlIP))
            MyUdp:Open(Device.LocalUnit.ControlIP, 0)
            MyUdp.Data = HandleData
            udpInitialized = true --have done initial setup, so set this as true so don't need to do again.
        else
            --IP address not ready, Try again next Timer pass
            print("Not ready Online Path with Device IP: " .. tostring(Device.LocalUnit.ControlIP))
        end
    else
        --UDP Socket is open with valid IP,
        --Now can send the data and do all the work each timer pass
        MyUdp:Send(otherUnitIP, port, messageSendFlashUnit)
    end
end

UDPStartTimer = Timer.New()
UDPStartTimer.EventHandler = UDPStartTimerClick
UDPStartTimer:Start(1)

Example 3 - Who’s it from?

This socket object and data packet .Address and .Port elements can be used to determine the source of the packet when handling the data, and perform a different action depending on the source.

function HandleData(socket, packet)
    --Do Stuff with the received packet
    if packet.Address == source1 then
        --Do stuff with the packet data
    elseif packet.Address == source2 then
        --Do different stuff with the packet data
    end
end

Example 3 - Multicast

ctrlIp = "0.0.0.0"
loopbackIp = "127.0.0.1"
multicastIp = "224.1.1.1"

RxUdp = UdpSocket.New()
RxUdp.MulticastTtl = 5
RxUdp.MulticastLoop = false
RxUdp:Open(ctrlIp)
RxUdp:JoinMulticast(multicastIp, ctrlIp)

function RxGotData (udpTable, packet)
    print("RxUdpData:", packet.Data, "From:", packet.Address, packet.Port)
end

RxUdp.Data = RxGotData
rxIp, rxPort = RxUdp:GetSockName()
print("Rx Name:", rxIp, rxPort)

TxUdp = UdpSocket.New()
TxUdp.MulticastTtl = 1
TxUdp.MulticastLoop = true
TxUdp:Open(ctrlIp)
TxUdp:JoinMulticast(multicastIp, ctrlIp)

function TxGotData (udpTable, packet)
    print("TxUdpData:", packet.Data, "From:", packet.Address, packet.Port)
end

TxUdp.Data = TxGotData
txIp, txPort = TxUdp:GetSockName()
print("Tx Name:", txIp, txPort)

TxUdp:Send(multicastIp, txPort, "Tx Sent Multicast Data to Tx")
print("Tx Multicast Sent:", multicastIp, txPort)
TxUdp:Send(loopbackIp, txPort, "Tx Sent Unicast Dat to Tx")
print("Tx Unicast Sent:", loopbackIp, txPort)

RxUdp:Send(multicastIp, txPort, "Rx Sent Multicast Data to Tx")
print("Rx Multicast Sent:", multicastIp, txPort)
RxUdp:Send(loopbackIp, txPort, "Rx Sent Unicast Data to Tx")
print("Rx Unicast Sent:", loopbackIp, txPort)

TxUdp:Send(multicastIp, rxPort, "Tx Sent Multicast Data to Rx")
print("Tx Multicast Sent:", multicastIp, rxPort)
TxUdp:Send(loopbackIp, rxPort, "Tx Sent Unicast Dat to Rx")
print("Tx Unicast Sent:", loopbackIp, rxPort)

RxUdp:Send(multicastIp, rxPort, "Rx Sent Multicast Data to Rx")
print("Rx Multicast Sent:", multicastIp, rxPort)
RxUdp:Send(loopbackIp, rxPort, "Rx Sent Unicast Data to Rx")
print("Rx Unicast Sent:", loopbackIp, rxPort)

output:

Offline script debugging started at Thu 01-23-2025 19:22:13
Rx Name:    0.0.0.0 61333
Tx Name:    0.0.0.0 61334
Tx Multicast Sent:  224.1.1.1   61334
Tx Unicast Sent:    127.0.0.1   61334
Rx Multicast Sent:  224.1.1.1   61334
Rx Unicast Sent:    127.0.0.1   61334
Tx Multicast Sent:  224.1.1.1   61333
Tx Unicast Sent:    127.0.0.1   61333
Rx Multicast Sent:  224.1.1.1   61333
Rx Unicast Sent:    127.0.0.1   61333
RxUdpData:  Tx Sent Multicast Data to Rx    From:   192.168.137.1   38639
TxUdpData:  Tx Sent Multicast Data to Tx    From:   192.168.137.1   38639
RxUdpData:  Tx Sent Unicast Dat to Rx   From:   127.0.0.1   38639
TxUdpData:  Tx Sent Unicast Dat to Tx   From:   127.0.0.1   38639
RxUdpData:  Rx Sent Multicast Data to Rx    From:   192.168.137.1   38383
TxUdpData:  Rx Sent Multicast Data to Tx    From:   192.168.137.1   38383
RxUdpData:  Rx Sent Unicast Data to Rx  From:   127.0.0.1   38383
TxUdpData:  Rx Sent Unicast Data to Tx  From:   127.0.0.1   38383