View unanswered posts | View active topics It is currently Sun May 19, 2013 7:50 pm



Reply to topic  [ 2 posts ] 
 pyserial question (issue?) 
Author Message
User avatar

Joined: Nov 18, 2008
Posts: 1720
Location: Berkeley, CA
Post pyserial question (issue?)
At Matt's suggestion I have been looking into pyserial as a more flexible means of creating a serial connection, while also allowing for IP socket connections. I have it running. But, as noted in another thread, I have found what looks like a bug in pyserial. Specifically, a timeout value of 0, which should be a blocking read - I.e. when used with readline() it only return data when a line has been read. Instead, use of the zero value simply blocks forever and never returns anything.

So, my solution was to simply use a value >0. However, since readline() returns on timeout as well as on a newline, it can return a lot of null data. Here is the code I am playing with:
Code: Select all
import serial

s = serial.serial_for_url('socket://192.168.4.2:5003', timeout=1)
foo = ""

while 1:
   while len(foo) == 0:
      foo = s.readline()      
   print foo
   foo = ""
s.close()
OTOH, I could also use an arbitrarily large value for timeout and essentially achieve the blocking read I want.

So, my questions.
Do you know if this is a bug in serial_for_url and if so, does it affect serial as well as socket connections?
In your opinion (which I value highly) which approach seems better... long timeout or short timeout and check for null data? Certainly the long timeout is simpler, but maybe there are other considerations.

TIA

EDIT: I forgot... there is one clear downside to a long timeout value. It causes the plugin to block and not die when asked to by Indiigo, like on a reload plugin.


Tue Nov 15, 2011 11:19 am
Profile
Site Admin
User avatar

Joined: Jan 27, 2003
Posts: 11683
Location: Texas
Post Re: pyserial question (issue?)
Note that the possible timeout parms are: None, 0, X. None is blocking, 0 is non-blocking. If you use 0 and call readline() with no data waiting, I think it should immediately return an empty string.

But note that the pySerial docs say to always use a timeout value when calling readline(). I wouldn't use 0 (besides for the fact it doesn't seem to work) since that would cause your loop to spin fast and waste CPU cycles if there is no data pending.

Instead I would probably use a timeout of 1 second, then loop like this:

Code: Select all
foo = ""
while True:
   while len(foo) == 0:
      foo = s.readline()
      if self.stopThread:
         raise self.StopThread
   print foo
   foo = ""

The only real change is the check for when a plugin has received a shutdown request from the server. 1 second is long enough that in the case of no incoming data your loop will be asleep a vast majority of the time (so low CPU usage), but short enough that the Indigo Server will be able to politely shutdown the plugin.

An alternative is to use the select.select() function to wait for incoming serial data. You would need to pass it both the serial connection descriptor and self._stopThreadPipeIn, the latter of which is automatically flagged when Indigo Server is shutting down a plugin. It would then block indefinitely until either data arrived or the plugin received a shutdown request. But just because some data had arrived doesn't mean an entire line will have arrived, so it will get more complex. IMO, the additional complexity isn't worth it in this case.

_________________
Image


Tue Nov 15, 2011 6:21 pm
Profile WWW
Display posts from previous:  Sort by  
Reply to topic   [ 2 posts ] 

Who is online

Users browsing this forum: No registered users and 1 guest


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group.   Template designed by STSoftware.