spacemanspiff2007 / PyArtNet

"Python wrappers for the Art-Net protocol to send DMX over Ethernet"
GNU General Public License v3.0
70 stars 14 forks source link

DMX Input #31

Open Breina opened 1 year ago

Breina commented 1 year ago

Context on my end

I'm implementing HomeAssistant as an ArtNet controller. This means it's going poll for ArtNet devices on the network and reply to other ArtNet controllers do the same. This will mean that other controllers will be able to update our state.

image

image

Code for the ArtNet server is available. I have yet to clean it up, as it's pretty messy. But it does work! :)

Current implementation on my end

I'm able to bridge my implementation to ArtNetNode (or BaseNode in the comingrelease). This just adds the logic that the server needs to start polling, opening sockets, etc... I've set it up this way so that I can keep your error correction and animations, whilst being able to expand on the functionality of ArtNet.

This is able to receive ArtDmx packets containing data on the port (net, sub_net, universe), and a bytearray of raw data. I'm able to simply override the universe's data, but omits output correction and callbacks.

Requested change on your end

spacemanspiff2007 commented 1 year ago

I don't understand what you are trying to achieve. The ArtPollReply does not contain the universe values, only the controller state. Do you want to receive ArtDmxPackages? And if so - why?

Breina commented 1 year ago

I added the ArtPollReply as context, as this is what I'm doing in the ArtNet server. The ArtPollReply contains universe numbers in its SwIn/SwOut fields, that's how I can discover nodes and other controllers without having to have an IP in advance.

The ArtDmx arrow in the sequence diagram should have been from Controller to HA (controller) for this use case.

So I receive ArtDmx packets from controllers that control universes that we've previously subscribed to. I wish to pass through your library in the reverse direction: undoing output correction, grouping multiple channels into multi-byte raw values and sending those back to the origin (HA in my case).

Breina commented 1 year ago

So to be more clear, this is how I thought about setting it up. Please correct me if that's not aligned with your vision for your library.

image

image

So this would make PyArtNet effectively bidirectional.

I can also create a PR to add the ArtNet server into your library, though my current code is way off your coding standard, would need some tidying up first in that case.

spacemanspiff2007 commented 1 year ago

I still am not 100% sure I understand what you are trying to achieve. I think the labels are also a little bit off in your diagram which contributes to my confusion. What exactly is ha-artnet-led ArtNet Server? Is this the ArtNetNode from pyartnet? Can we use controller for software that sends new dmx values and node for hardware that does artnet->dmx translation?

Can you describe what you want to achieve in easy words? E.g.: I have HA and I have DMX controller software XYZ and I want to use XYZ to control the lights and HA to pick up the new status.

Breina commented 1 year ago

Sorry I'm not great with text, here's another diagram:

image

ArtNet Server is my code that implements most of the ArtNet standard. Implements the ArtPoll/ArtPollReply mechanism to discover and be discovered, sending and receiving ArtDMX packets, and much more. But yes, this would be an alternative to ArtNetNode (I have this configurable to either use the server, or your direct approach).

As a lighting engineer, I would like to use my ArtNet controller hardware to update HA states, so that I can control my house using my hardware.

Here's two users asking this:

https://community.home-assistant.io/t/dmx-lighting/2248/345

https://github.com/Breina/ha-artnet-led/issues/23

spacemanspiff2007 commented 1 year ago

As a lighting engineer, I would like to use my ArtNet controller hardware to control [...] my house [...].

That's something I can understand.

Imho the most easy solution would be to just have pyartnet accept ArtDMX packages and provide some kind of callback. That way you could (manually) map the received universes to the corresponding HA entity. e.g.

Your Hardware -> ArtDMX -> payartnet -> HA entity -> pyartnet -> ArtDMX -> DMX Gateway -> DMX device

This would however require some kind of configuration on the HA side, e.g.

input universe 1, channel 1-3 -> ha_entity

Would something like this work with HA?

Breina commented 1 year ago

To be clear, the ArtDMX packets are sent to all nodes and controllers that subscribed to a universe. HA doesn't need to act as proxy.

Your Hardware -> ArtDMX -> payartnet -> HA entity
              -> ArtDMX -> DMX device

A callback would be perfect, but I prefer that pyartnet transforms the values into values that HA will understand.

I.e. HA sends value 200, cubic correction = 123, 16 bit = 8062868.

HA should receive a 200, and not a 8062868.

A mapping per universe, per channel will also work for me, yes. My current PR does callbacks on a channel level, the thought was that pyartnet doesn't need to bother mapping foreign HA objects.

spacemanspiff2007 commented 1 year ago

To be clear, the ArtDMX packets are sent to all nodes and controllers that subscribed to a universe.

But I don't see this? The response to the ArtPoll message is the ArtPollReply message. I don't see why the nodes/other controllers would start sending ArtDmx to the controller which sent the ArtPoll message.

HA doesn't need to act as proxy.

Why not - this would be an elegant solution and would make lots of things very easy.

Breina commented 1 year ago

This is how ArtNet is supposed to work:

  1. Controller ArtPoll boardcast: Hello everyone, I'm interested in universes ranging from 0 to 2.
  2. Node ArtPollReply unicast to Controller: Hi, I am node 1, with all of these parameters and I am interested in receiving universe 0.
  3. HA ArtPollReply unicast to Controller: Hi, I am HomeAssistant, with all of these parameters and I am interested in both sending and receiving universe 0
  4. Controller ArtDMX unicast to HA: Here's a new DMX with sequence 25
  5. Controller ArtDMX unicast to device: Here's a new DMX with sequence 25

ArtNet Controllers will be sending to Node, nothing we can do about that. We can just choose to also listen to these universes.

If HA decides to also send the same DMX frame to Node, then Node would receive DMX frames from multiple controllers, meaning it will go into merge mode, which opens a can of worms.

spacemanspiff2007 commented 1 year ago

I've had the old 2017 version of the ArtNet specification which does not define TargetPort (or at least I missed it). 😕 So what you mean is ArtPoll set Flag Bit 5 to 1 and Top/Bottom TargetPort the universe address. ? I understand it as a mask to not receive so many ArtPollReply.

I am interested in both sending and receiving universe 0

How would you set that it in the ArtPollReply?

I still understand ArtPoll and ArtPollReply as a discovery mechanism and not a subscription mechanism.

Breina commented 1 year ago

Ah that explains a bit, we're getting there! :)

So what you mean is ArtPoll set Flag Bit 5 to 1 and Top/Bottom TargetPort the universe address. ? I understand it as a mask to not receive so many ArtPollReply.

Yes Indeed. When 1, only certain nodes / controllers will reply. When 0, everyone will reply.

How would you set that it in the ArtPollReply?

Fields 23 (SwIn) and 24 (SwOut) define the universe number that you wish to subscribe to. Fields 7 (NetSwitch) and 8 (SubSwitch) define the net and subnet of the PortAddress.

An ArtPollReply can contain target up to 4 universes in one same net/subnet. If you need more, you're free to reply with multiple ArtNetReply packets.

I still understand ArtPoll and ArtPollReply as a discovery mechanism and not a subscription mechanism.

The subscription mechanism is at the core of this version of ArtNet at least.

https://art-net.org.uk/how-it-works/streaming-packets/subscription/

Not only is the ArtPollReply mandatory to be sending ArtDMX packets, not replying to a Poll will result in a termination.

If you don't like the need to ArtPoll every 2.5 to 3 seconds, you can set ArtPoll Flags Bit 1 to 1. Though you won't be informed on Node disconnects.

To be fair, it's not the best documentation of a protocol. :p

Btw, you're legally required to put Art-Net™ Designed by and Copyright Artistic Licence somewhere, if you're implementing ArtNet.

Breina commented 1 year ago

So to recap, there's two directions we can take this;

  1. Add a way to unpack bytes and reverse output correction (#36), leaving the Socket -> DMX data part to ha-artnet-led
  2. Same as 1, but doing the ArtNet Controller implementation in PyArtNet.

There's no hybrid approach, as only one project can listen to the ArtNet port. But I think, either way, we will need #36 as a way of flowing back to HA.

If you prefer option 2, I can submit a PR with the controller as well. Though personally, I prefer to have control over it directly, as I want to expand it with future functionalities (ArtTrigger, ArtCommand, ...)

Please let me know what's your take on this. :)