Compare commits
6 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 8ef7b4adba | |||
| d60e15be50 | |||
| b6d3646c26 | |||
| a75b7beca9 | |||
| 072fd69201 | |||
| e706c12b31 |
+3
-1
@@ -47,7 +47,9 @@ localforage.config({ name: 'bioprovue' })
|
||||
let MqttUrl
|
||||
// for developer
|
||||
if (process.env.NODE_ENV === 'development') {
|
||||
MqttUrl = 'ws://192.168.5.240:8083'
|
||||
// MqttUrl = 'ws://60.250.195.121:8080' // TODO: if change device, need to change this
|
||||
MqttUrl = 'ws://192.168.5.62:8083' // TODO: if change device, need to change this
|
||||
// MqttUrl = 'ws://192.168.5.240:8083'
|
||||
} else {
|
||||
// for user
|
||||
MqttUrl = `ws://${location.href.split('/')[2]}:8083`
|
||||
|
||||
@@ -61,6 +61,20 @@ export const navigationRoutes = {
|
||||
iconClass: 'vuestic-iconset vuestic-iconset-settings',
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'test',
|
||||
displayName: 'Test',
|
||||
meta: {
|
||||
iconClass: 'vuestic-iconset vuestic-iconset-settings',
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'TaskContent_v2',
|
||||
displayName: 'TaskContent_v2',
|
||||
meta: {
|
||||
iconClass: 'vuestic-iconset vuestic-iconset-statistics',
|
||||
},
|
||||
},
|
||||
// {
|
||||
// name: 'forms',
|
||||
// displayName: 'menu.forms',
|
||||
|
||||
@@ -142,7 +142,8 @@ import { taskInfo } from '@/data/task/TaskInfo'
|
||||
import { FulfillingBouncingCircleSpinner } from 'epic-spinners'
|
||||
|
||||
export default {
|
||||
name: 'devices-overview',
|
||||
name: 'devices-overview', // Q04: this is use for the template can call itself's script?(c.f. line 2: class="devices-overview")
|
||||
// Ans: other component can use this as the name to import this vue file
|
||||
components: {
|
||||
FulfillingBouncingCircleSpinner,
|
||||
},
|
||||
@@ -363,8 +364,8 @@ export default {
|
||||
await update()
|
||||
},
|
||||
mqttSub: function (val) {
|
||||
this.$mqtt.subscribe(val)
|
||||
},
|
||||
this.$mqtt.subscribe(val) // Q06: meaning of $ before the variable: shortcut for jQuery? or udnerscore? then define at where?
|
||||
}, // Q06: search: Vue-Matt
|
||||
mqttUnSub: function (val) {
|
||||
this.$mqtt.unsubscribe(val)
|
||||
},
|
||||
|
||||
@@ -0,0 +1,279 @@
|
||||
<template>
|
||||
<div>
|
||||
<va-card>
|
||||
<div>
|
||||
Current show Time: {{currentTime}} <br>
|
||||
Current Value: {{currentValue}}
|
||||
</div>
|
||||
<chart :options="chart_practice" style="width: auto;"> </chart>
|
||||
</va-card>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { mapFields } from 'vuex-map-fields'
|
||||
|
||||
export default {
|
||||
name: 'devices-overview',
|
||||
components: {
|
||||
},
|
||||
|
||||
data () {
|
||||
return {
|
||||
testData: [],
|
||||
dataBuffMax: 300,
|
||||
dataBuff: [],
|
||||
xAxisBuff: [],
|
||||
dataStart: 0,
|
||||
currentValue: 0,
|
||||
currentTime: '0',
|
||||
// title: [
|
||||
// {
|
||||
// left: 'center',
|
||||
// text: 'Gradient along the y axis'
|
||||
// },
|
||||
// {
|
||||
// top: '55%',
|
||||
// left: 'center',
|
||||
// text: 'Gradient along the x axis'
|
||||
// }
|
||||
// ],
|
||||
chart_practice: {
|
||||
// /*
|
||||
xAxis: [
|
||||
{
|
||||
type: 'category',
|
||||
// type: 'category',
|
||||
data: [],
|
||||
axisLabel: {
|
||||
formatter: function (val) {
|
||||
val = parseInt(val) / 1e6
|
||||
return val.toString() + 's'
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
gridIndex: 1,
|
||||
type: 'category',
|
||||
data: [],
|
||||
// data: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'],
|
||||
},
|
||||
],
|
||||
yAxis: [
|
||||
{
|
||||
type: 'value',
|
||||
// boundaryGap: ['100%', '100%'], // TODO: change the value
|
||||
},
|
||||
{
|
||||
gridIndex: 1,
|
||||
type: 'value',
|
||||
max: '100',
|
||||
min: '0',
|
||||
},
|
||||
],
|
||||
grid: [
|
||||
/*
|
||||
{
|
||||
bottom: '60%',
|
||||
left: '10%',
|
||||
width: 'auto',
|
||||
height: '30%',
|
||||
},
|
||||
{
|
||||
top: '20%',
|
||||
}
|
||||
*/
|
||||
{
|
||||
bottom: '60%',
|
||||
// left: '0%',
|
||||
width: 'auto',
|
||||
},
|
||||
{
|
||||
top: '60%',
|
||||
// bottom: '60%',
|
||||
// right: '0%',
|
||||
width: 'auto',
|
||||
},
|
||||
],
|
||||
series: [
|
||||
{
|
||||
data: [],
|
||||
type: 'line',
|
||||
// smooth: true,
|
||||
},
|
||||
{
|
||||
data: [],
|
||||
type: 'line',
|
||||
xAxisIndex: 1,
|
||||
yAxisIndex: 1,
|
||||
lineStyle: { color: '#d5ceeb' },
|
||||
// smooth: true,
|
||||
},
|
||||
],
|
||||
tooltip: {
|
||||
trigger: 'axis',
|
||||
},
|
||||
// dataZoom: [
|
||||
// {
|
||||
// type: 'slider',//資料滑塊
|
||||
// start: 0,
|
||||
// minSpan: 8, //5min
|
||||
// // minSpan:16, //10min
|
||||
// // minSpan:24, //15min
|
||||
// // minSpan:50, //30min
|
||||
// dataBackground:{
|
||||
// lineStyle:{
|
||||
// color:'#95BC2F'
|
||||
// },
|
||||
// areaStyle:{
|
||||
// color:'#95BC2F',
|
||||
// opacity:1,
|
||||
// }
|
||||
// },
|
||||
// // fillerColor:'rgba(255,255,255,.6)'
|
||||
// },
|
||||
// {
|
||||
// type:'inside'//使滑鼠在圖表中時滾輪可用
|
||||
// }
|
||||
// ],
|
||||
dataZoom: [
|
||||
{
|
||||
id: 'dataZoomX',
|
||||
// type: 'slider',
|
||||
type: 'inside',
|
||||
xAxisIndex: [0],
|
||||
filterMode: 'none',
|
||||
},
|
||||
{
|
||||
id: 'dataZoomY',
|
||||
type: 'inside',
|
||||
yAxisIndex: [0],
|
||||
filterMode: 'none',
|
||||
},
|
||||
],
|
||||
// dataZoom: [
|
||||
// {
|
||||
// type: 'slider',
|
||||
// },
|
||||
// {
|
||||
// type: 'slider',
|
||||
// },
|
||||
// ],
|
||||
},
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
...mapFields('', [
|
||||
'developer_mode',
|
||||
]),
|
||||
...mapFields('taskContent', [
|
||||
'chartData',
|
||||
'taskContentChartKey',
|
||||
]),
|
||||
},
|
||||
methods: {
|
||||
mqttSub: function (val) {
|
||||
this.$mqtt.subscribe(val)
|
||||
},
|
||||
mqttUnSub: function (val) {
|
||||
this.$mqtt.unsubscribe(val)
|
||||
},
|
||||
mqttPub: function (topic, mes) {
|
||||
this.$mqtt.publish(topic, mes)
|
||||
},
|
||||
updateTestDataValue: function () {
|
||||
setInterval(() => {
|
||||
// this.testData = this.testData.splice(1, 6);
|
||||
var today
|
||||
today = new Date().toLocaleTimeString()
|
||||
/*
|
||||
this.chart_practice.series[0].data.shift()
|
||||
this.chart_practice.series[0].data.push(Math.floor(Math.random() * 10)+50)
|
||||
this.chart_practice.xAxis[0].data.shift()
|
||||
this.chart_practice.xAxis[0].data.push(today)
|
||||
*/
|
||||
this.chart_practice.series[1].data.shift()
|
||||
this.chart_practice.series[1].data.push(Math.floor(Math.random() * 10) + 50)
|
||||
this.chart_practice.xAxis[1].data.shift()
|
||||
this.chart_practice.xAxis[1].data.push(today)
|
||||
}, 10)
|
||||
},
|
||||
updateDataValue: function () { // this part is use the mqtt input as buffer, then push it into the series
|
||||
setInterval(() => {
|
||||
if (this.chart_practice.series[0].data.length > this.dataBuffMax) {
|
||||
this.chart_practice.series[0].data.shift()
|
||||
this.chart_practice.xAxis[0].data.shift()
|
||||
}
|
||||
if (this.dataBuff.length > 0) {
|
||||
this.chart_practice.series[0].data.push(this.dataBuff[this.dataStart++])
|
||||
this.chart_practice.xAxis[0].data.push(this.xAxisBuff[this.dataStart++])
|
||||
}
|
||||
}, 10)
|
||||
setInterval(() => {
|
||||
if (this.dataBuff.length > 0) {
|
||||
this.currentValue = this.dataBuff[this.dataStart - 1]
|
||||
this.currentTime = (parseInt(this.xAxisBuff[this.dataStart - 1]) / 1e6).toString() + 's'
|
||||
}
|
||||
}, 1000)
|
||||
},
|
||||
destroyed () {
|
||||
this.mqttUnSub('+/data_server/device_data_stream/+/+')
|
||||
},
|
||||
},
|
||||
mqtt: {
|
||||
async '+/data_server/device_data_stream/+/+' (data, topic) {
|
||||
// console.log(data)
|
||||
// console.log(topic, String.fromCharCode.apply(null, data))
|
||||
var deviceData = String.fromCharCode.apply(null, data)
|
||||
var dataArr = deviceData.split(' ')
|
||||
var startTime = parseInt(dataArr.shift(), 10)
|
||||
var endTime = parseInt(dataArr.pop(), 10)
|
||||
var timeDiff = (endTime - startTime) / dataArr.length
|
||||
var eachTime = startTime - timeDiff
|
||||
dataArr = dataArr.map(Number)
|
||||
console.log(dataArr)
|
||||
// if (this.dataBuff.length > this.dataBuffMax) {
|
||||
// this.dataBuff = this.dataBuff.slice(dataArr.length)
|
||||
// this.xAxisBuff.data = this.xAxisBuff.data.slice(dataArr.length)
|
||||
// }
|
||||
dataArr.forEach(element => {
|
||||
this.dataBuff.push(element)
|
||||
this.xAxisBuff.push(eachTime)
|
||||
eachTime += timeDiff
|
||||
})
|
||||
/*
|
||||
if (this.chart_practice.series[0].data.length > this.dataBuffMax) {
|
||||
this.chart_practice.series[0].data = this.chart_practice.series[0].data.slice(dataArr.length)
|
||||
this.chart_practice.xAxis[0].data = this.chart_practice.xAxis[0].data.slice(dataArr.length)
|
||||
|
||||
}
|
||||
dataArr.forEach(element => {
|
||||
this.chart_practice.series[0].data.push(element)
|
||||
this.chart_practice.xAxis[0].data.push(eachTime)
|
||||
eachTime += timeDiff
|
||||
})
|
||||
*/
|
||||
},
|
||||
},
|
||||
async mounted () {
|
||||
/* --- 7/4 --- */
|
||||
|
||||
var index
|
||||
var today
|
||||
for (index = 0; index < 100; index++) {
|
||||
today = new Date().toLocaleTimeString()
|
||||
// this.chart_practice.series[0].data.push(Math.floor(Math.random() * 10)+50);
|
||||
// this.chart_practice.xAxis[0].data.push(today);
|
||||
this.chart_practice.series[1].data.push(Math.floor(Math.random() * 10) + 50)
|
||||
this.chart_practice.xAxis[1].data.push(today)
|
||||
}
|
||||
this.updateTestDataValue()
|
||||
this.updateDataValue()
|
||||
this.mqttSub('+/data_server/device_data_stream/+/0') // /device/channel
|
||||
},
|
||||
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
</style>
|
||||
@@ -575,6 +575,7 @@ export default {
|
||||
watch: {
|
||||
},
|
||||
async mounted () {
|
||||
console.log(this.$route.params)
|
||||
const devMode = this.$route.params.mode
|
||||
if (devMode === 'dev') {
|
||||
this.developer_mode = true
|
||||
|
||||
@@ -0,0 +1,623 @@
|
||||
<template>
|
||||
<div class="task-content">
|
||||
<!-- <div>
|
||||
{{chartData}}
|
||||
</div> -->
|
||||
<!-- <div>
|
||||
{{chartData[0]}}
|
||||
</div> -->
|
||||
<va-modal
|
||||
v-model="showShutdownModal"
|
||||
size="small"
|
||||
:title="'SHUTDOWN'"
|
||||
:message="'The controller shutdown.'"
|
||||
:okText=" $t('modal.confirm') "
|
||||
@ok="exit()"
|
||||
@cancel="exit()"
|
||||
/>
|
||||
|
||||
<va-modal
|
||||
v-model="showRemoveChartModal"
|
||||
size="small"
|
||||
:title="'REMOVE CHART'"
|
||||
:message="'The chart will be removed.'"
|
||||
:okText=" $t('modal.confirm') "
|
||||
@ok="removeChart(null)"
|
||||
/>
|
||||
|
||||
<div class="row row-equal">
|
||||
<div v-if="showDeviceSetting" class="flex md12 xl4 xs12 sm12">
|
||||
<div class="row">
|
||||
<!-- <div class="flex sm12 xl12 md12 xs12">
|
||||
<task-devices :ref="'devices_ref'" @add="addDevice($event)" @remove="removeDevice($event)" @refreshSetting="refreshChartSetting($event)" class="pa-0" />
|
||||
</div> -->
|
||||
<div class="flex sm12 xl12 md12 xs12">
|
||||
<task-devices-new :ref="'devices_ref'" @add="addDevice($event)" @remove="removeDevice($event)" @refreshSetting="refreshChartSetting($event)" class="pa-0" />
|
||||
</div>
|
||||
<div class="flex sm12 xl12 md12 xs12" v-if="developer_mode">
|
||||
<task-formula :ref="'formula_ref'" @add="addFormula($event)" @remove="removeFormula($event)" class="pa-0" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div :class="chartAreaClass">
|
||||
<div class="row" >
|
||||
<div class="flex sm12 xl12 md12 xs12">
|
||||
<div class="flex sm12 xl12 md12 xs12" style="text-align: center;">
|
||||
<va-card
|
||||
class="ma-0 pa-0"
|
||||
stripe="primary"
|
||||
>
|
||||
<!-- <template slot="header">
|
||||
<va-icon name="fa fa-gears mr-3" color="primary"/>
|
||||
<h5 class="mt-0 mb-0">CONTROL</h5>
|
||||
</template> -->
|
||||
<va-button class="no-dark-style-va-button" v-if="!showDeviceSetting" color="primary" target="_blank" @click="showDeviceSettingClick()" small>
|
||||
SHOW DEVICES
|
||||
</va-button>
|
||||
<va-button class="no-dark-style-va-button" v-if="showDeviceSetting" color="primary" target="_blank" @click="hideDeviceSettingClick()" small>
|
||||
HIDE DEVICES
|
||||
</va-button>
|
||||
<va-button class="" color="success" target="_blank" @click="startAllClick()" small>
|
||||
START ALL
|
||||
</va-button>
|
||||
<va-button class="no-dark-style-va-button" color="danger" target="_blank" @click="stopAllClick()" small>
|
||||
STOP ALL
|
||||
</va-button>
|
||||
<va-button class="no-dark-style-va-button" color="primary" target="_blank" @click.stop="addChart(false)" small>
|
||||
ADD CHART
|
||||
</va-button>
|
||||
</va-card>
|
||||
</div>
|
||||
<div :key="taskContentChartPanelKey">
|
||||
<div
|
||||
v-for="chart in chartData"
|
||||
:key="chart.chartID"
|
||||
>
|
||||
<canvas-chart
|
||||
:id="'chart' + chart.chartID"
|
||||
:ref="'chart_ref'"
|
||||
:cardheight="'400px'"
|
||||
:cardwidth="'auto'"
|
||||
:chartID="chart.chartID"
|
||||
@init="initChart(chart.chartID)"
|
||||
@remove="removeChartCheck(chart.chartID)"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div style="height: 150px;">
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { dataStreamBuffer } from '../../../data/task/DataStreamBuffer'
|
||||
import { taskInfo } from '../../../data/task/TaskInfo'
|
||||
import CanvasChart from './chart/CanvasChart'
|
||||
// import TaskDevices from './controller/TaskDevices'
|
||||
import TaskDevicesNew from './controller/TaskDevicesNew'
|
||||
// import api from '@/data/api'
|
||||
import { mapFields } from 'vuex-map-fields'
|
||||
import { mapActions } from 'vuex'
|
||||
import taskTypes from '@/store/modules/task/content/types'
|
||||
import TaskFormula from './formula/TaskFormula'
|
||||
|
||||
// TODO change chart data tag format
|
||||
|
||||
export default {
|
||||
name: 'TaskContent',
|
||||
components: {
|
||||
CanvasChart,
|
||||
// TaskDevices,
|
||||
TaskDevicesNew,
|
||||
TaskFormula,
|
||||
},
|
||||
computed: {
|
||||
...mapFields('taskContent', [
|
||||
'deviceList',
|
||||
'chartData',
|
||||
'taskContentChartPanelKey',
|
||||
'taskContentChartNumber',
|
||||
'deviceListNew',
|
||||
]),
|
||||
...mapFields('', [
|
||||
'developer_mode',
|
||||
]),
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
// modal
|
||||
showShutdownModal: false,
|
||||
showRemoveChartModal: false,
|
||||
// refresh timer
|
||||
dataRefreshTimer: null,
|
||||
|
||||
selectChartID: null,
|
||||
showDeviceSetting: true,
|
||||
chartAreaClass: ['flex', 'xs12', 'sm12', 'md12', 'xl8', 'pa-0'],
|
||||
getParmDone: false,
|
||||
}
|
||||
},
|
||||
mqtt: {
|
||||
async '+/get_device_info_all/+' (data, topic) {
|
||||
// console.log('get_device_info_all', String.fromCharCode.apply(null, data))
|
||||
this.deviceListNew = JSON.parse(String.fromCharCode.apply(null, data)).data
|
||||
|
||||
// console.log(this.deviceListNew)
|
||||
// await taskInfo.deviceInfo(String.fromCharCode.apply(null, data), this.deviceList)
|
||||
// console.log('this.deviceList 0', this.deviceList)
|
||||
// this.refreshDevicesWindow()
|
||||
// console.log('this.$refs.devices_ref', this.$refs.devices_ref)
|
||||
if (this.$refs.devices_ref != null) {
|
||||
await this.$refs.devices_ref.loadingDone()
|
||||
}
|
||||
await this.taskContentChartInitCustomizedFromCache()
|
||||
this.getParmDone = true
|
||||
},
|
||||
async '+/get_device_info/+' (data, topic) {
|
||||
// const dataObj = JSON.parse(String.fromCharCode.apply(null, data))
|
||||
// await taskInfo.deviceInfo(dataObj, this.deviceList)
|
||||
// this.refreshDevicesWindow()
|
||||
// this.checkStiStatus()
|
||||
|
||||
// const result = await this.taskContentChartDefaultChartGenerator({
|
||||
// _deviceList: this.deviceList,
|
||||
// _itemID: taskInfo.getDeviceIDByRaw(dataObj.data.device_id),
|
||||
// _chartID: null,
|
||||
// _type: 'device',
|
||||
// })
|
||||
// if (result) {
|
||||
// taskInfo.deviceStart(dataObj.data.device_id, this.deviceList)
|
||||
// }
|
||||
},
|
||||
async '+/device_parameter/+' (data, topic) {
|
||||
const res = JSON.parse(String.fromCharCode.apply(null, data))
|
||||
const device = this.deviceListNew.find((ele) => ele.mac_address === res.device)
|
||||
|
||||
for (const key of Object.keys(res.data)) {
|
||||
device.configuration[key] = res.data[key]
|
||||
}
|
||||
// await taskInfo.deviceParameter(String.fromCharCode.apply(null, data))
|
||||
// this.refreshDevicesWindow()
|
||||
},
|
||||
async '+/device_parameter_value/+' (data, topic) {
|
||||
const res = JSON.parse(String.fromCharCode.apply(null, data))
|
||||
const device = this.deviceListNew.find((ele) => ele.mac_address === res.device)
|
||||
|
||||
for (const key of Object.keys(res.data)) {
|
||||
device.configuration[key] = res.data[key]
|
||||
}
|
||||
},
|
||||
async '+/hardware_device/+' (data, topic) {
|
||||
await taskInfo.deviceInfo(String.fromCharCode.apply(null, data), this.deviceList)
|
||||
if (this.$refs.devices_ref != null) {
|
||||
await this.$refs.devices_ref.loadingDone()
|
||||
await this.taskContentChartInitCustomizedFromCache()
|
||||
}
|
||||
},
|
||||
// listen datastream [ topic: controllerID/data_server/device_data_stream/deviceID/channel ]
|
||||
async '+/data_server/device_data_stream/+/+' (data, topic) {
|
||||
const topicSplit = topic.split('/')
|
||||
const deviceID = parseInt(topicSplit[3])
|
||||
const channel = parseInt(topicSplit[4])
|
||||
|
||||
dataStreamBuffer.into(String.fromCharCode.apply(null, data), deviceID, (channel + 1))
|
||||
},
|
||||
'+/device_save_path/+' (data, topic) {
|
||||
taskInfo.deviceSavePath(String.fromCharCode.apply(null, data))
|
||||
// console.log(taskInfo.getTaskInfo())
|
||||
},
|
||||
'+/device_save_path_set/+' (data, topic) {
|
||||
taskInfo.deviceSavePath(String.fromCharCode.apply(null, data))
|
||||
// console.log(taskInfo.getTaskInfo())
|
||||
},
|
||||
async '+/device_sd_card_status/+' (data, topic) {
|
||||
const dataDecode = JSON.parse(String.fromCharCode.apply(null, data))
|
||||
for (const device of this.$refs.devices_ref.deviceList) {
|
||||
if (dataDecode.device === taskInfo.getRawDeviceID(device.id)) {
|
||||
device.sdCardStatus = dataDecode.data
|
||||
}
|
||||
}
|
||||
await taskInfo.updateSdCardStatus(String.fromCharCode.apply(null, data))
|
||||
this.refreshDevicesWindow()
|
||||
},
|
||||
async '+/broadcast' (data, topic) {
|
||||
const mes = String.fromCharCode.apply(null, data).split(':')
|
||||
let device
|
||||
// let content
|
||||
switch (mes[0]) {
|
||||
case 'state':
|
||||
switch (mes[1]) {
|
||||
case 'device_available':
|
||||
this.mqttPub(taskInfo.getTaskInfo().controllerID + '_user', JSON.stringify({
|
||||
header: 'hardware_device/0',
|
||||
}))
|
||||
break
|
||||
}
|
||||
break
|
||||
case 'disconnected':
|
||||
taskInfo.deviceDisconnected(mes[1])
|
||||
this.mqttPub(taskInfo.getTaskInfo().controllerID + '_user', JSON.stringify({
|
||||
header: 'get_device_info/0',
|
||||
device: parseInt(mes[1]),
|
||||
}))
|
||||
break
|
||||
case 'connected':
|
||||
this.mqttPub(taskInfo.getTaskInfo().controllerID + '_user', JSON.stringify({
|
||||
header: 'get_device_info/0',
|
||||
device: parseInt(mes[1]),
|
||||
}))
|
||||
taskInfo.deviceConnected(mes[1])
|
||||
break
|
||||
case 'shutdown':
|
||||
taskInfo.controllerShutdown(this.deviceList)
|
||||
this.showShutdownModal = true
|
||||
break
|
||||
case 'start':
|
||||
await this.taskContentChartDefaultChartGenerator({
|
||||
_deviceList: this.deviceListNew,
|
||||
_itemID: parseInt(mes[1]),
|
||||
_chartID: null,
|
||||
_type: 'device',
|
||||
})
|
||||
device = this.deviceListNew.find((ele) => ele.memory_board === parseInt(mes[1]))
|
||||
device.status = 1
|
||||
break
|
||||
case 'stop':
|
||||
if (mes[1] === 'all') {
|
||||
return false
|
||||
}
|
||||
device = this.deviceListNew.find((ele) => ele.memory_board === parseInt(mes[1]))
|
||||
device.status = 0
|
||||
await dataStreamBuffer.removeByDevice(parseInt(mes[1]))
|
||||
break
|
||||
case 'device_timeout':
|
||||
this.pageToast('The device [' + taskInfo.getDeviceIDByRaw(parseInt(mes[1])) + '] is timeout, please check its status or parameters.')
|
||||
break
|
||||
case 'device_mission_done':
|
||||
this.mqttPub(taskInfo.getTaskInfo().controllerID + '_user', JSON.stringify({
|
||||
header: 'device_instruction/0',
|
||||
device: parseInt(mes[1]),
|
||||
instruction: 'interrupt',
|
||||
}))
|
||||
this.pageToast('The device [' + taskInfo.getDeviceIDByRaw(parseInt(mes[1])) + '] mission is done.')
|
||||
break
|
||||
default:
|
||||
break
|
||||
}
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
mqttSub: function (val) {
|
||||
this.$mqtt.subscribe(val)
|
||||
},
|
||||
mqttUnSub: function (val) {
|
||||
this.$mqtt.unsubscribe(val)
|
||||
},
|
||||
mqttPub: function (topic, mes) {
|
||||
this.$mqtt.publish(topic, mes)
|
||||
},
|
||||
pageMqttSub: function (id) {
|
||||
this.mqttSub(id + '/hardware_device/+')
|
||||
this.mqttSub(id + '/broadcast')
|
||||
this.mqttSub(id + '/get_device_info_all/+')
|
||||
this.mqttSub(id + '/get_device_info/+')
|
||||
this.mqttSub(id + '/device_parameter/+')
|
||||
this.mqttSub(id + '/device_parameter_value/+')
|
||||
this.mqttSub(id + '/device_sd_card_status/+')
|
||||
},
|
||||
pageMqttUnSub: function (id) {
|
||||
for (const device in taskInfo.getTaskInfo().deviceList) {
|
||||
this.mqttUnSub(id + '/data_server/device_data_stream/' + device + '/+')
|
||||
}
|
||||
this.mqttUnSub(id + '/hardware_device/+')
|
||||
this.mqttUnSub(id + '/broadcast')
|
||||
this.mqttUnSub(id + '/get_device_info_all/+')
|
||||
this.mqttUnSub(id + '/get_device_info/+')
|
||||
this.mqttUnSub(id + '/device_parameter/+')
|
||||
this.mqttUnSub(id + '/device_parameter_value/+')
|
||||
this.mqttUnSub(id + '/device_sd_card_status/+')
|
||||
},
|
||||
pageInit: async function () {
|
||||
if (await this.$refs.devices_ref != null) {
|
||||
await this.$refs.devices_ref.loadingStart()
|
||||
}
|
||||
console.log(taskInfo.getTaskInfo().controllerID)
|
||||
this.mqttPub(taskInfo.getTaskInfo().controllerID + '_user', JSON.stringify({
|
||||
header: 'get_device_info_all/0',
|
||||
}))
|
||||
|
||||
this.taskContentChartNumber = Object.keys(this.chartData).length
|
||||
},
|
||||
pageToast: function (mes) {
|
||||
this.showToast(
|
||||
mes,
|
||||
{
|
||||
icon: 'fa-bell',
|
||||
position: 'bottom-right',
|
||||
duration: 4000,
|
||||
},
|
||||
)
|
||||
},
|
||||
refreshData: function () {
|
||||
// TODO don't need to refresh chart with stop status
|
||||
for (const chart in this.chartData) {
|
||||
// console.log(this.chartData[0]["data"])
|
||||
this.taskContentChartRefreshData({
|
||||
chartID: parseInt(chart),
|
||||
deviceList: this.deviceListNew,
|
||||
})
|
||||
}
|
||||
},
|
||||
refreshDevicesWindow: function () {
|
||||
// console.log(taskInfo.getTaskInfo())
|
||||
if (this.$refs.devices_ref != null) {
|
||||
this.$refs.devices_ref.refresh()
|
||||
}
|
||||
},
|
||||
addChart: async function (isDefault) {
|
||||
this.taskContentChartAdd({
|
||||
chartID: this.taskContentChartNumber,
|
||||
maxDots: 4000,
|
||||
gridLength: 1,
|
||||
})
|
||||
if (this.$refs.chart_ref != null) {
|
||||
this.$refs.chart_ref.forEach(ref => {
|
||||
ref.refreshMappingSelect()
|
||||
})
|
||||
}
|
||||
this.taskContentChartRefreshPanel()
|
||||
this.taskContentChartNumber++
|
||||
|
||||
if (!isDefault) {
|
||||
await this.taskContentChartSaveToCache()
|
||||
}
|
||||
this.pageToast('The chart has been added.')
|
||||
|
||||
return this.taskContentChartNumber - 1
|
||||
},
|
||||
refreshChartSetting: async function () {
|
||||
if (this.$refs.chart_ref != null) {
|
||||
this.$refs.chart_ref.forEach(ref => {
|
||||
ref.refreshMappingSelect()
|
||||
})
|
||||
}
|
||||
this.taskContentChartRefreshPanel()
|
||||
},
|
||||
initChart: function (chartID) {
|
||||
this.taskContentChartReset({
|
||||
chartID: chartID,
|
||||
mappingID: null,
|
||||
cardName: null,
|
||||
})
|
||||
this.pageToast('The chart has been Initialized.')
|
||||
},
|
||||
removeChartCheck: function (chartID) {
|
||||
this.selectChartID = chartID
|
||||
this.showRemoveChartModal = true
|
||||
},
|
||||
removeChart: async function (chartID) {
|
||||
if (chartID == null) {
|
||||
chartID = this.selectChartID
|
||||
}
|
||||
dataStreamBuffer.removeByChart(chartID)
|
||||
if (this.chartData[chartID] != null) {
|
||||
const defaultID = {}
|
||||
const update = async () => {
|
||||
for (const chart in this.chartData) {
|
||||
if (chart !== chartID) {
|
||||
defaultID[chart] = this.chartData[chart].mappingID
|
||||
}
|
||||
}
|
||||
delete this.chartData[chartID]
|
||||
}
|
||||
await update()
|
||||
|
||||
for (const chart in this.chartData) {
|
||||
this.chartData[chart].mappingID = defaultID[chart]
|
||||
}
|
||||
|
||||
if (this.$refs.chart_ref != null) {
|
||||
this.$refs.chart_ref.forEach(ref => {
|
||||
ref.refreshMappingSelect()
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
await this.taskContentChartSaveToCache()
|
||||
this.pageToast('The chart has been removed.')
|
||||
},
|
||||
showDeviceSettingClick: function () {
|
||||
this.showDeviceSetting = true
|
||||
this.chartAreaClass[3] = 'md12'
|
||||
this.chartAreaClass[4] = 'xl8'
|
||||
},
|
||||
hideDeviceSettingClick: function () {
|
||||
this.showDeviceSetting = false
|
||||
this.chartAreaClass[3] = 'md12'
|
||||
this.chartAreaClass[4] = 'xl12'
|
||||
},
|
||||
addMappingChart: async function (deviceID) {
|
||||
// if have chart with device ID
|
||||
for (const chart in this.chartData) {
|
||||
if (this.chartData[chart].mappingID === deviceID) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
const chart = await this.addChart(true)
|
||||
await this.$nextTick(async () => {
|
||||
this.chartData[chart].mappingID = deviceID
|
||||
if (this.$refs.chart_ref != null) {
|
||||
this.$refs.chart_ref.forEach(ref => {
|
||||
ref.refreshMappingSelect()
|
||||
})
|
||||
}
|
||||
})
|
||||
return chart
|
||||
},
|
||||
addDevice: async function (deviceID, memoryBoardID) {
|
||||
this.mqttSub(`${taskInfo.getTaskInfo().controllerID}/data_server/device_data_stream/${deviceID}/+`)
|
||||
await this.addMappingChart(deviceID)
|
||||
|
||||
await this.taskContentChartDefaultChartGenerator({
|
||||
_deviceList: this.deviceListNew,
|
||||
_itemID: deviceID,
|
||||
_chartID: null,
|
||||
_type: 'device',
|
||||
})
|
||||
this.pageToast('The device [' + deviceID + '] has been registered.')
|
||||
},
|
||||
removeDevice: function (deviceID) {
|
||||
this.mqttUnSub(taskInfo.getTaskInfo().controllerID + '/data_server/device_data_stream/' + deviceID + '/+')
|
||||
for (const chart in this.chartData) {
|
||||
if (this.chartData[chart].mappingID === deviceID) {
|
||||
dataStreamBuffer.removeByChart(chart)
|
||||
this.removeChart(chart)
|
||||
}
|
||||
}
|
||||
this.pageToast('The device [' + deviceID + '] has been removed.')
|
||||
},
|
||||
addFormula: async function (formulaID) {
|
||||
const chart = await this.addChart(true)
|
||||
await this.$nextTick(async () => {
|
||||
this.chartData[chart].mappingID = formulaID
|
||||
if (this.$refs.chart_ref != null) {
|
||||
this.$refs.chart_ref.forEach(ref => {
|
||||
ref.refreshMappingSelect()
|
||||
})
|
||||
}
|
||||
})
|
||||
this.pageToast('The formula [' + formulaID + '] has been registered.')
|
||||
},
|
||||
removeFormula: function (formulaID) {
|
||||
for (const chart in this.chartData) {
|
||||
if (this.chartData[chart].mappingID === formulaID) {
|
||||
dataStreamBuffer.removeByChart(chart)
|
||||
this.removeChart(chart)
|
||||
}
|
||||
}
|
||||
this.pageToast('The formula [' + formulaID + '] has been removed.')
|
||||
},
|
||||
startAllClick: async function () {
|
||||
for (const device of this.deviceListNew) {
|
||||
if (this.$refs.devices_ref === undefined) {
|
||||
this.startDevice(device)
|
||||
} else {
|
||||
await this.$refs.devices_ref.$refs.pdlist_ref.start(device)
|
||||
}
|
||||
}
|
||||
this.refreshDevicesWindow()
|
||||
this.pageToast('The all devices have been started')
|
||||
},
|
||||
startDevice: async function (device) {
|
||||
await this.taskContentChartDefaultChartGenerator({
|
||||
_deviceList: this.deviceList,
|
||||
_itemID: device.id,
|
||||
_chartID: null,
|
||||
_type: 'device',
|
||||
})
|
||||
if (device.status === 0) {
|
||||
this.mqttPub(taskInfo.getTaskInfo().controllerID + '_user', JSON.stringify({
|
||||
header: 'device_instruction/0',
|
||||
device: device.memory_board,
|
||||
instruction: 'start',
|
||||
}))
|
||||
device.status = 1
|
||||
}
|
||||
},
|
||||
stopAllClick: function () {
|
||||
for (const device of this.deviceListNew) {
|
||||
if (this.$refs.devices_ref === undefined) {
|
||||
this.stopDevice(device)
|
||||
} else {
|
||||
this.$refs.devices_ref.stopDevice(device)
|
||||
}
|
||||
}
|
||||
this.pageToast('The all devices have been stopped')
|
||||
},
|
||||
stopDevice: async function (device) {
|
||||
dataStreamBuffer.removeByDevice(device.id)
|
||||
if (device.status === 1) {
|
||||
this.mqttPub(taskInfo.getTaskInfo().controllerID + '_user', JSON.stringify({
|
||||
header: 'device_instruction/0',
|
||||
device: device.memory_board,
|
||||
instruction: 'interrupt',
|
||||
}))
|
||||
device.status = 0
|
||||
}
|
||||
},
|
||||
checkStiStatus: function () {
|
||||
this.$refs.devices_ref.checkStiStatus()
|
||||
},
|
||||
exit: function () {
|
||||
this.$router.push({
|
||||
path: '/',
|
||||
})
|
||||
},
|
||||
|
||||
...mapActions('taskContent', [
|
||||
taskTypes.chart.initCustomizedFromCache,
|
||||
taskTypes.chart.saveToCache,
|
||||
taskTypes.chart.add,
|
||||
taskTypes.chart.defaultChartGenerator,
|
||||
taskTypes.chart.reset,
|
||||
taskTypes.chart.refreshData,
|
||||
taskTypes.chart.refreshChart,
|
||||
taskTypes.chart.refreshPanel,
|
||||
]),
|
||||
},
|
||||
watch: {
|
||||
},
|
||||
async mounted () {
|
||||
console.log(this.$route.params)
|
||||
const devMode = this.$route.params.mode
|
||||
if (devMode === 'dev') {
|
||||
this.developer_mode = true
|
||||
}
|
||||
|
||||
await taskInfo.updateTaskInfo(this.$route.params.taskID)
|
||||
this.pageMqttSub(taskInfo.getTaskInfo().controllerID)
|
||||
await this.pageInit()
|
||||
|
||||
this.dataRefreshTimer = setInterval(this.refreshData, 100)
|
||||
},
|
||||
destroyed () {
|
||||
taskInfo.destroyed(this.deviceList)
|
||||
for (const chart in this.chartData) {
|
||||
this.removeChart(chart)
|
||||
}
|
||||
clearInterval(this.dataRefreshTimer)
|
||||
this.pageMqttUnSub(taskInfo.getTaskInfo().controllerID)
|
||||
},
|
||||
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
// .area-style {
|
||||
// height: 100%;
|
||||
// overflow-y: hidden;
|
||||
// overflow-x: hidden;
|
||||
|
||||
// @include media-breakpoint-only(xl) {
|
||||
// height: 94vh;
|
||||
// overflow-y: scroll;
|
||||
// overflow-x: hidden;
|
||||
// }
|
||||
// }
|
||||
|
||||
.no-dark-style-va-button {
|
||||
&:focus {
|
||||
filter: brightness(100%);
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -26,6 +26,7 @@
|
||||
</va-tabs>
|
||||
<div v-if="tabValue == 0" >
|
||||
<div v-if="chartData[chartID].legend.data.length != 0">
|
||||
<div>{{data.series[0].data}}<br><br><br></div>
|
||||
<chart :key="taskContentChartKey" :ref="'chart_ref'" :style="'width: '+ cardwidth + '; height: ' + cardheight + ';'" :options="data" :auto-resize="true"></chart>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
+14
-14
@@ -19,7 +19,7 @@ export default new Router({
|
||||
path: '*',
|
||||
redirect: { name: 'devices' },
|
||||
},
|
||||
{
|
||||
{ // Q01: how to build a boundary of one {} scope
|
||||
path: '/auth',
|
||||
component: AuthLayout,
|
||||
children: [
|
||||
@@ -88,8 +88,8 @@ export default new Router({
|
||||
},
|
||||
{
|
||||
name: 'Admin',
|
||||
path: '/admin/:mode?',
|
||||
component: AppLayout,
|
||||
path: '/admin/:mode?', // Q03: ":mode?" meaning? is for the path can cat something or not?(e.g. /#/Admin/dev/task-content) => dev will be the variable, see TaskContent => can pick the mode as ID to mounted inside the URL
|
||||
component: AppLayout, // Q05: trace the AppLayout
|
||||
children: [
|
||||
{
|
||||
name: 'dashboard',
|
||||
@@ -119,9 +119,19 @@ export default new Router({
|
||||
},
|
||||
{
|
||||
name: 'task-content',
|
||||
path: 'task-content/:taskID?',
|
||||
path: 'task-content/:taskID?', /// Trace: '/:taskID?' is for getting the value directly from the URL
|
||||
component: () => import('../components/task/content/TaskContent.vue'),
|
||||
},
|
||||
{
|
||||
name: 'test',
|
||||
path: 'test', // this is the url for the user call
|
||||
component: () => import('../components/devices/test.vue'), // this is the router for the redirect page
|
||||
},
|
||||
{
|
||||
name: 'TaskContent_v2',
|
||||
path: 'TaskContent_v2', // this is the url for the user call
|
||||
component: () => import('../components/task/content/TaskContent_v2.vue'), // this is the router for the redirect page
|
||||
},
|
||||
// {
|
||||
// name: 'task-content-g-m',
|
||||
// path: 'task-content-g-m/',
|
||||
@@ -148,16 +158,6 @@ export default new Router({
|
||||
path: 'project',
|
||||
component: () => import('../components/project/Project.vue'),
|
||||
},
|
||||
{
|
||||
name: 'developer',
|
||||
path: 'developer',
|
||||
component: () => import('../components/developer/Developer.vue'),
|
||||
},
|
||||
{
|
||||
name: 'debug',
|
||||
path: 'debug',
|
||||
component: () => import('../components/debug/Debug.vue'),
|
||||
},
|
||||
{
|
||||
name: 'statistics',
|
||||
path: 'statistics',
|
||||
|
||||
Reference in New Issue
Block a user