Compare commits

...

6 Commits

Author SHA1 Message Date
108000207 8ef7b4adba 7/1~7/4 practice 2022-07-07 09:44:14 +08:00
108000207 d60e15be50 add show the current value and time 2022-07-07 09:32:01 +08:00
108000207 b6d3646c26 7/6: start 2022-07-06 09:52:36 +08:00
108000207 a75b7beca9 7/4: echart practice; 7/5: connect mqtt 2022-07-06 09:39:32 +08:00
108000207 072fd69201 echart practice 2022-07-04 17:43:23 +08:00
108000207 e706c12b31 Merge remote-tracking branch 'origin/release/v1.2.4/develop_env_var' into trace_code_for_intern 2022-07-01 13:02:11 +08:00
8 changed files with 939 additions and 18 deletions
+3 -1
View File
@@ -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',
+4 -3
View File
@@ -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)
},
+279
View File
@@ -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
View File
@@ -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',