Compare commits

...

76 Commits

Author SHA1 Message Date
peterlu14 b7b70b86e2 Merge remote-tracking branch 'origin/dev/fix_dataZoom' into release/v1.2.8/realtime-tool 2022-08-03 14:50:36 +08:00
sss28072637 2575a97894 [debug] fix real-time dataZoom bug 2022-08-03 14:45:38 +08:00
peterlu14 a1f09942d9 Merge branch 'release/v1.2.9/fix-testing-bugs' into release/v1.2.8/realtime-tool 2022-08-02 18:42:49 +08:00
peterlu14 e9dc718d85 [update] fix cache with controller id 2022-08-02 16:25:47 +08:00
108000207 2f7a6b97e7 Merge branch 'dev/replay-calculation' into release/v1.2.8/realtime-tool 2022-08-02 14:35:31 +08:00
108000207 11a6de5e57 [update] add the getPanelInfo for tooltips formatter 2022-08-02 14:21:13 +08:00
peterlu14 7630951470 Merge remote-tracking branch 'origin/dev/realTimeDisplay_realTimeCalculation' into release/v1.2.8/realtime-tool 2022-08-02 12:52:16 +08:00
nthu1080112244 eb672d9c0a [update] real time cycle display 2022-08-02 12:51:19 +08:00
sss28072637 566f59e29c fix replay bugs, add integral in I-V mode(replay & realtime) and fix integral bugs 2022-08-01 18:22:01 +08:00
peterlu14 f06003304a Merge branch 'release/v1.2.9/fix-testing-bugs' into release/v1.2.8/realtime-tool 2022-07-29 14:54:26 +08:00
peterlu14 c0fc13c451 [update] cp-mode rename 2022-07-29 14:54:07 +08:00
peterlu14 ab1df2cfe1 [update] add time duration in excel and replay & add cp mode volt unit 2022-07-29 10:16:05 +08:00
peterlu14 0b01d6c785 [update] fix display problem & help pic 2022-07-28 16:56:26 +08:00
peterlu14 d769a50459 [debug] charge/discharge value error 2022-07-28 14:58:47 +08:00
peterlu14 dac276c9de [debug] fix cc mode charge display error 2022-07-28 14:40:36 +08:00
peterlu14 65c00031e3 [debug] fix volt step unit error 2022-07-28 10:35:51 +08:00
peterlu14 0ff3dd556f [update] remove vue warn 2022-07-28 10:30:09 +08:00
peterlu14 968c578cee Merge branch 'dev/realTimeDisplay_realTimeCalculation' into 'release/v1.2.8/realtime-tool'
[debug]  fix the conflict between display tool and funtional tool

See merge request wisetop/controller/wisetopvue!1
2022-07-28 02:22:44 +00:00
peterlu14 b3510b1990 [debug] fix volt step unit error 2022-07-28 10:05:47 +08:00
108000207 7fc8d24a71 [update] add replay functional, need to check the time gap 2022-07-27 18:31:52 +08:00
nthu1080112244 35d45a36a4 [update] time-axis formatter 2022-07-27 18:31:16 +08:00
nthu1080112244 f1a55c3cd1 [debug] remove useless code 2022-07-27 14:09:20 +08:00
nthu1080112244 2577dcba9a [update] 1. built and use CanvasChartTable.js
2. merge real time functional amd real time display
                3. tooltip update
2022-07-27 13:41:33 +08:00
108000207 f2709241d2 [init] add CanvasChartReplayCalculation component 2022-07-27 09:56:20 +08:00
ROY 632762ce14 [update] library EliteEIS rename cause replay problem 2022-07-26 18:29:34 +08:00
sss28072637 63b627622b [update] use setTimeOut to make the emit from changeScale work 2022-07-26 18:07:30 +08:00
ROY e4e89a414a [update] fix library rename replay nameing bug 2022-07-26 14:00:15 +08:00
ROY 921166cdc7 [update] update library name & change global chart setting 2022-07-26 11:05:50 +08:00
peterlu14 a3e7c7e2a6 Merge remote-tracking branch 'origin/dev/realTimeDisplayNew' into release/v1.2.8/realtime-tool 2022-07-26 09:53:25 +08:00
peterlu14 7469d270d0 Merge remote-tracking branch 'origin/dev/realtime-tool-fixed' into release/v1.2.8/realtime-tool 2022-07-26 09:53:21 +08:00
nthu1080112244 3c4676ec2c [update] construct new table for chart axis unit 2022-07-26 09:45:49 +08:00
sss28072637 265c363858 fix real-time tooltips 2022-07-25 14:14:26 +08:00
peterlu14 89da594392 Merge remote-tracking branch 'origin/dev/haolung' into release/v1.2.8/realtime-tool 2022-07-22 16:24:33 +08:00
sss28072637 436ed27479 fix button bug 2022-07-22 14:55:42 +08:00
peterlu14 ea14ee2f3e [update] remove redundence code 2022-07-22 14:31:16 +08:00
peterlu14 4416367acf [update] fix replay tooltip problem 2022-07-22 14:31:13 +08:00
peterlu14 e44c1e4c18 [update] fix merge config table problem 2022-07-22 14:31:09 +08:00
peterlu14 4910719aa4 Merge remote-tracking branch 'origin/dev/real_time_value' into release/v1.2.8/realtime-tool 2022-07-22 14:30:32 +08:00
peterlu14 223e898d5e [update] fix config-table rename problem ( download, replay ) 2022-07-22 14:25:05 +08:00
sss28072637 1e80731438 separate the calculation file 2022-07-22 14:17:09 +08:00
peterlu14 d3d080eb08 [update] add EIS mimi 2022-07-22 10:34:07 +08:00
nthu1080112244 0bd84d865f [update] integrate axis unit, tooltip information 2022-07-22 09:41:40 +08:00
sss28072637 b14488cf49 simplify the code (ver1) 2022-07-21 17:08:49 +08:00
peterlu14 4dda2d0a6a [update] switch page remove cache fix 2022-07-21 17:02:16 +08:00
sss28072637 3460a0bfa0 fix time axisLabel 2022-07-21 11:46:47 +08:00
sss28072637 90738611eb (07/20) finish differential, log, integral, add additional function, fix bugs and clear console log 2022-07-20 17:12:30 +08:00
peterlu14 35ba66ddd6 Merge branch 'release/v1.2.5/task_configuration' into release/v1.2.7/scheduler-parameter 2022-07-20 09:53:03 +08:00
peterlu14 4c3c63a0ba [update] schedule parameter fix & config-table add default value 2022-07-20 09:52:40 +08:00
sss28072637 d22653a5a5 clear console error 2022-07-19 16:38:39 +08:00
sss28072637 05cae92b12 finish integral, differential and log 2022-07-19 14:59:08 +08:00
sss28072637 adbf30f08d Merge remote-tracking branch 'origin/release/v1.2.5/task_configuration' into dev/haolung 2022-07-19 11:32:16 +08:00
nthu1080112244 5fe321828a Merge remote-tracking branch 'origin/release/v1.2.5/task_configuration' into dev/real_time_value 2022-07-19 11:30:21 +08:00
peterlu14 ca823d174b [update] reset series data type error fix 2022-07-19 11:26:46 +08:00
nthu1080112244 2e573e2c72 [update] add coment 2022-07-19 11:22:55 +08:00
nthu1080112244 84d136d4cf [update] real time display modularization 2022-07-18 18:28:23 +08:00
nthu1080112244 9b296c45bd [update] complete real time value display 2022-07-18 15:13:16 +08:00
nthu1080112244 ef9db8bee2 Merge commit 'bcf7b51dc6f0c241ab2f8bd3fdffb4173a5e7693' into dev/real_time_value 2022-07-18 14:15:23 +08:00
sss28072637 175f4ef23e Merge remote-tracking branch 'origin/release/v1.2.5/task_configuration' into dev/haolung 2022-07-18 10:28:38 +08:00
sss28072637 eba7c080b4 merge_0718 2022-07-18 09:55:05 +08:00
nthu1080112244 7c4515521d [update] unit correction, real time value bar 2022-07-15 19:40:34 +08:00
peterlu14 3db09734d2 [update] use deviceParameterWindow instead 2022-07-15 10:08:24 +08:00
peterlu14 c0e3a9c61a [update] rename param-table to config-table & add api to config 2022-07-15 10:08:24 +08:00
peterlu14 bcf7b51dc6 [update] mapping unify format string 2022-07-15 10:05:24 +08:00
peterlu14 ba660ac952 [update] fix girdsource not clear problem 2022-07-14 10:21:39 +08:00
sss28072637 1062aea8db fix tooltip constructor parameters, start / stop clicked reset, clear console errors, add differential function, get timeIndex automatically 2022-07-13 16:33:17 +08:00
sss28072637 b1f9edc624 Merge remote-tracking branch 'origin/release/v1.2.5/task_configuration' into dev/haolung 2022-07-13 09:37:41 +08:00
sss28072637 9210646611 add comments 2022-07-12 18:17:38 +08:00
sss28072637 de2315cd5b finish integral and log 2022-07-12 17:33:01 +08:00
sss28072637 ec231aa368 fix stop mode intergration 2022-07-12 15:33:21 +08:00
nthu1080112244 7b6948d027 Merge remote-tracking branch 'origin/release/v1.2.5/task_configuration' into dev/real_time_value 2022-07-12 15:15:12 +08:00
nthu1080112244 28f1aef82c [update] default real time representation 2022-07-12 15:14:31 +08:00
sss28072637 908db19110 finish mode switch button 2022-07-12 14:06:12 +08:00
sss28072637 9520e5102c finish integral of VT_mode 2022-07-12 12:02:58 +08:00
peterlu14 d171d8b572 [update] only refresh chart which device running 2022-07-12 10:41:43 +08:00
peterlu14 1e57bde1df [update] chartID uuid && fix mappingID -1 && reset series data && chart created manual or default 2022-07-12 10:38:04 +08:00
peterlu14 0946b01a41 [update] prop chartID add new type 2022-07-12 10:30:36 +08:00
66 changed files with 2653 additions and 1000 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://192.168.5.66:8083'
// MqttUrl = 'ws://192.168.5.57:8083'
// MqttUrl = 'ws://192.168.5.57:8080'
} else {
// for user
MqttUrl = `ws://${location.href.split('/')[2]}:8083`
@@ -9,7 +9,7 @@
<span slot="header">Control Panel</span>
<div slot="body">
<div>
<top-control-panel :ref="'top_control_panel'" @refreshChart="setOption" @changeAxis="changeAxis" @changeOverviewDataZoom="changeOverviewDataZoom"/>
<top-control-panel :ref="'top_control_panel'" @refreshChart="setOption" @changeAxis="changeAxis" @changeOverviewDataZoom="changeOverviewDataZoom" @changeFunctional="changeFunctional"/>
</div>
</div>
</va-collapse>
@@ -106,6 +106,8 @@ export default {
zoomTime: 0,
initDone: false,
chartAreaClass: ['flex', 'xs12', 'sm12', 'md12', 'xl9', 'pa-0'],
xfunctional: 'Linear',
yfunctional: 'Linear',
}
},
mqtt: {
@@ -236,7 +238,6 @@ export default {
this.windowLength = this.endTime - this.startTime
this.chartOverviewData.dataZoom[0].start = dataZoom.start
this.chartOverviewData.dataZoom[0].end = dataZoom.end
// console.log(this.startTime, this.endTime)
}
})
} else {
@@ -247,7 +248,6 @@ export default {
this.windowLength = this.endTime - this.startTime
this.chartOverviewData.dataZoom[0].start = e.start
this.chartOverviewData.dataZoom[0].end = e.end
// console.log(this.startTime, this.endTime)
}
}
this.zoomTime = 0
@@ -313,7 +313,6 @@ export default {
if (this.axisXDataType.description === 'Time') {
scale = await this.computeResampleScale(metaInfo, metaInfo.time_duration)
}
console.log('overview scale:', scale)
// download data
const getAllData = async function (_this) {
for (const ch in _this.dataInfo[meta]) {
@@ -346,6 +345,8 @@ export default {
this.hideChartLoading()
},
drawDetailData: async function () {
var panelInfo = this.$refs.top_control_panel.getPanelInfo()
console.log('panelInfo: ', panelInfo) // TODO: update the formatter for tooltips
this.showChartLoading('detail')
const timeDur = this.endTimeCurrent - this.startTimeCurrent
let _gridNumber = 0
@@ -368,7 +369,7 @@ export default {
this.updateChartSamplingChart({ chartID: this.chartDetailData.chartID, seriesIndex: _gridNumber, method: 'lttb' })
}
if (metaInfo.device.library_name === 'EliteEIS' && metaInfo.parameter_set.MODE === 0) {
if (metaInfo.device.library_name.includes('EIS') && metaInfo.parameter_set.MODE === 0) {
this.chartDetailData.series[this.chartDetailData.series.length - 1].showSymbol = true
this.chartDetailData.series[this.chartDetailData.series.length - 1].showAllSymbol = true
this.chartDetailData.series[this.chartDetailData.series.length - 1].symbolSize = 6
@@ -419,27 +420,113 @@ export default {
}
}
// download and push into chart
// due to the (endIndex - startIndex) may more than 1, need to record variables outside the loop
var integralResult = 0
var curXData = 0
var curYData = 0
var prevXData = 0
var prevYData = 0
for (let i = startIndex; i <= endIndex; i++) {
const data = await this.getData(parseInt(scale), this.sampleMethod, dataListY[i].id, channelY, metaInfo)
let dataX
if (this.axisXDataType.description !== 'Time') {
dataX = await this.getData(parseInt(scale), this.sampleMethod, dataListX[i].id, channelX, metaInfo)
}
var deltaX = 0
var diffResult = 0
var logZero = false
var lastXinThisTable
for (let j = 0, len = data.length; j < len; j++) {
// check which channel and push processed data (i.e. merge two channel data, now data is (time, value) format)
if (parseInt(data[j][0]) >= _startTime && parseInt(data[j][0]) <= _endTime) {
const processedData = data[j]
logZero = false
// cases without time
if (dataX !== undefined) {
processedData[0] = dataX[j][1]
// add time on the chart
// TODO: not sure the time is right or not?
processedData[2] = parseFloat(dataX[j][0])
}
if (this.displayType.x === 'log' || this.absToggleStatus.x === true) {
// below is the original version for the log
/* if (this.displayType.x === 'log' || this.absToggleStatus.x === true) {
processedData[0] = Math.abs(processedData[0])
}
if (this.displayType.y === 'log' || this.absToggleStatus.y === true) {
processedData[1] = Math.abs(processedData[1])
} */
if (this.xfunctional === 'Log') {
// avoid log10(0) cases
if (Math.abs(processedData[0]) === 0) logZero = true
processedData[0] = Math.log10(Math.abs(processedData[0]))
}
this.chartDetailData.series[_gridNumber].data.push(processedData)
if (this.yfunctional === 'Log') {
if (Math.abs(processedData[1]) === 0) logZero = true
processedData[1] = Math.log10(Math.abs(processedData[1]))
} else if (this.yfunctional === 'Integral') {
if (j === 0) {
// TODO: need to change the series[deviceID]
// TODO: change the time index(dynamic changing)
curYData = parseFloat(processedData[1])
// integral only when I-T & C-A, so writen as [0] directly
prevYData = parseFloat(data[j][1])
// initial integral as 0
if (i === 0) processedData[1] = 0
else {
if (dataX !== undefined) {
// e.g. I-V: deltaX is V
deltaX = parseFloat(dataX[j][1]) - lastXinThisTable
} else {
// e.g. I-T: deltaX is T
deltaX = parseFloat(data[j][0]) - lastXinThisTable
}
integralResult += parseFloat((Math.abs(curYData) + Math.abs(prevYData)) * Math.abs(deltaX) / 2)
processedData[1] = integralResult
}
} else {
curYData = parseFloat(data[j][1])
if (dataX !== undefined) {
// e.g. I-V: deltaX is V
deltaX = parseFloat(dataX[j][1]) - parseFloat(dataX[j - 1][1])
lastXinThisTable = parseFloat(dataX[j][1])
} else {
// e.g. I-T: deltaX is T
deltaX = parseFloat(data[j][0]) - parseFloat(data[j - 1][0])
lastXinThisTable = parseFloat(data[j][0])
}
integralResult += parseFloat((Math.abs(curYData) + Math.abs(prevYData)) * Math.abs(deltaX) / 2)
// assign here is due to the fetch the modify value
prevYData = curYData
processedData[1] = integralResult
}
} else if (this.yfunctional === 'Differential') {
if (j === 0) {
// TODO: need to change the series[deviceID]
// TODO: change the time index(dynamic changing)
curXData = parseFloat(processedData[0])
curYData = parseFloat(processedData[1])
deltaX = parseFloat(dataX[j + 1][0]) - parseFloat(dataX[j][0])
if (i === 0) logZero = true
// due to the limitation of the getData table, the number of page may > 1
else {
diffResult = parseFloat((curYData - prevYData) / (curXData - prevXData))
processedData[0] = curXData
processedData[1] = diffResult
}
prevXData = parseFloat(processedData[0])
prevYData = parseFloat(processedData[1])
} else {
curXData = parseFloat(processedData[0])
curYData = parseFloat(processedData[1])
diffResult = parseFloat((curYData - prevYData) / (curXData - prevXData))
prevXData = curXData
prevYData = curYData
processedData[0] = curXData
processedData[1] = diffResult
}
}
// avoid pushing the infinity data into the chart
if (!logZero) this.chartDetailData.series[_gridNumber].data.push(processedData)
}
}
}
@@ -478,6 +565,13 @@ export default {
}
}
},
changeFunctional (axis, functional) {
if (axis === 'x') {
this.xfunctional = functional
} else {
this.yfunctional = functional
}
},
changeAxis (gridIndex) {
if (this.initDone) {
const libName = this.metaList[gridIndex].device.library_name
@@ -486,9 +580,9 @@ export default {
if (this.axisXDataType.description === 'Time') {
xType = 'Time'
} else {
if (libName === 'EliteZM15') {
if (libName === 'EliteZM15' || libName.includes('Elite_EDC')) {
xType = 'Elite'
} else if (libName === 'EliteEIS') {
} else if (libName.includes('EIS')) {
xType = 'EliteEIS'
}
xValue = this.axisXDataType.id + 1
@@ -500,7 +594,7 @@ export default {
deviceNameX: xType,
deviceIDX: this.metaList[gridIndex].name,
channelX: xValue,
deviceNameY: libName === 'EliteEIS' ? 'EliteEIS' : 'Elite',
deviceNameY: libName.includes('EIS') ? 'EliteEIS' : 'Elite',
deviceIDY: '',
channelY: this.axisYDataType.id + 1,
})
@@ -15,7 +15,7 @@
<div class="flex-container mb-2">
<div class="flex sm2 xl2 md2 xs2 px-0 py-0">
<p class="display-6"> X-axis <p/>
<p class="display-6"> X-axis </p>
</div>
<div class="flex sm5 xl5 md5 xs5 pl-1 pr-0 py-0">
<change-axis :ref="'change_axis_x'" axis="x" @changeAxis="changeAxis" @changeUnit="changeUnit" @clearCycle="clearCycle"/>
@@ -27,7 +27,7 @@
<div class="flex-container mb-2">
<div class="flex sm2 xl2 md2 xs2 px-0 py-0" />
<div class="flex sm5 xl5 md5 xs5 pl-1 pr-0 py-0">
<change-scale :ref="'change_scale_x'" axis="x" @refreshChart="refreshChart" @clearCycle="clearCycle" @changeAxis="changeAxis"/>
<change-scale :ref="'change_scale_x'" axis="x" @refreshChart="refreshChart" @clearCycle="clearCycle" @changeAxis="changeAxis" @changeFunctional="changeFunctional"/>
</div>
<div class="flex sm5 xl5 md5 xs5 px-0 py-0">
<abs-toggle :ref="'abs_x'" axis="x" @changeAxis="changeAxis"/>
@@ -36,7 +36,7 @@
<div class="flex-container mb-2">
<div class="flex sm2 xl2 md2 xs2 px-0 py-0">
<p class="display-6"> Y-axis <p/>
<p class="display-6"> Y-axis </p>
</div>
<div class="flex sm5 xl5 md5 xs5 pl-1 pr-0 py-0">
<change-axis :ref="'change_axis_y'" axis="y" @changeAxis="changeAxis" @changeUnit="changeUnit" @clearCycle="clearCycle"/>
@@ -48,7 +48,7 @@
<div class="flex-container mb-2">
<div class="flex sm2 xl2 md2 xs2 px-0 py-0" />
<div class="flex sm5 xl5 md5 xs5 pl-1 pr-0 py-0">
<change-scale :ref="'change_scale_y'" axis="y" @refreshChart="refreshChart" @clearCycle="clearCycle" @changeAxis="changeAxis"/>
<change-scale :ref="'change_scale_y'" axis="y" @refreshChart="refreshChart" @clearCycle="clearCycle" @changeAxis="changeAxis" @changeFunctional="changeFunctional"/>
</div>
<div class="flex sm5 xl5 md5 xs5 px-0 py-0">
<abs-toggle :ref="'abs_y'" axis="y" @changeAxis="changeAxis"/>
@@ -122,10 +122,10 @@ export default {
methods: {
init () {
this.deviceName = this.metaList[0].device.library_name
this.$refs.change_axis_x.init(this.deviceName)
this.$refs.change_axis_y.init(this.deviceName)
this.$refs.change_unit_x.init(this.deviceName)
this.$refs.change_unit_y.init(this.deviceName)
this.$refs.change_axis_x.init(this.deviceName)
this.$refs.change_axis_y.init(this.deviceName)
this.$refs.change_scale_x.init(this.deviceName)
this.$refs.change_scale_y.init(this.deviceName)
this.$refs.abs_x.init(this.deviceName)
@@ -141,6 +141,9 @@ export default {
refreshChart (options) {
this.$emit('refreshChart', options)
},
changeFunctional (axis, functional) {
this.$emit('changeFunctional', axis, functional)
},
changeAxis (gridIndex) {
this.$emit('changeAxis', gridIndex)
},
@@ -151,6 +154,18 @@ export default {
this.$refs.change_unit_y.changeUnitByAxis()
}
},
getPanelInfo () {
var panelInfo = {
axis_x: this.$refs.change_axis_x.getChannelByAxis(),
axis_y: this.$refs.change_axis_y.getChannelByAxis(),
scale_x: this.$refs.change_scale_x.getScaleByAxis(),
scale_y: this.$refs.change_scale_y.getScaleByAxis(),
unit_x: this.$refs.change_unit_x.getUnitByAxis(),
unit_y: this.$refs.change_unit_y.getUnitByAxis(),
}
// console.log('panelInfo: ', panelInfo)
return panelInfo
},
clearCycle () {
this.$refs.change_cycle.clear()
},
@@ -70,7 +70,7 @@ export default {
},
performABS () {
this.absToggleStatus[this.axis] = !this.absToggleStatus[this.axis]
if (this.deviceName === 'EliteZM15' || this.deviceName === 'EliteEIS') {
if (this.deviceName === 'EliteZM15' || this.deviceName.includes('Elite_EDC') || this.deviceName.includes('EIS')) {
this.calculateHelper(this.metaIndex) // [TODO] elite tmp use metaIndex for grid index
}
this.clickTime++
@@ -93,7 +93,7 @@ export default {
data: seriesData,
})
} else {
if (this.deviceName === 'EliteZM15' || this.deviceName === 'EliteEIS') {
if (this.deviceName === 'EliteZM15' || this.deviceName.includes('Elite_EDC') || this.deviceName.includes('EIS')) {
this.$emit('changeAxis', this.metaIndex) // [TODO] elite tmp use metaIndex for grid index
}
}
@@ -0,0 +1,332 @@
<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 { 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 { getTimeFormatter } from '@/store/modules/task/content/actions/chartAct'
export default {
name: 'CanvasChartReplayCalculation',
components: {
},
props: {
chartID: {
type: [Number, String],
required: true,
},
},
computed: {
...mapFields('', [
'developer_mode',
]),
...mapFields('taskContent', [
'chartData',
'taskContentChartKey',
'deviceListNew',
]),
},
data () {
return {
info: null,
paramTable: paramTable,
rawData: null,
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))
_data.push([curXData, 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.$emit('switchModeButton', 'Integral')
} else if (this.xlogClicked || this.ylogClicked) {
this.$emit('switchModeButton', 'log')
} else if (this.diffClicked) {
this.$emit('switchModeButton', 'Differential')
} else {
this.$emit('switchModeButton', '')
}
// TODO: modify the redundant code
if (this.xName === 'TIME') {
this.data.xAxis[0].axisLabel.formatter = function (val) {
return getTimeFormatter(val)
}
}
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
},
// 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]
},
}
</script>
@@ -84,7 +84,7 @@ export default {
} else if (this.axis === 'y') {
this.axisYDataType = this.channelOptions[1]
}
} else if (this.deviceName === 'EliteZM15') {
} else if (this.deviceName === 'EliteZM15' || this.deviceName.includes('Elite_EDC')) {
// use state meta to decide which default unit need to be used (like check I-V mode...)
const setting = this.GLOBAL.getDefaultChartTypeByMode(this.metaList[this.metaIndex].parameter_set.MODE, this.deviceName)
const xType = setting[0]
@@ -130,7 +130,7 @@ export default {
}
this.channelFormat = this.axisYDataType
}
} else if (this.deviceName === 'EliteEIS') {
} else if (this.deviceName.includes('EIS')) {
const setting = this.GLOBAL.getDefaultChartTypeByMode(this.metaList[this.metaIndex].parameter_set.MODE, this.deviceName)
const xType = setting[0]
const xValue = setting[1]
@@ -141,7 +141,7 @@ export default {
if (this.axis === 'x') {
settingType = xType
settingValue = xValue
if (settingType === 'EliteEIS') {
if (settingType.includes('EIS')) {
this.axisXDataType = this.eisChannelOptions.find(element => element.id === parseInt(settingValue) - 1)
} else if (settingType === 'Elite') {
// 1: I, 2: V, 3: R
@@ -159,7 +159,7 @@ export default {
} else if (this.axis === 'y') {
settingType = yType
settingValue = yValue
if (settingType === 'EliteEIS') {
if (settingType.includes('EIS')) {
this.axisYDataType = this.eisChannelOptions.find(element => element.id === parseInt(settingValue) - 1)
} else if (settingType === 'Elite') {
// 1: I, 2: V, 3: R
@@ -184,7 +184,7 @@ export default {
if (this.deviceName.startsWith('Neulive')) {
// for elite now, cuz neulive now only have v-t graph, for future neulive replay need to adjust'
// console.log('(Last updated: 2021/06/19)')
} else if (this.deviceName === 'EliteZM15' || this.deviceName === 'EliteEIS') {
} else if (this.deviceName === 'EliteZM15' || this.deviceName.includes('Elite_EDC') || this.deviceName.includes('EIS')) {
if (this.axis === 'x') {
this.axisXDataType = this.channelFormat
} else if (this.axis === 'y') {
@@ -200,6 +200,9 @@ export default {
this.$emit('clearCycle')
}
},
getChannelByAxis () {
return this.channelFormat.description
},
},
mounted () {
},
@@ -1,3 +1,4 @@
<!-- eslint-disable prefer-const -->
<template>
<div>
<va-select
@@ -87,31 +88,116 @@ export default {
this.calculateScaleHelper(gridIndex, ch)
}
}
} else if (this.deviceName === 'EliteZM15' || this.deviceName === 'EliteEIS') {
} else if (this.deviceName === 'EliteZM15' || this.deviceName.includes('Elite_EDC') || this.deviceName.includes('EIS')) {
this.calculateScaleHelper(this.metaIndex, -1) // [TODO] elite tmp use metaIndex for grid index
}
},
async calculateScaleHelper (gridIndex, ch) {
let seriesData
if (this.scaleFormat.description === 'Log') {
seriesData = JSON.parse(JSON.stringify(this.chartData[this.chartID].series[gridIndex].data))
for (let i = 0; i < seriesData.length; i++) {
if (this.axis === 'x') {
seriesData[i][0] = Math.abs(seriesData[i][0])
} else if (this.axis === 'y') {
seriesData[i][1] = Math.abs(seriesData[i][1])
// console.log('desc', this.scaleFormat.description)
/* var _dataDiff = []
var _dataIntegral = []
var _dataLog = []
// this.$emit('changeAxis', this.metaIndex)
// this.$emit('clearCycle')
if (this.scaleFormat.description === 'Differential') {
// await this.reDrawChart()
// eslint-disable-next-line prefer-const
let seriesData = JSON.parse(JSON.stringify(this.chartData[this.chartID].series[gridIndex].data))
// console.log('diff')
var curXData = 0
var curYData = 0
var prevXData = 0
var prevYData = 0
var timeGap = 0
var curTime = 0
_dataDiff = []
var diffResult = 0
for (let index = 0; index < seriesData.length; 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]
// _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))
_dataDiff.push([curXData, diffResult])
}
}
this.updateSeriesChart({
chartID: this.chartID,
seriesIndex: gridIndex,
data: seriesData,
data: _dataDiff,
})
} else if (this.scaleFormat.description === 'Integral') {
// await this.reDrawChart()
// eslint-disable-next-line prefer-const
let seriesData = JSON.parse(JSON.stringify(this.chartData[this.chartID].series[gridIndex].data))
var curYDataIntegral = 0
var prevYDataIntegral = 0
var timeGapIntegral = 0
var curTimeIntegral = 0
var integralResult = 0
_dataIntegral = []
for (let index = 0; index < seriesData.length; index++) {
if (index === 0) {
curYDataIntegral = parseFloat(seriesData[index][1])
timeGapIntegral = seriesData[index + 1][0] - seriesData[index][0]
curTimeIntegral = seriesData[index][0]
_dataIntegral.push([curTime, 0])
} else {
prevYDataIntegral = parseFloat(seriesData[index - 1][1])
curYDataIntegral = parseFloat(seriesData[index][1])
integralResult += parseFloat((Math.abs(curYDataIntegral) + Math.abs(prevYDataIntegral)) * timeGapIntegral / 2)
curTimeIntegral += timeGapIntegral
_dataIntegral.push([curTimeIntegral, integralResult])
}
}
this.updateSeriesChart({
chartID: this.chartID,
seriesIndex: gridIndex,
data: _dataIntegral,
})
} else if (this.scaleFormat.description === 'Log') {
await this.reDrawChart()
setTimeout(() => {
// eslint-disable-next-line prefer-const
let seriesData = JSON.parse(JSON.stringify(this.chartData[this.chartID].series[gridIndex].data))
_dataLog = seriesData
for (let i = 0; i < seriesData.length; i++) {
if (this.axis === 'x') {
seriesData[i][0] = parseFloat(seriesData[i][0])
if (seriesData[i][0] !== 0) {
// seriesData[i][0] = Math.log10(Math.abs(seriesData[i][0]))
_dataLog[i][0] = Math.log10(Math.abs(seriesData[i][0]))
}
} else if (this.axis === 'y') {
seriesData[i][1] = parseFloat(seriesData[i][1])
if (seriesData[i][1] !== 0) {
// seriesData[i][1] = Math.log10(Math.abs(seriesData[i][1]))
_dataLog[i][1] = Math.log10(Math.abs(seriesData[i][1]))
}
}
}
this.updateSeriesChart({
chartID: this.chartID,
seriesIndex: gridIndex,
data: _dataLog,
})
console.log('done')
}, 2000)
// eslint-disable-next-line prefer-const
} else if (this.scaleFormat.description === 'Linear') {
// console.log(this.recInfo)
if (this.deviceName.startsWith('Neulive')) {
console.log('inside neulive')
// [Region] get the subfile index
seriesData = []
// eslint-disable-next-line prefer-const
let seriesData = []
const dataYList = this.recInfo[this.metaID][ch][this.currentScale]
let startIndex = 0
let endIndex = 0
@@ -140,12 +226,23 @@ export default {
}
}
} else if (this.deviceName === 'EliteZM15' || this.deviceName === 'EliteEIS') {
this.$emit('changeAxis', this.metaIndex)
this.$emit('clearCycle')
console.log('inside Elite')
// this.$emit('changeAxis', this.metaIndex)
// this.$emit('clearCycle')
this.reDrawChart()
}
}
} */
// console.log('inside changeScale: ', this.scaleFormat.description)
this.reDrawChart()
this.setAxisDisplayChart({ type: this.displayType[this.axis], axis: this.axis, chartID: this.chartID, gridIndex: gridIndex })
},
reDrawChart: function () {
// console.log('die here')
this.$emit('changeFunctional', this.axis, this.scaleFormat.description)
// console.log('reDrawChart: ', this.axis, this.scaleFormat.description)
this.$emit('changeAxis', this.metaIndex)
this.$emit('clearCycle')
},
getData: async function (scale, sampleMethod, id, channel, meta) {
if (scale === 1) {
return await download.rawByIDChannels(id, channel, meta)
@@ -157,11 +254,19 @@ export default {
}
}
},
getScaleByAxis () {
return this.scaleFormat.description
},
...mapActions('replay', [types.chart.setAxisDisplay]),
...mapMutations('replay', [types.chart.updateSeries]),
...mapGetters('replay', [types.rec.getCycleDict]),
},
mounted () {
if (this.axis === 'x') {
this.scaleOptions = this.scaleXOptions
} else if (this.axis === 'y') {
this.scaleOptions = this.scaleYOptions
}
},
data () {
return {
@@ -169,7 +274,8 @@ export default {
metaID: 0,
metaInfo: null,
scaleFormat: { id: 0, description: 'Linear' },
scaleOptions: [
scaleOptions: [],
scaleXOptions: [
{
id: 0,
description: 'Linear',
@@ -179,6 +285,24 @@ export default {
description: 'Log',
},
],
scaleYOptions: [
{
id: 0,
description: 'Linear',
},
{
id: 1,
description: 'Log',
},
{
id: 2,
description: 'Integral',
},
{
id: 3,
description: 'Differential',
},
],
}
},
destroyed () {
@@ -65,9 +65,9 @@ export default {
return item.unit === 'uV'
})
}
} else if (this.deviceName === 'EliteZM15') {
} else if (this.deviceName === 'EliteZM15' || this.deviceName.includes('Elite_EDC')) {
return this.valueFormatOptions[this.dataType][0]
} else if (this.deviceName === 'EliteEIS') {
} else if (this.deviceName.includes('EIS')) {
return this.eisValueFormatOptions[this.dataType][0]
}
},
@@ -80,7 +80,7 @@ export default {
} else if (this.axis === 'y') {
this.dataType = 'voltage'
}
} else if (this.deviceName === 'EliteZM15') {
} else if (this.deviceName === 'EliteZM15' || this.deviceName.includes('Elite_EDC')) {
// use state meta to decide which default unit need to be used (like check I-V mode...)
const setting = this.GLOBAL.getDefaultChartTypeByMode(this.metaList[this.metaIndex].parameter_set.MODE, this.deviceName)
const xType = setting[0]
@@ -111,7 +111,7 @@ export default {
} else if (settingType === 'Time') {
this.dataType = 'time'
}
} else if (this.deviceName === 'EliteEIS') {
} else if (this.deviceName.includes('EIS')) {
const setting = this.GLOBAL.getDefaultChartTypeByMode(this.metaList[this.metaIndex].parameter_set.MODE, this.deviceName)
const xType = setting[0]
const xValue = setting[1]
@@ -127,7 +127,7 @@ export default {
settingValue = yValue
}
if (settingType === 'EliteEIS') {
if (settingType.includes('EIS')) {
if (settingValue === 3) {
this.dataType = 'frequency'
} else if (settingValue === 5 || settingValue === 6 || settingValue === 7) {
@@ -179,7 +179,7 @@ export default {
channel: parseInt(key),
})
}
} else if (this.deviceName === 'EliteZM15' || this.deviceName === 'EliteEIS') {
} else if (this.deviceName === 'EliteZM15' || this.deviceName.includes('Elite_EDC') || this.deviceName.includes('EIS')) {
this.updateAxisLabelChart({
chartID: chartID,
axis: this.axis,
@@ -229,13 +229,20 @@ export default {
this.dataType = 'default'
}
}
if (this.deviceName === 'EliteZM15') {
if (this.deviceName === 'EliteZM15' || this.deviceName.includes('Elite_EDC')) {
this.valueFormat = this.valueFormatOptions[this.dataType][0]
} else if (this.deviceName === 'EliteEIS') {
} else if (this.deviceName.includes('EIS')) {
this.valueFormat = this.eisValueFormatOptions[this.dataType][0]
}
this.changeUnit()
},
getUnitByAxis () {
// console.log('valueFormat: ', this.valueFormat.unit)
if (this.valueFormat.unit === undefined) {
return 'auto'
}
return this.valueFormat.unit
},
// call vuex to mutate chart label formatter by unit and axis
...mapMutations('replay', [types.chart.updateAxisLabel]),
},
@@ -8,7 +8,7 @@
<script>
import { mapFields } from 'vuex-map-fields'
import paramTable from '@/data/param-table/index.js'
import paramTable from '@/data/config-table/index.js'
export default {
name: 'show-parameter',
@@ -378,19 +378,21 @@ export default {
this.content += ' Frequency: ' + String(1000 / period) + ' Hz' + '<br/>' // 1000 is cuz 1s = 1000ms
this.content += ' Period: ' + String(period) + ' ms' + '<br/>'
}
} else if (this.deviceName === 'EliteZM15' || this.deviceName === 'EliteEIS') {
} else if (this.deviceName === 'EliteZM15' || this.deviceName.includes('Elite_EDC') || this.deviceName.includes('EIS')) {
const mode = this.mode = params.MODE
const modeName = paramTable[this.deviceName].MODE[mode].name
const showParams = paramTable[this.deviceName].MODE[mode].showParameter
const config = paramTable.getConfig(this.deviceName)
const modeConfig = paramTable.getModeConfig(this.deviceName, mode)
const modeName = modeConfig.name
const showParams = modeConfig.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 = paramTable[this.deviceName][key].outputReadabilityData(params[key], 1, i)
const order = config[key].outputReadabilityData(params[key], 1, i)
if (parseInt(order) >= 0) { // if === -1, 代表沒有使用這個block
for (const key of duplicateParam) {
this.fillShowDict(key, paramTable[this.deviceName][key].outputReadabilityData(params[key], 1, i), i)
this.fillShowDict(key, config[key].outputReadabilityData(params[key], 1, i), i)
}
}
}
@@ -409,16 +411,17 @@ export default {
this.dump()
},
fillShowDict (key, value, index = -1) {
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
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
if (index >= 0) {
name += ` ${index + 1}`
}
const unit = paramTable[this.deviceName][key].defaultUnit
const unit = config[key].defaultUnit
this.showDict[name] = unit !== undefined ? expVal.toString() + unit : expVal.toString()
},
dump () {
+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 paramTable from '@/data/param-table/index'
import configTable from '@/data/config-table/index'
export default {
name: 'Download',
@@ -108,7 +108,7 @@ export default {
}
if (meta !== undefined) {
this.metaInfo = meta
const channelParamObj = paramTable[meta.device.library_name].MODE[meta.parameter_set.MODE].channels
const channelParamObj = configTable.getModeConfig(meta.device.library_name, 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 paramTable from '@/data/param-table/index'
import configTable from '@/data/config-table/index'
export default {
name: 'DownloadOffline',
@@ -113,7 +113,7 @@ export default {
}
if (meta !== undefined) {
this.metaInfo = meta
const channelParamObj = paramTable[meta.device.library_name].MODE[meta.parameter_set.MODE].channels
const channelParamObj = configTable.getModeConfig(meta.device.library_name, meta.parameter_set.MODE).channels
const channelArray = allChannel === 'all' ? JSON.parse(this.metaInfo.channels) : Object.keys(channelParamObj).filter(ele => ele !== 'time')
const channelList = []
@@ -6,29 +6,51 @@
</div>
</div>
<div>
<elite-parameter-window></elite-parameter-window>
<device-parameter-recording
:ref="'device_parameter_ref'"
:parameter="parameter"
:library="'EliteEDC1.5'"
@setParameter="setParameter"
@setParameterWithDebounce="setParameterWithDebounce"
/>
</div>
</div>
</template>
<script>
import { mapFields } from 'vuex-map-fields'
import newCondition from '@/factories/project/conditionFactory'
import EliteParameterWindow from '@/components/project/task/config/parameter/EliteParameterWindow'
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'
export default {
name: 'project-task-config-parameter',
components: {
EliteParameterWindow,
DeviceParameterRecording,
},
computed: {
...mapGetters('project', [
types.task.getSelect,
types.task.getParameterSet,
types.project.getDevice,
types.project.getSelect,
]),
...mapFields('project', [
'taskSelect',
'taskViewPanel',
'taskSelectKey',
'deviceSelectKey',
]),
},
data () {
return {
parameter: {},
conditionList: newCondition(),
deviceSelected: null,
parameterUUID: '',
device: null,
config: null,
}
},
methods: {
@@ -38,8 +60,54 @@ 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,6 +84,7 @@ export default {
...mapFields('project', [
'deviceConnectList',
'projectLibrary',
]),
},
data () {
@@ -157,6 +158,9 @@ 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()
@@ -173,6 +177,7 @@ export default {
this.optionDeviceConnect = this.deviceConnectList
if (device) {
this.device = device
this.projectLibrary = this.device.library.value
}
},
@@ -12,6 +12,7 @@
</template>
<script>
import { mapFields } from 'vuex-map-fields'
import { mapActions, mapGetters } from 'vuex'
import types from '@/store/modules/project/types'
@@ -23,6 +24,10 @@ export default {
...mapGetters('project', [
types.project.getSelect,
]),
...mapFields('project', [
'projectLibrary',
]),
},
data () {
return {
@@ -42,6 +47,11 @@ 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'">{{ parameterTable[parameterKey].alias }}: {{ parameterTable[parameterKey].transFormula(parameter) }} {{ parameterTable[parameterKey].unit[0] }}</span>
<span v-if="parameterKey !== 'target'"> {{ parameterName(parameterKey) }} : {{ parameterValue(parameterKey, parameter) }} </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,6 +131,10 @@ export default {
FulfillingBouncingCircleSpinner,
},
computed: {
config () {
return configTable.getConfig(this.projectLibrary)
},
...mapGetters('project', [
types.project.getSelect,
types.project.getDevice,
@@ -144,6 +148,7 @@ export default {
'taskSelectKey',
'deviceSelectKey',
'lockMode',
'projectLibrary',
]),
},
data () {
@@ -152,7 +157,6 @@ export default {
name: -1,
checked: [],
},
parameterTable: newEliteZm15Parameter(),
}
},
methods: {
@@ -186,6 +190,28 @@ 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,
]),
+52 -20
View File
@@ -108,6 +108,7 @@ 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
@@ -158,7 +159,7 @@ export default {
if (this.$refs.devices_ref != null) {
await this.$refs.devices_ref.loadingDone()
}
await this.taskContentChartInitCustomizedFromCache()
await this.taskContentChartInitCustomizedFromCache({ controllerID: taskInfo.getTaskInfo().controllerID })
this.getParmDone = true
},
async '+/get_device_info/+' (data, topic) {
@@ -199,7 +200,7 @@ export default {
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()
await this.taskContentChartInitCustomizedFromCache({ controllerID: taskInfo.getTaskInfo().controllerID })
}
},
// listen datastream [ topic: controllerID/data_server/device_data_stream/deviceID/channel ]
@@ -207,7 +208,6 @@ 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,12 +261,22 @@ 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
@@ -347,12 +357,20 @@ export default {
)
},
refreshData: function () {
// TODO don't need to refresh chart with stop status
for (const chart in this.chartData) {
this.taskContentChartRefreshData({
chartID: parseInt(chart),
deviceList: this.deviceListNew,
})
// 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,
})
}
}
},
refreshDevicesWindow: function () {
@@ -362,25 +380,35 @@ export default {
}
},
addChart: async function (isDefault) {
this.taskContentChartAdd({
chartID: this.taskContentChartNumber,
maxDots: 4000,
// create chartID with uuid instead of length of chart list
const newChart = await this.taskContentChartAdd({
chartID: uuid(),
maxDots: 5000,
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()
this.taskContentChartNumber++
// save chart config to web storage
if (!isDefault) {
await this.taskContentChartSaveToCache()
await this.taskContentChartSaveToCache({ controllerID: taskInfo.getTaskInfo().controllerID })
}
this.pageToast('The chart has been added.')
return this.taskContentChartNumber - 1
return newChart.chartID
},
refreshChartSetting: async function () {
if (this.$refs.chart_ref != null) {
@@ -402,7 +430,7 @@ export default {
this.selectChartID = chartID
this.showRemoveChartModal = true
},
removeChart: async function (chartID) {
removeChart: async function (chartID, saveCache = true) {
if (chartID == null) {
chartID = this.selectChartID
}
@@ -429,8 +457,9 @@ export default {
})
}
}
await this.taskContentChartSaveToCache()
if (saveCache === true) {
await this.taskContentChartSaveToCache({ controllerID: taskInfo.getTaskInfo().controllerID })
}
this.pageToast('The chart has been removed.')
},
showDeviceSettingClick: function () {
@@ -462,9 +491,11 @@ 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,
@@ -567,6 +598,7 @@ export default {
taskTypes.chart.add,
taskTypes.chart.defaultChartGenerator,
taskTypes.chart.reset,
taskTypes.chart.resetSeriesData,
taskTypes.chart.refreshData,
taskTypes.chart.refreshChart,
taskTypes.chart.refreshPanel,
@@ -589,7 +621,7 @@ export default {
destroyed () {
taskInfo.destroyed(this.deviceList)
for (const chart in this.chartData) {
this.removeChart(chart)
this.removeChart(chart, false)
}
clearInterval(this.dataRefreshTimer)
this.pageMqttUnSub(taskInfo.getTaskInfo().controllerID)
@@ -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,26 +14,56 @@
/>
</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" @switchModeButton="switchModeButton"/>
</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">
<chart :key="taskContentChartKey" :ref="'chart_ref'" :style="'width: '+ cardwidth + '; height: ' + cardheight + ';'" :options="data" :auto-resize="true"></chart>
<canvas-chart-real-time-display
:chartID="chartID" ref="CanvasChartRealTimeDisplay"
/>
<!-- chart -->
<chart :key="taskContentChartKey" :ref="'chart_ref'" :style="'width: '+ cardwidth + '; height: ' + cardheight + ';'" :options="data" @dataZoom="updateZoom" :auto-resize="true" @></chart>
</div>
</div>
<div v-else-if="tabValue == 1" :style="'width: '+ cardwidth + '; height: ' + cardheight + ';'" >
<canvas-chart-source :chartID="chartID" />
<canvas-chart-source :chartID="chartID" @addSource="addSource()" />
</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">
@@ -108,8 +138,13 @@ 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',
@@ -118,10 +153,12 @@ export default {
CanvasChartSource,
CanvasChartFilter,
CanvasChartFilterPopup,
CanvasChartRealTimeDisplay,
CanvasChartRealTimeCalculation,
},
props: {
chartID: {
type: Number,
type: [Number, String],
required: true,
},
cardclass: {
@@ -146,6 +183,7 @@ export default {
...mapFields('taskContent', [
'chartData',
'taskContentChartKey',
'deviceListNew',
]),
},
data () {
@@ -161,9 +199,16 @@ export default {
threeAxisIntervalInput: 'auto',
xIntervalInput: 'auto',
yIntervalInput: 'auto',
dataZoomStart: 0,
dataZoomEnd: 100,
}
},
methods: {
updateZoom: function (e) {
// console.log(e.batch)
this.dataZoomStart = e.batch[0].start
this.dataZoomEnd = e.batch[0].end
},
timeIntervalChange: function (val) {
if (!isNaN(parseInt(val))) {
this.chartData[this.chartID].xAxis.forEach(x => {
@@ -195,7 +240,7 @@ export default {
}
})
}
await this.taskContentChartSaveToCache()
await this.taskContentChartSaveToCache({ controllerID: taskInfo.getTaskInfo().controllerID })
},
yIntervalChange: async function (val) {
if (!isNaN(parseInt(val))) {
@@ -203,12 +248,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])))
@@ -232,7 +277,7 @@ export default {
}
})
}
await this.taskContentChartSaveToCache()
await this.taskContentChartSaveToCache({ controllerID: taskInfo.getTaskInfo().controllerID })
},
threeAxisIntervalChange: function (val) {
if (!isNaN(parseInt(val))) {
@@ -275,7 +320,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)
@@ -322,13 +367,24 @@ export default {
type: 'legendInverseSelect',
})
},
refreshData: function (rawData) {
this.data = rawData
// save the start & end of previous dataZoom setting to avoid reset dataZoom
this.data.dataZoom[0].start = this.dataZoomStart
this.data.dataZoom[0].end = this.dataZoomEnd
this.$refs.CanvasChartRealTimeDisplay.matchData(this.data)
},
switchModeButton: function (dataMode, gridIndex, channelIndex) {
// console.log('switchModeBtn')
this.$refs.CanvasChartRealTimeDisplay.matchFunctional(String(dataMode), gridIndex, channelIndex)
},
...mapActions('taskContent', [
taskTypes.chart.saveToCache,
]),
},
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,
type: [Number, String],
required: true,
},
filterIndex: {
@@ -29,7 +29,7 @@ export default {
},
props: {
chartID: {
type: Number,
type: [Number, String],
required: true,
},
chartRef: {
@@ -66,7 +66,7 @@ export default {
name: 'canvas-chart-filter-individual-filter',
props: {
chartID: {
type: Number,
type: [Number, String],
required: true,
},
seriesIndex: {
@@ -0,0 +1,361 @@
<template>
<div>
<va-button v-if="integralClicked && (mode_name==='Chronoamperometric' || mode_name==='I-T Graph' || mode_name==='I-V Curve')" color="danger" class="mb-2" @click="clickIntegral" small>
To Raw Mode
</va-button>
<va-button :disabled="disableInt" v-if="!integralClicked && (mode_name==='Chronoamperometric' || mode_name==='I-T Graph' || mode_name==='I-V Curve')" 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: {
},
props: {
chartID: {
type: [Number, String],
required: true,
},
},
computed: {
...mapFields('', [
'developer_mode',
]),
...mapFields('taskContent', [
'chartData',
'taskContentChartKey',
'deviceListNew',
]),
},
data () {
return {
info: null,
paramTable: paramTable,
rawData: null,
mode_name: '',
xName: '',
yName: '',
obj: null,
integralClicked: false,
xlogClicked: false,
ylogClicked: false,
diffClicked: false,
disableDiff: false,
disableLog: false,
disableInt: 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 deltaX = 0
var deltaTime = 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++) {
// console.log('x: ', seriesData[index][0])
// console.log('y: ', seriesData[index][1])
if (index === 0) {
// TODO: need to change the series[deviceID]
// TODO: change the time index(dynamic changing)
curYData = parseFloat(seriesData[index][1])
// deltaX = seriesData[index + 1][timeIndex] - seriesData[index][timeIndex]
curXData = parseFloat(seriesData[index][0])
curTime = seriesData[index][timeIndex]
if (this.mode_name === 'I-T Graph') {
_data.push([curTime, 0])
} else {
_data.push([curXData, 0, 0])
}
} else {
prevYData = parseFloat(seriesData[index - 1][1])
curYData = parseFloat(seriesData[index][1])
curXData = parseFloat(seriesData[index][0])
deltaX = seriesData[index][0] - seriesData[index - 1][0]
deltaTime = seriesData[index][timeIndex] - seriesData[index - 1][timeIndex]
integralResult += parseFloat((Math.abs(curYData) + Math.abs(prevYData)) * Math.abs(deltaX) / 2)
curTime += deltaTime
if (this.mode_name === 'I-T Graph') {
_data.push([curTime, integralResult])
} else {
_data.push([curXData, integralResult, curTime])
}
}
}
} 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])
deltaX = 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 += deltaX
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])
deltaX = 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 += deltaX
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])
deltaX = 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 += deltaX
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])
deltaX = 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 += deltaX
diffResult = parseFloat((curYData - prevYData) / (curXData - prevXData))
_data.push([curXData, diffResult, curTime])
}
}
}
// console.log(this.data.dataZoom[1])
// decide feed in raw data / modified one
if (this.integralClicked || this.xlogClicked || this.ylogClicked || this.diffClicked) {
this.data.series[0].data = _data
// console.log(this.data.series[0].data[this.data.series[0].data.length - 1])
}
this.data.xAxis[0].type = 'value'
if (this.integralClicked) {
this.$emit('switchModeButton', 'integral', 0, 0)
} else if (this.diffClicked) {
this.$emit('switchModeButton', 'differential', 0, 0)
} else {
this.$emit('switchModeButton', 'default', 0, 0)
}
// TODO: modify the redundant code
if (this.xName === 'TIME') {
this.data.xAxis[0].axisLabel.formatter = function (val) {
return getTimeFormatter(val)
}
}
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)
this.disableDiff = !(this.disableDiff)
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()
}
}
},
clickXLog: function () {
if (this.xlogClicked) {
this.xlogClicked = false
if (this.ylogClicked) {
this.disableDiff = true
this.disableInt = true
} else {
this.disableDiff = false
this.disableInt = false
}
} else {
this.xlogClicked = true
this.disableDiff = true
this.disableInt = 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
this.disableInt = true
} else {
this.disableDiff = false
this.disableInt = false
}
} else {
this.ylogClicked = true
this.disableDiff = true
this.disableInt = 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)
this.disableInt = !(this.disableInt)
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
},
// 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]
},
}
</script>
@@ -0,0 +1,261 @@
<template>
<div>
<!-- cycle display -->
<div v-if="data !== null && data.cycle > 0" class="row flex sm12 xl12 md12 xs12 align--center my-0 py-0">
<div style="text-align: right;">
<h1 style="color: #707ee7;"> cycle <span style="color: white; background-color: #707ee7; border-radius: 40%;" class="pa-2">{{ data.cycle }}</span></h1>
</div>
</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 { chartRouter } from './CanvasChartTable'
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,
chartRouter: chartRouter,
realTime: [[]],
}
},
methods: {
// for user to choose wanted unit
setUnit: function (gridIndex, channelIndex) {
// construct realTime object, i.e., record the coressponding value and unit
// the formate imitates the data.gridSource
if (this.data !== undefined && this.data.gridSource !== undefined) {
const _xPhysicsQuantity = this.data.gridSource[gridIndex][channelIndex].name.split('_')[0].at(-1)
const _yPhysicsQuantity = this.data.gridSource[gridIndex][channelIndex].name.split('_')[1].at(-1)
const [_xAxis, _yAxis] = this.chartRouter.getChartTable(_xPhysicsQuantity, _yPhysicsQuantity)
const _realTime = JSON.parse(JSON.stringify(this.realTime))
const _newChannel = {}
// set name, sourceIndex in data.series
_newChannel.name = this.data.gridSource[gridIndex][channelIndex].name
_newChannel.seriesSource = this.data.series.findIndex((ele) => ele.name === _newChannel.name)
// set x-axis
_newChannel.xValue = 0
_newChannel.xUnit = _xAxis.default.defaultUnit
_newChannel.xScale = _xAxis.default.unit
_newChannel.xUnitOption = Object.keys(_xAxis.default.unit)
_newChannel.xName = _xAxis.default.name
// set y-axis
_newChannel.yValue = 0
_newChannel.yUnit = _yAxis.default.defaultUnit
_newChannel.yScale = _yAxis.default.unit
_newChannel.yUnitOption = Object.keys(_yAxis.default.unit)
_newChannel.yName = _yAxis.default.name
// set functional
_newChannel.functional = 'default'
// 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
}
},
// 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].xScale[this.realTime[gridIndex][channelIndex].xUnit]).toFixed(3)
this.realTime[gridIndex][channelIndex].yValue = (this.data.series[this.realTime[gridIndex][channelIndex].seriesSource].data.at(-1)[1] / this.realTime[gridIndex][channelIndex].yScale[this.realTime[gridIndex][channelIndex].yUnit]).toFixed(3)
}
}
}
},
// match the number of real time display bar to data.gridSource
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)
}
}
}
}
},
// match the formatter to current unit and functional
matchFormatter: 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].xScale[this.realTime[gridIndex][channelIndex].xUnit]
const _yScale = this.realTime[gridIndex][channelIndex].yScale[this.realTime[gridIndex][channelIndex].yUnit]
// update xAxis.formatter
if (this.realTime[gridIndex][channelIndex].xName === 'Time') {
this.data.xAxis[gridIndex].axisLabel.formatter = this.timeFormatter
} else {
this.data.xAxis[gridIndex].axisLabel.formatter = function (val) {
return parseFloat(val / _xScale).toFixed(2) + _xUnit
}
}
// update yAxis.formatter
if (this.realTime[gridIndex][channelIndex].yName === 'Time') {
this.data.yAxis[gridIndex].axisLabel.formatter = this.timeFormatter
} else {
this.data.yAxis[gridIndex].axisLabel.formatter = function (val) {
return parseFloat(val / _yScale).toFixed(2) + _yUnit
}
}
// update tooltip.formatter
this.data.tooltip.formatter = newTooltip(this.realTime).formatter
}
}
}
},
// match the data to operated data in CanvasChart.vue
matchData: function (canvasChartData) {
this.data = canvasChartData
},
// match the functional to operated data in CanvasChart.vue
matchFunctional: function (newFunctional, gridIndex, channelIndex) {
if (this.realTime[gridIndex][channelIndex] === undefined) return
if (this.realTime[gridIndex][channelIndex].functional === newFunctional) return
const _currChannel = this.realTime[gridIndex][channelIndex]
const _xPhysicsQuantity = this.data.gridSource[gridIndex][channelIndex].name.split('_')[0].at(-1)
const _yPhysicsQuantity = this.data.gridSource[gridIndex][channelIndex].name.split('_')[1].at(-1)
const [_xAxis, _yAxis] = this.chartRouter.getChartTable(_xPhysicsQuantity, _yPhysicsQuantity)
_currChannel.functional = newFunctional
// set x-axis
_currChannel.xUnit = _xAxis.default.defaultUnit
_currChannel.xScale = _xAxis.default.unit
_currChannel.xUnitOption = Object.keys(_xAxis.default.unit)
_currChannel.xName = _xAxis.default.name
// set y-axis
_currChannel.yUnit = _yAxis[newFunctional].defaultUnit
_currChannel.yScale = _yAxis[newFunctional].unit
_currChannel.yUnitOption = Object.keys(_yAxis[newFunctional].unit)
_currChannel.yName = _yAxis[newFunctional].name
},
timeFormatter: function (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
},
},
mounted () {
this.data = this.chartData[this.chartID]
},
watch: {
data: {
handler: function () {
this.updateValue()
this.matchChart()
},
deep: true,
},
realTime: {
handler: function () {
this.matchFormatter()
},
deep: true,
},
},
}
</script>
@@ -30,7 +30,7 @@ export default {
name: 'canvas-chart-setting',
props: {
chartID: {
type: Number,
type: [Number, String],
required: true,
},
},
@@ -95,7 +95,7 @@ export default {
name: 'canvas-chart-source',
props: {
chartID: {
type: Number,
type: [Number, String],
required: true,
},
},
@@ -183,7 +183,7 @@ export default {
this.channelSelectDisableX = false
} else if (deviceInfo.library_name.includes('Elite')) {
let channelSet
if (deviceInfo.library_name === 'EliteEIS' && deviceInfo.configuration.MODE === 0) {
if (deviceInfo.library_name.includes('EIS') && deviceInfo.configuration.MODE === 0) {
channelSet = ['Zimag_Raw', 'Zreal_Raw', 'Frequency', 'Cycle', 'Zimag', 'Zreal', 'Impedance', 'Phase', 'Current', 'Level gain']
} else {
channelSet = deviceInfo.configuration.CHANNEL_LABEL
@@ -251,7 +251,7 @@ export default {
this.channelSelectDisableY = false
} else if (deviceInfo.library_name.indexOf('Elite') >= 0) {
let channelSet
if (deviceInfo.library_name === 'EliteEIS' && deviceInfo.configuration.MODE === 0) {
if (deviceInfo.library_name.includes('EIS') && deviceInfo.configuration.MODE === 0) {
channelSet = ['Zimag_Raw', 'Zreal_Raw', 'Frequency', 'Cycle', 'Zimag', 'Zreal', 'Impedance', 'Phase', 'Current', 'Level gain']
} else {
channelSet = deviceInfo.configuration.CHANNEL_LABEL
@@ -310,7 +310,7 @@ export default {
if (this.deviceSelectX.name.indexOf('Neulive') >= 0) {
deviceNameX = 'Neulive'
} else if (this.deviceSelectX.name.indexOf('Elite') >= 0) {
if (deviceXInfo.library_name === 'EliteEIS') {
if (deviceXInfo.library_name.includes('EIS')) {
deviceNameX = 'EliteEIS'
} else {
deviceNameX = 'Elite'
@@ -321,7 +321,7 @@ export default {
if (this.deviceSelectY.name.indexOf('Neulive') >= 0) {
deviceNameY = 'Neulive'
} else if (this.deviceSelectY.name.indexOf('Elite') >= 0) {
if (deviceYInfo.library_name === 'EliteEIS') {
if (deviceYInfo.library_name.includes('EIS')) {
deviceNameY = 'EliteEIS'
} else {
deviceNameY = 'Elite'
@@ -350,7 +350,8 @@ export default {
}
this.sourceAddStatus = true
this.clearSelectOptions()
await this.taskContentChartSaveToCache()
await this.taskContentChartSaveToCache({ controllerID: taskInfo.getTaskInfo().controllerID })
this.$emit('addSource')
},
async addGrid () {
this.taskContentChartUpdateGridList({
@@ -358,7 +359,7 @@ export default {
length: this.chartData[this.chartID].grid.length + 1,
})
this.updateGridOptions()
await this.taskContentChartSaveToCache()
await this.taskContentChartSaveToCache({ controllerID: taskInfo.getTaskInfo().controllerID })
},
checkSourceAddStatus () {
if (this.sourceList.indexOf([this.deviceSelectX.name, this.deviceSelectX.id, this.channelSelectX.id].toString()) >= 0) {
@@ -0,0 +1,191 @@
const chartTable = {
// 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: 'Ω',
},
// Power = ∫ V di
integral: {
name: 'Power',
unit: {
mW: 1e12,
W: 1e15,
kW: 1e18,
},
defaultUnit: 'W',
downloadUnit: 'W',
},
},
// 1
{
default: {
name: 'Current',
unit: {
nA: 1,
uA: 1e3,
mA: 1e6,
A: 1e9,
},
defaultUnit: 'mA',
downloadUnit: 'mA',
},
// Gm = dI/dV
differential: {
name: 'Transconductance',
unit: {
'mA/V': 1,
'A/V': 1e3,
'kA/V': 1e6,
},
defaultUnit: 'A/V',
downloadUnit: 'A/V',
},
// Power = ∫ I dv
integral: {
name: 'Power',
unit: {
mW: 1e12,
W: 1e15,
kW: 1e18,
},
defaultUnit: 'W',
downloadUnit: 'W',
},
},
],
}
export const chartRouter = {
getChartTable: (xAxis, yAxis) => {
const name1 = xAxis + '_' + yAxis
const name2 = yAxis + '_' + xAxis
if (chartTable[name1] !== undefined) return [chartTable[name1][0], chartTable[name1][1]]
else if (chartTable[name2] !== undefined) return [chartTable[name2][1], chartTable[name2][0]]
else return 'idiot'
},
}
@@ -41,11 +41,13 @@
</va-item>
</span>
<div slot="body">
<div>
<file-control-window :ref="'fcwindow_ref'" :device="device" class="pl-0 pr-0" />
</div>
<div v-if="device.library_name.includes('Elite')">
<elite-parameter-window :ref="'epwindow_ref'" :device="device" class="pl-0 pr-0" />
<div class="mt-0 mb-0" style="height: 60vh; overflow-y: scroll; overflow-x: hidden;" :key="'detail' + device.id">
<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>
</div>
</div>
</va-collapse>
@@ -54,18 +56,21 @@
</template>
<script>
import EliteParameterWindow from '../parameter/EliteParameterWindow'
import DeviceParameterWindow from '../parameter/DeviceParameterWindow'
// 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: {
EliteParameterWindow,
DeviceParameterWindow,
// EliteParameterWindow,
// NeuliveParameterWindow,
FileControlWindow,
},
@@ -120,6 +125,7 @@ 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.status === 0"
:disable="name === 'CTRL_HIGH_Z_15' && device && 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(parameter.MODE)
? parameterTable[name].showName(modeSelection)
: 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.status === 0"
:disable="name === 'CTRL_HIGH_Z_15' && device && device.status === 0"
v-bind="parameterTable[name]"
@parameterChange="parameterChange"
@getParameter="getParameter"
@@ -93,7 +93,7 @@
<!-- guide picture button -->
<div>
<vue-final-modal
v-if="library.includes('ZM15')"
v-if="library.includes('Elite_EDC')"
v-model="showModal"
classes="modal-container"
content-class="modal-content"
@@ -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 parameterTable from '@/data/param-table/index.js'
import configTable from '@/data/config-table/index'
export default {
name: 'EliteParameterRecordingElitezm15',
@@ -148,7 +148,9 @@ export default {
},
library: {
type: String,
required: true,
},
serialNumber: {
type: [String, Array],
},
device: {
type: Object,
@@ -156,9 +158,30 @@ 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'
@@ -184,7 +207,6 @@ export default {
},
data () {
return {
parameterTable: parameterTable[this.library],
showModal: false,
workingModeSelect: null,
workingModeOptions: [],
@@ -197,11 +219,12 @@ 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(this.parameter[name], scale)} ${this.parameterTable[name].defaultUnit} )`
return ` ( ${this.parameterTable[name].outputReadabilityData(value, scale)} ${this.parameterTable[name].defaultUnit} )`
} else if (this.parameterTable[name].type === 'array') {
return ` ( ${this.parameterTable[name].outputReadabilityData(this.parameter[name])} )`
return ` ( ${this.parameterTable[name].outputReadabilityData(value)} )`
} else if (this.parameterTable[name].type === 'none') {
return ''
}
@@ -243,9 +266,8 @@ export default {
// ? this.workingModeOptions = this.workingModeDevOptions
// : this.workingModeOptions = this.workingModeNoDevOptions
this.workingModeOptions = this.parameterTable.MODE_OPTIONS
// init mode
this.workingModeSelect = this.workingModeOptions.find(ele => ele.id === this.parameter.MODE)
this.workingModeSelect = (this.parameter.MODE !== undefined) ? this.workingModeOptions.find(ele => ele.id === this.parameter.MODE) : this.workingModeOptions[0]
},
watch: {
},
@@ -0,0 +1,78 @@
<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/param-table/index.js'
import parameterTable from '@/data/config-table/index.js'
export default {
name: 'EliteParameterRecordingElitezm15',
@@ -25,7 +25,7 @@ export default {
h: 60 * 60 * 1e6,
auto: 1,
},
defaultUnit: 'auto',
defaultUnit: 'us',
},
0: {
name: 'I_in',
@@ -25,7 +25,7 @@ export default {
h: 60 * 60 * 1e6,
auto: 1,
},
defaultUnit: 'auto',
defaultUnit: 'us',
},
0: {
name: 'I_in',
@@ -1,8 +1,8 @@
export default {
name: 'Chronoamperometric',
name: 'Chronoamperometry',
parameter: ['VOLT_VSCAN', 'SAMPLE_RATE', 'ADC_LEVEL_I_15', 'ADC_LEVEL_V_IN_15', 'CTRL_HIGH_Z_15', 'TIME_DURATION'], // 這個mode用到的參數
showParameter: ['ADC_LEVEL_I_15', 'ADC_LEVEL_V_IN_15', 'CTRL_HIGH_Z_15', 'VOLT_VSCAN', 'SAMPLE_RATE'], // 有要秀給user看的參數
headerParameter: () => ['VOLT_VSCAN', 'SAMPLE_RATE', 'ADC_LEVEL_I_15', 'ADC_LEVEL_V_IN_15'], // 有要秀給user看的參數
showParameter: ['ADC_LEVEL_I_15', 'ADC_LEVEL_V_IN_15', 'CTRL_HIGH_Z_15', 'VOLT_VSCAN', 'SAMPLE_RATE', 'TIME_DURATION'], // 有要秀給user看的參數
headerParameter: () => ['VOLT_VSCAN', 'SAMPLE_RATE', 'ADC_LEVEL_I_15', 'ADC_LEVEL_V_IN_15', 'TIME_DURATION'], // 有要秀給user看的參數
valScales: {
linear: {
func: (val) => {
@@ -22,11 +22,10 @@ export default {
us: 1,
ms: 1e3,
s: 1e6,
m: 60 * 1e6,
h: 60 * 60 * 1e6,
auto: 1,
minute: 60 * 1e6,
hour: 60 * 60 * 1e6,
},
defaultUnit: 'auto',
defaultUnit: 'ms',
downloadUnit: 'ms',
},
0: {
@@ -36,7 +35,7 @@ export default {
uA: 1e3,
mA: 1e6,
},
defaultUnit: 'uA',
defaultUnit: 'mA',
downloadUnit: 'mA',
},
1: {
@@ -1,8 +1,8 @@
export default {
name: 'Chronopotentiometry',
parameter: ['Charge', 'Const_Current_value', 'SAMPLE_RATE', 'VOLTSTOP_MAX', 'VOLTSTOP_MIN', 'CC_CP_SPEED', 'ADC_LEVEL_I_15', 'ADC_LEVEL_V_IN_15', 'TIME_DURATION'], // 這個mode用到的參數
showParameter: ['ADC_LEVEL_I_15', 'ADC_LEVEL_V_IN_15', 'CTRL_HIGH_Z_15', 'SAMPLE_RATE', 'Charge', 'Const_Current_value', 'VOLTSTOP_MAX', 'VOLTSTOP_MIN'], // 有要秀給user看的參數
headerParameter: () => ['Charge', 'Const_Current_value', 'SAMPLE_RATE', 'VOLTSTOP_MAX', 'VOLTSTOP_MIN', 'CC_CP_SPEED', 'ADC_LEVEL_I_15', 'ADC_LEVEL_V_IN_15'], // 有要秀給user看的參數
showParameter: ['ADC_LEVEL_I_15', 'ADC_LEVEL_V_IN_15', 'CTRL_HIGH_Z_15', 'SAMPLE_RATE', 'Charge', 'Const_Current_value', 'VOLTSTOP_MAX', 'VOLTSTOP_MIN', 'TIME_DURATION'], // 有要秀給user看的參數
headerParameter: () => ['Charge', 'Const_Current_value', 'SAMPLE_RATE', 'VOLTSTOP_MAX', 'VOLTSTOP_MIN', 'CC_CP_SPEED', 'ADC_LEVEL_I_15', 'ADC_LEVEL_V_IN_15', 'TIME_DURATION'], // 有要秀給user看的參數
valScales: {
linear: {
func: (val) => {
@@ -22,11 +22,10 @@ export default {
us: 1,
ms: 1e3,
s: 1e6,
m: 60 * 1e6,
h: 60 * 60 * 1e6,
auto: 1,
minute: 60 * 1e6,
hour: 60 * 60 * 1e6,
},
defaultUnit: 'auto',
defaultUnit: 'ms',
downloadUnit: 'ms',
},
0: {
@@ -36,7 +35,7 @@ export default {
uA: 1e3,
mA: 1e6,
},
defaultUnit: 'uA',
defaultUnit: 'mA',
downloadUnit: 'mA',
},
1: {
@@ -57,6 +56,7 @@ export default {
V: 1e6,
},
defaultUnit: 'mV',
downloadUnit: 'mV',
},
},
charts: {
@@ -1,8 +1,8 @@
export default {
name: 'Constant Current',
parameter: ['Charge', 'Const_Current_value', 'SAMPLE_RATE', 'VOLTSTOP_MAX', 'VOLTSTOP_MIN', 'CC_CP_SPEED', 'ADC_LEVEL_I_15', 'ADC_LEVEL_V_IN_15', 'TIME_DURATION'], // 這個mode用到的參數
showParameter: ['ADC_LEVEL_I_15', 'ADC_LEVEL_V_IN_15', 'CTRL_HIGH_Z_15', 'SAMPLE_RATE', 'Charge', 'Const_Current_value', 'VOLTSTOP_MAX', 'VOLTSTOP_MIN'], // 有要秀給user看的參數
headerParameter: () => ['Charge', 'Const_Current_value', 'SAMPLE_RATE', 'VOLTSTOP_MAX', 'VOLTSTOP_MIN', 'CC_CP_SPEED', 'ADC_LEVEL_I_15', 'ADC_LEVEL_V_IN_15'], // 有要秀給user看的參數
showParameter: ['ADC_LEVEL_I_15', 'ADC_LEVEL_V_IN_15', 'CTRL_HIGH_Z_15', 'SAMPLE_RATE', 'Charge', 'Const_Current_value', 'VOLTSTOP_MAX', 'VOLTSTOP_MIN', 'TIME_DURATION'], // 有要秀給user看的參數
headerParameter: () => ['Charge', 'Const_Current_value', 'SAMPLE_RATE', 'VOLTSTOP_MAX', 'VOLTSTOP_MIN', 'CC_CP_SPEED', 'ADC_LEVEL_I_15', 'ADC_LEVEL_V_IN_15', 'TIME_DURATION'], // 有要秀給user看的參數
valScales: {
linear: {
func: (val) => {
@@ -22,11 +22,10 @@ export default {
us: 1,
ms: 1e3,
s: 1e6,
m: 60 * 1e6,
h: 60 * 60 * 1e6,
auto: 1,
minute: 60 * 1e6,
hour: 60 * 60 * 1e6,
},
defaultUnit: 'auto',
defaultUnit: 'ms',
downloadUnit: 'ms',
},
0: {
@@ -36,7 +35,7 @@ export default {
uA: 1e3,
mA: 1e6,
},
defaultUnit: 'uA',
defaultUnit: 'mA',
downloadUnit: 'mA',
},
1: {
@@ -22,11 +22,10 @@ export default {
us: 1,
ms: 1e3,
s: 1e6,
m: 60 * 1e6,
h: 60 * 60 * 1e6,
auto: 1,
minute: 60 * 1e6,
hour: 60 * 60 * 1e6,
},
defaultUnit: 'auto',
defaultUnit: 'ms',
downloadUnit: 'ms',
},
0: {
@@ -36,7 +35,7 @@ export default {
uA: 1e3,
mA: 1e6,
},
defaultUnit: 'uA',
defaultUnit: 'mA',
downloadUnit: 'mA',
},
1: {
@@ -24,9 +24,8 @@ export default {
s: 1e6,
m: 60 * 1e6,
h: 60 * 60 * 1e6,
auto: 1,
},
defaultUnit: 'auto',
defaultUnit: 'ms',
downloadUnit: 'ms',
},
0: {
@@ -36,7 +35,7 @@ export default {
uA: 1e3,
mA: 1e6,
},
defaultUnit: 'uA',
defaultUnit: 'mA',
downloadUnit: 'mA',
},
1: {
@@ -27,11 +27,10 @@ export default {
us: 1,
ms: 1e3,
s: 1e6,
m: 60 * 1e6,
h: 60 * 60 * 1e6,
auto: 1,
minute: 60 * 1e6,
hour: 60 * 60 * 1e6,
},
defaultUnit: 'auto',
defaultUnit: 'ms',
downloadUnit: 'ms',
},
0: {
@@ -41,7 +40,7 @@ export default {
uA: 1e3,
mA: 1e6,
},
defaultUnit: 'uA',
defaultUnit: 'mA',
downloadUnit: 'mA',
},
1: {
@@ -1,8 +1,8 @@
export default {
name: 'Function Generator',
parameter: ['DAC_VOLT', 'SAMPLE_RATE', 'ADC_LEVEL_I_15', 'ADC_LEVEL_V_IN_15', 'CTRL_HIGH_Z_15', 'TIME_DURATION'], // 這個mode用到的參數
showParameter: ['ADC_LEVEL_I_15', 'ADC_LEVEL_V_IN_15', 'CTRL_HIGH_Z_15', 'DAC_VOLT', 'SAMPLE_RATE'], // 有要秀給user看的參數
headerParameter: () => ['DAC_VOLT', 'SAMPLE_RATE', 'ADC_LEVEL_I_15', 'ADC_LEVEL_V_IN_15'], // export header的參數
showParameter: ['ADC_LEVEL_I_15', 'ADC_LEVEL_V_IN_15', 'CTRL_HIGH_Z_15', 'DAC_VOLT', 'SAMPLE_RATE', 'TIME_DURATION'], // 有要秀給user看的參數
headerParameter: () => ['DAC_VOLT', 'SAMPLE_RATE', 'ADC_LEVEL_I_15', 'ADC_LEVEL_V_IN_15', 'TIME_DURATION'], // export header的參數
valScales: {
linear: {
func: (val) => {
@@ -22,11 +22,10 @@ export default {
us: 1,
ms: 1e3,
s: 1e6,
m: 60 * 1e6,
h: 60 * 60 * 1e6,
auto: 1,
minute: 60 * 1e6,
hour: 60 * 60 * 1e6,
},
defaultUnit: 'auto',
defaultUnit: 'ms',
downloadUnit: 'ms',
},
0: {
@@ -36,7 +35,7 @@ export default {
uA: 1e3,
mA: 1e6,
},
defaultUnit: 'uA',
defaultUnit: 'mA',
downloadUnit: 'mA',
},
1: {
@@ -1,8 +1,8 @@
export default {
name: 'I-T Graph',
parameter: ['DAC_VOLT', 'SAMPLE_RATE', 'ADC_LEVEL_I_15', 'ADC_LEVEL_V_IN_15', 'CTRL_HIGH_Z_15', 'TIME_DURATION'], // 這個mode用到的參數
showParameter: ['ADC_LEVEL_I_15', 'ADC_LEVEL_V_IN_15', 'CTRL_HIGH_Z_15', 'DAC_VOLT', 'SAMPLE_RATE'], // 有要秀給user看的參數
headerParameter: () => ['DAC_VOLT', 'SAMPLE_RATE', 'ADC_LEVEL_I_15', 'ADC_LEVEL_V_IN_15'], // export header的參數
showParameter: ['ADC_LEVEL_I_15', 'ADC_LEVEL_V_IN_15', 'CTRL_HIGH_Z_15', 'DAC_VOLT', 'SAMPLE_RATE', 'TIME_DURATION'], // 有要秀給user看的參數
headerParameter: () => ['DAC_VOLT', 'SAMPLE_RATE', 'ADC_LEVEL_I_15', 'ADC_LEVEL_V_IN_15', 'TIME_DURATION'], // export header的參數
valScales: {
linear: {
func: (val) => {
@@ -22,11 +22,10 @@ export default {
us: 1,
ms: 1e3,
s: 1e6,
m: 60 * 1e6,
h: 60 * 60 * 1e6,
auto: 1,
minute: 60 * 1e6,
hour: 60 * 60 * 1e6,
},
defaultUnit: 'auto',
defaultUnit: 'ms',
downloadUnit: 'ms',
},
0: {
@@ -36,7 +35,7 @@ export default {
uA: 1e3,
mA: 1e6,
},
defaultUnit: 'uA',
defaultUnit: 'mA',
downloadUnit: 'mA',
},
1: {
@@ -22,11 +22,10 @@ export default {
us: 1,
ms: 1e3,
s: 1e6,
m: 60 * 1e6,
h: 60 * 60 * 1e6,
auto: 1,
minute: 60 * 1e6,
hour: 60 * 60 * 1e6,
},
defaultUnit: 'auto',
defaultUnit: 'ms',
downloadUnit: 'ms',
},
0: {
@@ -36,7 +35,7 @@ export default {
uA: 1e3,
mA: 1e6,
},
defaultUnit: 'uA',
defaultUnit: 'mA',
downloadUnit: 'mA',
},
1: {
@@ -22,11 +22,10 @@ export default {
us: 1,
ms: 1e3,
s: 1e6,
m: 60 * 1e6,
h: 60 * 60 * 1e6,
auto: 1,
minute: 60 * 1e6,
hour: 60 * 60 * 1e6,
},
defaultUnit: 'auto',
defaultUnit: 'ms',
downloadUnit: 'ms',
},
0: {
@@ -36,7 +35,7 @@ export default {
uA: 1e3,
mA: 1e6,
},
defaultUnit: 'uA',
defaultUnit: 'mA',
downloadUnit: 'mA',
},
1: {
@@ -1,8 +1,8 @@
export default {
name: 'Open Circuit Potential',
parameter: ['SAMPLE_RATE', 'ADC_LEVEL_I_15', 'ADC_LEVEL_V_IN_15', 'TIME_DURATION'], // 這個mode用到的參數
showParameter: ['ADC_LEVEL_I_15', 'ADC_LEVEL_V_IN_15', 'SAMPLE_RATE'], // 有要秀給user看的參數
headerParameter: () => ['SAMPLE_RATE', 'ADC_LEVEL_I_15', 'ADC_LEVEL_V_IN_15'], // export header的參數
showParameter: ['ADC_LEVEL_I_15', 'ADC_LEVEL_V_IN_15', 'SAMPLE_RATE', 'TIME_DURATION'], // 有要秀給user看的參數
headerParameter: () => ['SAMPLE_RATE', 'ADC_LEVEL_I_15', 'ADC_LEVEL_V_IN_15', 'TIME_DURATION'], // export header的參數
valScales: {
linear: {
func: (val) => {
@@ -22,11 +22,10 @@ export default {
us: 1,
ms: 1e3,
s: 1e6,
m: 60 * 1e6,
h: 60 * 60 * 1e6,
auto: 1,
minute: 60 * 1e6,
hour: 60 * 60 * 1e6,
},
defaultUnit: 'auto',
defaultUnit: 'ms',
downloadUnit: 'ms',
},
0: {
@@ -36,7 +35,7 @@ export default {
uA: 1e3,
mA: 1e6,
},
defaultUnit: 'uA',
defaultUnit: 'mA',
downloadUnit: 'mA',
},
1: {
@@ -38,11 +38,10 @@ export default {
us: 1,
ms: 1e3,
s: 1e6,
m: 60 * 1e6,
h: 60 * 60 * 1e6,
auto: 1,
minute: 60 * 1e6,
hour: 60 * 60 * 1e6,
},
defaultUnit: 'auto',
defaultUnit: 'ms',
downloadUnit: 'ms',
},
0: {
@@ -52,7 +51,7 @@ export default {
uA: 1e3,
mA: 1e6,
},
defaultUnit: 'uA',
defaultUnit: 'mA',
downloadUnit: 'mA',
},
1: {
@@ -62,7 +61,7 @@ export default {
uA: 1e3,
mA: 1e6,
},
defaultUnit: 'uA',
defaultUnit: 'mA',
downloadUnit: 'mA',
},
},
@@ -1,8 +1,8 @@
export default {
name: 'R-T Graph',
parameter: ['DAC_VOLT', 'SAMPLE_RATE', 'CTRL_HIGH_Z_15', 'TIME_DURATION'], // 這個mode用到的參數
showParameter: ['CTRL_HIGH_Z_15', 'DAC_VOLT', 'SAMPLE_RATE'], // 有要秀給user看的參數
headerParameter: () => ['DAC_VOLT', 'SAMPLE_RATE', 'ADC_LEVEL_I_15', 'ADC_LEVEL_V_IN_15'], // export header的參數
showParameter: ['CTRL_HIGH_Z_15', 'DAC_VOLT', 'SAMPLE_RATE', 'TIME_DURATION'], // 有要秀給user看的參數
headerParameter: () => ['DAC_VOLT', 'SAMPLE_RATE', 'ADC_LEVEL_I_15', 'ADC_LEVEL_V_IN_15', 'TIME_DURATION'], // export header的參數
valScales: {
linear: {
func: (val) => {
@@ -22,11 +22,10 @@ export default {
us: 1,
ms: 1e3,
s: 1e6,
m: 60 * 1e6,
h: 60 * 60 * 1e6,
auto: 1,
minute: 60 * 1e6,
hour: 60 * 60 * 1e6,
},
defaultUnit: 'auto',
defaultUnit: 'ms',
downloadUnit: 'ms',
},
0: {
@@ -36,7 +35,7 @@ export default {
uA: 1e3,
mA: 1e6,
},
defaultUnit: 'uA',
defaultUnit: 'mA',
downloadUnit: 'mA',
},
1: {
@@ -50,7 +49,7 @@ export default {
downloadUnit: 'mV',
},
2: {
name: 'Resister',
name: 'Resistor',
unit: {
: 1,
mohm: 1,
@@ -1,8 +1,8 @@
export default {
name: 'V-T Graph',
parameter: ['SAMPLE_RATE', 'ADC_LEVEL_I_15', 'ADC_LEVEL_V_IN_15', 'CTRL_HIGH_Z_15', 'TIME_DURATION'], // 這個mode用到的參數
showParameter: ['ADC_LEVEL_I_15', 'ADC_LEVEL_V_IN_15', 'CTRL_HIGH_Z_15', 'SAMPLE_RATE'], // 有要秀給user看的參數
headerParameter: () => ['SAMPLE_RATE', 'ADC_LEVEL_I_15', 'ADC_LEVEL_V_IN_15'], // export header的參數
showParameter: ['ADC_LEVEL_I_15', 'ADC_LEVEL_V_IN_15', 'CTRL_HIGH_Z_15', 'SAMPLE_RATE', 'TIME_DURATION'], // 有要秀給user看的參數
headerParameter: () => ['SAMPLE_RATE', 'ADC_LEVEL_I_15', 'ADC_LEVEL_V_IN_15', 'TIME_DURATION'], // export header的參數
valScales: {
linear: {
func: (val) => {
@@ -22,11 +22,10 @@ export default {
us: 1,
ms: 1e3,
s: 1e6,
m: 60 * 1e6,
h: 60 * 60 * 1e6,
auto: 1,
minute: 60 * 1e6,
hour: 60 * 60 * 1e6,
},
defaultUnit: 'auto',
defaultUnit: 'ms',
downloadUnit: 'ms',
},
0: {
@@ -36,7 +35,7 @@ export default {
uA: 1e3,
mA: 1e6,
},
defaultUnit: 'uA',
defaultUnit: 'mA',
downloadUnit: 'mA',
},
1: {
File diff suppressed because it is too large Load Diff
@@ -24,7 +24,7 @@ export default {
h: 60 * 60 * 1e6,
auto: 1,
},
defaultUnit: 'auto',
defaultUnit: 'us',
},
0: {
name: '0',
+137
View File
@@ -0,0 +1,137 @@
import EliteEDC from './EliteEDC/index'
import EliteEIS from './EliteEIS/index'
// object saving library name mapping table
const libraryNameMappingTable = {
EliteZM15: EliteEDC,
'Elite_EDC_1.4': null,
'Elite_EDC_1.5': EliteEDC,
'Elite_EDC_1.5re': EliteEDC,
'Elite_EDC_1.5r2': EliteEDC,
'Elite_BAT_1.0': EliteEDC,
'Elite_EIS_1.0': EliteEIS,
'Elite_EIS_1.1': EliteEIS,
'Elite_EIS_MINI_1.0': EliteEIS,
'Elite_TRIG_0.1': null,
'Elite_MEGAFLY_0.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: EliteEDC, // BAT1.0
},
},
4: {
1: {
0: EliteEIS, // EIS1.0
1: EliteEIS, // EIS1.1
2: EliteEIS, // EIS1.1mini
},
},
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
+2 -2
View File
@@ -24,7 +24,7 @@ const hasCycleMode = (mode, lib) => {
}
const getDefaultChartTypeByMode = (mode, lib) => {
if (lib === 'EliteZM15') {
if (lib === 'EliteZM15' || lib.includes('Elite_EDC')) {
const settings = {}
settings[0] = ['Elite', 2, 'Elite', 1]
settings[1] = ['Elite', 2, 'Elite', 1]
@@ -43,7 +43,7 @@ const getDefaultChartTypeByMode = (mode, lib) => {
settings[15] = ['Elite', 2, 'Elite', 1]
settings[16] = ['Time', 2, 'Elite', 2]
return settings[mode]
} else if (lib === 'EliteEIS') {
} else if (lib.includes('EIS') || lib.includes('Elite_EIS')) {
const settings = {}
settings[0] = ['EliteEIS', 6, 'EliteEIS', 5]
settings[1] = ['Elite', 2, 'Elite', 1]
-9
View File
@@ -1,9 +0,0 @@
import EliteZM15 from './EliteZM15/index'
import EliteEIS from './EliteEIS/index'
const paramTable = {
EliteZM15,
EliteEIS,
}
export default paramTable
+13 -3
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])
@@ -84,7 +84,7 @@ export const dataStreamBuffer = {
// console.log(dataBatch)
// }
for (const chart in _dataStreamBuffer) {
if (_dataStreamBuffer[chart][currentDeviceID] != null && _dataStreamBuffer[chart][currentDeviceID][currentChannel] != null) {
if (_dataStreamBuffer[chart][currentDeviceID] != null) {
// const samplingDataBatch = {}
// let lastTime = -1
// dataBatch.forEach(data => {
@@ -95,6 +95,9 @@ export const dataStreamBuffer = {
// lastTime = samplingTime
// })
const _dataBatch = Array.from(dataBatch)
if (_dataStreamBuffer[chart][currentDeviceID][currentChannel] === undefined) {
_dataStreamBuffer[chart][currentDeviceID][currentChannel] = []
}
_dataStreamBuffer[chart][currentDeviceID][currentChannel].push(_dataBatch)
if (_dataStreamBuffer[chart][currentDeviceID][currentChannel].length > _dataStreamBufferSize) {
_dataStreamBuffer[chart][currentDeviceID][currentChannel].shift()
@@ -109,7 +112,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,3 +135,10 @@ export const dataStreamBuffer = {
},
}
/*
{
"chartID" : {
"deviceID": {
"channel": [[dataset1], ... [dataset5], [datasetlog6]]
}
} */
+6 -4
View File
@@ -1,6 +1,6 @@
function newChart (chartID) {
function newChart (chartID, numOfCharts) {
return {
chartID: parseInt(chartID),
chartID: chartID,
chartType: 'detail',
chartDevice: 'elite', // elite or neulive
chartMode: 0,
@@ -8,10 +8,11 @@ function newChart (chartID) {
chartYUnit: '',
chartXMode: 'value', // value or time
chartYMode: 'value', // value or time
cardName: 'chart' + String(chartID),
cardName: 'chart' + String(numOfCharts),
cardHeight: '500px',
cardWidth: 'auto',
mappingID: -1,
mappingID: '-1',
createdBy: '', // manual ror default
run: false,
timer: 0,
legend: {
@@ -34,6 +35,7 @@ function newChart (chartID) {
yAxis: [],
dataZoom: null,
series: [],
cycle: 0,
}
}
+2
View File
@@ -13,6 +13,8 @@ function newDataZoom () {
showDataShadow: false,
showDetail: false,
xAxisIndex: [],
start: 0,
end: 100,
}, {
type: 'inside',
xAxisIndex: [],
+125
View File
@@ -0,0 +1,125 @@
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
+41 -86
View File
@@ -5,6 +5,7 @@ function getTime (val) {
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 '
}
@@ -17,13 +18,13 @@ function getTime (val) {
if (millisecond > 0) {
label += millisecond + ' ms '
}
if (microsecond > 0 && hour === 0 && minute === 0 && second === 0) {
if (microsecond >= 0 && hour === 0 && minute === 0 && second === 0) {
label += microsecond + ' µs '
}
return label
}
function newTooltip (chartID) {
function newTooltip (realTime, dataMode) {
return {
hideDelay: 5000,
trigger: 'axis',
@@ -32,92 +33,46 @@ function newTooltip (chartID) {
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
// 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 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
tip += '<span style="' + style + '">' + param.seriesName + ':<ul style = "list-style-type: disc; list-style-position: inside">'
if (unitTable.xName !== 'Time') {
value = parseFloat(param.value[0] / unitTable.xScale[unitTable.xUnit]).toFixed(3) + unitTable.xUnit
tip += '<li>' + unitTable.xName + ' = ' + value + '</li>'
}
if (unitTable.yName !== 'Time') {
value = parseFloat(param.value[1] / unitTable.yScale[unitTable.yUnit]).toFixed(3) + unitTable.yUnit
tip += '<li>' + unitTable.yName + ' = ' + value + '</li>'
}
tip += '</ul></span>'
}
}
return tip
},
}
}
+1
View File
@@ -9,3 +9,4 @@ $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/tooltipFactory'
import newTooltip from '@/factories/chart/replayTooltipFactory'
import newDataZoom from '@/factories/chart/dataZoomFactory'
import types from '@/store/modules/analysis/replay/types'
@@ -283,15 +283,16 @@ const actions = {
const axis = payload.axis
const chartID = payload.chartID
const gridIndex = payload.gridIndex
if (type === 'log') {
if (axis === 'x') {
state.chartData[chartID].xAxis[gridIndex].type = type
state.chartData[chartID].xAxis[gridIndex].minorSplitLine.show = true
} else if (axis === 'y') {
state.chartData[chartID].yAxis[gridIndex].type = type
state.chartData[chartID].yAxis[gridIndex].minorSplitLine.show = true
}
} else if (type === 'value') {
// if (type === 'log') {
// if (axis === 'x') {
// state.chartData[chartID].xAxis[gridIndex].type = type
// state.chartData[chartID].xAxis[gridIndex].minorSplitLine.show = true
// } else if (axis === 'y') {
// state.chartData[chartID].yAxis[gridIndex].type = type
// state.chartData[chartID].yAxis[gridIndex].minorSplitLine.show = true
// }
// } else
if (type === 'value') {
if (axis === 'x') {
state.chartData[chartID].xAxis[gridIndex].type = type
state.chartData[chartID].xAxis[gridIndex].minorSplitLine.show = false
@@ -1,6 +1,6 @@
import types from '@/store/modules/download/types'
import golbalMethods from '@/data/global/global'
import paramTable from '@/data/param-table/index'
import configTable from '@/data/config-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 = paramTable[libraryName]
const paramObj = configTable.getConfig(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 = paramTable[libraryName].MODE[meta.parameter_set.MODE]
const modeObj = configTable.getModeConfig(libraryName, meta.parameter_set.MODE)
const downloadInfo = state.downloadInfo
const titleArray = []
const channelString = ''
@@ -66,6 +66,8 @@ 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
},
/**
+2 -3
View File
@@ -1,8 +1,5 @@
function newState () {
return {
projectAll: {},
projectSelectKey: '',
projectList: [],
projectSelectIndex: -1,
@@ -17,6 +14,8 @@ function newState () {
projectManagerPanel: {
show: true,
},
// library
projectLibrary: null,
taskViewPanel: {
show: false,
@@ -16,31 +16,30 @@ 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')
const { controllerID } = payload
const cacheData = await localforage.getItem('chart_data_' + controllerID)
if (cacheData !== null) {
// use ID to create new chart by cache
for (const _chart of Object.values(cacheData)) {
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],
})
}
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],
})
}
state.taskContentChartNumber++
dispatch(typePath.refreshPanel)
}
state.chartData[_chart.chartID].createdBy = 'manual'
}
dispatch(typePath.refreshPanel)
}
},
/**
@@ -48,21 +47,19 @@ const chartActs = {
*
*/
[typePath.saveToCache]: async ({ state, getters, commit, dispatch }, payload) => {
const { controllerID } = payload
const _chartData = {}
for (const [_id, _chart] of Object.entries(state.chartData)) {
if (_chart.mappingID === -1) { // not default chart
// manual chart clear series data
if (_chart.createdBy === 'manual') {
_chartData[_id] = JSON.parse(JSON.stringify(_chart))
if (_chartData[_id].series.data != null) {
_chartData[_id].series.data.length = 0
}
_chartData[_id].series.length = 0
_chartData[_id].series.map((ele) => { ele.data.length = 0 })
}
}
await localforage.setItem('chart_data', _chartData)
await localforage.setItem('chart_data_' + controllerID, _chartData)
},
/**
/*
* add chartID to chartData
*
* @param {String} chartID
* @param {Number} maxDots
* @param {Number} gridLength
@@ -70,8 +67,8 @@ const chartActs = {
*/
[typePath.add]: ({ state, getters, commit, dispatch }, payload) => {
const { chartID, maxDots, gridLength } = payload
if (state.chartData[parseInt(chartID)] == null) {
state.chartData[parseInt(chartID)] = newChart(chartID)
if (state.chartData[chartID] == null) {
state.chartData[chartID] = newChart(chartID, Object.keys(state.chartData).length)
state.chartData[chartID].maxDots = maxDots
state.chartData[chartID].tooltip = newTooltip()
dispatch(typePath.updateGridList, { chartID: chartID, length: gridLength })
@@ -80,6 +77,7 @@ const chartActs = {
return state.chartData[chartID]
}
},
/**
* register source channel setting from cache
*
@@ -234,28 +232,10 @@ 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) {
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
return getTimeFormatter(val)
}
state.chartData[chartID].xAxis[_xAxisIndex].interval = 500 * 1000
} else if (sourceList[0].name === 'Elite') {
@@ -282,7 +262,7 @@ const chartActs = {
default:
break
}
} else if (sourceList[0].name === 'EliteEIS') {
} else if (sourceList[0].name.includes('EIS')) {
switch (sourceList[0].channel) {
case 3:
state.chartData[chartID].xAxis[_xAxisIndex].axisLabel.formatter = function (val) {
@@ -362,7 +342,6 @@ 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) {
@@ -379,7 +358,7 @@ const chartActs = {
default:
break
}
} else if (sourceList[1].name === 'EliteEIS') {
} else if (sourceList[1].name.includes('EIS')) {
switch (sourceList[1].channel) {
case 3:
state.chartData[chartID].yAxis[_yAxisIndex].axisLabel.formatter = function (val) {
@@ -515,7 +494,14 @@ const chartActs = {
if (!state.chartData[chartID].gridSource[gridIndex].some(el => el.name === _gridSeries.name)) {
state.chartData[chartID].gridSource[gridIndex].push(_gridSeries)
}
// console.log(state.chartData[chartID])
// assign mappingID with device ID
if (deviceIDX >= 0) {
state.chartData[chartID].mappingID = deviceIDX
}
if (deviceIDY >= 0) {
state.chartData[chartID].mappingID = deviceIDY
}
return state.chartData[chartID]
},
/**
@@ -537,7 +523,7 @@ const chartActs = {
* @param {String} chartID
*/
[typePath.refreshData]: ({ state, getters, commit, dispatch }, payload) => {
const { chartID, deviceList } = payload
const { chartID } = payload
if (state.chartData[chartID] == null) {
return false
}
@@ -710,24 +696,12 @@ const chartActs = {
// series data list shift by time
if (series.data.length > 0) {
if (series.xAxisSource[0] === -1) {
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)
}
if (series.data.length > state.chartData[chartID].maxDots) {
series.data.splice(0, series.data.length - state.chartData[chartID].maxDots)
}
} else if (series.yAxisSource[0] === -1) {
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)
}
if (series.data.length > state.chartData[chartID].maxDots) {
series.data.splice(0, series.data.length - state.chartData[chartID].maxDots)
}
}
}
@@ -768,7 +742,6 @@ const chartActs = {
// }
return false
}
// get data from buffer
const popDataX = dataStreamBuffer.pop(chartID, rawDeviceIDX, series.xAxisSource[1])
const popDataY = dataStreamBuffer.pop(chartID, rawDeviceIDY, series.yAxisSource[1])
@@ -862,6 +835,11 @@ const chartActs = {
}
}
})
const popCycle = dataStreamBuffer.pop(chartID, state.chartData[chartID].mappingID, 4)
if (popCycle.length) {
state.chartData[chartID].cycle = popCycle.at(-1).data
}
},
/**
* generate default chart
@@ -1002,7 +980,7 @@ const chartActs = {
mappingID: state.chartData[_chartID].mappingID,
cardName: state.chartData[_chartID].cardName,
})
state.chartData[_chartID].mappingID = parseInt(item.id)
state.chartData[_chartID].mappingID = item.id
switch (_type) {
case 'device':
_chartRegisterDevice(_chartID, item)
@@ -1016,21 +994,23 @@ const chartActs = {
let isSetting = false
for (const chartID in state.chartData) {
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
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
}
}
}
}
@@ -1053,12 +1033,13 @@ 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)
@@ -1066,6 +1047,22 @@ 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
*
@@ -1318,3 +1315,24 @@ 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,6 +9,7 @@ const types = {
updateGridList: 'taskContentChartUpdateGridList',
defaultChartGenerator: 'taskContentChartDefaultChartGenerator',
reset: 'taskContentChartReset',
resetSeriesData: 'taskContentChartResetSeriesData',
refreshData: 'taskContentChartRefreshData',
refreshChart: 'taskContentChartRefreshChart',
refreshPanel: 'taskContentChartRefreshPanel',