Reading strings written by Citect PSDirect to Siemens S7-1500 in ignition

Hi,

I have an issue when trying to read strings written by Citect to a S7.
The Citect system is already in operation and i cannot change anything in the PLC or Citect. Citect/PSDirect uses a different approach to reading/write strings than Ignition

Citect uses the PSDirect driver.
TAG in PLC:
DB1000, offset 0, String[32]

TAG in Citect
DB1000, offset 2, String[30]

The string appears as empty in the PLC but if if monitor as an array of chars i can see the values.

I have tried reading where Ignition is configured as an OPC UA Client. The value is then returned as an empty string.

I have also tried the S7 driver at both offset 0, len 32 and offset 2, len 30. Still empty.

The only way i found is by scripting but i would prefer to have it in tags and especially OPC UA.

But this works:

def readString(plc, db, offset, length): # In order to be able to use Citect and Ignition to read the same strings at the same time we need to to this manually
	opcServer = "Ignition OPC UA Server"
	itemPaths = []
	stringOut = ""
	
	for i in range(length):
		itemPath = "["+plc+"]"+"DB"+str(db)+",C"+str(offset+i)
		print(itemPath)
		itemPaths.append(itemPath)
		
	qualifiedValues = system.opc.readValues(opcServer, itemPaths)
	
	for qualifiedValue in qualifiedValues:
		ascii = qualifiedValue.value
		c = chr(ascii)
		stringOut += str(c)
		#print c
	stringOut = stringOut.rstrip('\x00')  # Removes null bytes from the right end of the string
	return stringOut
	
	
def writeString(plc, db, offset, length, stringToWrite):
    opcServer = "Ignition OPC UA Server"
    itemPaths = []
    valuesToWrite = []
    
    # Ensure the string is exactly the length required, padded with null bytes if necessary
    stringToWrite = stringToWrite.ljust(length, '\x00')  # Pads with null bytes to the right

    for i in range(length):
        itemPath = "[" + plc + "]" + "DB" + str(db) + ",C" + str(offset + i)
        #print(itemPath)
        itemPaths.append(itemPath)
        
        # Convert each character of the string to its ASCII value and append to the list
        asciiValue = ord(stringToWrite[i])
        valuesToWrite.append(asciiValue)

    # Write all the values at once after the loop
    system.opc.writeValues(opcServer, itemPaths, valuesToWrite)
    
    # Return confirmation of the write operation
    return 0

Use offset 0 in Ignition's native driver. Ensure the actual string length is at the byte at offset zero, and the max length (30 in this case) is in the byte at offset 1. Ignition will then be able to read the strings.

(Citect is doing it wrong.)

2 Likes

Edit:

It works if i write from Ignition first so that the value in the PLC is filled with this:
image

But existing values that appears empty in the PLC are not showing in Ignition.

As pturmel mentioned, setting the length of the bytes in offset 0 & 1 works. Then i can read/write using OPC UA.

Now i just have to figure out how to do this for all strings in the PLC.

Just a quick update:

The OPC server will return something like this:

 "ProductName": "Product raw\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000",

This can be trimmed away in an expression using the following expression:

replace(tag("tagpath"), char(0), "")

That means Citech isn't setting the length when it should. No surprise, since you say in the OP that it is pointing at offset 2.

Citech is broken.

Yes, Citect gives me headache

1 Like

WinCC does this too, I constantly have this issue where Ignition follows the rules with strings but all the other users do not, even the PLC doesn't set the length when doing operations. I would love an "Autodetect length" option from Ignition to avoid this.

1 Like