From ffc8eac9099291bb5590fb389a2eced8bae127ca Mon Sep 17 00:00:00 2001 From: Fisch Date: Sun, 30 Jun 2019 14:48:00 +0200 Subject: [PATCH] add animations for textFull and image --- FlipdotSender.py | 79 ++++++++++++++++++++++++++-------------------- mqtt-to-flipdot.py | 66 ++++++++++++++++++++++++++++---------- 2 files changed, 94 insertions(+), 51 deletions(-) diff --git a/FlipdotSender.py b/FlipdotSender.py index 932958d..027cb34 100644 --- a/FlipdotSender.py +++ b/FlipdotSender.py @@ -11,7 +11,7 @@ class FlipdotSender(object): ''' classdocs ''' - + C_BLACK = 0 C_WHITE = 255 @@ -20,17 +20,17 @@ class FlipdotSender(object): lastimgmap = [] - def __init__(self, udphost, udpport, img_size=(80,16), font_size=9, font_size_scroll=12, - font_offset1=(0,0), font_offset2=(0,8), + def __init__(self, udphost, udpport, img_size=(80,16), font_size=9, font_size_scroll=12, + font_offset1=(0,0), font_offset2=(0,8), #font_family='/usr/share/fonts/gnu-free/FreeMono.ttf', font_family='/usr/share/fonts/truetype/dejavu/DejaVuSansMono.ttf', - #font_family='/usr/share/fonts/truetype/freefont/FreeMono.ttf', - + #font_family='/usr/share/fonts/truetype/freefont/FreeMono.ttf', + chars_per_line=11): ''' Constructor ''' - + self._udphost = udphost if not type(udpport) is int or udpport > 65536: raise TypeError('port has to be int and > 65536 !!') @@ -42,24 +42,24 @@ class FlipdotSender(object): self._font_offset2 = font_offset2 self._font_family = font_family self._chars_per_line = chars_per_line - + self._sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) def stopAnimation(self): global threadrunning threadrunning=False #tried to stop a running animation - - + + def _list2byte(self, l): byte = 0 i = 0 for i in range(8): byte += 2**(7-i) if l[i] else 0 return byte - - def _array2packet(self, a): + + def _array2packet(self, a): return [self._list2byte(a[i*8:i*8+8]) for i in range(int(len(a)/8))] - + ''' def _send(self, image): #old function, backup imgmap = [] @@ -71,14 +71,14 @@ class FlipdotSender(object): imgmap.append(0) lastimgmap=imgmap - + packet = self._array2packet(imgmap) - + self._sock.sendto(bytes(packet), (self._udphost, self._udpport))''' def _send(self, image,fadespeed=0): #changes slowly 'fadespeed'-pixels at a time global threadrunning - #if fadespeed=0 -> change instant. + #if fadespeed=0 -> change instant. #time to change= 1280/25*0.2 imgmap = [] for pixel in image.getdata(): @@ -90,7 +90,7 @@ class FlipdotSender(object): imgmaptmp=FlipdotSender.lastimgmap - + if fadespeed>0: threadrunning=True #diff=np.sum(np.array(imgmaptmp) != np.array(imgmap)) #different pixels @@ -111,14 +111,14 @@ class FlipdotSender(object): threadrunning=False else: self.sendPacket(imgmap) #send packet and save last-imagemap - + def sendPacket(self, imgmap): packet = self._array2packet(imgmap) self._sock.sendto(bytes(packet), (self._udphost, self._udpport)) FlipdotSender.lastimgmap=imgmap - + def send_bytes(self, img): imgmap = [] for pixel in img: @@ -134,70 +134,81 @@ class FlipdotSender(object): self._sock.sendto(bytes(packet), (self._udphost, self._udpport)) - + def send_binimage(self, data,fadespeed=0): #works like send_bytes, but enables fadeanimation + image = Image.new("RGBA", self._img_size, FlipdotSender.C_BLACK) + draw = ImageDraw.Draw(image) + draw.fontmode = "1" + + for i,d in enumerate(data): + if d=="1": + draw.point((i%self._img_size[0],int(i/self._img_size[0])), fill=FlipdotSender.C_WHITE) + + self._send(image,fadespeed) + + def send_text(self, text,fadespeed=0): image = Image.new("RGBA", self._img_size, FlipdotSender.C_BLACK) draw = ImageDraw.Draw(image) draw.fontmode = "1" # No AA - + font = ImageFont.truetype(self._font_family, self._font_size) - + cut = self._chars_per_line - + splitted_text = text.split("|") - + draw.text(self._font_offset1, splitted_text[0], font=font, fill=FlipdotSender.C_WHITE) if len(splitted_text)>1: draw.text(self._font_offset2, splitted_text[1], font=font, fill=FlipdotSender.C_WHITE) - + self._send(image,fadespeed) def send_textFull(self, text,fadespeed=0): image = Image.new("RGBA", self._img_size, FlipdotSender.C_BLACK) draw = ImageDraw.Draw(image) draw.fontmode = "1" # No AA - + l=1000 #init very high splitpoint=40 #very high currentfontsize=12+1 #init with max font size font = ImageFont.truetype(self._font_family, currentfontsize) while(l>80): #while text too long and font not too small - if currentfontsize>8: + if currentfontsize>8: currentfontsize=currentfontsize-1 #reduce size and try if fits else: #if fontsize too small, try cutting sentence (2 lines) splitpoint=splitpoint-1 - + font = ImageFont.truetype(self._font_family, currentfontsize) l=draw.textsize(text[0:splitpoint], font=font)[0] print("Textlength="+str(l)+" split="+str(splitpoint)) - + if splitpoint==40: #not splitted draw.text((0,int((16-currentfontsize)/2) ), text, font=font, fill=FlipdotSender.C_WHITE) else: draw.text((0,-1), text[0:splitpoint], font=font, fill=FlipdotSender.C_WHITE) draw.text((0,-1+currentfontsize), text[splitpoint:], font=font, fill=FlipdotSender.C_WHITE) - + self._send(image,fadespeed) - + def send_marquee(self, str, speed=3): global threadrunning threadrunning=True offset = self._img_size[0] font = ImageFont.truetype(self._font_family, self._font_size_scroll) - + while offset >= -font.getsize(str)[0]-speed and threadrunning==True: image = Image.new("RGBA", self._img_size, FlipdotSender.C_BLACK) draw = ImageDraw.Draw(image) draw.fontmode = "1" # No AA - + draw.text((offset,0), str, font=font, fill=FlipdotSender.C_WHITE) self._send(image) offset -= speed time.sleep(0.15) threadrunning=False - + def send_img(self, img): background = Image.new("RGBA", self._img_size, FlipdotSender.C_BLACK) stream = io.BytesIO(img) @@ -207,5 +218,5 @@ class FlipdotSender(object): image.save('/tmp/send2.jpeg', 'JPEG') background.paste(image, box=(0,0), mask=None) background.save('/tmp/send.jpeg', 'JPEG') - + self._send(background) diff --git a/mqtt-to-flipdot.py b/mqtt-to-flipdot.py index cfafde0..51cec44 100644 --- a/mqtt-to-flipdot.py +++ b/mqtt-to-flipdot.py @@ -33,14 +33,14 @@ def on_message(client, userdata, msg): mode="inuse" updateTimeout() payload = msg.payload.decode("utf-8") - + if len(payload)>0 and (payload[0]).isdigit(): speed = int(payload[0]) text = payload[1:] - else: + else: speed = 3 text = payload - + #flipdot.send_marquee(text, speed) if flipthread is not None and flipthread.isAlive(): flipdot.stopAnimation() @@ -48,7 +48,7 @@ def on_message(client, userdata, msg): flipdot.stopAnimation() #try to stop animation time.sleep(0.1) flipthread.join() #wait for thread to finish - + flipthread=Thread(target=flipdot.send_marquee, args=(text,speed)) flipthread.start() @@ -72,21 +72,55 @@ def on_message(client, userdata, msg): flipthread.start() - if msg.topic == "raum2/flipdot/textFull/set": #scale/break text automatically - mode="inuse" - updateTimeout() + if mode!="inuse" and msg.topic == "raum2/flipdot/textFull/set": #scale/break text automatically + #mode="inuse" + #updateTimeout() payload = msg.payload.decode("utf-8") + + if flipthread is not None and flipthread.isAlive(): + flipdot.stopAnimation() + while flipthread.isAlive(): + flipdot.stopAnimation() #try to stop animation + time.sleep(0.1) + flipthread.join() + if len(payload)>0 and payload[0]=='~': payload=payload[1:] - flipdot.send_textFull(payload,50) - flipdot.send_textFull(payload) - + #flipdot.send_textFull(payload,50) + flipthread=Thread(target=flipdot.send_textFull, args=(payload,64)) + else: + #flipdot.send_textFull(payload) + flipthread=Thread(target=flipdot.send_textFull, args=(payload,)) + + flipthread.start() + if msg.topic == "raum2/flipdot/image/set": + ''' mode="inuse" updateTimeout() payload = msg.payload.decode("utf-8") print(payload) - flipdot.send_bytes(payload) + flipdot.send_bytes(payload) + ''' + payload = msg.payload.decode("utf-8") + + if flipthread is not None and flipthread.isAlive(): + flipdot.stopAnimation() + while flipthread.isAlive(): + flipdot.stopAnimation() #try to stop animation + time.sleep(0.1) + flipthread.join() + + if len(payload)>0 and payload[0]=='~': + payload=payload[1:] + #flipdot.send_textFull(payload,50) + flipthread=Thread(target=flipdot.send_binimage, args=(payload,64)) + else: + #flipdot.send_textFull(payload) + flipthread=Thread(target=flipdot.send_binimage, args=(payload,)) + + flipthread.start() + @@ -98,7 +132,7 @@ def on_message(client, userdata, msg): updateTimeout() client.publish("raum2/flipdot/hangman","started") mode="hangman" - + elif (mode=="hangman") and (len(payload)>0): #try entered character updateTimeout() trychar=payload[-1] @@ -112,16 +146,16 @@ def on_message(client, userdata, msg): client.publish("raum2/flipdot/hangman","won") elif gamestatus==0: #ended in another way client.publish("raum2/flipdot/hangman","ended") - + if payload=="#stop": - mode="standby" + mode="standby" client.publish("raum2/flipdot/hangman","ended") def updateTimeout(): global timeout timeout=int(round(time.time() * 1000)) - + #flipdot = FlipdotSender("2001:67c:275c:a9::c", 2323) flipdot = FlipdotSender("localhost", 2323) @@ -150,5 +184,3 @@ while True: timeout=0 time.sleep(2) - -