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
62 changed files with 1831 additions and 2380 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',
@@ -8,7 +8,7 @@
<script>
import { mapFields } from 'vuex-map-fields'
import paramTable from '@/data/config-table/index.js'
import paramTable from '@/data/param-table/index.js'
export default {
name: 'show-parameter',
@@ -380,19 +380,17 @@ export default {
}
} else if (this.deviceName === 'EliteZM15' || this.deviceName === 'EliteEIS') {
const mode = this.mode = params.MODE
const config = paramTable.getConfig(this.deviceName)
const modeConfig = paramTable.getModeConfig(this.deviceName, mode)
const modeName = modeConfig.name
const showParams = modeConfig.showParameter
const modeName = paramTable[this.deviceName].MODE[mode].name
const showParams = paramTable[this.deviceName].MODE[mode].showParameter
this.showDict.MODE = modeName
if (modeName === 'Pulse Sensing') {
const duplicateParam = ['V_initial', 't_pulse', 'CURR_REC']
for (let i = 0; i < 4; i++) {
const key = 'segment_order'
const order = config[key].outputReadabilityData(params[key], 1, i)
const order = paramTable[this.deviceName][key].outputReadabilityData(params[key], 1, i)
if (parseInt(order) >= 0) { // if === -1, 代表沒有使用這個block
for (const key of duplicateParam) {
this.fillShowDict(key, config[key].outputReadabilityData(params[key], 1, i), i)
this.fillShowDict(key, paramTable[this.deviceName][key].outputReadabilityData(params[key], 1, i), i)
}
}
}
@@ -411,17 +409,16 @@ export default {
this.dump()
},
fillShowDict (key, value, index = -1) {
const config = paramTable.getConfig(this.deviceName)
const expVal = config[key].defaultUnit
? config[key].outputReadabilityData(value, config[key].unit[config[key].defaultUnit])
: config[key].outputReadabilityData(value)
let name = typeof (config[key].showName) === 'function'
? config[key].showName(this.mode)
: config[key].showName
const expVal = paramTable[this.deviceName][key].defaultUnit
? paramTable[this.deviceName][key].outputReadabilityData(value, paramTable[this.deviceName][key].unit[paramTable[this.deviceName][key].defaultUnit])
: paramTable[this.deviceName][key].outputReadabilityData(value)
let name = typeof (paramTable[this.deviceName][key].showName) === 'function'
? paramTable[this.deviceName][key].showName(this.mode)
: paramTable[this.deviceName][key].showName
if (index >= 0) {
name += ` ${index + 1}`
}
const unit = config[key].defaultUnit
const unit = paramTable[this.deviceName][key].defaultUnit
this.showDict[name] = unit !== undefined ? expVal.toString() + unit : expVal.toString()
},
dump () {
+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>
+2 -2
View File
@@ -22,7 +22,7 @@ import { mapFields } from 'vuex-map-fields'
import newDownload from '@/factories/file/downloadFactory'
import newChannel from '@/factories/file/channelFactory'
import { taskInfo } from '@/data/task/TaskInfo'
import configTable from '@/data/config-table/index'
import paramTable from '@/data/param-table/index'
export default {
name: 'Download',
@@ -108,7 +108,7 @@ export default {
}
if (meta !== undefined) {
this.metaInfo = meta
const channelParamObj = configTable.getModeConfig(meta.device.library_name, meta.parameter_set.MODE).channels
const channelParamObj = paramTable[meta.device.library_name].MODE[meta.parameter_set.MODE].channels
const channelArray = allChannel === 'all' ? JSON.parse(this.metaInfo.channels) : Object.keys(channelParamObj).filter(ele => ele !== 'time')
const channelList = []
+2 -2
View File
@@ -26,7 +26,7 @@ import newDownload from '@/factories/file/downloadFactory'
import newChannel from '@/factories/file/channelFactory'
import progressModal from '@/components/common/progressBarByValueModal/progressModal.vue'
import { taskInfo } from '@/data/task/TaskInfo'
import configTable from '@/data/config-table/index'
import paramTable from '@/data/param-table/index'
export default {
name: 'DownloadOffline',
@@ -113,7 +113,7 @@ export default {
}
if (meta !== undefined) {
this.metaInfo = meta
const channelParamObj = configTable.getModeConfig(meta.device.library_name, meta.parameter_set.MODE).channels
const channelParamObj = paramTable[meta.device.library_name].MODE[meta.parameter_set.MODE].channels
const channelArray = allChannel === 'all' ? JSON.parse(this.metaInfo.channels) : Object.keys(channelParamObj).filter(ele => ele !== 'time')
const channelList = []
@@ -6,51 +6,29 @@
</div>
</div>
<div>
<device-parameter-recording
:ref="'device_parameter_ref'"
:parameter="parameter"
:library="'EliteEDC1.5'"
@setParameter="setParameter"
@setParameterWithDebounce="setParameterWithDebounce"
/>
<elite-parameter-window></elite-parameter-window>
</div>
</div>
</template>
<script>
import newCondition from '@/factories/project/conditionFactory'
import { mapActions, mapGetters } from 'vuex'
import { mapFields } from 'vuex-map-fields'
import types from '@/store/modules/project/types'
import DeviceParameterRecording from '@/components/task/content/parameter/DeviceParameterRecording.vue'
import _ from 'lodash'
import configTable from '@/data/config-table/index'
import newCondition from '@/factories/project/conditionFactory'
import EliteParameterWindow from '@/components/project/task/config/parameter/EliteParameterWindow'
export default {
name: 'project-task-config-parameter',
components: {
DeviceParameterRecording,
EliteParameterWindow,
},
computed: {
...mapGetters('project', [
types.task.getSelect,
types.task.getParameterSet,
types.project.getDevice,
types.project.getSelect,
]),
...mapFields('project', [
'taskViewPanel',
'taskSelectKey',
'deviceSelectKey',
'taskSelect',
]),
},
data () {
return {
parameter: {},
conditionList: newCondition(),
deviceSelected: null,
parameterUUID: '',
device: null,
config: null,
}
},
methods: {
@@ -60,54 +38,8 @@ export default {
selectCondition: function (condition) {
condition.select = !condition.select
},
setParameter: function (name, value) {
this.parameter = Object.assign({}, this.parameter)
if (this.parameterUUID === '') {
this.parameterUUID = this.GLOBAL.getUUID()
}
this.setParameterSetTask({
parameterSet: {
[name]: value,
target: this.deviceSelectKey,
},
parameterKey: this.parameterUUID,
})
},
setParameterWithDebounce: _.debounce(function (name, value) {
this.setParameter(name, value)
}, 100),
resetParameter: function (mode) {
// get Device
this.device = this.getDeviceProject(this.deviceSelectKey)
// get Config
this.config = configTable.getConfig(this.device.library.value)
// create default parameter
const defaultValue = {}
for (const key in this.config) {
if (this.config[key].defaultValue !== undefined) {
defaultValue[key] = this.config[key].defaultValue
}
}
const parameterSet = this.getParameterSetTask(this.taskSelectKey, this.deviceSelectKey)
this.parameter = { ...defaultValue }
if (parameterSet) {
this.parameterUUID = Object.keys(parameterSet)[0]
const param = Object.values(parameterSet)[0]
const modeOption = this.$refs.device_parameter_ref.workingModeOptions.find(ele => ele.id === param.MODE)
this.$refs.device_parameter_ref.workingModeSelectChange(modeOption)
this.parameter = Object.assign(this.parameter, Object.values(parameterSet)[0])
}
},
...mapActions('project',
[
types.task.setParameterSet,
],
),
},
mounted () {
// init parameter
this.resetParameter()
},
}
</script>
@@ -84,7 +84,6 @@ export default {
...mapFields('project', [
'deviceConnectList',
'projectLibrary',
]),
},
data () {
@@ -158,9 +157,6 @@ export default {
} else {
await this.setDeviceProject({ device: this.device, index: deviceIndex })
}
if (this.device.library !== undefined) {
this.projectLibrary = this.device.library.value
}
this.hide()
this.resetSetting()
@@ -177,7 +173,6 @@ export default {
this.optionDeviceConnect = this.deviceConnectList
if (device) {
this.device = device
this.projectLibrary = this.device.library.value
}
},
@@ -12,7 +12,6 @@
</template>
<script>
import { mapFields } from 'vuex-map-fields'
import { mapActions, mapGetters } from 'vuex'
import types from '@/store/modules/project/types'
@@ -24,10 +23,6 @@ export default {
...mapGetters('project', [
types.project.getSelect,
]),
...mapFields('project', [
'projectLibrary',
]),
},
data () {
return {
@@ -47,11 +42,6 @@ export default {
),
},
mounted () {
for (const device in this.getSelectProject.device) {
if (this.projectLibrary === null) {
this.projectLibrary = this.getSelectProject.device[device].library.value
}
}
},
}
</script>
@@ -92,7 +92,7 @@
<div class="flex">
<div v-for="(parameterSet, parameterSetKey) in getParameterSetTask(taskIndex, deviceUUID)" :key="parameterSetKey">
<div v-for="(parameter, parameterKey) in parameterSet" :key="parameterKey">
<span v-if="parameterKey !== 'target'"> {{ parameterName(parameterKey) }} : {{ parameterValue(parameterKey, parameter) }} </span>
<span v-if="parameterKey !== 'target'">{{ parameterTable[parameterKey].alias }}: {{ parameterTable[parameterKey].transFormula(parameter) }} {{ parameterTable[parameterKey].unit[0] }}</span>
</div>
</div>
</div>
@@ -122,8 +122,8 @@
import { mapFields } from 'vuex-map-fields'
import { mapActions, mapGetters } from 'vuex'
import types from '@/store/modules/project/types'
import newEliteZm15Parameter from '@/factories/project/eliteZM15ParmameterFactory'
import { FulfillingBouncingCircleSpinner } from 'epic-spinners'
import configTable from '@/data/config-table/index'
export default {
name: 'project-table',
@@ -131,10 +131,6 @@ export default {
FulfillingBouncingCircleSpinner,
},
computed: {
config () {
return configTable.getConfig(this.projectLibrary)
},
...mapGetters('project', [
types.project.getSelect,
types.project.getDevice,
@@ -148,7 +144,6 @@ export default {
'taskSelectKey',
'deviceSelectKey',
'lockMode',
'projectLibrary',
]),
},
data () {
@@ -157,6 +152,7 @@ export default {
name: -1,
checked: [],
},
parameterTable: newEliteZm15Parameter(),
}
},
methods: {
@@ -190,28 +186,6 @@ export default {
}
}
},
parameterName (name) {
if (name === 'MODE') {
return 'Mode'
}
if (typeof this.config[name].showName === 'function') {
return this.config[name].showName()
}
return this.config[name].showName
},
parameterValue (name, value) {
if (name === 'MODE') {
return this.config.MODE[value].name
}
if (this.config[name].type === 'number') {
const scale = this.config[name].unit[this.config[name].defaultUnit]
return `${this.config[name].outputReadabilityData(value, scale)} ${this.config[name].defaultUnit}`
} else if (this.config[name].type === 'array') {
return `${this.config[name].outputReadabilityData(value)}`
} else if (this.config[name].type === 'none') {
return ''
}
},
...mapActions('project', [
types.task.delete,
]),
+18 -49
View File
@@ -108,7 +108,6 @@ import { mapFields } from 'vuex-map-fields'
import { mapActions } from 'vuex'
import taskTypes from '@/store/modules/task/content/types'
import TaskFormula from './formula/TaskFormula'
import { v4 as uuid } from 'uuid'
// TODO change chart data tag format
@@ -208,6 +207,7 @@ export default {
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) {
@@ -261,22 +261,12 @@ export default {
this.showShutdownModal = true
break
case 'start':
// register default chart again
await this.taskContentChartDefaultChartGenerator({
_deviceList: this.deviceListNew,
_itemID: parseInt(mes[1]),
_chartID: null,
_type: 'device',
})
// remove mapping ID chart series data
for (const chart in this.chartData) {
this.taskContentChartResetSeriesData({
chartID: chart,
mappingID: mes[1],
})
}
device = this.deviceListNew.find((ele) => ele.memory_board === parseInt(mes[1]))
device.status = 1
break
@@ -357,20 +347,12 @@ export default {
)
},
refreshData: function () {
// TODO don't need to refresh chart with stop status
for (const chart in this.chartData) {
// find each chart mappingID with device memory_board
const device = this.deviceListNew.find(ele => String(ele.memory_board) === String(this.chartData[chart].mappingID))
// device not found continue
if (device === undefined) {
continue
}
// device is running refresh chart
if (device.status === 1) {
this.taskContentChartRefreshData({
chartID: chart,
deviceList: this.deviceListNew,
})
}
this.taskContentChartRefreshData({
chartID: parseInt(chart),
deviceList: this.deviceListNew,
})
}
},
refreshDevicesWindow: function () {
@@ -380,35 +362,25 @@ export default {
}
},
addChart: async function (isDefault) {
// create chartID with uuid instead of length of chart list
const newChart = await this.taskContentChartAdd({
chartID: uuid(),
maxDots: 5000,
this.taskContentChartAdd({
chartID: this.taskContentChartNumber,
maxDots: 4000,
gridLength: 1,
})
// createby default
if (isDefault === true) {
newChart.createdBy = 'default'
}
// createby manaul
if (isDefault === false) {
newChart.createdBy = 'manual'
}
if (this.$refs.chart_ref != null) {
this.$refs.chart_ref.forEach(ref => {
ref.refreshMappingSelect()
})
}
this.taskContentChartRefreshPanel()
// save chart config to web storage
this.taskContentChartNumber++
if (!isDefault) {
await this.taskContentChartSaveToCache()
}
this.pageToast('The chart has been added.')
return newChart.chartID
return this.taskContentChartNumber - 1
},
refreshChartSetting: async function () {
if (this.$refs.chart_ref != null) {
@@ -430,7 +402,7 @@ export default {
this.selectChartID = chartID
this.showRemoveChartModal = true
},
removeChart: async function (chartID, saveCache = true) {
removeChart: async function (chartID) {
if (chartID == null) {
chartID = this.selectChartID
}
@@ -457,9 +429,8 @@ export default {
})
}
}
if (saveCache === true) {
await this.taskContentChartSaveToCache()
}
await this.taskContentChartSaveToCache()
this.pageToast('The chart has been removed.')
},
showDeviceSettingClick: function () {
@@ -491,11 +462,9 @@ export default {
return chart
},
addDevice: async function (deviceID, memoryBoardID) {
// subscribe datastream when add device
this.mqttSub(`${taskInfo.getTaskInfo().controllerID}/data_server/device_data_stream/${deviceID}/+`)
// add mapping chart
await this.addMappingChart(deviceID)
// register default chart
await this.taskContentChartDefaultChartGenerator({
_deviceList: this.deviceListNew,
_itemID: deviceID,
@@ -598,7 +567,6 @@ export default {
taskTypes.chart.add,
taskTypes.chart.defaultChartGenerator,
taskTypes.chart.reset,
taskTypes.chart.resetSeriesData,
taskTypes.chart.refreshData,
taskTypes.chart.refreshChart,
taskTypes.chart.refreshPanel,
@@ -607,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
@@ -621,7 +590,7 @@ export default {
destroyed () {
taskInfo.destroyed(this.deviceList)
for (const chart in this.chartData) {
this.removeChart(chart, false)
this.removeChart(chart)
}
clearInterval(this.dataRefreshTimer)
this.pageMqttUnSub(taskInfo.getTaskInfo().controllerID)
@@ -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>
@@ -4,7 +4,7 @@
<template slot="header">
<div class="row flex sm12 xl12 md12 xs12 align--center my-0 py-0">
<div class="flex sm5 xl5 md5 xs5 px-0 mx-0">
<h5 class="mt-0 mb-0"><va-icon name="fa fa-area-chart mr-3" color="primary"/>{{ nameCard }}</h5>
<h5 class="mt-0 mb-0"><va-icon name="fa fa-area-chart mr-3" color="primary"/>{{nameCard}}</h5>
</div>
<div class="flex sm7 xl7 md7 xs7 pa-0 ma-0" style="text-align: right;">
<va-button class="pa-0 ma-0 circle-button" small color="dark" @click="remove()">
@@ -14,56 +14,27 @@
/>
</va-button>
</div>
<!-- <div>
<va-button v-if="integralClicked && (mode_name==='Chronoamperometric' || mode_name==='I-T Graph')" color="danger" class="mb-2" @click="clickIntegral" small>
To Raw Mode
</va-button>
<va-button v-if="!integralClicked && (mode_name==='Chronoamperometric' || mode_name==='I-T Graph')" color="primary" class="mb-2" @click="clickIntegral" small>
To Integral Mode
</va-button>
<va-button v-if="xlogClicked && (mode_name==='Linear Sweep Voltammetry' || mode_name==='I-V Curve')" color="danger" class="mb-2" @click="clickXLog" small>
To Raw Mode
</va-button>
<va-button :disabled="disableLog" v-if="!xlogClicked && (mode_name==='Linear Sweep Voltammetry' || mode_name==='I-V Curve')" color="primary" class="mb-2" @click="clickXLog" small>
To log Mode (x-axis)
</va-button>
<va-button v-if="ylogClicked && (mode_name==='Linear Sweep Voltammetry' || mode_name==='I-V Curve')" color="danger" class="mb-2" @click="clickYLog" small>
To Raw Mode
</va-button>
<va-button :disabled="disableLog" v-if="!ylogClicked && (mode_name==='Linear Sweep Voltammetry' || mode_name==='I-V Curve')" color="primary" class="mb-2" @click="clickYLog" small>
To log Mode (y-axis)
</va-button>
<va-button v-if="diffClicked && (mode_name==='Linear Sweep Voltammetry' || mode_name==='I-V Curve')" color="danger" class="mb-2" @click="clickDiff" small>
To Raw Mode
</va-button>
<va-button :disabled="disableDiff" v-if="!diffClicked && (mode_name==='Linear Sweep Voltammetry' || mode_name==='I-V Curve')" color="primary" class="mb-2" @click="clickDiff" small>
To Differential Mode
</va-button>
</div> -->
<canvas-chart-real-time-calculation :chartID="chartID" @refreshData="refreshData"/>
</div>
</template>
<va-tabs v-model="tabValue" class="mb-3" style="width: 100%; min-width: 100px;">
<va-tab>
{{ 'CHART' }}
{{'CHART'}}
</va-tab>
<va-tab>
{{ 'SOURCE' }}
{{'SOURCE'}}
</va-tab>
</va-tabs>
<div v-if="tabValue == 0" >
<div v-if="chartData[chartID].legend.data.length != 0">
<canvas-chart-real-time-display
:chartID="chartID"
/>
<!-- chart -->
<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>
<div v-else-if="tabValue == 1" :style="'width: '+ cardwidth + '; height: ' + cardheight + ';'" >
<canvas-chart-source :chartID="chartID" @addSource="addSource()" />
<canvas-chart-source :chartID="chartID" />
</div>
<div v-else :style="'width: '+ cardwidth + '; height: ' + cardheight + ';'" >
<!-- <canvas-chart-setting :chartID="chartID"></canvas-chart-setting> -->
</div>
<div v-if="this.$refs.chart_ref != null">
<va-button small class="mb-3" @click="selectAllSeries">
@@ -138,13 +109,8 @@ import CanvasChartFilterPopup from './CanvasChartFilterPopup.vue'
import CanvasChartSource from './CanvasChartSource'
import { taskInfo } from '../../../../data/task/TaskInfo'
import { mapFields } from 'vuex-map-fields'
import CanvasChartRealTimeDisplay from '@/components/task/content/chart/CanvasChartRealTimeDisplay'
import { mapActions } from 'vuex'
import taskTypes from '@/store/modules/task/content/types'
// import paramTable from '@/data/param-table/index'
// import { newTooltip } from '@/factories/chart/tooltipFactory'
// import { getTimeFormatter } from '@/store/modules/task/content/actions/chartAct'
import CanvasChartRealTimeCalculation from './CanvasChartRealTimeCalculation.vue'
export default {
name: 'CanvasChart',
@@ -153,12 +119,10 @@ export default {
CanvasChartSource,
CanvasChartFilter,
CanvasChartFilterPopup,
CanvasChartRealTimeDisplay,
CanvasChartRealTimeCalculation,
},
props: {
chartID: {
type: [Number, String],
type: Number,
required: true,
},
cardclass: {
@@ -183,15 +147,11 @@ export default {
...mapFields('taskContent', [
'chartData',
'taskContentChartKey',
'deviceListNew',
]),
},
data () {
return {
// info: null,
// paramTable: paramTable,
data: null,
// rawData: null,
tabValue: 0,
resizeTimer: null,
mappingSelect: '',
@@ -202,264 +162,9 @@ export default {
threeAxisIntervalInput: 'auto',
xIntervalInput: 'auto',
yIntervalInput: 'auto',
// mode_name: '',
// xName: '',
// yName: '',
// obj: null,
// integralClicked: false,
// xlogClicked: false,
// ylogClicked: false,
// diffClicked: false,
// disableDiff: false,
// disableLog: false,
}
},
// watch rawData is use for detect whether the chartData is changed
// watch: {
// rawData: {
// deep: true,
// handler: function () {
// // avoid getting null data
// if (this.rawData.series.length > 0) {
// this.watchHandler()
// }
// },
// },
// },
methods: {
// Do arithmetic operations triggered by button(raw, integral, log)
// watchHandler: function () {
// // this.data need to be deep copy from rawData, since we don't want to modify the source(chartData[])
// // this.data = Object.assign({}, this.rawData)
// this.data = JSON.parse(JSON.stringify(this.rawData))
// this.addSource()
// var curXData = 0
// var curYData = 0
// var prevXData = 0
// var prevYData = 0
// var timeGap = 0
// var curTime = 0
// var integralResult = 0
// var diffResult = 0
// var index = 0
// var timeIndex = this.getTimeIndex()
// var _data = []
// const dataLength = this.data.series[0].data.length
// const seriesData = this.data.series[0].data
// if (this.integralClicked) {
// for (index = 0; index < dataLength; index++) {
// if (index === 0) {
// // TODO: need to change the series[deviceID]
// // TODO: change the time index(dynamic changing)
// curYData = parseFloat(seriesData[index][1])
// timeGap = seriesData[index + 1][timeIndex] - seriesData[index][timeIndex]
// curTime = seriesData[index][timeIndex]
// _data.push([curTime, 0])
// } else {
// prevYData = parseFloat(seriesData[index - 1][1])
// curYData = parseFloat(seriesData[index][1])
// integralResult += parseFloat((Math.abs(curYData) + Math.abs(prevYData)) * timeGap / 2)
// curTime += timeGap
// _data.push([curTime, integralResult])
// }
// }
// } else if (this.xlogClicked || this.ylogClicked) {
// if (this.xlogClicked && this.ylogClicked) {
// for (index = 0; index < dataLength; index++) {
// if (index === 0) {
// curXData = parseFloat(seriesData[index][0])
// curYData = parseFloat(seriesData[index][1])
// timeGap = seriesData[index + 1][timeIndex] - seriesData[index][timeIndex]
// curTime = seriesData[index][timeIndex]
// if (curXData !== 0 && curYData !== 0) {
// _data.push([Math.log10(Math.abs(curXData)), Math.log10(Math.abs(curYData)), curTime])
// }
// } else {
// curXData = parseFloat(seriesData[index][0])
// curYData = parseFloat(seriesData[index][1])
// curTime += timeGap
// if (curXData !== 0 && curYData !== 0) {
// _data.push([Math.log10(Math.abs(curXData)), Math.log10(Math.abs(curYData)), curTime])
// }
// }
// }
// } else if (this.xlogClicked && !(this.ylogClicked)) {
// for (index = 0; index < dataLength; index++) {
// if (index === 0) {
// curXData = parseFloat(seriesData[index][0])
// curYData = parseFloat(seriesData[index][1])
// timeGap = seriesData[index + 1][timeIndex] - seriesData[index][timeIndex]
// curTime = seriesData[index][timeIndex]
// if (curXData !== 0) {
// _data.push([Math.log10(Math.abs(curXData)), curYData, curTime])
// }
// } else {
// curXData = parseFloat(seriesData[index][0])
// curYData = parseFloat(seriesData[index][1])
// curTime += timeGap
// if (curXData !== 0) {
// _data.push([Math.log10(Math.abs(curXData)), curYData, curTime])
// }
// }
// }
// } else if (!(this.xlogClicked) && this.ylogClicked) {
// for (index = 0; index < dataLength; index++) {
// if (index === 0) {
// curXData = parseFloat(seriesData[index][0])
// curYData = parseFloat(seriesData[index][1])
// timeGap = seriesData[index + 1][timeIndex] - seriesData[index][timeIndex]
// curTime = seriesData[index][timeIndex]
// if (curYData !== 0) {
// _data.push([curXData, Math.log10(Math.abs(curYData)), curTime])
// }
// } else {
// curXData = parseFloat(seriesData[index][0])
// curYData = parseFloat(seriesData[index][1])
// curTime += timeGap
// if (curYData !== 0) {
// _data.push([curXData, Math.log10(Math.abs(curYData)), curTime])
// }
// }
// }
// }
// } else if (this.diffClicked) {
// for (index = 0; index < dataLength; index++) {
// if (index === 0) {
// // TODO: need to change the series[deviceID]
// // TODO: change the time index(dynamic changing)
// curXData = parseFloat(seriesData[index][0])
// curYData = parseFloat(seriesData[index][1])
// timeGap = seriesData[index + 1][timeIndex] - seriesData[index][timeIndex]
// curTime = seriesData[index][timeIndex]
// // _data.push([curTime, 0, curTime])
// } else {
// curXData = parseFloat(seriesData[index][0])
// curYData = parseFloat(seriesData[index][1])
// prevXData = parseFloat(seriesData[index - 1][0])
// prevYData = parseFloat(seriesData[index - 1][1])
// curTime += timeGap
// diffResult = parseFloat((curYData - prevYData) / (curXData - prevXData))
// console.log((curYData - prevYData), (curXData - prevXData), diffResult)
// _data.push([curTime, diffResult, curTime])
// }
// }
// }
// // decide feed in raw data / modified one
// if (this.integralClicked || this.xlogClicked || this.ylogClicked || this.diffClicked) {
// this.data.series[0].data = _data
// }
// this.data.xAxis[0].type = 'value'
// if (this.integralClicked) {
// this.data.tooltip.formatter = newTooltip('Integral').formatter
// } else if (this.xlogClicked || this.ylogClicked) {
// this.data.tooltip.formatter = newTooltip('log').formatter
// } else if (this.diffClicked) {
// this.data.tooltip.formatter = newTooltip('Differential').formatter
// } else {
// this.data.tooltip.formatter = newTooltip('').formatter
// }
// // TODO: modify the redundant code
// if (this.xName === 'TIME') {
// // this.data.xAxis[0].axisLabel.hideOverlap = true
// this.data.xAxis[0].axisLabel.formatter = function (val) {
// return getTimeFormatter(val)
// /* const hour = parseInt(val / 3.6e9)
// const minute = parseInt((val % 3.6e9) / 1000000 / 60)
// const second = parseInt((val % 6e7) / 1000000)
// const millisecond = parseInt((val % 1e6) / 1000)
// let label = ''
// if (hour > 0) {
// label += hour + ' h '
// }
// if (minute > 0) {
// label += minute + ' m '
// }
// if (second > 0) {
// label += second + ' s '
// }
// if (millisecond > 0) {
// label += millisecond + ' ms '
// }
// return label */
// }
// }
// },
// resetClicked: function () {
// this.integralClicked = false
// this.xlogClicked = false
// this.ylogClicked = false
// this.diffClicked = false
// this.disableDiff = false
// this.disableLog = false
// },
// clickIntegral: function () {
// this.integralClicked = !(this.integralClicked)
// const device = this.deviceListNew.find(ele => String(ele.memory_board) === String(this.data.mappingID))
// if (device !== undefined) {
// if (device.status === 0) {
// this.watchHandler()
// }
// }
// },
// clickXLog: function () {
// if (this.xlogClicked) {
// this.xlogClicked = false
// this.disableDiff = false
// } else {
// this.xlogClicked = true
// this.disableDiff = true
// }
// const device = this.deviceListNew.find(ele => String(ele.memory_board) === String(this.data.mappingID))
// if (device !== undefined) {
// if (device.status === 0) {
// this.watchHandler()
// }
// }
// },
// clickYLog: function () {
// if (this.ylogClicked) {
// this.ylogClicked = false
// this.disableDiff = false
// } else {
// this.ylogClicked = true
// this.disableDiff = true
// }
// const device = this.deviceListNew.find(ele => String(ele.memory_board) === String(this.data.mappingID))
// if (device !== undefined) {
// if (device.status === 0) {
// this.watchHandler()
// }
// }
// },
// clickDiff: function () {
// this.diffClicked = !(this.diffClicked)
// this.disableLog = !(this.disableLog)
// const device = this.deviceListNew.find(ele => String(ele.memory_board) === String(this.data.mappingID))
// if (device !== undefined) {
// if (device.status === 0) {
// this.watchHandler()
// }
// }
// },
// addSource () {
// if (this.data.gridSource.length > 0) {
// const xAxisName = this.data.gridSource[0][0].xAxis
// const yAxisName = this.data.gridSource[0][0].yAxis
// this.xName = (xAxisName.split(' ')).pop()
// this.yName = (yAxisName.split(' ')).pop()
// if ((this.xName === 'VOLTAGE' && this.yName === 'CURRENT') || (this.xName === 'CURRENT' && this.yName === 'VOLTAGE')) {
// this.mode_name = 'I-V Curve' // integration
// } else if (this.xName === 'TIME' && this.yName === 'CURRENT') {
// this.mode_name = 'I-T Graph' // differential and log
// }
// }
// },
// // index 0 is for the mode which x-axis is represent time, 2 is for the other mode(s)
// getTimeIndex: function () {
// let xAxisName = this.rawData.gridSource[0][0].xAxis
// xAxisName = (xAxisName.split(' ')).pop()
// return (xAxisName === 'TIME') ? 0 : 2
// },
timeIntervalChange: function (val) {
if (!isNaN(parseInt(val))) {
this.chartData[this.chartID].xAxis.forEach(x => {
@@ -499,12 +204,12 @@ export default {
if (parseInt(y.channel) <= 255) {
if (this.chartData[this.chartID].chartYUnit === 'uV') {
y.interval = parseInt(val)
// console.log(y.interval)
} else {
y.interval = val * 1000
}
const maxList = []
const minList = []
// TODO: follow this way to iterate the deviceID
y.seriesIndex.forEach(i => {
maxList.push(Math.max(...this.chartData[this.chartID].series[i].data.map(p => p[1])))
minList.push(Math.min(...this.chartData[this.chartID].series[i].data.map(p => p[1])))
@@ -571,7 +276,7 @@ export default {
},
refreshMappingSelect: async function () {
this.setMappingSelect(this.chartData[this.chartID].mappingID)
if (this.chartData[this.chartID].mappingID !== '-1' && this.chartData[this.chartID].mappingID != null) {
if (this.chartData[this.chartID].mappingID !== -1 && this.chartData[this.chartID].mappingID != null) {
taskInfo.getMappingList().forEach(item => {
if (item.id === this.chartData[this.chartID].mappingID) {
this.setChartName(item.name)
@@ -618,22 +323,6 @@ export default {
type: 'legendInverseSelect',
})
},
// these function below are using for print out the data (debug)
// getAlldata: function () {
// return this.data.series[0].data[(this.data.series[0].data).length - 1]
// },
// getXdata: function () {
// var value = this.data.series[0].data[(this.data.series[0].data).length - 1][0]
// return this.xName + ': ' + value + ' ' + this.xUnit
// },
// getYdata: function () {
// var value = this.data.series[0].data[(this.data.series[0].data).length - 1][1]
// return this.yName + ': ' + value + ' ' + this.yUnit
// },
refreshData: function (rawData) {
this.data = rawData
},
...mapActions('taskContent', [
taskTypes.chart.saveToCache,
@@ -641,7 +330,6 @@ export default {
},
async mounted () {
this.data = this.chartData[this.chartID]
// this.data = this.chartData[this.chartID]
this.resizeTimer = setInterval(this.resize, 1000)
this.nameCard = this.chartData[this.chartID].cardName
await this.refreshMappingSelect()
@@ -65,7 +65,7 @@ export default {
name: 'canvas-chart-filter',
props: {
chartID: {
type: [Number, String],
type: Number,
required: true,
},
filterIndex: {
@@ -29,7 +29,7 @@ export default {
},
props: {
chartID: {
type: [Number, String],
type: Number,
required: true,
},
chartRef: {
@@ -66,7 +66,7 @@ export default {
name: 'canvas-chart-filter-individual-filter',
props: {
chartID: {
type: [Number, String],
type: Number,
required: true,
},
seriesIndex: {
@@ -1,561 +0,0 @@
<template>
<div>
<va-button v-if="integralClicked && (mode_name==='Chronoamperometric' || mode_name==='I-T Graph')" color="danger" class="mb-2" @click="clickIntegral" small>
To Raw Mode
</va-button>
<va-button v-if="!integralClicked && (mode_name==='Chronoamperometric' || mode_name==='I-T Graph')" color="primary" class="mb-2" @click="clickIntegral" small>
To Integral Mode
</va-button>
<va-button v-if="xlogClicked && (mode_name==='Linear Sweep Voltammetry' || mode_name==='I-V Curve')" color="danger" class="mb-2" @click="clickXLog" small>
To Raw Mode
</va-button>
<va-button :disabled="disableLog" v-if="!xlogClicked && (mode_name==='Linear Sweep Voltammetry' || mode_name==='I-V Curve')" color="primary" class="mb-2" @click="clickXLog" small>
To log Mode (x-axis)
</va-button>
<va-button v-if="ylogClicked && (mode_name==='Linear Sweep Voltammetry' || mode_name==='I-V Curve')" color="danger" class="mb-2" @click="clickYLog" small>
To Raw Mode
</va-button>
<va-button :disabled="disableLog" v-if="!ylogClicked && (mode_name==='Linear Sweep Voltammetry' || mode_name==='I-V Curve')" color="primary" class="mb-2" @click="clickYLog" small>
To log Mode (y-axis)
</va-button>
<va-button v-if="diffClicked && (mode_name==='Linear Sweep Voltammetry' || mode_name==='I-V Curve')" color="danger" class="mb-2" @click="clickDiff" small>
To Raw Mode
</va-button>
<va-button :disabled="disableDiff" v-if="!diffClicked && (mode_name==='Linear Sweep Voltammetry' || mode_name==='I-V Curve')" color="primary" class="mb-2" @click="clickDiff" small>
To Differential Mode
</va-button>
</div>
</template>
<script>
// import CanvasChartFilter from './CanvasChartFilter.vue'
// import CanvasChartFilterPopup from './CanvasChartFilterPopup.vue'
// import CanvasChartSource from './CanvasChartSource'
// import { taskInfo } from '../../../../data/task/TaskInfo'
import { mapFields } from 'vuex-map-fields'
import { mapActions } from 'vuex'
import taskTypes from '@/store/modules/task/content/types'
import paramTable from '@/data/config-table/index'
import newTooltip from '@/factories/chart/tooltipFactory'
import { getTimeFormatter } from '@/store/modules/task/content/actions/chartAct'
export default {
name: 'CanvasChartRealTimeCalculation',
components: {
// CanvasChartSetting,
// CanvasChartSource,
// CanvasChartFilter,
// CanvasChartFilterPopup,
},
props: {
chartID: {
type: [Number, String],
required: true,
},
// cardclass: {
// type: Array,
// default: function () {
// return ['xs12', 'md12', 'xl12', 'sm12']
// },
// },
// cardheight: {
// type: String,
// default: '400px',
// },
// cardwidth: {
// type: String,
// default: 'auto',
// },
},
computed: {
...mapFields('', [
'developer_mode',
]),
...mapFields('taskContent', [
'chartData',
'taskContentChartKey',
'deviceListNew',
]),
},
data () {
return {
info: null,
paramTable: paramTable,
// data: null,
rawData: null,
// tabValue: 0,
// resizeTimer: null,
// mappingSelect: '',
// mappingOptions: taskInfo.getMappingList(),
// nameCard: '',
// initDone: false,
// timeIntervalInput: 'auto',
// threeAxisIntervalInput: 'auto',
// xIntervalInput: 'auto',
// yIntervalInput: 'auto',
mode_name: '',
xName: '',
yName: '',
obj: null,
integralClicked: false,
xlogClicked: false,
ylogClicked: false,
diffClicked: false,
disableDiff: false,
disableLog: false,
}
},
// watch rawData is use for detect whether the chartData is changed
watch: {
rawData: {
deep: true,
handler: function () {
// avoid getting null data
if (this.rawData.series.length > 0) {
this.watchHandler()
}
},
},
},
methods: {
// Do arithmetic operations triggered by button(raw, integral, log)
watchHandler: function () {
// this.data need to be deep copy from rawData, since we don't want to modify the source(chartData[])
// this.data = Object.assign({}, this.rawData)
this.data = JSON.parse(JSON.stringify(this.rawData))
this.addSource()
var curXData = 0
var curYData = 0
var prevXData = 0
var prevYData = 0
var timeGap = 0
var curTime = 0
var integralResult = 0
var diffResult = 0
var index = 0
var timeIndex = this.getTimeIndex()
var _data = []
const dataLength = this.data.series[0].data.length
const seriesData = this.data.series[0].data
if (this.integralClicked) {
for (index = 0; index < dataLength; index++) {
if (index === 0) {
// TODO: need to change the series[deviceID]
// TODO: change the time index(dynamic changing)
curYData = parseFloat(seriesData[index][1])
timeGap = seriesData[index + 1][timeIndex] - seriesData[index][timeIndex]
curTime = seriesData[index][timeIndex]
_data.push([curTime, 0])
} else {
prevYData = parseFloat(seriesData[index - 1][1])
curYData = parseFloat(seriesData[index][1])
integralResult += parseFloat((Math.abs(curYData) + Math.abs(prevYData)) * timeGap / 2)
curTime += timeGap
_data.push([curTime, integralResult])
}
}
} else if (this.xlogClicked || this.ylogClicked) {
if (this.xlogClicked && this.ylogClicked) {
for (index = 0; index < dataLength; index++) {
if (index === 0) {
curXData = parseFloat(seriesData[index][0])
curYData = parseFloat(seriesData[index][1])
timeGap = seriesData[index + 1][timeIndex] - seriesData[index][timeIndex]
curTime = seriesData[index][timeIndex]
if (curXData !== 0 && curYData !== 0) {
_data.push([Math.log10(Math.abs(curXData)), Math.log10(Math.abs(curYData)), curTime])
}
} else {
curXData = parseFloat(seriesData[index][0])
curYData = parseFloat(seriesData[index][1])
curTime += timeGap
if (curXData !== 0 && curYData !== 0) {
_data.push([Math.log10(Math.abs(curXData)), Math.log10(Math.abs(curYData)), curTime])
}
}
}
} else if (this.xlogClicked && !(this.ylogClicked)) {
for (index = 0; index < dataLength; index++) {
if (index === 0) {
curXData = parseFloat(seriesData[index][0])
curYData = parseFloat(seriesData[index][1])
timeGap = seriesData[index + 1][timeIndex] - seriesData[index][timeIndex]
curTime = seriesData[index][timeIndex]
if (curXData !== 0) {
_data.push([Math.log10(Math.abs(curXData)), curYData, curTime])
}
} else {
curXData = parseFloat(seriesData[index][0])
curYData = parseFloat(seriesData[index][1])
curTime += timeGap
if (curXData !== 0) {
_data.push([Math.log10(Math.abs(curXData)), curYData, curTime])
}
}
}
} else if (!(this.xlogClicked) && this.ylogClicked) {
for (index = 0; index < dataLength; index++) {
if (index === 0) {
curXData = parseFloat(seriesData[index][0])
curYData = parseFloat(seriesData[index][1])
timeGap = seriesData[index + 1][timeIndex] - seriesData[index][timeIndex]
curTime = seriesData[index][timeIndex]
if (curYData !== 0) {
_data.push([curXData, Math.log10(Math.abs(curYData)), curTime])
}
} else {
curXData = parseFloat(seriesData[index][0])
curYData = parseFloat(seriesData[index][1])
curTime += timeGap
if (curYData !== 0) {
_data.push([curXData, Math.log10(Math.abs(curYData)), curTime])
}
}
}
}
} else if (this.diffClicked) {
for (index = 0; index < dataLength; index++) {
if (index === 0) {
// TODO: need to change the series[deviceID]
// TODO: change the time index(dynamic changing)
curXData = parseFloat(seriesData[index][0])
curYData = parseFloat(seriesData[index][1])
timeGap = seriesData[index + 1][timeIndex] - seriesData[index][timeIndex]
curTime = seriesData[index][timeIndex]
// _data.push([curTime, 0, curTime])
} else {
curXData = parseFloat(seriesData[index][0])
curYData = parseFloat(seriesData[index][1])
prevXData = parseFloat(seriesData[index - 1][0])
prevYData = parseFloat(seriesData[index - 1][1])
curTime += timeGap
diffResult = parseFloat((curYData - prevYData) / (curXData - prevXData))
// console.log((curYData - prevYData), (curXData - prevXData), diffResult)
_data.push([curTime, diffResult, curTime])
}
}
}
// decide feed in raw data / modified one
if (this.integralClicked || this.xlogClicked || this.ylogClicked || this.diffClicked) {
// console.log(_data)
this.data.series[0].data = _data
}
this.data.xAxis[0].type = 'value'
if (this.integralClicked) {
this.data.tooltip.formatter = newTooltip('Integral').formatter
} else if (this.xlogClicked || this.ylogClicked) {
this.data.tooltip.formatter = newTooltip('log').formatter
} else if (this.diffClicked) {
this.data.tooltip.formatter = newTooltip('Differential').formatter
} else {
this.data.tooltip.formatter = newTooltip('').formatter
}
// TODO: modify the redundant code
if (this.xName === 'TIME') {
// this.data.xAxis[0].axisLabel.hideOverlap = true
this.data.xAxis[0].axisLabel.formatter = function (val) {
return getTimeFormatter(val)
/* const hour = parseInt(val / 3.6e9)
const minute = parseInt((val % 3.6e9) / 1000000 / 60)
const second = parseInt((val % 6e7) / 1000000)
const millisecond = parseInt((val % 1e6) / 1000)
let label = ''
if (hour > 0) {
label += hour + ' h '
}
if (minute > 0) {
label += minute + ' m '
}
if (second > 0) {
label += second + ' s '
}
if (millisecond > 0) {
label += millisecond + ' ms '
}
return label */
}
}
this.$emit('refreshData', this.data)
},
resetClicked: function () {
this.integralClicked = false
this.xlogClicked = false
this.ylogClicked = false
this.diffClicked = false
this.disableDiff = false
this.disableLog = false
},
clickIntegral: function () {
this.integralClicked = !(this.integralClicked)
const device = this.deviceListNew.find(ele => String(ele.memory_board) === String(this.data.mappingID))
if (device !== undefined) {
if (device.status === 0) {
this.watchHandler()
}
}
},
clickXLog: function () {
if (this.xlogClicked) {
this.xlogClicked = false
if (this.ylogClicked) {
this.disableDiff = true
} else {
this.disableDiff = false
}
} else {
this.xlogClicked = true
this.disableDiff = true
}
const device = this.deviceListNew.find(ele => String(ele.memory_board) === String(this.data.mappingID))
if (device !== undefined) {
if (device.status === 0) {
this.watchHandler()
}
}
},
clickYLog: function () {
if (this.ylogClicked) {
this.ylogClicked = false
if (this.xlogClicked) {
this.disableDiff = true
} else {
this.disableDiff = false
}
} else {
this.ylogClicked = true
this.disableDiff = true
}
const device = this.deviceListNew.find(ele => String(ele.memory_board) === String(this.data.mappingID))
if (device !== undefined) {
if (device.status === 0) {
this.watchHandler()
}
}
},
clickDiff: function () {
this.diffClicked = !(this.diffClicked)
this.disableLog = !(this.disableLog)
const device = this.deviceListNew.find(ele => String(ele.memory_board) === String(this.data.mappingID))
if (device !== undefined) {
if (device.status === 0) {
this.watchHandler()
}
}
},
addSource () {
if (this.data.gridSource.length > 0) {
const xAxisName = this.data.gridSource[0][0].xAxis
const yAxisName = this.data.gridSource[0][0].yAxis
this.xName = (xAxisName.split(' ')).pop()
this.yName = (yAxisName.split(' ')).pop()
if ((this.xName === 'VOLTAGE' && this.yName === 'CURRENT') || (this.xName === 'CURRENT' && this.yName === 'VOLTAGE')) {
this.mode_name = 'I-V Curve' // integration
} else if (this.xName === 'TIME' && this.yName === 'CURRENT') {
this.mode_name = 'I-T Graph' // differential and log
}
}
},
// index 0 is for the mode which x-axis is represent time, 2 is for the other mode(s)
getTimeIndex: function () {
let xAxisName = this.rawData.gridSource[0][0].xAxis
xAxisName = (xAxisName.split(' ')).pop()
return (xAxisName === 'TIME') ? 0 : 2
},
// timeIntervalChange: function (val) {
// if (!isNaN(parseInt(val))) {
// this.chartData[this.chartID].xAxis.forEach(x => {
// if (x.type === 'time') {
// x.interval = val * 1000
// }
// })
// } else {
// this.timeIntervalInput = 'auto'
// this.chartData[this.chartID].xAxis.forEach(x => {
// if (x.type === 'time') {
// x.interval = 500 * 1000
// }
// })
// }
// },
// xIntervalChange: async function (val) {
// if (!isNaN(parseInt(val))) {
// this.chartData[this.chartID].xAxis.forEach(x => {
// if (x.type === 'value') {
// x.interval = val * 1000
// }
// })
// } else {
// this.timeIntervalInput = 'auto'
// this.chartData[this.chartID].xAxis.forEach(x => {
// if (x.type === 'value') {
// x.interval = null
// }
// })
// }
// await this.taskContentChartSaveToCache()
// },
// yIntervalChange: async function (val) {
// if (!isNaN(parseInt(val))) {
// this.chartData[this.chartID].yAxis.forEach(y => {
// if (parseInt(y.channel) <= 255) {
// if (this.chartData[this.chartID].chartYUnit === 'uV') {
// y.interval = parseInt(val)
// } else {
// y.interval = val * 1000
// }
// const maxList = []
// const minList = []
// // TODO: follow this way to iterate the deviceID
// y.seriesIndex.forEach(i => {
// maxList.push(Math.max(...this.chartData[this.chartID].series[i].data.map(p => p[1])))
// minList.push(Math.min(...this.chartData[this.chartID].series[i].data.map(p => p[1])))
// })
// const max = Math.max(maxList)
// const min = Math.min(minList)
// const center = (max + min) / 2
// y.max = center + (max - min)
// y.min = center - (max - min)
// y.max = (parseInt(y.max / y.interval) + 1) * y.interval
// y.min = (parseInt(y.min / y.interval) - 1) * y.interval
// }
// })
// } else {
// this.timeIntervalInput = 'auto'
// this.chartData[this.chartID].yAxis.forEach(y => {
// if (parseInt(y.channel) <= 255) {
// y.interval = null
// y.max = 'dataMax'
// y.min = 'dataMin'
// }
// })
// }
// await this.taskContentChartSaveToCache()
// },
// threeAxisIntervalChange: function (val) {
// if (!isNaN(parseInt(val))) {
// this.chartData[this.chartID].yAxis.forEach(y => {
// if (parseInt(y.channel) >= 255) {
// y.interval = val * 1
// }
// })
// } else {
// this.timeIntervalInput = 'auto'
// this.chartData[this.chartID].yAxis.forEach(y => {
// if (parseInt(y.channel) >= 255) {
// y.interval = null
// }
// })
// }
// },
// init: function () {
// this.mappingSelect = ''
// this.nameCard = 'chart' + this.chartID
// this.$emit('init')
// },
// remove: function () {
// this.$emit('remove')
// },
// resetSetting: function () {
// this.mappingSelect = ''
// this.nameCard = 'chart' + this.chartID
// },
// setMappingSelect: async function (itemID) {
// if (itemID === -1 || itemID == null) {
// return false
// }
// this.mappingOptions.forEach(item => {
// if (item.id === itemID) {
// this.mappingSelect = item
// this.chartData[this.chartID].mappingID = item.id
// }
// })
// },
// refreshMappingSelect: async function () {
// this.setMappingSelect(this.chartData[this.chartID].mappingID)
// if (this.chartData[this.chartID].mappingID !== '-1' && this.chartData[this.chartID].mappingID != null) {
// taskInfo.getMappingList().forEach(item => {
// if (item.id === this.chartData[this.chartID].mappingID) {
// this.setChartName(item.name)
// }
// })
// }
// },
// setChartName: function (name) {
// this.chartData[this.chartID].cardName = name
// this.nameCard = name
// },
// resize: function () {
// if (this.$refs.chart_ref != null) {
// this.$refs.chart_ref.resize()
// }
// },
// showFilterPopup (params) {
// this.$refs.filter_popup_ref.showPanel(params)
// },
// setCursor (params) {
// this.$refs.chart_ref.chart._zr.setCursorStyle('copy')
// },
// legendChange (params) {
// const activeLegendLen = Object.values(params.selected).filter(val => val === true).length
// let index = 0
// for (const [gridIndex, value] of Object.values(params.selected).entries()) { // [TODO] 技術債,目前real time chart一個grid只對應一條series
// if (value === true) {
// this.chartData[this.chartID].grid[gridIndex].height = (85 / activeLegendLen) + '%'
// this.chartData[this.chartID].grid[gridIndex].top = index * (85 / activeLegendLen) + 1 + '%'
// index++
// } else {
// this.chartData[this.chartID].grid[gridIndex].height = '0%'
// this.chartData[this.chartID].grid[gridIndex].top = '0%'
// }
// }
// },
// selectAllSeries () {
// this.$refs.chart_ref.dispatchAction({
// type: 'legendAllSelect',
// })
// },
// inverseSelectAllSeries () {
// this.$refs.chart_ref.dispatchAction({
// type: 'legendInverseSelect',
// })
// },
// these function below are using for print out the data (debug)
getAlldata: function () {
return this.data.series[0].data[(this.data.series[0].data).length - 1]
},
getXdata: function () {
var value = this.data.series[0].data[(this.data.series[0].data).length - 1][0]
return this.xName + ': ' + value + ' ' + this.xUnit
},
getYdata: function () {
var value = this.data.series[0].data[(this.data.series[0].data).length - 1][1]
return this.yName + ': ' + value + ' ' + this.yUnit
},
...mapActions('taskContent', [
taskTypes.chart.saveToCache,
]),
},
async mounted () {
this.rawData = this.chartData[this.chartID]
// this.data = this.chartData[this.chartID]
// this.resizeTimer = setInterval(this.resize, 1000)
// this.nameCard = this.chartData[this.chartID].cardName
// await this.refreshMappingSelect()
// this.initDone = true
// if (this.$refs.chart_ref != null) {
// // this.$refs.chart_ref.chart._zr.on('click', this.showFilterPopup)
// // this.$refs.chart_ref.chart._zr.on('mousemove', this.setCursor)
// this.$refs.chart_ref.chart.on('legendselectchanged', this.legendChange)
// this.$refs.chart_ref.chart.on('legendselectall', this.legendChange)
// this.$refs.chart_ref.chart.on('legendinverseselect', this.legendChange)
// }
// this.timeIntervalInput = '500'
// this.timeIntervalChange('500')
},
// destroyed () {
// clearInterval(this.resizeTimer)
// },
}
</script>
@@ -1,218 +0,0 @@
<template>
<div>
<div v-for="(chart, chartIndex) in realTime" :key="'c'+chartIndex">
<div v-for="(grid, gridIndex) in chart" :key="'s'+gridIndex" class="row ma-0 pa-0">
<div class="col flex xs0 sm0 lg0 md0 xl0 xxl1"/>
<div class="col flex xs2 sm2 lg2 md2 xl2 xxl1" pa-0 ma-0>
<p color="primary" style="text-align: right;">{{ grid.name }}</p>
</div>
<!-- value (y-axis) -->
<div class="col flex sm2 xl2 md2 xs2">
<va-input
label="y-value"
disable="disable"
v-model="grid.yValue"
/>
</div>
<!-- unit (y-axis) -->
<div class="col flex sm2 xl2 md2 xs2">
<va-select
label="y-unit"
v-model="grid.yUnit"
:options="grid.yUnitOption"
noClear
/>
</div>
<div class="col flex sm1 xl1 md1 xs1"></div>
<!-- value (x-axis) -->
<div class="col flex sm2 xl2 md2 xs2">
<va-input
label="x-value"
disable="disable"
v-model="grid.xValue"
/>
</div>
<!-- unit (x-axis) -->
<div class="col flex sm2 xl2 md2 xs2">
<va-select
label="x-unit"
v-model="grid.xUnit"
:options="grid.xUnitOption"
noClear
/>
</div>
</div>
</div>
</div>
</template>
<script>
import { mapFields } from 'vuex-map-fields'
import configTable from '@/data/config-table/index.js'
import newTooltip from '@/factories/chart/tooltipFactory'
export default {
name: 'CanvasChartRealTimeDisplay',
props: {
chartID: {
type: [Number, String],
required: true,
},
},
computed: {
...mapFields('taskContent', [
'chartData',
'deviceListNew',
]),
},
data () {
return {
data: null,
configTable: configTable,
realTime: [[]],
}
},
methods: {
// record the latest data as the real time value
updateValue: function () {
if ((this.realTime.length === 0)) {
return
}
for (let gridIndex = 0; gridIndex < this.realTime.length; gridIndex++) {
for (let channelIndex = 0; channelIndex < this.realTime[gridIndex].length; channelIndex++) {
// miss the source of data -> try to find the source
if (this.realTime[gridIndex][channelIndex].seriesSource === -1) {
this.realTime[gridIndex][channelIndex].seriesSource = this.data.series.findIndex((ele) => ele.name === this.realTime[gridIndex][channelIndex].name)
}
// the device is active now --> update the real time value
if (this.data.series[this.realTime[gridIndex][channelIndex].seriesSource] !== undefined && this.data.series[this.realTime[gridIndex][channelIndex].seriesSource].data !== undefined && this.data.series[this.realTime[gridIndex][channelIndex].seriesSource].data.length > 0) {
this.realTime[gridIndex][channelIndex].xValue = this.data.series[this.realTime[gridIndex][channelIndex].seriesSource].data.at(-1)[0] / this.realTime[gridIndex][channelIndex].xValueScale[this.realTime[gridIndex][channelIndex].xUnit]
this.realTime[gridIndex][channelIndex].yValue = this.data.series[this.realTime[gridIndex][channelIndex].seriesSource].data.at(-1)[1] / this.realTime[gridIndex][channelIndex].yValueScale[this.realTime[gridIndex][channelIndex].yUnit]
}
}
}
},
// change the axis unit of charts
updateUnit: function () {
for (let gridIndex = 0; gridIndex < this.realTime.length; gridIndex++) {
for (let channelIndex = 0; channelIndex < this.realTime[gridIndex].length; channelIndex++) {
if (channelIndex === 0) {
const _xUnit = this.realTime[gridIndex][channelIndex].xUnit
const _yUnit = this.realTime[gridIndex][channelIndex].yUnit
const _xScale = this.realTime[gridIndex][channelIndex].xValueScale[this.realTime[gridIndex][channelIndex].xUnit]
const _yScale = this.realTime[gridIndex][channelIndex].yValueScale[this.realTime[gridIndex][channelIndex].yUnit]
this.data.xAxis[gridIndex].axisLabel.formatter = function (val) {
return parseFloat(val / _xScale).toFixed(2) + _xUnit
}
this.data.yAxis[gridIndex].axisLabel.formatter = function (val) {
return parseFloat(val / _yScale).toFixed(2) + _yUnit
}
// update tooltip
this.data.tooltip.formatter = newTooltip(this.realTime).formatter
}
}
}
},
// for user to choose wanted unit
setUnit: function (gridIndex, channelIndex) {
// find coressponding device for current chart
const device = this.deviceListNew.find(chart => {
return chart.memory_board === parseInt(this.chartData[this.chartID].mappingID)
})
if (!device) {
return
}
// construct realTime object, i.e., record the coressponding value and unit
// the formate imitates the data.gridSource
const modeTable = this.configTable.getModeConfig(device.library_name, device.configuration.MODE)
const _realTime = JSON.parse(JSON.stringify(this.realTime))
const _newChannel = {}
let xAxis = null
let yAxis = null
// find the the data of each axis coming from which channel
if (this.data.series.length > 0) {
_newChannel.name = this.data.gridSource[gridIndex][channelIndex].name
_newChannel.seriesSource = this.data.series.findIndex((ele) => ele.name === _newChannel.name)
xAxis = this.data.series[_newChannel.seriesSource].xAxisSource[1] - 1
yAxis = this.data.series[_newChannel.seriesSource].yAxisSource[1] - 1
xAxis = (xAxis === -2) ? 'time' : xAxis
yAxis = (yAxis === -2) ? 'time' : yAxis
}
// check if xAxis unit has been defined in modeTable
if (Object.prototype.hasOwnProperty.call(modeTable.channels, xAxis)) {
_newChannel.xUnit = modeTable.channels[xAxis].defaultUnit
_newChannel.xValueScale = modeTable.channels[xAxis].unit
_newChannel.xUnitOption = Object.keys(modeTable.channels[xAxis].unit)
} else {
_newChannel.xUnit = 'unvalid'
_newChannel.xValueScale = { unvalid: NaN }
_newChannel.xUnitOption = ['']
}
// check if yAxis unit has been defined in modeTable
if (Object.prototype.hasOwnProperty.call(modeTable.channels, yAxis)) {
_newChannel.yUnit = modeTable.channels[yAxis].defaultUnit
_newChannel.yValueScale = modeTable.channels[yAxis].unit
_newChannel.yUnitOption = Object.keys(modeTable.channels[yAxis].unit)
} else {
_newChannel.yUnit = 'unvalid'
_newChannel.yValueScale = { unvalid: NaN }
_newChannel.yUnitOption = ['']
}
// set real time value = 0 as default
_newChannel.xValue = 0
_newChannel.yValue = 0
// padding
while (gridIndex >= _realTime.length) {
_realTime.push([])
}
while (channelIndex >= _realTime[gridIndex].length) {
_realTime[gridIndex].push({})
}
// merge the additional part into original part
_realTime[gridIndex][channelIndex] = _newChannel
this.realTime = _realTime
},
// for each lines on the charts should have its own real time display
matchChart: function () {
for (let gridIndex = 0; gridIndex < this.data.gridSource.length; gridIndex++) {
if (this.data.gridSource[gridIndex] !== undefined) {
for (let channelIndex = 0; channelIndex < this.data.gridSource[gridIndex].length; channelIndex++) {
if (gridIndex >= this.realTime.length) {
this.setUnit(gridIndex, channelIndex)
} else if (channelIndex >= this.realTime[gridIndex].length) {
this.setUnit(gridIndex, channelIndex)
}
}
}
}
},
},
mounted () {
this.data = this.chartData[this.chartID]
},
watch: {
data: {
handler: function () {
this.updateValue()
this.matchChart()
},
deep: true,
},
realTime: {
handler: function () {
this.updateUnit()
},
deep: true,
},
},
}
</script>
@@ -30,7 +30,7 @@ export default {
name: 'canvas-chart-setting',
props: {
chartID: {
type: [Number, String],
type: Number,
required: true,
},
},
@@ -95,7 +95,7 @@ export default {
name: 'canvas-chart-source',
props: {
chartID: {
type: [Number, String],
type: Number,
required: true,
},
},
@@ -351,7 +351,6 @@ export default {
this.sourceAddStatus = true
this.clearSelectOptions()
await this.taskContentChartSaveToCache()
this.$emit('addSource')
},
async addGrid () {
this.taskContentChartUpdateGridList({
@@ -44,8 +44,8 @@
<div>
<file-control-window :ref="'fcwindow_ref'" :device="device" class="pl-0 pr-0" />
</div>
<div>
<device-parameter-window :ref="'epwindow_ref'" :device="device" class="pl-0 pr-0" />
<div v-if="device.library_name.includes('Elite')">
<elite-parameter-window :ref="'epwindow_ref'" :device="device" class="pl-0 pr-0" />
</div>
</div>
</va-collapse>
@@ -54,21 +54,18 @@
</template>
<script>
import DeviceParameterWindow from '../parameter/DeviceParameterWindow'
// import EliteParameterWindow from '../parameter/EliteParameterWindow'
import EliteParameterWindow from '../parameter/EliteParameterWindow'
// import NeuliveParameterWindow from '../parameter/NeuliveParameterWindow'
import FileControlWindow from '../meta/FileControlWindow'
import { mapActions } from 'vuex'
import types from '@/store/modules/task/content/types'
import { taskInfo } from '../../../../data/task/TaskInfo'
import api from '@/data/api'
import CanvasChart from '../chart/CanvasChart'
export default {
name: 'TaskDeviceList',
components: {
DeviceParameterWindow,
// EliteParameterWindow,
EliteParameterWindow,
// NeuliveParameterWindow,
FileControlWindow,
},
@@ -123,7 +120,6 @@ export default {
api.task.update({
device_config: taskInfo.getTaskInfo().deviceListNew,
})
CanvasChart.methods.resetClicked()
}
},
stop: function (device) {
@@ -36,7 +36,7 @@
:withHeader="true"
:parameterName="name"
:inputValue="parameter[name]"
:disable="name === 'CTRL_HIGH_Z_15' && device && device.status === 0"
:disable="name === 'CTRL_HIGH_Z_15' && device.status === 0"
v-bind="parameterTable[name]"
@parameterChange="parameterChange"
@getParameter="getParameter"
@@ -71,7 +71,7 @@
v-for="name in parameterArrayInMode"
:key="name"
:label="`${typeof parameterTable[name].showName === 'function'
? parameterTable[name].showName(modeSelection)
? parameterTable[name].showName(parameter.MODE)
: parameterTable[name].showName} ${parameterValue(name)}`"
style="font-size: 20px;"
>
@@ -80,7 +80,7 @@
:is="parameterTable[name].componentType"
:parameterName="name"
:inputValue="parameter[name]"
:disable="name === 'CTRL_HIGH_Z_15' && device && device.status === 0"
:disable="name === 'CTRL_HIGH_Z_15' && device.status === 0"
v-bind="parameterTable[name]"
@parameterChange="parameterChange"
@getParameter="getParameter"
@@ -126,7 +126,7 @@ import DevMode from '../parameter/itemNew/DevMode'
import EliteParameterRecordingElitePulseSensing from '../parameter/itemNew/PulseSensingNew/EliteParameterRecordingElitePulseSensing'
import { VueFinalModal } from 'vue-final-modal'
import { mapFields } from 'vuex-map-fields'
import configTable from '@/data/config-table/index'
import parameterTable from '@/data/param-table/index.js'
export default {
name: 'EliteParameterRecordingElitezm15',
@@ -148,9 +148,7 @@ export default {
},
library: {
type: String,
},
serialNumber: {
type: String,
required: true,
},
device: {
type: Object,
@@ -158,30 +156,9 @@ export default {
},
},
computed: {
parameterTable () {
if (this.library !== undefined) {
const config = configTable.getConfig(this.library)
if (config !== undefined) {
return config
}
}
if (this.serialNumber !== undefined) {
const config = configTable.getConfig(this.serialNumber)
if (config !== undefined) {
return config
}
}
return null
},
parameterArrayInMode () {
return this.workingModeSelect && this.parameterTable.MODE[this.workingModeSelect.id].parameter
},
modeSelection () {
if (this.parameter.MODE) {
return this.parameter.MODE
}
return this.workingModeSelect.id
},
getImageUrl () {
if (this.workingModeSelect === null) {
return 'IV-Wire'
@@ -207,6 +184,7 @@ export default {
},
data () {
return {
parameterTable: parameterTable[this.library],
showModal: false,
workingModeSelect: null,
workingModeOptions: [],
@@ -219,12 +197,11 @@ export default {
this.$mqtt.publish(topic, mes)
},
parameterValue (name) {
const value = this.parameter[name]
if (this.parameterTable[name].type === 'number') {
const scale = this.parameterTable[name].unit[this.parameterTable[name].defaultUnit]
return ` ( ${this.parameterTable[name].outputReadabilityData(value, scale)} ${this.parameterTable[name].defaultUnit} )`
return ` ( ${this.parameterTable[name].outputReadabilityData(this.parameter[name], scale)} ${this.parameterTable[name].defaultUnit} )`
} else if (this.parameterTable[name].type === 'array') {
return ` ( ${this.parameterTable[name].outputReadabilityData(value)} )`
return ` ( ${this.parameterTable[name].outputReadabilityData(this.parameter[name])} )`
} else if (this.parameterTable[name].type === 'none') {
return ''
}
@@ -266,8 +243,9 @@ export default {
// ? this.workingModeOptions = this.workingModeDevOptions
// : this.workingModeOptions = this.workingModeNoDevOptions
this.workingModeOptions = this.parameterTable.MODE_OPTIONS
// init mode
this.workingModeSelect = (this.parameter.MODE !== undefined) ? this.workingModeOptions.find(ele => ele.id === this.parameter.MODE) : this.workingModeOptions[0]
this.workingModeSelect = this.workingModeOptions.find(ele => ele.id === this.parameter.MODE)
},
watch: {
},
@@ -1,78 +0,0 @@
<template>
<div v-if="device">
<device-parameter-recording
:parameter="device.configuration"
:library="device.library_name"
:serialNumber="device.serial_number"
:device="device"
@sendInstruction="sendInstruction"
@getParameter="getParameter"
@setParameter="setParameter"
@setParameterWithDebounce="setParameterWithDebounce"
/>
</div>
</template>
<script>
import DeviceParameterRecording from './DeviceParameterRecording'
import { taskInfo } from '../../../../data/task/TaskInfo'
import _ from 'lodash'
export default {
name: 'EliteParameterWindow',
components: {
DeviceParameterRecording,
},
props: {
device: {
type: Object,
},
},
data () {
return {
}
},
mqtt: {
},
methods: {
mqttPublish: function (topic, mes) {
this.$mqtt.publish(topic, mes)
},
sendInstruction: function (instruction) {
this.mqttPublish(taskInfo.getTaskInfo().controllerID + '_user', JSON.stringify({
header: 'device_instruction/0',
device: this.device.mac_address,
instruction: instruction,
}))
},
getParameter: function (parameterName) {
this.mqttPublish(taskInfo.getTaskInfo().controllerID + '_user', JSON.stringify({
header: 'device_parameter_value/0',
device: this.device.mac_address,
parameter: parameterName,
}))
},
setParameter: function (parameterName, parameterValue) {
this.mqttPublish(taskInfo.getTaskInfo().controllerID + '_user', JSON.stringify({
header: 'device_parameter/0',
device: this.device.mac_address,
parameter: parameterName,
content: parameterValue,
}))
},
setParameterWithDebounce: _.debounce(function (parameterName, parameterValue) {
this.mqttPublish(taskInfo.getTaskInfo().controllerID + '_user', JSON.stringify({
header: 'device_parameter/0',
device: this.device.mac_address,
parameter: parameterName,
content: parameterValue,
}))
}, 100),
},
mounted () {
},
watch: {
},
}
</script>
@@ -120,7 +120,7 @@ import DevMode from '../parameter/itemNew/DevMode'
import EliteParameterRecordingElitePulseSensing from '../parameter/itemNew/PulseSensingNew/EliteParameterRecordingElitePulseSensing'
import { VueFinalModal } from 'vue-final-modal'
import { mapFields } from 'vuex-map-fields'
import parameterTable from '@/data/config-table/index.js'
import parameterTable from '@/data/param-table/index.js'
export default {
name: 'EliteParameterRecordingElitezm15',
@@ -1,170 +0,0 @@
const chartConfigTable = {
// split 'A-B' by '-',
// then A-B[0] is about 'A' and A-B[1] is about 'B'
T_V: [
// 0
{
default: {
name: 'Time',
unit: {
us: 1,
ms: 1e3,
s: 1e6,
min: 60 * 1e6,
hour: 60 * 60 * 1e6,
},
defaultUnit: 'ms',
downloadUnit: 'ms',
},
},
// 1
{
default: {
name: 'Voltage',
unit: {
uV: 1,
mV: 1e3,
V: 1e6,
},
defaultUnit: 'mV',
downloadUnit: 'mV',
},
},
],
T_I: [
// 0
{
default: {
name: 'Time',
unit: {
us: 1,
ms: 1e3,
s: 1e6,
min: 60 * 1e6,
hour: 60 * 60 * 1e6,
},
defaultUnit: 'ms',
downloadUnit: 'ms',
},
},
// 1
{
default: {
name: 'Current',
unit: {
nA: 1,
uA: 1e3,
mA: 1e6,
A: 1e9,
},
defaultUnit: 'mA',
downloadUnit: 'mA',
},
// Q = ∫ I dt
integral: {
name: 'Charge',
unit: {
nC: 1e6,
uC: 1e9,
mC: 1e12,
C: 1e15,
},
defaultUnit: 'mC',
downloadUnit: 'mC',
},
},
],
T_R: [
// 0
{
default: {
name: 'Time',
unit: {
us: 1,
ms: 1e3,
s: 1e6,
min: 60 * 1e6,
hour: 60 * 60 * 1e6,
},
defaultUnit: 'ms',
downloadUnit: 'ms',
},
},
// 1
{
default: {
name: 'Resistor',
unit: {
: 1,
Ω: 1e3,
: 1e6,
: 1e9,
},
defaultUnit: 'Ω',
downloadUnit: 'Ω',
},
},
],
V_I: [
// 0
{
default: {
name: 'Voltage',
unit: {
uV: 1,
mV: 1e3,
V: 1e6,
},
defaultUnit: 'mV',
downloadUnit: 'mV',
},
// 𝜡 = dV/dI
differential: {
name: 'Impedance',
unit: {
: 1,
Ω: 1e3,
: 1e6,
: 1e9,
},
defaultUnit: 'Ω',
downloadUnit: 'Ω',
},
},
// 1
{
default: {
name: 'Current',
unit: {
nA: 1,
uA: 1e3,
mA: 1e6,
A: 1e9,
},
defaultUnit: 'mA',
downloadUnit: 'mA',
},
// Gm = dI/dV
differential: {
name: 'Trancuductance',
unit: {
'mA/V': 1,
'A/V': 1e3,
'kA/V': 1e6,
},
defaultUnit: 'A/V',
downloadUnit: 'A/V',
},
},
],
}
export const chartConfigRouter = {
getUnit: (xAxis, yAxis, funct) => {
funct = (funct === undefined) ? 'default' : funct
const name1 = xAxis + '_' + yAxis
const name2 = yAxis + '_' + xAxis
if (chartConfigTable[name1] !== undefined) return chartConfigTable[name1]
else if (chartConfigTable[name2] !== undefined) return chartConfigTable[name2]
else return 'idiot'
},
}
-135
View File
@@ -1,135 +0,0 @@
import EliteEDC from './EliteEDC/index'
import EliteEIS from './EliteEIS/index'
// object saving library name mapping table
const libraryNameMappingTable = {
EliteZM15: EliteEDC,
'EliteEDC1.4': null,
'EliteEDC1.5': EliteEDC,
'EliteEDC1.5re': EliteEDC,
'EliteEDC1.5r2': EliteEDC,
'BAT1.0': null,
'EIS1.0': EliteEIS,
'EIS1.1': EliteEIS,
'EIS1.1_MINI': EliteEIS,
'TRIG0.1': null,
'MEGAFLY0.1': null,
}
// object saving serial number mapping table
const serialNumberMappingTable = {
0: {
2: {
1: {
5: null, // EDC1.4
6: EliteEDC, // EDC1.5
7: EliteEDC, // EDC1.5re
8: EliteEDC, // EDC1.5r2
},
},
3: {
1: {
0: null, // BAT1.0
},
},
4: {
0: EliteEIS, // EIS1.0
1: EliteEIS, // EIS1.1
2: EliteEIS, // EIS1.1_MINI
},
5: {
1: {
0: null, // TRIG0.1
},
},
6: {
1: {
0: null, // MEAGFLY0.1
},
},
},
}
/**
* return config table by libray or serial number (type)
* @param {String | Object} type
* @returns {Object} : config
*/
function getConfig (type) {
// library name
if (typeof type === 'string') {
return libraryNameMappingTable[type]
}
// serial number
if (typeof type === 'object') {
return serialNumberMappingTable[type[0]][type[1]][type[2]][type[3]]
}
}
/**
* return mode config table by type and mode
* @param {String | Object} type
* @param {Number} mode
* @returns {Object} : mode-config
*/
function getModeConfig (type, mode) {
return getConfig(type).MODE[mode]
}
/**
* return parameter config table by type and parameter name
* @param {String | Object} type
* @param {String} parameterName
* @returns {Object} : parameter-config
*/
function getParameterConfig (deviceType, parameterName) {
return getConfig(deviceType)[parameterName]
}
/**
* return channel config table by type and mode
* @param {String | Object} type
* @param {String} mode
* @param {String | Number} channel
* @returns {Object} : channel-config
*/
function getChannelConfig (type, mode, channel) {
if (channel === undefined) {
return getModeConfig(type, mode).channels
}
return getModeConfig(type, mode).channels[channel]
}
/**
* return chart config table by type and mode and chartType
* @param {String | Object} type
* @param {String} mode
* @param {String} chartType
* @returns {Object} : chart-config
*/
function getChartConfig (type, mode, chartType = 'default') {
return getModeConfig(type, mode).charts[chartType]
}
/**
* return mode's parameter list
* @param {String | Object} type
* @param {String} mode
* @returns {Object} : parameter list
*/
function getModeParameter (type, mode) {
return getModeConfig(type, mode).parameter
}
const configTable = {
getConfig,
getModeConfig,
getChannelConfig,
getParameterConfig,
getChartConfig,
getModeParameter,
EliteEDC,
EliteEIS,
}
export default configTable
@@ -25,7 +25,7 @@ export default {
h: 60 * 60 * 1e6,
auto: 1,
},
defaultUnit: 'us',
defaultUnit: 'auto',
},
0: {
name: 'I_in',
@@ -25,7 +25,7 @@ export default {
h: 60 * 60 * 1e6,
auto: 1,
},
defaultUnit: 'us',
defaultUnit: 'auto',
},
0: {
name: 'I_in',
@@ -22,10 +22,11 @@ export default {
us: 1,
ms: 1e3,
s: 1e6,
minute: 60 * 1e6,
hour: 60 * 60 * 1e6,
m: 60 * 1e6,
h: 60 * 60 * 1e6,
auto: 1,
},
defaultUnit: 'ms',
defaultUnit: 'auto',
downloadUnit: 'ms',
},
0: {
@@ -35,7 +36,7 @@ export default {
uA: 1e3,
mA: 1e6,
},
defaultUnit: 'mA',
defaultUnit: 'uA',
downloadUnit: 'mA',
},
1: {
@@ -22,10 +22,11 @@ export default {
us: 1,
ms: 1e3,
s: 1e6,
minute: 60 * 1e6,
hour: 60 * 60 * 1e6,
m: 60 * 1e6,
h: 60 * 60 * 1e6,
auto: 1,
},
defaultUnit: 'ms',
defaultUnit: 'auto',
downloadUnit: 'ms',
},
0: {
@@ -35,7 +36,7 @@ export default {
uA: 1e3,
mA: 1e6,
},
defaultUnit: 'mA',
defaultUnit: 'uA',
downloadUnit: 'mA',
},
1: {
@@ -22,10 +22,11 @@ export default {
us: 1,
ms: 1e3,
s: 1e6,
minute: 60 * 1e6,
hour: 60 * 60 * 1e6,
m: 60 * 1e6,
h: 60 * 60 * 1e6,
auto: 1,
},
defaultUnit: 'ms',
defaultUnit: 'auto',
downloadUnit: 'ms',
},
0: {
@@ -35,7 +36,7 @@ export default {
uA: 1e3,
mA: 1e6,
},
defaultUnit: 'mA',
defaultUnit: 'uA',
downloadUnit: 'mA',
},
1: {
@@ -22,10 +22,11 @@ export default {
us: 1,
ms: 1e3,
s: 1e6,
minute: 60 * 1e6,
hour: 60 * 60 * 1e6,
m: 60 * 1e6,
h: 60 * 60 * 1e6,
auto: 1,
},
defaultUnit: 'ms',
defaultUnit: 'auto',
downloadUnit: 'ms',
},
0: {
@@ -35,7 +36,7 @@ export default {
uA: 1e3,
mA: 1e6,
},
defaultUnit: 'mA',
defaultUnit: 'uA',
downloadUnit: 'mA',
},
1: {
@@ -24,8 +24,9 @@ export default {
s: 1e6,
m: 60 * 1e6,
h: 60 * 60 * 1e6,
auto: 1,
},
defaultUnit: 'ms',
defaultUnit: 'auto',
downloadUnit: 'ms',
},
0: {
@@ -35,7 +36,7 @@ export default {
uA: 1e3,
mA: 1e6,
},
defaultUnit: 'mA',
defaultUnit: 'uA',
downloadUnit: 'mA',
},
1: {
@@ -27,10 +27,11 @@ export default {
us: 1,
ms: 1e3,
s: 1e6,
minute: 60 * 1e6,
hour: 60 * 60 * 1e6,
m: 60 * 1e6,
h: 60 * 60 * 1e6,
auto: 1,
},
defaultUnit: 'ms',
defaultUnit: 'auto',
downloadUnit: 'ms',
},
0: {
@@ -40,7 +41,7 @@ export default {
uA: 1e3,
mA: 1e6,
},
defaultUnit: 'mA',
defaultUnit: 'uA',
downloadUnit: 'mA',
},
1: {
@@ -24,7 +24,7 @@ export default {
h: 60 * 60 * 1e6,
auto: 1,
},
defaultUnit: 'us',
defaultUnit: 'auto',
},
0: {
name: '0',
@@ -22,10 +22,11 @@ export default {
us: 1,
ms: 1e3,
s: 1e6,
minute: 60 * 1e6,
hour: 60 * 60 * 1e6,
m: 60 * 1e6,
h: 60 * 60 * 1e6,
auto: 1,
},
defaultUnit: 'ms',
defaultUnit: 'auto',
downloadUnit: 'ms',
},
0: {
@@ -35,7 +36,7 @@ export default {
uA: 1e3,
mA: 1e6,
},
defaultUnit: 'mA',
defaultUnit: 'uA',
downloadUnit: 'mA',
},
1: {
@@ -22,10 +22,11 @@ export default {
us: 1,
ms: 1e3,
s: 1e6,
minute: 60 * 1e6,
hour: 60 * 60 * 1e6,
m: 60 * 1e6,
h: 60 * 60 * 1e6,
auto: 1,
},
defaultUnit: 'ms',
defaultUnit: 'auto',
downloadUnit: 'ms',
},
0: {
@@ -35,7 +36,7 @@ export default {
uA: 1e3,
mA: 1e6,
},
defaultUnit: 'mA',
defaultUnit: 'uA',
downloadUnit: 'mA',
},
1: {
@@ -22,10 +22,11 @@ export default {
us: 1,
ms: 1e3,
s: 1e6,
minute: 60 * 1e6,
hour: 60 * 60 * 1e6,
m: 60 * 1e6,
h: 60 * 60 * 1e6,
auto: 1,
},
defaultUnit: 'ms',
defaultUnit: 'auto',
downloadUnit: 'ms',
},
0: {
@@ -35,7 +36,7 @@ export default {
uA: 1e3,
mA: 1e6,
},
defaultUnit: 'mA',
defaultUnit: 'uA',
downloadUnit: 'mA',
},
1: {
@@ -22,10 +22,11 @@ export default {
us: 1,
ms: 1e3,
s: 1e6,
minute: 60 * 1e6,
hour: 60 * 60 * 1e6,
m: 60 * 1e6,
h: 60 * 60 * 1e6,
auto: 1,
},
defaultUnit: 'ms',
defaultUnit: 'auto',
downloadUnit: 'ms',
},
0: {
@@ -35,7 +36,7 @@ export default {
uA: 1e3,
mA: 1e6,
},
defaultUnit: 'mA',
defaultUnit: 'uA',
downloadUnit: 'mA',
},
1: {
@@ -22,10 +22,11 @@ export default {
us: 1,
ms: 1e3,
s: 1e6,
minute: 60 * 1e6,
hour: 60 * 60 * 1e6,
m: 60 * 1e6,
h: 60 * 60 * 1e6,
auto: 1,
},
defaultUnit: 'ms',
defaultUnit: 'auto',
downloadUnit: 'ms',
},
0: {
@@ -35,7 +36,7 @@ export default {
uA: 1e3,
mA: 1e6,
},
defaultUnit: 'mA',
defaultUnit: 'uA',
downloadUnit: 'mA',
},
1: {
@@ -38,10 +38,11 @@ export default {
us: 1,
ms: 1e3,
s: 1e6,
minute: 60 * 1e6,
hour: 60 * 60 * 1e6,
m: 60 * 1e6,
h: 60 * 60 * 1e6,
auto: 1,
},
defaultUnit: 'ms',
defaultUnit: 'auto',
downloadUnit: 'ms',
},
0: {
@@ -51,7 +52,7 @@ export default {
uA: 1e3,
mA: 1e6,
},
defaultUnit: 'mA',
defaultUnit: 'uA',
downloadUnit: 'mA',
},
1: {
@@ -61,7 +62,7 @@ export default {
uA: 1e3,
mA: 1e6,
},
defaultUnit: 'mA',
defaultUnit: 'uA',
downloadUnit: 'mA',
},
},
@@ -22,10 +22,11 @@ export default {
us: 1,
ms: 1e3,
s: 1e6,
minute: 60 * 1e6,
hour: 60 * 60 * 1e6,
m: 60 * 1e6,
h: 60 * 60 * 1e6,
auto: 1,
},
defaultUnit: 'ms',
defaultUnit: 'auto',
downloadUnit: 'ms',
},
0: {
@@ -35,7 +36,7 @@ export default {
uA: 1e3,
mA: 1e6,
},
defaultUnit: 'mA',
defaultUnit: 'uA',
downloadUnit: 'mA',
},
1: {
@@ -49,7 +50,7 @@ export default {
downloadUnit: 'mV',
},
2: {
name: 'Resistor',
name: 'Resister',
unit: {
: 1,
mohm: 1,
@@ -22,10 +22,11 @@ export default {
us: 1,
ms: 1e3,
s: 1e6,
minute: 60 * 1e6,
hour: 60 * 60 * 1e6,
m: 60 * 1e6,
h: 60 * 60 * 1e6,
auto: 1,
},
defaultUnit: 'ms',
defaultUnit: 'auto',
downloadUnit: 'ms',
},
0: {
@@ -35,7 +36,7 @@ export default {
uA: 1e3,
mA: 1e6,
},
defaultUnit: 'mA',
defaultUnit: 'uA',
downloadUnit: 'mA',
},
1: {
File diff suppressed because it is too large Load Diff
+9
View File
@@ -0,0 +1,9 @@
import EliteZM15 from './EliteZM15/index'
import EliteEIS from './EliteEIS/index'
const paramTable = {
EliteZM15,
EliteEIS,
}
export default paramTable
+2 -9
View File
@@ -58,7 +58,7 @@ export const dataStreamBuffer = {
into: (currentDataByChannel, currentDeviceID, currentChannel) => {
// currentData = [ timeStart, d1, d2..... , timeEnd ]
// const currentData = JSON.parse(currentDataByChannel).binary.split(' '))
// const currentData = JSON.parse(currentDataByChannel).binary.split(' ')
const currentData = currentDataByChannel.split(' ')
// console.log(currentData)
const timeStart = parseInt(currentData[0])
@@ -109,7 +109,7 @@ export const dataStreamBuffer = {
// pop the first batch data from datastream buffer
pop: (chartID, deviceID, channel) => {
if (_dataStreamBuffer[chartID] != null && _dataStreamBuffer[chartID][deviceID] != null &&
_dataStreamBuffer[chartID][deviceID][channel] != null && _dataStreamBuffer[chartID][deviceID][channel].length > 0) {
_dataStreamBuffer[chartID][deviceID][channel] != null && _dataStreamBuffer[chartID][deviceID][channel].length > 0) {
return _dataStreamBuffer[chartID][deviceID][channel].shift()
}
return []
@@ -132,10 +132,3 @@ export const dataStreamBuffer = {
},
}
/*
{
"chartID" : {
"deviceID": {
"channel": [[dataset1], ... [dataset5], [datasetlog6]]
}
} */
+4 -5
View File
@@ -1,6 +1,6 @@
function newChart (chartID, numOfCharts) {
function newChart (chartID) {
return {
chartID: chartID,
chartID: parseInt(chartID),
chartType: 'detail',
chartDevice: 'elite', // elite or neulive
chartMode: 0,
@@ -8,11 +8,10 @@ function newChart (chartID, numOfCharts) {
chartYUnit: '',
chartXMode: 'value', // value or time
chartYMode: 'value', // value or time
cardName: 'chart' + String(numOfCharts),
cardName: 'chart' + String(chartID),
cardHeight: '500px',
cardWidth: 'auto',
mappingID: '-1',
createdBy: '', // manual ror default
mappingID: -1,
run: false,
timer: 0,
legend: {
-125
View File
@@ -1,125 +0,0 @@
function getTime (val) {
let label = ''
const hour = Math.floor(val / 3.6e9)
const minute = Math.floor((val % 3.6e9) / 1000000 / 60)
const second = Math.floor((val % 6e7) / 1000000)
const millisecond = Math.floor((val % 1e6) / 1000)
const microsecond = Math.floor(val % 1e6) - 1000 * millisecond
if (hour > 0) {
label += hour + ' h '
}
if (minute > 0) {
label += minute + ' m '
}
if (second > 0) {
label += second + ' s '
}
if (millisecond > 0) {
label += millisecond + ' ms '
}
if (microsecond > 0 && hour === 0 && minute === 0 && second === 0) {
label += microsecond + ' µs '
}
return label
}
function newTooltip (chartID) {
return {
hideDelay: 5000,
trigger: 'axis',
backgroundColor: '#fff',
borderColor: 'rgba(0, 0, 200, 0.2)',
borderWidth: 1,
borderRadius: 0,
padding: 10,
// axisPointer: {
// type: 'cross',
// animation: false,
// label: {
// backgroundColor: '#505765',
// },
// },
formatter: function (params) {
if (params.length) {
if (params[0].seriesName.split('_')[0] === 'T' && params[0].seriesName.split('_')[1] !== 'T') {
params.unshift({ seriesName: 'Time', value: [null, getTime(parseFloat(params[0].value[0]))], color: '#5193f2' })
} else if (params[0].seriesName.split('_')[0] !== 'T' && params[0].seriesName.split('_')[1] === 'T') {
params.unshift({ seriesName: 'Time', value: [null, getTime(parseFloat(params[0].value[1]))], color: '#5193f2' })
} else {
params.unshift({ seriesName: 'Time', value: [null, getTime(parseFloat(params[0].value[2]))], color: '#5193f2' })
}
let tip = ''
for (var i = 0; i < params.length; i++) {
const param = params[i]
const style = 'color: ' + param.color
let value
// console.log(param.value)
if (param.seriesName === 'Time') {
value = param.value[1]
} else if (param.seriesName.split('_')[1] === 'T' && param.seriesName.split('_')[0] !== 'T') {
const physicalQuantity = param.seriesName.split('_')[0][param.seriesName.split('_')[0].length - 1]
if (physicalQuantity === 'V') {
value = parseFloat(param.value[0]).toFixed(3) + ' μV'
} else if (physicalQuantity === 'I') {
value = parseFloat(param.value[0]).toFixed(3) + ' nA'
} else if (physicalQuantity === 'R') {
value = parseFloat(param.value[0]).toFixed(3) + ' mΩ'
} else if (physicalQuantity === 'X' || physicalQuantity === 'Y' || physicalQuantity === 'Z' || physicalQuantity === 'M') {
value = (parseFloat(param.value[0]) / 100).toFixed(3) + ' (g)'
} else if (!isNaN(physicalQuantity)) {
value = (parseFloat(param.value[0]) / 1000).toFixed(3) + ' (mV)'
} else {
value = parseFloat(param.value[0]).toFixed(3)
}
} else if (param.seriesName.split('_')[1] !== 'T' && param.seriesName.split('_')[0] === 'T') {
const physicalQuantity = param.seriesName.split('_')[1][param.seriesName.split('_')[1].length - 1]
if (physicalQuantity === 'V') {
value = parseFloat(param.value[1]).toFixed(3) + ' μV'
} else if (physicalQuantity === 'I') {
value = parseFloat(param.value[1]).toFixed(3) + ' nA'
} else if (physicalQuantity === 'R') {
value = parseFloat(param.value[1]).toFixed(3) + ' mΩ'
} else if (physicalQuantity === 'X' || physicalQuantity === 'Y' || physicalQuantity === 'Z' || physicalQuantity === 'M') {
value = (parseFloat(param.value[1]) / 100).toFixed(3) + ' (g)'
} else if (!isNaN(physicalQuantity)) {
value = (parseFloat(param.value[1]) / 1000).toFixed(3) + ' (mV)'
} else {
value = parseFloat(param.value[1]).toFixed(3)
}
} else {
let value1
let value2
if (param.seriesName.split('_')[0][param.seriesName.split('_')[0].length - 1] === 'V') {
value1 = parseFloat(param.value[0]).toFixed(3) + ' μV'
} else if (param.seriesName.split('_')[0][param.seriesName.split('_')[0].length - 1] === 'I') {
value1 = parseFloat(param.value[0]).toFixed(3) + ' nA'
} else if (param.seriesName.split('_')[0][param.seriesName.split('_')[0].length - 1] === 'R') {
value1 = parseFloat(param.value[0]).toFixed(3) + ' mΩ'
} else {
value1 = parseFloat(param.value[0]).toFixed(3)
}
if (param.seriesName.split('_')[1][param.seriesName.split('_')[1].length - 1] === 'V') {
value2 = parseFloat(param.value[1]).toFixed(3) + ' μV'
} else if (param.seriesName.split('_')[1][param.seriesName.split('_')[1].length - 1] === 'I') {
value2 = parseFloat(param.value[1]).toFixed(3) + ' nA'
} else if (param.seriesName.split('_')[1][param.seriesName.split('_')[1].length - 1] === 'R') {
value2 = parseFloat(param.value[1]).toFixed(3) + ' mΩ'
} else {
value2 = parseFloat(param.value[1]).toFixed(3)
}
value = value1 + ', ' + value2
}
tip += '<span style="' + style + '">' +
param.seriesName +
'</span><span style="' +
style + '">' + value + '</span><br>'
}
return tip
}
},
}
}
export default newTooltip
+84 -58
View File
@@ -23,25 +23,7 @@ function getTime (val) {
return label
}
function getPhysicsQunatity (name, dataMode) {
// console.log('getPhysicsQunatity', name, dataMode)
const label = []
name = name.split('_')
for (let i = 0; i < name.length; i++) {
if (name[i].includes('T')) {
label.push('Time')
} else if (name[i].includes('V')) {
label.push('Voltage')
} else if (name[i].includes('I')) {
label.push('Current')
} else if (name[i].includes('R')) {
label.push('Impedance')
}
}
return label
}
function newTooltip (realTime, dataMode) {
function newTooltip (chartID) {
return {
hideDelay: 5000,
trigger: 'axis',
@@ -50,48 +32,92 @@ function newTooltip (realTime, dataMode) {
borderWidth: 1,
borderRadius: 0,
padding: 10,
// axisPointer: {
// type: 'cross',
// animation: false,
// label: {
// backgroundColor: '#505765',
// },
// },
formatter: function (params) {
// params is empty
if (!params.length && realTime.length) return params
// params is unempty
let tip = ''
let param // find coressonding parameter to the channel
let unitTable // unit is store in this object
let physicsQunatity // type is store here
let style // color
let value // value on cursor
const timeIndex = params[0].seriesName.split('_').findIndex(title => title === 'T')
// (Default) Time
if (timeIndex === -1) {
value = getTime(parseFloat(params[0].value[2]))
} else {
value = getTime(parseFloat(params[0].value[timeIndex]))
}
tip += '<span style="color: #5193f2">' + 'Time: ' + value + '</span><br>'
// (Manual) Voltage, Current, Impedance
for (let gridIndex = 0; gridIndex < realTime.length; gridIndex++) {
for (let channelIndex = 0; channelIndex < realTime[gridIndex].length; channelIndex++) {
param = params.find(x => x.seriesName === realTime[gridIndex][channelIndex].name)
if (param === undefined) continue
unitTable = realTime[gridIndex][channelIndex]
style = 'color: ' + param.color
physicsQunatity = getPhysicsQunatity(param.seriesName, dataMode)
tip += '<span style="' + style + '">' + param.seriesName + ':<ul style = "list-style-type: disc; list-style-position: inside">'
if (physicsQunatity[0] !== 'Time') {
value = parseFloat(param.value[0] / unitTable.xValueScale[unitTable.xUnit]).toFixed(3) + unitTable.xUnit
tip += '<li>' + physicsQunatity[0] + ' = ' + value + '</li>'
}
if (physicsQunatity[1] !== 'Time') {
value = parseFloat(param.value[1] / unitTable.yValueScale[unitTable.yUnit]).toFixed(3) + unitTable.yUnit
tip += '<li>' + physicsQunatity[1] + ' = ' + value + '</li>'
}
tip += '</ul></span>'
if (params.length) {
if (params[0].seriesName.split('_')[0] === 'T' && params[0].seriesName.split('_')[1] !== 'T') {
params.unshift({ seriesName: 'Time', value: [null, getTime(parseFloat(params[0].value[0]))], color: '#5193f2' })
} else if (params[0].seriesName.split('_')[0] !== 'T' && params[0].seriesName.split('_')[1] === 'T') {
params.unshift({ seriesName: 'Time', value: [null, getTime(parseFloat(params[0].value[1]))], color: '#5193f2' })
} else {
params.unshift({ seriesName: 'Time', value: [null, getTime(parseFloat(params[0].value[2]))], color: '#5193f2' })
}
let tip = ''
for (var i = 0; i < params.length; i++) {
const param = params[i]
const style = 'color: ' + param.color
let value
// console.log(param.value)
if (param.seriesName === 'Time') {
value = param.value[1]
} else if (param.seriesName.split('_')[1] === 'T' && param.seriesName.split('_')[0] !== 'T') {
const physicalQuantity = param.seriesName.split('_')[0][param.seriesName.split('_')[0].length - 1]
if (physicalQuantity === 'V') {
value = parseFloat(param.value[0]).toFixed(3) + ' μV'
} else if (physicalQuantity === 'I') {
value = parseFloat(param.value[0]).toFixed(3) + ' nA'
} else if (physicalQuantity === 'R') {
value = parseFloat(param.value[0]).toFixed(3) + ' mΩ'
} else if (physicalQuantity === 'X' || physicalQuantity === 'Y' || physicalQuantity === 'Z' || physicalQuantity === 'M') {
value = (parseFloat(param.value[0]) / 100).toFixed(3) + ' (g)'
} else if (!isNaN(physicalQuantity)) {
value = (parseFloat(param.value[0]) / 1000).toFixed(3) + ' (mV)'
} else {
value = parseFloat(param.value[0]).toFixed(3)
}
} else if (param.seriesName.split('_')[1] !== 'T' && param.seriesName.split('_')[0] === 'T') {
const physicalQuantity = param.seriesName.split('_')[1][param.seriesName.split('_')[1].length - 1]
if (physicalQuantity === 'V') {
value = parseFloat(param.value[1]).toFixed(3) + ' μV'
} else if (physicalQuantity === 'I') {
value = parseFloat(param.value[1]).toFixed(3) + ' nA'
} else if (physicalQuantity === 'R') {
value = parseFloat(param.value[1]).toFixed(3) + ' mΩ'
} else if (physicalQuantity === 'X' || physicalQuantity === 'Y' || physicalQuantity === 'Z' || physicalQuantity === 'M') {
value = (parseFloat(param.value[1]) / 100).toFixed(3) + ' (g)'
} else if (!isNaN(physicalQuantity)) {
value = (parseFloat(param.value[1]) / 1000).toFixed(3) + ' (mV)'
} else {
value = parseFloat(param.value[1]).toFixed(3)
}
} else {
let value1
let value2
if (param.seriesName.split('_')[0][param.seriesName.split('_')[0].length - 1] === 'V') {
value1 = parseFloat(param.value[0]).toFixed(3) + ' μV'
} else if (param.seriesName.split('_')[0][param.seriesName.split('_')[0].length - 1] === 'I') {
value1 = parseFloat(param.value[0]).toFixed(3) + ' nA'
} else if (param.seriesName.split('_')[0][param.seriesName.split('_')[0].length - 1] === 'R') {
value1 = parseFloat(param.value[0]).toFixed(3) + ' mΩ'
} else {
value1 = parseFloat(param.value[0]).toFixed(3)
}
if (param.seriesName.split('_')[1][param.seriesName.split('_')[1].length - 1] === 'V') {
value2 = parseFloat(param.value[1]).toFixed(3) + ' μV'
} else if (param.seriesName.split('_')[1][param.seriesName.split('_')[1].length - 1] === 'I') {
value2 = parseFloat(param.value[1]).toFixed(3) + ' nA'
} else if (param.seriesName.split('_')[1][param.seriesName.split('_')[1].length - 1] === 'R') {
value2 = parseFloat(param.value[1]).toFixed(3) + ' mΩ'
} else {
value2 = parseFloat(param.value[1]).toFixed(3)
}
value = value1 + ', ' + value2
}
tip += '<span style="' + style + '">' +
param.seriesName +
'</span><span style="' +
style + '">' + value + '</span><br>'
}
return tip
}
return tip
},
}
}
+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',
-1
View File
@@ -9,4 +9,3 @@ $ionicons-font-path: "~ionicons/dist/fonts";
$fa-font-path: "~font-awesome/fonts";
@import "../../../node_modules/font-awesome/scss/font-awesome";
@import url(https://fonts.googleapis.com/icon?family=Material+Icons);
@@ -1,6 +1,6 @@
import newSeries from '@/factories/chart/seriesFactory'
import newChart from '@/factories/chart/chartFactory'
import newTooltip from '@/factories/chart/replayTooltipFactory'
import newTooltip from '@/factories/chart/tooltipFactory'
import newDataZoom from '@/factories/chart/dataZoomFactory'
import types from '@/store/modules/analysis/replay/types'
@@ -1,6 +1,6 @@
import types from '@/store/modules/download/types'
import golbalMethods from '@/data/global/global'
import configTable from '@/data/config-table/index'
import paramTable from '@/data/param-table/index'
import api from '@/data/api'
const typePath = types.export
@@ -49,7 +49,7 @@ const exportActs = {
metaPath[metaPath.length - 1].split('.')[0],
]
const paramObj = configTable.getConfig(libraryName)
const paramObj = paramTable[libraryName]
const modeObj = paramObj.MODE[meta.parameter_set.MODE]
const param = modeObj.headerParameter(meta.parameter_set)
@@ -120,7 +120,7 @@ const exportActs = {
[typePath.getTitle]: function ({ state, getters, commit, dispatch }, payload) {
const meta = state.metaInfo
const { library_name: libraryName } = meta.device
const modeObj = configTable.getModeConfig(libraryName, meta.parameter_set.MODE)
const modeObj = paramTable[libraryName].MODE[meta.parameter_set.MODE]
const downloadInfo = state.downloadInfo
const titleArray = []
const channelString = ''
@@ -66,8 +66,6 @@ const projectActs = {
*/
[typePath.select]: async ({ state, getters, commit }, payload) => {
state.projectSelectIndex = payload.index
// initial default device library
state.projectLibrary = state.projectList[payload.index].device[0]?.library.value
},
/**
+3 -2
View File
@@ -1,5 +1,8 @@
function newState () {
return {
projectAll: {},
projectSelectKey: '',
projectList: [],
projectSelectIndex: -1,
@@ -14,8 +17,6 @@ function newState () {
projectManagerPanel: {
show: true,
},
// library
projectLibrary: null,
taskViewPanel: {
show: false,
@@ -16,29 +16,31 @@ const chartActs = {
/**
* init chartData from cache (cache will only record non-default chart)
*
**/
*/
[typePath.initCustomizedFromCache]: async ({ state, getters, commit, dispatch }, payload) => {
const cacheData = await localforage.getItem('chart_data')
if (cacheData !== null) {
// use ID to create new chart by cache
for (const _chart of Object.values(cacheData)) {
dispatch(typePath.add, {
chartID: _chart.chartID,
maxDots: _chart.maxDots,
gridLength: _chart.grid.length,
})
for (let gridIndex = 0; gridIndex < _chart.grid.length; gridIndex++) {
if (gridIndex in _chart.gridSource) {
dispatch(typePath.registerFromCache, {
chartID: _chart.chartID,
gridIndex: gridIndex,
gridSource: _chart.gridSource[gridIndex],
})
if (_chart.mappingID === -1) { // not default chart
const newChartID = state.taskContentChartNumber
dispatch(typePath.add, {
chartID: newChartID,
maxDots: _chart.maxDots,
gridLength: _chart.grid.length,
})
for (let gridIndex = 0; gridIndex < _chart.grid.length; gridIndex++) {
if (gridIndex in _chart.gridSource) {
dispatch(typePath.registerFromCache, {
chartID: newChartID,
gridIndex: gridIndex,
gridSource: _chart.gridSource[gridIndex],
})
}
}
state.taskContentChartNumber++
dispatch(typePath.refreshPanel)
}
state.chartData[_chart.chartID].createdBy = 'manual'
}
dispatch(typePath.refreshPanel)
}
},
/**
@@ -48,16 +50,19 @@ const chartActs = {
[typePath.saveToCache]: async ({ state, getters, commit, dispatch }, payload) => {
const _chartData = {}
for (const [_id, _chart] of Object.entries(state.chartData)) {
// manual chart clear series data
if (_chart.createdBy === 'manual') {
if (_chart.mappingID === -1) { // not default chart
_chartData[_id] = JSON.parse(JSON.stringify(_chart))
_chartData[_id].series.map((ele) => { ele.data.length = 0 })
if (_chartData[_id].series.data != null) {
_chartData[_id].series.data.length = 0
}
_chartData[_id].series.length = 0
}
}
await localforage.setItem('chart_data', _chartData)
},
/*
/**
* add chartID to chartData
*
* @param {String} chartID
* @param {Number} maxDots
* @param {Number} gridLength
@@ -65,8 +70,8 @@ const chartActs = {
*/
[typePath.add]: ({ state, getters, commit, dispatch }, payload) => {
const { chartID, maxDots, gridLength } = payload
if (state.chartData[chartID] == null) {
state.chartData[chartID] = newChart(chartID, Object.keys(state.chartData).length)
if (state.chartData[parseInt(chartID)] == null) {
state.chartData[parseInt(chartID)] = newChart(chartID)
state.chartData[chartID].maxDots = maxDots
state.chartData[chartID].tooltip = newTooltip()
dispatch(typePath.updateGridList, { chartID: chartID, length: gridLength })
@@ -75,7 +80,6 @@ const chartActs = {
return state.chartData[chartID]
}
},
/**
* register source channel setting from cache
*
@@ -230,10 +234,28 @@ const chartActs = {
state.chartData[chartID].yAxis[_yAxisIndex].seriesIndex.push(_seriesIndex)
// set xAxis format
// TODO: need to get the time unit for the CanvasChart
if (sourceList[0].name === 'Time') {
state.chartData[chartID].xAxis[_xAxisIndex].axisLabel.formatter = function (val) {
return getTimeFormatter(val)
const hour = parseInt(val / 3.6e9)
const minute = parseInt((val % 3.6e9) / 1000000 / 60)
const second = parseInt((val % 6e7) / 1000000)
const millisecond = parseInt((val % 1e6) / 1000)
let label = ''
if (hour > 0) {
label += hour + ' h '
}
if (minute > 0) {
label += minute + ' m '
}
if (second > 0) {
label += second + ' s '
}
if (millisecond > 0) {
label += millisecond + ' ms '
}
// const label = parseInt(parseInt(val / 1000000) / 60) + ' m ' + parseInt((val % 60000000) / 1000000) + ' s'
return label
}
state.chartData[chartID].xAxis[_xAxisIndex].interval = 500 * 1000
} else if (sourceList[0].name === 'Elite') {
@@ -340,6 +362,7 @@ const chartActs = {
return parseFloat(val / 1000).toFixed(2) + 'uA'
}
state.chartData[chartID].chartYUnit = 'uA' // nA * 1000
console.log(state.chartData[chartID])
break
case 2:
state.chartData[chartID].yAxis[_yAxisIndex].axisLabel.formatter = function (val) {
@@ -492,14 +515,7 @@ const chartActs = {
if (!state.chartData[chartID].gridSource[gridIndex].some(el => el.name === _gridSeries.name)) {
state.chartData[chartID].gridSource[gridIndex].push(_gridSeries)
}
// assign mappingID with device ID
if (deviceIDX >= 0) {
state.chartData[chartID].mappingID = deviceIDX
}
if (deviceIDY >= 0) {
state.chartData[chartID].mappingID = deviceIDY
}
// console.log(state.chartData[chartID])
return state.chartData[chartID]
},
/**
@@ -521,7 +537,7 @@ const chartActs = {
* @param {String} chartID
*/
[typePath.refreshData]: ({ state, getters, commit, dispatch }, payload) => {
const { chartID } = payload
const { chartID, deviceList } = payload
if (state.chartData[chartID] == null) {
return false
}
@@ -694,12 +710,24 @@ const chartActs = {
// series data list shift by time
if (series.data.length > 0) {
if (series.xAxisSource[0] === -1) {
if (series.data.length > state.chartData[chartID].maxDots) {
series.data.splice(0, series.data.length - state.chartData[chartID].maxDots)
if (deviceList.find(ele => ele.memory_board === series.yAxisSource[0]).library_name.includes('Elite')) {
if (series.data.length > state.chartData[chartID].maxDots) {
series.data.splice(0, series.data.length - state.chartData[chartID].maxDots)
}
} else {
if (series.data[series.data.length - 1][0] - series.data[0][0] > 3000000) {
series.data.splice(0, popData.length)
}
}
} else if (series.yAxisSource[0] === -1) {
if (series.data.length > state.chartData[chartID].maxDots) {
series.data.splice(0, series.data.length - state.chartData[chartID].maxDots)
if (deviceList.find(ele => ele.memory_board === series.xAxisSource[0]).library_name.includes('Elite')) {
if (series.data.length > state.chartData[chartID].maxDots) {
series.data.splice(0, series.data.length - state.chartData[chartID].maxDots)
}
} else {
if (series.data[series.data.length - 1][1] - series.data[0][1] > 3000000) {
series.data.splice(0, popData.length)
}
}
}
}
@@ -974,7 +1002,7 @@ const chartActs = {
mappingID: state.chartData[_chartID].mappingID,
cardName: state.chartData[_chartID].cardName,
})
state.chartData[_chartID].mappingID = item.id
state.chartData[_chartID].mappingID = parseInt(item.id)
switch (_type) {
case 'device':
_chartRegisterDevice(_chartID, item)
@@ -988,23 +1016,21 @@ const chartActs = {
let isSetting = false
for (const chartID in state.chartData) {
if (state.chartData[chartID].mappingID === item.id) {
if (state.chartData[chartID].createdBy === 'default') {
isSetting = true
dispatch(typePath.reset, {
chartID: chartID,
mappingID: state.chartData[chartID].mappingID,
cardName: state.chartData[chartID].cardName,
})
state.chartData[chartID].mappingID = item.id
switch (_type) {
case 'device':
_chartRegisterDevice(chartID, item)
break
case 'formula':
_chartRegisterFormula(chartID, item)
break
}
if (parseInt(state.chartData[chartID].mappingID) === parseInt(item.id)) {
isSetting = true
dispatch(typePath.reset, {
chartID: chartID,
mappingID: state.chartData[chartID].mappingID,
cardName: state.chartData[chartID].cardName,
})
state.chartData[chartID].mappingID = parseInt(item.id)
switch (_type) {
case 'device':
_chartRegisterDevice(chartID, item)
break
case 'formula':
_chartRegisterFormula(chartID, item)
break
}
}
}
@@ -1027,13 +1053,12 @@ const chartActs = {
state.chartData[chartID].legend.data.length = 0
state.chartData[chartID].xAxis.length = 0
state.chartData[chartID].yAxis.length = 0
state.chartData[chartID].gridSource.length = 0
if (state.chartData[chartID].series.data != null) {
state.chartData[chartID].series.data.length = 0
}
state.chartData[chartID].series.length = 0
if (mappingID == null) {
state.chartData[chartID].mappingID = '-1'
state.chartData[chartID].mappingID = -1
}
if (cardName == null) {
state.chartData[chartID].cardName = 'chart' + String(chartID)
@@ -1041,22 +1066,6 @@ const chartActs = {
state.chartData[chartID].dataZoom = null
dispatch(typePath.updateGridList, { chartID: chartID, length: 1 })
},
/**
* reset chart option
*
* @param {String} chartID
* @param {String} mappingID
* @param {String} cardName
*/
[typePath.resetSeriesData]: ({ state, getters, commit, dispatch }, payload) => {
const { chartID, mappingID } = payload
if (String(mappingID) === String(state.chartData[chartID].mappingID)) {
for (const i in state.chartData[chartID].series) {
state.chartData[chartID].series[i].data.length = 0
}
}
},
/**
* refresh (key++) EChart
*
@@ -1309,24 +1318,3 @@ function getLegendName (sourceList, formulaID) {
}
return legendName
}
export function getTimeFormatter (val) {
const hour = parseInt(val / 3.6e9)
const minute = parseInt((val % 3.6e9) / 1000000 / 60)
const second = parseInt((val % 6e7) / 1000000)
const millisecond = parseInt((val % 1e6) / 1000)
let label = ''
if (hour > 0) {
label += hour + ' h '
}
if (minute > 0) {
label += minute + ' m '
}
if (second > 0) {
label += second + ' s '
}
if (millisecond > 0) {
label += millisecond + ' ms '
}
return label
}
-1
View File
@@ -9,7 +9,6 @@ const types = {
updateGridList: 'taskContentChartUpdateGridList',
defaultChartGenerator: 'taskContentChartDefaultChartGenerator',
reset: 'taskContentChartReset',
resetSeriesData: 'taskContentChartResetSeriesData',
refreshData: 'taskContentChartRefreshData',
refreshChart: 'taskContentChartRefreshChart',
refreshPanel: 'taskContentChartRefreshPanel',