Commit 7edb84c9 authored by wanli's avatar wanli

update

parent c739dee8
'''
Author: your name
Date: 2021-06-29 19:33:41
LastEditTime: 2021-07-05 09:26:59
LastEditTime: 2021-07-05 16:53:48
LastEditors: Please set LastEditors
Description: In User Settings Edit
FilePath: \evm-store\backend\view\monitor.py
......@@ -14,7 +14,6 @@ from tornado.websocket import WebSocketHandler, WebSocketClosedError
import json
import signal
import time
import logging
import pprint
import traceback
import jwt
......@@ -22,11 +21,10 @@ from typing import ( Any,)
from threading import Timer
from datetime import datetime, timedelta
from app import config
from fullstack.log import logger
from model.monitor import session, Device, User
from controller.monitor import insert_data, get_monitor_list, get_watch_list
logger = logging.getLogger(__name__)
def datetime2secs(mydate):
return time.mktime(mydate.timetuple())
......@@ -81,13 +79,14 @@ def pushmessage(func):
msg, binary = ret
try:
if isinstance(msg, WebsocketResponse) or isinstance(msg, dict):
self.write(json.dumps(msg), binary)
self.write_message(json.dumps(msg), binary)
elif isinstance(msg, str) or isinstance(msg, str):
self.write(msg, binary)
self.write_message(msg, binary)
else:
self.write(repr(msg), binary)
self.write_message(repr(msg), binary)
except WebSocketClosedError as e:
logger.error(e)
traceback.print_exc()
self.on_close()
return send
......@@ -109,6 +108,7 @@ class BaseWebsocket(WebSocketHandler):
if className not in self.handlers:
self.handlers[className] = set()
self.handlers[className].add(self)
logger.info(self.handlers[className])
pprint.pprint(self.handlers)
@pushmessage
......@@ -118,8 +118,10 @@ class BaseWebsocket(WebSocketHandler):
def on_close(self):
className = self.__class__.__name__
logger.warning("websocket of %s is closed" % className)
if className in self.handlers:
print("122 ======>", type(self.handlers), type(className), type(self.handlers[className]))
if className in self.handlers and self in self.handlers[className]:
# 更加健壮的处理是,这里需要增加一个self是否存在的判断
# logger.info(self.handlers[className])
# logger.info(id(self))
self.handlers[className].remove(self)
def check_origin(self, origin):
......@@ -136,7 +138,7 @@ class BaseWebsocket(WebSocketHandler):
for item in cls._clients:
if message.get("imei") in item.get("devices", []):
item.get("context").send(json.dumps(message), binary)
# print(id(item.get("context")))
# item.get("context").write_message(json.dumps(message))
# className = cls.__name__
# message = json.dumps(message)
......@@ -158,9 +160,10 @@ class NotifyHandler(BaseWebsocket):
super(NotifyHandler, self).open()
def on_message(self, message):
className = self.__class__.__name__
message = json.loads(message)
try:
className = self.__class__.__name__
logger.info(message)
message = json.loads(message)
# 判断消息类型
if message.get("type"):
# 获取token值,检验正确与否,获取uuid
......@@ -169,7 +172,7 @@ class NotifyHandler(BaseWebsocket):
# 认证包,认证不通过,则剔除该连接
if message.get("type") == "auth":
if not message.get("token"):
self.write(json.dumps({ "code": 400, "data": None, "msg": "token can not be null" }))
self.write_message(json.dumps({ "code": 400, "data": None, "msg": "token can not be null" }))
return
user = session.query(User).filter(User.id == payload.get("data").get("id")).all()
......@@ -185,7 +188,7 @@ class NotifyHandler(BaseWebsocket):
self._clients.append({
'uuid': payload.get("data").get("uuid"),
'context': self,
'devices': lambda d:d.imei,
'devices': list(map(lambda d:d.imei, devices)),
'ts': int(time.time())
})
self.write_message(json.dumps({ 'code': 200, 'data': None, 'msg': 'auth passed' }))
......@@ -203,18 +206,21 @@ class NotifyHandler(BaseWebsocket):
self.write_message(json.dumps({ 'code': 200, 'data': None, 'msg': 'unkonw message packet, disconnect by server' }))
self.handlers[className].remove(self)
except Exception as e:
self.handlers[className].remove(self)
# 认证失败会导致触发异常,这里不能remove(self),否则会导致on_close方法报错
self.write_message(json.dumps({ 'code': 400, 'data': e.args, 'msg': "server error" }))
logger.error(e)
traceback.print_exc()
logger.info(message)
def on_heartbeat(self):
className = self.__class__.__name__
# 心跳定时器,固定间隔扫描连接列表,当连接超时,主动剔除该连接
for i in range(len(self._clients) - 1, -1, -1):
if int(time.time()) - self._clients[i].get("ts") > 5:
self._clients.remove(self._clients[i])
if self.handlers.get(className, None):
# self._clients.pop(i)
del self._clients[i]
className = self.__class__.__name__
if self.handlers.get(className, None) and self in self.handlers[className]:
logger.info(self.handlers[className])
self.handlers[className].remove(self)
self._timer = Timer(1, self.on_heartbeat)
......@@ -231,15 +237,13 @@ class MainHandler(BaseHandler):
# self.get_query_argument('a', value)
# self.get_body_argument()
# self.request.files
self.write("Hello, world")
self.write(json.dumps({ "msg": "Hello, world" }))
def post(self):
data = tornado.escape.json_decode(self.request.body)
print("=====>", data, type(data))
self.write(json.dumps({ 'code': 100, 'msg': 'success' }))
self.write(json.dumps({ 'code': 100, 'data': data, 'msg': 'success' }))
message = {'imei': '12345678900005', 'system': {'free_size': 0}, 'lvgl': {'total_size': 5242880, 'free_cnt': 31, 'free_size': 1279664, 'free_biggest_size': 1205448, 'used_cnt': 832, 'used_pct': 76, 'frag_pct': 6}, 'evm': {'total_size': 2097152, 'free_size': 0, 'gc_usage': 50}, 'image': [{'uri': 'evue_launcher', 'length': 1043, 'png_total_count': 0, 'png_uncompressed_size': 0, 'png_file_size': 0}, {'uri': 'kdgs_1_storyList', 'length': 9608, 'png_total_count': 193, 'png_uncompressed_size': 370884, 'png_file_size': 209807}]}
message = {'imei': '12345678900005', 'type': 'report', 'system': {'free_size': 0}, 'lvgl': {'total_size': 5242880, 'free_cnt': 31, 'free_size': 1279664, 'free_biggest_size': 1205448, 'used_cnt': 832, 'used_pct': 76, 'frag_pct': 6}, 'evm': {'total_size': 2097152, 'free_size': 0, 'gc_usage': 50}, 'image': [{'uri': 'evue_launcher', 'length': 1043, 'png_total_count': 0, 'png_uncompressed_size': 0, 'png_file_size': 0}, {'uri': 'kdgs_1_storyList', 'length': 9608, 'png_total_count': 193, 'png_uncompressed_size': 370884, 'png_file_size': 209807}]}
insert_data(message)
# 这里不能使用广播,得点对点发送,有此设备的账号才能看到调试信息
NotifyHandler.broadcastMessage(message)
......@@ -303,16 +307,15 @@ class DeviceMessageHandler(BaseHandler):
def post(self):
data = tornado.escape.json_decode(self.request.body)
request = {
data.update({ 'request': {
'host': self.request.remote_ip,
'path': self.request.path,
'protocol': self.request.protocol
}
data.update({ 'request': request })
} })
insert_data(data)
data['type'] = 'report'
data['request'].update({ 'timestamp': datetime.now().strftime("%Y-%m-%d %H:%M:%S") })
NotifyHandler.broadcastMessage(data)
self.write(json.dumps({ 'code': 100, 'message': 'success' }))
......
......@@ -238,7 +238,7 @@ export const constantRoutes = [
path: 'index',
name: 'Monitor',
component: () => import('@/views/system/monitor'),
meta: { title: 'monitor', icon: 'home' }
meta: { title: '资源监视', icon: 'home' }
}]
},
{
......
/*
* @Author: your name
* @Date: 2021-07-01 15:02:16
* @LastEditTime: 2021-07-03 19:50:11
* @LastEditors: Please set LastEditors
* @LastEditTime: 2021-07-05 15:22:36
* @LastEditors: your name
* @Description: In User Settings Edit
* @FilePath: \evm-store\frontend\src\utils\eventBus.js
*/
/*
* @Author: your name
* @Date: 2021-04-14 14:12:19
* @LastEditTime: 2021-07-01 01:11:46
* @LastEditors: Please set LastEditors
* @Description: In User Settings Edit
* @FilePath: \evm-store\frontend\src\utils\wsNotify.js
*/
import Vue from "vue";
import store from "@/store";
......
<template>
<div class="app-container">
<el-form :inline="true" :model="form" ref="query" size="mini">
<el-form :inline="true" ref="query" size="mini">
<el-form-item label="设备">
<el-select
v-model="watch_id"
v-model="device"
filterable
placeholder="请输入设备名称"
@change="onChange"
......@@ -12,7 +12,7 @@
v-for="(item, index) in watchs"
:key="index"
:label="item.imei"
:value="item.id"
:value="item.imei"
></el-option>
</el-select>
</el-form-item>
......@@ -46,12 +46,8 @@ export default {
evmList: [],
lvgl: {},
lvglList: [],
image: [],
image: {},
imageList: [],
form: {
start: null,
end: null,
},
};
},
components: {
......@@ -59,9 +55,6 @@ export default {
LvglChart,
},
methods: {
sendMsg() {
this.socket.send("hello,world");
},
fetchData() {
this.isLoading = true;
getWatchList()
......@@ -69,62 +62,44 @@ export default {
if (res.code == 200) this.watchs = res.data;
})
.catch((err) => {
this.$message.warning(err.msg);
this.$message.warning(err.msg)
})
.finally(() => {
this.isLoading = false;
});
},
queryData() {
let params = {
getMonitorData({
watch: this.watch_id,
};
if (this.value2 && this.value2.length) {
if (this.value2.length > 1) {
params.start = Math.ceil(this.value2[0] / 1000);
params.end = Math.ceil(this.value2[1] / 1000);
} else {
params.start = Math.ceil(this.value2[0] / 1000);
}
}
getMonitorData(params)
})
.then((res) => {
if (res.type == "object") {
this.evmList = res.data.evm
this.lvglList = res.data.lvgl
this.imageList = res.data.image
} else {
if (params.category == "evm") this.evmList = res.data
else if (params.category == "lvgl") this.lvglList = res.data
else if (params.category == "image") this.imageList = res.data
}
})
.catch((err) => {
this.$message.warning(err.msg);
this.$message.warning(err.msg)
});
},
onChange(res) {
if (!res) return null;
var t = this.watchs.find((item) => {
return item.id == res;
});
if (t) this.device = t.imei;
// 清空之前数据
this.processData();
onChange() {
this.processData()
},
onSubmit() {
this.queryData();
this.queryData()
},
onReset(formName) {
this.$refs[formName].resetFields();
this.fetchData();
this.$refs[formName].resetFields()
this.fetchData()
},
handleMessage(message) {
if (!this.device) this.device = message.imei;
this.devices[message.imei] = message;
this.watchs.push({
imei: message.imei,
id: this.watchs.length
})
this.processData()
},
processData() {
......@@ -139,7 +114,6 @@ export default {
created() {
this.socket = wsNotify;
wsNotify.eventBus.$on("open", (message) => {
this.sendMsg();
this.$nextTick(() => {
console.log(message);
});
......@@ -155,8 +129,6 @@ export default {
this.handleMessage(message);
});
});
this.fetchData();
},
};
</script>
......
......@@ -7,6 +7,7 @@ import * as echarts from "echarts";
require("echarts/theme/macarons"); // echarts theme
import resize from "./mixins/resize";
import { getDateTimeString } from "@/utils/utils";
import { wsNotify } from "@/utils/eventBus.js";
// function randomData() {
// now = new Date(+now + oneDay);
......@@ -50,7 +51,7 @@ export default {
},
height: {
type: String,
default: "350px",
default: "270px",
},
autoResize: {
type: Boolean,
......@@ -128,6 +129,10 @@ export default {
this.$nextTick(() => {
this.initChart();
});
wsNotify.eventBus.$on("resize", () => {
if (this.chart) this.chart.resize()
});
},
beforeDestroy() {
if (!this.chart) {
......@@ -202,13 +207,13 @@ export default {
show: false,
},
},
// grid: {
// left: 10,
// right: 10,
// bottom: 20,
// top: 30,
// containLabel: true,
// },
grid: {
left: 10,
right: 10,
bottom: 10,
top: 50,
containLabel: true,
},
tooltip: {
trigger: "axis",
axisPointer: {
......@@ -233,6 +238,11 @@ export default {
},
legend: {
data: this.legendData,
selected: {
heap_total_size: false,
stack_total_size: false,
stack_used_size: false,
},
},
series: this.series,
});
......
......@@ -7,6 +7,7 @@ import * as echarts from "echarts";
require("echarts/theme/macarons"); // echarts theme
import resize from "./mixins/resize";
import { getDateTimeString } from "@/utils/utils";
import { wsNotify } from "@/utils/eventBus.js";
const seriesData = {
frag_pct: [],
......@@ -31,7 +32,7 @@ export default {
},
height: {
type: String,
default: "350px",
default: "270px",
},
autoResize: {
type: Boolean,
......@@ -113,7 +114,7 @@ export default {
data: seriesData.used_cnt,
},
{
name: "used_pctused_pct",
name: "used_pct",
type: "line",
showSymbol: false,
emphasis: {
......@@ -152,6 +153,10 @@ export default {
this.$nextTick(() => {
this.initChart();
});
wsNotify.eventBus.$on("resize", () => {
if (this.chart) this.chart.resize()
});
},
beforeDestroy() {
if (!this.chart) {
......@@ -201,10 +206,17 @@ export default {
title: {
text: "LVGL",
},
grid: {
left: 10,
right: 10,
bottom: 10,
top: 50,
containLabel: true,
},
xAxis: {
type: "time",
splitLine: {
show: false,
},
axisLabel: {
formatter: "{HH}:{mm}:{ss}",
......@@ -214,7 +226,7 @@ export default {
type: "value",
// boundaryGap: [0, "100%"],
splitLine: {
show: false,
},
},
tooltip: {
......@@ -227,6 +239,13 @@ export default {
},
legend: {
data: this.legendData,
selected: {
frag_pct: false,
free_biggest_size: false,
free_cnt: false,
free_size: false,
total_size: false,
},
},
series: this.series,
});
......
<template>
<div class="app-container">
<div>
<el-select
size="mini"
v-model="device"
@change="onSelectChange"
placeholder="请选择设备"
<div style="margin-top: 10px">
<grid-layout
:layout.sync="layout"
:col-num="12"
:row-height="30"
:is-draggable="draggable"
:is-resizable="resizable"
:vertical-compact="true"
:use-css-transforms="true"
@layout-created="layoutCreatedEvent"
@layout-before-mount="layoutBeforeMountEvent"
@layout-mounted="layoutMountedEvent"
@layout-ready="layoutReadyEvent"
@layout-updated="layoutUpdatedEvent"
>
<el-option
v-for="(item, index) in deviceList"
:key="index"
:label="item"
:value="item"
></el-option>
</el-select>
</div>
<h2>REQUEST</h2>
<el-table
element-loading-text="Loading"
:data="request"
size="mini"
border
stripe
fit
highlight-current-row
>
<el-table-column
prop="host"
label="host"
min-width="180"
show-overflow-tooltip
></el-table-column>
<el-table-column
prop="path"
label="path"
min-width="180"
show-overflow-tooltip
></el-table-column>
<el-table-column
prop="timestamp"
label="timestamp"
min-width="180"
show-overflow-tooltip
></el-table-column>
</el-table>
<h2>SYSTEM</h2>
<el-table
element-loading-text="Loading"
:data="system"
size="mini"
border
stripe
fit
highlight-current-row
>
<el-table-column label="imei" min-width="180" show-overflow-tooltip>
<template slot-scope="scope">{{ scope.row.imei }}</template>
</el-table-column>
<el-table-column label="free_size" min-width="180" show-overflow-tooltip>
<template slot-scope="scope">{{ scope.row.free_size }}(KB)</template>
</el-table-column>
</el-table>
<h2>LVGL</h2>
<el-table
element-loading-text="Loading"
:data="lvgl"
size="mini"
border
stripe
fit
highlight-current-row
>
<el-table-column label="total_size" min-width="180" show-overflow-tooltip>
<template slot-scope="scope">{{ scope.row.total_size }}(KB)</template>
</el-table-column>
<el-table-column
prop="free_cnt"
label="free_cnt"
min-width="180"
show-overflow-tooltip
></el-table-column>
<el-table-column label="free_size" min-width="180" show-overflow-tooltip>
<template slot-scope="scope">{{ scope.row.free_size }}(KB)</template>
</el-table-column>
<el-table-column label="free_biggest_size" min-width="180">
<template slot-scope="scope"
>{{ scope.row.free_biggest_size }}(KB)</template
<grid-item
:x="0"
:y="0"
:w="6"
:h="5"
i="1"
@resize="resizeEvent"
@move="moveEvent"
@resized="resizedEvent"
@container-resized="containerResizedEvent"
@moved="movedEvent"
>
</el-table-column>
<el-table-column label="used_cnt" min-width="180">
<template slot-scope="scope">{{ scope.row.used_cnt }}</template>
</el-table-column>
<el-table-column label="used_pct" min-width="180">
<template slot-scope="scope">{{ scope.row.used_pct }}(%)</template>
</el-table-column>
<el-table-column label="frag_pct" min-width="180">
<template slot-scope="scope">{{ scope.row.frag_pct }}(%)</template>
</el-table-column>
</el-table>
<h2>EVM</h2>
<el-table
element-loading-text="Loading"
:data="evm"
size="mini"
border
stripe
fit
highlight-current-row
>
<!-- <el-table-column
label="total_size"
min-width="180"
show-overflow-tooltip
>
<template slot-scope="scope">{{ scope.row.total_size }}(KB)</template>
</el-table-column>
<el-table-column
label="free_size"
min-width="180"
show-overflow-tooltip
>
<template slot-scope="scope">{{ scope.row.free_size }}(KB)</template>
</el-table-column> -->
<el-table-column
label="heap_map_size"
min-width="180"
show-overflow-tooltip
>
<template slot-scope="scope"
>{{ scope.row.heap_map_size }}(KB)</template
<p class="item-title">DEVICE</p>
<div style="padding: 15px">
<el-select
size="mini"
v-model="device"
@change="onSelectChange"
placeholder="请选择设备"
>
<el-option
v-for="(item, index) in deviceList"
:key="index"
:label="item"
:value="item"
></el-option>
</el-select>
</div>
</grid-item>
<grid-item
:x="6"
:y="0"
:w="6"
:h="5"
i="2"
@resize="resizeEvent"
@move="moveEvent"
@resized="resizedEvent"
@container-resized="containerResizedEvent"
@moved="movedEvent"
>
</el-table-column>
<el-table-column
label="heap_total_size"
min-width="180"
show-overflow-tooltip
>
<template slot-scope="scope"
>{{ scope.row.heap_total_size }}(KB)</template
>
</el-table-column>
<el-table-column
label="heap_used_size"
min-width="180"
show-overflow-tooltip
>
<template slot-scope="scope"
>{{ scope.row.heap_used_size }}(KB)</template
<p class="item-title">SYSTEM</p>
<el-table
element-loading-text="Loading"
:data="system"
size="mini"
border
stripe
fit
highlight-current-row
>
<el-table-column
prop="host"
label="host"
min-width="150"
show-overflow-tooltip
></el-table-column>
<el-table-column
prop="path"
label="path"
min-width="150"
show-overflow-tooltip
></el-table-column>
<el-table-column
prop="timestamp"
label="timestamp"
min-width="150"
show-overflow-tooltip
></el-table-column>
<el-table-column label="imei" min-width="150" show-overflow-tooltip>
<template slot-scope="scope">{{ scope.row.imei }}</template>
</el-table-column>
<el-table-column
label="free_size"
min-width="100"
show-overflow-tooltip
>
<template slot-scope="scope"
>{{ scope.row.free_size }}(KB)</template
>
</el-table-column>
</el-table>
</grid-item>
<grid-item
:x="0"
:y="5"
:w="6"
:h="5"
i="3"
@resize="resizeEvent"
@move="moveEvent"
@resized="resizedEvent"
@container-resized="containerResizedEvent"
@moved="movedEvent"
>
</el-table-column>
<el-table-column
label="stack_total_size"
min-width="180"
show-overflow-tooltip
>
<template slot-scope="scope"
>{{ scope.row.stack_total_size }}(KB)</template
<p class="item-title">EVM</p>
<el-table
element-loading-text="Loading"
:data="evmList"
size="mini"
border
stripe
fit
highlight-current-row
>
<el-table-column
label="heap_map_size"
min-width="150"
show-overflow-tooltip
>
<template slot-scope="scope"
>{{ scope.row.heap_map_size }}(KB)</template
>
</el-table-column>
<el-table-column
label="heap_total_size"
min-width="150"
show-overflow-tooltip
>
<template slot-scope="scope"
>{{ scope.row.heap_total_size }}(KB)</template
>
</el-table-column>
<el-table-column
label="heap_used_size"
min-width="150"
show-overflow-tooltip
>
<template slot-scope="scope"
>{{ scope.row.heap_used_size }}(KB)</template
>
</el-table-column>
<el-table-column
label="stack_total_size"
min-width="150"
show-overflow-tooltip
>
<template slot-scope="scope"
>{{ scope.row.stack_total_size }}(KB)</template
>
</el-table-column>
<el-table-column
label="stack_used_size"
min-width="150"
show-overflow-tooltip
>
<template slot-scope="scope"
>{{ scope.row.stack_used_size }}(KB)</template
>
</el-table-column>
</el-table>
</grid-item>
<grid-item
:x="6"
:y="5"
:w="6"
:h="5"
i="4"
@resize="resizeEvent"
@move="moveEvent"
@resized="resizedEvent"
@container-resized="containerResizedEvent"
@moved="movedEvent"
>
</el-table-column>
<el-table-column
label="stack_used_size"
min-width="180"
show-overflow-tooltip
>
<template slot-scope="scope"
>{{ scope.row.stack_used_size }}(KB)</template
<p class="item-title">LVGL</p>
<el-table
element-loading-text="Loading"
:data="lvglList"
size="mini"
border
stripe
fit
highlight-current-row
>
<el-table-column
label="total_size"
min-width="100"
show-overflow-tooltip
>
<template slot-scope="scope"
>{{ scope.row.total_size }}(KB)</template
>
</el-table-column>
<el-table-column
prop="free_cnt"
label="free_cnt"
min-width="100"
show-overflow-tooltip
></el-table-column>
<el-table-column
label="free_size"
min-width="120"
show-overflow-tooltip
>
<template slot-scope="scope"
>{{ scope.row.free_size }}(KB)</template
>
</el-table-column>
<el-table-column label="free_biggest_size" min-width="120">
<template slot-scope="scope"
>{{ scope.row.free_biggest_size }}(KB)</template
>
</el-table-column>
<el-table-column label="used_cnt" min-width="100">
<template slot-scope="scope">{{ scope.row.used_cnt }}</template>
</el-table-column>
<el-table-column label="used_pct" min-width="100">
<template slot-scope="scope"
>{{ scope.row.used_pct }}(%)</template
>
</el-table-column>
<el-table-column label="frag_pct" min-width="100">
<template slot-scope="scope"
>{{ scope.row.frag_pct }}(%)</template
>
</el-table-column>
</el-table>
</grid-item>
<grid-item
:x="0"
:y="10"
:w="12"
:h="7"
i="5"
@resize="resizeEvent"
@move="moveEvent"
@resized="resizedEvent"
@container-resized="containerResizedEvent"
@moved="movedEvent"
>
</el-table-column>
</el-table>
<h2>APP</h2>
<el-table
element-loading-text="Loading"
:data="image"
size="mini"
border
stripe
fit
highlight-current-row
>
<el-table-column
prop="uri"
label="uri"
min-width="180"
show-overflow-tooltip
></el-table-column>
<el-table-column label="length" min-width="180" show-overflow-tooltip>
<template slot-scope="scope">{{ scope.row.length }}(KB)</template>
</el-table-column>
<el-table-column
label="png_file_size"
min-width="180"
show-overflow-tooltip
>
<template slot-scope="scope"
>{{ scope.row.png_file_size }}(KB)</template
<p class="item-title">APP</p>
<el-table
element-loading-text="Loading"
:data="imageList"
size="mini"
border
stripe
fit
highlight-current-row
>
<el-table-column
prop="uri"
label="uri"
min-width="150"
show-overflow-tooltip
></el-table-column>
<el-table-column
label="length"
min-width="150"
show-overflow-tooltip
>
<template slot-scope="scope">{{ scope.row.length }}(KB)</template>
</el-table-column>
<el-table-column
label="png_file_size"
min-width="150"
show-overflow-tooltip
>
<template slot-scope="scope"
>{{ scope.row.png_file_size }}(KB)</template
>
</el-table-column>
<el-table-column
prop="png_total_count"
label="png_total_count"
min-width="150"
show-overflow-tooltip
></el-table-column>
<el-table-column
label="png_uncompressed_size"
min-width="150"
show-overflow-tooltip
>
<template slot-scope="scope"
>{{ scope.row.png_uncompressed_size }}(KB)</template
>
</el-table-column>
</el-table>
</grid-item>
<grid-item
:x="0"
:y="17"
:w="12"
:h="7"
i="6"
@resize="resizeEvent"
@move="moveEvent"
@resized="resizedEvent"
@container-resized="containerResizedEvent"
@moved="movedEvent"
>
</el-table-column>
<el-table-column
prop="png_total_count"
label="png_total_count"
min-width="180"
show-overflow-tooltip
></el-table-column>
<el-table-column
label="png_uncompressed_size"
min-width="180"
show-overflow-tooltip
>
<template slot-scope="scope"
>{{ scope.row.png_uncompressed_size }}(KB)</template
<EvmChart :chartData="evm"></EvmChart>
</grid-item>
<grid-item
:x="0"
:y="24"
:w="12"
:h="7"
i="7"
@resize="resizeEvent"
@move="moveEvent"
@resized="resizedEvent"
@container-resized="containerResizedEvent"
@moved="movedEvent"
>
</el-table-column>
</el-table>
<LvglChart :chartData="lvgl"></LvglChart>
</grid-item>
</grid-layout>
</div>
</div>
</template>
<script>
import { getWatchList, getMonitorData } from "@/api/index";
import EvmChart from "./components/EvmChart";
import LvglChart from "./components/LvglChart";
import { GridLayout, GridItem } from "vue-grid-layout";
import { wsNotify } from "@/utils/eventBus.js";
export default {
name: "Monitor",
data() {
return {
watchs: [],
device: null,
devices: {},
deviceList: [],
deviceList: null,
system: [],
lvgl: [],
evm: [],
image: [],
request: [],
evm: {},
evmList: [],
lvgl: {},
lvglList: [],
image: {},
imageList: [],
socket: null,
form: {
system: ["free_size"],
......@@ -243,24 +362,163 @@ export default {
],
image: ["png_uncompressed_size", "png_file_size", "length"],
},
layout: [
{ x: 0, y: 0, w: 6, h: 5, i: "0", static: false },
{ x: 6, y: 0, w: 6, h: 5, i: "1", static: true },
{ x: 0, y: 5, w: 6, h: 5, i: "2", static: false },
{ x: 6, y: 5, w: 6, h: 5, i: "3", static: false },
{ x: 0, y: 10, w: 12, h: 7, i: "4", static: false },
{ x: 0, y: 17, w: 12, h: 7, i: "4", static: false },
{ x: 0, y: 24, w: 12, h: 7, i: "4", static: false },
],
draggable: true,
resizable: true,
};
},
components: {
GridLayout,
GridItem,
EvmChart,
LvglChart,
},
methods: {
moveEvent (i, newX, newY) {
const msg = "MOVE i=" + i + ", X=" + newX + ", Y=" + newY;
console.log(msg);
},
movedEvent (i, newX, newY) {
const msg = "MOVED i=" + i + ", X=" + newX + ", Y=" + newY;
console.log(msg);
},
resizeEvent (i, newH, newW, newHPx, newWPx) {
const msg =
"RESIZE i=" +
i +
", H=" +
newH +
", W=" +
newW +
", H(px)=" +
newHPx +
", W(px)=" +
newWPx;
console.log(msg);
},
resizedEvent (i, newX, newY, newHPx, newWPx) {
const msg =
"RESIZED i=" +
i +
", X=" +
newX +
", Y=" +
newY +
", H(px)=" +
newHPx +
", W(px)=" +
newWPx;
console.log(msg);
},
containerResizedEvent (i, newH, newW, newHPx, newWPx) {
const msg =
"CONTAINER RESIZED i=" +
i +
", H=" +
newH +
", W=" +
newW +
", H(px)=" +
newHPx +
", W(px)=" +
newWPx;
console.log(msg);
},
layoutCreatedEvent (newLayout) {
console.log("Created layout: ", newLayout);
},
layoutBeforeMountEvent (newLayout) {
console.log("beforeMount layout: ", newLayout);
},
layoutMountedEvent (newLayout) {
console.log("Mounted layout: ", newLayout);
},
layoutReadyEvent (newLayout) {
console.log("Ready layout: ", newLayout);
},
layoutUpdatedEvent (newLayout) {
console.log("Updated layout: ", newLayout);
},
fetchData() {
this.isLoading = true;
getWatchList()
.then((res) => {
if (res.code == 200) this.watchs = res.data;
})
.catch((err) => {
this.$message.warning(err.msg);
})
.finally(() => {
this.isLoading = false;
});
},
queryData() {
getMonitorData({
watch: this.device,
})
.then((res) => {
if (res.type == "object") {
this.evmList = res.data.evm;
this.lvglList = res.data.lvgl;
this.imageList = res.data.image;
}
})
.catch((err) => {
this.$message.warning(err.msg);
});
},
onChange(res) {
if (!res) return null;
var t = this.watchs.find((item) => {
return item.id == res;
});
if (t) this.device = t.imei;
// 清空之前数据
this.resetData();
},
onSubmit() {
this.queryData();
},
onReset(formName) {
this.$refs[formName].resetFields();
this.fetchData();
},
sendMsg() {
let message = JSON.stringify({ type: "auth", token: this.$store.getters.token });
let message = JSON.stringify({
type: "auth",
token: this.$store.getters.token,
});
this.socket.send(message);
},
handleMessage(msg) {
if (!this.deviceList.includes(msg.imei)) {
if (msg.type !== "report") return false;
if (this.deviceList && !this.deviceList.includes(msg.imei)) {
this.deviceList.push(msg.imei);
}
if (!this.device) {
if (!this.device && this.deviceList) {
this.device = this.deviceList[0];
} else {
this.device = msg.imei
}
this.devices[msg.imei] = msg;
this.processData(this.devices[this.device]);
this.resetData();
},
processData(msg) {
console.log(msg)
if (!msg) return null;
Object.keys(msg).forEach((item) => {
if (this.form[item]) {
var keys = this.form[item];
......@@ -277,27 +535,42 @@ export default {
}
});
this.system = [{ imei: msg.imei, ...msg.system }];
this.lvgl = [{ ...msg.lvgl }];
this.evm = [{ ...msg.evm }];
this.request = [{ ...msg.request }];
console.log(msg)
this.evmList = [{ ...msg.evm }];
this.lvglList = [{ ...msg.lvgl }];
this.system = [{ imei: msg.imei, ...msg.system, ...msg.request }];
// 这里需要特殊处理下,先判断uri是否存在,不存在则添加,存在则更新
let uris = [];
this.image.forEach((img) => {
uris.push(img.uri)
this.imageList.forEach((img) => {
uris.push(img.uri);
});
msg.image && msg.image.forEach((item) => {
if (!uris.includes(item.uri)) {
this.image.push(item)
}
});
// this.image = msg.image;
msg.image &&
msg.image.forEach((item) => {
if (!uris.includes(item.uri)) {
this.imageList.push(item);
}
});
// this.imageList = msg.image;
},
onSelectChange(res) {
this.device = res;
this.processData(this.devices[this.device]);
console.log(res);
},
resetData() {
wsNotify.eventBus.$emit("resize");
if (this.devices[this.device]) {
if (this.devices[this.device].evm)
this.evm = this.devices[this.device].evm;
if (this.devices[this.device].lvgl)
this.lvgl = this.devices[this.device].lvgl;
if (this.devices[this.device].image)
this.image = this.devices[this.device].image;
}
}
},
mounted() {},
created() {
......@@ -307,6 +580,7 @@ export default {
this.$nextTick(() => {
console.log(message);
});
// 这里启动一个定时器,10秒钟后,如果没有消息进来,说明当前没有在线设备
});
wsNotify.eventBus.$on("close", (message) => {
this.$nextTick(() => {
......@@ -328,4 +602,64 @@ export default {
margin: 10px 0px;
}
}
.vue-grid-layout {
background: #aaa;
}
.vue-grid-item:not(.vue-grid-placeholder) {
background: #fff;
border: 0px solid #eee;
}
.vue-grid-item .resizing {
opacity: 0.9;
}
.vue-grid-item .static {
background: #cce;
}
.vue-grid-item .text {
font-size: 24px;
text-align: center;
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
margin: auto;
height: 100%;
width: 100%;
}
.vue-grid-item .item-title {
margin-left: 15px;
}
.vue-grid-item .no-drag {
height: 100%;
width: 100%;
}
.vue-grid-item .minMax {
font-size: 12px;
}
.vue-grid-item .add {
cursor: pointer;
}
.vue-draggable-handle {
position: absolute;
width: 20px;
height: 20px;
top: 0;
left: 0;
background: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='10' height='10'><circle cx='5' cy='5' r='5' fill='#999999'/></svg>")
no-repeat;
background-position: bottom right;
padding: 0 8px 8px 0;
background-repeat: no-repeat;
background-origin: content-box;
box-sizing: border-box;
cursor: pointer;
}
.layoutJSON {
background: #ddd;
border: 1px solid black;
margin-top: 10px;
padding: 10px;
}
</style>
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment