String <=> Unicode Comparison?

I have an array of ASCII codes coming from a PLC into Ignition - this corresponds to a string in the PLC. I am doing the following:

VALUES = [list of ASCII codes]

S = ''.join(chr(v) for v in VALUES)

test_string = [string equivalent to S]

print S==test_string

This always returns False, even though S and test_string are type (str) and clearly the same. I think this has something to with chr() and Unicode vs. String, but I don't really know what I'm talking about here.

My goal is to compare the incoming "string" with a predefined reference string - could someone please point me in the right direction on this? I would prefer not decompose the reference string into ASCII characters and compare the arrays, but I will if it's the only way...

Any example of a non-working VALUES list?


VALUES  = [72, 101, 108, 108, 111, 32, 119, 111, 114, 108, 100]

S = ''.join(chr(v) for v in VALUES)

print VALUES
print S

test_string = u'Hello world'
S == test_string
[72, 101, 108, 108, 111, 32, 119, 111, 114, 108, 100]
Hello world
True

Maybe I'm doing something else wrong here? Thank you very much

last line should be S==test_string but this produces the same result

Your sample data has ASCII NUL characters. You aren't excluding them, so your comparision string will have to have them too.

Try using print repr(S) to see what you really have.

1 Like

I see, there is more going on there than I thought.

I need the strings to be be dynamically sized (hence the 20 character limit), so I guess I will do the comparisons on the ASCII code lists.

Thank you very much

Or stop building the string on the first null. Most PLC drivers will help you read strings using the brand's conventions, so you don't have to go through these contortions. What kind of PLC is this?

{ For example specific to your usage, see the @string and @utf8 modifiers in §8.3.4 of my EtherNet/IP Driver Manual. }

1 Like

EDIT: Sorry, would have answered sooner, but I was having lunch with my daughter. Not many more days before she's back off to college... :slight_smile:

As Phil mentioned, the PLC driver should ideally have a format for strings.

If, however, you're stuck with what you have (some MODBUS-y things come to mind), then finding the location of the first null should work:

S = ''.join(chr(v) for v in VALUES)[:VALUES.index(0)]

Example:

test_string = u'545276'

VALUES  = [53,52,53,50,55,54, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]

S = ''.join(chr(v) for v in VALUES)[:VALUES.index(0)]

print VALUES
print S
S == test_string
[53, 52, 53, 50, 55, 54, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
545276
True

itertools has something for this case (it usually does):

from itertools import takewhile
S = ''.join(chr(v) for v in takewhile(lambda x: x != 0, VALUES))

Might not be worth it in this case, but I like itertools a lot and try to showcase its possibilities when I can !

Sorry, revisiting after a delay...

These are AB Micro800 PLCs, so yes it is Modbus and I believe I'm stuck with what I have, unless we see that Micro800 EtherNet driver I've seen mentioned on here :slightly_smiling_face:

I was able to hide the ugliness in a function and it seems to be working pretty well. Thanks very much

1 Like

It was released in April, latest is here:

1 Like