From 1499890862488253bac4872c46a1ebd709594eff Mon Sep 17 00:00:00 2001 From: Thomas van der Berg Date: Sun, 21 May 2017 17:44:30 +0200 Subject: [PATCH 1/2] Simplify example Python client - Move handling packet size out of RandomFill - Adds an InitMessage function to vloed.py to set message header without using NewMessage - No more exceptions in normal program flow! --- client.py | 31 ++++++++++++++++++------------- vloed.py | 4 ++++ 2 files changed, 22 insertions(+), 13 deletions(-) diff --git a/client.py b/client.py index 5984c0d..d79037b 100755 --- a/client.py +++ b/client.py @@ -9,9 +9,9 @@ __version__ = 0.3 __author__ = "Jan Klopper " import random -from vloed import PixelVloedClient, NewMessage, RGBPixel, MAX_PIXELS +from vloed import PixelVloedClient, InitMessage, RGBPixel, MAX_PIXELS -def RandomFill(message, width, height): +def RandomFill(pixels, width, height): """Generates a random number of pixels with a random color""" for pixel in xrange(0, random.randint(10, MAX_PIXELS)): pixel = RGBPixel(random.randint(0, width), @@ -19,12 +19,7 @@ def RandomFill(message, width, height): random.randint(0, 255), random.randint(0, 255), random.randint(0, 255)) - try: - message.append(pixel) - except IndexError: - yield ''.join(message) - message[2:] = [pixel] - yield ''.join(message) + pixels.append(pixel) def RunClient(options): """Discover the servers and start sending to the first one""" @@ -36,15 +31,25 @@ def RunClient(options): options.width, # Screen pixels wide, None for autodetect options.height # Screen pixels height, None for autodetect ) - message = NewMessage() #create a new message that buffers the output etc # loop the effect until we cancel by pressing ctrl+c / exit the program while True: - # create a new message and send it every time the buffer is full + pixels = [] # list to store the pixels we want to send + + # add some pixels to the output with our functions # the width/height are read from the client's config - for packet in RandomFill(message, client.width, client.height): - # send the message we just filled with random pixels - client.SendPacket(packet) + RandomFill(pixels, client.width, client.height) + + # send our pixels in packets including a message header and less than + # MAX_PIXELS pixels + for part in SplitList(MAX_PIXELS, pixels): + packet = InitMessage([]) + part + client.SendPacket(''.join(packet)) + +def SplitList(max_size, lis): + """Splits a list into equal-sized chunks""" + for i in xrange(0, len(lis), max_size): + yield lis[i:i+max_size] if __name__ == '__main__': # if this script is called from the command line, and thus not imported diff --git a/vloed.py b/vloed.py index a54dce7..52b8275 100755 --- a/vloed.py +++ b/vloed.py @@ -264,6 +264,10 @@ class PixelVloedClient(object): def NewMessage(): """Creates a new message with the correct max size, rgb mode and version""" message = MaxSizeList(MAX_PIXELS+2) + InitMessage(message) + return message + +def InitMessage(message): message.append(SetRGBAMode(False)) message.append(SetVersionBit()) return message From 82892cae7ad65c9a218d6c2a03ff5ce498ca3be8 Mon Sep 17 00:00:00 2001 From: Thomas van der Berg Date: Thu, 15 Jun 2017 20:20:20 +0200 Subject: [PATCH 2/2] Simplify client using new Packet class Packet is a list of pixels that automatically sends pixels if it reaches the max packet size. Client code has been simplified using this class. --- client.py | 17 ++++++----------- vloed.py | 40 +++++++++++++++++++++++++++++++++++++++- 2 files changed, 45 insertions(+), 12 deletions(-) diff --git a/client.py b/client.py index d79037b..e0e96d0 100755 --- a/client.py +++ b/client.py @@ -9,7 +9,7 @@ __version__ = 0.3 __author__ = "Jan Klopper " import random -from vloed import PixelVloedClient, InitMessage, RGBPixel, MAX_PIXELS +from vloed import PixelVloedClient, Packet, RGBPixel, MAX_PIXELS def RandomFill(pixels, width, height): """Generates a random number of pixels with a random color""" @@ -34,22 +34,17 @@ def RunClient(options): # loop the effect until we cancel by pressing ctrl+c / exit the program while True: - pixels = [] # list to store the pixels we want to send + + # packet will automatically send its pixels if gets to the maximum pixel length + pixels = Packet(client) # add some pixels to the output with our functions # the width/height are read from the client's config RandomFill(pixels, client.width, client.height) - # send our pixels in packets including a message header and less than - # MAX_PIXELS pixels - for part in SplitList(MAX_PIXELS, pixels): - packet = InitMessage([]) + part - client.SendPacket(''.join(packet)) + # send whatever pixels are left in the packet + pixels.flush() -def SplitList(max_size, lis): - """Splits a list into equal-sized chunks""" - for i in xrange(0, len(lis), max_size): - yield lis[i:i+max_size] if __name__ == '__main__': # if this script is called from the command line, and thus not imported diff --git a/vloed.py b/vloed.py index 52b8275..e92d52d 100755 --- a/vloed.py +++ b/vloed.py @@ -24,6 +24,8 @@ PROTOCOL_VERSION = 1 MAX_PROTOCOL_VERSION = 1 PROTOCOL_PREAMBLE = "pixelvloed" MAX_PIXELS = 140 +MESSAGE_HEADER_SIZE = 2 +MAX_MESSAGE = MAX_PIXELS + MESSAGE_HEADER_SIZE class Canvas(object): """PixelVloed display class""" @@ -263,7 +265,7 @@ class PixelVloedClient(object): def NewMessage(): """Creates a new message with the correct max size, rgb mode and version""" - message = MaxSizeList(MAX_PIXELS+2) + message = MaxSizeList(MAX_MESSAGE) InitMessage(message) return message @@ -303,6 +305,42 @@ class MaxSizeList(list): raise IndexError('max size reached') super(MaxSizeList, self).append(item) +class Packet(list): + """A Pixelvloed packet. + + Append pixels to it. It will send automatically if it has MAX_PIXELS length. + """ + + def __init__(self, client): + """Create a new pixelvloed packet. + + This packet can be reused for the whole program. + + Arguments: + client: PixelVloedClient used to send the packet when it is full. + """ + self.client = client + super(Packet, self).__init__() + InitMessage(self) + + def append(self, item): + """Appends a pixel to this packet. + + Sends pixels and resets the packet if packet would exceed MAX_MESSAGE + (MAX_PIXELS + MESSAGE_HEADER_SIZE). + """ + if self.__len__() >= MAX_MESSAGE: + self._send() + super(Packet, self).append(item) + + def flush(self): + """Immediately send all pixels currently in this packet and empty it""" + self._send() + + def _send(self): + self.client.SendPacket(''.join(self)) + del self[MESSAGE_HEADER_SIZE:] # reset packet + def RunServer(options): """Runs a pixelvloed server""" PixelVloedServer('%s:%d' %(options.ip, options.port),