Hundemeier / sacn

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

Query: Per address output? #17

Closed jcoopertech closed 4 years ago

jcoopertech commented 4 years ago

Hi Hundemeier,

I've not had enough time to experiment with this, but is it possible to output specific address values instead of a whole universe? I'm looking to control specific addresses in any given universe, and take priority of only those addresses, leaving lower priority control alone.

Hundemeier commented 4 years ago

The DMX data transmitted via sACN always contains a whole universe. This means the incoming UDP-packets normally contain a whole 512 bytes of DMX data. There is no definition of "unused" values, so therefore a whole universe is given as the data in the callback (packet.dmxData). (Note: technically it is possible to shorten this data in UDP-packets, but I never saw this in reality and the packet.dmxData field has always a length of 512) The DMX data (packet.dmxData) is a tuple, so you can sub-select any values as you need them.

sACN priorities are handled by the receiver and the callback will only receive the data with the highest priority.

I don't understand your sentence

I'm looking to control specific addresses in any given universe, and take priority of only those addresses, leaving lower priority control alone.

jcoopertech commented 4 years ago

Hi,

I’m referring to the sending part of the code.

After reading the E1.31 standard, what I realise I want to do is specify the First Property address - so to only output the data from DMX address NN in the universe, then modify the property value count to tell the reciever it’s expecting X many addresses/slots.

Broadly speaking: It’s very common to give per-DMX-address priority over parts of an sACN universe. For example: A source gives Address 2 thru 6 a value of 255, but that packet had been sent at a higher priority than another source which outputs the rest of the universe.

Am only wondering if your code is able to be modified to acheive something similar

On 17 Apr 2020, at 20:40, Hundemeier notifications@github.com wrote:



The DMX data transmitted via sACN always contains a whole universe. This means the incoming UDP-packets normally contain a whole 512 bytes of DMX data. There is no definition of "unused" values, so therefore a whole universe is given as the data in the callback (packet.dmxData). (Note: technically it is possible to shorten this data in UDP-packets, but I never saw this in reality and the packet.dmxData field has always a length of 512) The DMX data (packet.dmxData) is a tuple, so you can sub-select any values as you need them.

sACN priorities are handled by the receiver and the callback will only receive the data with the highest priority.

I don't understand your sentence

I'm looking to control specific addresses in any given universe, and take priority of only those addresses, leaving lower priority control alone.

— You are receiving this because you authored the thread. Reply to this email directly, view it on GitHubhttps://eur04.safelinks.protection.outlook.com/?url=https%3A%2F%2Fgithub.com%2FHundemeier%2Fsacn%2Fissues%2F17%23issuecomment-615430220&data=02%7C01%7C%7C819eef890e7b4aa9974508d7e3073414%7C84df9e7fe9f640afb435aaaaaaaaaaaa%7C1%7C0%7C637227492377763742&sdata=c1pg%2F%2BEVi4J7jGEMB%2B7gEU0u%2BW%2FGGlIp9qtxYg9kdzE%3D&reserved=0, or unsubscribehttps://eur04.safelinks.protection.outlook.com/?url=https%3A%2F%2Fgithub.com%2Fnotifications%2Funsubscribe-auth%2FAOBWOJ4L2ZF64DXS3NRZMBTRNCWDHANCNFSM4MJZN44A&data=02%7C01%7C%7C819eef890e7b4aa9974508d7e3073414%7C84df9e7fe9f640afb435aaaaaaaaaaaa%7C1%7C0%7C637227492377773751&sdata=BzMHmrPkqjYQ9UMxeBgqgVzISWOHs44bT7idf2b5JJo%3D&reserved=0.

Hundemeier commented 4 years ago

Now I think I get what you want: You want to send out not 512 but less bytes as DMX data? It is possible and actually already implemented, but an extra step is taken to use always 512 as the length of the DMX data. These are the offending lines. I'm not sure if I want to change this, because in my experience some older devices did not receive DMX data properly when there were less than 512 DMX-data-bytes. And for priority merging: I don't know if its a good idea, because the priority is then dependent on the DMX-address in a weird manner. So lower addresses receive from the higher priority (eg. address 0-10 with priority of 200) and higher addresses with lower priority (eg. address 11-511 with priority of 100), but never the other way around. The lower addresses always have to start from 0, so your example with addresses from 2-6 with higher priority won't be possible? (Your example would mean 0-6 with higher priority not 2-6)

Sidenote: The receiver of this library does not support this edge-case.

But if you want to implement this, feel free to try it out by changing the lines.

jcoopertech commented 4 years ago

Yep, thats pretty much exactly it - I’ll have a look in a bit, but thanks for pointing me in the right direction

How does the code go about determining the property value count (bytes 123-124 of a data packet) - since the library is usually used for full universe, has this been hard coded as 0x0201, or is it dependant on the length of dmxData?

Then for First property address (bytes 119-120), I presume I’ll have to pass that into the sender?

On 18 Apr 2020, at 14:36, Hundemeier notifications@github.com wrote:



Now I think I get what you want: You want to send out not 512 but less bytes as DMX data? It is possible and actually already implemented, but an extra step is taken to use always 512 as the length of the DMX data. Thesehttps://eur05.safelinks.protection.outlook.com/?url=https%3A%2F%2Fgithub.com%2FHundemeier%2Fsacn%2Fblob%2Fmaster%2Fsacn%2Fmessages%2Fdata_packet.py%23L82-L89&data=02%7C01%7C%7C90dfe6b46dbe40a2f22b08d7e39d8d7c%7C84df9e7fe9f640afb435aaaaaaaaaaaa%7C1%7C0%7C637228138122901363&sdata=yLc3sduDCvDtfL5gGGVzqLiw20oV8xLrPXvXS4%2BlUxA%3D&reserved=0 are the offending lines. I'm not sure if I want to change this, because in my experience some older devices did not receive DMX data properly when there were less than 512 DMX-data-bytes. And for priority merging: I don't know if its a good idea, because the priority is then dependent on the DMX-address in a weird manner. So lower addresses receive from the higher priority (eg. address 0-10 with priority of 200) and higher addresses with lower priority (eg. address 11-511 with priority of 100), but never the other way around. The lower addresses always have to start from 0, so your example with addresses from 2-6 with higher priority won't be possible? (Your example would mean 0-6 with higher priority not 2-6)

Sidenote: The receiver of this library does not support this edge-case.

But if you want to implement this, feel free to try it out by changing the lineshttps://eur05.safelinks.protection.outlook.com/?url=https%3A%2F%2Fgithub.com%2FHundemeier%2Fsacn%2Fblob%2Fmaster%2Fsacn%2Fmessages%2Fdata_packet.py%23L84-L87&data=02%7C01%7C%7C90dfe6b46dbe40a2f22b08d7e39d8d7c%7C84df9e7fe9f640afb435aaaaaaaaaaaa%7C1%7C0%7C637228138122911359&sdata=vDaJD9BSFILn9jRbWYWU0%2BbOzCR%2Ba23%2BbNz4Vu1Ekoo%3D&reserved=0.

— You are receiving this because you authored the thread. Reply to this email directly, view it on GitHubhttps://eur05.safelinks.protection.outlook.com/?url=https%3A%2F%2Fgithub.com%2FHundemeier%2Fsacn%2Fissues%2F17%23issuecomment-615873115&data=02%7C01%7C%7C90dfe6b46dbe40a2f22b08d7e39d8d7c%7C84df9e7fe9f640afb435aaaaaaaaaaaa%7C1%7C0%7C637228138122911359&sdata=SjfY966EevNS9JcVT%2BBornHqgKiIPo%2Fci7GSXIapjgw%3D&reserved=0, or unsubscribehttps://eur05.safelinks.protection.outlook.com/?url=https%3A%2F%2Fgithub.com%2Fnotifications%2Funsubscribe-auth%2FAOBWOJZZUQVODMIPZQCI5GTRNGUHHANCNFSM4MJZN44A&data=02%7C01%7C%7C90dfe6b46dbe40a2f22b08d7e39d8d7c%7C84df9e7fe9f640afb435aaaaaaaaaaaa%7C1%7C0%7C637228138122921353&sdata=BjLJHN4fJi869EaEVoj%2B%2B88zJdin%2BnoWym5Ms61RFG0%3D&reserved=0.

Hundemeier commented 4 years ago

When the sACN data packet (class DataPacket) is parsed into raw bytes, the length of the dmxData-field is actually taken into consideration (this line sets the bytes 123 and 124 of the UDP-packet). when changing the length of the UDP-packet by changing the size of the DMX-data payload, all the length bytes in the packet have to be set accordingly (bytes 16-17, 38-39, 115-116). This is what the field length is used for and the parsing of the DataPacket is actually already dynamic (see lines 94 and 122 in data_packet.py and lines 39ff in root_layer.py). So all length fields are already dynamic and use the length of _dmxData and length to set correct lengths in the packet.

So when you want to set something different than 512 bytes as the DMX data, then you should be good to go by only modifying the dmxData.setter like this:

@dmxData.setter
def dmxData(self, data: tuple):
    self._dmxData = data
    # in theory this class supports dynamic length,
    # so the next line is correcting the length
    self.length = 126 + len(self._dmxData)

But please test and verify this proposed code (eg. with Wireshark) and keep in mind that you know can pass longer tuples than 512 bytes into the setter now, which is not spec conformant and could break things.

jcoopertech commented 4 years ago

Brilliant! Thanks for this!

As it happens, I’ve now found the solution I was originally looking to solve is done by sending data out to the whole universe (full length dmxData), but with a 0xDD dmx start code. This is used primarily with ETC manufactured lighting equipment to assign a priority which the source has over part of the DMX output - where receivers process which source has what priority over which dmx values.

Hopefully that makes sense... nonetheless, thanks for the help thus far. I think I now just need to parse a new start code to the dmxData and I should be all good!

jcoopertech commented 4 years ago

Hi again... Out of interest, how easy is it to send sACN from the same "sACN source / CID", but using a different DMX start code, and separate data?

Hundemeier commented 4 years ago

Sorry for the late reply.

If you use one sender like this, the CID for each universe send out by this sender is the same. The CID can be set via an optional parameter:

sender = sacn.sACNsender(cid=(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16))

If the provided tuple is not of length 16 a random CID will be generated.

You can set different DMX data for each universe via sender[1].dmx_data = (1, 2, 3, 4) (universe=1).

As for the DMX start code: this is currently not supported, but possible. I would welcome a pull-request for this!

jcoopertech commented 4 years ago

Brilliant, thanks for the pointers. I'll have another look at it. I'll probably end up manually specifying the CID for two sender instances - and probably modify the sacn.sACNsender function inputs to allow a startCode to be passed in.

That said, I've not looked at the code for a few weeks, but that's my thought!

I'll close this now - if I do get the custom startCode working I'll start a pull-request.