add autodiscovery of server to client

This commit is contained in:
Jan Klopper 2016-04-25 12:18:39 +02:00
parent 060693625f
commit 9209bd989e
2 changed files with 75 additions and 13 deletions

View file

@ -5,9 +5,12 @@ Inspired by the PixelFlut beamer on eth0:winter 2016 and
code from https://github.com/defnull/pixelflut/ code from https://github.com/defnull/pixelflut/
""" """
__version__ = 0.1 __version__ = 0.2
__author__ = "Jan Klopper <jan@underdark.nl>" __author__ = "Jan Klopper <jan@underdark.nl>"
MAX_PROTOCOL_VERSION = 1;
PROTOCOL_PREAMBLE = 'pixelvloed'
import socket import socket
import struct import struct
import random import random
@ -65,15 +68,48 @@ def SendPacket(ipaddress, port, message):
socket.SOCK_DGRAM) # UDP socket.SOCK_DGRAM) # UDP
sock.sendto(message, (ipaddress, port)) sock.sendto(message, (ipaddress, port))
def main(): def DiscoverServers(discoveryport, timeout=5):
"""Sends some random pixels untill we break with ctrl+c""" """Discover servers that send out the pixelfvloed preample"""
ipaddress = "127.0.0.1" DiscoverySock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
port = 5005 DiscoverySock.bind(('', discoveryport))
starttime = time.time()
servers = []
foundhash = {}
while (time.time() - timeout) < starttime:
data, addr = DiscoverySock.recvfrom(1024)
try:
if data.startswith(PROTOCOL_PREAMBLE):
dataset = data.split(' ')
if float(dataset[0].split(':')[1]) <= MAX_PROTOCOL_VERSION:
ip = dataset[1].split(':')[0]
port = int(dataset[1].split(':')[1])
width = int(dataset[2].split('*')[0])
height = int(dataset[2].split('*')[1])
if data not in foundhash:
newserver = {'ip': ip,
'port': port,
'width': width,
'height': height}
foundhash[data] = True
print 'New pixelvloed screen found: %r' % newserver
servers.append(newserver)
except:
pass
if servers:
return servers
return False
def main():
"""Discover the servers and start sending to the first one"""
discoveryport = 5006
servers = False
while servers == False:
servers = DiscoverServers(discoveryport)
print 'displaying on %(ip)s:%(port)d, %(width)d*%(height)dpx' % servers[0]
while True: while True:
for packet in RandomFill(): for packet in RandomFill(servers[0]['width'], servers[0]['height']):
time.sleep(0.01) time.sleep(0.01)
SendPacket(ipaddress, port, packet) SendPacket(servers[0]['ip'], servers[0]['port'], packet)
if __name__ == '__main__': if __name__ == '__main__':
main() main()

View file

@ -19,6 +19,8 @@ from gevent.queue import Queue
monkey.patch_all() monkey.patch_all()
UDP_IP = "127.0.0.1" UDP_IP = "127.0.0.1"
UDP_PORT= 5005 UDP_PORT= 5005
PROTOCOL_VERSION = 1
PROTOCOL_PREAMBLE = "pixelvloed"
def main(): def main():
"""Runs a pixelvloed server""" """Runs a pixelvloed server"""
@ -27,7 +29,7 @@ def main():
class Canvas(object): class Canvas(object):
"""PixelVloed server class""" """PixelVloed server class"""
def __init__(self, queue, debug=False): def __init__(self, queue, width=1366, height=768, debug=True):
"""Init the pixelVloed server""" """Init the pixelVloed server"""
self.debug = debug self.debug = debug
self.pixeloffset = 2 self.pixeloffset = 2
@ -35,10 +37,15 @@ class Canvas(object):
self.screen = None self.screen = None
self.udp_ip = UDP_IP self.udp_ip = UDP_IP
self.udp_port = UDP_PORT self.udp_port = UDP_PORT
self.width = width
self.height = height
self.canvas() self.canvas()
self.set_title() self.set_title()
self.queue = queue self.queue = queue
self.limit = 140 self.limit = 140
self.broadcastSocket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
self.broadcastSocket.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1)
self.broadcastSocket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
@staticmethod @staticmethod
def set_title(text=None): def set_title(text=None):
@ -48,12 +55,12 @@ class Canvas(object):
title += ' ' + text title += ' ' + text
pygame.display.set_caption(title) pygame.display.set_caption(title)
def canvas(self, width=1366, height=768): def canvas(self):
"""Init the pygame canvas""" """Init the pygame canvas"""
pygame.init() pygame.init()
pygame.mixer.quit() pygame.mixer.quit()
flags = DOUBLEBUF flags = DOUBLEBUF
self.screen = pygame.display.set_mode((width, height), flags) self.screen = pygame.display.set_mode((self.width, self.height), flags)
def clear(self, r=0, g=0, b=0): # pylint: disable=C0103 def clear(self, r=0, g=0, b=0): # pylint: disable=C0103
""" Fill the entire screen with a solid colour (default: black)""" """ Fill the entire screen with a solid colour (default: black)"""
@ -69,9 +76,14 @@ class Canvas(object):
def CanvasUpdate(self): def CanvasUpdate(self):
"""Updates the screen according to self.fps""" """Updates the screen according to self.fps"""
lasttime = time.time() lasttime = time.time()
lastbroadcast = time.time()
changed = False changed = False
while True: while True:
changed = self.Draw() or changed changed = self.Draw() or changed
if time.time() - lastbroadcast > 2:
lastbroadcast = time.time()
self.SendDiscoveryPacket()
if time.time() - lasttime >= 1.0 / self.fps and changed: if time.time() - lasttime >= 1.0 / self.fps and changed:
self.pixels = None # release the lock on these pixels so we can flip self.pixels = None # release the lock on these pixels so we can flip
pygame.display.flip() pygame.display.flip()
@ -99,10 +111,10 @@ class Canvas(object):
if preamble else if preamble else
7 #xx,yy,r,g,b 7 #xx,yy,r,g,b
) )
pixelcount = (len(data)-1) / pixellength pixelcount = min(((len(data)-1) / pixellength),
self.limit)
if self.debug: if self.debug:
print '%d pixels received, protocol V %d ' % ( print '%d pixels received, protocol V %d ' % (pixelcount, protocol)
min(pixelcount, self.limit), protocol)
for i in xrange(0, pixelcount): for i in xrange(0, pixelcount):
pixel = struct.unpack_from( pixel = struct.unpack_from(
packetformat, packetformat,
@ -114,6 +126,20 @@ class Canvas(object):
# indicate that we have been drawing stuff # indicate that we have been drawing stuff
return True return True
def SendDiscoveryPacket(self):
"""Lets send out our ip/port/resolution to any listening clients"""
self.broadcastSocket.sendto(
'%s:%f %s:%d %d*%d' % (PROTOCOL_PREAMBLE, PROTOCOL_VERSION,
UDP_IP, UDP_PORT,
self.width, self.height),
('<broadcast>', UDP_PORT+1))
if self.debug:
print 'sending discovery packet'
def __del__(self):
"""Clean up any sockets we created"""
self.broadcastSocket.close()
class PixelVloed(DatagramServer): class PixelVloed(DatagramServer):
"""PixelVloed server class""" """PixelVloed server class"""
queue = Queue() queue = Queue()