From a2bec3cdca39e05e81f1292f3937a63316d5f119 Mon Sep 17 00:00:00 2001 From: Kacper Date: Wed, 14 Feb 2024 12:53:19 +0100 Subject: [PATCH 1/5] Added possibility to send ArtSync. --- stupidArtnet/StupidArtnet.py | 70 ++++++++++++++++++++++++++++++++---- 1 file changed, 63 insertions(+), 7 deletions(-) diff --git a/stupidArtnet/StupidArtnet.py b/stupidArtnet/StupidArtnet.py index a4d5ec5..7aa685e 100644 --- a/stupidArtnet/StupidArtnet.py +++ b/stupidArtnet/StupidArtnet.py @@ -44,6 +44,7 @@ def __init__(self, target_ip='127.0.0.1', universe=0, packet_size=512, fps=30, self.net = 0 self.packet_size = put_in_range(packet_size, 2, 512, even_packet_size) self.packet_header = bytearray() + self.artsync_header = bytearray() self.buffer = bytearray(self.packet_size) self.make_even = even_packet_size @@ -61,13 +62,16 @@ def __init__(self, target_ip='127.0.0.1', universe=0, packet_size=512, fps=30, self.fps = fps self.__clock = None - self.make_header() + self.make_artdmx_header() + self.make_artsync_header() + def __del__(self): """Graceful shutdown.""" self.stop() self.close() + def __str__(self): """Printable object state.""" state = "===================================\n" @@ -82,7 +86,8 @@ def __str__(self): return state - def make_header(self): + + def make_artdmx_header(self): """Make packet header.""" # 0 - id (7 x bytes + Null) self.packet_header = bytearray() @@ -125,6 +130,38 @@ def make_header(self): self.packet_header.append(msb) self.packet_header.append(lsb) + + def make_artsync_header(self): + """Make ArtSync header""" + self.artsync_header = bytearray() # Initialize as empty bytearray + # ID: Array of 8 characters, the final character is a null termination. + self.artsync_header.extend(bytearray('Art-Net', 'utf8')) + self.artsync_header.append(0x0) + # OpCode: Defines the class of data within this UDP packet. Transmitted low byte first. + self.artsync_header.append(0x00) + self.artsync_header.append(0x52) + # ProtVerHi and ProtVerLo: Art-Net protocol revision number. Current value =14. + # Controllers should ignore communication with nodes using a protocol version lower than =14. + self.artsync_header.append(0x0) + self.artsync_header.append(14) + # Aux1 and Aux2: Should be transmitted as zero. + self.artsync_header.append(0x0) + self.artsync_header.append(0x0) + + + def send_artsync(self): + """Send Artsync""" + self.make_artsync_header() + packet = bytearray() + packet.extend(self.artsync_header) + try: + self.socket_client.sendto(packet, (self.target_ip, self.UDP_PORT)) + except socket.error as error: + print(f"ERROR: Socket error with exception: {error}") + finally: + self.sequence = (self.sequence + 1) % 256 + + def show(self): """Finally send data.""" packet = bytearray() @@ -137,6 +174,7 @@ def show(self): finally: self.sequence = (self.sequence + 1) % 256 + def close(self): """Close UDP socket.""" self.socket_client.close() @@ -150,6 +188,7 @@ def start(self): self.__clock.daemon = True self.__clock.start() + def stop(self): """Stops thread clock.""" if self.__clock is not None: @@ -169,7 +208,8 @@ def set_universe(self, universe): self.universe = put_in_range(universe, 0, 255, False) else: self.universe = put_in_range(universe, 0, 15, False) - self.make_header() + self.make_artdmx_header() + def set_subnet(self, sub): """Setter for subnet address (0 - 15). @@ -177,7 +217,8 @@ def set_subnet(self, sub): Set simplify to false to use """ self.subnet = put_in_range(sub, 0, 15, False) - self.make_header() + self.make_artdmx_header() + def set_net(self, net): """Setter for net address (0 - 127). @@ -185,12 +226,13 @@ def set_net(self, net): Set simplify to false to use """ self.net = put_in_range(net, 0, 127, False) - self.make_header() + self.make_artdmx_header() + def set_packet_size(self, packet_size): """Setter for packet size (2 - 512, even only).""" self.packet_size = put_in_range(packet_size, 2, 512, self.make_even) - self.make_header() + self.make_artdmx_header() # SETTERS - DATA # @@ -198,6 +240,7 @@ def clear(self): """Clear DMX buffer.""" self.buffer = bytearray(self.packet_size) + def set(self, value): """Set buffer.""" if len(value) != self.packet_size: @@ -205,6 +248,7 @@ def set(self, value): return self.buffer = value + def set_16bit(self, address, value, high_first=False): """Set single 16bit value in DMX buffer.""" if address > self.packet_size: @@ -223,6 +267,7 @@ def set_16bit(self, address, value, high_first=False): self.buffer[address - 1] = (value) & 0xFF # low self.buffer[address] = (value >> 8) & 0xFF # high + def set_single_value(self, address, value): """Set single value in DMX buffer.""" if address > self.packet_size: @@ -233,6 +278,7 @@ def set_single_value(self, address, value): return self.buffer[address - 1] = put_in_range(value, 0, 255, False) + def set_single_rem(self, address, value): """Set single value while blacking out others.""" if address > self.packet_size: @@ -244,6 +290,7 @@ def set_single_rem(self, address, value): self.clear() self.buffer[address - 1] = put_in_range(value, 0, 255, False) + def set_rgb(self, address, red, green, blue): """Set RGB from start address.""" if address > self.packet_size: @@ -268,6 +315,7 @@ def send(self, packet): self.set(packet) self.show() + def set_simplified(self, simplify): """Builds Header accordingly. @@ -279,21 +327,25 @@ def set_simplified(self, simplify): if simplify == self.is_simplified: return self.is_simplified = simplify - self.make_header() + self.make_artdmx_header() + def see_header(self): """Show header values.""" print(self.packet_header) + def see_buffer(self): """Show buffer values.""" print(self.buffer) + def blackout(self): """Sends 0's all across.""" self.clear() self.show() + def flash_all(self, delay=None): """Sends 255's all across.""" self.set([255] * self.packet_size) @@ -331,6 +383,10 @@ def flash_all(self, delay=None): a.show() print("Values sent") + + a.send_artsync() + + print("ArtSync sent") # Cleanup when you are done del a From 38eb32b00fb670a1466f3fa9244d028076991f00 Mon Sep 17 00:00:00 2001 From: kacper516 <116543741+kacper516@users.noreply.github.com> Date: Wed, 14 Feb 2024 13:09:43 +0100 Subject: [PATCH 2/5] Update stupidArtnet/StupidArtnet.py Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> --- stupidArtnet/StupidArtnet.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/stupidArtnet/StupidArtnet.py b/stupidArtnet/StupidArtnet.py index 7aa685e..fb4f282 100644 --- a/stupidArtnet/StupidArtnet.py +++ b/stupidArtnet/StupidArtnet.py @@ -159,8 +159,6 @@ def send_artsync(self): except socket.error as error: print(f"ERROR: Socket error with exception: {error}") finally: - self.sequence = (self.sequence + 1) % 256 - def show(self): """Finally send data.""" From 93ec1a58587b654a10be8e616b1f7bfdfc12c8ac Mon Sep 17 00:00:00 2001 From: Kacper Date: Wed, 14 Feb 2024 13:11:55 +0100 Subject: [PATCH 3/5] Deleted unnecesary finally block --- stupidArtnet/StupidArtnet.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stupidArtnet/StupidArtnet.py b/stupidArtnet/StupidArtnet.py index fb4f282..89430b6 100644 --- a/stupidArtnet/StupidArtnet.py +++ b/stupidArtnet/StupidArtnet.py @@ -158,7 +158,7 @@ def send_artsync(self): self.socket_client.sendto(packet, (self.target_ip, self.UDP_PORT)) except socket.error as error: print(f"ERROR: Socket error with exception: {error}") - finally: + def show(self): """Finally send data.""" From 3d43c47f80ba89c5aee17b1510d66608fe6163ff Mon Sep 17 00:00:00 2001 From: Kacper Date: Wed, 14 Feb 2024 14:53:46 +0100 Subject: [PATCH 4/5] Update GitHub Actions configuration for testing. --- .github/workflows/run tests.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/run tests.yml b/.github/workflows/run tests.yml index 8aebdd7..d2d031d 100644 --- a/.github/workflows/run tests.yml +++ b/.github/workflows/run tests.yml @@ -7,10 +7,10 @@ jobs: steps: - uses: actions/checkout@master - - name: Set up Python 3.10.12 + - name: Set up Python 3.11.8 uses: actions/setup-python@v1 with: - python-version: 3.10.12 + python-version: 3.11.8 - name: Run test run: python -m unittest discover --v \ No newline at end of file From 621eb08cb1b03e9ddc750f7ee34250a6749ca34b Mon Sep 17 00:00:00 2001 From: Kacper Date: Thu, 15 Feb 2024 12:32:15 +0100 Subject: [PATCH 5/5] Enhanced functionality: ArtSync option in constructor and direct function invocation. --- stupidArtnet/StupidArtnet.py | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/stupidArtnet/StupidArtnet.py b/stupidArtnet/StupidArtnet.py index 89430b6..fd98bf0 100644 --- a/stupidArtnet/StupidArtnet.py +++ b/stupidArtnet/StupidArtnet.py @@ -20,7 +20,7 @@ class StupidArtnet(): UDP_PORT = 6454 def __init__(self, target_ip='127.0.0.1', universe=0, packet_size=512, fps=30, - even_packet_size=True, broadcast=False): + even_packet_size=True, broadcast=False, artsync=False): """Initializes Art-Net Client. Args: @@ -30,6 +30,7 @@ def __init__(self, target_ip='127.0.0.1', universe=0, packet_size=512, fps=30, fps - transmition rate even_packet_size - Some receivers enforce even packets broadcast - whether to broadcast in local sub + artsync - if we want to synchronize buffer Returns: None @@ -41,10 +42,10 @@ def __init__(self, target_ip='127.0.0.1', universe=0, packet_size=512, fps=30, self.physical = 0 self.universe = universe self.subnet = 0 + self.if_sync = artsync self.net = 0 self.packet_size = put_in_range(packet_size, 2, 512, even_packet_size) self.packet_header = bytearray() - self.artsync_header = bytearray() self.buffer = bytearray(self.packet_size) self.make_even = even_packet_size @@ -63,7 +64,10 @@ def __init__(self, target_ip='127.0.0.1', universe=0, packet_size=512, fps=30, self.__clock = None self.make_artdmx_header() - self.make_artsync_header() + + if self.if_sync: + self.artsync_header = bytearray() + self.make_artsync_header() def __del__(self): @@ -152,14 +156,12 @@ def make_artsync_header(self): def send_artsync(self): """Send Artsync""" self.make_artsync_header() - packet = bytearray() - packet.extend(self.artsync_header) try: - self.socket_client.sendto(packet, (self.target_ip, self.UDP_PORT)) + self.socket_client.sendto(self.artsync_header, (self.target_ip, self.UDP_PORT)) except socket.error as error: print(f"ERROR: Socket error with exception: {error}") - + def show(self): """Finally send data.""" packet = bytearray() @@ -167,6 +169,8 @@ def show(self): packet.extend(self.buffer) try: self.socket_client.sendto(packet, (self.target_ip, self.UDP_PORT)) + if self.if_sync: # if we want to send artsync + self.send_artsync() except socket.error as error: print(f"ERROR: Socket error with exception: {error}") finally: @@ -361,7 +365,7 @@ def flash_all(self, delay=None): UNIVERSE_TO_SEND = 15 # see docs PACKET_SIZE = 20 # it is not necessary to send whole universe - a = StupidArtnet(TARGET_IP, UNIVERSE_TO_SEND, PACKET_SIZE) + a = StupidArtnet(TARGET_IP, UNIVERSE_TO_SEND, PACKET_SIZE, artsync=True) a.set_simplified(False) a.set_net(129) a.set_subnet(16) @@ -381,10 +385,6 @@ def flash_all(self, delay=None): a.show() print("Values sent") - - a.send_artsync() - - print("ArtSync sent") # Cleanup when you are done del a