robinson / gos7

Implementation of Siemens S7 protocol in golang
BSD 3-Clause "New" or "Revised" License
314 stars 121 forks source link

BUG : gos7.SetWStringAt() #53

Open XMNHCAS opened 2 years ago

XMNHCAS commented 2 years ago

Hi Robinson. When I'm use gos7.SetWStringAt() to obtain the byte array written to PLC, it will always write several more bytes, For example, when I want to write the string "中文", it will finally be written as "中文$0000$0000$0000$0000". After consulting the data on the Internet, I learned that in Go, Chinese word is stored in three bytes, so using len() method to obtain the number of characters will get the wrong result, resulting in the wrong number of characters in the finally generated message, so PLC will supplement the extra "$0000" according to the wrong number of characters . To solve this problem, I modified this method, removed the parameter of the maximum number of characters, set the maximum number of characters in the method to the default 254, and calculate the number of characters of the incoming string. The following is my modification. I hope it will be helpful to you.

当我在使用gos7.SetWStringAt()这个方法来获取写入PLC的字节数组的时候,它总是会多写入几个字节,比如我要写入”中文“这个字符串的时候,它最后会写成”中文$0000$0000$0000$0000“,在网上查阅资料后,我得知在Go中,中文是用三个字节进行存储的,所以使用len()方法来获取字符数会得到错误的结果,导致最后生成的报文里的字符数是错的,所以PLC根据错误的字符数补上多余的”$0000“。为此,我修改了一下这个方法,移除了最大的字符数这个参数,在方法内将最大字符数设置为默认254,并计算传入的字符串的字符数。下面是我的修改,希望能对你有帮助。

func (s7 Helper) SetWStringAt(buffer []byte, pos int, value string) []byte { chars := []rune(value) sLen := len(chars) maxlen := 254 if maxLen < sLen { sLen = maxLen } s7.SetValueAt(buffer, pos+0, int16(maxLen)) s7.SetValueAt(buffer, pos+2, int16(sLen)) for i, c := range chars { if i >= sLen { return buffer } s7.SetValueAt(buffer, pos+4+i2, uint16(c)) } return buffer }