@ -247,9 +247,9 @@ charmap = u'ABCDEFGHIJKLMNOPQRSTUVWXYZ' + \
u " àäòöùüèéêëôöûîïÿç " + \
u " àäòöùüèéêëôöûîïÿç " + \
u " ÀÅÄÉÈÊËÖÔÜÛÙŸ "
u " ÀÅÄÉÈÊËÖÔÜÛÙŸ "
char_offset = { }
char_offsets = { }
for i in range ( len ( charmap ) ) :
for i in range ( len ( charmap ) ) :
char_offset [ charmap [ i ] ] = 11 * i
char_offsets [ charmap [ i ] ] = 11 * i
# print(i, charmap[i], char_offset[charmap[i]])
# print(i, charmap[i], char_offset[charmap[i]])
bitmap_preloaded = [ ( [ ] , 0 ) ]
bitmap_preloaded = [ ( [ ] , 0 ) ]
@ -320,7 +320,7 @@ def bitmap_char(ch):
bitmaps_preloaded_unused = False
bitmaps_preloaded_unused = False
return bitmap_preloaded [ ord ( ch ) ]
return bitmap_preloaded [ ord ( ch ) ]
o = char_offset [ ch ]
o = char_offsets [ ch ]
return ( font_11x44 [ o : o + 11 ] , 1 )
return ( font_11x44 [ o : o + 11 ] , 1 )
@ -334,7 +334,7 @@ def bitmap_text(text):
" :gfx/logo.png: " preloads the file gfx / logo . png and is replaced the corresponding control char .
" :gfx/logo.png: " preloads the file gfx / logo . png and is replaced the corresponding control char .
"""
"""
def colon repl( m ) :
def replace_symbolic ( m ) :
name = m . group ( 1 )
name = m . group ( 1 )
if name == ' ' :
if name == ' ' :
return ' : '
return ' : '
@ -343,10 +343,9 @@ def bitmap_text(text):
if ' . ' in name :
if ' . ' in name :
bitmap_preloaded . append ( bitmap_img ( name ) )
bitmap_preloaded . append ( bitmap_img ( name ) )
return chr ( len ( bitmap_preloaded ) - 1 )
return chr ( len ( bitmap_preloaded ) - 1 )
b = bitmap_named [ name ]
return bitmap_named [ name ] [ 2 ]
return b [ 2 ]
text = re . sub ( r ' :([^:]*): ' , colon repl, text )
text = re . sub ( r ' :([^:]*): ' , replace_symbolic , text )
buf = array ( ' B ' )
buf = array ( ' B ' )
cols = 0
cols = 0
for c in text :
for c in text :
@ -391,7 +390,7 @@ def bitmap_img(file):
def bitmap ( arg ) :
def bitmap ( arg ) :
""" if arg is a valid and existing path name, we load it as an image.
""" if arg is a valid and existing path name, we load it as an image.
Otherwise we take it as a string .
Otherwise , we take it as a string .
"""
"""
if os . path . exists ( arg ) :
if os . path . exists ( arg ) :
return bitmap_img ( arg )
return bitmap_img ( arg )
@ -406,7 +405,7 @@ proto_header = (
)
)
def header ( lengths , speeds , modes , blink , ants , brightness = 100 ) :
def header ( lengths , speeds , modes , blink , ants , brightness = 100 , date = datetime . now ( ) ) :
""" lengths[0] is the number of chars of the first text
""" lengths[0] is the number of chars of the first text
Speeds come in as 1. .8 , but are needed 0. .7 here .
Speeds come in as 1. .8 , but are needed 0. .7 here .
@ -443,38 +442,39 @@ def header(lengths, speeds, modes, blink, ants, brightness=100):
h [ 17 + ( 2 * i ) - 1 ] = lengths [ i ] / / 256
h [ 17 + ( 2 * i ) - 1 ] = lengths [ i ] / / 256
h [ 17 + ( 2 * i ) ] = lengths [ i ] % 256
h [ 17 + ( 2 * i ) ] = lengths [ i ] % 256
cdate = datetime . now ( )
h [ 38 + 0 ] = date . year % 100
h [ 38 + 0 ] = cdate . year % 100
h [ 38 + 1 ] = date . month
h [ 38 + 1 ] = cdate . month
h [ 38 + 2 ] = date . day
h [ 38 + 2 ] = cdate . day
h [ 38 + 3 ] = date . hour
h [ 38 + 3 ] = cdate . hour
h [ 38 + 4 ] = date . minute
h [ 38 + 4 ] = cdate . minute
h [ 38 + 5 ] = date . second
h [ 38 + 5 ] = cdate . second
return h
return h
parser = argparse . ArgumentParser ( formatter_class = argparse . RawDescriptionHelpFormatter ,
if __name__ == ' __main__ ' :
parser = argparse . ArgumentParser ( formatter_class = argparse . RawDescriptionHelpFormatter ,
description = ' Upload messages or graphics to a 11x44 led badge via USB HID. \n Version %s from https://github.com/jnweiger/led-badge-ls32 \n -- see there for more examples and for updates. ' % __version ,
description = ' Upload messages or graphics to a 11x44 led badge via USB HID. \n Version %s from https://github.com/jnweiger/led-badge-ls32 \n -- see there for more examples and for updates. ' % __version ,
epilog = ' Example combining image and text: \n sudo %s " I:HEART2:you " ' % sys . argv [ 0 ] )
epilog = ' Example combining image and text: \n sudo %s " I:HEART2:you " ' % sys . argv [ 0 ] )
parser . add_argument ( ' -t ' , ' --type ' , default = ' 11x44 ' ,
parser . add_argument ( ' -t ' , ' --type ' , default = ' 11x44 ' ,
help = " Type of display: supported values are 12x48 or (default) 11x44. Rename the program to led-badge-12x48, to switch the default. " )
help = " Type of display: supported values are 12x48 or (default) 11x44. Rename the program to led-badge-12x48, to switch the default. " )
parser . add_argument ( ' -s ' , ' --speed ' , default = ' 4 ' , help = " Scroll speed (Range 1..8). Up to 8 comma-separated values " )
parser . add_argument ( ' -s ' , ' --speed ' , default = ' 4 ' , help = " Scroll speed (Range 1..8). Up to 8 comma-separated values " )
parser . add_argument ( ' -B ' , ' --brightness ' , default = ' 100 ' ,
parser . add_argument ( ' -B ' , ' --brightness ' , default = ' 100 ' ,
help = " Brightness for the display in percent: 25, 50, 75, or 100 " )
help = " Brightness for the display in percent: 25, 50, 75, or 100 " )
parser . add_argument ( ' -m ' , ' --mode ' , default = ' 0 ' ,
parser . add_argument ( ' -m ' , ' --mode ' , default = ' 0 ' ,
help = " Up to 8 mode values: Scroll-left(0) -right(1) -up(2) -down(3); still-centered(4); animation(5); drop-down(6); curtain(7); laser(8); See ' --mode-help ' for more details. " )
help = " Up to 8 mode values: Scroll-left(0) -right(1) -up(2) -down(3); still-centered(4); animation(5); drop-down(6); curtain(7); laser(8); See ' --mode-help ' for more details. " )
parser . add_argument ( ' -b ' , ' --blink ' , default = ' 0 ' , help = " 1: blinking, 0: normal. Up to 8 comma-separated values " )
parser . add_argument ( ' -b ' , ' --blink ' , default = ' 0 ' , help = " 1: blinking, 0: normal. Up to 8 comma-separated values " )
parser . add_argument ( ' -a ' , ' --ants ' , default = ' 0 ' , help = " 1: animated border, 0: normal. Up to 8 comma-separated values " )
parser . add_argument ( ' -a ' , ' --ants ' , default = ' 0 ' , help = " 1: animated border, 0: normal. Up to 8 comma-separated values " )
parser . add_argument ( ' -p ' , ' --preload ' , metavar = ' FILE ' , action = ' append ' ,
parser . add_argument ( ' -p ' , ' --preload ' , metavar = ' FILE ' , action = ' append ' ,
help = argparse . SUPPRESS ) # "Load bitmap images. Use ^A, ^B, ^C, ... in text messages to make them visible. Deprecated, embed within ':' instead")
help = argparse . SUPPRESS ) # "Load bitmap images. Use ^A, ^B, ^C, ... in text messages to make them visible. Deprecated, embed within ':' instead")
parser . add_argument ( ' -l ' , ' --list-names ' , action = ' version ' , help = " list named icons to be embedded in messages and exit " ,
parser . add_argument ( ' -l ' , ' --list-names ' , action = ' version ' , help = " list named icons to be embedded in messages and exit " ,
version = ' : ' + ' : : ' . join ( bitmap_named . keys ( ) ) + ' : :: or e.g. :path/to/some_icon.png: ' )
version = ' : ' + ' : : ' . join ( bitmap_named . keys ( ) ) + ' : :: or e.g. :path/to/some_icon.png: ' )
parser . add_argument ( ' message ' , metavar = ' MESSAGE ' , nargs = ' + ' ,
parser . add_argument ( ' message ' , metavar = ' MESSAGE ' , nargs = ' + ' ,
help = " Up to 8 message texts with embedded builtin icons or loaded images within colons(:) -- See -l for a list of builtins " )
help = " Up to 8 message texts with embedded builtin icons or loaded images within colons(:) -- See -l for a list of builtins " )
parser . add_argument ( ' --mode-help ' , action = ' version ' , help = argparse . SUPPRESS , version = """
parser . add_argument ( ' --mode-help ' , action = ' version ' , help = argparse . SUPPRESS , version = """
- m 5 " Animation "
- m 5 " Animation "
Animation frames are 6 character ( or 48 px ) wide . Upload an animation of
Animation frames are 6 character ( or 48 px ) wide . Upload an animation of
N frames as one image N * 48 pixels wide , 11 pixels high .
N frames as one image N * 48 pixels wide , 11 pixels high .
@ -484,23 +484,23 @@ parser.add_argument('--mode-help', action='version', help=argparse.SUPPRESS, ver
Example of a slowly beating heart :
Example of a slowly beating heart :
sudo % s - s1 - m5 " :heart2: :HEART2: "
sudo % s - s1 - m5 " :heart2: :HEART2: "
- m 9 " Smooth "
- m 9 " Smooth "
- m 10 " Rotate "
- m 10 " Rotate "
These modes are mentioned in the BMP Badge software .
These modes are mentioned in the BMP Badge software .
Text is shown static , or sometimes ( longer texts ? ) not shown at all .
Text is shown static , or sometimes ( longer texts ? ) not shown at all .
One significant difference is : The text of the first message stays visible after
One significant difference is : The text of the first message stays visible after
upload , even if the USB cable remains connected .
upload , even if the USB cable remains connected .
( No " rotation " or " smoothing " ( ? ) effect can be expected , though )
( No " rotation " or " smoothing " ( ? ) effect can be expected , though )
""" % s ys.argv[0])
""" % s ys.argv[0])
args = parser . parse_args ( )
args = parser . parse_args ( )
if have_pyhidapi :
if have_pyhidapi :
devinfo = pyhidapi . hid_enumerate ( 0x0416 , 0x5020 )
devinfo = pyhidapi . hid_enumerate ( 0x0416 , 0x5020 )
# dev = pyhidapi.hid_open(0x0416, 0x5020)
# dev = pyhidapi.hid_open(0x0416, 0x5020)
else :
else :
dev = usb . core . find ( idVendor = 0x0416 , idProduct = 0x5020 )
dev = usb . core . find ( idVendor = 0x0416 , idProduct = 0x5020 )
if have_pyhidapi :
if have_pyhidapi :
if devinfo :
if devinfo :
dev = pyhidapi . hid_open_path ( devinfo [ 0 ] . path )
dev = pyhidapi . hid_open_path ( devinfo [ 0 ] . path )
print ( " using [ %s %s ] int= %d page= %s via pyHIDAPI " % (
print ( " using [ %s %s ] int= %d page= %s via pyHIDAPI " % (
@ -509,7 +509,7 @@ if have_pyhidapi:
print ( " No led tag with vendorID 0x0416 and productID 0x5020 found. " )
print ( " No led tag with vendorID 0x0416 and productID 0x5020 found. " )
print ( " Connect the led tag and run this tool as root. " )
print ( " Connect the led tag and run this tool as root. " )
sys . exit ( 1 )
sys . exit ( 1 )
else :
else :
if dev is None :
if dev is None :
print ( " No led tag with vendorID 0x0416 and productID 0x5020 found. " )
print ( " No led tag with vendorID 0x0416 and productID 0x5020 found. " )
print ( " Connect the led tag and run this tool as root. " )
print ( " Connect the led tag and run this tool as root. " )
@ -523,51 +523,51 @@ else:
dev . set_configuration ( )
dev . set_configuration ( )
print ( " using [ %s %s ] bus= %d dev= %d " % ( dev . manufacturer , dev . product , dev . bus , dev . address ) )
print ( " using [ %s %s ] bus= %d dev= %d " % ( dev . manufacturer , dev . product , dev . bus , dev . address ) )
if args . preload :
if args . preload :
for file in args . preload :
for file in args . preload :
bitmap_preloaded . append ( bitmap_img ( file ) )
bitmap_preloaded . append ( bitmap_img ( file ) )
bitmaps_preloaded_unused = True
bitmaps_preloaded_unused = True
msgs = [ ]
msg_bitmap s = [ ]
for arg in args . message :
for msg_ arg in args . message :
msgs . append ( bitmap ( arg ) )
msg_bitmap s . append ( bitmap ( msg_ arg) )
if bitmaps_preloaded_unused == True :
if bitmaps_preloaded_unused == True :
print (
print (
" \n WARNING: \n Your preloaded images are not used. \n Try without ' -p ' or embed the control character ' ^A ' in your message. \n " )
" \n WARNING: \n Your preloaded images are not used. \n Try without ' -p ' or embed the control character ' ^A ' in your message. \n " )
if ' 12 ' in args . type or ' 12 ' in sys . argv [ 0 ] :
if ' 12 ' in args . type or ' 12 ' in sys . argv [ 0 ] :
print ( " Type: 12x48 " )
print ( " Type: 12x48 " )
for msg in msgs :
for msg_bitmap in msg_bitmap s :
# trivial hack to support 12x48 badges:
# trivial hack to support 12x48 badges:
# patch extra empty lines into the message stream.
# patch extra empty lines into the message stream.
for o in reversed ( range ( 1 , int ( len ( msg [ 0 ] ) / 11 ) + 1 ) ) :
for o in reversed ( range ( 1 , int ( len ( msg_bitmap [ 0 ] ) / 11 ) + 1 ) ) :
msg [ 0 ] [ o * 11 : o * 11 ] = array ( ' B ' , [ 0 ] )
msg_bitmap [ 0 ] [ o * 11 : o * 11 ] = array ( ' B ' , [ 0 ] )
else :
else :
print ( " Type: 11x44 " )
print ( " Type: 11x44 " )
buf = array ( ' B ' )
buf = array ( ' B ' )
buf . extend ( header ( list ( map ( lambda x : x [ 1 ] , msgs ) ) , args . speed , args . mode , args . blink , args . ants , int ( args . brightness ) ) )
buf . extend ( header ( list ( map ( lambda x : x [ 1 ] , msg_bitmap s ) ) , args . speed , args . mode , args . blink , args . ants , int ( args . brightness ) ) )
for msg in msgs :
for msg_bitmap in msg_bitmap s :
buf . extend ( msg [ 0 ] )
buf . extend ( msg_bitmap [ 0 ] )
needpadding = len ( buf ) % 64
need_ padding = len ( buf ) % 64
if needpadding :
if need_ padding :
buf . extend ( ( 0 , ) * ( 64 - needpadding ) )
buf . extend ( ( 0 , ) * ( 64 - need_ padding ) )
# print(buf) # array('B', [119, 97, 110, 103, 0, 0, 0, 0, 48, 48, 48, 48, 48, 48, 48, 48, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 60, 126, 255, 255, 255, 255, 126, 60, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0])
# print(buf) # array('B', [119, 97, 110, 103, 0, 0, 0, 0, 48, 48, 48, 48, 48, 48, 48, 48, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 60, 126, 255, 255, 255, 255, 126, 60, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0])
if len ( buf ) > 8192 :
if len ( buf ) > 8192 :
print ( " Writing more than 8192 bytes damages the display! " )
print ( " Writing more than 8192 bytes damages the display! " )
sys . exit ( 1 )
sys . exit ( 1 )
if have_pyhidapi :
if have_pyhidapi :
pyhidapi . hid_write ( dev , buf )
pyhidapi . hid_write ( dev , buf )
else :
else :
for i in range ( int ( len ( buf ) / 64 ) ) :
for i in range ( int ( len ( buf ) / 64 ) ) :
time . sleep ( 0.1 )
time . sleep ( 0.1 )
dev . write ( 1 , buf [ i * 64 : i * 64 + 64 ] )
dev . write ( 1 , buf [ i * 64 : i * 64 + 64 ] )
if have_pyhidapi :
if have_pyhidapi :
pyhidapi . hid_close ( dev )
pyhidapi . hid_close ( dev )