xfmls 发表于 2024-8-3 13:29

javascript 解析SECS gem 报文

方便小白理解secs gem报文解析,不能理解的代码需要阅读semi手册,手册E5-0200-SECS-II自行百度
1. 协议手册参考SEMI E5官方文档:image.png
2.效果:image.png

<!DOCTYPE html>
<html>

<head lang="en">
    <meta charset="UTF-8">
    <title></title>
    <!-- vue -->
    <script type="text/javascript" src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
    <!-- element引入样式 -->
    <link rel="stylesheet" href="https://unpkg.com/element-ui/lib/theme-chalk/index.css">
    <!-- element引入组件库 -->
    <script src="https://unpkg.com/element-ui/lib/index.js"></script>
    <!--Axios-->
    <script src="https://unpkg.com/axios/dist/axios.min.js"></script>

</head>

<body>
    <div id="App">
      <div style="margin-top: 15px;">
            <el-input placeholder="请输入内容" size="small" v-model="BodyMessage" class="input-with-select">
                <el-switch v-model="isHeadMeaasge" slot="prepend" active-text="包含头报文" inactive-text="不包含头报文">
                </el-switch>
                <el-button slot="append" icon="el-icon-search" @click.prevent.stop="but1"></el-button>
            </el-input>
            <div>
                <p style="white-space: pre-wrap;">{{ showlog }}</p>
            </div>
      </div>
    </div>
</body>
<script>
    class Logger {
      constructor() {
            this.indentationLevel = 0;
            this.logContainer = '';
      }

      Indent() {
            this.indentationLevel++;
      }

      Unindent() {
            if (this.indentationLevel > 0) {
                this.indentationLevel--;
            }
      }

      Print(message) {
            let spaces = " ".repeat(this.indentationLevel * 3);
            console.log(spaces + message);
            this.logContainer += spaces + message + '\n'
      }
      ShowLog(){
            return this.logContainer;
      }
      clear(){
            this.logContainer = '';
      }
    }
    var vm = new Vue({
      el: "#App",
      data: {
            BodyMessage: '',
            isHeadMeaasge: false,
            SECSFormat: {
                Ascii: 'Ascii',
                Binary: 'Binary',
                Boolean: 'Boolean',
                F4: 'F4',
                F8: 'F8',
                I1: 'I1',
                I2: 'I2',
                I4: 'I4',
                I8: 'I8',
                List: 'List',
                U1: 'U1',
                U2: 'U2',
                U4: 'U4',
                U8: 'U8',
                Char: 'Char',
                UNRECOGNIZE_FORMAT: 'UNRECOGNIZE_FORMAT'
            },
            log: new Logger(),
            showlog: '',

      },
      created() {
      },
      mounted() {
      },
      methods: {
            but1() {
                this.log.clear();
                this.InMsg(this.hexStringToUint8Array(this.BodyMessage), false, this.isHeadMeaasge)
                console.log(this.log.ShowLog());
                this.showlog = this.log.ShowLog();
               
            },
            /**
             *
             * @Param {number} decimalValue 十进制值
             * @param {number} numBits 要求返回8位的二进制
             * @returns
             */
            decimalToBinary(decimalValue, numBits) {
                // 将十进制数转换为二进制字符串
                var binaryString = parseInt(decimalValue).toString(2);

                // 如果二进制字符串的长度小于指定位数,则在前面补零,使其长度达到指定位数
                while (binaryString.length < numBits) {
                  binaryString = '0' + binaryString;
                }

                return binaryString;
            },
            /**
             *
             * @param {number} bits 8位的二进制
             * @param {number} start 开始索引
             * @param {number} end 结束索引
             * @returns
             */
            AssembleBits(bits, index, length) {
                var stringBuilder = "";
                for (var i = index; i < index + length; i++) {
                  stringBuilder += bits.charAt(i);
                }
                return stringBuilder;
            },

            ReverseByte(buffer) {
                var array = new Uint8Array(buffer.length);
                for (var i = 0; i < buffer.length; i++) {
                  array = buffer;
                }
                return array;
            },


            /**
             *
             * @param { 0x } hexString
             * @returns
             */
            hexStringToUint8Array(hexString) {
                // 将十六进制字符串拆分为十六进制数字数组
                //const hexArray = hexString.split(' ');
                const hexArray = hexString.split(/\s+/).filter(Boolean);

                // 将十六进制数字转换为字节值,并存储在 Uint8Array 中
                const bytes = new Uint8Array(hexArray.map(hex => parseInt(hex, 16)));

                return bytes;
            },

            GetFormat(formatCode, formatLength) {
                var bytes = new Uint8Array();
                var bits = this.decimalToBinary(bytes, 8);
                var length = this.AssembleBits(bits, 6, 8)
                switch (length) {
                  case "01":
                        formatLength = 1;
                        break;
                  case "10":
                        formatLength = 2;
                        break;
                  case "11":
                        formatLength = 3;
                        break;
                }
                var text = this.AssembleBits(bits, 0, 6);
                var result = this.SECSFormat.UNRECOGNIZE_FORMAT;
                switch (text) {
                  case "000000":
                        result = this.SECSFormat.List;
                        break;
                  case "001000":
                        result = this.SECSFormat.Binary;
                        break;
                  case "001001":
                        result = this.SECSFormat.Boolean;
                        break;
                  case "010000":
                        result = this.SECSFormat.Ascii;
                        break;
                  case "010010":
                        result = this.SECSFormat.Char;
                        break;
                  case "011000":
                        result = this.SECSFormat.I8;
                        break;
                  case "011001":
                        result = this.SECSFormat.I1;
                        break;
                  case "011010":
                        result = this.SECSFormat.I2;
                        break;
                  case "011100":
                        result = this.SECSFormat.I4;
                        break;
                  case "100000":
                        result = this.SECSFormat.F8;
                        break;
                  case "100100":
                        result = this.SECSFormat.F4;
                        break;
                  case "101000":
                        result = this.SECSFormat.U8;
                        break;
                  case "101001":
                        result = this.SECSFormat.U1;
                        break;
                  case "101010":
                        result = this.SECSFormat.U2;
                        break;
                  case "101100":
                        result = this.SECSFormat.U4;
                        break;
                  default:
                        result = this.SECSFormat.UNRECOGNIZE_FORMAT;
                        break;
                  case "010001":
                        break;
                }
                return result;
            },

            MessageHeader(header) {
                let bytes = header.subarray(2, 3);
                var bitArray = this.decimalToBinary(bytes, 8);
                var wait = bitArray.charAt(0)
                var streamID = 0;
                var functionID = 0;

                if (wait == '1') {
                  streamID = header - 128;
                  wait = 'W'
                } else {
                  streamID = header;
                  wait = ''
                }
                functionID = header;

                return { 'streamID': streamID, 'functionID': functionID, 'wait': wait }
            }
            ,
            InMsg(message, Messagelength, MessageHead) {
                if (Messagelength) {
                  message = message.slice(4);
                }
                if (MessageHead) {
                  const headBytes = message.subarray(0, 10);
                  var resultHead = this.MessageHeader(headBytes)
                  this.log.Print("S" + resultHead.streamID + "F" + resultHead.functionID + " " + resultHead.wait);
                  message = message.slice(10);
                }


                let index = 0;
                let formatLength = 1;
                while (index < message.length) {
                  let incrementer = 0;
                  let formatCode = message;
                  let format = this.GetFormat(formatCode, formatLength);
                  index++;
                  let length;
                  switch (format) {
                        case this.SECSFormat.List: {
                            length = message;
                            if (length === 0) {
                              return;
                            }
                            index++;
                            this.log.Print("<L[" + length + "]");
                            this.log.Indent();

                            var result = this.InMsgChild(message, index, incrementer, length);
                            index = result.index;
                            incrementer = result.incrementer;
                            length = result.length;

                            this.log.Unindent();
                            this.log.Print(">");
                            break;
                        }
                        case this.SECSFormat.UNRECOGNIZE_FORMAT:
                            console.log("UNRECOGNIZE_FORMAT");
                            return;
                        default: {
                            length = message;
                            index++;
                            let array = new Uint8Array(length);
                            for (let i = 0; i < length; i++) {
                              array = message;
                            }

                            if (array.length === 0) {
                              this.log.Print("<" + format + "[" + 0 + "] " + '' + ">");
                            } else if (format === this.SECSFormat.Binary) {
                              if (array.length === 1) {
                                    let b = array;
                              } else {
                                    console.log(array)
                              }
                              this.log.Print("<" + format + "[" + array.length + "] " + Array.from(array).map(byte => byte.toString(16).padStart(2, '0')).join(' ') + ">");
                            } else {
                              let SECSValue = this.GetMessageValue(format, array);
                              if (format === this.SECSFormat.Ascii) {
                                    this.log.Print("<" + format + "[" + SECSValue.toString().length + "] '" + SECSValue + "'>");
                              } else {
                                    this.log.Print("<" + format + "[" + SECSValue.toString().length + "] " + SECSValue + ">");
                              }
                            }
                            break;
                        }
                  }
                  if (incrementer !== length) {
                        index += length;
                  }
                }
            }
            ,
            InMsgChild(message, index, incrementer, length) {
                let length2 = 0;
                let formatLength = 1;
                while (index < message.length && incrementer < length) {
                  let incrementer2 = 0;
                  let formatCode = message;
                  let format = this.GetFormat(formatCode, formatLength);
                  switch (format) {
                        case this.SECSFormat.List:
                            index++;
                            length2 = message;
                            index++;
                            this.log.Print("<L[" + length2 + "]");
                            this.log.Indent();

                            var result = this.InMsgChild(message, index, incrementer2, length2);
                            index = result.index;
                            incrementer2 = result.incrementer;
                            length2 = result.length;

                            this.log.Unindent();
                            this.log.Print(">");
                            incrementer++;
                            break;
                        case this.SECSFormat.UNRECOGNIZE_FORMAT:
                            return;
                        default:
                            incrementer++;
                            index++;
                            let array = new Uint8Array(formatLength);
                            array.set(message.slice(index, index + formatLength), 0);
                            array = this.ReverseByte(array);
                            if (array.length === 1) {
                              length2 = array;
                            } else if (array.length === 2) {
                              let value = new Int16Array(array.buffer);
                              length2 = value;
                            }
                            index += formatLength;
                            let array2 = new Uint8Array(length2);
                            array2.set(message.slice(index, index + length2), 0);
                            if (array2.length === 0) {
                              this.log.Print("<" + format + "[" + 0 + "] " + '' + ">");
                            } else if (format === this.SECSFormat.Binary) {
                              if (array2.length === 1) {
                                    let b = array2;
                              } else {
                                    console.log(array)
                              }
                              this.log.Print("<" + format + "[" + array2.length + "] " + Array.from(array2).map(byte => byte.toString(16).padStart(2, '0')).join(' ') + ">");
                            } else {
                              let SECSValue = this.GetMessageValue(format, array2);
                              if (format === this.SECSFormat.Ascii) {
                                    this.log.Print("<" + format + "[" + SECSValue.toString().length + "] '" + SECSValue + "'>");
                              } else {
                                    this.log.Print("<" + format + "[" + SECSValue.toString().length + "] " + SECSValue + ">");
                              }
                            }
                            break;
                  }
                  if (incrementer2 !== length2) {
                        index += length2;
                  }
                }
                return { 'index': index, 'incrementer': incrementer, 'length': length }
            }
            ,
            GetMessageValue(formatCode, message) {
                let obj = null;
                switch (formatCode) {
                  case this.SECSFormat.Ascii:
                        obj = String.fromCharCode.apply(null, message);
                        break;
                  case this.SECSFormat.Boolean:
                        obj = !!message;
                        break;
                  case this.SECSFormat.Char:
                        obj = String.fromCharCode(message);
                        break;
                  case this.SECSFormat.F4:
                        message = this.ReverseByte(message);
                        obj = new DataView(new Uint8Array(message).buffer).getFloat32(0, true);
                        break;
                  case this.SECSFormat.F8:
                        message = this.ReverseByte(message);
                        obj = new DataView(new Uint8Array(message).buffer).getFloat64(0, true);
                        break;
                  case this.SECSFormat.I1:
                        message = this.ReverseByte(message);
                        let b2 = message;
                        obj = (b2 <= 127) ? b2 : (b2 - 256);
                        break;
                  case this.SECSFormat.I2:
                        message = this.ReverseByte(message);
                        obj = new DataView(new Uint8Array(message).buffer).getInt16(0, true);
                        break;
                  case this.SECSFormat.I4:
                        message = this.ReverseByte(message);
                        obj = new DataView(new Uint8Array(message).buffer).getInt32(0, true);
                        break;
                  case this.SECSFormat.I8:
                        message = this.ReverseByte(message);
                        obj = new DataView(new Uint8Array(message).buffer).getBigInt64(0, true);
                        break;
                  case this.SECSFormat.U1:
                        message = this.ReverseByte(message);
                        let b = message;
                        obj = b;
                        break;
                  case this.SECSFormat.U2:
                        message = this.ReverseByte(message);
                        obj = new DataView(new Uint8Array(message).buffer).getUint16(0, true);
                        break;
                  case this.SECSFormat.U4:
                        message = this.ReverseByte(message);
                        obj = new DataView(new Uint8Array(message).buffer).getUint32(0, true);
                        break;
                  case this.SECSFormat.U8:
                        message = this.ReverseByte(message);
                        obj = new DataView(new Uint8Array(message).buffer).getBigUint64(0, true);
                        break;
                }
                return obj.toString();
            },



      }
    })
</script>

</html>

页: [1]
查看完整版本: javascript 解析SECS gem 报文