diff options
| author | CoprDistGit <infra@openeuler.org> | 2023-05-18 05:57:16 +0000 |
|---|---|---|
| committer | CoprDistGit <infra@openeuler.org> | 2023-05-18 05:57:16 +0000 |
| commit | ff73b93fdfa8835f28d45fff0baff90e4cf3d7f4 (patch) | |
| tree | 3caa4d55bb9b230bb76cf215530efb9b043c2e2a | |
| parent | 25e58d8ee061009d0dd59f591d19ddecb5b07cc3 (diff) | |
automatic import of python-sacn
| -rw-r--r-- | .gitignore | 1 | ||||
| -rw-r--r-- | python-sacn.spec | 570 | ||||
| -rw-r--r-- | sources | 1 |
3 files changed, 572 insertions, 0 deletions
@@ -0,0 +1 @@ +/sacn-1.9.0.tar.gz diff --git a/python-sacn.spec b/python-sacn.spec new file mode 100644 index 0000000..341ee6a --- /dev/null +++ b/python-sacn.spec @@ -0,0 +1,570 @@ +%global _empty_manifest_terminate_build 0 +Name: python-sacn +Version: 1.9.0 +Release: 1 +Summary: sACN / E1.31 module for easy handling of DMX data over ethernet +License: MIT License +URL: https://www.github.com/Hundemeier/sacn +Source0: https://mirrors.nju.edu.cn/pypi/web/packages/2b/3a/5f7fa70575492ed6fbbf3cb2093059c6d38ae634cd96f3b6de0930720371/sacn-1.9.0.tar.gz +BuildArch: noarch + + +%description +## Usage +### Sending +To use the sending functionality you have to use the `sACNsender`. +```python +import sacn +import time +sender = sacn.sACNsender() # provide an IP-Address to bind to if you want to send multicast packets from a specific interface +sender.start() # start the sending thread +sender.activate_output(1) # start sending out data in the 1st universe +sender[1].multicast = True # set multicast to True +# sender[1].destination = "192.168.1.20" # or provide unicast information. +# Keep in mind that if multicast is on, unicast is not used +sender[1].dmx_data = (1, 2, 3, 4) # some test DMX data +time.sleep(10) # send the data for 10 seconds +sender.stop() # do not forget to stop the sender +``` +You can activate an output universe via `activate_output(<universe>)` and then change the attributes of this universe +via `sender[<universe>].<attribute>`. To deactivate an output use `deactivate_output(<universe>)`. The output is +terminated like the [E1.31][e1.31] describes it on page 14. +If you want to flush manually and the sender thread should not send out automatic, use the +`sACNsender.manual_flush` option. This is useful when you want to use a fixture that is using more than one universe +and all the data on multiple universes should send out at the same time. +Tip: you can get the activated outputs with `get_active_outputs()` and you can move an output with all its settings +from one universe to another with `move_universe(<from>, <to>)`. +Available Attributes for `sender[<universe>].<attribute>` are: + * `destination: str`: the unicast destination as string. (eg "192.168.1.150") Default: "127.0.0.1" + * `multicast: bool`: set whether to send out via multicast or not. Default: False + If True the data is send out via multicast and not unicast. + * `ttl: int`: the time-to-live for the packets that are send out via multicast on this universe. Default: 8 + * `priority: int`: (must be between 0-200) the priority for this universe that is send out. If multiple sources in a + network are sending to the same receiver the data with the highest priority wins. Default: 100 + * `preview_data: bool`: Flag to mark the data as preview data for visualization purposes. Default: False + * `dmx_data: tuple`: the DMX data as a tuple. Max length is 512 and for legacy devices all data that is smaller than + 512 is merged to a 512 length tuple with 0 as filler value. The values in the tuple have to be [0-255]! +`sACNsender` Creates a sender object. A sender is used to manage multiple sACN universes and handles their output. +DMX data is send out every second, when no data changes. Some changes may be not send out, because the fps +setting defines how often packets are send out to prevent network overuse. So if you change the DMX values too +often in a second they may not all been send. Vary the fps parameter to your needs (Default=30). + * `bind_address: str`: the IP-Address to bind to. + Provide an IP-Address to bind to if you want to send multicast packets from a specific interface. + * `bind_port: int`: optionally bind to a specific port. Default=5568. It is not recommended to change the port. + Change the port number if you have trouble with another program or the sACNreceiver blocking the port + * `source_name: str`: the source name used in the sACN packets. See the [standard][e1.31] for more information. + * `cid: tuple`: the cid. If not given, a random CID will be generated. See the [standard][e1.31] for more information. + * `fps: int` the frames per second. See explanation above. Has to be >0. Default: 30 + * `universeDiscovery: bool` if true, universe discovery messages are send out via broadcast every 10s. Default: True + * `sync_universe: int` set a specific universe used in the sync-packets. Default: 63999 +When manually flushed, the E1.31 sync feature is used. So all universe data is send out, and after all data was send out +a sync packet is send to all receivers and then they are allowed to display the received data. Note that not all +receiver implemented this feature of the sACN protocol. +Example for the usage of the manual_flush: +```python +import sacn +import time +sender = sacn.sACNsender() +sender.start() +sender.activate_output(1) +sender.activate_output(2) +sender[1].multicast = True +sender[2].multicast = True +sender.manual_flush = True # turning off the automatic sending of packets +sender[1].dmx_data = (1, 2, 3, 4) # some test DMX data +sender[2].dmx_data = (5, 6, 7, 8) # by the time we are here, the above data would be already send out, +# if manual_flush would be False. This could cause some jitter +# so instead we are flushing manual +time.sleep(1) # let the sender initialize itself +sender.flush() +sender.manual_flush = False # keep manual flush off as long as possible, because if it is on, the automatic +# sending of packets is turned off and that is not recommended +sender.stop() # stop sending out +``` +### Receiving +To use the receiving functionality you have to use the `sACNreceiver`. +```python +import sacn +import time +# provide an IP-Address to bind to if you want to send multicast packets from a specific interface +receiver = sacn.sACNreceiver() +receiver.start() # start the receiving thread +# define a callback function +@receiver.listen_on('universe', universe=1) # listens on universe 1 +def callback(packet): # packet type: sacn.DataPacket + print(packet.dmxData) # print the received DMX data +# optional: if multicast is desired, join with the universe number as parameter +receiver.join_multicast(1) +time.sleep(10) # receive for 10 seconds +# optional: if multicast was previously joined +receiver.leave_multicast(1) +receiver.stop() +``` +The usage of the receiver is way more simple than the sender. +The `sACNreceiver` can be initialized with the following parameters: + * `bind_address: str`: Provide an IP-Address to bind to if you want to receive multicast packets from a specific interface. + * `bind_port: int`: Default: 5568. It is not recommended to change this value! + Only use when you are know what you are doing! +Please keep in mind to not use the callbacks for time consuming tasks! +If you do this, then the receiver can not react fast enough on incoming messages! +Functions: + * `join_multicast(<universe>)`: joins the multicast group for the specific universe. + * `leave_multicast(<universe>)`: leave the multicast group specified by the universe. + * `get_possible_universes()`: Returns a tuple with all universes that have sources that are sending out data and this + data is received by this machine + * `register_listener(<trigger>, <callback>, **kwargs)`: register a listener for the given trigger. + You can also use the decorator `listen_on(<trigger>, **kwargs)`. Possible trigger so far: + * `availability`: gets called when there is no data for a universe anymore or there is now data + available. This gets also fired if a source terminates a stream via the stream_termination bit. + The callback should get two arguments: `callback(universe, changed)` + * `universe: int`: is the universe where the action happened + * `changed: str`: can be 'timeout' or 'available' + * `universe`: registers a listener for the given universe. The callback gets only one parameter, the DataPacket. + You can also use the decorator `@listen_on('universe', universe=<universe>)`. + The callback should have one argument: `callback(packet)` + * `packet: DataPacket`: the received DataPacket with all information + * `remove_listener(<callback>)`: removes a previously registered listener regardless of the trigger. + This means a listener can only be removed completely, even if it was listening to multiple universes. + If the function never was registered, nothing happens. + Note: if a function was registered multiple times, this remove function needs to be called only once. + * `remove_listener_from_universe(<universe>)`: removes all listeners from the given universe. + This does only have effect on the 'universe' listening trigger. + If no function was registered for this universe, nothing happens. +### DataPacket +This is an abstract representation of an sACN Data packet that carries the DMX data. This class is used internally by +the module and is used in the callbacks of the receiver. +The DataPacket provides following attributes: + * `sourceName: str`: a string that is used to identify the source. Only the first 64 bytes are used. + * `priority: int`: the priority used to manage multiple DMX data on one receiver. [1-200] Default: 100 + * `universe: int`: the universe for the whole message and its DMX data. [1-63999] + * `sequence: int`: the sequence number. Should increment for every new message and can be used to check for wrong + order of arriving packets. + * `option_StreamTerminated: bool`: True if this packet is the last one of the stream for the given universe. + * `option_PreviewData: bool`: True if this data is for visualization purposes. + * `option_ForceSync: bool`: True if this should only function in a synchronized state. + * `dmxStartCode: int`: the start code for the data tuple. [1-255] Default: 0x00 for streaming level data. See + [Alternate START Codes](https://tsp.esta.org/tsp/working_groups/CP/DMXAlternateCodes.php) for more information. + * `dmxData: tuple`: the DMX data as tuple. Max length is 512 and shorter tuples getting normalized to a length of 512. + Filled with 0 for empty spaces. +## Development +Some tools are used to help with development of this library. These are [flake8](https://flake8.pycqa.org), [pytest](https://pytest.org) and [coverage.py](https://coverage.readthedocs.io). +Install those tools with pip: +``` +pip install flake8 pytest pytest-timeout coverage +``` +`flake8` checks for formatting issues and can be run with `flake8` or `python -m flake8` in the root directory of this repository. +`pytest` is used for unit testing and can be executed with `pytest` or `python -m pytest` in the root directory of this repository. +By default, this skips the integration test, which uses real hardware I/O and might not run in every configuration. +Use the flag `--run-integration-tests` to run the additional tests (e.g. `python -m pytest --run-integration-tests`) +It is useful to check if the test coverage changed with `coverage run -m pytest` and then `coverage html`, which generates a `htmlcov/index.html` file with all the information. +### Changelog + * 1.9.0: The behavior of multicast sending and receiving is now unified across most operating systems. This means Windows no longer requires to set a `bind_address` to be able to use multicast or universe discovery. (Thanks to mthespian! See #42 for more information) + * 1.8.1: Calling `stop` on a sender or receiver now closes the underlying socket too. Note: after stopping a sender or receiver, it can not be started again with `start`. (See #39 for more information) + * 1.8.0: Added function for removing a listener on a receiver by universe. See `sACNreceiver.remove_listener_from_universe(<universe>)` for more information. + * 1.7.1: Small changes that might improve timing on the sender. (Thanks to mthespian! See #36 for more information) + * 1.7.0: Added function for removing a listener on a receiver. See `sACNreceiver.remove_listener(<callback>)` for more information. + * 1.6.4: Functionality related to sending of sACN data is now mostly covered by tests. Removed undocumented parameters for `sACNsender.start()`. + * 1.6.3: Functionality related to receiving sACN data is now mostly covered by tests. Fixed a bug, where an exception was thrown on the first `DataPacket` when the stream-termination option was set. (Additional thanks to mthespian! See #31 for more information) + * 1.6.2: Test coverage of sub-module `messages` is now 100%. Fixed a bug where a too long source name did not throw an exception. + Fixed a bug where invalid DMX data could be set on the `DataPacket`. (Thanks to mthespian! See #30 for more information) + * 1.6.1: Fixed a bug, where the DMX start code was not set on received packets (Thanks to mthespian! See #29 for more information) + * 1.6: Added dmxStartCode property to DataPacket (Thanks to mthespian! see #27 for more information) + * 1.5: Performance improvement: Deleted debugging statements in hot path of packet sending and receiving (Thanks to shauneccles! See #25 for more information) + * 1.4.6: Fix: When creating a DataPacket with invalid DMX start codes (i.e. not `0x00`) an exception is thrown (Thanks to niggiover9000! See #11 for more information) + * 1.4.5: When using a manual flush, only a specified list of universes can be flushed (Thanks to CrazyIvan359! See #22 for more information) + * 1.4.4: The universe used for the sACN-sync messages can now be set when creating a `sACNsender` (Thanks to CrazyIvan359! See #21 for more information) + * 1.4.3: The sequence number of the sync-packet when using manual flush was not increased (Thanks to @BlakeGarner ! See #19 for more information) + * 1.4.2: The internal logging of the receiver_thread and output_thread was using the root logger instead of its module-logger. (Thanks to @mje-nz ! See #18 for more information) + * 1.4: Added a manual flush feature for sending out all universes at the same time. Thanks to ahodges9 for the idea. +[e1.31]: http://tsp.esta.org/tsp/documents/docs/E1-31-2016.pdf + +%package -n python3-sacn +Summary: sACN / E1.31 module for easy handling of DMX data over ethernet +Provides: python-sacn +BuildRequires: python3-devel +BuildRequires: python3-setuptools +BuildRequires: python3-pip +%description -n python3-sacn +## Usage +### Sending +To use the sending functionality you have to use the `sACNsender`. +```python +import sacn +import time +sender = sacn.sACNsender() # provide an IP-Address to bind to if you want to send multicast packets from a specific interface +sender.start() # start the sending thread +sender.activate_output(1) # start sending out data in the 1st universe +sender[1].multicast = True # set multicast to True +# sender[1].destination = "192.168.1.20" # or provide unicast information. +# Keep in mind that if multicast is on, unicast is not used +sender[1].dmx_data = (1, 2, 3, 4) # some test DMX data +time.sleep(10) # send the data for 10 seconds +sender.stop() # do not forget to stop the sender +``` +You can activate an output universe via `activate_output(<universe>)` and then change the attributes of this universe +via `sender[<universe>].<attribute>`. To deactivate an output use `deactivate_output(<universe>)`. The output is +terminated like the [E1.31][e1.31] describes it on page 14. +If you want to flush manually and the sender thread should not send out automatic, use the +`sACNsender.manual_flush` option. This is useful when you want to use a fixture that is using more than one universe +and all the data on multiple universes should send out at the same time. +Tip: you can get the activated outputs with `get_active_outputs()` and you can move an output with all its settings +from one universe to another with `move_universe(<from>, <to>)`. +Available Attributes for `sender[<universe>].<attribute>` are: + * `destination: str`: the unicast destination as string. (eg "192.168.1.150") Default: "127.0.0.1" + * `multicast: bool`: set whether to send out via multicast or not. Default: False + If True the data is send out via multicast and not unicast. + * `ttl: int`: the time-to-live for the packets that are send out via multicast on this universe. Default: 8 + * `priority: int`: (must be between 0-200) the priority for this universe that is send out. If multiple sources in a + network are sending to the same receiver the data with the highest priority wins. Default: 100 + * `preview_data: bool`: Flag to mark the data as preview data for visualization purposes. Default: False + * `dmx_data: tuple`: the DMX data as a tuple. Max length is 512 and for legacy devices all data that is smaller than + 512 is merged to a 512 length tuple with 0 as filler value. The values in the tuple have to be [0-255]! +`sACNsender` Creates a sender object. A sender is used to manage multiple sACN universes and handles their output. +DMX data is send out every second, when no data changes. Some changes may be not send out, because the fps +setting defines how often packets are send out to prevent network overuse. So if you change the DMX values too +often in a second they may not all been send. Vary the fps parameter to your needs (Default=30). + * `bind_address: str`: the IP-Address to bind to. + Provide an IP-Address to bind to if you want to send multicast packets from a specific interface. + * `bind_port: int`: optionally bind to a specific port. Default=5568. It is not recommended to change the port. + Change the port number if you have trouble with another program or the sACNreceiver blocking the port + * `source_name: str`: the source name used in the sACN packets. See the [standard][e1.31] for more information. + * `cid: tuple`: the cid. If not given, a random CID will be generated. See the [standard][e1.31] for more information. + * `fps: int` the frames per second. See explanation above. Has to be >0. Default: 30 + * `universeDiscovery: bool` if true, universe discovery messages are send out via broadcast every 10s. Default: True + * `sync_universe: int` set a specific universe used in the sync-packets. Default: 63999 +When manually flushed, the E1.31 sync feature is used. So all universe data is send out, and after all data was send out +a sync packet is send to all receivers and then they are allowed to display the received data. Note that not all +receiver implemented this feature of the sACN protocol. +Example for the usage of the manual_flush: +```python +import sacn +import time +sender = sacn.sACNsender() +sender.start() +sender.activate_output(1) +sender.activate_output(2) +sender[1].multicast = True +sender[2].multicast = True +sender.manual_flush = True # turning off the automatic sending of packets +sender[1].dmx_data = (1, 2, 3, 4) # some test DMX data +sender[2].dmx_data = (5, 6, 7, 8) # by the time we are here, the above data would be already send out, +# if manual_flush would be False. This could cause some jitter +# so instead we are flushing manual +time.sleep(1) # let the sender initialize itself +sender.flush() +sender.manual_flush = False # keep manual flush off as long as possible, because if it is on, the automatic +# sending of packets is turned off and that is not recommended +sender.stop() # stop sending out +``` +### Receiving +To use the receiving functionality you have to use the `sACNreceiver`. +```python +import sacn +import time +# provide an IP-Address to bind to if you want to send multicast packets from a specific interface +receiver = sacn.sACNreceiver() +receiver.start() # start the receiving thread +# define a callback function +@receiver.listen_on('universe', universe=1) # listens on universe 1 +def callback(packet): # packet type: sacn.DataPacket + print(packet.dmxData) # print the received DMX data +# optional: if multicast is desired, join with the universe number as parameter +receiver.join_multicast(1) +time.sleep(10) # receive for 10 seconds +# optional: if multicast was previously joined +receiver.leave_multicast(1) +receiver.stop() +``` +The usage of the receiver is way more simple than the sender. +The `sACNreceiver` can be initialized with the following parameters: + * `bind_address: str`: Provide an IP-Address to bind to if you want to receive multicast packets from a specific interface. + * `bind_port: int`: Default: 5568. It is not recommended to change this value! + Only use when you are know what you are doing! +Please keep in mind to not use the callbacks for time consuming tasks! +If you do this, then the receiver can not react fast enough on incoming messages! +Functions: + * `join_multicast(<universe>)`: joins the multicast group for the specific universe. + * `leave_multicast(<universe>)`: leave the multicast group specified by the universe. + * `get_possible_universes()`: Returns a tuple with all universes that have sources that are sending out data and this + data is received by this machine + * `register_listener(<trigger>, <callback>, **kwargs)`: register a listener for the given trigger. + You can also use the decorator `listen_on(<trigger>, **kwargs)`. Possible trigger so far: + * `availability`: gets called when there is no data for a universe anymore or there is now data + available. This gets also fired if a source terminates a stream via the stream_termination bit. + The callback should get two arguments: `callback(universe, changed)` + * `universe: int`: is the universe where the action happened + * `changed: str`: can be 'timeout' or 'available' + * `universe`: registers a listener for the given universe. The callback gets only one parameter, the DataPacket. + You can also use the decorator `@listen_on('universe', universe=<universe>)`. + The callback should have one argument: `callback(packet)` + * `packet: DataPacket`: the received DataPacket with all information + * `remove_listener(<callback>)`: removes a previously registered listener regardless of the trigger. + This means a listener can only be removed completely, even if it was listening to multiple universes. + If the function never was registered, nothing happens. + Note: if a function was registered multiple times, this remove function needs to be called only once. + * `remove_listener_from_universe(<universe>)`: removes all listeners from the given universe. + This does only have effect on the 'universe' listening trigger. + If no function was registered for this universe, nothing happens. +### DataPacket +This is an abstract representation of an sACN Data packet that carries the DMX data. This class is used internally by +the module and is used in the callbacks of the receiver. +The DataPacket provides following attributes: + * `sourceName: str`: a string that is used to identify the source. Only the first 64 bytes are used. + * `priority: int`: the priority used to manage multiple DMX data on one receiver. [1-200] Default: 100 + * `universe: int`: the universe for the whole message and its DMX data. [1-63999] + * `sequence: int`: the sequence number. Should increment for every new message and can be used to check for wrong + order of arriving packets. + * `option_StreamTerminated: bool`: True if this packet is the last one of the stream for the given universe. + * `option_PreviewData: bool`: True if this data is for visualization purposes. + * `option_ForceSync: bool`: True if this should only function in a synchronized state. + * `dmxStartCode: int`: the start code for the data tuple. [1-255] Default: 0x00 for streaming level data. See + [Alternate START Codes](https://tsp.esta.org/tsp/working_groups/CP/DMXAlternateCodes.php) for more information. + * `dmxData: tuple`: the DMX data as tuple. Max length is 512 and shorter tuples getting normalized to a length of 512. + Filled with 0 for empty spaces. +## Development +Some tools are used to help with development of this library. These are [flake8](https://flake8.pycqa.org), [pytest](https://pytest.org) and [coverage.py](https://coverage.readthedocs.io). +Install those tools with pip: +``` +pip install flake8 pytest pytest-timeout coverage +``` +`flake8` checks for formatting issues and can be run with `flake8` or `python -m flake8` in the root directory of this repository. +`pytest` is used for unit testing and can be executed with `pytest` or `python -m pytest` in the root directory of this repository. +By default, this skips the integration test, which uses real hardware I/O and might not run in every configuration. +Use the flag `--run-integration-tests` to run the additional tests (e.g. `python -m pytest --run-integration-tests`) +It is useful to check if the test coverage changed with `coverage run -m pytest` and then `coverage html`, which generates a `htmlcov/index.html` file with all the information. +### Changelog + * 1.9.0: The behavior of multicast sending and receiving is now unified across most operating systems. This means Windows no longer requires to set a `bind_address` to be able to use multicast or universe discovery. (Thanks to mthespian! See #42 for more information) + * 1.8.1: Calling `stop` on a sender or receiver now closes the underlying socket too. Note: after stopping a sender or receiver, it can not be started again with `start`. (See #39 for more information) + * 1.8.0: Added function for removing a listener on a receiver by universe. See `sACNreceiver.remove_listener_from_universe(<universe>)` for more information. + * 1.7.1: Small changes that might improve timing on the sender. (Thanks to mthespian! See #36 for more information) + * 1.7.0: Added function for removing a listener on a receiver. See `sACNreceiver.remove_listener(<callback>)` for more information. + * 1.6.4: Functionality related to sending of sACN data is now mostly covered by tests. Removed undocumented parameters for `sACNsender.start()`. + * 1.6.3: Functionality related to receiving sACN data is now mostly covered by tests. Fixed a bug, where an exception was thrown on the first `DataPacket` when the stream-termination option was set. (Additional thanks to mthespian! See #31 for more information) + * 1.6.2: Test coverage of sub-module `messages` is now 100%. Fixed a bug where a too long source name did not throw an exception. + Fixed a bug where invalid DMX data could be set on the `DataPacket`. (Thanks to mthespian! See #30 for more information) + * 1.6.1: Fixed a bug, where the DMX start code was not set on received packets (Thanks to mthespian! See #29 for more information) + * 1.6: Added dmxStartCode property to DataPacket (Thanks to mthespian! see #27 for more information) + * 1.5: Performance improvement: Deleted debugging statements in hot path of packet sending and receiving (Thanks to shauneccles! See #25 for more information) + * 1.4.6: Fix: When creating a DataPacket with invalid DMX start codes (i.e. not `0x00`) an exception is thrown (Thanks to niggiover9000! See #11 for more information) + * 1.4.5: When using a manual flush, only a specified list of universes can be flushed (Thanks to CrazyIvan359! See #22 for more information) + * 1.4.4: The universe used for the sACN-sync messages can now be set when creating a `sACNsender` (Thanks to CrazyIvan359! See #21 for more information) + * 1.4.3: The sequence number of the sync-packet when using manual flush was not increased (Thanks to @BlakeGarner ! See #19 for more information) + * 1.4.2: The internal logging of the receiver_thread and output_thread was using the root logger instead of its module-logger. (Thanks to @mje-nz ! See #18 for more information) + * 1.4: Added a manual flush feature for sending out all universes at the same time. Thanks to ahodges9 for the idea. +[e1.31]: http://tsp.esta.org/tsp/documents/docs/E1-31-2016.pdf + +%package help +Summary: Development documents and examples for sacn +Provides: python3-sacn-doc +%description help +## Usage +### Sending +To use the sending functionality you have to use the `sACNsender`. +```python +import sacn +import time +sender = sacn.sACNsender() # provide an IP-Address to bind to if you want to send multicast packets from a specific interface +sender.start() # start the sending thread +sender.activate_output(1) # start sending out data in the 1st universe +sender[1].multicast = True # set multicast to True +# sender[1].destination = "192.168.1.20" # or provide unicast information. +# Keep in mind that if multicast is on, unicast is not used +sender[1].dmx_data = (1, 2, 3, 4) # some test DMX data +time.sleep(10) # send the data for 10 seconds +sender.stop() # do not forget to stop the sender +``` +You can activate an output universe via `activate_output(<universe>)` and then change the attributes of this universe +via `sender[<universe>].<attribute>`. To deactivate an output use `deactivate_output(<universe>)`. The output is +terminated like the [E1.31][e1.31] describes it on page 14. +If you want to flush manually and the sender thread should not send out automatic, use the +`sACNsender.manual_flush` option. This is useful when you want to use a fixture that is using more than one universe +and all the data on multiple universes should send out at the same time. +Tip: you can get the activated outputs with `get_active_outputs()` and you can move an output with all its settings +from one universe to another with `move_universe(<from>, <to>)`. +Available Attributes for `sender[<universe>].<attribute>` are: + * `destination: str`: the unicast destination as string. (eg "192.168.1.150") Default: "127.0.0.1" + * `multicast: bool`: set whether to send out via multicast or not. Default: False + If True the data is send out via multicast and not unicast. + * `ttl: int`: the time-to-live for the packets that are send out via multicast on this universe. Default: 8 + * `priority: int`: (must be between 0-200) the priority for this universe that is send out. If multiple sources in a + network are sending to the same receiver the data with the highest priority wins. Default: 100 + * `preview_data: bool`: Flag to mark the data as preview data for visualization purposes. Default: False + * `dmx_data: tuple`: the DMX data as a tuple. Max length is 512 and for legacy devices all data that is smaller than + 512 is merged to a 512 length tuple with 0 as filler value. The values in the tuple have to be [0-255]! +`sACNsender` Creates a sender object. A sender is used to manage multiple sACN universes and handles their output. +DMX data is send out every second, when no data changes. Some changes may be not send out, because the fps +setting defines how often packets are send out to prevent network overuse. So if you change the DMX values too +often in a second they may not all been send. Vary the fps parameter to your needs (Default=30). + * `bind_address: str`: the IP-Address to bind to. + Provide an IP-Address to bind to if you want to send multicast packets from a specific interface. + * `bind_port: int`: optionally bind to a specific port. Default=5568. It is not recommended to change the port. + Change the port number if you have trouble with another program or the sACNreceiver blocking the port + * `source_name: str`: the source name used in the sACN packets. See the [standard][e1.31] for more information. + * `cid: tuple`: the cid. If not given, a random CID will be generated. See the [standard][e1.31] for more information. + * `fps: int` the frames per second. See explanation above. Has to be >0. Default: 30 + * `universeDiscovery: bool` if true, universe discovery messages are send out via broadcast every 10s. Default: True + * `sync_universe: int` set a specific universe used in the sync-packets. Default: 63999 +When manually flushed, the E1.31 sync feature is used. So all universe data is send out, and after all data was send out +a sync packet is send to all receivers and then they are allowed to display the received data. Note that not all +receiver implemented this feature of the sACN protocol. +Example for the usage of the manual_flush: +```python +import sacn +import time +sender = sacn.sACNsender() +sender.start() +sender.activate_output(1) +sender.activate_output(2) +sender[1].multicast = True +sender[2].multicast = True +sender.manual_flush = True # turning off the automatic sending of packets +sender[1].dmx_data = (1, 2, 3, 4) # some test DMX data +sender[2].dmx_data = (5, 6, 7, 8) # by the time we are here, the above data would be already send out, +# if manual_flush would be False. This could cause some jitter +# so instead we are flushing manual +time.sleep(1) # let the sender initialize itself +sender.flush() +sender.manual_flush = False # keep manual flush off as long as possible, because if it is on, the automatic +# sending of packets is turned off and that is not recommended +sender.stop() # stop sending out +``` +### Receiving +To use the receiving functionality you have to use the `sACNreceiver`. +```python +import sacn +import time +# provide an IP-Address to bind to if you want to send multicast packets from a specific interface +receiver = sacn.sACNreceiver() +receiver.start() # start the receiving thread +# define a callback function +@receiver.listen_on('universe', universe=1) # listens on universe 1 +def callback(packet): # packet type: sacn.DataPacket + print(packet.dmxData) # print the received DMX data +# optional: if multicast is desired, join with the universe number as parameter +receiver.join_multicast(1) +time.sleep(10) # receive for 10 seconds +# optional: if multicast was previously joined +receiver.leave_multicast(1) +receiver.stop() +``` +The usage of the receiver is way more simple than the sender. +The `sACNreceiver` can be initialized with the following parameters: + * `bind_address: str`: Provide an IP-Address to bind to if you want to receive multicast packets from a specific interface. + * `bind_port: int`: Default: 5568. It is not recommended to change this value! + Only use when you are know what you are doing! +Please keep in mind to not use the callbacks for time consuming tasks! +If you do this, then the receiver can not react fast enough on incoming messages! +Functions: + * `join_multicast(<universe>)`: joins the multicast group for the specific universe. + * `leave_multicast(<universe>)`: leave the multicast group specified by the universe. + * `get_possible_universes()`: Returns a tuple with all universes that have sources that are sending out data and this + data is received by this machine + * `register_listener(<trigger>, <callback>, **kwargs)`: register a listener for the given trigger. + You can also use the decorator `listen_on(<trigger>, **kwargs)`. Possible trigger so far: + * `availability`: gets called when there is no data for a universe anymore or there is now data + available. This gets also fired if a source terminates a stream via the stream_termination bit. + The callback should get two arguments: `callback(universe, changed)` + * `universe: int`: is the universe where the action happened + * `changed: str`: can be 'timeout' or 'available' + * `universe`: registers a listener for the given universe. The callback gets only one parameter, the DataPacket. + You can also use the decorator `@listen_on('universe', universe=<universe>)`. + The callback should have one argument: `callback(packet)` + * `packet: DataPacket`: the received DataPacket with all information + * `remove_listener(<callback>)`: removes a previously registered listener regardless of the trigger. + This means a listener can only be removed completely, even if it was listening to multiple universes. + If the function never was registered, nothing happens. + Note: if a function was registered multiple times, this remove function needs to be called only once. + * `remove_listener_from_universe(<universe>)`: removes all listeners from the given universe. + This does only have effect on the 'universe' listening trigger. + If no function was registered for this universe, nothing happens. +### DataPacket +This is an abstract representation of an sACN Data packet that carries the DMX data. This class is used internally by +the module and is used in the callbacks of the receiver. +The DataPacket provides following attributes: + * `sourceName: str`: a string that is used to identify the source. Only the first 64 bytes are used. + * `priority: int`: the priority used to manage multiple DMX data on one receiver. [1-200] Default: 100 + * `universe: int`: the universe for the whole message and its DMX data. [1-63999] + * `sequence: int`: the sequence number. Should increment for every new message and can be used to check for wrong + order of arriving packets. + * `option_StreamTerminated: bool`: True if this packet is the last one of the stream for the given universe. + * `option_PreviewData: bool`: True if this data is for visualization purposes. + * `option_ForceSync: bool`: True if this should only function in a synchronized state. + * `dmxStartCode: int`: the start code for the data tuple. [1-255] Default: 0x00 for streaming level data. See + [Alternate START Codes](https://tsp.esta.org/tsp/working_groups/CP/DMXAlternateCodes.php) for more information. + * `dmxData: tuple`: the DMX data as tuple. Max length is 512 and shorter tuples getting normalized to a length of 512. + Filled with 0 for empty spaces. +## Development +Some tools are used to help with development of this library. These are [flake8](https://flake8.pycqa.org), [pytest](https://pytest.org) and [coverage.py](https://coverage.readthedocs.io). +Install those tools with pip: +``` +pip install flake8 pytest pytest-timeout coverage +``` +`flake8` checks for formatting issues and can be run with `flake8` or `python -m flake8` in the root directory of this repository. +`pytest` is used for unit testing and can be executed with `pytest` or `python -m pytest` in the root directory of this repository. +By default, this skips the integration test, which uses real hardware I/O and might not run in every configuration. +Use the flag `--run-integration-tests` to run the additional tests (e.g. `python -m pytest --run-integration-tests`) +It is useful to check if the test coverage changed with `coverage run -m pytest` and then `coverage html`, which generates a `htmlcov/index.html` file with all the information. +### Changelog + * 1.9.0: The behavior of multicast sending and receiving is now unified across most operating systems. This means Windows no longer requires to set a `bind_address` to be able to use multicast or universe discovery. (Thanks to mthespian! See #42 for more information) + * 1.8.1: Calling `stop` on a sender or receiver now closes the underlying socket too. Note: after stopping a sender or receiver, it can not be started again with `start`. (See #39 for more information) + * 1.8.0: Added function for removing a listener on a receiver by universe. See `sACNreceiver.remove_listener_from_universe(<universe>)` for more information. + * 1.7.1: Small changes that might improve timing on the sender. (Thanks to mthespian! See #36 for more information) + * 1.7.0: Added function for removing a listener on a receiver. See `sACNreceiver.remove_listener(<callback>)` for more information. + * 1.6.4: Functionality related to sending of sACN data is now mostly covered by tests. Removed undocumented parameters for `sACNsender.start()`. + * 1.6.3: Functionality related to receiving sACN data is now mostly covered by tests. Fixed a bug, where an exception was thrown on the first `DataPacket` when the stream-termination option was set. (Additional thanks to mthespian! See #31 for more information) + * 1.6.2: Test coverage of sub-module `messages` is now 100%. Fixed a bug where a too long source name did not throw an exception. + Fixed a bug where invalid DMX data could be set on the `DataPacket`. (Thanks to mthespian! See #30 for more information) + * 1.6.1: Fixed a bug, where the DMX start code was not set on received packets (Thanks to mthespian! See #29 for more information) + * 1.6: Added dmxStartCode property to DataPacket (Thanks to mthespian! see #27 for more information) + * 1.5: Performance improvement: Deleted debugging statements in hot path of packet sending and receiving (Thanks to shauneccles! See #25 for more information) + * 1.4.6: Fix: When creating a DataPacket with invalid DMX start codes (i.e. not `0x00`) an exception is thrown (Thanks to niggiover9000! See #11 for more information) + * 1.4.5: When using a manual flush, only a specified list of universes can be flushed (Thanks to CrazyIvan359! See #22 for more information) + * 1.4.4: The universe used for the sACN-sync messages can now be set when creating a `sACNsender` (Thanks to CrazyIvan359! See #21 for more information) + * 1.4.3: The sequence number of the sync-packet when using manual flush was not increased (Thanks to @BlakeGarner ! See #19 for more information) + * 1.4.2: The internal logging of the receiver_thread and output_thread was using the root logger instead of its module-logger. (Thanks to @mje-nz ! See #18 for more information) + * 1.4: Added a manual flush feature for sending out all universes at the same time. Thanks to ahodges9 for the idea. +[e1.31]: http://tsp.esta.org/tsp/documents/docs/E1-31-2016.pdf + +%prep +%autosetup -n sacn-1.9.0 + +%build +%py3_build + +%install +%py3_install +install -d -m755 %{buildroot}/%{_pkgdocdir} +if [ -d doc ]; then cp -arf doc %{buildroot}/%{_pkgdocdir}; fi +if [ -d docs ]; then cp -arf docs %{buildroot}/%{_pkgdocdir}; fi +if [ -d example ]; then cp -arf example %{buildroot}/%{_pkgdocdir}; fi +if [ -d examples ]; then cp -arf examples %{buildroot}/%{_pkgdocdir}; fi +pushd %{buildroot} +if [ -d usr/lib ]; then + find usr/lib -type f -printf "/%h/%f\n" >> filelist.lst +fi +if [ -d usr/lib64 ]; then + find usr/lib64 -type f -printf "/%h/%f\n" >> filelist.lst +fi +if [ -d usr/bin ]; then + find usr/bin -type f -printf "/%h/%f\n" >> filelist.lst +fi +if [ -d usr/sbin ]; then + find usr/sbin -type f -printf "/%h/%f\n" >> filelist.lst +fi +touch doclist.lst +if [ -d usr/share/man ]; then + find usr/share/man -type f -printf "/%h/%f.gz\n" >> doclist.lst +fi +popd +mv %{buildroot}/filelist.lst . +mv %{buildroot}/doclist.lst . + +%files -n python3-sacn -f filelist.lst +%dir %{python3_sitelib}/* + +%files help -f doclist.lst +%{_docdir}/* + +%changelog +* Thu May 18 2023 Python_Bot <Python_Bot@openeuler.org> - 1.9.0-1 +- Package Spec generated @@ -0,0 +1 @@ +77e6e8918eb0a170a374b19d46bc3a75 sacn-1.9.0.tar.gz |
