2018-01-11 23:46:46 +01:00
#!/usr/bin/env python3
# -*- coding: UTF-8 -*-
import _thread
import socket
import pygame
import math
import random
import numpy as np
from pygame . locals import *
import time
WIDTH = 160
HEIGHT = 24 * 6
PIXELSIZE = 4 #For Simulator Display
UDPPORT = 2323
DEBUG = True
BITSPERPIXEL = 2
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 . flipdotMatrixSimulatorWidget = FlipdotMatrixSimulatorWidget ( 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 . timesincelastpacket = time . time ( )
2018-01-13 13:11:20 +01:00
self . timelastcalculation = 0
2018-01-11 23:46:46 +01:00
def run ( self ) :
self . RunServer ( )
def bitlistToInt ( self , bitlist ) : #lsb last, [1,0]=2, [0,1]=1
number = 0
for bitindex , bitvalue in enumerate ( reversed ( bitlist ) ) :
number + = bitvalue * pow ( 2 , bitindex )
return number
def RunServer ( self ) :
try :
while True :
#rawData = self.udpHostSocket.recv(4096)
rawData = self . udpHostSocket . recv ( 4096 * 2 )
imageArray = ImageArrayAdapter ( ) . convertPacketToImageArray ( rawData )
if DEBUG :
2018-01-13 13:11:20 +01:00
print ( " Received Data. Time since last message: " + str ( round ( time . time ( ) - self . timesincelastpacket , 2 ) ) + " s ( " + str ( round ( ( 1 / ( time . time ( ) - self . timesincelastpacket ) ) , 2 ) ) + " FPS), last calctime= " + str ( round ( ( self . timelastcalculation ) , 2 ) ) )
2018-01-11 23:46:46 +01:00
self . timesincelastpacket = time . time ( )
_bitsneeded = self . imageSize [ 0 ] * self . imageSize [ 1 ] * self . bitsperpixel
if len ( imageArray ) < _bitsneeded :
if DEBUG :
print ( " WARNING: Not enough data received. Got " + str ( len ( imageArray ) ) + " bits, needs " + str ( _bitsneeded ) + " bits " )
emptyArray = np . zeros ( _bitsneeded , dtype = int )
emptyArray [ 0 : len ( imageArray ) ] = imageArray
imageArray = emptyArray
elif len ( imageArray ) > _bitsneeded :
if DEBUG :
print ( " WARNING: Too much data received. Got " + str ( len ( imageArray ) ) + " bits, needs " + str ( _bitsneeded ) + " bits " )
imageArray = imageArray [ 0 : _bitsneeded ]
imageArray = [ self . bitlistToInt ( x ) for x in np . array ( imageArray ) . reshape ( ( int ( len ( imageArray ) / self . bitsperpixel ) , self . bitsperpixel ) ) ]
self . flipdotMatrixSimulatorWidget . show ( imageArray ) #send to simulator display
2018-01-13 13:11:20 +01:00
self . timelastcalculation = time . time ( ) - self . timesincelastpacket #calculate time it took for calculation and drawing
2018-01-11 23:46:46 +01:00
finally :
self . udpHostSocket . close ( )
class ImageArrayAdapter ( ) :
def __init__ ( self ) :
self . arrayOfBinaryInts = [ ]
def convertPacketToImageArray ( self , udpPacketStr ) :
self . arrayOfBinaryInts = [ ]
byteArray = bytearray ( udpPacketStr )
#Fix for other format. Not Used
#byteArray = udpPacketStr.translate(None, b'\r\n').decode().replace('[','').replace(']','').replace(' ','').split(',')
#byteArray = [int(x) for x in byteArray]
#print("rawtype="+str(type(byteArray)))
#print(byteArray)
for byte in byteArray :
#print("byte:"+str(byte))
self . __appendByteToArrayOfBinaryInts ( byte )
return self . arrayOfBinaryInts
def __appendByteToArrayOfBinaryInts ( self , byte ) :
byteValue = int ( byte )
for i in range ( 8 ) :
if math . floor ( byteValue / ( 2 * * ( 7 - i ) ) ) > 0 :
self . arrayOfBinaryInts . append ( 1 )
#print("append 1")
else :
self . arrayOfBinaryInts . append ( 0 )
#print("append 0")
byteValue = byteValue % ( 2 * * ( 7 - i ) )
class FlipdotMatrixSimulatorWidget ( ) :
BLACKCOLOR = 0
WHITECOLOR = 1
def __init__ ( self ,
imageSize = ( 160 , 48 ) ,
pixelSize = 4 ,
bitsperpixel = 1 ) :
self . imageSize = imageSize
self . pixelSize = pixelSize
pygame . init ( )
self . screen = pygame . display . set_mode ( ( imageSize [ 0 ] * pixelSize , imageSize [ 1 ] * pixelSize ) )
self . screen . fill ( ( 255 , 255 , 255 ) )
_thread . start_new_thread ( self . watchCloseThread , ( ) )
self . bitsperpixel = bitsperpixel
def watchCloseThread ( self ) :
while True :
for event in pygame . event . get ( ) :
if event . type in ( QUIT , QUIT ) :
import os
os . kill ( os . getpid ( ) , 9 )
pygame . time . delay ( 500 )
def show ( self , imageArray ) :
for yValue in range ( self . imageSize [ 1 ] ) :
for xValue in range ( self . imageSize [ 0 ] ) :
i = self . imageSize [ 0 ] * yValue + xValue
color = imageArray [ i ] / ( pow ( 2 , self . bitsperpixel ) - 1 ) #gives a number between 0 and 1 inclusive. Example for bitsperpixel=2: [1,0]-> 2/ (2^2-1)=2/3
self . updatePixel ( xValue , yValue , color )
pygame . display . update ( )
def clearPixels ( self ) :
for xValue in range ( self . imageSize [ 0 ] ) :
for yValue in range ( self . imageSize [ 1 ] ) :
self . updatePixel ( xValue , yValue , self . BLACKCOLOR )
def updatePixel ( self , xValue , yValue , brightness ) :
surface = pygame . Surface ( ( self . pixelSize , self . pixelSize ) )
minimumbrightness = 32
rectcolor = ( ( 255 - minimumbrightness ) * brightness + minimumbrightness , 127 * brightness + minimumbrightness / 2 , minimumbrightness / 4 )
#surface.fill(rectcolor)
pygame . draw . circle ( surface , rectcolor , ( int ( self . pixelSize / 2 ) , int ( self . pixelSize / 2 ) ) , int ( self . pixelSize / 2 ) ) #Draw LED as filled circles
self . screen . blit ( surface , ( xValue * self . pixelSize , yValue * self . pixelSize ) )
if __name__ == ' __main__ ' :
FlipdotSim ( imageSize = ( WIDTH , HEIGHT ) , pixelSize = PIXELSIZE , udpPort = UDPPORT , bitsperpixel = BITSPERPIXEL ) . run ( )