前端js解析二进制数据流写入echarts折线图详情

本文详细介绍了如何在前端接收后端发送的二进制数据流,通过DataView解析,去掉冗余字节,并利用算法将数据转换为Echarts折线图的显示数据。涉及包头处理、通道数据提取和echarts图表的动态更新。
摘要由CSDN通过智能技术生成

#问题:

后端发给前端二进制数据流,前端如何解析,实时写入echarts折线图,接下来我们看下面解析和用到的前端技术。

一, 需要了解的内容

1,大家都知道二进制的字节是(1111 1111)是一个字节,那么转换成16进制就是(ff)。
2,我解析的二进制数据流的数据格式是
	(ff ff ff ff 0x xx xx xx  1x xx xx xx …… 7x xx xx xx,0x xx xx xx……循环到1028个字节),
	描述:
	1>,ff ff ff ff是包头是四个字节,每1028个字节中有一个包头,实际数据是1024加包头是1028。
	2>,0x到7x是一组数据是8个通道的数据,(除0通道以外,0x这一小组数据有效数据是第2个字节和第3个字节,
		也就是说,第1个字节和4个字节是无用数据),每组数据的每四个字节的是一小组,一小组的第一个字节
		是无用数据也就是1x,有用的数据是xx xx xx,
3,正常一个数据包都是1024个字节,但是此数据的长度是fpga自定义的1028个字节为一包数据,关于fpga是啥不明白可以百度,这里不做过多的描述。

不明白的可以看图
不明白的可以看图

二,我们来看下方的解析数据

在这里插入图片描述

描述:如何解析二进制码流

1,先使用$axios获取后端的接口数据使用try判断你当前发送的数据是arraybuffer还是json的数据,因为我们要接收俩种数据类型的数据。

2,接下来我们使用DataView来获取二进制数据流,如不知道DataView是什么请看此链接   
		(https://blog.csdn.net/qiqingjin/article/details/51816227)
		
3,使用for循环算出后端一共给我们多少包数据,在使用一个for循环去掉每包数据的前四个字节的数据。因为我们要已四个字节为
		一组所以所以我们要使用getuint32,算出来的就是四字节一小组数据,然后我们push到提取创建好的二维数组中。
		
4,var定义的h,m,s,是echarts中的x轴的数据,判断that.form.timee.length>=6000是保证图中可以放下6000个点,超过6000就从
		图中左侧开始删除,保证图中最多6000个。

DataView–链接点击此处

相应的代码

webSocketClientOnopen(now) {
      var that = this
      this.$axios({// ajax
        url:'/send_fpga_data',
        method:'post',
        responseType:'arraybuffer',
      })
      .then(function (response) {
        try{                                                 //执行代码
          let enc = new TextDecoder('utf-8')
          var tmp = JSON.parse(enc.decode(new Uint8Array(response.data)))
          if(tmp.code == 20000){
            that.form.Click_on_the_state = true
            that.$message('关闭成功!')
            clearInterval(that.clearTimeSet);               //关闭定时器
          }
        }
        catch(err){   //处理错误
          console.log(response)
          const view1 = new DataView(response.data);
          for(var i=0;i<view1.byteLength/1028;i++){         
            for(var p=1;p<(1028/4);p++){                   
              var algodata = view1.getUint32(i*1028+p*4)
              //console.log(algodata.toString(16))
              that.form.channel[(p-1)%8].push(that.analytic_function(((p-1)%8), algodata))
              var myDate = new Date();
              var h=myDate.getHours();   
              var m=myDate.getMinutes(); 
              var s=myDate.getSeconds(); 
              var now = h+":"+m+"."+s
                if(that.form.channel[that.form.select_aisle].length == that.form.timee.length){
                  console.log('数据正在写入中...')
                }else{
                  that.form.timee.push(now)
                  that.set_option();
                  if (that.form.timee.length>=6000){
                    that.form.timee.shift()
                    that.form.channel[0].shift()
                    that.form.channel[1].shift()
                    that.form.channel[2].shift()
                    that.form.channel[3].shift()
                    that.form.channel[4].shift()
                    that.form.channel[5].shift()
                    that.form.channel[6].shift()
                    that.form.channel[7].shift()
                  }
                }
            }
          }
        }
      })
      .catch(function (error) {
        console.log(error);
      })
    },

三,接下来我们创建二维数组

在这里插入图片描述

描述:

先创建一个数组,初始化的时候我们在这个数组中循环插入8个数组,也是8个通道的y轴数据。

相应的代码

<script>
const echarts = require('echarts');
export default{
  data () {
    //watch
    return {
      form:{
        channel:[],//二维数组
      },
    };
  },
  mounted(){    //在这发起后端请求,拿回数据,配合路由钩子做一些事情(dom渲染完成 组件挂载完成 )
    this.initCharts();
    for(var chn=0;chn<8;chn++){
      this.form.channel[chn] = new Array()
    }
  },       
 }

四,解析完数据,通过算法得到需要的数据

描述:
1,下图中if判断==0是判断的二维数组中第一个数组,其他的数组都走的是else,因为0通道的数据比较特殊,需要单独解析和算。
2,0通道我们拿到数据以后吧四字节数据像左移8,像右边移16就可以去掉第一个字节和第4个字节,我们拿到的就是有效数据了。
3,根据算法,数据*5/2^15就是我们要的值,保留4位小数,把他写入echarts。
4,其他通道同样的道理,不做过多描述。
5,Set_option函数每次只展示一个通道的数据,根据this.form.select_aisle实时获取数据变化去实现的,也是吧数据实时写入图中的函数。

在这里插入图片描述

相应代码

methods: {//methods中一般都是定义的需要事件触发的一些函数。每次只要触发事件,就会执行对应的方法
    analytic_function(chn,algodata){
      var price;
      if(chn==0){
        algodata = algodata<<8
        //console.log(algodata.toString(16))
        var right_shift_1 = algodata>>16
        var channel_algorithm1 = right_shift_1*5
        var calculate_square1 = Math.pow(2,15)
        var answer1 = channel_algorithm1/calculate_square1
        price = answer1.toFixed(4)
      }else{
        var true_data2 = algodata<<8
        var right_shift_2 = true_data2>>8
        //console.log(right_shift_2.toString(16))
        var channel_algorithm2 = right_shift_2*5
        var calculate_square2 = Math.pow(2,23)
        var answer2 = channel_algorithm2/calculate_square2
        price =answer2.toFixed(4)
      }
      return price
    },
    set_option(){
      var Minus_one = parseInt(this.form.select_aisle)
      var Minus_one_data = Minus_one+1
      // console.log(Minus_one_data)
      this.myChart.setOption({
        xAxis: {
          data : this.form.timee,
        },
        series: [
          {
            name:'通道'+ Minus_one_data,
            data:this.form.channel[this.form.select_aisle],//.splice(0,1000)
          },
        ]
      });
    },
  }

五,获取页面数据发送后端,启动定时器

描述:
1,下图是页面输入需要打包数据的接口函数,点击查看波形图启动定时器,定时像后端获取数据,直到你获取到你
	所需要的全部包数停下来。

在这里插入图片描述

相应代码

look_at_the_picture(){
   var that =this
   if(this.form.package!='' && this.form.package<=8000 && this.form.package>0){
     this.data_package = {"packet_num":parseInt(this.form.package)}
     this.$axios.post("/set_packet_num",this.data_package)
       .then(function(response){
         // console.log(response);
         if(response.data.code==20000){
           that.form.timee = []//第二次请求,清空二维数组,重新加载
           that.form.channel[0] = []
           that.form.channel[1] = []
           that.form.channel[2] = []
           that.form.channel[3] = []
           that.form.channel[4] = []
           that.form.channel[5] = []
           that.form.channel[6] = []
           that.form.channel[7] = []
           that.myChart.dispose();
           that.initCharts()
           if (that.form.Click_on_the_state == true) {
             that.form.Click_on_the_state = false
             that.$message('点击成功!')
             that.clearTimeSet=setInterval(() => {//定时器
               that.webSocketClientOnopen();
             }, 3000);
           }else{
             that.$message('点击无效!')
           }
         }else{
         	that.$message({type: 'error',message: '配置失败!'});
         }

       })
       .catch(function (error) {
         console.log(error);
       })
   }else{
     this.$message({type: 'error',message: '输入无效!'});
   }
 },

六,echarts折线图代码

下图是折线图代码,不做描述。
initCharts () {
      window.addEventListener("resize",()=>{
        this.myChart.resize();
      })
      this.myChart = echarts.init(document.getElementById("map"))

      this.option = {
        // title: { text: '在Vue中使用' },
        grid:{//调试折线图,是否撑满容器
          top:"50px",
          left:"60px",
          right:"60px",
          bottom:"40px"
        },
        tooltip: {
          trigger:'axis'
        },
        legend:{
          data:['通道1','通道2','通道3','通道4','通道5','通道6','通道7','通道8']
        },
        toolbox: {//折线图右上角的放大缩小等等功能
          show: true,
          feature: {
            dataZoom: {
              yAxisIndex: 'none'
            },
            dataView: {readOnly: false},
            magicType: {type: ['line', 'bar']},
            restore: {},
            saveAsImage: {}
          }
        },
        xAxis: {
          type : 'category',
          boundaryGap : false,
          // axisLabel:{
          //      	interval:100, //加入axisLabel字段,interval后面加你想要间隔的个数
          // },
          show:false,
          data : this.form.timee,
        },
        yAxis: {
          type : 'value',
          splitLine: {//去除网格线
            show: false ,
          },
          axisTick: {
            show: true,
          },
          name: '(幅值)'
        },
        tooltip: {
          trigger: 'axis',
          position: function (pt) {
            return [pt[0], '10%'];
          }
        },
        dataZoom: [
          {
            type: 'inside',
            start: 100,
            end: 80
          },
          {
            start: 0,
            end: 10
          }
        ],
        series: [
          {
            name:'通道'+this.form.select_aisle,
            type:'line',
            stack: '总量',
            smooth: true,//调试曲线
            //sampling: 'average',//降采样策略
            symbol:'none',
            data:this.form.channel[this.form.select_aisle],
            markLine: {
              precision:4,//调试最大值最小值等,保留几位小数
                data: [
                  {type: 'average', name: '偏置'},
                  {type: 'max',name:'最大值'},
                  {type: 'min',name:'最小值'},
                ]
            }
          },
        ]
      };
      //this.option &&
      this.myChart.setOption(this.option)
    }

六,页面,和正确波形图

1,页面

在这里插入图片描述

2,正确波形图

在这里插入图片描述
完结,不喜勿喷!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值