sender.py 2.5 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283
  1. # -*- coding: utf-8 -*-
  2. from __future__ import print_function, absolute_import, division
  3. import socket
  4. from struct import pack, unpack
  5. from functools import wraps
  6. from collections import namedtuple
  7. DECODER = {}
  8. ENCODER = {}
  9. def decode(data):
  10. format, make = DECODER[ord(data[0])]
  11. args = tuple([e if not isinstance(e, str) else e.decode('utf-8').rstrip('\0') for e in unpack(format, data[1:])])
  12. return make(args)
  13. class Sender(object):
  14. def __init__(self, host, port):
  15. self.host = host
  16. self.port = port
  17. self.sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
  18. def send(encoder):
  19. def _send(*args, **kwargs):
  20. data = encoder(*args, **kwargs)
  21. print('sending %s bytes' % len(data))
  22. self.sock.sendto(data, (self.host, self.port))
  23. return _send
  24. for name, f in ENCODER.iteritems():
  25. setattr(self, name, send(f))
  26. def matrix_api(api_index, format, names):
  27. assert api_index < 256
  28. def wrap(func):
  29. DECODER[api_index] = (format, namedtuple(func.__name__, names)._make)
  30. @wraps(func)
  31. def w(*args, **kwargs):
  32. pack_args = func(*args, **kwargs)
  33. if pack_args is None:
  34. assert not format and not names
  35. return chr(api_index)
  36. else:
  37. if isinstance(pack_args, (basestring, int, float)):
  38. pack_args = (pack_args, )
  39. #~ print(format, pack_args, pack(format, *pack_args))
  40. return chr(api_index) + pack(format, *pack_args)
  41. ENCODER[func.__name__] = w
  42. return w
  43. return wrap
  44. ## API Decls
  45. @matrix_api(1, '500s', 'text')
  46. def print_text(text):
  47. '''The maximum safe UDP payload is 508 bytes'''
  48. return text.encode('utf-8')
  49. @matrix_api(2, '500sh', 'text loop')
  50. def scroll_text(text, loop=1):
  51. return text.encode('utf-8'), loop
  52. @matrix_api(3, '500shh', 'text width fade')
  53. def fit_text(text, width=0, fade=0):
  54. return text.encode('utf-8'), width, fade
  55. @matrix_api(10, 'hh', 'step total')
  56. def progress(text, step=0, total=0):
  57. return step, total
  58. @matrix_api(255, '', '')
  59. def destroy():
  60. return None
  61. if __name__ == '__main__':
  62. #~ print(repr(print_text(u'Christine ♥')))
  63. print(decode(print_text(u'Christine ♥')).text.encode('utf-8'))
  64. #~ print(decode(print_text('Christine ♥'))._asdict())
  65. #~ print(type(decode(print_text('Christine ♥'))).__name__)
  66. sender = Sender('blaubeere.fritz.box', 10000)
  67. sender.print_text(u'Christine ♥')