VB/JS source code of CRC data verification algorithm in HJ212-2017 "Data Transmission Standard for Online Pollutant Monitoring (Monitoring) System"

PS: The source code is collected from:  CRC Cyclic Redundancy Check of HJT212- Developer Knowledge Base  

I organized and merged them into one function, so far, I finally got this painful code.

Origin:

    In the past few days, I am going to write a simple data receiving end that supports HJ212-2017 "On-line Pollutant Monitoring (Monitoring) System Data Transmission Standard" for fun. After carefully studying the text of the communication protocol, I found that the data block needs to be checked by CRC16 in the communication, so I dug out the CRC16 code from a few years ago and tested it with an example (pages 19 and 20 in the standard),

I found that the results were inconsistent. My original code:

Public Function crc16Str(s As String) As String
    Dim data() As Byte
    Dim ReturnData(1) As Byte
    Dim CRC_Reg_Lo, CRC_Reg_Hi As Byte
    Dim CL, CH As Byte
    Dim SaveHi, SaveLo As Byte
    Dim i, j As Integer
    CRC_Reg_Lo = &HFF
    CRC_Reg_Hi = &HFF   'CRC寄存器&H FF FF
    CH = &HA0
    CL = &H1        '多项式&H A0 01
    data = StrConv(s, vbFromUnicode)
    For i = 0 To UBound(data)
        CRC_Reg_Lo = CRC_Reg_Lo Xor data(i) '依次和寄存器低8位进行异或运算
        For j = 0 To 7
            SaveHi = CRC_Reg_Hi             '保存高位,是为了判断右移时是否向低位字节进1
            SaveLo = CRC_Reg_Lo             '保存地位,是为了判断LSB是否为0
'以下是右移'''''''''''''''''''''''''''''''''''''
            CRC_Reg_Hi = CRC_Reg_Hi \ 2
            CRC_Reg_Lo = CRC_Reg_Lo \ 2
            If ((SaveHi And &H1) = &H1) Then
                CRC_Reg_Lo = CRC_Reg_Lo Or &H80
            End If
'右移完成'''''''''''''''''''''''''''''''''''''''
            If ((SaveLo And &H1) = &H1) Then
                CRC_Reg_Hi = CRC_Reg_Hi Xor CH
                CRC_Reg_Lo = CRC_Reg_Lo Xor CL
            End If
        Next j
    Next i
    ReturnData(0) = CRC_Reg_Lo  '低位
    ReturnData(1) = CRC_Reg_Hi  '高位
    s = ""
    For i = 0 To UBound(ReturnData)
        s = Right("00" & Hex(ReturnData(i)), 2) & s
    Next
    crc16Str = s
End Function

Check example string:

QN=20160801085857223;ST=32;CN=1062;PW=100000;MN=010000A8900016F000169DC0;Flag=5;CP=&&RtdInterval=30&&

The result is &H0759, not &H1C80. After checking it, I found that there are many versions of CRC16. The one above belongs to the ModBus algorithm. From the online CRC calculator: CRC (Cyclic Redundancy Check) online calculation_ip33.com, pilot test All CRC16 algorithms found that the results did not match.

It seems that if this is the case, it can only be changed directly according to the C language algorithm in the HJ212 standard. In the search again, I found that  the online automatic monitoring (monitoring) system data transmission standard of pollutants (HJ212-2017) - CRC data verification - Liu Siyuan -   There is a Java algorithm in  the blog garden http://t.csdn.cn/jGja6 , in order to quickly debug, I changed it to JS language, threw it into the browser and tried it, and the result actually matched:

<html>
<head>
</head>
<body>
<script type="text/javascript">
 function strToUtf8Bytes(str) {
  const utf8 = [];
  for (let ii = 0; ii < str.length; ii++) {
    let charCode = str.charCodeAt(ii);
    if (charCode < 0x80) utf8.push(charCode);
    else if (charCode < 0x800) {
      utf8.push(0xc0 | (charCode >> 6), 0x80 | (charCode & 0x3f));
    } else if (charCode < 0xd800 || charCode >= 0xe000) {
      utf8.push(0xe0 | (charCode >> 12), 0x80 | ((charCode >> 6) & 0x3f), 0x80 | (charCode & 0x3f));
    } else {
      ii++;
      // Surrogate pair:
      // UTF-16 encodes 0x10000-0x10FFFF by subtracting 0x10000 and
      // splitting the 20 bits of 0x0-0xFFFFF into two halves
      charCode = 0x10000 + (((charCode & 0x3ff) << 10) | (str.charCodeAt(ii) & 0x3ff));
      utf8.push(
        0xf0 | (charCode >> 18),
        0x80 | ((charCode >> 12) & 0x3f),
        0x80 | ((charCode >> 6) & 0x3f),
        0x80 | (charCode & 0x3f),
      );
    }
  }
  //兼容汉字,ASCII码表最大的值为127,大于127的值为特殊字符
  for(let jj=0;jj<utf8.length;jj++){
	  var code = utf8[jj];
	  if(code>127){
		  utf8[jj] = code - 256;
	  }
  }
  return utf8;
}

 function getCRC(data212) {
        let CRC =0xFFFF;
        let num =0xA001;
        let inum = 0;
        let sb =strToUtf8Bytes(data212);//.getBytes();
        for(let j = 0; j < sb.length; j ++) {
            inum = sb[j];
            CRC = (CRC >> 8) & 0x00FF;
            CRC ^= inum;
            for(let k = 0; k < 8; k++) {
                let flag = CRC % 2;
                CRC = CRC >> 1;            
                if(flag == 1) {
                    CRC = CRC ^ num;
                }
            }
        }
        //console.log(CRC); 7296        
        return CRC.toString(16).toUpperCase(); //最后别忘了,需要的是16进制结果,Integer.toHexString()
  }
	console.log(getCRC('QN=20160801085857223;ST=32;CN=1062;PW=100000;MN=010000A8900016F000169DC0;Flag=5;CP=&&RtdInterval=30&&'));
	document.write(getCRC('QN=20160801085857223;ST=32;CN=1062;PW=100000;MN=010000A8900016F000169DC0;Flag=5;CP=&&RtdInterval=30&&')+'<br/>');

</script>
</body>
</html>

Among them, strToUtf8Bytes comes from: Implementing Java's getBytes() method in JS_kinpowoo's blog-CSDN blog   .

Suddenly I was too lazy to change it to VB by myself, and in the bd search results with lower and lower search hit rates, a webpage that took 3 minutes to open: HJT212 CRC Cyclic Redundancy Check -  found on the developer knowledge base There is a piece of VB code in the second half page, take it over immediately, and modify it:

Function CRC16forHJ212_2017(s As String) As String  '(data() As Byte) As Long
    Dim r As Long
    Dim hi As Byte
    Dim flag As Byte
    Dim i As Long, j As Long, data() As Byte
    data = StrConv(s, vbFromUnicode)
    r = &HFFFF&
    For j = 0 To UBound(data)
        hi = r \ &H100&
        hi = hi Xor data(j)
        r = hi
        For i = 1 To 8
            flag = r And 1
            r = r \ 2
            If flag = 1 Then
                r = r Xor &HA001&
            End If
        Next
    Next
    CRC16forHJ212_2017 = Right("0000" & Hex(r), 4)
End Function

Several pieces of data were tested, and the results exactly matched those in HJ212-2017.

’------------------

This note!

Related resources (5 points): HJ212-2017 "Data Transmission Standard for Online Pollutant Monitoring (Monitoring) System"-C Document Resources-CSDN Download

Guess you like

Origin blog.csdn.net/jessezappy/article/details/125092472