We met a issue on reading string tag value from S7-1500 PLC with Ignition S7-1500 driver, the data in the PLC is Chinese character store in DB, and ignition get the string as garbled text. We tried to decode and encode with different character set(UTF8, iso-8859-1, gbk), but failed to get the right Chinese string as recipe name from equipment.
Below is the custom script we using for the string extraction: defined a function to decode the string
def decode_siemens_gbk(raw_string):
# 1. 安全检查:空值处理 Check if it is null
if raw_string is None or str(raw_string).strip() == "":
return ""
# 2. 如果传入的已经是 unicode 对象 if the raw string is unicode
if isinstance(raw_string, unicode):
try:
# 尝试用 iso-8859-1 还原底层字节流(针对 2_V7 这种真正的单字节乱码)
# Try using iso-8859-1 to restore the underlying byte stream
raw_bytes = raw_string.encode('iso-8859-1')
return raw_bytes.decode('gbk', 'ignore')
except UnicodeEncodeError:
# 【触发报错的地方】如果含有 latin-1 无法编码的字符,说明里面已经有真正的中文字符
# If it contains characters that latin-1 cannot encode, it means there are already real Chinese characters inside
try:
# 尝试直接用 gbk 重新解码(以防万一)Try directly decoding with gbk
return raw_string.encode('utf-8').decode('gbk', 'ignore')
except Exception:
# 如果怎么转都错,说明这个字符串在 Ignition 里已经是正确的中文了,直接返回原值
#If no matter how you convert it, it means the string is already in correct Chinese in Ignition,
#and it returns the original value directly
return raw_string
# 3. 如果传入的是标准 str (字节流) If the input is a standard str (byte stream)
else:
try:
return str(raw_string).decode('gbk', 'ignore')
except Exception:
return str(raw_string)
I've done my best to recover the code formatting on your original post; see this thread for more instructions on how to do it.
Step 1, most likely, is to drop all this stuff you're trying to do via scripting. Strings Ignition returns to you are natively unicode and you don't have to mess around with encodings in most scenarios.
Post the exact value of what raw_string is as soon as you get it - e.g. use system.util.getLogger("stringDebug").infof("raw string: %s", repr(raw_string))
Also, this is just a hunch, but be very careful with the output of LLMs/AI with regard to Ignition. LLMs need very diligent prompting because they don't fully understand Ignition's context and will happily provide you lots and lots of code you don't actually need.
You have no chance at reinterpreting the bytes, by the time they've gotten to you they've already been turned from bytes into a string using the platform encoding. It probably should be explicitly UTF-8 instead of whatever the platform encoding happens to be, but that's how it's implemented right now.
You might try setting -Dfile.encoding=UTF-8 in ignition.conf (requires gateway restart) to see if that changes anything for you...
It seems our DEV Igniton edge server has already configured the UTF-8 encoding setting.
Beside, the variable address table on the two S7-1500 PLCs are set as shown below, with variable names created in Chinese, we retrieved the variable with address [devicename]DB3,STRING46.25 and [devicename]DB23,STRING94.20, why not using 254 as offset since it would cause all the data retrieved from PLC crashed in Ignition.
Using system.opc.readValue to read the string value by Bytes, taking [devicename]DB3,STRING46.25 for example, the string start from Byte offset 46 in DB3, the string length is stored in Byte offset 47 in DB3 and the actual first character should be stored in Byte offset 48 in DB3. After get all the characters in bytes array with the length from Byte offset 47 in DB3, and change them to signed byte (if the bytes large than 256 then subtract 256), then translate them to GBK set with JString function from Java, and we could get the right Chinese string.