66import struct
77import time
88from collections import defaultdict
9- from typing import Any , Optional , Tuple , Union , cast
9+ from typing import Any , Optional , Sequence , Tuple , Union , cast
1010
1111from .network import AF_PACKET , getifaddrs
12+ from .rdm import RDMDevice
1213
1314# Art-Net implementation for Python asyncio
1415# Any page references to 'spec' refer to
@@ -110,7 +111,7 @@ def __init__(self, portaddress: int):
110111 self ._last_publish : float = 0.0
111112 self ._last_tod_request : float = 0.0
112113 self .publisherseq : dict [Tuple [DGAddr , int ], int ] = {}
113- self .tod_uuids : set [bytes ] = set ()
114+ self ._tod : dict [bytes , RDMDevice ] = {}
114115
115116 def split (self ) -> Tuple [int , int , int ]:
116117 # name net:sub_net:universe
@@ -124,13 +125,16 @@ def __repr__(self) -> str:
124125 net , sub_net , universe = self .split ()
125126 return f"{ net } :{ sub_net } :{ universe } "
126127
127- def set_dmx (self , data : bytes ):
128+ def set_dmx (self , data : bytes ) -> None :
128129 assert len (data ) == DMX_UNIVERSE_SIZE
129130 self .last_data [:] = data [:]
130131
131132 def get_dmx (self ) -> bytes :
132133 return self .last_data
133134
135+ def get_rdm_uuids (self ) -> Sequence [bytes ]:
136+ return list (self ._tod .keys ())
137+
134138
135139class ArtNetPort :
136140 def __init__ (
@@ -140,6 +144,7 @@ def __init__(
140144 media : int ,
141145 portaddr : int ,
142146 universe : ArtNetUniverse ,
147+ flags : int ,
143148 ):
144149 self .node = node
145150 self .is_input = is_input
@@ -265,7 +270,9 @@ def on_art_poll_reply(self, addr: DGAddr, data: bytes) -> None:
265270
266271 # iterate through the ports and create ports and universes
267272 portList = []
268- for _type , _in , _out , _swin , _swout in zip (ptype , ins , outs , swin , swout ):
273+ for _type , _in , _out , _swin , _swout , _goodout in zip (
274+ ptype , ins , outs , swin , swout , goodout
275+ ):
269276 in_port_addr = (
270277 ((netsw & 0x7F ) << 8 ) + ((subsw & 0x0F ) << 4 ) + (_swin & 0x0F )
271278 )
@@ -275,11 +282,13 @@ def on_art_poll_reply(self, addr: DGAddr, data: bytes) -> None:
275282 if _type & 0b10000000 :
276283 outu = self .client ._get_create_universe (out_port_addr )
277284 portList .append (
278- ArtNetPort (nn , False , _type & 0x1F , out_port_addr , outu )
285+ ArtNetPort (nn , False , _type & 0x1F , out_port_addr , outu , _goodout )
279286 )
280287 if _type & 0b01000000 :
281288 inu = self .client ._get_create_universe (in_port_addr )
282- portList .append (ArtNetPort (nn , True , _type & 0x1F , in_port_addr , inu ))
289+ portList .append (
290+ ArtNetPort (nn , True , _type & 0x1F , in_port_addr , inu , 0 )
291+ )
283292
284293 # track which 'pages' of port bindings we have seen
285294 old_ports = nn ._portBinds [bindindex ]
@@ -375,7 +384,7 @@ def on_art_tod_data(self, addr: DGAddr, data: bytes) -> None:
375384 # I think tot_uid and block_count are *paging* related if more tod UIDs than can fit in a packet
376385 for i in range (uid_count ):
377386 uid = data [18 + i * 6 : 18 + (i + 1 ) * 6 ]
378- u .tod_uuids . add (uid )
387+ u ._tod [ uid ] = RDMDevice (uid )
379388 logger .info (
380389 f"Received Art-Net TOD entry: universe { portaddress } uid={ uid .hex ()} from { addr } "
381390 )
@@ -515,7 +524,7 @@ def _send_art_dmx_subscriber(
515524 if self .transport :
516525 self .transport .sendto (message , addr = (node .ip , node .udpport ))
517526
518- def _send_art_tod_request (self , universe : ArtNetUniverse ):
527+ def _send_art_tod_request (self , universe : ArtNetUniverse ) -> None :
519528 logger .debug (f"sending art tod request for { universe } " )
520529 universe ._last_tod_request = time .time ()
521530
@@ -685,7 +694,12 @@ def set_port_config(
685694
686695 if is_input or is_output :
687696 port = ArtNetPort (
688- node = self , is_input = is_input , media = 0 , portaddr = port_addr , universe = u
697+ node = self ,
698+ is_input = is_input ,
699+ media = 0 ,
700+ portaddr = port_addr ,
701+ universe = u ,
702+ flags = 0 ,
689703 )
690704 self .ports .append (port )
691705 logger .info (f"configured own port { port } " )
0 commit comments