Am 23.01.2012 22:48 schrieb M.Pekala:
Hello, I am having some trouble with a serial stream on a project I am
working on. I have an external board that is attached to a set of
sensors. The board polls the sensors, filters them, formats the
values, and sends the formatted values over a serial bus. The serial
stream comes out like $A1234$$B-10$$C987$,  where "$A.*$" is a sensor
value, "$B.*$" is a sensor value, "$C.*$" is a sensor value, ect...

When one sensor is running my python script grabs the data just fine,
removes the formatting, and throws it into a text control box. However
when 3 or more sensors are running, I get output like the following:

Sensor 1: 373
Sensor 2: 112$$M-160$G373
Sensor 3: 763$$A892$

I am fairly certain this means that my code is running too slow to
catch all the '$' markers.

This would just result in the receive buffer constantly growing.

Probably the thing with the RE which has been mentionned by Jon is the cause.

But I have some remarks to your code.

First, you have code repetition. You could use functions to avoid this.

Second, you have discrepancies between your 3 blocks: with A, you work with sensorabuffer, the others have sensor[bc]enable.

Third, if you have a buffer content of '$A1234$$B-10$$C987$', your "A code" will match the whole buffer and thus do

    # s = sensorresult.group(0) ->
    s = '$A1234$$B-10$$C987$'
    # s = s[2:-1]
    s = '1234$$B-10$$C987'
    # maybe put that into self.SensorAValue
    self.sensorabuffer = ''


I suggest the following way to go:

* Process your data only once.
* Do something like

[...]
theonebuffer = '$A1234$$B-10$$C987$' # for now

while True:
    sensorresult = re.search(r'\$(.)(.*?)\$(.*)', theonebuffer)
    if sensorresult:
        sensor, value, rest = sensorresult.groups()
        # replace the self.SensorAValue concept with a dict
        self.sensorvalues[sensor] = value
        theonebuffer = rest
    else: break # out of the while

If you execute this code, you'll end with a self.sensorvalues of

    {'A': '1234', 'C': '987', 'B': '-10'}

and a theonebuffer of ''.


Let's make another test with an incomplete sensor value.

theonebuffer = '$A1234$$B-10$$C987$$D65'

[code above]

-> the dict is the same, but theonebuffer='$D65'.

* Why did I do this? Well, you are constantly receiving data. I do this with the hope that the $ terminating the D value is yet to come.

* Why does this happen? The regex does not match this incomplete packet, the while loop terminates (resp. breaks) and the buffer will contain the last known value.


But you might be right - speed might become a concern if you are processing your data slower than they come along. Then your buffer fills up and eventually kills your program due to full memory. As the buffer fills up, the string copying becomes slower and slower, making things worse. Whether this becomes relevant, you'll have to test.

BTW, as you use this one regex quite often, a way to speed up could be to compile the regex. This will change your code to

sensorre = re.compile(r'\$(.)(.*?)\$(.*)')
theonebuffer = '$A1234$$B-10$$C987$' # for now

while True:
    sensorresult = sensorre.search(theonebuffer)
    if sensorresult:
        sensor, value, rest = sensorresult.groups()
        # replace the self.SensorAValue concept with a dict
        self.sensorvalues[sensor] = value
        theonebuffer = rest
    else: break # out of the while


And finally, you can make use of re.finditer() resp. sensorre.finditer(). So you can do

sensorre = re.compile(r'\$(.)(.*?)\$') # note the change
theonebuffer = '$A1234$$B-10$$C987$' # for now

sensorresult = None # init it for later
for sensorresult in sensorre.finditer(theonebuffer):
    sensor, value = sensorresult.groups()
    # replace the self.SensorAValue concept with a dict
    self.sensorvalues[sensor] = value
# and now, keep the rest
if sensorresult is not None:
    # the for loop has done something - cut out the old stuff
    # and keep a possible incomplete packet at the end
    theonebuffer = theonebuffer[sensorresult.end():]

This removes the mentionned string copying as source of increased slowness.

HTH,

Thomas
--
http://mail.python.org/mailman/listinfo/python-list

Reply via email to