I have a string array in Omron NJ memory that is bound to CJ memory type “D” and manipulated by a vijeo designer HMI to display a recipe name. This is edited by the HMI and stored in the PLC array for manipulation. I am trying to replicate the HMI function in Ignition to allow editing the string text .
The data is string characters are displaying byte swapped where " Recipe 123" is displaying as “eRicep1 32”
How do I swap each pair of characters to read/write correctly?
I would use a derived tag, with a character-swapping runScript() expression in both directions.
Thanks, I was hoping there was an automatic function for this. I’ll need to practice my script writing, Cheers
Just so you don’t scratch your head for too long on this:
s = "eRicep1 32"
s = ''.join(c for pair in zip(s[1::2], s[::2]) for c in pair)
s[1::2]
and s[::2]
will produce strings with even or odd characters ([1::2] = start from 1, stop at the end, step 2),
zip
will take one character from each,
then it’s simply a matter of putting things in the right order.
So, with "eRicep1 32"
, s[1::2]
will be "Rcp 2"
and s[::2]
"eie13"
zip("Rcp 2", "eie13")
produces the pairs [('R', 'e'), ('c', 'i'), ('p', 'e'), (' ', '1'), ('2', '3')]
and iterating through those pairs and picking single extracts them from the tuples to produce the list ['R', 'e', 'c', 'i', 'p', 'e', ' ', '1', '2', '3']
All that’s left to do is join them on nothing with ''.join()
There might be libraries with builtins for this, but, well…
Thanks Pascal,
Managed to script a solution which works fine. See below
Script
Swap
def ByteSwap(text): ## Swap each pair of characters to match byte order of string characters
result ="" #clear result
if (len(text)%2) ==1: # test if odd number of bytes
text=text+" " #Add extra character
for x in range (1,len(text),2): #loop through each second byte of entire string
result = result+(text) #add second character
result =result+(text[x-1]) #add first character
return result #output final concatenated byte swapped string
Derived Tag Read expression
runScript(“Swap.ByteSwap”,0,{source})
Derived Tag Write expression
runScript(“Swap.ByteSwap”,0,{value})
Thanks
Paul Reynolds
Electrotech Controls Ltd
Automation & Controls Manager
P 06 835 2260 F 06 835 2253 M 021 431 153 E paul@electrotech.co.nz W www.techgroup.co.nz
12 Sheffield Place, PO Box 3016, Napier 4142, New Zealand
A member of the Tech Group of Companies Ltd
Thanks Pascal,
Managed to script a solution which works fine. See below
Script
Swap
def ByteSwap(text): ## Swap each pair of characters to match byte order of string characters
result ="" #clear result
if (len(text)%2) ==1: # test if odd number of bytes
text=text+" " #Add extra character
for x in range (1,len(text),2): #loop through each second byte of entire string
result = result+(text[x]) #add second character
result =result+(text[x-1]) #add first character
return result #output final concatenated byte swapped string
Derived Tag Read expression
runScript("Swap.ByteSwap",0,{source})
Derived Tag Write expression
runScript("Swap.ByteSwap",0,{value})
Cheers
It’s a good thing you found a solution by yourself, but I’d suggest you use the snippet I posted above.
It’s a more pythonic way of doing things, using very pythonic things (zip, generators, comprehensions…)
def swap_bytes(s):
return ''.join(c for pair in zip(s[1::2], s[::2]) for c in pair)
If it’s a bit too obscure as it is, I’ll deconstruct and explain it in more details.
On the other hand, there is the struct
library that could allow you to do this, but frankly I’m not familiar with it and couldn’t help figure out how to use it.