You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
204 lines
5.7 KiB
204 lines
5.7 KiB
4 years ago
|
# Web侧高频数据 chart 展示预研说明文档
|
||
|
|
||
|
Author: 彭玲 CreatedTime: 2021/5/11
|
||
|
|
||
|
---
|
||
|
|
||
|
[TOC]
|
||
|
|
||
|
---
|
||
|
|
||
|
|
||
|
|
||
|
## 背景
|
||
|
|
||
|
目前,光纤光栅、振动连续采集、动应变、GNSS 实时动态解析等的采样频率高达到 1~100Hz(或更高)。针对高频采样,之前接入侧常采用”降低采样频率“”分时段采样(振动)“等处理方式,但存在数据”丢失“的必然结果。
|
||
|
|
||
|
为满足客户对高频数据接入的需求,针对高频数据采集进行了专项处理:平台侧接收原始采集粒度数据、存储于 HDFS 文件系统中,并提供 HDFS 查询服务和可视化 (不限于平台)。
|
||
|
|
||
|
|
||
|
|
||
|
## 功能说明
|
||
|
|
||
|
Web侧将平台接入的高频数据以图表形式进行展示。
|
||
|
|
||
|
### 输入
|
||
|
|
||
|
输入为:chart 图片的 Base64 地址 (Data URLs)
|
||
|
|
||
|
- Data URLs:`data:image/png;base64,<image-data>`
|
||
|
- Base64 图片来源:平台 PyRpcService (http://10.8.30.22/FS-Anxinyun/trunk/codes/services/PyRpcService) 接口查询服务`high_frequency_chart`(查询 HDFS 存储数据)
|
||
|
|
||
|
### 输出
|
||
|
|
||
|
输出为:chart 图片
|
||
|
|
||
|
必要的查询组件:**结构物**选择器、**起止时间**选择框
|
||
|
|
||
|
![](E:\WorkSpace\iFS-Backend\高频数据接入\assets\高频数据展示-web-demo.png)
|
||
|
|
||
|
|
||
|
|
||
|
## Postman 请求
|
||
|
|
||
|
参数说明:
|
||
|
|
||
|
- HDFS 文件地址,包括:结构物 id,HDFS 文件夹 `<年份>`,HDFS 文件夹 `<月份>`
|
||
|
- 查询起止时间:Unix 时间戳 (ms)
|
||
|
|
||
|
![](E:\WorkSpace\iFS-Backend\高频数据接入\assets\Postman RPC:high_frequency_chart.png)
|
||
|
|
||
|
|
||
|
|
||
|
## 关键代码
|
||
|
|
||
|
### web-api
|
||
|
|
||
|
```js
|
||
|
const request = require('superagent')
|
||
|
|
||
|
module.exports = {
|
||
|
entry: function (app, router, opts) {
|
||
|
|
||
|
const RPC_SVR_URL = opts.highFrequencyChartRpcSvrUrl || `http://localhost:15000/api`;
|
||
|
|
||
|
let fetchHighFrequencyChartData = async function (ctx, next) {
|
||
|
const params = ctx.request.body;
|
||
|
try {
|
||
|
const reqBody = {
|
||
|
"jsonrpc": "2.0",
|
||
|
"id": "myid",
|
||
|
"method": "high_frequency_chart",
|
||
|
"params": params,
|
||
|
// "params": {
|
||
|
// "url": "/anxinyun/structure_data/structure_854/raw/2021/2/gxwd1-1.csv",
|
||
|
// "gte": 1613810269584,
|
||
|
// "lt": 1613810706956
|
||
|
// }
|
||
|
}
|
||
|
const proxyReq = request.post(RPC_SVR_URL).send(reqBody)
|
||
|
const res = await proxyReq
|
||
|
|
||
|
ctx.status = res.status
|
||
|
ctx.body = { data: res.body.result }
|
||
|
} catch (e) {
|
||
|
let errMsg = `fetch high_frequency_chart data error: ${e}`
|
||
|
ctx.status = 500;
|
||
|
ctx.fs.logger.error(errMsg)
|
||
|
ctx.body = { err: errMsg }
|
||
|
}
|
||
|
}
|
||
|
|
||
|
router.post('/_high_frequency_chart', fetchHighFrequencyChartData)
|
||
|
}
|
||
|
};
|
||
|
|
||
|
```
|
||
|
|
||
|
|
||
|
|
||
|
### web
|
||
|
|
||
|
```js
|
||
|
import React, { Component } from 'react'
|
||
|
|
||
|
import { Select, DatePicker } from 'antd'
|
||
|
const Option = Select.Option
|
||
|
const { RangePicker } = DatePicker
|
||
|
|
||
|
const request = require('superagent')
|
||
|
|
||
|
class HighFrequencyChart extends Component {
|
||
|
constructor(props) {
|
||
|
super(props)
|
||
|
|
||
|
this.state = {
|
||
|
chartData: null
|
||
|
}
|
||
|
}
|
||
|
|
||
|
fetchHighFrequencyChartData = () => {
|
||
|
let structId = 854
|
||
|
let hdfsDirYear = '2021',
|
||
|
hdrsDirMonth = '2'
|
||
|
let filterBegin = 1613810269584, // 2021-02-20 16:37:49
|
||
|
fiterEnd = 1613810706956 // 2021-02-20 16:45:06
|
||
|
|
||
|
const params = {
|
||
|
// Example: /anxinyun/structure_data/structure_854/raw/2021/2/gxwd1-1.csv
|
||
|
"url": `/anxinyun/structure_data/structure_${structId}/raw/${hdfsDirYear}/${hdrsDirMonth}/gxwd1-1.csv`,
|
||
|
"gte": filterBegin, // begin time for part of the HDFS resource
|
||
|
"lt": fiterEnd // end time for part of the HDFS resource
|
||
|
}
|
||
|
|
||
|
request.post('_high_frequency_chart').send(params).end((err, res) => {
|
||
|
if (!err) {
|
||
|
let chartData = res.body.data
|
||
|
this.setState({ chartData })
|
||
|
} else {
|
||
|
// handle err msg...
|
||
|
}
|
||
|
})
|
||
|
}
|
||
|
|
||
|
componentDidMount() {
|
||
|
this.fetchHighFrequencyChartData()
|
||
|
}
|
||
|
|
||
|
renderStructures = () => {
|
||
|
return (
|
||
|
<Select
|
||
|
showSearch
|
||
|
style={{ width: 200 }}
|
||
|
placeholder="Select a structure"
|
||
|
optionFilterProp="children"
|
||
|
filterOption={(input, option) => option.props.children.toLowerCase().indexOf(input.toLowerCase()) >= 0}
|
||
|
>
|
||
|
<Option value="bridge">桥梁 #1</Option>
|
||
|
<Option value="slope">边坡 #2</Option>
|
||
|
</Select>
|
||
|
)
|
||
|
}
|
||
|
|
||
|
renderRangePicker = () => {
|
||
|
return (
|
||
|
<RangePicker
|
||
|
showTime={{ format: 'HH:mm' }}
|
||
|
format="YYYY-MM-DD HH:mm"
|
||
|
placeholder={['Start Time', 'End Time']}
|
||
|
/>
|
||
|
)
|
||
|
}
|
||
|
|
||
|
renderHighFrequencyChart = () => {
|
||
|
let data = this.state.chartData
|
||
|
if (data) {
|
||
|
return <img src={data} width='1000' height='500' />
|
||
|
}
|
||
|
return null
|
||
|
}
|
||
|
|
||
|
render() {
|
||
|
return (
|
||
|
<div>
|
||
|
<section style={{ padding: '32px 0' }}>
|
||
|
<span>结构物选择:</span>{this.renderStructures()}
|
||
|
<span style={{ paddingLeft: '24px' }}>起止时间选择:</span>{this.renderRangePicker()}
|
||
|
</section>
|
||
|
|
||
|
{/* HighFrequencyChart Module */}
|
||
|
<section>
|
||
|
{this.renderHighFrequencyChart()}
|
||
|
</section>
|
||
|
</div>
|
||
|
)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
export default HighFrequencyChart
|
||
|
|
||
|
```
|
||
|
|
||
|
|
||
|
|