Sometime back I had a requirement to communicate with an external device which is connected to a USB port of my computer. The external device was a MSB430 sensor mote running contiki on it. My application running on the mote communicate with the computer using SLIP protocol. Therefore I needed to make my program on the PC to communicate using SLIP protocol over the USB port with the sensor mote.
Serial Line Internet Protocol (SLIP) is a very simple protocol which can be used to communicate between different devices over serial lines. It just encodes the users data byte streams before writing to the serial line and decode after reading from the serial line. I found a C language implementation of the SLIP protocol but I wanted a Python implementation. So first thing I did was searching through the Internet for a python based implementation of SLIP. But I couldn't find anything. Finally what I had to do is implement it on my own. Since there can be more people who need such a Python based implementation of SLIP protocol, I thought to put my code in the Internet.
My code consists of two source files. SLIP protocol encoding and decoding functions are defined in the ProtoSLIP.py file. Another file named as SerialComm.py wraps around those functions and provide some high-level functions which can be used by a user program to open a serial port, write data to it and read data from it using SLIP protocol. So, here we go.
Content of the ProtoSLIP.py file
Content of the SerialComm.py file
SerialComm.py file should be imported from a user program and call the functions appropriately. I hope comments I have put in the code will make understanding of functionality of the program clear enough. Some information like the exact serial port we are opening, baud rate, parity, etc has to be edited in the code according to the requirement.
I hope my code will help someone. Cheers!
Serial Line Internet Protocol (SLIP) is a very simple protocol which can be used to communicate between different devices over serial lines. It just encodes the users data byte streams before writing to the serial line and decode after reading from the serial line. I found a C language implementation of the SLIP protocol but I wanted a Python implementation. So first thing I did was searching through the Internet for a python based implementation of SLIP. But I couldn't find anything. Finally what I had to do is implement it on my own. Since there can be more people who need such a Python based implementation of SLIP protocol, I thought to put my code in the Internet.
My code consists of two source files. SLIP protocol encoding and decoding functions are defined in the ProtoSLIP.py file. Another file named as SerialComm.py wraps around those functions and provide some high-level functions which can be used by a user program to open a serial port, write data to it and read data from it using SLIP protocol. So, here we go.
Content of the ProtoSLIP.py file
1: import termios
2: import serial
3: from collections import deque
4: SLIP_END = 0300 # declared in octal
5: SLIP_ESC = 0333
6: SLIP_ESC_END = 0334
7: SLIP_ESC_ESC = 0335
8: DEBUG_MAKER = 0015
9: MAX_MTU = 200
10: readBufferQueue = deque([])
11: #-------------------------------------------------------------------------------
12: # This function takes a byte list, encode it in SLIP protocol and return the encoded byte list
13: def encodeToSLIP(byteList):
14: tempSLIPBuffer = []
15: tempSLIPBuffer.append(SLIP_END)
16: for i in byteList:
17: if i == SLIP_END:
18: tempSLIPBuffer.append(SLIP_ESC)
19: tempSLIPBuffer.append(SLIP_ESC_END)
20: elif i == SLIP_ESC:
21: tempSLIPBuffer.append(SLIP_ESC)
22: tempSLIPBuffer.append(SLIP_ESC_ESC)
23: else:
24: tempSLIPBuffer.append(i)
25: tempSLIPBuffer.append(SLIP_END)
26: return tempSLIPBuffer
27: #-------------------------------------------------------------------------------
28: #-------------------------------------------------------------------------------
29: # This function uses getSerialByte() function to get SLIP encoded bytes from the serial port and return a decoded byte list
30: def decodeFromSLIP(serialFD):
31: dataBuffer = []
32: while 1:
33: serialByte = getSerialByte(serialFD)
34: if serialByte is None:
35: return -1
36: elif serialByte == SLIP_END:
37: if len(dataBuffer) > 0:
38: return dataBuffer
39: elif serialByte == SLIP_ESC:
40: serialByte = getSerialByte(serialFD)
41: if serialByte is None:
42: return -1
43: elif serialByte == SLIP_ESC_END:
44: dataBuffer.append(SLIP_END)
45: elif serialByte == SLIP_ESC_ESC:
46: dataBuffer.append(SLIP_ESC)
47: elif serialByte == DEBUG_MAKER:
48: dataBuffer.append(DEBUG_MAKER)
49: else:
50: print("Protocol Error")
51: else:
52: dataBuffer.append(serialByte)
53: return
54: #-------------------------------------------------------------------------------
55: #-------------------------------------------------------------------------------
56: # This function read byte chuncks from the serial port and return one byte at a time
57: def getSerialByte(serialFD):
58: if len(readBufferQueue) == 0:
59: #fetch a new data chunk from the serial port
60: i = 0
61: while len(readBufferQueue) < MAX_MTU:
62: newByte = ord(serialFD.read())
63: readBufferQueue.append(newByte)
64: newByte = readBufferQueue.popleft()
65: return newByte
66: else:
67: newByte = readBufferQueue.popleft()
68: return newByte
69: #-------------------------------------------------------------------------------
Content of the SerialComm.py file
1: import ProtoSLIP
2: import termios
3: import serial
4: #-------------------------------------------------------------------------------
5: # This function connect and configure the serial port. Then returns the file discripter
6: def connectToSerialPort():
7: serialFD = serial.Serial(port='/dev/ttyUSB0', baudrate=115200, bytesize=8, parity='N', stopbits=1, xonxoff=False, rtscts=False)
8: # port='/dev/ttyUSB0'- port to open
9: # baudrate=115200 - baud rate to communicate with the port
10: # bytesize=8 - size of a byte
11: # parity='N' - no parity
12: # stopbits=1 - 1 stop bit
13: # xonxoff=False - no software handshakes
14: # rtscts=False - no hardware handshakes
15: if serialFD < 0:
16: print("Couldn't open serial port")
17: return -1
18: else:
19: print("Opened serial port")
20: return serialFD
21: #-------------------------------------------------------------------------------
22: #-------------------------------------------------------------------------------
23: # This function accept a byte array and write it to the serial port
24: def writeToSerialPort(serialFD, byteArray):
25: encodedSLIPBytes = ProtoSLIP.encodeToSLIP(byteArray)
26: byteString = ''.join(chr(b) for b in encodedSLIPBytes) #convert byte list to a string
27: serialFD.write(byteString)
28: return
29: #-------------------------------------------------------------------------------
30: #-------------------------------------------------------------------------------
31: # This function reads from the serial port and return a byte array
32: def readFromSerialPort(serialFD):
33: i = 1
34: byteArray = None
35: byteArray = ProtoSLIP.decodeFromSLIP(serialFD)
36: if byteArray is None:
37: print "readFromSerialPort(serialFD): Error"
38: return -1
39: else:
40: return byteArray
41: #-------------------------------------------------------------------------------
42: #-------------------------------------------------------------------------------
43: # This function reads from the serial port and return a byte array
44: def disconnectFromSerialPort(serialFD):
45: serialFD.close()
46: return
47: #-------------------------------------------------------------------------------
SerialComm.py file should be imported from a user program and call the functions appropriately. I hope comments I have put in the code will make understanding of functionality of the program clear enough. Some information like the exact serial port we are opening, baud rate, parity, etc has to be edited in the code according to the requirement.
I hope my code will help someone. Cheers!
Nice! would you mind hosting it on bitbucket or github? A lot more people would find it that way
ReplyDeleteGood idea! :) I have never hosted any code in github. I will put this as you suggested :)
ReplyDeleteHi Ansanka,
ReplyDeleteI put your useful code on github under public domain license and reference to this page: https://github.com/mehdix/pyslip/
Thank you so much Mehdi :) It will be so useful to everybody now!
DeleteHi, Someone know a c/c++ library for read/write data over serial port, i know already how to send, receive data, BUT sometime i have somes errors.
ReplyDeleteThere is a library to handle error ?
Thanks
1. there is a python library which is called "sliplib". it has the function encode and decode. does this do the same encoding and decoding like you did here?.
ReplyDelete2. reading your article i concluded that slip basically do not make any connection. on the other side it just add some values with actual data. do you confirm it ?