Compare commits
39 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| e204d0c041 | |||
| 94696e4fa8 | |||
| 37b402e1f7 | |||
| e66d3ad0cd | |||
| bae437c26b | |||
| 4295fc02e2 | |||
| 2ef4b4b393 | |||
| 93c4692dc0 | |||
| f92f4ebb6c | |||
| 65ca86b38d | |||
| 5d3da784cb | |||
| 8d05136dcc | |||
| 8c2c33fdd0 | |||
| 3c5596144f | |||
| 02eae10c82 | |||
| 9976903789 | |||
| 7ce9b2408b | |||
| 764d62dc9c | |||
| dba3e118f4 | |||
| 8c53573857 | |||
| 9a77e6dcff | |||
| c8644f320a | |||
| 8b6348e77e | |||
| 48555dd793 | |||
| 02617bbb86 | |||
| 5328bd76ba | |||
| 9d19fd3fc9 | |||
| 1e2bf182bf | |||
| 288f9b325c | |||
| e4a8f1e8d3 | |||
| 48ce6e6342 | |||
| 7f0564a3ca | |||
| aa9c8c21b7 | |||
| 0924c20e9e | |||
| a239223361 | |||
| e0341356c8 | |||
| b56c753063 | |||
| 04741d8a77 | |||
| 3721e4a515 |
Generated
+11
-4
@@ -3739,6 +3739,14 @@
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"pako": "~1.0.5"
|
||||
},
|
||||
"dependencies": {
|
||||
"pako": {
|
||||
"version": "1.0.11",
|
||||
"resolved": "https://registry.npmjs.org/pako/-/pako-1.0.11.tgz",
|
||||
"integrity": "sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==",
|
||||
"dev": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"browserslist": {
|
||||
@@ -12486,10 +12494,9 @@
|
||||
"dev": true
|
||||
},
|
||||
"pako": {
|
||||
"version": "1.0.11",
|
||||
"resolved": "https://registry.npmjs.org/pako/-/pako-1.0.11.tgz",
|
||||
"integrity": "sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==",
|
||||
"dev": true
|
||||
"version": "2.0.4",
|
||||
"resolved": "https://registry.npmjs.org/pako/-/pako-2.0.4.tgz",
|
||||
"integrity": "sha512-v8tweI900AUkZN6heMU/4Uy4cXRc2AYNRggVmTR+dEncawDJgCdLMximOVA2p4qO57WMynangsfGRb5WD6L1Bg=="
|
||||
},
|
||||
"parallel-transform": {
|
||||
"version": "1.2.0",
|
||||
|
||||
@@ -39,6 +39,7 @@
|
||||
"medium-editor": "^5.23.3",
|
||||
"normalize.css": "^8.0.1",
|
||||
"nprogress": "^0.2.0",
|
||||
"pako": "^2.0.4",
|
||||
"popper.js": "^1.16.0",
|
||||
"regenerator-runtime": "^0.13.3",
|
||||
"register-service-worker": "^1.6.2",
|
||||
|
||||
+2
-2
@@ -58,9 +58,9 @@ Vue.use(VueAxios, axios)
|
||||
Vue.use(Toast)
|
||||
|
||||
// Vue.use(VueMqtt, 'ws://52.194.17.114:8083')
|
||||
Vue.use(VueMqtt, 'ws://' + location.href.split('/')[2] + ':8083')
|
||||
// Vue.use(VueMqtt, 'ws://' + location.href.split('/')[2] + ':8083')
|
||||
// Vue.use(VueMqtt, 'ws://' + '192.168.151.125' + ':8083')
|
||||
// Vue.use(VueMqtt, 'ws://' + '192.168.3.211' + ':8083')
|
||||
Vue.use(VueMqtt, 'ws://' + '192.168.3.211' + ':8083')
|
||||
|
||||
Vue.prototype.GLOBAL = global_
|
||||
|
||||
|
||||
@@ -46,58 +46,6 @@ export default {
|
||||
description: '800',
|
||||
},
|
||||
],
|
||||
neuliveSampleRateOptions: [
|
||||
{
|
||||
id: 0,
|
||||
value: 1000,
|
||||
description: '1k',
|
||||
},
|
||||
{
|
||||
id: 1,
|
||||
value: 2000,
|
||||
description: '2k',
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
value: 4000,
|
||||
description: '4k',
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
value: 5000,
|
||||
description: '5k',
|
||||
},
|
||||
{
|
||||
id: 4,
|
||||
value: 8000,
|
||||
description: '8k',
|
||||
},
|
||||
{
|
||||
id: 5,
|
||||
value: 10000,
|
||||
description: '10k',
|
||||
},
|
||||
{
|
||||
id: 6,
|
||||
value: 20000,
|
||||
description: '20k',
|
||||
},
|
||||
{
|
||||
id: 7,
|
||||
value: 40000,
|
||||
description: '40k',
|
||||
},
|
||||
{
|
||||
id: 8,
|
||||
value: 80000,
|
||||
description: '80k',
|
||||
},
|
||||
{
|
||||
id: 9,
|
||||
value: 100000,
|
||||
description: '100k',
|
||||
},
|
||||
],
|
||||
stimulateElectrodeOptions: [
|
||||
{
|
||||
label: 'Monopolar',
|
||||
@@ -351,11 +299,7 @@ export default {
|
||||
}
|
||||
} else if (key === 'SAMPLE_RATE') {
|
||||
showKey = 'Sample Rate'
|
||||
for (let i = 0; i < this.neuliveSampleRateOptions.length; i++) {
|
||||
if (this.neuliveSampleRateOptions[i].value === value) {
|
||||
showValue = this.neuliveSampleRateOptions[i].description
|
||||
}
|
||||
}
|
||||
showValue = value
|
||||
}
|
||||
this.content += ' ' + showKey + ': ' + showValue + '<br/>'
|
||||
}
|
||||
|
||||
@@ -38,7 +38,7 @@
|
||||
|
||||
<div class="row flex">
|
||||
<div
|
||||
class="flex sm12 xl6 md12 xs12 ma-0"
|
||||
class="flex sm12 xl12 md12 xs12 ma-0"
|
||||
v-for="device in controller.devices" :key="device.addr"
|
||||
>
|
||||
<div v-if="!controller.isScan || device.status == 'connected'">
|
||||
@@ -94,6 +94,35 @@
|
||||
</va-card>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="flex sm12 xl6 md12 xs12 ma-0"
|
||||
v-for="trigger in triggerList" :key="trigger.mac"
|
||||
>
|
||||
<div v-if="!controller.isScan">
|
||||
<va-card
|
||||
style="background-color: #f8f8f8; box-shadow: 5px 5px 0 0 #f1f1f1;"
|
||||
class="ma-0 pa-0"
|
||||
>
|
||||
<va-item :key="trigger.mac" class="pa-0 ma-0"
|
||||
>
|
||||
<!-- <va-item-section avatar class="ml-1">
|
||||
<va-avatar style="border-radius: 0;">
|
||||
<img :src="trigger.pic" :alt="trigger.name">
|
||||
</va-avatar>
|
||||
</va-item-section> -->
|
||||
<va-item-section class="ml-3">
|
||||
<va-item-label>
|
||||
{{ trigger.name }}
|
||||
<va-badge class="px-1 py-0 ml-2 mt-0" color="success">connected</va-badge>
|
||||
</va-item-label>
|
||||
<va-item-label caption>
|
||||
{{ trigger.mac }}
|
||||
</va-item-label>
|
||||
</va-item-section>
|
||||
</va-item>
|
||||
</va-card>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -140,12 +169,18 @@
|
||||
import api from '@/data/api/index'
|
||||
import { taskInfo } from '@/data/task/TaskInfo'
|
||||
import { FulfillingBouncingCircleSpinner } from 'epic-spinners'
|
||||
import { mapFields } from 'vuex-map-fields'
|
||||
|
||||
export default {
|
||||
name: 'devices-overview',
|
||||
components: {
|
||||
FulfillingBouncingCircleSpinner,
|
||||
},
|
||||
computed: {
|
||||
...mapFields('device', [
|
||||
'triggerList',
|
||||
]),
|
||||
},
|
||||
created () {
|
||||
},
|
||||
data () {
|
||||
@@ -248,6 +283,44 @@ export default {
|
||||
})
|
||||
}
|
||||
},
|
||||
'+/data-server/trigger_manager/#' (data, topic) {
|
||||
const mes = new TextDecoder('utf-8').decode(data)
|
||||
const topicSplit = topic.split('/')
|
||||
const baseIndex = topicSplit.indexOf('trigger_manager')
|
||||
const actionIndex = baseIndex + 1
|
||||
const action = topicSplit[actionIndex]
|
||||
const macIndex = baseIndex + 2
|
||||
let _mac
|
||||
if (topicSplit.length - 1 >= macIndex) {
|
||||
_mac = topicSplit[macIndex]
|
||||
}
|
||||
let foundIndex
|
||||
let mesJson
|
||||
switch (action) {
|
||||
case 'info_all': // control_ID/data-server/trigger_manager/info_all
|
||||
this.triggerList = JSON.parse(mes)
|
||||
break
|
||||
case 'register': // control_ID/data-server/trigger_manager/register
|
||||
mesJson = JSON.parse(mes)
|
||||
foundIndex = this.triggerList.findIndex(o => o.mac === mesJson.mac)
|
||||
if (foundIndex < 0) { // -1: not found
|
||||
this.triggerList.push(mesJson)
|
||||
} else {
|
||||
this.triggerList[foundIndex] = mesJson
|
||||
}
|
||||
break
|
||||
case 'remove': // control_ID/data-server/trigger_manager/remove/device_mac
|
||||
foundIndex = this.triggerList.findIndex(o => o.mac === _mac)
|
||||
this.triggerList.splice(foundIndex, 1)
|
||||
break
|
||||
case 'info': // control_ID/data-server/trigger_manager/info/device_mac
|
||||
foundIndex = this.triggerList.findIndex(o => o.mac === _mac)
|
||||
this.triggerList[foundIndex] = mesJson
|
||||
break
|
||||
default:
|
||||
break
|
||||
}
|
||||
},
|
||||
async '+/broadcast' (data, topic) {
|
||||
const topicSplit = topic.split('/')
|
||||
const mes = String.fromCharCode.apply(null, data).split(':')
|
||||
@@ -379,6 +452,7 @@ export default {
|
||||
this.mqttSub(controller.id + '/hardware_device_connect/+')
|
||||
this.mqttSub(controller.id + '/hardware_scan/+')
|
||||
this.mqttSub(controller.id + '/broadcast')
|
||||
this.mqttSub(controller.id + '/data-server/trigger_manager/#')
|
||||
})
|
||||
},
|
||||
pageMqttUnSub: function () {
|
||||
@@ -389,6 +463,7 @@ export default {
|
||||
this.mqttUnSub(controller.id + '/hardware_device_connect/+')
|
||||
this.mqttUnSub(controller.id + '/hardware_scan/+')
|
||||
this.mqttUnSub(controller.id + '/broadcast')
|
||||
this.mqttUnSub(controller.id + '/data-server/trigger_manager/#')
|
||||
})
|
||||
},
|
||||
pageInitPub: function () {
|
||||
@@ -403,6 +478,8 @@ export default {
|
||||
this.mqttPub(controller.id + '_user', JSON.stringify({
|
||||
header: 'hardware_info/0',
|
||||
}))
|
||||
this.mqttPub(controller.id + '/client/trigger_manager/scan', '{}')
|
||||
this.mqttPub(controller.id + '/client/trigger_manager/info_all', '{}')
|
||||
// this.mqttPub(controller.id + '_user', JSON.stringify({
|
||||
// header: 'device_update_usb/0',
|
||||
// }))
|
||||
@@ -427,6 +504,7 @@ export default {
|
||||
this.mqttPub(controller.id + '_user', JSON.stringify({
|
||||
header: 'hardware_scan/0',
|
||||
}))
|
||||
this.mqttPub(controller.id + '/client/trigger_manager/scan', '{}')
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
@@ -74,6 +74,7 @@ export default {
|
||||
types.export.setHeader,
|
||||
types.export.setTitle,
|
||||
types.export.setData,
|
||||
types.export.getChipIndex,
|
||||
types.download.closeWriter,
|
||||
types.download.setStream,
|
||||
types.download.setSampleRate,
|
||||
@@ -111,11 +112,23 @@ export default {
|
||||
|
||||
// split to different subfile by channel
|
||||
if (meta.device.library_name.indexOf('Neulive') >= 0) {
|
||||
if (channelArray.some(el => el >= 256)) {
|
||||
channelList.push(channelArray.filter(el => (el >= 256 && el <= 259)))
|
||||
channelList.push(channelArray.filter(el => el < 256))
|
||||
if (meta.device.library_name === 'Neulive3.5ex') {
|
||||
if (channelArray.some(el => el >= 256)) { // 3-axis
|
||||
channelList.push(channelArray.filter(el => (el >= 256 && el <= 259)))
|
||||
}
|
||||
if (channelArray.some(el => (el >= 32 && el <= 63))) { // chip 2
|
||||
channelList.push(channelArray.filter(el => (el >= 32 && el <= 63)))
|
||||
}
|
||||
if (channelArray.some(el => (el >= 0 && el <= 31))) { // chip 1
|
||||
channelList.push(channelArray.filter(el => (el >= 0 && el <= 31)))
|
||||
}
|
||||
} else {
|
||||
channelList.push(channelArray)
|
||||
if (channelArray.some(el => el >= 256)) {
|
||||
channelList.push(channelArray.filter(el => (el >= 256 && el <= 259)))
|
||||
channelList.push(channelArray.filter(el => el < 256))
|
||||
} else {
|
||||
channelList.push(channelArray)
|
||||
}
|
||||
}
|
||||
} else if (meta.device.library_name.indexOf('Elite') >= 0) {
|
||||
channelList.push(channelArray)
|
||||
@@ -156,6 +169,15 @@ export default {
|
||||
this.downloadInfo.filename = meta.name
|
||||
this.downloadInfo.filename += (sd !== undefined) ? '-sd' : ''
|
||||
this.downloadInfo.size = parseInt(meta.size / (maxSplitFiles))
|
||||
|
||||
if (this.downloadInfo.device[1] === '3.5ex') {
|
||||
const chipIndex = await this.getChipIndexExport({ downloadInfo: this.downloadInfo })
|
||||
if (chipIndex === 1) {
|
||||
this.downloadInfo.filename += '_ch01-32'
|
||||
} else if (chipIndex === 2) {
|
||||
this.downloadInfo.filename += '_ch33-64'
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (meta.device.library_name.indexOf('Elite') >= 0) {
|
||||
this.downloadInfo.device = [meta.device.library_name.slice(0, 5), meta.device.library_name.slice(5)]
|
||||
|
||||
@@ -184,7 +184,7 @@
|
||||
/>
|
||||
</va-popover>
|
||||
<va-popover :message="`download ${props.rowData.name} in csv format`" placement="top">
|
||||
<va-button flat small color="gray" icon="fa fa-download" v-if="props.rowData.type !== 'folder' && props.rowData.device.library_name.indexOf('Neulive') >= 0" @click.stop="downloadCsv(props.rowData)"/>
|
||||
<va-button flat small color="success" icon="fa fa-download" v-if="props.rowData.type !== 'folder' && props.rowData.device.library_name.indexOf('Neulive') >= 0" @click.stop="downloadCsv(props.rowData)"/>
|
||||
</va-popover>
|
||||
<va-popover :message="`download ${props.rowData.name} in excel format`" placement="top">
|
||||
<va-button flat small color="gray" icon="fa fa-download" v-if="props.rowData.type !== 'folder' && props.rowData.device.library_name.indexOf('Elite') >= 0" @click.stop="downloadExcel(props.rowData)"/>
|
||||
@@ -701,7 +701,7 @@ export default {
|
||||
if (this.controllerList[0].sd_uploading === false) {
|
||||
const ret = await api.sdcard.getuuidList()
|
||||
if (ret.status === 200) {
|
||||
this.SDuuidList = ret.data.data
|
||||
this.SDuuidList = ret.data
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,16 +10,11 @@
|
||||
flat
|
||||
small
|
||||
>
|
||||
<va-icon
|
||||
<i
|
||||
v-if="meta.sd_data_uploaded === false"
|
||||
class="va-button__content__icon va-button__content__icon-left"
|
||||
name="material-icons"
|
||||
color="grey"
|
||||
@click.native.stop="performButtonAction()"
|
||||
small
|
||||
fixed-width
|
||||
> sd_card
|
||||
</va-icon>
|
||||
class="i-sd-card"
|
||||
@click="performButtonAction()"
|
||||
/>
|
||||
</va-button>
|
||||
|
||||
<sd-card-api-action :ref="'sd_card_api'"/>
|
||||
|
||||
@@ -78,6 +78,15 @@
|
||||
@remove="removeChartCheck(chart.chartID)"
|
||||
/>
|
||||
</div>
|
||||
<div
|
||||
v-for="trigger in triggerList"
|
||||
:key="trigger.id"
|
||||
>
|
||||
<trigger-chart
|
||||
v-show="trigger.display === true"
|
||||
:mac="trigger.mac"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div style="height: 150px;">
|
||||
@@ -100,8 +109,11 @@ import { chartData } from '../../../data/task/ChartsManagement'
|
||||
import { taskInfo } from '../../../data/task/TaskInfo'
|
||||
import CanvasChart from './chart/CanvasChart'
|
||||
import TaskDevices from './controller/TaskDevices'
|
||||
import TriggerChart from './chart/TriggerChart'
|
||||
// import api from '@/data/api'
|
||||
import { mapFields } from 'vuex-map-fields'
|
||||
import { mapActions } from 'vuex'
|
||||
import deviceTypes from '@/store/modules/device/types'
|
||||
// import TaskFormula from './formula/TaskFormula'
|
||||
|
||||
// TODO change chart data tag format
|
||||
@@ -111,12 +123,17 @@ export default {
|
||||
components: {
|
||||
CanvasChart,
|
||||
TaskDevices,
|
||||
TriggerChart,
|
||||
// TaskFormula,
|
||||
},
|
||||
computed: {
|
||||
...mapFields('taskContent', [
|
||||
'deviceList',
|
||||
]),
|
||||
...mapFields('device', [
|
||||
'triggerList',
|
||||
'chartKey',
|
||||
]),
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
@@ -127,8 +144,6 @@ export default {
|
||||
dataRefreshTimer: null,
|
||||
// charts data
|
||||
chartDataAll: chartData.getAllChartsData(),
|
||||
// chart refresh key
|
||||
chartKey: 0,
|
||||
chartNumber: taskInfo.getTaskInfo().chartList.length,
|
||||
selectChartID: null,
|
||||
showDeviceSetting: true,
|
||||
@@ -230,6 +245,50 @@ export default {
|
||||
await taskInfo.updateSdCardStatus(String.fromCharCode.apply(null, data))
|
||||
this.refreshDevicesWindow()
|
||||
},
|
||||
'+/data-server/trigger_manager/#' (data, topic) {
|
||||
let foundIndex
|
||||
let mesJson
|
||||
const mes = new TextDecoder('utf-8').decode(data)
|
||||
const topicSplit = topic.split('/')
|
||||
const baseIndex = topicSplit.indexOf('trigger_manager')
|
||||
const actionIndex = baseIndex + 1
|
||||
const action = topicSplit[actionIndex]
|
||||
const macIndex = baseIndex + 2
|
||||
let _mac
|
||||
if (topicSplit.length - 1 >= macIndex) {
|
||||
_mac = topicSplit[macIndex]
|
||||
foundIndex = this.triggerList.findIndex(o => o.mac === _mac)
|
||||
}
|
||||
switch (action) {
|
||||
case 'info_all': // control_ID/data-server/trigger_manager/info_all
|
||||
this.triggerList = JSON.parse(mes)
|
||||
this.deviceTriggerChartSetDisplay()
|
||||
break
|
||||
case 'register': // control_ID/data-server/trigger_manager/register
|
||||
mesJson = JSON.parse(mes)
|
||||
foundIndex = this.triggerList.findIndex(o => o.mac === mesJson.mac)
|
||||
if (foundIndex < 0) { // -1: not found
|
||||
this.triggerList.push(mesJson)
|
||||
} else {
|
||||
this.triggerList[foundIndex] = mesJson
|
||||
}
|
||||
break
|
||||
case 'remove': // control_ID/data-server/trigger_manager/remove/device_mac
|
||||
this.triggerList.splice(foundIndex, 1)
|
||||
break
|
||||
case 'info': // control_ID/data-server/trigger_manager/info/device_mac
|
||||
this.triggerList[foundIndex] = JSON.parse(mes)
|
||||
this.deviceTriggerChartSetDisplay()
|
||||
break
|
||||
case 'set_parameter': // control_ID/data-server/trigger_manager/set_parameter/device_mac
|
||||
this.triggerList[foundIndex].parameter = JSON.parse(mes)
|
||||
break
|
||||
case 'runtime': // control_ID/data-server/trigger_manager/runtime/device_mac
|
||||
break
|
||||
default:
|
||||
break
|
||||
}
|
||||
},
|
||||
async '+/broadcast' (data, topic) {
|
||||
const mes = String.fromCharCode.apply(null, data).split(':')
|
||||
// let content
|
||||
@@ -310,6 +369,7 @@ export default {
|
||||
this.mqttSub(id + '/device_parameter/+')
|
||||
this.mqttSub(id + '/device_parameter_value/+')
|
||||
this.mqttSub(id + '/device_sd_card_status/+')
|
||||
this.mqttSub(id + '/data-server/trigger_manager/#')
|
||||
},
|
||||
pageMqttUnSub: function (id) {
|
||||
for (const device in taskInfo.getTaskInfo().deviceList) {
|
||||
@@ -322,6 +382,7 @@ export default {
|
||||
this.mqttUnSub(id + '/device_parameter/+')
|
||||
this.mqttUnSub(id + '/device_parameter_value/+')
|
||||
this.mqttUnSub(id + '/device_sd_card_status/+')
|
||||
this.mqttUnSub(id + '/data-server/trigger_manager/#')
|
||||
},
|
||||
pageInit: async function () {
|
||||
if (await this.$refs.devices_ref != null) {
|
||||
@@ -340,6 +401,8 @@ export default {
|
||||
header: 'hardware_device/0',
|
||||
}))
|
||||
await taskInfo.updateChartInfo()
|
||||
this.mqttPub(taskInfo.getTaskInfo().controllerID + '/client/trigger_manager/scan', '{}')
|
||||
this.mqttPub(taskInfo.getTaskInfo().controllerID + '/client/trigger_manager/info_all', '{}')
|
||||
this.chartNumber = taskInfo.getTaskInfo().chartNumber
|
||||
},
|
||||
pageToast: function (mes) {
|
||||
@@ -595,6 +658,8 @@ export default {
|
||||
path: '/',
|
||||
})
|
||||
},
|
||||
|
||||
...mapActions('device', [deviceTypes.triggerChart.setDisplay]),
|
||||
},
|
||||
watch: {
|
||||
},
|
||||
|
||||
@@ -0,0 +1,225 @@
|
||||
<template>
|
||||
<div class="flex" :class="cardclass">
|
||||
<va-card>
|
||||
<chart :ref="'chart_ref'" :style="'width: '+ cardwidth + '; height: ' + cardheight + ';'" :options="sketchmapData" :auto-resize="true"></chart>
|
||||
</va-card>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
|
||||
import { mapActions } from 'vuex'
|
||||
import { taskInfo } from '@/data/task/TaskInfo'
|
||||
import { mapFields } from 'vuex-map-fields'
|
||||
import deviceTypes from '@/store/modules/device/types'
|
||||
|
||||
export default {
|
||||
name: 'TriggerChart',
|
||||
components: {
|
||||
},
|
||||
computed: {
|
||||
...mapFields('device', [
|
||||
'triggerList',
|
||||
'allChannels',
|
||||
]),
|
||||
},
|
||||
props: {
|
||||
mac: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
},
|
||||
created () {
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
timer: null,
|
||||
cardclass: ['xs12', 'md12', 'xl12', 'sm12'],
|
||||
cardheight: '400px',
|
||||
cardwidth: 'auto',
|
||||
sketchmapData: {},
|
||||
activeChannels: [],
|
||||
}
|
||||
},
|
||||
mqtt: {
|
||||
async '+/data-server/trigger_manager/#' (data, topic) {
|
||||
const mes = new TextDecoder('utf-8').decode(data)
|
||||
const topicSplit = topic.split('/')
|
||||
const baseIndex = topicSplit.indexOf('trigger_manager')
|
||||
const actionIndex = baseIndex + 1
|
||||
const action = topicSplit[actionIndex]
|
||||
const macIndex = baseIndex + 2
|
||||
let _mac
|
||||
if (topicSplit.length - 1 >= macIndex) {
|
||||
_mac = topicSplit[macIndex]
|
||||
}
|
||||
if (_mac === this.mac) {
|
||||
switch (action) {
|
||||
case 'set_parameter': // control_ID/data-server/trigger_manager/set_parameter/device_mac
|
||||
await this.initActiveChannels()
|
||||
this.initChart()
|
||||
break
|
||||
case 'runtime': // control_ID/data-server/trigger_manager/runtime/device_mac
|
||||
this.updateTimer(mes)
|
||||
break
|
||||
default:
|
||||
break
|
||||
}
|
||||
}
|
||||
},
|
||||
'+/data-server/trigger_runtime/#' (data, topic) { // control_ID/data-server/trigger_runtime/pin_event/device_mac/channel
|
||||
const mes = new TextDecoder('utf-8').decode(data)
|
||||
const topicSplit = topic.split('/')
|
||||
const baseIndex = topicSplit.indexOf('trigger_runtime')
|
||||
const actionIndex = baseIndex + 1
|
||||
const action = topicSplit[actionIndex]
|
||||
const macIndex = baseIndex + 2
|
||||
const channelIndex = baseIndex + 3
|
||||
let _mac
|
||||
if (topicSplit.length - 1 >= macIndex) {
|
||||
_mac = topicSplit[macIndex]
|
||||
}
|
||||
let channel
|
||||
if (topicSplit.length - 1 >= channelIndex) {
|
||||
channel = parseInt(topicSplit[channelIndex])
|
||||
}
|
||||
let mesJson
|
||||
if (_mac === this.mac) {
|
||||
switch (action) {
|
||||
case 'pin_event':
|
||||
mesJson = JSON.parse(mes)
|
||||
this.addSketchMapData(mesJson.timestamp, mesJson.status === 'high' ? 3.3 : 0.0, channel)
|
||||
break
|
||||
default:
|
||||
break
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
addSketchMapData (timestamp, val, channel) {
|
||||
const gridIndex = this.activeChannels.indexOf(channel)
|
||||
this.sketchmapData.series[gridIndex].data.push([parseInt(timestamp), val])
|
||||
if (this.sketchmapData.series[gridIndex].data.length > 1000) {
|
||||
this.sketchmapData.series[gridIndex].data.shift()
|
||||
}
|
||||
},
|
||||
mqttSub: function (val) {
|
||||
this.$mqtt.subscribe(val)
|
||||
},
|
||||
mqttUnSub: function (val) {
|
||||
this.$mqtt.unsubscribe(val)
|
||||
},
|
||||
makeGrid (index, length) {
|
||||
const _height = (100 / length) - 2 + '%'
|
||||
const _top = index * (100 / length) + 2 + '%'
|
||||
const _left = '0%'
|
||||
const _right = '3%'
|
||||
return {
|
||||
index: index,
|
||||
top: _top,
|
||||
height: _height,
|
||||
left: _left,
|
||||
right: _right,
|
||||
containLabel: true,
|
||||
}
|
||||
},
|
||||
makeSeries (xAxisIndex, yAxisIndex) {
|
||||
return {
|
||||
type: 'line',
|
||||
step: 'start',
|
||||
data: [],
|
||||
animation: false,
|
||||
xAxisIndex: xAxisIndex,
|
||||
yAxisIndex: yAxisIndex,
|
||||
}
|
||||
},
|
||||
makeXAxis (gridIndex) {
|
||||
return {
|
||||
show: false,
|
||||
type: 'time',
|
||||
gridIndex: gridIndex,
|
||||
min: 'dataMin',
|
||||
max: 'dataMax',
|
||||
}
|
||||
},
|
||||
makeYAxis (gridIndex) {
|
||||
return {
|
||||
type: 'value',
|
||||
gridIndex: gridIndex,
|
||||
splitNumber: 1,
|
||||
splitLine: {
|
||||
show: false,
|
||||
},
|
||||
axisLabel: {
|
||||
formatter: function (value) {
|
||||
return value + 'V'
|
||||
},
|
||||
},
|
||||
min: 'dataMin',
|
||||
max: 'dataMax',
|
||||
}
|
||||
},
|
||||
async initActiveChannels () {
|
||||
this.activeChannels = await this.deviceTriggerGetActiveChannels({ mac: this.mac })
|
||||
},
|
||||
initChart () {
|
||||
this.clearChart()
|
||||
const currImplementedChannels = this.activeChannels.filter(ch => ch < 4) // [TODO] now only open 4 channels (2022/01/05)
|
||||
const gridLength = currImplementedChannels.length
|
||||
for (let gridIndex = 0; gridIndex < gridLength; gridIndex++) {
|
||||
this.sketchmapData.grid.push(this.makeGrid(gridIndex, gridLength))
|
||||
this.sketchmapData.xAxis.push(this.makeXAxis(gridIndex))
|
||||
this.sketchmapData.yAxis.push(this.makeYAxis(gridIndex))
|
||||
this.sketchmapData.series.push(this.makeSeries(gridIndex, gridIndex))
|
||||
if (gridIndex === gridLength - 1) {
|
||||
this.sketchmapData.xAxis[gridLength - 1].show = true
|
||||
}
|
||||
}
|
||||
},
|
||||
clearChart () {
|
||||
this.sketchmapData = {
|
||||
xAxis: [],
|
||||
yAxis: [],
|
||||
tooltip: {
|
||||
trigger: 'axis',
|
||||
},
|
||||
series: [],
|
||||
grid: [],
|
||||
}
|
||||
},
|
||||
updateTimer (status) {
|
||||
if (status === 'start') {
|
||||
if (this.timer === null) {
|
||||
this.timer = setInterval(this.updateCurrentTime, 1000)
|
||||
}
|
||||
} else {
|
||||
clearInterval(this.timer)
|
||||
this.timer = null
|
||||
}
|
||||
},
|
||||
updateCurrentTime () {
|
||||
const currTime = Date.now()
|
||||
this.sketchmapData.xAxis.forEach(axis => {
|
||||
axis.min = currTime - 10000 // 10000ms = 10s
|
||||
axis.max = currTime + 1000
|
||||
})
|
||||
},
|
||||
|
||||
...mapActions('device', [deviceTypes.trigger.getActiveChannels]),
|
||||
},
|
||||
async mounted () {
|
||||
this.mqttSub(taskInfo.getTaskInfo().controllerID + '/data-server/trigger_manager/#')
|
||||
this.mqttSub(taskInfo.getTaskInfo().controllerID + '/data-server/trigger_runtime/#')
|
||||
await this.initActiveChannels()
|
||||
this.initChart()
|
||||
this.updateTimer('start')
|
||||
},
|
||||
destroyed () {
|
||||
this.mqttUnSub(taskInfo.getTaskInfo().controllerID + '/data-server/trigger_manager/#')
|
||||
this.mqttUnSub(taskInfo.getTaskInfo().controllerID + '/data-server/trigger_runtime/#')
|
||||
this.clearChart()
|
||||
this.updateTimer('stop')
|
||||
},
|
||||
}
|
||||
</script>
|
||||
@@ -38,7 +38,7 @@
|
||||
</va-item-section>
|
||||
|
||||
<va-item-section class="mr-3" v-if="device.type == 'Neulive'" side>
|
||||
<i v-if="!device.sdCardStatus" class="i-sd-card mr-3" style="width: 1rem; height: 1rem;"></i>
|
||||
<i v-if="device.sdCardStatus" class="i-sd-card mr-3" style="width: 1rem; height: 1rem;"></i>
|
||||
<!-- <va-icon
|
||||
name="fas fa-sd-card"
|
||||
:color="(device.sdCardStatus === true) ? 'primary' : 'grey'"
|
||||
|
||||
@@ -48,12 +48,35 @@
|
||||
</div>
|
||||
|
||||
</va-card>
|
||||
<va-card class="mt-2">
|
||||
<template slot="header">
|
||||
<va-icon name="fa fa-bluetooth-b mr-3" color="primary"/>
|
||||
<h5 class="mt-0 mb-0">TRIGGERS</h5>
|
||||
</template>
|
||||
<div v-if="state.LOADING" class="flex-center spinner-box mt-4 mb-5">
|
||||
<fulfilling-bouncing-circle-spinner
|
||||
:animation-duration="3000"
|
||||
:color="this.$themes.primary"
|
||||
:size="60"
|
||||
>
|
||||
</fulfilling-bouncing-circle-spinner>
|
||||
</div>
|
||||
|
||||
<div class="flex row align--center">
|
||||
<trigger-list
|
||||
@start="startTrigger($event)"
|
||||
@stop="stopTrigger($event)"
|
||||
/>
|
||||
</div>
|
||||
|
||||
</va-card>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { FulfillingBouncingCircleSpinner } from 'epic-spinners'
|
||||
import TaskDeviceList from './TaskDeviceList'
|
||||
import TriggerList from './TriggerList'
|
||||
// import TaskDeviceListGM from './neulive-gimer/TaskDeviceListGM'
|
||||
import { taskInfo } from '../../../../data/task/TaskInfo'
|
||||
import { chartData } from '../../../../data/task/ChartsManagement'
|
||||
@@ -67,6 +90,7 @@ export default {
|
||||
// TaskDeviceListGM,
|
||||
FulfillingBouncingCircleSpinner,
|
||||
TaskDeviceList,
|
||||
TriggerList,
|
||||
},
|
||||
props: {
|
||||
cardclass: {
|
||||
@@ -336,6 +360,26 @@ export default {
|
||||
device: taskInfo.getRawDeviceID(device.id),
|
||||
}))
|
||||
},
|
||||
startTrigger (trigger) {
|
||||
// save automatically when start
|
||||
this.mqttPub(taskInfo.getTaskInfo().controllerID + '/client/trigger_manager/set_parameter', JSON.stringify({
|
||||
mac: trigger.mac,
|
||||
parameter_set: trigger.parameter,
|
||||
}),
|
||||
)
|
||||
this.mqttPub(taskInfo.getTaskInfo().controllerID + '/client/trigger_manager/runtime', JSON.stringify({
|
||||
mac: trigger.mac,
|
||||
instruction: 'start',
|
||||
}),
|
||||
)
|
||||
},
|
||||
stopTrigger (trigger) {
|
||||
this.mqttPub(taskInfo.getTaskInfo().controllerID + '/client/trigger_manager/runtime', JSON.stringify({
|
||||
mac: trigger.mac,
|
||||
instruction: 'stop',
|
||||
}),
|
||||
)
|
||||
},
|
||||
addDevice: async function (selectID) {
|
||||
if (selectID == null) {
|
||||
return false
|
||||
|
||||
@@ -0,0 +1,85 @@
|
||||
<template>
|
||||
<div class="flex sm12 xl12 md12 xs12">
|
||||
<va-accordion v-for="trigger in triggerList" :key="trigger.id">
|
||||
<va-collapse class="mb-2" :isOpenDefault='true'>
|
||||
<span slot="header" >
|
||||
<va-item :key="trigger.id" class="pa-0 ma-0"
|
||||
>
|
||||
<va-item-section class="ml-3" caption>
|
||||
<va-item-label>
|
||||
{{ trigger.name }}
|
||||
</va-item-label>
|
||||
<va-item-label caption>
|
||||
{{ trigger.mac }}
|
||||
</va-item-label>
|
||||
</va-item-section>
|
||||
</va-item>
|
||||
|
||||
<va-item class="pa-0 ma-0 mt-2">
|
||||
<va-item-section class="ml-3">
|
||||
<va-item-label>
|
||||
<va-button @click.stop="start(trigger)" v-if="trigger.status !== 'RUNNING'" class="px-2 py-0 mr-0" color="success" small>START</va-button>
|
||||
<va-button @click.stop="stop(trigger)" v-if="trigger.status === 'RUNNING'" class="px-2 py-0 mr-0" color="danger" small>STOP</va-button>
|
||||
</va-item-label>
|
||||
</va-item-section>
|
||||
</va-item>
|
||||
</span>
|
||||
<div slot="body">
|
||||
<div class="mt-0 mb-0" style="height: 350px; overflow-y: scroll; overflow-x: hidden;" :key="'detail' + trigger.id">
|
||||
<div>
|
||||
<trigger-control-window :mac="trigger.mac" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</va-collapse>
|
||||
</va-accordion>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { mapFields } from 'vuex-map-fields'
|
||||
import TriggerControlWindow from '../trigger/TriggerControlWindow'
|
||||
|
||||
export default {
|
||||
name: 'TriggerList',
|
||||
components: {
|
||||
TriggerControlWindow,
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
...mapFields('device', [
|
||||
'triggerList',
|
||||
'chartKey',
|
||||
]),
|
||||
},
|
||||
methods: {
|
||||
start: async function (trigger) {
|
||||
this.$emit('start', trigger)
|
||||
this.triggerList.find(o => o.mac === trigger.mac).display = true
|
||||
this.triggerList.find(o => o.mac === trigger.mac).status = 'RUNNING'
|
||||
this.chartKey++
|
||||
this.pageToast('The trigger ' + trigger.name + ' has been started.')
|
||||
},
|
||||
stop: function (trigger) {
|
||||
this.$emit('stop', trigger)
|
||||
this.triggerList.find(o => o.mac === trigger.mac).status = 'CONNTECTED'
|
||||
this.pageToast('The trigger ' + trigger.name + ' has been stopped.')
|
||||
},
|
||||
pageToast: function (mes) {
|
||||
this.showToast(
|
||||
mes,
|
||||
{
|
||||
icon: 'fa-bell',
|
||||
position: 'bottom-right',
|
||||
duration: 4000,
|
||||
},
|
||||
)
|
||||
},
|
||||
},
|
||||
destroyed () {
|
||||
},
|
||||
}
|
||||
</script>
|
||||
@@ -205,6 +205,16 @@ export default {
|
||||
value: 20000,
|
||||
description: '20k',
|
||||
},
|
||||
{
|
||||
id: 7,
|
||||
value: 25000,
|
||||
description: '25k',
|
||||
},
|
||||
{
|
||||
id: 8,
|
||||
value: 31250,
|
||||
description: '31.25k',
|
||||
},
|
||||
],
|
||||
acceleratorSensitivitySelect: null,
|
||||
acceleratorSensitivityOptions: [
|
||||
@@ -333,7 +343,7 @@ export default {
|
||||
},
|
||||
sampleRateSelectChange () {
|
||||
if (this.sampleRateSelect != null && this.sampleRateSelect.value !== ((taskInfo.getDeviceInfo(this.deviceID).parameterSet.SAMPLE_RATE))) {
|
||||
const adcClock = 8e5 / this.sampleRateSelect.value
|
||||
const adcClock = 1e6 / this.sampleRateSelect.value
|
||||
this.mqttPub(taskInfo.getTaskInfo().controllerID + '_user', JSON.stringify({
|
||||
header: 'device_parameter/0',
|
||||
device: taskInfo.getRawDeviceID(this.deviceID),
|
||||
|
||||
@@ -202,43 +202,43 @@ export default {
|
||||
},
|
||||
{
|
||||
id: 6,
|
||||
value: 16000,
|
||||
description: '16k',
|
||||
},
|
||||
{
|
||||
id: 7,
|
||||
value: 20000,
|
||||
description: '20k',
|
||||
},
|
||||
{
|
||||
id: 7,
|
||||
value: 30000,
|
||||
description: '30k',
|
||||
id: 8,
|
||||
value: 25000,
|
||||
description: '25k',
|
||||
},
|
||||
{
|
||||
id: 8,
|
||||
id: 9,
|
||||
value: 32000,
|
||||
description: '32k',
|
||||
},
|
||||
{
|
||||
id: 10,
|
||||
value: 40000,
|
||||
description: '40k',
|
||||
},
|
||||
{
|
||||
id: 9,
|
||||
id: 11,
|
||||
value: 50000,
|
||||
description: '50k',
|
||||
},
|
||||
{
|
||||
id: 10,
|
||||
value: 60000,
|
||||
description: '60k',
|
||||
},
|
||||
{
|
||||
id: 11,
|
||||
value: 70000,
|
||||
description: '70k',
|
||||
},
|
||||
{
|
||||
id: 12,
|
||||
value: 80000,
|
||||
description: '80k',
|
||||
value: 64000,
|
||||
description: '64k',
|
||||
},
|
||||
{
|
||||
id: 13,
|
||||
value: 90000,
|
||||
description: '90k',
|
||||
value: 80000,
|
||||
description: '80k',
|
||||
},
|
||||
{
|
||||
id: 14,
|
||||
|
||||
@@ -203,43 +203,43 @@ export default {
|
||||
},
|
||||
{
|
||||
id: 6,
|
||||
value: 16000,
|
||||
description: '16k',
|
||||
},
|
||||
{
|
||||
id: 7,
|
||||
value: 20000,
|
||||
description: '20k',
|
||||
},
|
||||
{
|
||||
id: 7,
|
||||
value: 30000,
|
||||
description: '30k',
|
||||
id: 8,
|
||||
value: 25000,
|
||||
description: '25k',
|
||||
},
|
||||
{
|
||||
id: 8,
|
||||
id: 9,
|
||||
value: 32000,
|
||||
description: '32k',
|
||||
},
|
||||
{
|
||||
id: 10,
|
||||
value: 40000,
|
||||
description: '40k',
|
||||
},
|
||||
{
|
||||
id: 9,
|
||||
id: 11,
|
||||
value: 50000,
|
||||
description: '50k',
|
||||
},
|
||||
{
|
||||
id: 10,
|
||||
value: 60000,
|
||||
description: '60k',
|
||||
},
|
||||
{
|
||||
id: 11,
|
||||
value: 70000,
|
||||
description: '70k',
|
||||
},
|
||||
{
|
||||
id: 12,
|
||||
value: 80000,
|
||||
description: '80k',
|
||||
value: 64000,
|
||||
description: '64k',
|
||||
},
|
||||
{
|
||||
id: 13,
|
||||
value: 90000,
|
||||
description: '90k',
|
||||
value: 80000,
|
||||
description: '80k',
|
||||
},
|
||||
{
|
||||
id: 14,
|
||||
|
||||
@@ -955,10 +955,10 @@ export default {
|
||||
return false
|
||||
}
|
||||
|
||||
if (usVal < 60) {
|
||||
this.periodNumber = 60
|
||||
this.periodNumberInput = String(60 / this.unitMultiply)
|
||||
this.pageToast('Reset to 60 us')
|
||||
if (usVal < 10) {
|
||||
this.periodNumber = 10
|
||||
this.periodNumberInput = String(10 / this.unitMultiply)
|
||||
this.pageToast('Reset to 10 us')
|
||||
} else if (usVal > 1e6) { // freq: 1 to 20000Hz, so period < 1e6us (1e6/1e6=1)
|
||||
this.periodNumber = 1e6
|
||||
this.periodNumberInput = String(1e6 / this.unitMultiply)
|
||||
@@ -1137,7 +1137,7 @@ export default {
|
||||
// val unit: us
|
||||
const val = (this.t1Range + this.t2Range + this.t3Range + this.t4Range) * 10 // UI us
|
||||
|
||||
if (val < 80) { // us
|
||||
if (val < 10) { // us
|
||||
for (const tRange of [1, 2, 3, 4]) {
|
||||
this.updateTRangeErrorMsg({ stiIimeSelect: tRange, status: true, msg: 'Period < 0.08ms' })
|
||||
}
|
||||
|
||||
@@ -956,10 +956,10 @@ export default {
|
||||
return false
|
||||
}
|
||||
|
||||
if (usVal < 60) {
|
||||
this.periodNumber = 60
|
||||
this.periodNumberInput = String(60 / this.unitMultiply)
|
||||
this.pageToast('Reset to 60 us')
|
||||
if (usVal < 10) {
|
||||
this.periodNumber = 10
|
||||
this.periodNumberInput = String(10 / this.unitMultiply)
|
||||
this.pageToast('Reset to 10 us')
|
||||
} else if (usVal > 1e6) { // freq: 1 to 20000Hz, so period < 1e6us (1e6/1e6=1)
|
||||
this.periodNumber = 1e6
|
||||
this.periodNumberInput = String(1e6 / this.unitMultiply)
|
||||
@@ -1138,7 +1138,7 @@ export default {
|
||||
// val unit: us
|
||||
const val = (this.t1Range + this.t2Range + this.t3Range + this.t4Range) * 10 // UI us
|
||||
|
||||
if (val < 80) { // us
|
||||
if (val < 10) { // us
|
||||
for (const tRange of [1, 2, 3, 4]) {
|
||||
this.updateTRangeErrorMsg({ stiIimeSelect: tRange, status: true, msg: 'Period < 0.08ms' })
|
||||
}
|
||||
|
||||
@@ -0,0 +1,92 @@
|
||||
<template>
|
||||
<div class="row flex px-0 mx-0 my-0 py-0">
|
||||
<div class="flex sm5 xl5 md5 xs5 px-0 mx-0 my-0 py-2">
|
||||
<p class="display-6">Action<p/>
|
||||
</div>
|
||||
<div class="flex sm7 xl7 md7 xs7 px-0 mx-0 my-0 py-0" :key="inputKey">
|
||||
<!-- <p class="display-6">Method<p/> -->
|
||||
<va-input
|
||||
@mouseleave.native="itemChange()"
|
||||
@keyup.enter="itemChange()"
|
||||
@blur="itemChange()"
|
||||
v-model="methodInput"
|
||||
class="my-2"
|
||||
label="Method"
|
||||
/>
|
||||
<va-input
|
||||
@mouseleave.native="itemChange()"
|
||||
@keyup.enter="itemChange()"
|
||||
@blur="itemChange()"
|
||||
v-model="dataInput"
|
||||
class="mb-0"
|
||||
label="Data"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
|
||||
import { mapFields } from 'vuex-map-fields'
|
||||
import { mapActions } from 'vuex'
|
||||
import deviceTypes from '@/store/modules/device/types'
|
||||
|
||||
export default {
|
||||
name: 'Action',
|
||||
components: {
|
||||
},
|
||||
computed: {
|
||||
...mapFields('device', [
|
||||
'triggerList',
|
||||
]),
|
||||
},
|
||||
props: {
|
||||
mac: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
channelIndex: {
|
||||
type: Number,
|
||||
required: true,
|
||||
},
|
||||
},
|
||||
created () {
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
inputKey: 0,
|
||||
methodInput: '',
|
||||
dataInput: '',
|
||||
}
|
||||
},
|
||||
mqtt: {
|
||||
},
|
||||
methods: {
|
||||
itemChange () {
|
||||
const key = 'channel_event_' + this.channelIndex
|
||||
const obj = this.triggerList.find(o => o.mac === this.mac)
|
||||
obj.parameter[key].action = {
|
||||
method: this.methodInput,
|
||||
data: this.dataInput,
|
||||
}
|
||||
},
|
||||
async refresh () {
|
||||
const key = 'channel_event_' + this.channelIndex
|
||||
const obj = this.triggerList.find(o => o.mac === this.mac)
|
||||
const inputChannels = await this.deviceTriggerGetInputChannels({ mac: this.mac })
|
||||
if (inputChannels.includes(String(this.channelIndex))) {
|
||||
this.methodInput = obj.parameter[key].action.method
|
||||
this.dataInput = String(obj.parameter[key].action.data)
|
||||
}
|
||||
},
|
||||
|
||||
...mapActions('device', [deviceTypes.trigger.getInputChannels]),
|
||||
},
|
||||
mounted () {
|
||||
},
|
||||
destroyed () {
|
||||
},
|
||||
watch: {
|
||||
},
|
||||
}
|
||||
</script>
|
||||
@@ -0,0 +1,52 @@
|
||||
<template>
|
||||
<div class="row flex sm12 xl12 md12 xs12 my-3 py-0">
|
||||
<div class="flex sm4 xl4 md4 xs4 px-0 py-0 mx-0 my-0">
|
||||
<p class="display-6"> CHANNEL {{ channelIndex + 1 }} <p/>
|
||||
</div>
|
||||
<div class="flex sm8 xl8 md8 xs8 px-0 py-0 mx-0 mt-1" :key="inputKey">
|
||||
<mode :ref="'mode'" class="mb-1" :mac="mac" :channelIndex="channelIndex" />
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
|
||||
import Mode from './Mode'
|
||||
|
||||
export default {
|
||||
name: 'Channel',
|
||||
components: {
|
||||
Mode,
|
||||
},
|
||||
props: {
|
||||
mac: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
channelIndex: {
|
||||
type: Number,
|
||||
required: true,
|
||||
},
|
||||
},
|
||||
created () {
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
inputKey: 0,
|
||||
}
|
||||
},
|
||||
mqtt: {
|
||||
},
|
||||
methods: {
|
||||
refresh () {
|
||||
this.$refs.mode.refresh()
|
||||
},
|
||||
},
|
||||
mounted () {
|
||||
},
|
||||
watch: {
|
||||
},
|
||||
destroyed () {
|
||||
},
|
||||
}
|
||||
</script>
|
||||
@@ -0,0 +1,79 @@
|
||||
<template>
|
||||
<div class="row flex px-0 mx-0 my-0 py-0">
|
||||
<div class="flex sm5 xl5 md5 xs5 px-0 mx-0 my-0 py-2">
|
||||
<p class="display-6">Description<p/>
|
||||
</div>
|
||||
<div class="flex sm7 xl7 md7 xs7 px-0 mx-0 my-0 py-0">
|
||||
<va-input
|
||||
@mouseleave.native="itemChange()"
|
||||
@keyup.enter="itemChange()"
|
||||
@blur="itemChange()"
|
||||
:key="inputKey"
|
||||
style="float: left;"
|
||||
v-model="itemInput"
|
||||
class="mb-0"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
|
||||
import { mapFields } from 'vuex-map-fields'
|
||||
import { mapActions } from 'vuex'
|
||||
import deviceTypes from '@/store/modules/device/types'
|
||||
|
||||
export default {
|
||||
name: 'Description',
|
||||
components: {
|
||||
},
|
||||
computed: {
|
||||
...mapFields('device', [
|
||||
'triggerList',
|
||||
]),
|
||||
},
|
||||
props: {
|
||||
mac: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
channelIndex: {
|
||||
type: Number,
|
||||
required: true,
|
||||
},
|
||||
},
|
||||
created () {
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
inputKey: 0,
|
||||
itemInput: '',
|
||||
}
|
||||
},
|
||||
mqtt: {
|
||||
},
|
||||
methods: {
|
||||
itemChange () {
|
||||
const key = 'channel_event_' + this.channelIndex
|
||||
const obj = this.triggerList.find(o => o.mac === this.mac)
|
||||
obj.parameter[key].description = this.itemInput
|
||||
},
|
||||
async refresh () {
|
||||
const key = 'channel_event_' + this.channelIndex
|
||||
const obj = this.triggerList.find(o => o.mac === this.mac)
|
||||
const inputChannels = await this.deviceTriggerGetInputChannels({ mac: this.mac })
|
||||
if (inputChannels.includes(String(this.channelIndex))) {
|
||||
this.itemInput = obj.parameter[key].description
|
||||
}
|
||||
},
|
||||
|
||||
...mapActions('device', [deviceTypes.trigger.getInputChannels]),
|
||||
},
|
||||
mounted () {
|
||||
},
|
||||
destroyed () {
|
||||
},
|
||||
watch: {
|
||||
},
|
||||
}
|
||||
</script>
|
||||
@@ -0,0 +1,64 @@
|
||||
<template>
|
||||
<div class="row flex px-0 mx-0 my-0 py-0">
|
||||
<div class="flex sm4 xl4 md4 xs4 px-0 mx-0 my-0 py-2">
|
||||
<p class="display-6">INTERVAL<p/>
|
||||
</div>
|
||||
<div class="flex sm4 xl4 md4 xs4 px-0 mx-0 my-0 py-0">
|
||||
<va-input
|
||||
@mouseleave.native="itemChange()"
|
||||
@keyup.enter="itemChange()"
|
||||
@blur="itemChange()"
|
||||
:key="inputKey"
|
||||
v-model="itemInput"
|
||||
class="mb-0"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
|
||||
import { mapFields } from 'vuex-map-fields'
|
||||
|
||||
export default {
|
||||
name: 'Interval',
|
||||
components: {
|
||||
},
|
||||
computed: {
|
||||
...mapFields('device', [
|
||||
'triggerList',
|
||||
]),
|
||||
},
|
||||
props: {
|
||||
mac: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
},
|
||||
created () {
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
inputKey: 0,
|
||||
itemInput: 0.01,
|
||||
}
|
||||
},
|
||||
mqtt: {
|
||||
},
|
||||
methods: {
|
||||
itemChange () {
|
||||
const obj = this.triggerList.find(o => o.mac === this.mac)
|
||||
obj.parameter.runtime_interval = parseFloat(this.itemInput)
|
||||
},
|
||||
refresh () {
|
||||
this.itemInput = this.triggerList.find(o => o.mac === this.mac).parameter.runtime_interval
|
||||
},
|
||||
},
|
||||
async mounted () {
|
||||
},
|
||||
destroyed () {
|
||||
},
|
||||
watch: {
|
||||
},
|
||||
}
|
||||
</script>
|
||||
@@ -0,0 +1,135 @@
|
||||
<template>
|
||||
<div class="row">
|
||||
<va-radio-button
|
||||
v-for="(option, index) in optionMode"
|
||||
:key="index"
|
||||
v-model="selectMode"
|
||||
:option="optionMode[index]"
|
||||
:label="optionMode[index]"
|
||||
class="pl-2"
|
||||
@click.native.stop="itemChange(index)"
|
||||
/>
|
||||
<div v-show="selectMode === 'INPUT'" class="my-3 pl-3">
|
||||
<ttl :ref="'ttl'" :mac="mac" :channelIndex="channelIndex" />
|
||||
<description :ref="'desc'" :mac="mac" :channelIndex="channelIndex" />
|
||||
<action :ref="'action'" :mac="mac" :channelIndex="channelIndex" />
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
|
||||
import { mapActions } from 'vuex'
|
||||
import { mapFields } from 'vuex-map-fields'
|
||||
import deviceTypes from '@/store/modules/device/types'
|
||||
import Ttl from './Ttl'
|
||||
import Description from './Description'
|
||||
import Action from './Action'
|
||||
|
||||
export default {
|
||||
name: 'Mode',
|
||||
components: {
|
||||
Ttl,
|
||||
Description,
|
||||
Action,
|
||||
},
|
||||
computed: {
|
||||
...mapFields('device', [
|
||||
'triggerList',
|
||||
'allChannels',
|
||||
]),
|
||||
},
|
||||
props: {
|
||||
mac: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
channelIndex: {
|
||||
type: Number,
|
||||
required: true,
|
||||
},
|
||||
},
|
||||
created () {
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
inputeKey: 0,
|
||||
selectMode: 'OUTPUT',
|
||||
optionMode: [
|
||||
'INPUT',
|
||||
'OUTPUT',
|
||||
],
|
||||
}
|
||||
},
|
||||
mqtt: {
|
||||
},
|
||||
methods: {
|
||||
getBitMode (channelList) {
|
||||
let channelSet = ''
|
||||
for (let i = 7; i >= 0; i--) {
|
||||
if (channelList.indexOf(i) >= 0) {
|
||||
channelSet += '1'
|
||||
} else {
|
||||
channelSet += '0'
|
||||
}
|
||||
}
|
||||
return parseInt(channelSet, 2)
|
||||
},
|
||||
async updateBitMode (obj) {
|
||||
const outputChannels = await this.deviceTriggerGetOutputChannels({ mac: this.mac })
|
||||
this.selectMode === 'OUTPUT' ? outputChannels.add(this.channelIndex) : outputChannels.delete(this.channelIndex)
|
||||
obj.parameter.bitmode = this.getBitMode(Array.from(outputChannels))
|
||||
},
|
||||
itemChange () {
|
||||
const key = 'channel_event_' + this.channelIndex
|
||||
const obj = this.triggerList.find(o => o.mac === this.mac)
|
||||
if (this.selectMode === 'INPUT') {
|
||||
if (Object.keys(obj.parameter[key]).length === 0) {
|
||||
obj.parameter[key] = {
|
||||
ttl: 'high',
|
||||
description: 'camera on',
|
||||
action: {},
|
||||
broadcast: 1,
|
||||
}
|
||||
}
|
||||
this.$refs.ttl.itemChange()
|
||||
this.$refs.desc.itemChange()
|
||||
this.$refs.action.itemChange()
|
||||
} else {
|
||||
obj.parameter[key] = {}
|
||||
}
|
||||
this.updateBitMode(obj)
|
||||
},
|
||||
async refreshSelectMode () {
|
||||
const outputChannels = await this.deviceTriggerGetOutputChannels({ mac: this.mac })
|
||||
if (outputChannels.has(this.channelIndex)) {
|
||||
this.selectMode = 'OUTPUT'
|
||||
}
|
||||
const inputChannels = await this.deviceTriggerGetInputChannels({ mac: this.mac })
|
||||
if (inputChannels.includes(this.channelIndex)) {
|
||||
this.selectMode = 'INPUT'
|
||||
}
|
||||
},
|
||||
refresh () {
|
||||
this.refreshSelectMode()
|
||||
if (this.$refs.ttl != null) {
|
||||
this.$refs.ttl.refresh()
|
||||
}
|
||||
if (this.$refs.desc != null) {
|
||||
this.$refs.desc.refresh()
|
||||
}
|
||||
if (this.$refs.action != null) {
|
||||
this.$refs.action.refresh()
|
||||
}
|
||||
},
|
||||
|
||||
...mapActions('device', [deviceTypes.trigger.getOutputChannels, deviceTypes.trigger.getInputChannels]),
|
||||
},
|
||||
mounted () {
|
||||
},
|
||||
watch: {
|
||||
},
|
||||
destroyed () {
|
||||
},
|
||||
}
|
||||
</script>
|
||||
@@ -0,0 +1,80 @@
|
||||
<template>
|
||||
<div>
|
||||
<div style="text-align: right;">
|
||||
<!-- <va-button small v-if="display !== true" color="primary" @click="setDisplayParam(true)"> DISPLAY </va-button>
|
||||
<va-button small v-if="display === true" color="danger" @click="setDisplayParam(false)"> HIDE </va-button> -->
|
||||
<va-button small @click="updateParam"> SAVE </va-button>
|
||||
</div>
|
||||
<interval :ref="'interval'" :mac="mac" />
|
||||
<div v-for="channelIndex in allChannels" :key="channelIndex">
|
||||
<channel :ref="'channel'" :mac="mac" :channelIndex="channelIndex" />
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
|
||||
import Interval from './Interval'
|
||||
import Channel from './Channel'
|
||||
import { taskInfo } from '@/data/task/TaskInfo'
|
||||
import { mapFields } from 'vuex-map-fields'
|
||||
|
||||
export default {
|
||||
name: 'TriggerControlWindow',
|
||||
components: {
|
||||
Interval,
|
||||
Channel,
|
||||
},
|
||||
computed: {
|
||||
...mapFields('device', [
|
||||
'triggerList',
|
||||
'allChannels',
|
||||
'chartKey',
|
||||
]),
|
||||
},
|
||||
props: {
|
||||
mac: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
},
|
||||
created () {
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
}
|
||||
},
|
||||
mqtt: {
|
||||
},
|
||||
methods: {
|
||||
// setDisplayParam (status) {
|
||||
// this.triggerList.find(o => o.mac === this.mac).display = status
|
||||
// this.display = status
|
||||
// this.chartKey++
|
||||
// },
|
||||
updateParam () {
|
||||
const trigger = this.triggerList.find(o => o.mac === this.mac)
|
||||
this.mqttPub(taskInfo.getTaskInfo().controllerID + '/client/trigger_manager/set_parameter', JSON.stringify({
|
||||
mac: trigger.mac,
|
||||
parameter_set: trigger.parameter,
|
||||
}),
|
||||
)
|
||||
},
|
||||
mqttPub: function (topic, mes) {
|
||||
this.$mqtt.publish(topic, mes)
|
||||
},
|
||||
},
|
||||
mounted () {
|
||||
if (this.$refs.interval != null) {
|
||||
this.$refs.interval.refresh()
|
||||
}
|
||||
if (this.$refs.channel != null) {
|
||||
this.$refs.channel.forEach(ch => ch.refresh())
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
},
|
||||
destroyed () {
|
||||
},
|
||||
}
|
||||
</script>
|
||||
@@ -0,0 +1,77 @@
|
||||
<template>
|
||||
<div class="row pl-2">
|
||||
<va-radio-button
|
||||
v-for="(option, index) in optionMode"
|
||||
:key="index"
|
||||
v-model="selectMode"
|
||||
:option="optionMode[index]"
|
||||
:label="optionMode[index]"
|
||||
@click.native.stop="itemChange()"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
|
||||
import { mapFields } from 'vuex-map-fields'
|
||||
import { mapActions } from 'vuex'
|
||||
import deviceTypes from '@/store/modules/device/types'
|
||||
|
||||
export default {
|
||||
name: 'Ttl',
|
||||
components: {
|
||||
},
|
||||
computed: {
|
||||
...mapFields('device', [
|
||||
'triggerList',
|
||||
]),
|
||||
},
|
||||
props: {
|
||||
mac: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
channelIndex: {
|
||||
type: Number,
|
||||
required: true,
|
||||
},
|
||||
},
|
||||
created () {
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
inputeKey: 0,
|
||||
selectMode: 'HIGH',
|
||||
optionMode: [
|
||||
'HIGH',
|
||||
'LOW',
|
||||
],
|
||||
}
|
||||
},
|
||||
mqtt: {
|
||||
},
|
||||
methods: {
|
||||
itemChange () {
|
||||
const key = 'channel_event_' + this.channelIndex
|
||||
const obj = this.triggerList.find(o => o.mac === this.mac)
|
||||
obj.parameter[key].ttl = this.selectMode.toLowerCase()
|
||||
},
|
||||
async refresh () {
|
||||
const key = 'channel_event_' + this.channelIndex
|
||||
const obj = this.triggerList.find(o => o.mac === this.mac)
|
||||
const inputChannels = await this.deviceTriggerGetInputChannels({ mac: this.mac })
|
||||
if (inputChannels.includes(String(this.channelIndex))) {
|
||||
this.selectMode = obj.parameter[key].ttl.toUpperCase()
|
||||
}
|
||||
},
|
||||
|
||||
...mapActions('device', [deviceTypes.trigger.getInputChannels]),
|
||||
},
|
||||
mounted () {
|
||||
},
|
||||
watch: {
|
||||
},
|
||||
destroyed () {
|
||||
},
|
||||
}
|
||||
</script>
|
||||
@@ -0,0 +1,268 @@
|
||||
<template>
|
||||
<div class="row testing">
|
||||
<va-card class="mb-2" style="width: 100%; height: 5vh;">
|
||||
<div class="row">
|
||||
<va-button small style="width: 80px;" @click="scan()" :aria-disabled="true">
|
||||
SCAN
|
||||
<div v-if="scanning" class="flex-center spinner-box ml-1">
|
||||
<fulfilling-bouncing-circle-spinner
|
||||
:animation-duration="3000"
|
||||
:color="'#fff'"
|
||||
:size="15"
|
||||
>
|
||||
</fulfilling-bouncing-circle-spinner>
|
||||
</div>
|
||||
</va-button>
|
||||
|
||||
<va-select
|
||||
class="mr-1"
|
||||
style="width: 200px; height: 15px;"
|
||||
:label="'DEVICE CONNECTED'"
|
||||
v-model="deviceConnectedSelect"
|
||||
textBy="mac"
|
||||
:options="deviceConnected"
|
||||
/>
|
||||
<va-button small style="width: 120px;" @click="disconnect(deviceConnectedSelect.mac)" :color="'danger'">
|
||||
DISCONNECT
|
||||
<div v-if="disconnecting" class="flex-center spinner-box ml-1">
|
||||
<fulfilling-bouncing-circle-spinner
|
||||
:animation-duration="3000"
|
||||
:color="'#fff'"
|
||||
:size="15"
|
||||
>
|
||||
</fulfilling-bouncing-circle-spinner>
|
||||
</div>
|
||||
</va-button>
|
||||
|
||||
<va-select
|
||||
class="mr-1"
|
||||
style="width: 200px; height: 15px;"
|
||||
:label="'DEVICE FOUND'"
|
||||
v-model="deviceNewFoundSelect"
|
||||
textBy="mac"
|
||||
:options="deviceNewFound"
|
||||
/>
|
||||
<va-button small style="width: 100px;" @click="connect(deviceNewFoundSelect.mac)">
|
||||
CONNECT
|
||||
<div v-if="connecting" class="flex-center spinner-box ml-1">
|
||||
<fulfilling-bouncing-circle-spinner
|
||||
:animation-duration="3000"
|
||||
:color="'#fff'"
|
||||
:size="15"
|
||||
>
|
||||
</fulfilling-bouncing-circle-spinner>
|
||||
</div>
|
||||
</va-button>
|
||||
|
||||
<va-select
|
||||
class="mr-1"
|
||||
style="width: 200px; height: 15px;"
|
||||
:label="'DEVICE LIBRARY'"
|
||||
v-model="deviceLibrarySelect"
|
||||
textBy="mac"
|
||||
:options="deviceLibrary"
|
||||
/>
|
||||
<va-button small style="width: 100px;" @click="connect(deviceLibrarySelect.mac)">
|
||||
CONNECT
|
||||
<div v-if="connecting" class="flex-center spinner-box ml-1">
|
||||
<fulfilling-bouncing-circle-spinner
|
||||
:animation-duration="3000"
|
||||
:color="'#fff'"
|
||||
:size="15"
|
||||
>
|
||||
</fulfilling-bouncing-circle-spinner>
|
||||
</div>
|
||||
</va-button>
|
||||
<!-- <va-input
|
||||
style="width: 100px;"
|
||||
v-model="dataRefreshInterval"
|
||||
class="mb-0 mr-1"
|
||||
:label="'Refresh Interval'"
|
||||
>
|
||||
<va-button slot="append" small @click="setRefreshInterval(parseInt(dataRefreshInterval))">
|
||||
SET
|
||||
</va-button>
|
||||
</va-input> -->
|
||||
</div>
|
||||
</va-card>
|
||||
<div style="width: 100%;">
|
||||
<div
|
||||
style="width: 100%;"
|
||||
v-for="devConnected in deviceConnected"
|
||||
:key="devConnected.mac"
|
||||
>
|
||||
<testing-chart :key="chartList" class="mb-2" style="width: 100%;" :mac="devConnected.mac" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { mapFields } from 'vuex-map-fields'
|
||||
import TestingChart from './TestingChart.vue'
|
||||
import { FulfillingBouncingCircleSpinner } from 'epic-spinners'
|
||||
|
||||
export default {
|
||||
name: 'testing',
|
||||
props: {
|
||||
},
|
||||
components: {
|
||||
TestingChart,
|
||||
FulfillingBouncingCircleSpinner,
|
||||
},
|
||||
computed: {
|
||||
...mapFields('', [
|
||||
'chartkey',
|
||||
]),
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
dataRefreshTimer: null,
|
||||
dataRefreshInterval: '200',
|
||||
scanning: false,
|
||||
connecting: false,
|
||||
disconnecting: false,
|
||||
deviceConnected: [],
|
||||
deviceNewFound: [],
|
||||
deviceLibrary: [],
|
||||
deviceNewFoundSelect: '',
|
||||
deviceLibrarySelect: '',
|
||||
deviceConnectedSelect: '',
|
||||
chartList: 0,
|
||||
}
|
||||
},
|
||||
mqtt: {
|
||||
async '+/data_server/device_manager/neulive_manager/scan' (data, topic) {
|
||||
const mes = new TextDecoder('utf-8').decode(data)
|
||||
if (mes === 'start') {
|
||||
this.scanning = true
|
||||
} else {
|
||||
this.scanning = false
|
||||
this.getDeviceAll()
|
||||
this.pageToast('scan done')
|
||||
}
|
||||
},
|
||||
async '+/data_server/device_manager/neulive_manager/connect' (data, topic) {
|
||||
const mes = new TextDecoder('utf-8').decode(data)
|
||||
const status = JSON.parse(mes)
|
||||
this.connecting = false
|
||||
if (status.status === 'success') {
|
||||
this.pageToast(`connect success: ${status.mac}`)
|
||||
this.getDeviceAll()
|
||||
} else {
|
||||
this.pageToast(`connect fail: ${status.mac}`)
|
||||
}
|
||||
this.chartList++
|
||||
},
|
||||
async '+/data_server/device_manager/neulive_manager/remove' (data, topic) {
|
||||
const mes = new TextDecoder('utf-8').decode(data)
|
||||
const status = JSON.parse(mes)
|
||||
this.disconnecting = false
|
||||
this.getDeviceAll()
|
||||
this.pageToast(`disconnect ${status.mac}`)
|
||||
this.chartList++
|
||||
},
|
||||
async '+/data_server/device_manager/neulive_manager/info_all' (data, topic) {
|
||||
const mes = new TextDecoder('utf-8').decode(data)
|
||||
const infoAll = JSON.parse(mes).content
|
||||
this.deviceConnected = infoAll.connected
|
||||
this.deviceNewFound = infoAll.found
|
||||
this.deviceLibrary = infoAll.library
|
||||
this.deviceConnected.forEach(devConnected => {
|
||||
for (let i = 0; i < this.deviceLibrary.length; i++) {
|
||||
if (this.deviceLibrary[i].mac === devConnected.mac) {
|
||||
this.deviceLibrary.splice(i, 1)
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
for (let i = 0; i < this.deviceConnected.length; i++) {
|
||||
this.deviceConnected[i].id = i
|
||||
}
|
||||
for (let i = 0; i < this.deviceLibrary.length; i++) {
|
||||
this.deviceLibrary[i].id = i
|
||||
}
|
||||
for (let i = 0; i < this.deviceNewFound.length; i++) {
|
||||
this.deviceNewFound[i].id = i
|
||||
}
|
||||
this.deviceNewFoundSelect = ''
|
||||
this.deviceLibrarySelect = ''
|
||||
this.deviceConnectedSelect = ''
|
||||
},
|
||||
async '+/data_server/device_manager/neulive_manager/info' (data, topic) {
|
||||
},
|
||||
},
|
||||
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('dc:a6:32:6c:bc:b4/data_server/device_manager/neulive_manager/#')
|
||||
},
|
||||
pageMqttUnSub: function (id) {
|
||||
},
|
||||
scan () {
|
||||
this.mqttPub('dc:a6:32:6c:bc:b4/client/device_manager/neulive_manager/scan', JSON.stringify({}))
|
||||
},
|
||||
connect (mac) {
|
||||
this.connecting = true
|
||||
this.mqttPub('dc:a6:32:6c:bc:b4/client/device_manager/neulive_manager/connect', JSON.stringify({
|
||||
mac: mac,
|
||||
}))
|
||||
},
|
||||
disconnect (mac) {
|
||||
this.disconnecting = true
|
||||
this.mqttPub('dc:a6:32:6c:bc:b4/client/device_manager/neulive_manager/disconnect', JSON.stringify({
|
||||
mac: mac,
|
||||
}))
|
||||
},
|
||||
getDeviceConnected () {
|
||||
this.mqttPub('dc:a6:32:6c:bc:b4/client/device_manager/neulive_manager/info_connected', JSON.stringify({}))
|
||||
},
|
||||
getDeviceFound () {
|
||||
this.mqttPub('dc:a6:32:6c:bc:b4/client/device_manager/neulive_manager/info_found', JSON.stringify({}))
|
||||
},
|
||||
getDeviceAll () {
|
||||
this.mqttPub('dc:a6:32:6c:bc:b4/client/device_manager/neulive_manager/info_all', JSON.stringify({}))
|
||||
},
|
||||
pageToast: function (mes) {
|
||||
this.showToast(
|
||||
mes,
|
||||
{
|
||||
icon: 'fa-bell',
|
||||
position: 'bottom-right',
|
||||
duration: 4000,
|
||||
},
|
||||
)
|
||||
},
|
||||
refreshData () {
|
||||
this.chartkey++
|
||||
// if (this.chartList > 10000) {
|
||||
// this.chartkey = 0
|
||||
// }
|
||||
},
|
||||
setRefreshInterval (val) {
|
||||
if (this.dataRefreshTimer != null) {
|
||||
clearInterval(this.dataRefreshTimer)
|
||||
}
|
||||
this.dataRefreshTimer = setInterval(this.refreshData, val)
|
||||
},
|
||||
},
|
||||
watch: {
|
||||
},
|
||||
async mounted () {
|
||||
this.pageMqttSub()
|
||||
this.getDeviceAll()
|
||||
// this.setRefreshInterval(parseInt(this.dataRefreshInterval))
|
||||
},
|
||||
destroyed () {
|
||||
},
|
||||
|
||||
}
|
||||
</script>
|
||||
@@ -0,0 +1,456 @@
|
||||
<template>
|
||||
<div class="testing-chart">
|
||||
<va-card>
|
||||
<div class="row">
|
||||
<va-input
|
||||
v-model="deviceMac"
|
||||
class="mb-0 mr-1"
|
||||
:label="'MAC'"
|
||||
>
|
||||
<va-button slot="append" small @click="setMac()">
|
||||
SET
|
||||
</va-button>
|
||||
</va-input>
|
||||
<va-input
|
||||
v-model="deviceChannel"
|
||||
class="mb-0 mr-1"
|
||||
:label="'CHANNEL'"
|
||||
>
|
||||
<va-button slot="append" small @click="setChannel()">
|
||||
SET
|
||||
</va-button>
|
||||
</va-input>
|
||||
<va-input
|
||||
v-model="deviceSampleRate"
|
||||
class="mb-0 mr-1"
|
||||
:label="'SAMPLE RATE'"
|
||||
>
|
||||
<va-button slot="append" small @click="setSampleRate()">
|
||||
SET
|
||||
</va-button>
|
||||
</va-input>
|
||||
<va-input
|
||||
v-model="deviceThreshold"
|
||||
class="mb-0 mr-1"
|
||||
:label="'Threshold'"
|
||||
>
|
||||
<va-button slot="append" small @click="setThreshold()">
|
||||
SET
|
||||
</va-button>
|
||||
</va-input>
|
||||
<h6 class="mx-1 mt-2">
|
||||
TOTAL DATA POINT: {{ parseInt(chartMaxPoint / deviceThreshold) }}
|
||||
</h6>
|
||||
<va-button small @click="record()" :color="recordColor">
|
||||
{{ recordStatus }}
|
||||
</va-button>
|
||||
</div>
|
||||
<chart
|
||||
:key="chartKey"
|
||||
:ref="'chart_ref'"
|
||||
:style="'width: '+ 'auto' + '; height: ' + '500px' + ';'"
|
||||
:options="testChartData[deviceMac]"
|
||||
@dataZoom="updateZoom"
|
||||
/>
|
||||
</va-card>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { mapFields } from 'vuex-map-fields'
|
||||
import newDataZoom from '@/factories/chart/dataZoomFactory'
|
||||
import pako from 'pako'
|
||||
|
||||
export default {
|
||||
name: 'testing-chart',
|
||||
props: {
|
||||
mac: {
|
||||
type: String,
|
||||
default: 'f7:34:3b:f9:4f:30',
|
||||
},
|
||||
},
|
||||
computed: {
|
||||
...mapFields('', [
|
||||
'testChartData',
|
||||
]),
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
isSetMac: false,
|
||||
deviceMac: this.mac,
|
||||
deviceChannel: '0',
|
||||
deviceSampleRate: '10000',
|
||||
deviceThreshold: '1',
|
||||
recordStatus: 'START',
|
||||
recordColor: 'primary',
|
||||
channelList: [],
|
||||
chartKey: 0,
|
||||
chartMaxPoint: 16384,
|
||||
chartMaxPointCurrent: 16384,
|
||||
// ChartData: {
|
||||
// xAxis: [],
|
||||
// yAxis: [],
|
||||
// series: [],
|
||||
// grid: [],
|
||||
// },
|
||||
dataIndex: 0,
|
||||
lastTime: -1,
|
||||
} // sync_data/data/{self._device_mac}/{str(channel)}
|
||||
},
|
||||
mqtt: {
|
||||
async '+/data_server/device_manager/neulive_manager/info' (data, topic) {
|
||||
const mes = new TextDecoder('utf-8').decode(data)
|
||||
const info = JSON.parse(mes).content
|
||||
if (info.mac !== this.deviceMac) {
|
||||
return
|
||||
}
|
||||
|
||||
if (info.status === 'RECORDING') {
|
||||
this.recordStatus = 'STOP'
|
||||
this.recordColor = 'danger'
|
||||
} else {
|
||||
this.recordStatus = 'START'
|
||||
}
|
||||
this.deviceThreshold = info.threshold.toString()
|
||||
this.deviceSampleRate = parseInt(info.parameter.SAMPLE_RATE)
|
||||
this.channelList = info.parameter.RECORDING_CH
|
||||
this.deviceChannel = this.channelList.join(',')
|
||||
this.chartMaxPointCurrent = parseInt((this.chartMaxPoint / this.channelList.length) / this.deviceThreshold)
|
||||
console.log(this.chartMaxPointCurrent)
|
||||
|
||||
this.initChart()
|
||||
this.chartKey++
|
||||
},
|
||||
async '+/data_server/device_manager/neulive_manager/record' (data, topic) {
|
||||
const mes = new TextDecoder('utf-8').decode(data)
|
||||
const info = JSON.parse(mes)
|
||||
if (info.mac !== this.deviceMac) {
|
||||
return
|
||||
}
|
||||
this.recordStatus = info.status.toUpperCase()
|
||||
this.recordStatus = this.recordStatus === 'STOP' ? 'START' : 'STOP'
|
||||
this.recordColor = this.recordStatus === 'STOP' ? 'danger' : 'primary'
|
||||
},
|
||||
async '+/data_server/device_manager/neulive_manager/set_parameter' (data, topic) {
|
||||
this.mqttPub('dc:a6:32:6c:bc:b4/client/device_manager/neulive_manager/info', JSON.stringify({
|
||||
mac: this.deviceMac,
|
||||
}))
|
||||
},
|
||||
async '+/data_server/device_manager/neulive_manager/neulive_device/neulive_runtime/sync_data/+/+' (data, topic) {
|
||||
const topicList = topic.split('/')
|
||||
if (!this.isSetMac || this.deviceMac !== topicList[topicList.length - 2]) {
|
||||
return
|
||||
}
|
||||
let mes = new TextDecoder('utf-8').decode(data)
|
||||
mes = this.unzip(mes)
|
||||
|
||||
// const t2 = Date.now()
|
||||
const channel = topicList[topicList.length - 1]
|
||||
const mesList = mes.split(',')
|
||||
const sampleRate = parseInt(mesList[0])
|
||||
const timeSpare = parseInt(1e6 / sampleRate * this.channelList.length)
|
||||
const timePairList = mesList[1].split(' ')
|
||||
let dataList = mesList[2].split(' ')
|
||||
let timeList = []
|
||||
for (let i = 0; i < timePairList.length - 1; i = i + 2) {
|
||||
// console.log('******', i, timeList.length)
|
||||
const startTime = parseInt(timePairList[i])
|
||||
while (this.lastTime + timeSpare < startTime && this.lastTime > 0) {
|
||||
const diff = parseInt((startTime - (this.lastTime + timeSpare)) / timeSpare)
|
||||
const _tmpTimeList = Array.from({ length: diff }, (_, i) => startTime + (timeSpare * i))
|
||||
const _tmpDataList = Array.from({ length: diff }, (_, i) => null)
|
||||
dataList.splice(timeList.length, 0, ..._tmpDataList)
|
||||
// TODO Maximum call stack size exceeded
|
||||
timeList = timeList.concat(_tmpTimeList)
|
||||
this.lastTime = _tmpTimeList[_tmpTimeList.length - 1]
|
||||
// console.log('######', _tmpTimeList.length, timeList.length)
|
||||
}
|
||||
// timeList.push(startTime)
|
||||
const count = parseInt(timePairList[i + 1])
|
||||
const tmpList = Array.from({ length: count }, (_, i) => startTime + (timeSpare * i))
|
||||
this.lastTime = tmpList[tmpList.length - 1]
|
||||
// console.log(startTime, tmpList)
|
||||
timeList = timeList.concat(tmpList)
|
||||
}
|
||||
// console.log(mes)
|
||||
|
||||
dataList = this.testChartData[this.deviceMac].series[channel].data.concat(dataList)
|
||||
timeList = this.testChartData[this.deviceMac].xAxis[channel].data.concat(timeList)
|
||||
|
||||
// console.log(dataList.length, timeList.length)
|
||||
|
||||
const maxPoint = this.chartMaxPointCurrent
|
||||
|
||||
if (dataList.length > maxPoint) {
|
||||
dataList.splice(0, (dataList.length - maxPoint))
|
||||
timeList.splice(0, (timeList.length - maxPoint))
|
||||
}
|
||||
|
||||
// console.log(timeList)
|
||||
|
||||
this.testChartData[this.deviceMac].series[channel].data = dataList
|
||||
this.testChartData[this.deviceMac].xAxis[channel].data = timeList
|
||||
// this.testChartData[this.deviceMac].xAxis[0].data = Array.from({ length: dataList.length }, (_, i) => i + 1)
|
||||
|
||||
if (parseInt(channel) === this.channelList[this.channelList.length - 1]) {
|
||||
this.chartKey++
|
||||
if (this.chartKey > 10000) {
|
||||
this.chartKey = 0
|
||||
}
|
||||
}
|
||||
// console.log('total', Date.now() - t2)
|
||||
},
|
||||
},
|
||||
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) {
|
||||
},
|
||||
pageMqttUnSub: function (id) {
|
||||
},
|
||||
unzip (b64Data) {
|
||||
let strData = atob(b64Data)
|
||||
// Convert binary string to character-number array
|
||||
const charData = strData.split('').map(function (x) { return x.charCodeAt(0) })
|
||||
// Turn number array into byte-array
|
||||
const binData = new Uint8Array(charData)
|
||||
// // unzip
|
||||
const data = pako.inflate(binData)
|
||||
// Convert gunzipped byteArray back to ascii string:
|
||||
strData = new TextDecoder('utf-8').decode(data)
|
||||
return strData
|
||||
},
|
||||
makeGrid (index, length) {
|
||||
const _height = (100 / length) - 2 + '%'
|
||||
const _top = index * (100 / length) + 2 + '%'
|
||||
const _left = '0%'
|
||||
const _right = '3%'
|
||||
return {
|
||||
index: index,
|
||||
top: _top,
|
||||
height: _height,
|
||||
left: _left,
|
||||
right: _right,
|
||||
containLabel: true,
|
||||
}
|
||||
},
|
||||
makeSeries (xAxisIndex, yAxisIndex) {
|
||||
return {
|
||||
type: 'line',
|
||||
data: [],
|
||||
sampling: 'average',
|
||||
// sampling: function (frame) {
|
||||
// return frame[0]
|
||||
// },
|
||||
connectNulls: true,
|
||||
animation: false,
|
||||
hoverAnimation: false,
|
||||
xAxisIndex: xAxisIndex,
|
||||
yAxisIndex: yAxisIndex,
|
||||
itemStyle: {
|
||||
normal: {
|
||||
},
|
||||
},
|
||||
lineStyle: {
|
||||
width: 1.5,
|
||||
},
|
||||
showSymbol: false,
|
||||
showAllSymbol: false,
|
||||
}
|
||||
},
|
||||
makeXAxis (gridIndex) {
|
||||
return {
|
||||
show: false,
|
||||
type: 'category',
|
||||
gridIndex: gridIndex,
|
||||
min: 'dataMin',
|
||||
max: 'dataMax',
|
||||
axisLabel: {
|
||||
formatter: function (value) {
|
||||
let microSec = value
|
||||
let miniSec = parseInt(microSec / 1e3)
|
||||
let sec = parseInt(miniSec / 1e3)
|
||||
let hours = Math.floor(sec / 3600)
|
||||
let minutes = Math.floor((sec - (hours * 3600)) / 60)
|
||||
sec = sec % 60
|
||||
miniSec = miniSec % 1e3
|
||||
microSec = microSec % 1e3
|
||||
|
||||
if (hours < 10) { hours = '0' + hours }
|
||||
if (minutes < 10) { minutes = '0' + minutes }
|
||||
if (sec < 10) { sec = '0' + sec }
|
||||
return hours + 'h ' + minutes + 'm ' + sec + 's ' + miniSec + 'ms ' + microSec + 'us'
|
||||
},
|
||||
},
|
||||
data: [],
|
||||
}
|
||||
},
|
||||
makeYAxis (gridIndex) {
|
||||
return {
|
||||
type: 'value',
|
||||
gridIndex: gridIndex,
|
||||
splitNumber: 1,
|
||||
splitLine: {
|
||||
show: false,
|
||||
},
|
||||
axisLabel: {
|
||||
formatter: function (value) {
|
||||
return value + 'uV'
|
||||
},
|
||||
},
|
||||
min: -2047,
|
||||
max: 2047,
|
||||
}
|
||||
},
|
||||
initChart () {
|
||||
this.testChartData[this.deviceMac] = {
|
||||
xAxis: [],
|
||||
yAxis: [],
|
||||
series: [],
|
||||
dataZoom: newDataZoom(),
|
||||
tooltip: {
|
||||
hideDelay: 5000,
|
||||
trigger: 'axis',
|
||||
backgroundColor: 'rgba(255, 255, 255, 1)',
|
||||
borderColor: 'rgba(0, 0, 200, 0.2)',
|
||||
borderWidth: 1,
|
||||
// borderRadius: 0,
|
||||
padding: 10,
|
||||
formatter: function (params) {
|
||||
const timeFormat = function (value) {
|
||||
let microSec = value
|
||||
let miniSec = parseInt(microSec / 1e3)
|
||||
let sec = parseInt(miniSec / 1e3)
|
||||
let hours = Math.floor(sec / 3600)
|
||||
let minutes = Math.floor((sec - (hours * 3600)) / 60)
|
||||
sec = sec % 60
|
||||
miniSec = miniSec % 1e3
|
||||
microSec = microSec % 1e3
|
||||
|
||||
if (hours < 10) { hours = '0' + hours }
|
||||
if (minutes < 10) { minutes = '0' + minutes }
|
||||
if (sec < 10) { sec = '0' + sec }
|
||||
return hours + 'h ' + minutes + 'm ' + sec + 's ' + miniSec + 'ms ' + microSec + 'us'
|
||||
}
|
||||
const time = timeFormat(parseInt(params[0].name))
|
||||
let tip = '<span style="color: black;">' + time + '</span><br>'
|
||||
for (let i = 0; i < params.length; i++) {
|
||||
const name = params[i].seriesIndex
|
||||
const style = 'color: ' + params[i].color
|
||||
tip += '<span style="' + style + '">channel ' + name + ': </span><span style="' + style + '">' +
|
||||
params[i].value + ' uV</span><br>'
|
||||
}
|
||||
return tip
|
||||
},
|
||||
},
|
||||
grid: [],
|
||||
}
|
||||
this.testChartData[this.deviceMac].dataZoom[0].bottom = '0%'
|
||||
|
||||
this.testChartData[this.deviceMac].dataZoom[0].xAxisIndex = this.channelList
|
||||
this.testChartData[this.deviceMac].dataZoom[1].xAxisIndex = this.channelList
|
||||
this.testChartData[this.deviceMac].dataZoom[2].yAxisIndex = this.channelList
|
||||
|
||||
const gridLength = this.channelList.length
|
||||
for (let gridIndex = 0; gridIndex < gridLength; gridIndex++) {
|
||||
this.testChartData[this.deviceMac].grid.push(this.makeGrid(gridIndex, gridLength))
|
||||
this.testChartData[this.deviceMac].xAxis.push(this.makeXAxis(gridIndex))
|
||||
this.testChartData[this.deviceMac].yAxis.push(this.makeYAxis(gridIndex))
|
||||
this.testChartData[this.deviceMac].series.push(this.makeSeries(gridIndex, gridIndex))
|
||||
if (gridIndex === gridLength - 1) {
|
||||
this.testChartData[this.deviceMac].xAxis[gridLength - 1].show = true
|
||||
}
|
||||
}
|
||||
},
|
||||
record () {
|
||||
this.mqttPub('dc:a6:32:6c:bc:b4/client/device_manager/neulive_manager/record', JSON.stringify({
|
||||
mac: this.deviceMac,
|
||||
status: this.recordStatus.toLowerCase(),
|
||||
}))
|
||||
this.recordStatus = this.recordStatus === 'STOP' ? 'START' : 'STOP'
|
||||
this.recordColor = this.recordStatus === 'STOP' ? 'danger' : 'primary'
|
||||
if (this.recordStatus === 'START') {
|
||||
this.chartKey++
|
||||
} else {
|
||||
this.initChart()
|
||||
this.chartKey++
|
||||
}
|
||||
},
|
||||
setMac () {
|
||||
this.pageMqttSub()
|
||||
this.mqttPub('dc:a6:32:6c:bc:b4/client/device_manager/neulive_manager/info', JSON.stringify({
|
||||
mac: this.deviceMac,
|
||||
}))
|
||||
this.isSetMac = true
|
||||
},
|
||||
setSampleRate () {
|
||||
this.mqttPub('dc:a6:32:6c:bc:b4/client/device_manager/neulive_manager/set_parameter', JSON.stringify({
|
||||
mac: this.deviceMac,
|
||||
parameter_set: {
|
||||
SAMPLE_RATE: parseInt(this.deviceSampleRate),
|
||||
},
|
||||
}))
|
||||
},
|
||||
setThreshold () {
|
||||
this.mqttPub('dc:a6:32:6c:bc:b4/client/device_manager/neulive_manager/set_threshold', JSON.stringify({
|
||||
mac: this.deviceMac,
|
||||
threshold: parseInt(this.deviceThreshold),
|
||||
}))
|
||||
this.chartMaxPointCurrent = parseInt((this.chartMaxPoint / this.channelList.length) / this.deviceThreshold)
|
||||
},
|
||||
setChannel () {
|
||||
this.channelList = this.deviceChannel.split(',').map(Number)
|
||||
this.chartMaxPointCurrent = parseInt((this.chartMaxPoint / this.channelList.length) / this.deviceThreshold)
|
||||
this.mqttPub('dc:a6:32:6c:bc:b4/client/device_manager/neulive_manager/set_parameter', JSON.stringify({
|
||||
mac: this.deviceMac,
|
||||
parameter_set: {
|
||||
RECORDING_CH: this.channelList,
|
||||
},
|
||||
}))
|
||||
},
|
||||
updateZoom: function (e) {
|
||||
if (e.batch != null) {
|
||||
// console.log(e.batch)
|
||||
e.batch.forEach(dataZoom => {
|
||||
const id = parseInt(dataZoom.dataZoomId.substr(dataZoom.dataZoomId.length - 3, dataZoom.dataZoomId.length - 1))
|
||||
if (id === 1) {
|
||||
this.testChartData[this.deviceMac].dataZoom[0].start = dataZoom.start
|
||||
this.testChartData[this.deviceMac].dataZoom[0].end = dataZoom.end
|
||||
// this.startTime = parseInt(this.maxTime * dataZoom.start / 100)
|
||||
// this.endTime = parseInt(this.maxTime * dataZoom.end / 100)
|
||||
// this.windowLength = this.endTime - this.startTime
|
||||
// this.chartOverviewData.dataZoom[0].start = dataZoom.start
|
||||
// this.chartOverviewData.dataZoom[0].end = dataZoom.end
|
||||
}
|
||||
})
|
||||
} else {
|
||||
const id = parseInt(e.dataZoomId.substr(e.dataZoomId.length - 3, e.dataZoomId.length - 1))
|
||||
if (id === 0) {
|
||||
this.testChartData[this.deviceMac].dataZoom[0].start = e.start
|
||||
this.testChartData[this.deviceMac].dataZoom[0].end = e.end
|
||||
// this.startTime = parseInt(this.maxTime * e.start / 100)
|
||||
// this.endTime = parseInt(this.maxTime * e.end / 100)
|
||||
// this.windowLength = this.endTime - this.startTime
|
||||
// this.chartOverviewData.dataZoom[0].start = e.start
|
||||
// this.chartOverviewData.dataZoom[0].end = e.end
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
watch: {
|
||||
},
|
||||
async mounted () {
|
||||
this.setMac()
|
||||
},
|
||||
destroyed () {
|
||||
},
|
||||
|
||||
}
|
||||
</script>
|
||||
@@ -11,8 +11,8 @@ import analysis from './analysis'
|
||||
import sdcard from './sdcard'
|
||||
import connection from './connection'
|
||||
|
||||
// axios.defaults.baseURL = 'http://192.168.3.211:3000'
|
||||
axios.defaults.baseURL = 'http://' + location.href.split('/')[2].split(':')[0] + ':3000'
|
||||
axios.defaults.baseURL = 'http://192.168.3.211:3000'
|
||||
// axios.defaults.baseURL = 'http://' + location.href.split('/')[2].split(':')[0] + ':3000'
|
||||
|
||||
const api = {
|
||||
axios,
|
||||
|
||||
@@ -18,6 +18,8 @@ function newState () {
|
||||
lighterGray: '#ddd',
|
||||
},
|
||||
},
|
||||
testChartData: {},
|
||||
chartkey: {},
|
||||
isLoading: true,
|
||||
licenseCheck: true,
|
||||
}
|
||||
|
||||
@@ -112,6 +112,11 @@ export default new Router({
|
||||
path: 'data-replay/elite/:metaList?',
|
||||
component: () => import('../components/analysis/replay/elite/EliteDataReplay.vue'),
|
||||
},
|
||||
{
|
||||
name: 'testing',
|
||||
path: 'testing',
|
||||
component: () => import('../components/testing/Testing.vue'),
|
||||
},
|
||||
{
|
||||
name: 'data-spike',
|
||||
path: 'data-spike/:metaList?',
|
||||
|
||||
@@ -3,6 +3,7 @@ import Vuex from 'vuex'
|
||||
import VuexI18n from 'vuex-i18n' // load vuex i18n module
|
||||
// import app from './modules/app'
|
||||
import setting from './modules/setting'
|
||||
import device from './modules/device'
|
||||
import taskContent from './modules/task/content'
|
||||
|
||||
import state from './state'
|
||||
@@ -25,6 +26,7 @@ const store = new Vuex.Store({
|
||||
replay,
|
||||
spike,
|
||||
setting,
|
||||
device,
|
||||
download,
|
||||
file,
|
||||
},
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
const controllerActs = {
|
||||
}
|
||||
|
||||
export default controllerActs
|
||||
@@ -0,0 +1,9 @@
|
||||
import controllerAct from './controllerAct'
|
||||
import triggerAct from './triggerAct'
|
||||
import triggerChartAct from './triggerChartAct'
|
||||
|
||||
export default {
|
||||
...controllerAct,
|
||||
...triggerAct,
|
||||
...triggerChartAct,
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
import types from '@/store/modules/device/types'
|
||||
|
||||
const typePath = types.trigger
|
||||
|
||||
const triggerActs = {
|
||||
/**
|
||||
* get trigger output channels set
|
||||
* @param {string} mac
|
||||
* @return {set}
|
||||
*/
|
||||
[typePath.getOutputChannels]: async ({ state, getters, commit, dispatch }, payload) => {
|
||||
const outputChannels = new Set()
|
||||
const obj = state.triggerList.find(o => o.mac === payload.mac)
|
||||
const channelSet = obj.parameter.bitmode.toString(2).split('').reverse()
|
||||
channelSet.forEach((element, index) => {
|
||||
if (parseInt(element) > 0) {
|
||||
outputChannels.add(index)
|
||||
}
|
||||
})
|
||||
return outputChannels
|
||||
},
|
||||
/**
|
||||
* get trigger input channels list
|
||||
* @param {string} mac
|
||||
* @return {array}
|
||||
*/
|
||||
[typePath.getInputChannels]: async ({ state, getters, commit, dispatch }, payload) => {
|
||||
const outputChannels = Array.from(await dispatch(typePath.getOutputChannels, { mac: payload.mac }))
|
||||
const remain = state.allChannels.filter(x => !outputChannels.includes(x))
|
||||
const obj = state.triggerList.find(o => o.mac === payload.mac)
|
||||
const inputChannels = []
|
||||
for (const index of remain) {
|
||||
const key = 'channel_event_' + index
|
||||
if (Object.keys(obj.parameter[key]).length !== 0) {
|
||||
inputChannels.push(index)
|
||||
}
|
||||
}
|
||||
return inputChannels
|
||||
},
|
||||
/**
|
||||
* get trigger active (input + output) channels list
|
||||
* @param {string} mac
|
||||
* @return {array}
|
||||
*/
|
||||
[typePath.getActiveChannels]: async ({ state, getters, commit, dispatch }, payload) => {
|
||||
const outputChannels = Array.from(await dispatch(typePath.getOutputChannels, { mac: payload.mac }))
|
||||
const inputChannels = await dispatch(typePath.getInputChannels, { mac: payload.mac })
|
||||
const union = [...new Set([...outputChannels, ...inputChannels])].sort()
|
||||
var result = union.map(function (x) {
|
||||
return parseInt(x, 10)
|
||||
})
|
||||
return result
|
||||
},
|
||||
}
|
||||
|
||||
export default triggerActs
|
||||
@@ -0,0 +1,20 @@
|
||||
import types from '@/store/modules/device/types'
|
||||
|
||||
const typePath = types.triggerChart
|
||||
|
||||
const triggerChartActs = {
|
||||
/**
|
||||
* set trigger chart display or not
|
||||
*/
|
||||
[typePath.setDisplay]: async ({ state, getters, commit, dispatch }, payload) => {
|
||||
state.triggerList.forEach((element, index) => {
|
||||
if (element.status === 'RUNNING') {
|
||||
element.display = true
|
||||
} else {
|
||||
element.display = false
|
||||
}
|
||||
})
|
||||
},
|
||||
}
|
||||
|
||||
export default triggerChartActs
|
||||
@@ -0,0 +1,6 @@
|
||||
|
||||
import { getField } from 'vuex-map-fields'
|
||||
|
||||
export default {
|
||||
getField,
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
import actions from './actions'
|
||||
import getters from './getters'
|
||||
import mutations from './mutations'
|
||||
import state from './state'
|
||||
|
||||
export default {
|
||||
namespaced: true,
|
||||
state: state,
|
||||
getters: getters,
|
||||
actions: actions,
|
||||
mutations: mutations,
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
const controllerMutations = {
|
||||
}
|
||||
|
||||
export default controllerMutations
|
||||
@@ -0,0 +1,7 @@
|
||||
import controllerMut from './controllerMut'
|
||||
import { updateField } from 'vuex-map-fields'
|
||||
|
||||
export default {
|
||||
...controllerMut,
|
||||
updateField,
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
function newState () {
|
||||
return {
|
||||
triggerList: [],
|
||||
chartKey: 0, // chart refresh key
|
||||
allChannels: [0, 1, 2, 3], // trigger channel
|
||||
}
|
||||
}
|
||||
|
||||
export default newState
|
||||
@@ -0,0 +1,13 @@
|
||||
|
||||
const types = {
|
||||
trigger: {
|
||||
getOutputChannels: 'deviceTriggerGetOutputChannels',
|
||||
getInputChannels: 'deviceTriggerGetInputChannels',
|
||||
getActiveChannels: 'deviceTriggerGetActiveChannels',
|
||||
},
|
||||
triggerChart: {
|
||||
setDisplay: 'deviceTriggerChartSetDisplay',
|
||||
},
|
||||
}
|
||||
|
||||
export default types
|
||||
@@ -4,34 +4,81 @@ import golbalMethods from '@/data/global/global'
|
||||
const typePath = types.export
|
||||
const typePathDownload = types.download
|
||||
|
||||
const NeuliveParameterOrder = ['RECORDING_CH', 'AXIS_CH', 'AMP_GAIN', 'SAMPLE_RATE']
|
||||
const NeuliveParameterOrder = ['AXIS_CH', 'AMP_GAIN', 'SAMPLE_RATE'] // all version neulive common param
|
||||
const Neulive30NameList = ['Neulive3.0', 'Neulive3.1']
|
||||
const Neulive35NameList = ['Neulive3.5', 'Neulive3.5-REC', 'Neulive3.5-STI']
|
||||
const Neulive35NameList = ['Neulive3.5', 'Neulive3.5-REC', 'Neulive3.5-STI', 'Neulive3.5ex']
|
||||
const Neulive30AmpGain = [100, 400, 800]
|
||||
const Neulive35AmpGain = [100, 500, 300]
|
||||
|
||||
const exportActs = {
|
||||
[typePath.getHeader]: function ({ state, getters, commit, dispatch }, payload) {
|
||||
|
||||
[typePath.getHeader]: async function ({ state, getters, commit, dispatch }, payload) {
|
||||
const meta = state.metaInfo
|
||||
const device = state.downloadInfo.device
|
||||
const deviceHeader = ['Device', meta.device.device_name, golbalMethods.transMac(meta.device.device_address)]
|
||||
const libraryHeader = ['Libaray', meta.device.library_name, meta.device.library_version]
|
||||
const parameter = []
|
||||
// [Region] for neulive 3.5 ex
|
||||
const chipIndex = await dispatch(typePath.getChipIndex, { downloadInfo: state.downloadInfo })
|
||||
// [EndRegion]
|
||||
|
||||
if (device[0] === 'Neulive') {
|
||||
NeuliveParameterOrder.forEach(p => {
|
||||
const value = meta.parameter_set[p]
|
||||
if (p === 'RECORDING_CH') {
|
||||
let result = ''
|
||||
const channelList = value.toString(2).split('').reverse()
|
||||
channelList.forEach((_value, _index) => {
|
||||
// device-specific param
|
||||
if (device[1] === '3.5') {
|
||||
let result = ''
|
||||
const lowChannelList = meta.parameter_set.RECORDING_CH_L.toString(2).split('').reverse()
|
||||
lowChannelList.forEach((_value, _index) => {
|
||||
if (_value === '1') {
|
||||
result = result + `${_index + 1},`
|
||||
}
|
||||
})
|
||||
const highChannelList = meta.parameter_set.RECORDING_CH_H.toString(2).split('').reverse()
|
||||
highChannelList.forEach((_value, _index) => {
|
||||
if (_value === '1') {
|
||||
result = result + `${_index + 33},`
|
||||
}
|
||||
})
|
||||
result = result.slice(0, -1)
|
||||
parameter.push(['Record channels', result])
|
||||
} else if (device[1] === '3.5ex') {
|
||||
let result = ''
|
||||
if (chipIndex === 1) {
|
||||
const lowChannelList = meta.parameter_set.REC_CH_DEV00.toString(2).split('').reverse()
|
||||
lowChannelList.forEach((_value, _index) => {
|
||||
if (_value === '1') {
|
||||
result = result + `${_index + 1},`
|
||||
}
|
||||
})
|
||||
result = result.slice(0, -1)
|
||||
parameter.push(['Record channels', result])
|
||||
} else if (p === 'AXIS_CH') {
|
||||
} else if (chipIndex === 2) {
|
||||
const highChannelList = meta.parameter_set.REC_CH_DEV01.toString(2).split('').reverse()
|
||||
highChannelList.forEach((_value, _index) => {
|
||||
if (_value === '1') {
|
||||
result = result + `${_index + 33},`
|
||||
}
|
||||
})
|
||||
}
|
||||
result = result.slice(0, -1)
|
||||
parameter.push(['Record channels', result])
|
||||
} else {
|
||||
let result = ''
|
||||
const channelList = meta.parameter_set.RECORDING_CH.toString(2).split('').reverse()
|
||||
channelList.forEach((_value, _index) => {
|
||||
if (_value === '1') {
|
||||
result = result + `${_index + 1},`
|
||||
}
|
||||
})
|
||||
result = result.slice(0, -1)
|
||||
parameter.push(['Record channels', result])
|
||||
}
|
||||
|
||||
// common param
|
||||
NeuliveParameterOrder.forEach(p => {
|
||||
if (!(p in meta.parameter_set)) {
|
||||
return
|
||||
}
|
||||
const value = meta.parameter_set[p]
|
||||
|
||||
if (p === 'AXIS_CH') {
|
||||
let result = ''
|
||||
const channelList = value.toString(2).split('').reverse()
|
||||
channelList.forEach((_value, _index) => {
|
||||
@@ -58,8 +105,18 @@ const exportActs = {
|
||||
parameter.push(['Amp gain', Neulive35AmpGain[value]])
|
||||
}
|
||||
} else if (p === 'SAMPLE_RATE') {
|
||||
const recordChannel = JSON.parse(meta.channels).filter(ch => parseInt(ch) < 256)
|
||||
parameter.push(['Sample Rate', parseInt(value / recordChannel.length)])
|
||||
if (device[1] === '3.5ex') {
|
||||
if (chipIndex === 1) {
|
||||
const chip1RecordChannel = JSON.parse(meta.channels).filter(ch => (ch >= 0 && ch <= 31))
|
||||
parameter.push(['Sample Rate', parseInt(value / chip1RecordChannel.length)])
|
||||
} else if (chipIndex === 2) {
|
||||
const chip2RecordChannel = JSON.parse(meta.channels).filter(ch => (ch >= 32 && ch <= 63))
|
||||
parameter.push(['Sample Rate', parseInt(value / chip2RecordChannel.length)])
|
||||
}
|
||||
} else {
|
||||
const recordChannel = JSON.parse(meta.channels).filter(ch => parseInt(ch) < 256)
|
||||
parameter.push(['Sample Rate', parseInt(value / recordChannel.length)])
|
||||
}
|
||||
}
|
||||
})
|
||||
} else if (device[0] === 'Elite') {
|
||||
@@ -285,6 +342,12 @@ const exportActs = {
|
||||
|
||||
exportString = null
|
||||
},
|
||||
|
||||
// for neulive 3.5ex
|
||||
[typePath.getChipIndex]: async function ({ state, getters, commit, dispatch }, payload) {
|
||||
const { downloadInfo } = payload
|
||||
return downloadInfo.channel.every((val, i, arr) => val < 32) ? 1 : 2
|
||||
},
|
||||
}
|
||||
|
||||
export default exportActs
|
||||
|
||||
@@ -92,7 +92,7 @@ const rawActs = {
|
||||
if (raw.sd_data !== null && raw.sd_data.length > 0) {
|
||||
const encodedData = raw.sd_data.split('"***"').slice(0, -1)
|
||||
const unzipDatas = encodedData.map(ctx => {
|
||||
return ctx.split(' ')
|
||||
return ctx.split(' ').filter(el => el !== '')
|
||||
})
|
||||
|
||||
for (let i = 0; i <= unzipDatas.length - 1; i++) {
|
||||
|
||||
@@ -20,6 +20,7 @@ const types = {
|
||||
getHeader: 'getHeaderExport',
|
||||
getTitle: 'getTitleExport',
|
||||
getData: 'getDataExport',
|
||||
getChipIndex: 'getChipIndexExport',
|
||||
},
|
||||
raw: {
|
||||
rawDataByID: 'rawDataByIDRaw',
|
||||
|
||||
Reference in New Issue
Block a user