Skip to content

Serial Reinitialise#27

Closed
jamesleesaunders wants to merge 8 commits intoniolabs:masterfrom
jamesleesaunders:serial-re-init
Closed

Serial Reinitialise#27
jamesleesaunders wants to merge 8 commits intoniolabs:masterfrom
jamesleesaunders:serial-re-init

Conversation

@jamesleesaunders
Copy link
Copy Markdown
Collaborator

@jamesleesaunders jamesleesaunders commented Sep 20, 2016

This PR modifies base.py, it adds code which will attempt to re-initialise a serial port following a failure, physical unplugging of the USB port or premature closing of the serial port. This means that an XBee thread will continue to run even if the USB port is pulled out and will continually retry (every 10 seconds) to re-initiate the serial port if/when it becomes available again.

A second feature is being added which allows for the 'ser' parameter to be passed either a serial object or a dict of serial settings. For example, it means as well as initiating an XBee/ZigBee object as per current method:

import serial
serialObject = serial.Serial('/dev/ttyUSB0', 9600)
zb = ZigBee(ser=serialObject, callback=receiveMessage, error_callback=xbeeError)

or you can also initiate an XBee/ZigBee object by passing serial settings dict as follows:

serialDict = {'port': XBEE_PORT, 'parity': 'N', 'baudrate': 9600, 'bytesize': 8, 
    'xonxoff': False, 'rtscts': False, 'timeout': None, 'inter_byte_timeout': None, 
    'stopbits': 1, 'dsrdtr': False, 'write_timeout': None}
zb = ZigBee(ser=serialDict, callback=receiveMessage, error_callback=xbeeError)

Both of the above result in the same end, the only difference is that with the second (dict) method base.py initialises the serial object (you will also see serial has been added to the use imports on base.py) where as the first method the serial object must be initialised by the calling code before hand.

Credit must be given to @thom-nic who had the original idea for this and wrote the first part of these changes a few years ago. I have simply progressed his code and brought it up-to-date with the current base.

In order to ensure the modified base.py still passes unit tests I have also modified some of the tests, most notably the 'Fake.py' device. These have been proposed on PR #25 (but you will also see them merged into this PR so as to allow Travis tests to run cleanly). Each should be reviewed under their respective PR's and if PR #25 is approved I will re-base this PR such that only base.py is in the diff.

As well as the unit tests I have also tested this on MacBook and Raspberry Pi testing various combinations of serial port failure (I could not think of a way to write any unit test code which would simulate a serial port failure). There were occasional situations where following unplugging and plugging back in the serial port would not recover (the serial os.path e.g '/dev/ttyUSB0' would not come back until system restart), but I don't know if this is an OS issue more than Python code? I do not know enough about unix/linux UART drivers to diagnose any further. I would love to hear from anyone who may be able to enlighten/improve on this.

I would also be interested to hear if @Etherfi has any comments on this PR as I know they was also recently looking at modifying base.py (PR #23) to add timeouts to wait_read_frame() and I think had other enhancements in mind.

thom-nic and others added 2 commits September 15, 2016 22:30
* Adding logging.
* If serial port is prematurely closed or unplugged attempt to re-initialise port.
* Make XBeeBase inherit from object.
* Added timeout for wait_read_frame.
* Don't timeout early when reading a packet.
* Log a message when partial packets are dropped.
@jamesleesaunders
Copy link
Copy Markdown
Collaborator Author

Hi @hansmosh please will you consider this PR fir inclusion upstream? This is also dependent on PR #25.

PR #25 could be merged on its own as it improves the 'fake serial' test code.

* Replaced the previous FakeDevice and FakeReadDevice with the new fake Serial class.
* Use of get_data_written().
* Modify BadReadDevice accordingly.
* Adding default second argument 'length' to BadReadDevice().
* Removed test_read_too_many() test as no longer required.
* Adds option to pass a dictionary of serial settings instead of serial object to init().
* Imports serial class.
* If port closed first simply attempt to re-open it.
* Otherwise on error then attempt re-init from settings.
* Small code tidy-ups.
* Adds timeout to wait_read_frame().
@jamesleesaunders
Copy link
Copy Markdown
Collaborator Author

Does not seem to have sparked any interest. Will revisit again in the future.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants