1+ import asyncio
12from typing import List , Callable
23
34
45class Universe :
56 def __init__ (self ):
6- pass
7+ # Dictionary to store channel value: {channel_number: current_value}
8+ self ._channel_values = {}
9+
10+ # Dictionary to store callbacks: {channel_number: [callback1, callback2, ...]}
11+ self ._channel_callbacks = {}
712
813 def register_channel_listener (self , channels : int | List [int ],
9- callback : Callable [[int ], None ]
10- ) -> None :
11- pass
14+ callback : Callable [[int , int ], None ]) -> None :
15+ """
16+ Register a callback to be called when a channel value changes.
17+
18+ Args:
19+ channels: Single channel number or list of channel numbers
20+ callback: Function to call with channel number and new value
21+ """
22+ if isinstance (channels , int ):
23+ channels = [channels ]
24+
25+ for channel in channels :
26+ if channel not in self ._channel_callbacks :
27+ self ._channel_callbacks [channel ] = []
28+
29+ if callback not in self ._channel_callbacks [channel ]:
30+ self ._channel_callbacks [channel ].append (callback )
31+
32+ def unregister_channel_listener (self , channels : int | List [int ],
33+ callback : Callable [[int , int ], None ]) -> None :
34+ """Remove a callback from the registry."""
35+ if isinstance (channels , int ):
36+ channels = [channels ]
37+
38+ for channel in channels :
39+ if channel in self ._channel_callbacks and callback in self ._channel_callbacks [channel ]:
40+ self ._channel_callbacks [channel ].remove (callback )
1241
1342 async def update_value (self , channel : int | List [int ], value : int ) -> None :
14- print (f"Updating { channel } to { value } " )
15- pass
43+ """
44+ Update the value of one or more channels and notify all listeners.
45+
46+ Args:
47+ channel: Single channel number or list of channel numbers
48+ value: New value for the channel(s)
49+ """
50+ # Convert to list if single channel
51+ if isinstance (channel , int ):
52+ channels = [channel ]
53+ else :
54+ channels = channel
55+
56+ # Update all specified channels
57+ for ch in channels :
58+ # Only process if value has changed or channel is new
59+ if ch not in self ._channel_values or self ._channel_values [ch ] != value :
60+ # Update stored value
61+ self ._channel_values [ch ] = value
62+
63+ # Notify all listeners for this channel
64+ if ch in self ._channel_callbacks :
65+ for callback in self ._channel_callbacks [ch ]:
66+ try :
67+ # Pass both channel and value to callback
68+ await self ._call_callback (callback , ch , value )
69+ except Exception as e :
70+ print (f"Error calling callback for channel { ch } : { e } " )
71+
72+ # Perform actual DMX output
73+ print (f"Updating DMX channel { ch } to value { value } " )
74+ # Actual DMX output code would go here
75+
76+ async def _call_callback (self , callback , channel , value ):
77+ """Helper method to call callbacks that might be async or regular functions."""
78+ if asyncio .iscoroutinefunction (callback ):
79+ await callback (channel , value )
80+ else :
81+ callback (channel , value )
82+
83+ def get_channel_value (self , channel : int ) -> int :
84+ """Get the current value of a channel."""
85+ return self ._channel_values .get (channel , 0 )
0 commit comments