summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChris Liechti <cliechti@gmx.net>2015-08-25 00:55:51 +0200
committerChris Liechti <cliechti@gmx.net>2015-08-25 00:55:51 +0200
commitc0c660a3297a5babb03a01b6fca89f6348b1bd36 (patch)
tree097f464e381b1add32d884637e960c0acb5f369d
parent9a72085e2ef8c50404f6d1643efcb9b0fba680ec (diff)
downloadpyserial-git-c0c660a3297a5babb03a01b6fca89f6348b1bd36.tar.gz
miniterm: add "hexlify" codec
the hexlify codec can send and receive hex encoded data and converts bytes to strings (unlike the built-in hex code) try it with --encoding hexlify
-rw-r--r--serial/tools/hexlify_codec.py82
-rw-r--r--serial/tools/miniterm.py6
2 files changed, 88 insertions, 0 deletions
diff --git a/serial/tools/hexlify_codec.py b/serial/tools/hexlify_codec.py
new file mode 100644
index 0000000..f3ba04f
--- /dev/null
+++ b/serial/tools/hexlify_codec.py
@@ -0,0 +1,82 @@
+"""\
+Python 'hex' Codec - 2-digit hex with spaces content transfer encoding.
+"""
+
+import codecs
+import serial
+
+HEXDIGITS = '0123456789ABCDEF'
+
+### Codec APIs
+
+def hex_encode(input, errors='strict'):
+ return (serial.to_bytes([int(h, 16) for h in input.split()]), len(input))
+
+def hex_decode(input, errors='strict'):
+ return (''.join('{:02X} '.format(b) for b in input), len(input))
+
+class Codec(codecs.Codec):
+ def encode(self, input, errors='strict'):
+ return serial.to_bytes([int(h, 16) for h in input.split()])
+ def decode(self, input, errors='strict'):
+ return ''.join('{:02X} '.format(b) for b in input)
+
+class IncrementalEncoder(codecs.IncrementalEncoder):
+
+ def __init__(self, errors='strict'):
+ self.errors = errors
+ self.state = 0
+
+ def reset(self):
+ self.state = 0
+
+ def getstate(self):
+ return self.state
+
+ def setstate(self, state):
+ self.state = state
+
+ def encode(self, input, final=False):
+ state = self.state
+ encoded = []
+ for c in input.upper():
+ if c in HEXDIGITS:
+ z = HEXDIGITS.index(c)
+ if state:
+ encoded.append(z + (state & 0xf0))
+ state = 0
+ else:
+ state = 0x100 + (z << 4)
+ elif c == ' ': # allow spaces to separate values
+ if state and self.errors == 'strict':
+ raise UnicodeError('odd number of hex digits')
+ state = 0
+ else:
+ if self.errors == 'strict':
+ raise UnicodeError('non-hex digit found: %r' % c)
+ self.state = state
+ return serial.to_bytes(encoded)
+
+class IncrementalDecoder(codecs.IncrementalDecoder):
+ def decode(self, input, final=False):
+ return ''.join('{:02X} '.format(b) for b in input)
+
+class StreamWriter(Codec, codecs.StreamWriter):
+ pass
+
+class StreamReader(Codec, codecs.StreamReader):
+ pass
+
+### encodings module API
+
+def getregentry():
+ return codecs.CodecInfo(
+ name='hexlify',
+ encode=hex_encode,
+ decode=hex_decode,
+ incrementalencoder=IncrementalEncoder,
+ incrementaldecoder=IncrementalDecoder,
+ streamwriter=StreamWriter,
+ streamreader=StreamReader,
+ _is_text_encoding=True,
+ )
diff --git a/serial/tools/miniterm.py b/serial/tools/miniterm.py
index cb60a2b..e56e4cc 100644
--- a/serial/tools/miniterm.py
+++ b/serial/tools/miniterm.py
@@ -20,6 +20,9 @@ except NameError:
raw_input = input # in python3 it's "raw"
unichr = chr
+from . import hexlify_codec
+codecs.register(lambda c: hexlify_codec.getregentry() if c == 'hexlify' else None)
+
def key_description(character):
"""generate a readable description for a key"""
@@ -198,6 +201,7 @@ class NoControls(NoTerminal):
class Printable(Transform):
"""Show decimal code for all non-ASCII characters and replace most control codes"""
+
def rx(self, text):
r = []
for t in text:
@@ -215,6 +219,7 @@ class Printable(Transform):
class Colorize(Transform):
"""Apply different colors for received and echo"""
+
def __init__(self):
# XXX make it configurable, use colorama?
self.input_color = '\x1b[37m'
@@ -229,6 +234,7 @@ class Colorize(Transform):
class DebugIO(Transform):
"""Print what is sent and received"""
+
def rx(self, text):
sys.stderr.write(' [RX:{}] '.format(repr(text)))
sys.stderr.flush()