From 00c37d76ca1aa251a6a674e9a9350a95d572e307 Mon Sep 17 00:00:00 2001 From: Fisch Date: Sun, 1 Apr 2018 15:40:02 +0200 Subject: [PATCH] implement matrixsimulator to pixelflut bridge in python --- client_sw/matrixsimulator_pixelflut.py | 175 +++++++++++++++++++++++++ 1 file changed, 175 insertions(+) create mode 100644 client_sw/matrixsimulator_pixelflut.py diff --git a/client_sw/matrixsimulator_pixelflut.py b/client_sw/matrixsimulator_pixelflut.py new file mode 100644 index 0000000..a106193 --- /dev/null +++ b/client_sw/matrixsimulator_pixelflut.py @@ -0,0 +1,175 @@ +#!/usr/bin/env python3 +# -*- coding: UTF-8 -*- +import _thread +import socket +import math +import random +import numpy as np +from pygame.locals import * +import time +import sys +from _thread import start_new_thread + + +#PIXELFLUT +TCP_IP = '94.45.232.48' #eh18 +TCP_PORT = 1234 +BUFFER_SIZE = 4096 +flutwidth = 1920 +flutheight = 1080 +commandsarray=[] + +#FLITDOT +WIDTH=160 +HEIGHT=24*6 +PIXELSIZE=2 #For Simulator Display +UDPPORT=2323 +DEBUG=True +BITSPERPIXEL=2 + + + + + + +def randomnumber(pseed,pmin,pmax,v1,v2,v3): + return (pseed*v1+pseed^2*v2+pseed^3*v3)%(pmax-pmin)+pmin + +newseed=(int)(time.time()/60) #seed based on timestamp (full minutes) +seed=newseed + +user=int(sys.argv[1]) #1..n +parts=int(sys.argv[2]) #n users + +pixelcoords=[] +for _x in range(WIDTH): + for _y in range(HEIGHT): + pixelcoords+=[(_x,_y)] + +random.seed(42) +random.shuffle(pixelcoords) #pseudorandom order + +pixelcoords=pixelcoords[int(len(pixelcoords)/parts)*(user-1):int(len(pixelcoords)/parts)*(user)] #divide in parts for multiple connection + +xv=flutwidth-WIDTH*PIXELSIZE +yv=flutheight-HEIGHT*PIXELSIZE-500 + + +class FlipdotSim(): + def __init__(self, + imageSize = (160,48), #80,16 + pixelSize = 10, + udpPort = 2323, + bitsperpixel=1): + self.imageSize=imageSize + self.udpPort = udpPort + self.bitsperpixel=bitsperpixel + self.MatrixsimulatorPixelflut = MatrixsimulatorPixelflut(imageSize, pixelSize, bitsperpixel) #comment out if no simulator needed + self.udpHostSocket = socket.socket(socket.AF_INET6, socket.SOCK_DGRAM) + self.udpHostSocket.bind(("", self.udpPort)) + + self.time_receivedpacket=0 + + self.bitsneeded=self.imageSize[0]*self.imageSize[1]*self.bitsperpixel + + + def run(self): + self.RunServer() + + + def RunServer(self): + try: + while True: + rawData = self.udpHostSocket.recv(4096*2) + _fps=1/(time.time()-self.time_receivedpacket) + self.time_receivedpacket=time.time() + + self.MatrixsimulatorPixelflut.showFromRawData(rawData) #send to simulator display + + calctime=time.time()-self.time_receivedpacket + print(str(round(calctime,4))+"s, maxFPS="+str(round(1/calctime,2))+", actual FPS="+str(round(_fps,2))) #calculate time it took for calculation and drawing + + finally: + self.udpHostSocket.close() + + + +class MatrixsimulatorPixelflut(): + BLACKCOLOR = 0 + WHITECOLOR = 1 + + def __init__(self, + imageSize = (160,48), + pixelSize = 1, + bitsperpixel = 1): + self.imageSize = imageSize + self.pixelSize = pixelSize + + + self.bitsperpixel=bitsperpixel + + minimumbrightness=0 + self.colorTable=[] + for i in range(pow(2,self.bitsperpixel)): + brightness=i/pow(2,self.bitsperpixel) + #self.colorTable.append( ( int( (255-minimumbrightness)*brightness+minimumbrightness) , int(127*brightness+ minimumbrightness/2), int(minimumbrightness/4) ) ) + self.colorTable.append( ( int( 255*brightness) , int( 255*brightness) ,int( 255*brightness) )) + + + + def showFromRawData(self, rawData): + x=0 #pixel x position + y=0 #pixel y position + bitshifts=[x*self.bitsperpixel for x in range(int(8/self.bitsperpixel))] + bitmask=int('00000011', 2) + + global commandsarray + commandsarray=[] + _current_command="" + + for cbyte in rawData: + for numbershifts in bitshifts: + pixelbyte = ( cbyte & (bitmask<> numbershifts + + #pygame.draw.circle(self.screen, self.colorTable[pixelbyte], (int(x*self.pixelSize+self.pixelSize/2), int(y*self.pixelSize+self.pixelSize/2)), int(self.pixelSize/2)) #Draw LED as filled circles + r,g,b=self.colorTable[pixelbyte] + + for i in range(self.pixelSize): + for j in range(self.pixelSize): + _current_command+='PX %d %d %02x%02x%02x\n' % (int(x*self.pixelSize+self.pixelSize/2)+xv+i, int(y*self.pixelSize+self.pixelSize/2)+yv+j,r,g,b) #rgb + #_current_command+='PX %d %d %02x\n' % ((int(x*self.pixelSize+self.pixelSize/2)+xv, int(y*self.pixelSize+self.pixelSize/2)+yv),r) #monochrome only red channel + + + + if len(_current_command)>=1400: #divide in packets smaller than 1500 byte + commandsarray+=[_current_command.encode()] #append packet + _current_command="" + + x+=1 #next pixel + y+=int(x/self.imageSize[0]) #next column if end of row + x%=self.imageSize[0] #start at first column if end of row + commandsarray+=[_current_command.encode()] #append last packet + +def sendthread(a): + s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + def __init__(self): + self.s.connect((TCP_IP, TCP_PORT)) + while True: + try: + starttime=time.time() + for command in commandsarray: + s.send(command) + print("Send Image in "+str(time.time()-starttime)+" seconds") + except BrokenPipeError: #Brokn Pipe? Reconnect!! + print("BrokenPipeError. Reconnecting") + s.close() + s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + s.connect((TCP_IP, TCP_PORT)) #reconnect + print("reconnected") + +if __name__ == '__main__': + start_new_thread(sendthread,(99,)) + start_new_thread(sendthread,(99,)) #more connections + start_new_thread(sendthread,(99,)) #more connections + start_new_thread(sendthread,(99,)) #more connections + FlipdotSim(imageSize=(WIDTH,HEIGHT), pixelSize = PIXELSIZE, udpPort=UDPPORT, bitsperpixel=BITSPERPIXEL).run()