Hundemeier / sacn

A simple ANSI E1.31 (aka sACN) module for python.
MIT License
47 stars 21 forks source link

Can't send and receive on the same device. #41

Open robertwb opened 2 years ago

robertwb commented 2 years ago

I'd like to be able to test out a sACN app on a single device, however the following bare-bones code doesn't work for me:

import sacn
import time

HOST = 'localhost'
PORT = 5569

# Whichever of these two is second fails with OSError: [Errno 48] Address already in use
# followed by AttributeError: 'sACNsender' object has no attribute '_sender_handler'
# I would expect the receiver to be a server socket and the sender to be a client socket.
receiver = sacn.sACNreceiver(HOST, PORT)
receiver.start()

sender = sacn.sACNsender(HOST, PORT)
sender.start()

@receiver.listen_on('universe', universe=1)
def callback(packet):
    print(packet.dmxData)

sender.activate_output(1)
sender[1].dmx_data = (1, 2, 3, 4)

# I would expect callback to get called and print the packet out.

time.sleep(10)
sender.stop()
receiver.stop()

I get the same issue if I create the sender and receiver in separate processes as well.

Hundemeier commented 2 years ago

I think you just need to change one line:

import sacn
import time

HOST = 'localhost'
PORT = 5569

# Whichever of these two is second fails with OSError: [Errno 48] Address already in use
# followed by AttributeError: 'sACNsender' object has no attribute '_sender_handler'
# I would expect the receiver to be a server socket and the sender to be a client socket.
receiver = sacn.sACNreceiver(HOST)
receiver.start()

sender = sacn.sACNsender(HOST, PORT)
sender.start()

@receiver.listen_on('universe', universe=1)
def callback(packet):
    print(packet.dmxData)

sender.activate_output(1)
sender[1].dmx_data = (1, 2, 3, 4)

# I would expect callback to get called and print the packet out.

time.sleep(10)
sender.stop()
receiver.stop()

Notice the change to receiver = sacn.sACNreceiver(HOST).

robertwb commented 2 years ago

Sweet, this works. I'll have to admit I'm a bit confused tough--is the sender always sending to the default port no matter the port parameter passed?

Hundemeier commented 2 years ago

is the sender always sending to the default port no matter the port parameter passed?

Yes. The sender always sends out packets with a destination port of 5568. Sender: Some port5568 Receiver: 5568Some Port

Note how the parameter for the constructor is called bind_port. This means only the source port of the UDP packets is changed (by opening a socket on that port via the OS).

The sACN spec this library is based on is a bit vague about the correct port number for destination and source ports. Section 9.3 "Allocation of Multicast Addresses" only briefly mentions the value 5568.

I must admit, that the API is a bit confusing though: the source port for the sender can be changed, but not the destination port. The receiver only has the port for listening as a parameter and accepts any packets regardless of source port.