Allow None animation, stopping the update thread

This commit is contained in:
Stefan Bethke 2022-07-23 17:47:19 +02:00
parent d4166db9ab
commit f4f5458209
2 changed files with 39 additions and 25 deletions

60
dmx.py
View file

@ -12,7 +12,7 @@ def hsv_to_rgb(h, s, v):
def ledlog(value): def ledlog(value):
return int(pow(float(value)/255.0, 2)*255) return int(pow(float(value) / 255.0, 2) * 255)
class RGB: class RGB:
@ -23,30 +23,31 @@ class RGB:
def rgb(self, color): def rgb(self, color):
(r, g, b) = color (r, g, b) = color
self.dmx.set(self.slot+self.offset+0, ledlog(r)) self.dmx.set(self.slot + self.offset + 0, ledlog(r))
self.dmx.set(self.slot+self.offset+1, ledlog(g)) self.dmx.set(self.slot + self.offset + 1, ledlog(g))
self.dmx.set(self.slot+self.offset+2, ledlog(b)) self.dmx.set(self.slot + self.offset + 2, ledlog(b))
class Bar252(RGB): class Bar252(RGB):
def __init__(self, dmx, slot=1): def __init__(self, dmx, slot=1):
super(Bar252, self).__init__(dmx, slot, 2) super(Bar252, self).__init__(dmx, slot, 2)
dmx.set(self.slot+0, 81) dmx.set(self.slot + 0, 81)
dmx.set(self.slot+1, 0) dmx.set(self.slot + 1, 0)
class REDSpot18RGB(RGB): class REDSpot18RGB(RGB):
def __init__(self, dmx, slot=1): def __init__(self, dmx, slot=1):
super(REDSpot18RGB, self).__init__(dmx, slot, 1) super(REDSpot18RGB, self).__init__(dmx, slot, 1)
dmx.set(self.slot+0, 0) dmx.set(self.slot + 0, 0)
class StairvilleLedPar56(RGB): class StairvilleLedPar56(RGB):
def __init__(self, dmx, slot=1): def __init__(self, dmx, slot=1):
super(StairvilleLedPar56, self).__init__(dmx, slot, 0) super(StairvilleLedPar56, self).__init__(dmx, slot, 0)
dmx.set(self.slot+3, 0) dmx.set(self.slot + 3, 0)
dmx.set(self.slot+4, 0) dmx.set(self.slot + 4, 0)
dmx.set(self.slot+5, 0) dmx.set(self.slot + 5, 0)
dmx.set(self.slot+6, 255) dmx.set(self.slot + 6, 255)
class Steady: class Steady:
@ -122,7 +123,7 @@ class DMX:
self.data = bytearray(maxchan) self.data = bytearray(maxchan)
packet = bytearray() packet = bytearray()
packet.extend(map(ord, "Art-Net")) packet.extend(map(ord, "Art-Net"))
packet.append(0x00) # Null terminate Art-Net packet.append(0x00) # Null terminate Art-Net
packet.extend([0x00, 0x50]) # Opcode ArtDMX 0x5000 (Little endian) packet.extend([0x00, 0x50]) # Opcode ArtDMX 0x5000 (Little endian)
packet.extend([0x00, 0x0e]) # Protocol version 14 packet.extend([0x00, 0x0e]) # Protocol version 14
self.header = packet self.header = packet
@ -130,30 +131,35 @@ class DMX:
self.animation = FadeTo(255, 255, 255) self.animation = FadeTo(255, 255, 255)
self.rgbs = [] self.rgbs = []
self.thread = None self.thread = None
self.updating = False
def start(self): def start(self):
if self.thread and self.thread.is_alive(): if self.thread and self.thread.is_alive():
return return
self.thread = Thread(daemon=True, target=self.background) self.thread = Thread(daemon=True, target=self.background)
self.updating = True
self.thread.start() self.thread.start()
def background(self): def background(self):
while True: while self.updating:
animation = self.animation
for i in range(0, len(self.rgbs)):
self.rgbs[i].rgb(animation.update(i, len(self.rgbs)))
self.update() self.update()
# print("updating") # print("updating")
# print(self.data) # print(self.data)
# break # break
sleep(1.0/30) sleep(1.0 / 30)
def update(self): def update(self):
if not self.animation:
return
for i in range(0, len(self.rgbs)):
self.rgbs[i].rgb(self.animation.update(i, len(self.rgbs)))
packet = self.header[:] packet = self.header[:]
packet.append(self.sequence) # Sequence, packet.append(self.sequence) # Sequence,
packet.append(0x00) # Physical packet.append(0x00) # Physical
packet.append(self.universe & 0xFF) # Universe LowByte packet.append(self.universe & 0xFF) # Universe LowByte
packet.append(self.universe >> 8 & 0xFF) # Universe HighByte packet.append(self.universe >> 8 & 0xFF) # Universe HighByte
packet.extend(struct.pack('>h', len(self.data))) # Pack the number of channels Big endian packet.extend(struct.pack('>h', len(self.data))) # Pack the number of channels Big endian
packet.extend(self.data) packet.extend(self.data)
@ -165,8 +171,16 @@ class DMX:
self.sequence = 1 self.sequence = 1
def set(self, slot, value): def set(self, slot, value):
self.data[slot-1] = value self.data[slot - 1] = value
def setAnimation(self, animation): def setAnimation(self, animation):
self.animation = animation if not animation:
self.updating = False
self.thread.join()
# one frame black
self.animation = Steady(0, 0, 0)
self.update()
else:
self.animation = animation
self.start()
print(f"Animation: {animation}", file=sys.stderr) print(f"Animation: {animation}", file=sys.stderr)

View file

@ -20,7 +20,7 @@ def static(path):
@route('/api/state/<state>') @route('/api/state/<state>')
def update(state): def update(state):
if state == "off": if state == "off":
dmx.setAnimation(Steady(0, 0, 0)) dmx.setAnimation(None)
elif state == "white": elif state == "white":
dmx.setAnimation(Steady(255, 255, 255)) dmx.setAnimation(Steady(255, 255, 255))
elif state == "red": elif state == "red":