11from tinylink import utils
22
33import struct
4+ import six
45
56__version__ = "1.1"
67
7- __all__ = ["Frame" , "DamagedFrame" , "ResetFrame" , " TinyLink" ]
8+ __all__ = ["Frame" , "TinyLink" ]
89
910# This can be anything, and is used to synchronize a frame
1011PREAMBLE = 0xAA55AA55
1314LITTLE_ENDIAN = "<"
1415BIG_ENDIAN = ">"
1516
16- # Protocol states
17+ # Protocol states.
1718WAITING_FOR_PREAMBLE = 1
1819WAITING_FOR_HEADER = 2
1920WAITING_FOR_BODY = 3
2021
21- # Message flags
22+ # Message flags (reserved).
2223FLAG_NONE = 0x00
2324FLAG_RESET = 0x01
25+ FLAG_ERROR = 0x02
26+ FLAG_PRIORITY = 0x04
2427
2528# Don't change these values!
2629LEN_PREAMBLE = 4
3235LEN_BODY = LEN_CRC
3336
3437
35- class BaseFrame (object ):
38+ class Frame (object ):
3639 """
37- Base frame.
40+ Represents a frame.
3841 """
3942
40- def __init__ (self , data = None , flags = FLAG_NONE ):
43+ def __init__ (self , data = None , flags = FLAG_NONE , damaged = False ):
44+ if data is not None :
45+ if not type (data ) == six .binary_type :
46+ raise ValueError ("Provided data must be encoded as bytes." )
47+ else :
48+ data = bytes ()
49+
4150 self .data = data
4251 self .flags = flags
52+ self .damaged = damaged
4353
4454 def __repr__ (self ):
45- return "%s(%s, flags=%d)" % (
46- self .__class__ .__name__ , repr (self .data ), self .flags )
47-
48-
49- class Frame (BaseFrame ):
50- """
51- Represent normal frame.
52- """
53- pass
54-
55-
56- class DamagedFrame (BaseFrame ):
57- """
58- Represent damaged frame.
59- """
60- pass
61-
62-
63- class ResetFrame (BaseFrame ):
64- """
65- Represent reset frame.
66- """
67-
68- def __init__ (self ):
69- super (ResetFrame , self ).__init__ (None , FLAG_RESET )
70-
71- def __repr__ (self ):
72- return "ResetFrame()"
55+ return "%s(%s, flags=%d, damaged=%s)" % (
56+ self .__class__ .__name__ , repr (self .data ), self .flags , self .damaged )
7357
7458
7559class TinyLink (object ):
@@ -78,7 +62,7 @@ class TinyLink(object):
7862 applications that only use RX/TX. Every message is encapsulated in a frame.
7963 A frame has a header checksum and a frame checksum, to detect errors as
8064 fast as possible (this can happen when you jump right into a stream of
81- packets).
65+ packets, without being synchronized ).
8266
8367 A typical frame has 13 bytes overhead, and can have a data payload up to
8468 65536 bytes.
@@ -108,16 +92,22 @@ def __init__(self, handle, endianness=LITTLE_ENDIAN,
10892 self .handle = handle
10993 self .endianness = endianness
11094 self .max_length = max_length
95+ self .ignore_damaged = ignore_damaged
11196
11297 # Set initial state
11398 self .state = WAITING_FOR_PREAMBLE
11499
115100 # Pre-allocate buffer that fits header + body. The premable will be
116101 # cleared when it is detected, so it doesn't need space.
117102 self .stream = bytearray (max_length + LEN_HEADER + LEN_BODY )
118- self .buffer = buffer (self .stream )
119103 self .index = 0
120104
105+ # Python 2 does not allow unpack from bytearray, but Python 3.
106+ if six .PY3 :
107+ self .buffer = self .stream
108+ else :
109+ self .buffer = buffer (self .stream )
110+
121111 def write_frame (self , frame ):
122112 """
123113 Write a frame via the handle.
@@ -148,13 +138,6 @@ def write_frame(self, frame):
148138 # Write to file
149139 return self .handle .write (result )
150140
151- def reset (self ):
152- """
153- Shorthand for `write_frame(ResetFrame())'.
154- """
155-
156- return self .write_frame (ResetFrame ())
157-
158141 def write (self , data , flags = FLAG_NONE ):
159142 """
160143 Shorthand for `write_frame(Frame(data, flags=flags))'.
@@ -164,9 +147,8 @@ def write(self, data, flags=FLAG_NONE):
164147
165148 def read (self , limit = 1 ):
166149 """
167- Read up to `limit' bytes from the handle and process this byte. Returns
168- a list of received frames, if any. A reset frame is indicated by a
169- `ResetFrame' instance.
150+ Read up to `limit' bytes from the handle and process it. Returns a list
151+ of received frames, if any.
170152 """
171153
172154 # List of frames received
@@ -180,7 +162,7 @@ def read(self, limit=1):
180162 return []
181163
182164 # Append to stream
183- self .stream [self .index ] = char
165+ self .stream [self .index ] = ord ( char )
184166 self .index += 1
185167
186168 # Decide what to do
@@ -212,8 +194,8 @@ def read(self, limit=1):
212194 if length > 0 :
213195 self .state = WAITING_FOR_BODY
214196 else :
215- # Empty frame to indicate a reset frame
216- frames .append (ResetFrame ( ))
197+ # Frame without body.
198+ frames .append (Frame ( flags = flags ))
217199
218200 self .index = 0
219201 self .state = WAITING_FOR_PREAMBLE
@@ -237,7 +219,7 @@ def read(self, limit=1):
237219 if checksum_b == utils .checksum_frame (result , checksum_a ):
238220 frames .append (Frame (result , flags = flags ))
239221 elif not self .ignore_damaged :
240- frames .append (DamagedFrame (result , flags = flags ))
222+ frames .append (Frame (result , flags = flags , damaged = True ))
241223
242224 # Reset to start state
243225 self .index = 0
0 commit comments