Compare commits

...

44 Commits

Author SHA1 Message Date
peterlu14 1d6d8aef19 refactor: refactor data handling, parsing, and comparison methods
- Change the way to handle downloaded data, by adding 'bytea_data' to the attributes fetched and going through byte data instead of regular data
- Add a 'parseByteData' method to replace the previous 'parseRawData' method
- Ensure data normalization by parsing the downloaded data into integers
- The change applies to both online and offline downloading
- Minor update in timestamp comparison operation, with data parsed to integer before being compared.

Signed-off-by: peterlu14 <peterlu810516@gmail.com>
2024-01-23 15:48:22 +08:00
peterlu14 4f13ea68e7 Merge branch 'dev/trigger' into dev/new_configuration 2023-12-15 12:05:19 +08:00
peterlu14 5e761d68b4 feat: refine UI behavior and enhance test compatibility
- Clear input value after confirming in the SaveConfigModal component
- Add a check for undefined grid source before removing series in chart actions

Signed-off-by: peterlu14 <peterlu810516@gmail.com>
2023-12-15 11:59:53 +08:00
peterlu14 bcbe2b94b5 feat: improve configuration management and chart data handling
- Add `save.svg` and `whitecross.svg` icons to the project assets
- Implement a `copy` function in `TaskContent.vue` to copy selected charts and their data streams
- Update conditions for creating and removing grid sources in `CanvasChartSource1.vue`
- Add the config name display and individual config deletion functionality in the configuration module
- Include a new function in `Configuration.vue` to remove stored chart data
- Change the save icon reference in the configuration module, and handle deletion of a selected config
- Modification in `Configuration.vue` and `Library.vue` to load a selected configuration from the config array, and highlight the selected one in the libraries
- Improve user experience by providing visual cues for action by changing the background color for selected config.

Overall, these changes mostly involve updates to handling configuration and chart data within the project, as well as some user interface improvements for better user experience.
2023-12-15 11:56:16 +08:00
peterlu14 0fab677729 - replace chart source with a new style and function 2023-12-08 11:55:05 +08:00
peterlu14 2ae9c4716a feat: "Enhance task content and configuration components functionality"
- Added the `reset` function to the task content component to remove all existing charts and generate default charts
- Added the `copy` function to the task content component for copying configuration
- Updated UI layout of the configuration component to be more responsive and interactive
- Implemented checkbox functionality to the configuration component
- Included the `buildAccordingBlock` method to handle accordion interaction in the configuration component
- Moved `loadConfig` method handling to the `Library` component
- Added a new `Library` component to load saved configurations
- Added new styles to the `Configuration` component to improve the user interface
- Replaced the `CanvasChartSource` import in `Configuration` component.

Signed-off-by: peterlu14 <peterlu810516@gmail.com>
2023-12-07 17:36:34 +08:00
peterlu14 cc96798671 chore: "Add new SVG icons to assets"
- Added 'add-chart' SVG icon to the assets
- Added 'add-config' SVG icon to the assets
- Added 'copy' SVG icon to the assets
- Added 'library' SVG icon to the assets
- Added 'reset' SVG icon to the assets
- Added 'save-as' SVG icon to the assets
2023-12-07 17:32:01 +08:00
peterlu14 4c24b08d92 -unshow battery when device working 2023-11-21 15:56:29 +08:00
peterlu14 753248826d -update add BAT 2023-10-02 14:43:08 +08:00
peterlu14 57c9972855 - change download default to excel 2023-07-11 15:30:43 +08:00
peterlu14 ba7145be76 - cycle cannot 0 2023-07-05 17:42:04 +08:00
peterlu14 f0fe12bc84 - 需要下拉選單的指示
- enable/disanable 綠色調整
- 開關往下移讓他跟 s 置中對齊
- 5V output 的 on
- 前端/ UI 輸入要做限制,s 輸入最小精度 0.1 s,current 電流輸入最小精度 0.1 mA
- 名稱文字調整
- Fix current range
2023-06-21 16:58:56 +08:00
peterlu14 096ecb4a7e -update folder click 2023-06-14 16:10:40 +08:00
peterlu14 5614bf69ed -fix backend data type error 2023-06-13 13:42:49 +08:00
peterlu14 d60438e952 - update trigger 2023-06-13 09:49:16 +08:00
peterlu14 55dde2a4e4 -remake trigger 2023-06-13 09:31:07 +08:00
peterlu14 0b1afd6f29 -add trigger dev mode 2023-05-15 11:37:40 +08:00
peterlu14 1e602052ab - create configuration
- subplot more flexable
- reorder chart
- TODO rename legend
2023-05-11 15:10:06 +08:00
peterlu14 dc3635190a - change chart reference by mem to mac_address
- remove gridSource
- remove grid
- remove useless code
2023-04-26 17:48:15 +08:00
Roy 74f755a966 [update] fix channel unit 2023-04-14 09:03:49 +08:00
peterlu14 1072b37139 - fix folder bug 2023-04-13 16:34:08 +08:00
peterlu14 030e63b8c6 - fix real time channel info 2023-04-13 16:26:48 +08:00
peterlu14 1aa6cc6d31 - config table add physicalQuantity 2023-04-13 16:24:34 +08:00
peterlu14 30db3a9232 - fix folder conflict problem 2023-04-13 11:47:38 +08:00
peterlu14 0d2b97b87e - remove duplicate messages
- prevent multi-user refresh cause chart clear problem
- chart series add lttb
2023-04-13 10:56:24 +08:00
peterlu14 b4169367aa - download display rebuild
- support download
- support offline-download
2023-04-12 18:44:32 +08:00
peterlu14 820d59cb2f Merge remote-tracking branch 'origin/dev/8hstia' into dev/scheduler-datatable-8hstia 2023-04-12 14:57:15 +08:00
peterlu14 c58ec8c907 - fixed download 2023-04-12 14:55:39 +08:00
peterlu14 dcf9d1b98c - fix edit file way
- remove popover message
- remove sd card button
2023-04-11 18:07:00 +08:00
peterlu14 fd4ff2d99d - click outside table unselect all
- fix the select word conflict with shift
- fix delect files page wrong
2023-04-11 17:47:15 +08:00
peterlu14 8bf7a893ae -real time chart unit more flexible
-add source into gridsource
2023-04-11 17:45:35 +08:00
Roy ce4cf4078b [update] up to 8 hstia 2023-04-11 13:12:32 +08:00
peterlu14 cbd45415bd - download selected files 2023-04-10 14:28:26 +08:00
peterlu14 140a564ee7 - create modal for moving folder
- remove check illegal char
- change UI layout
- add hot key to select file ctrl & shift
- fix edit folder name
- fix delete folder inner all files
- fix refs datatable_ref undefined problem
- when selected file the text in table cannot be select
2023-04-07 16:51:46 +08:00
peterlu14 8d24a93f6d -fix checkbox 2023-03-31 11:18:23 +08:00
peterlu14 98135d6ce2 - update file with sorted
- change single click & double click
- fix delete folder
2023-03-31 11:07:22 +08:00
peterlu14 a3ccb942e5 - fix create task 2023-03-25 13:18:41 +08:00
peterlu14 eacc0d9547 - project sort with created time
- new project created time reassign
- copy project created time reassign
- save project (create task, copy task, delete task)
2023-03-25 13:07:46 +08:00
peterlu14 9cc653b761 -auto save ( cycle, device) 2023-03-24 19:22:38 +08:00
peterlu14 0cfc02c939 - reset projecttableselectIndex
- prevent select task null
- fixed parameter is undefined
- fix scheduler change mode reset problem
- auto save
2023-03-24 19:07:42 +08:00
ROY 60252b5cfe [update] update AC_AMP defaultValue of schedule 2023-03-21 16:21:51 +08:00
peterlu14 cc5207ae07 - fix legend name duplicate problem 2023-03-16 17:56:32 +08:00
peterlu14 4ad2b51161 - Elite EDC VOLT_VSCAN to CA_VOLT 2023-03-08 09:37:12 +08:00
ROY 0f32263d12 [update] update bat0.1 and new bat1.0 2023-03-07 18:03:59 +08:00
89 changed files with 3996 additions and 1895 deletions
+8
View File
@@ -0,0 +1,8 @@
<svg width="28" height="28" viewBox="0 0 28 28" fill="none" xmlns="http://www.w3.org/2000/svg">
<mask id="mask0_806_98" style="mask-type:alpha" maskUnits="userSpaceOnUse" x="0" y="0" width="28" height="28">
<rect width="28" height="28" fill="#D9D9D9"/>
</mask>
<g mask="url(#mask0_806_98)">
<path d="M12.8334 19.8333H15.1667V15.1666H19.8334V12.8333H15.1667V8.16665H12.8334V12.8333H8.16671V15.1666H12.8334V19.8333ZM14 25.6666C12.3862 25.6666 10.8695 25.3604 9.45004 24.7479C8.0306 24.1354 6.79587 23.3041 5.74587 22.2541C4.69587 21.2041 3.86462 19.9694 3.25212 18.55C2.63962 17.1305 2.33337 15.6139 2.33337 14C2.33337 12.3861 2.63962 10.8694 3.25212 9.44998C3.86462 8.03053 4.69587 6.79581 5.74587 5.74581C6.79587 4.69581 8.0306 3.86456 9.45004 3.25206C10.8695 2.63956 12.3862 2.33331 14 2.33331C15.6139 2.33331 17.1306 2.63956 18.55 3.25206C19.9695 3.86456 21.2042 4.69581 22.2542 5.74581C23.3042 6.79581 24.1355 8.03053 24.748 9.44998C25.3605 10.8694 25.6667 12.3861 25.6667 14C25.6667 15.6139 25.3605 17.1305 24.748 18.55C24.1355 19.9694 23.3042 21.2041 22.2542 22.2541C21.2042 23.3041 19.9695 24.1354 18.55 24.7479C17.1306 25.3604 15.6139 25.6666 14 25.6666ZM14 23.3333C16.6056 23.3333 18.8125 22.4291 20.6209 20.6208C22.4292 18.8125 23.3334 16.6055 23.3334 14C23.3334 11.3944 22.4292 9.18748 20.6209 7.37915C18.8125 5.57081 16.6056 4.66665 14 4.66665C11.3945 4.66665 9.18754 5.57081 7.37921 7.37915C5.57087 9.18748 4.66671 11.3944 4.66671 14C4.66671 16.6055 5.57087 18.8125 7.37921 20.6208C9.18754 22.4291 11.3945 23.3333 14 23.3333Z" fill="#2C4053"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.5 KiB

+4
View File
@@ -0,0 +1,4 @@
<svg width="28" height="24" viewBox="0 0 28 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M2 20.0513V4.25641C2 3.65797 2.25286 3.08405 2.70294 2.66089C3.15303 2.23773 3.76348 2 4.4 2H23.6C24.2365 2 24.847 2.23773 25.2971 2.66089C25.7471 3.08405 26 3.65797 26 4.25641V20.0513C26 20.6497 25.7471 21.2236 25.2971 21.6468C24.847 22.07 24.2365 22.3077 23.6 22.3077H4.4C3.76348 22.3077 3.15303 22.07 2.70294 21.6468C2.25286 21.2236 2 20.6497 2 20.0513Z" stroke="#2C4053" stroke-width="2.5"/>
<path d="M2 6.51279H26M10.4 14.4102H14M14 14.4102H17.6M14 14.4102V11.0256M14 14.4102V17.7948" stroke="#2C4053" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"/>
</svg>

After

Width:  |  Height:  |  Size: 687 B

+4
View File
@@ -0,0 +1,4 @@
<svg width="270" height="110" viewBox="0 0 270 110" fill="none" xmlns="http://www.w3.org/2000/svg">
<rect width="270" height="110" rx="55" fill="#A4A3A3"/>
<path d="M84.9 88.9C80.4 88.9 76.41 88 72.93 86.2C69.45 84.34 66.75 81.73 64.83 78.37C62.97 75.01 62.04 71.14 62.04 66.76V46.24C62.04 41.92 63 38.11 64.92 34.81C66.84 31.45 69.51 28.87 72.93 27.07C76.41 25.21 80.4 24.28 84.9 24.28C89.46 24.28 93.45 25.21 96.87 27.07C100.35 28.87 103.05 31.45 104.97 34.81C106.89 38.11 107.85 41.92 107.85 46.24V66.76C107.85 71.14 106.89 75.01 104.97 78.37C103.05 81.73 100.35 84.34 96.87 86.2C93.45 88 89.46 88.9 84.9 88.9ZM84.9 79.9C88.68 79.9 91.71 78.73 93.99 76.39C96.27 74.05 97.41 70.96 97.41 67.12V46.15C97.41 42.25 96.27 39.13 93.99 36.79C91.71 34.45 88.68 33.28 84.9 33.28C81.18 33.28 78.18 34.45 75.9 36.79C73.62 39.13 72.48 42.25 72.48 46.15V67.12C72.48 70.96 73.62 74.05 75.9 76.39C78.18 78.73 81.18 79.9 84.9 79.9ZM162.038 32.92C162.038 33.22 161.918 33.49 161.678 33.73C161.498 33.91 161.258 34 160.958 34H130.358C130.058 34 129.908 34.15 129.908 34.45V51.28C129.908 51.58 130.058 51.73 130.358 51.73H150.968C151.268 51.73 151.508 51.85 151.688 52.09C151.928 52.27 152.048 52.51 152.048 52.81V59.65C152.048 59.95 151.928 60.22 151.688 60.46C151.508 60.64 151.268 60.73 150.968 60.73H130.358C130.058 60.73 129.908 60.88 129.908 61.18V86.92C129.908 87.22 129.788 87.49 129.548 87.73C129.368 87.91 129.128 88 128.828 88H120.548C120.248 88 119.978 87.91 119.738 87.73C119.558 87.49 119.468 87.22 119.468 86.92V26.08C119.468 25.78 119.558 25.54 119.738 25.36C119.978 25.12 120.248 25 120.548 25H160.958C161.258 25 161.498 25.12 161.678 25.36C161.918 25.54 162.038 25.78 162.038 26.08V32.92ZM212.751 32.92C212.751 33.22 212.631 33.49 212.391 33.73C212.211 33.91 211.971 34 211.671 34H181.071C180.771 34 180.621 34.15 180.621 34.45V51.28C180.621 51.58 180.771 51.73 181.071 51.73H201.681C201.981 51.73 202.221 51.85 202.401 52.09C202.641 52.27 202.761 52.51 202.761 52.81V59.65C202.761 59.95 202.641 60.22 202.401 60.46C202.221 60.64 201.981 60.73 201.681 60.73H181.071C180.771 60.73 180.621 60.88 180.621 61.18V86.92C180.621 87.22 180.501 87.49 180.261 87.73C180.081 87.91 179.841 88 179.541 88H171.261C170.961 88 170.691 87.91 170.451 87.73C170.271 87.49 170.181 87.22 170.181 86.92V26.08C170.181 25.78 170.271 25.54 170.451 25.36C170.691 25.12 170.961 25 171.261 25H211.671C211.971 25 212.211 25.12 212.391 25.36C212.631 25.54 212.751 25.78 212.751 26.08V32.92Z" fill="white"/>
</svg>

After

Width:  |  Height:  |  Size: 2.4 KiB

+3
View File
@@ -0,0 +1,3 @@
<svg width="65" height="65" viewBox="0 0 65 65" fill="none" xmlns="http://www.w3.org/2000/svg">
<rect width="65" height="65" rx="32.5" fill="#CDCDCD"/>
</svg>

After

Width:  |  Height:  |  Size: 159 B

+3
View File
@@ -0,0 +1,3 @@
<svg width="65" height="65" viewBox="0 0 65 65" fill="none" xmlns="http://www.w3.org/2000/svg">
<rect width="65" height="65" rx="32.5" fill="#2CE9A4"/>
</svg>

After

Width:  |  Height:  |  Size: 159 B

+4
View File
@@ -0,0 +1,4 @@
<svg width="270" height="110" viewBox="0 0 270 110" fill="none" xmlns="http://www.w3.org/2000/svg">
<rect width="270" height="110" rx="55" fill="#FF8989"/>
<path d="M84.9 88.9C80.4 88.9 76.41 88 72.93 86.2C69.45 84.34 66.75 81.73 64.83 78.37C62.97 75.01 62.04 71.14 62.04 66.76V46.24C62.04 41.92 63 38.11 64.92 34.81C66.84 31.45 69.51 28.87 72.93 27.07C76.41 25.21 80.4 24.28 84.9 24.28C89.46 24.28 93.45 25.21 96.87 27.07C100.35 28.87 103.05 31.45 104.97 34.81C106.89 38.11 107.85 41.92 107.85 46.24V66.76C107.85 71.14 106.89 75.01 104.97 78.37C103.05 81.73 100.35 84.34 96.87 86.2C93.45 88 89.46 88.9 84.9 88.9ZM84.9 79.9C88.68 79.9 91.71 78.73 93.99 76.39C96.27 74.05 97.41 70.96 97.41 67.12V46.15C97.41 42.25 96.27 39.13 93.99 36.79C91.71 34.45 88.68 33.28 84.9 33.28C81.18 33.28 78.18 34.45 75.9 36.79C73.62 39.13 72.48 42.25 72.48 46.15V67.12C72.48 70.96 73.62 74.05 75.9 76.39C78.18 78.73 81.18 79.9 84.9 79.9ZM162.038 32.92C162.038 33.22 161.918 33.49 161.678 33.73C161.498 33.91 161.258 34 160.958 34H130.358C130.058 34 129.908 34.15 129.908 34.45V51.28C129.908 51.58 130.058 51.73 130.358 51.73H150.968C151.268 51.73 151.508 51.85 151.688 52.09C151.928 52.27 152.048 52.51 152.048 52.81V59.65C152.048 59.95 151.928 60.22 151.688 60.46C151.508 60.64 151.268 60.73 150.968 60.73H130.358C130.058 60.73 129.908 60.88 129.908 61.18V86.92C129.908 87.22 129.788 87.49 129.548 87.73C129.368 87.91 129.128 88 128.828 88H120.548C120.248 88 119.978 87.91 119.738 87.73C119.558 87.49 119.468 87.22 119.468 86.92V26.08C119.468 25.78 119.558 25.54 119.738 25.36C119.978 25.12 120.248 25 120.548 25H160.958C161.258 25 161.498 25.12 161.678 25.36C161.918 25.54 162.038 25.78 162.038 26.08V32.92ZM212.751 32.92C212.751 33.22 212.631 33.49 212.391 33.73C212.211 33.91 211.971 34 211.671 34H181.071C180.771 34 180.621 34.15 180.621 34.45V51.28C180.621 51.58 180.771 51.73 181.071 51.73H201.681C201.981 51.73 202.221 51.85 202.401 52.09C202.641 52.27 202.761 52.51 202.761 52.81V59.65C202.761 59.95 202.641 60.22 202.401 60.46C202.221 60.64 201.981 60.73 201.681 60.73H181.071C180.771 60.73 180.621 60.88 180.621 61.18V86.92C180.621 87.22 180.501 87.49 180.261 87.73C180.081 87.91 179.841 88 179.541 88H171.261C170.961 88 170.691 87.91 170.451 87.73C170.271 87.49 170.181 87.22 170.181 86.92V26.08C170.181 25.78 170.271 25.54 170.451 25.36C170.691 25.12 170.961 25 171.261 25H211.671C211.971 25 212.211 25.12 212.391 25.36C212.631 25.54 212.751 25.78 212.751 26.08V32.92Z" fill="white"/>
</svg>

After

Width:  |  Height:  |  Size: 2.4 KiB

+4
View File
@@ -0,0 +1,4 @@
<svg width="270" height="110" viewBox="0 0 270 110" fill="none" xmlns="http://www.w3.org/2000/svg">
<rect width="270" height="110" rx="55" fill="#41DBA2"/>
<path d="M104.9 88.9C100.4 88.9 96.41 88 92.93 86.2C89.45 84.34 86.75 81.73 84.83 78.37C82.97 75.01 82.04 71.14 82.04 66.76V46.24C82.04 41.92 83 38.11 84.92 34.81C86.84 31.45 89.51 28.87 92.93 27.07C96.41 25.21 100.4 24.28 104.9 24.28C109.46 24.28 113.45 25.21 116.87 27.07C120.35 28.87 123.05 31.45 124.97 34.81C126.89 38.11 127.85 41.92 127.85 46.24V66.76C127.85 71.14 126.89 75.01 124.97 78.37C123.05 81.73 120.35 84.34 116.87 86.2C113.45 88 109.46 88.9 104.9 88.9ZM104.9 79.9C108.68 79.9 111.71 78.73 113.99 76.39C116.27 74.05 117.41 70.96 117.41 67.12V46.15C117.41 42.25 116.27 39.13 113.99 36.79C111.71 34.45 108.68 33.28 104.9 33.28C101.18 33.28 98.18 34.45 95.9 36.79C93.62 39.13 92.48 42.25 92.48 46.15V67.12C92.48 70.96 93.62 74.05 95.9 76.39C98.18 78.73 101.18 79.9 104.9 79.9ZM176.098 26.08C176.098 25.78 176.188 25.54 176.368 25.36C176.608 25.12 176.878 25 177.178 25H185.458C185.758 25 185.998 25.12 186.178 25.36C186.418 25.54 186.538 25.78 186.538 26.08V86.92C186.538 87.22 186.418 87.49 186.178 87.73C185.998 87.91 185.758 88 185.458 88H177.448C176.848 88 176.428 87.76 176.188 87.28L150.268 44.8C150.148 44.62 150.028 44.56 149.908 44.62C149.788 44.62 149.728 44.74 149.728 44.98L149.908 86.92C149.908 87.22 149.788 87.49 149.548 87.73C149.368 87.91 149.128 88 148.828 88H140.548C140.248 88 139.978 87.91 139.738 87.73C139.558 87.49 139.468 87.22 139.468 86.92V26.08C139.468 25.78 139.558 25.54 139.738 25.36C139.978 25.12 140.248 25 140.548 25H148.558C149.158 25 149.578 25.24 149.818 25.72L175.648 68.2C175.768 68.38 175.888 68.47 176.008 68.47C176.128 68.41 176.188 68.26 176.188 68.02L176.098 26.08Z" fill="white"/>
</svg>

After

Width:  |  Height:  |  Size: 1.8 KiB

+8
View File
@@ -0,0 +1,8 @@
<svg width="26" height="26" viewBox="0 0 26 26" fill="none" xmlns="http://www.w3.org/2000/svg">
<mask id="mask0_806_67" style="mask-type:alpha" maskUnits="userSpaceOnUse" x="0" y="0" width="26" height="26">
<rect width="26" height="26" fill="#D9D9D9"/>
</mask>
<g mask="url(#mask0_806_67)">
<path d="M20.5833 20.5833H8.66663C8.07079 20.5833 7.56072 20.3712 7.13642 19.9469C6.71211 19.5226 6.49996 19.0125 6.49996 18.4166V3.24998C6.49996 2.65415 6.71211 2.14408 7.13642 1.71977C7.56072 1.29547 8.07079 1.08331 8.66663 1.08331H16.25L22.75 7.58331V18.4166C22.75 19.0125 22.5378 19.5226 22.1135 19.9469C21.6892 20.3712 21.1791 20.5833 20.5833 20.5833ZM15.1666 8.66665V3.24998H8.66663V18.4166H20.5833V8.66665H15.1666ZM4.33329 24.9166C3.73746 24.9166 3.22739 24.7045 2.80308 24.2802C2.37878 23.8559 2.16663 23.3458 2.16663 22.75V7.58331H4.33329V22.75H16.25V24.9166H4.33329Z" fill="#2C4053"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 898 B

+8
View File
@@ -0,0 +1,8 @@
<svg width="32" height="32" viewBox="0 0 32 32" fill="none" xmlns="http://www.w3.org/2000/svg">
<mask id="mask0_806_37" style="mask-type:alpha" maskUnits="userSpaceOnUse" x="0" y="0" width="32" height="32">
<rect width="32" height="32" fill="#D9D9D9"/>
</mask>
<g mask="url(#mask0_806_37)">
<path d="M9.55556 21.3333C10.6 21.3333 11.6167 21.45 12.6056 21.6833C13.5944 21.9166 14.5778 22.2666 15.5556 22.7333V9.59998C14.6444 9.06665 13.6778 8.66665 12.6556 8.39998C11.6333 8.13331 10.6 7.99998 9.55556 7.99998C8.75556 7.99998 7.96112 8.07776 7.17223 8.23331C6.38334 8.38887 5.62223 8.6222 4.8889 8.93331V22.1333C5.66667 21.8666 6.4389 21.6666 7.20556 21.5333C7.97223 21.4 8.75556 21.3333 9.55556 21.3333ZM18.2222 22.7333C19.2 22.2666 20.1833 21.9166 21.1722 21.6833C22.1611 21.45 23.1778 21.3333 24.2222 21.3333C25.0222 21.3333 25.8056 21.4 26.5722 21.5333C27.3389 21.6666 28.1111 21.8666 28.8889 22.1333V8.93331C28.1556 8.6222 27.3944 8.38887 26.6056 8.23331C25.8167 8.07776 25.0222 7.99998 24.2222 7.99998C23.1778 7.99998 22.1444 8.13331 21.1222 8.39998C20.1 8.66665 19.1333 9.06665 18.2222 9.59998V22.7333ZM16.8889 26.6666C15.8222 25.8222 14.6667 25.1666 13.4222 24.7C12.1778 24.2333 10.8889 24 9.55556 24C8.62223 24 7.70556 24.1222 6.80556 24.3666C5.90556 24.6111 5.04445 24.9555 4.22223 25.4C3.75556 25.6444 3.30556 25.6333 2.87223 25.3666C2.4389 25.1 2.22223 24.7111 2.22223 24.2V8.13331C2.22223 7.88887 2.28334 7.65554 2.40556 7.43331C2.52778 7.21109 2.71112 7.04442 2.95556 6.93331C3.97778 6.39998 5.04445 5.99998 6.15556 5.73331C7.26667 5.46665 8.40001 5.33331 9.55556 5.33331C10.8444 5.33331 12.1056 5.49998 13.3389 5.83331C14.5722 6.16665 15.7556 6.66665 16.8889 7.33331C18.0222 6.66665 19.2056 6.16665 20.4389 5.83331C21.6722 5.49998 22.9333 5.33331 24.2222 5.33331C25.3778 5.33331 26.5111 5.46665 27.6222 5.73331C28.7333 5.99998 29.8 6.39998 30.8222 6.93331C31.0667 7.04442 31.25 7.21109 31.3722 7.43331C31.4944 7.65554 31.5556 7.88887 31.5556 8.13331V24.2C31.5556 24.7111 31.3389 25.1 30.9056 25.3666C30.4722 25.6333 30.0222 25.6444 29.5556 25.4C28.7333 24.9555 27.8722 24.6111 26.9722 24.3666C26.0722 24.1222 25.1556 24 24.2222 24C22.8889 24 21.6 24.2333 20.3556 24.7C19.1111 25.1666 17.9556 25.8222 16.8889 26.6666Z" fill="#2C4053"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.2 KiB

+3
View File
@@ -0,0 +1,3 @@
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M6.49165 0.360356C6.72538 0.591162 6.85668 0.90416 6.85668 1.23052C6.85668 1.55688 6.72538 1.86988 6.49165 2.10068L4.2562 4.30748H14.0259C15.9986 4.30748 17.927 4.88495 19.5672 5.96687C21.2074 7.04879 22.4858 8.58657 23.2408 10.3857C23.9957 12.1849 24.1932 14.1647 23.8083 16.0746C23.4235 17.9846 22.4735 19.7391 21.0786 21.1161C19.6837 22.4931 17.9065 23.4309 15.9717 23.8108C14.0369 24.1907 12.0315 23.9957 10.2089 23.2505C8.38639 22.5053 6.82864 21.2432 5.73267 19.624C4.6367 18.0048 4.05173 16.1011 4.05173 14.1537C4.05173 13.8273 4.18308 13.5143 4.4169 13.2834C4.65071 13.0526 4.96783 12.923 5.29849 12.923C5.62916 12.923 5.94628 13.0526 6.18009 13.2834C6.4139 13.5143 6.54526 13.8273 6.54526 14.1537C6.54526 15.6143 6.98399 17.042 7.80597 18.2565C8.62795 19.4709 9.79626 20.4174 11.1632 20.9763C12.5301 21.5352 14.0342 21.6815 15.4853 21.3965C16.9363 21.1116 18.2693 20.4083 19.3154 19.3755C20.3616 18.3427 21.0741 17.0269 21.3627 15.5944C21.6514 14.1619 21.5032 12.6771 20.937 11.3277C20.3708 9.97836 19.412 8.82503 18.1819 8.01359C16.9517 7.20215 15.5054 6.76904 14.0259 6.76904H4.2562L6.49165 8.97583C6.71876 9.20796 6.84442 9.51886 6.84158 9.84157C6.83874 10.1643 6.70762 10.473 6.47646 10.7012C6.2453 10.9294 5.9326 11.0588 5.6057 11.0616C5.2788 11.0644 4.96386 10.9404 4.72872 10.7162L0.365036 6.40842C0.131304 6.17762 0 5.86462 0 5.53826C0 5.2119 0.131304 4.8989 0.365036 4.6681L4.72872 0.360356C4.96252 0.12962 5.27959 0 5.61018 0C5.94078 0 6.25784 0.12962 6.49165 0.360356Z" fill="#2C4053"/>
</svg>

After

Width:  |  Height:  |  Size: 1.6 KiB

+3
View File
@@ -0,0 +1,3 @@
<svg width="25" height="25" viewBox="0 0 25 25" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M3.61832 0C2.65868 0 1.73835 0.381215 1.05978 1.05978C0.381215 1.73835 0 2.65868 0 3.61832V20.0652C0 21.0249 0.381215 21.9452 1.05978 22.6238C1.73835 23.3023 2.65868 23.6836 3.61832 23.6836H9.20896C9.19911 23.4209 9.22658 23.1582 9.29053 22.9033L9.58921 21.7099H5.92089V14.8022C5.92089 14.5405 6.02486 14.2895 6.20992 14.1044C6.39498 13.9194 6.64598 13.8154 6.9077 13.8154H15.5956L17.4837 11.9273C17.2521 11.8705 17.0144 11.8418 16.7759 11.8418H6.9077C6.12255 11.8418 5.36954 12.1537 4.81435 12.7089C4.25916 13.2641 3.94726 14.0171 3.94726 14.8022V21.7099H3.61832C2.71045 21.7099 1.97363 20.9731 1.97363 20.0652V3.61832C1.97363 2.71045 2.71045 1.97363 3.61832 1.97363H5.26301V5.59195C5.26301 5.98072 5.33959 6.36569 5.48836 6.72486C5.63714 7.08404 5.8552 7.4104 6.13011 7.6853C6.6853 8.24049 7.4383 8.55239 8.22346 8.55239H14.1443C14.5331 8.55239 14.9181 8.47582 15.2773 8.32704C15.6364 8.17827 15.9628 7.9602 16.2377 7.6853C16.5126 7.4104 16.7307 7.08404 16.8794 6.72486C17.0282 6.36569 17.1048 5.98072 17.1048 5.59195V2.00389C17.5758 2.08284 18.0153 2.30652 18.3574 2.64861L21.0349 5.32617C21.4678 5.75774 21.7099 6.34325 21.7099 6.95507V9.21948C21.8032 9.2131 21.8967 9.21003 21.9902 9.21027H21.9928C22.5678 9.21027 23.1441 9.32474 23.6836 9.55368V6.95639C23.6837 6.39462 23.5731 5.83833 23.3582 5.3193C23.1433 4.80028 22.8282 4.32868 22.431 3.93147L19.7534 1.25391C19.3563 0.856429 18.8848 0.541099 18.3657 0.325946C17.8467 0.110792 17.2903 3.34626e-05 16.7285 0H3.61832ZM7.23664 5.59195V1.97363H15.1312V5.59195C15.1312 5.85367 15.0272 6.10467 14.8421 6.28973C14.6571 6.4748 14.4061 6.57877 14.1443 6.57877H8.22346C7.96174 6.57877 7.71074 6.4748 7.52567 6.28973C7.34061 6.10467 7.23664 5.85367 7.23664 5.59195ZM21.9928 10.526H21.9902C21.2205 10.526 20.4508 10.8194 19.8652 11.4076L12.0997 19.1732C11.6466 19.6256 11.325 20.1928 11.1694 20.8139L10.5668 23.223C10.5069 23.4627 10.5101 23.7139 10.5761 23.952C10.6421 24.1901 10.7686 24.407 10.9434 24.5817C11.1182 24.7563 11.3352 24.8827 11.5734 24.9485C11.8115 25.0143 12.0626 25.0173 12.3023 24.9572L14.7101 24.3559C15.3317 24.2005 15.8994 23.879 16.3522 23.4257L24.1178 15.6601C24.5387 15.2398 24.8256 14.704 24.9419 14.1206C25.0583 13.5372 24.999 12.9324 24.7715 12.3828C24.544 11.8331 24.1585 11.3633 23.6639 11.0327C23.1693 10.7022 22.5877 10.5259 21.9928 10.526Z" fill="#2C4053"/>
</svg>

After

Width:  |  Height:  |  Size: 2.4 KiB

+3
View File
@@ -0,0 +1,3 @@
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M0 3.66667C0 2.69421 0.386309 1.76158 1.07394 1.07394C1.76158 0.386309 2.69421 1.33214e-07 3.66667 1.33214e-07H16.952C17.5213 -0.000141016 18.085 0.111887 18.611 0.329685C19.1369 0.547482 19.6148 0.86678 20.0173 1.26933L22.7307 3.98267C23.544 4.796 24 5.89867 24 7.048V20.3333C24 21.3058 23.6137 22.2384 22.9261 22.9261C22.2384 23.6137 21.3058 24 20.3333 24H3.66667C2.69421 24 1.76158 23.6137 1.07394 22.9261C0.386309 22.2384 0 21.3058 0 20.3333V3.66667ZM3.66667 2C2.74667 2 2 2.74667 2 3.66667V20.3333C2 21.2533 2.74667 22 3.66667 22H4V15C4 14.2044 4.31607 13.4413 4.87868 12.8787C5.44129 12.3161 6.20435 12 7 12H17C17.7956 12 18.5587 12.3161 19.1213 12.8787C19.6839 13.4413 20 14.2044 20 15V22H20.3333C21.2533 22 22 21.2533 22 20.3333V7.048C22 6.428 21.7547 5.83467 21.316 5.39733L18.6027 2.684C18.2582 2.33896 17.8143 2.11048 17.3333 2.03067V5.66667C17.3333 6.06063 17.2557 6.45074 17.105 6.81472C16.9542 7.17869 16.7332 7.50941 16.4547 7.78799C16.1761 8.06656 15.8454 8.28754 15.4814 8.43831C15.1174 8.58907 14.7273 8.66667 14.3333 8.66667H8.33333C7.53768 8.66667 6.77462 8.3506 6.21201 7.78799C5.6494 7.22538 5.33333 6.46232 5.33333 5.66667V2H3.66667ZM18 22V15C18 14.7348 17.8946 14.4804 17.7071 14.2929C17.5196 14.1054 17.2652 14 17 14H7C6.73478 14 6.48043 14.1054 6.29289 14.2929C6.10536 14.4804 6 14.7348 6 15V22H18ZM7.33333 2V5.66667C7.33333 6.21867 7.78133 6.66667 8.33333 6.66667H14.3333C14.5985 6.66667 14.8529 6.56131 15.0404 6.37377C15.228 6.18624 15.3333 5.93188 15.3333 5.66667V2H7.33333Z" fill="#2C4053"/>
</svg>

After

Width:  |  Height:  |  Size: 1.6 KiB

+3
View File
@@ -0,0 +1,3 @@
<svg width="14" height="14" viewBox="0 0 14 14" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M11.2132 12.6274L6.97054 8.38479L2.7279 12.6274L1.31369 11.2132L5.55633 6.97058L1.31369 2.72794L2.7279 1.31373L6.97054 5.55637L11.2132 1.31373L12.6274 2.72794L8.38475 6.97058L12.6274 11.2132L11.2132 12.6274Z" fill="#000000" stroke="#B8C3CC" stroke-linejoin="round"/>
</svg>

After

Width:  |  Height:  |  Size: 379 B

+184 -172
View File
@@ -1,15 +1,5 @@
<template>
<div>
<div class="row flex sm12 xl12 md12 xs12" style="height: 100vh;">
<div class="flex-center spinner-box mt-4 mb-5">
<fulfilling-bouncing-circle-spinner
:animation-duration="3000"
:color="'#6c7fee'"
:size="60"
>
</fulfilling-bouncing-circle-spinner>
</div>
</div>
</div>
</template>
@@ -17,7 +7,6 @@
import api from '@/data/api/index'
import types from '@/store/modules/download/types'
import { mapActions, mapMutations } from 'vuex'
import { FulfillingBouncingCircleSpinner } from 'epic-spinners'
import { mapFields } from 'vuex-map-fields'
import newDownload from '@/factories/file/downloadFactory'
import newChannel from '@/factories/file/channelFactory'
@@ -27,11 +16,17 @@ import configTable from '@/data/config-table/index'
export default {
name: 'Download',
components: {
FulfillingBouncingCircleSpinner,
},
data: () => {
return {
controllerList: [],
downloadList: [],
format: 'excel',
channel: '',
metaListNew: [],
downloading: false,
fileNums: 0,
count: 0,
}
},
computed: {
@@ -67,6 +62,179 @@ export default {
}
return results
},
writeFiles: async function () {
if (this.metaListNew.length !== 0 && this.downloading === false) {
this.downloading = true
let meta
const metaID = this.metaListNew.pop()
const ret = await api.meta.getByID(metaID)
if (ret.status === 200) {
meta = ret.data[0]
}
if (meta !== undefined) {
this.metaInfo = meta
const channelParamObj = configTable.getModeConfig(meta.device.library_name, meta.parameter_set.MODE).channels
const channelArray = this.channel === 'all' ? JSON.parse(this.metaInfo.channels) : Object.keys(channelParamObj).filter(ele => ele !== 'time')
const channelList = []
// split to different subfile by channel
if (meta.device.library_name.indexOf('Neulive') >= 0) {
if (channelArray.some(el => el >= 256)) {
channelList.push(channelArray.filter(el => (el >= 256 && el <= 259)))
channelList.push(channelArray.filter(el => el < 256))
} else {
channelList.push(channelArray)
}
} else if (meta.device.library_name.indexOf('Elite') >= 0) {
channelList.push(channelArray)
}
while (channelList.length > 0) {
const channels = channelList.pop()
let maxSplitFiles = 1
let fileIndex = 0
// find max raw data need sub file
for (const rawDataIndex of channels) {
const dataLength = meta.raw_data[rawDataIndex].length
maxSplitFiles = Math.max(maxSplitFiles, Math.ceil(meta.raw_data[rawDataIndex].length / dataLength))
meta.raw_data[rawDataIndex] = this.chunkArray(meta.raw_data[rawDataIndex], dataLength)
}
while (fileIndex < maxSplitFiles) {
// create new download info & add channel
if (this.downloadInfo === null) {
this.downloadInfo = newDownload()
}
this.downloadInfo.channel = channels
// download format
this.downloadInfo.format = this.format
// download device and filename
if (meta.device.library_name.indexOf('Neulive') >= 0) {
this.downloadInfo.device = [meta.device.library_name.slice(0, 7), meta.device.library_name.slice(7)]
if (this.downloadInfo.channel.some(el => el >= 256 && el <= 259)) {
this.downloadInfo.filename = meta.name + '-accerlate'
this.downloadInfo.size = parseInt(parseInt(meta.size) / (76 * (maxSplitFiles)))
} else {
this.downloadInfo.filename = meta.name
this.downloadInfo.size = parseInt(meta.size / (maxSplitFiles))
}
} else if (meta.device.library_name.indexOf('Elite') >= 0) {
this.downloadInfo.device = [meta.device.library_name.slice(0, 5), meta.device.library_name.slice(5)]
this.downloadInfo.filename = meta.name
this.downloadInfo.size = parseInt(meta.size / (maxSplitFiles))
}
// create new channel info & get sample rate
for (const channel of this.downloadInfo.channel) {
if (this.downloadInfo.channelInfo[channel] === undefined) {
this.downloadInfo.channelInfo[channel] = newChannel()
this.setSampleRateDownload({ channel: channel })
}
}
// set download ID list
this.clearIDListDownload()
for (const channel of this.downloadInfo.channel) {
this.setIDListDownload({ channel: channel, fileIndex: fileIndex })
}
// if create writer
this.clearStreamDownload()
this.setStreamDownload()
// set Header
if (this.downloadInfo.format !== 'csv-edf') {
await this.setHeaderExport()
}
await this.setTitleExport()
// start download data
let rowIndex = 0
let columnNum = 0
const requestArray = []
console.time('download')
// console.log(this.downloadInfo)
while (rowIndex - 10 < this.downloadInfo.maxRows) {
// console.log('rowIndex < this.downloadInfo.maxRows', rowIndex, this.downloadInfo.maxRows)
for (const channel of this.downloadInfo.channel) {
columnNum = this.downloadInfo.channelInfo[channel].downloadIDList.length
for (const idx in this.downloadInfo.channelInfo[channel].downloadIDList) {
const _idx = parseInt(idx)
if (this.downloadInfo.channelInfo[channel].downloadDataBuffer[idx] === undefined) {
this.downloadInfo.channelInfo[channel].downloadDataBuffer[idx] = []
}
// const rawID = this.downloadInfo.channelInfo[channel].downloadIDList[_idx][rowIndex]
const rawIDList = this.downloadInfo.channelInfo[channel].downloadIDList[_idx].slice(rowIndex, rowIndex + 10)
// console.log(channel, rawIDList)
rawIDList.length > 0 && requestArray.push(api.raw.getAttrByIDs(channel, rawIDList, 'id-channel-size-serial_number-start_time-end_time-data-bytea_data'))
if (rawIDList.length === 0) columnNum -= 1
}
}
const responseArray = await Promise.all(requestArray)
for (const responseIndex in responseArray) {
const response = responseArray[responseIndex]
// console.log('response', response)
const idx = responseIndex % columnNum
for (const data of response.data) {
const timeUnitScale = channelParamObj.time.unit[channelParamObj.time.downloadUnit]
const channelUnitScale = channelParamObj[data.channel]?.unit[channelParamObj[data.channel]?.downloadUnit]
// console.log('data', data)
const bytesData = new Int8Array(data.bytea_data.data)
// console.log('bytesData', bytesData)
const integers = []
for (let i = 0; i < bytesData.length; i += 8) {
// Create a DataView for each 8-byte chunk
const view = new DataView(bytesData.buffer, i, 8)
// Read the integer as BigInt (assuming little-endian byte order)
const integer = view.getBigInt64(0)
integers.push(integer)
}
const newArray = integers.map((ele, index) => {
return (index % 2 === 0)
? String((parseInt(ele) / timeUnitScale).toFixed(Math.log10(timeUnitScale)))
: channelUnitScale ? String((parseInt(ele) / channelUnitScale).toFixed(Math.log10(channelUnitScale))) : ele
})
this.downloadInfo.channelInfo[data.channel].downloadDataBuffer[idx].push(...newArray)
// // console.log('rawArray', rawArray)
// }
}
}
requestArray.length = 0
// console.log('this.downloadInfo.channelInfo', this.downloadInfo.channelInfo)
// console.log('this.downloadInfo.maxRows', this.downloadInfo.maxRows)
await this.setDataExport({ last: (rowIndex >= this.downloadInfo.maxRows - 1) })
rowIndex += 10
}
this.closeWriterDownload()
fileIndex += 1
}
console.timeEnd('download')
}
}
this.count += 1
this.downloading = false
this.$emit('download-finish')
if (this.fileNums === 1) {
this.showToast('Download Finish', {
position: 'bottom-right',
})
} else {
this.showToast(`${this.count} / ${this.fileNums} Finish`, {
position: 'bottom-right',
})
}
}
},
...mapActions('download',
[
types.raw.rawDataByID,
@@ -93,169 +261,13 @@ export default {
async mounted () {
await this.getControllerList()
// TODO authorization
const format = this.$route.params.format.split('-')[0]
const allChannel = this.$route.params.format.split('-')[1]
this.metaList = this.$route.params.metaList.split('-')
const sd = this.$route.params.sd
while (this.metaList.length !== 0) {
let meta
const metaID = this.metaList.pop()
const ret = await api.meta.getByID(metaID)
if (ret.status === 200) {
meta = ret.data[0]
}
if (meta !== undefined) {
this.metaInfo = meta
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 = []
// split to different subfile by channel
if (meta.device.library_name.indexOf('Neulive') >= 0) {
if (channelArray.some(el => el >= 256)) {
channelList.push(channelArray.filter(el => (el >= 256 && el <= 259)))
channelList.push(channelArray.filter(el => el < 256))
} else {
channelList.push(channelArray)
}
} else if (meta.device.library_name.indexOf('Elite') >= 0) {
channelList.push(channelArray)
}
while (channelList.length > 0) {
const channels = channelList.pop()
let maxSplitFiles = 1
let fileIndex = 0
// find max raw data need sub file
for (const rawDataIndex of channels) {
const dataLength = meta.raw_data[rawDataIndex].length
maxSplitFiles = Math.max(maxSplitFiles, Math.ceil(meta.raw_data[rawDataIndex].length / dataLength))
meta.raw_data[rawDataIndex] = this.chunkArray(meta.raw_data[rawDataIndex], dataLength)
}
while (fileIndex < maxSplitFiles) {
// create new download info & add channel
if (this.downloadInfo === null) {
this.downloadInfo = newDownload()
}
this.downloadInfo.channel = channels
// download format
this.downloadInfo.format = format
// download device and filename
if (meta.device.library_name.indexOf('Neulive') >= 0) {
this.downloadInfo.device = [meta.device.library_name.slice(0, 7), meta.device.library_name.slice(7)]
if (this.downloadInfo.channel.some(el => el >= 256 && el <= 259)) {
this.downloadInfo.filename = meta.name + '-accerlate'
this.downloadInfo.filename += (sd !== undefined) ? '-sd' : ''
this.downloadInfo.size = parseInt(parseInt(meta.size) / (76 * (maxSplitFiles)))
} else {
this.downloadInfo.filename = meta.name
this.downloadInfo.filename += (sd !== undefined) ? '-sd' : ''
this.downloadInfo.size = parseInt(meta.size / (maxSplitFiles))
}
} else if (meta.device.library_name.indexOf('Elite') >= 0) {
this.downloadInfo.device = [meta.device.library_name.slice(0, 5), meta.device.library_name.slice(5)]
this.downloadInfo.filename = meta.name
this.downloadInfo.size = parseInt(meta.size / (maxSplitFiles))
}
// create new channel info & get sample rate
for (const channel of this.downloadInfo.channel) {
if (this.downloadInfo.channelInfo[channel] === undefined) {
this.downloadInfo.channelInfo[channel] = newChannel()
this.setSampleRateDownload({ channel: channel })
}
}
// set download ID list
this.clearIDListDownload()
for (const channel of this.downloadInfo.channel) {
this.setIDListDownload({ channel: channel, fileIndex: fileIndex })
}
// if create writer
this.clearStreamDownload()
this.setStreamDownload()
// set Header
if (this.downloadInfo.format !== 'csv-edf') {
await this.setHeaderExport()
}
await this.setTitleExport()
// start download data
let rowIndex = 0
let columnNum = 0
const requestArray = []
console.time('download')
// console.log(this.downloadInfo)
while (rowIndex - 10 < this.downloadInfo.maxRows) {
// console.log('rowIndex < this.downloadInfo.maxRows', rowIndex, this.downloadInfo.maxRows)
for (const channel of this.downloadInfo.channel) {
columnNum = this.downloadInfo.channelInfo[channel].downloadIDList.length
for (const idx in this.downloadInfo.channelInfo[channel].downloadIDList) {
const _idx = parseInt(idx)
if (this.downloadInfo.channelInfo[channel].downloadDataBuffer[idx] === undefined) {
this.downloadInfo.channelInfo[channel].downloadDataBuffer[idx] = []
}
// const rawID = this.downloadInfo.channelInfo[channel].downloadIDList[_idx][rowIndex]
const rawIDList = this.downloadInfo.channelInfo[channel].downloadIDList[_idx].slice(rowIndex, rowIndex + 10)
// console.log(channel, rawIDList)
rawIDList.length > 0 && requestArray.push(api.raw.getAttrByIDs(channel, rawIDList, 'id-channel-size-serial_number-start_time-end_time-data'))
if (rawIDList.length === 0) columnNum -= 1
}
}
const responseArray = await Promise.all(requestArray)
// console.log('responseArray', responseArray)
for (const responseIndex in responseArray) {
const response = responseArray[responseIndex]
// console.log('response', response)
const idx = responseIndex % columnNum
for (const data of response.data) {
const timeUnitScale = channelParamObj.time.unit[channelParamObj.time.downloadUnit]
const channelUnitScale = channelParamObj[data.channel]?.unit[channelParamObj[data.channel]?.downloadUnit]
// console.log('data', data)
const dataArray = data.data.split('"***"').slice(0, -1)
// console.log('dataArray', dataArray)
for (const raw of dataArray) {
const rawArray = raw.split(' ')
const newArray = rawArray[0] === '' ? [] : rawArray.map((ele, index) => {
// console.log((parseInt(ele) / timeUnitScale).toFixed(Math.log10(timeUnitScale)))
return (index % 2 === 0) ? String((parseInt(ele) / timeUnitScale).toFixed(Math.log10(timeUnitScale))) : channelUnitScale ? String((parseInt(ele) / channelUnitScale).toFixed(Math.log10(channelUnitScale))) : ele
})
this.downloadInfo.channelInfo[data.channel].downloadDataBuffer[idx].push(...newArray)
// console.log('rawArray', rawArray)
}
}
}
requestArray.length = 0
// console.log('this.downloadInfo.channelInfo', this.downloadInfo.channelInfo)
// console.log('this.downloadInfo.maxRows', this.downloadInfo.maxRows)
await this.setDataExport({ last: (rowIndex >= this.downloadInfo.maxRows - 1) })
rowIndex += 10
}
this.closeWriterDownload()
fileIndex += 1
}
console.timeEnd('download')
}
}
}
await new Promise(resolve => setTimeout(resolve, 2000)) // sleep 2s prevent window close
window.close()
// await new Promise(resolve => setTimeout(resolve, 2000)) // sleep 2s prevent window close
// window.close()
setInterval(this.writeFiles, 1000)
},
destroyed () {
this.pageMqttUnSub()
// this.pageMqttUnSub()
},
}
</script>
+166 -170
View File
@@ -1,18 +1,8 @@
<template>
<div>
<div class="row flex sm12 xl12 md12 xs12" style="height: 100vh;">
<div class="flex-center spinner-box mt-4 mb-5">
<fulfilling-bouncing-circle-spinner
:animation-duration="3000"
:color="'#6c7fee'"
:size="60"
>
</fulfilling-bouncing-circle-spinner>
<progress-modal
:ref="'progressModalRef'"
/>
</div>
</div>
<progress-modal
:ref="'progressModalRef'"
/>
</div>
</template>
@@ -20,7 +10,6 @@
import api from '@/data/api/index'
import types from '@/store/modules/download/types'
import { mapActions, mapMutations } from 'vuex'
import { FulfillingBouncingCircleSpinner } from 'epic-spinners'
import { mapFields } from 'vuex-map-fields'
import newDownload from '@/factories/file/downloadFactory'
import newChannel from '@/factories/file/channelFactory'
@@ -31,12 +20,18 @@ import configTable from '@/data/config-table/index'
export default {
name: 'DownloadOffline',
components: {
FulfillingBouncingCircleSpinner,
progressModal,
},
data: () => {
return {
controllerList: [],
downloadList: [],
format: 'excel',
channel: '',
metaListNew: [],
downloading: false,
fileNums: 0,
count: 0,
}
},
computed: {
@@ -72,6 +67,161 @@ export default {
}
return results
},
writeFiles: async function () {
if (this.metaListNew.length !== 0 && this.downloading === false) {
let meta
const metaID = this.metaListNew.pop()
const ret = await api.meta.getByID(metaID)
if (ret.status === 200) {
meta = ret.data[0]
}
if (meta !== undefined) {
this.metaInfo = meta
const channelParamObj = configTable.getModeConfig(meta.device.library_name, meta.parameter_set.MODE).channels
const channelArray = this.channel === 'all' ? JSON.parse(this.metaInfo.channels) : Object.keys(channelParamObj).filter(ele => ele !== 'time')
const channelList = []
if (meta.device.library_name.indexOf('Neulive') >= 0) {
if (channelArray.some(el => el >= 256)) {
channelList.push(channelArray.filter(el => (el >= 256 && el <= 259)))
channelList.push(channelArray.filter(el => el < 256))
} else {
channelList.push(channelArray)
}
} else if (meta.device.library_name.indexOf('Elite') >= 0) {
channelList.push(channelArray)
}
this.$refs.progressModalRef.show()
while (channelList.length > 0) {
const channels = channelList.pop()
let maxSplitFiles = 1
let fileIndex = 0
// find max raw data need sub file
for (const rawDataIndex of Object.keys(meta.raw_data)) {
let dataLength = 0
if (rawDataIndex >= 256) {
dataLength = meta.raw_data[rawDataIndex].length
} else {
dataLength = 10000
}
maxSplitFiles = Math.max(maxSplitFiles, Math.ceil(meta.raw_data[rawDataIndex].length / dataLength))
meta.raw_data[rawDataIndex] = this.chunkArray(meta.raw_data[rawDataIndex], dataLength)
}
while (fileIndex < maxSplitFiles) {
if (this.downloadInfo === null) {
this.downloadInfo = newDownload()
}
this.downloadInfo.channel = channels
// download format
this.downloadInfo.format = this.format
// download device and filename
if (meta.device.library_name.indexOf('Neulive') >= 0) {
this.downloadInfo.device = [meta.device.library_name.slice(0, 7), meta.device.library_name.slice(7)]
if (this.downloadInfo.channel.some(el => el >= 256 && el <= 259)) {
this.downloadInfo.filename = meta.name + '-accerlate-' + this.format
this.downloadInfo.size = parseInt(parseInt(meta.size) / 76)
} else {
this.downloadInfo.filename = meta.name + '-' + this.format
this.downloadInfo.size = parseInt(meta.size)
}
} else if (meta.device.library_name.indexOf('Elite') >= 0) {
this.downloadInfo.device = [meta.device.library_name.slice(0, 5), meta.device.library_name.slice(5)]
this.downloadInfo.filename = meta.name + '-' + (fileIndex + 1).toString()
this.downloadInfo.size = parseInt(meta.size)
}
this.$refs.progressModalRef.setTitle(this.downloadInfo.filename)
// get sampleRate && downloadList
for (const channel of this.downloadInfo.channel) {
if (this.downloadInfo.channelInfo[channel] === undefined) {
this.downloadInfo.channelInfo[channel] = newChannel()
this.setSampleRateDownload({ channel: channel })
}
}
this.clearIDListDownload()
for (const channel of this.downloadInfo.channel) {
this.setIDListDownload({ channel: channel, fileIndex: fileIndex })
}
// start download data
fileIndex += 1
let rowIndex = 0
let columnNum = 0
const requestArray = []
console.time('download')
while (rowIndex - 10 < this.downloadInfo.maxRows) {
this.$refs.progressModalRef.setValue(parseInt((rowIndex / this.downloadInfo.maxRows) * 100))
// console.log('rowIndex < this.downloadInfo.maxRows', rowIndex, this.downloadInfo.maxRows)
for (const channel of this.downloadInfo.channel) {
columnNum = this.downloadInfo.channelInfo[channel].downloadIDList.length
for (const idx in this.downloadInfo.channelInfo[channel].downloadIDList) {
const _idx = parseInt(idx)
if (this.downloadInfo.channelInfo[channel].downloadDataBuffer[idx] === undefined) {
this.downloadInfo.channelInfo[channel].downloadDataBuffer[idx] = []
}
// const rawID = this.downloadInfo.channelInfo[channel].downloadIDList[_idx][rowIndex]
const rawIDList = this.downloadInfo.channelInfo[channel].downloadIDList[_idx].slice(rowIndex, rowIndex + 10)
// console.log(channel, rawIDList)
rawIDList.length > 0 && requestArray.push(api.raw.getAttrByIDs(channel, rawIDList, 'id-channel-size-serial_number-start_time-end_time-data-bytea_data'))
if (rawIDList.length === 0) columnNum -= 1
}
}
const responseArray = await Promise.all(requestArray)
// console.log('responseArray', responseArray)
for (const responseIndex in responseArray) {
const response = responseArray[responseIndex]
// console.log('response', response)
const idx = responseIndex % columnNum
// console.log('response', response)
for (const data of response.data) {
const timeUnitScale = channelParamObj.time.unit[channelParamObj.time.downloadUnit]
const channelUnitScale = channelParamObj[data.channel]?.unit[channelParamObj[data.channel]?.downloadUnit]
// console.log('data', data)
const bytesData = new Int8Array(data.bytea_data.data)
// console.log('bytesData', bytesData)
const integers = []
for (let i = 0; i < bytesData.length; i += 8) {
// Create a DataView for each 8-byte chunk
const view = new DataView(bytesData.buffer, i, 8)
// Read the integer as BigInt (assuming little-endian byte order)
const integer = view.getBigInt64(0)
integers.push(integer)
}
const newArray = integers.map((ele, index) => {
return (index % 2 === 0)
? String((parseInt(ele) / timeUnitScale).toFixed(Math.log10(timeUnitScale)))
: channelUnitScale ? String((parseInt(ele) / channelUnitScale).toFixed(Math.log10(channelUnitScale))) : ele
})
this.downloadInfo.channelInfo[data.channel].downloadDataBuffer[idx].push(...newArray)
// // console.log('rawArray', rawArray)
// }
}
}
requestArray.length = 0
// console.log('this.downloadInfo.channelInfo', this.downloadInfo.channelInfo)
// console.log('this.downloadInfo.maxRows', this.downloadInfo.maxRows)
// await this.setDataExport({ last: (rowIndex >= this.downloadInfo.maxRows - 1) })
rowIndex += 10
}
await this.setAllExport({ last: (rowIndex >= this.downloadInfo.maxRows - 1) })
this.$refs.progressModalRef.setValue(100)
}
}
}
}
},
...mapActions('download',
[
types.raw.rawDataByID,
@@ -97,161 +247,7 @@ export default {
},
async mounted () {
await this.getControllerList()
// TODO authorization
const format = this.$route.params.format.split('-')[0]
const allChannel = this.$route.params.format.split('-')[1]
this.metaList = this.$route.params.metaList.split('-')
const sd = this.$route.params.sd
while (this.metaList.length !== 0) {
let meta
const metaID = this.metaList.pop()
const ret = await api.meta.getByID(metaID)
if (ret.status === 200) {
meta = ret.data[0]
}
if (meta !== undefined) {
this.metaInfo = meta
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 = []
if (meta.device.library_name.indexOf('Neulive') >= 0) {
if (channelArray.some(el => el >= 256)) {
channelList.push(channelArray.filter(el => (el >= 256 && el <= 259)))
channelList.push(channelArray.filter(el => el < 256))
} else {
channelList.push(channelArray)
}
} else if (meta.device.library_name.indexOf('Elite') >= 0) {
channelList.push(channelArray)
}
this.$refs.progressModalRef.show()
while (channelList.length > 0) {
const channels = channelList.pop()
let maxSplitFiles = 1
let fileIndex = 0
// find max raw data need sub file
for (const rawDataIndex of Object.keys(meta.raw_data)) {
let dataLength = 0
if (rawDataIndex >= 256) {
dataLength = meta.raw_data[rawDataIndex].length
} else {
dataLength = 10000
}
maxSplitFiles = Math.max(maxSplitFiles, Math.ceil(meta.raw_data[rawDataIndex].length / dataLength))
meta.raw_data[rawDataIndex] = this.chunkArray(meta.raw_data[rawDataIndex], dataLength)
}
while (fileIndex < maxSplitFiles) {
if (this.downloadInfo === null) {
this.downloadInfo = newDownload()
}
this.downloadInfo.channel = channels
// download format
this.downloadInfo.format = format
// download device and filename
if (meta.device.library_name.indexOf('Neulive') >= 0) {
this.downloadInfo.device = [meta.device.library_name.slice(0, 7), meta.device.library_name.slice(7)]
if (this.downloadInfo.channel.some(el => el >= 256 && el <= 259)) {
this.downloadInfo.filename = meta.name + '-accerlate-' + format
this.downloadInfo.filename += (sd !== undefined) ? '-sd' : ''
this.downloadInfo.size = parseInt(parseInt(meta.size) / 76)
} else {
this.downloadInfo.filename = meta.name + '-' + format
this.downloadInfo.filename += (sd !== undefined) ? '-sd' : ''
this.downloadInfo.size = parseInt(meta.size)
}
} else if (meta.device.library_name.indexOf('Elite') >= 0) {
this.downloadInfo.device = [meta.device.library_name.slice(0, 5), meta.device.library_name.slice(5)]
this.downloadInfo.filename = meta.name + '-' + (fileIndex + 1).toString()
this.downloadInfo.size = parseInt(meta.size)
}
this.$refs.progressModalRef.setTitle(this.downloadInfo.filename)
// get sampleRate && downloadList
for (const channel of this.downloadInfo.channel) {
if (this.downloadInfo.channelInfo[channel] === undefined) {
this.downloadInfo.channelInfo[channel] = newChannel()
this.setSampleRateDownload({ channel: channel })
}
}
this.clearIDListDownload()
for (const channel of this.downloadInfo.channel) {
this.setIDListDownload({ channel: channel, fileIndex: fileIndex })
}
// start download data
fileIndex += 1
let rowIndex = 0
let columnNum = 0
const requestArray = []
console.time('download')
while (rowIndex - 10 < this.downloadInfo.maxRows) {
this.$refs.progressModalRef.setValue(parseInt((rowIndex / this.downloadInfo.maxRows) * 100))
// console.log('rowIndex < this.downloadInfo.maxRows', rowIndex, this.downloadInfo.maxRows)
for (const channel of this.downloadInfo.channel) {
columnNum = this.downloadInfo.channelInfo[channel].downloadIDList.length
for (const idx in this.downloadInfo.channelInfo[channel].downloadIDList) {
const _idx = parseInt(idx)
if (this.downloadInfo.channelInfo[channel].downloadDataBuffer[idx] === undefined) {
this.downloadInfo.channelInfo[channel].downloadDataBuffer[idx] = []
}
// const rawID = this.downloadInfo.channelInfo[channel].downloadIDList[_idx][rowIndex]
const rawIDList = this.downloadInfo.channelInfo[channel].downloadIDList[_idx].slice(rowIndex, rowIndex + 10)
// console.log(channel, rawIDList)
rawIDList.length > 0 && requestArray.push(api.raw.getAttrByIDs(channel, rawIDList, 'id-channel-size-serial_number-start_time-end_time-data'))
if (rawIDList.length === 0) columnNum -= 1
}
}
const responseArray = await Promise.all(requestArray)
// console.log('responseArray', responseArray)
for (const responseIndex in responseArray) {
const response = responseArray[responseIndex]
// console.log('response', response)
const idx = responseIndex % columnNum
// console.log('response', response)
for (const data of response.data) {
const timeUnitScale = channelParamObj.time.unit[channelParamObj.time.downloadUnit]
const channelUnitScale = channelParamObj[data.channel]?.unit[channelParamObj[data.channel]?.downloadUnit]
// console.log('data', data)
const dataArray = data.data.split('"***"').slice(0, -1)
// console.log('dataArray', dataArray)
for (const raw of dataArray) {
const rawArray = raw.split(' ')
const newArray = rawArray[0] === '' ? [] : rawArray.map((ele, index) => {
return (index % 2 === 0) ? String((parseInt(ele) / timeUnitScale).toFixed(Math.log10(timeUnitScale))) : channelUnitScale ? String((parseInt(ele) / channelUnitScale).toFixed(Math.log10(channelUnitScale))) : ele
})
this.downloadInfo.channelInfo[data.channel].downloadDataBuffer[idx].push(...newArray)
// console.log('rawArray', rawArray)
}
}
}
requestArray.length = 0
// console.log('this.downloadInfo.channelInfo', this.downloadInfo.channelInfo)
// console.log('this.downloadInfo.maxRows', this.downloadInfo.maxRows)
// await this.setDataExport({ last: (rowIndex >= this.downloadInfo.maxRows - 1) })
rowIndex += 10
}
await this.setAllExport({ last: (rowIndex >= this.downloadInfo.maxRows - 1) })
this.$refs.progressModalRef.setValue(100)
}
}
}
}
await new Promise(resolve => setTimeout(resolve, 2000)) // sleep
window.close()
setInterval(this.writeFiles, 1000)
},
destroyed () {
},
+353 -134
View File
@@ -1,5 +1,10 @@
<template>
<div class="file-list">
<div class="file-list" @mousedown="unSelectAll">
<!-- Move Folder Modal -->
<download ref="download_ref"></download>
<download-offline ref="download_offline_ref"></download-offline>
<folder-modal ref="folder_modal_ref" @refreshPage="refreshPage"></folder-modal>
<!-- Create Folder Modal -->
<va-modal
class="flex sm12 xl12 md12 xs12"
v-model="showModal.createFolder"
@@ -20,7 +25,7 @@
removable
/>
</va-modal>
<!-- Edit File Modal -->
<va-modal
class="flex sm12 xl12 md12 xs12"
v-model="showModal.editFile"
@@ -48,6 +53,7 @@
removable
/>
</va-modal>
<!-- Delete File Modal-->
<va-modal
v-model="showModal.deleteFile"
size="small"
@@ -64,6 +70,7 @@
<p>Delete File {{ deleteInfo.name }} ? <input type="text" :ref="'delete_input'" style="opacity: 0; line-height: 0;"/></p>
</va-modal>
<!-- Delete MultiFiles Modal -->
<va-modal
v-model="showModal.deleteMultiFiles"
size="small"
@@ -81,17 +88,6 @@
</va-modal>
<va-card class="flex sm12 xl12 md12 xs12">
<template slot="header">
<div class="flex sm12 xl12 md12 xs12" style="text-align: end;">
<va-button class="" color="success" v-if="selected.length" @click="downloadSelected" target="_blank" small>
DOWNLOAD
</va-button>
<va-button class="" color="danger" v-if="selected.length" @click="deleteMultiFilesConfirm" target="_blank" small>
DELETE
</va-button>
</div>
</template>
<!-- SearchField & perPageSelect-->
<div class="row align--center">
<div class="flex xs12 md6">
@@ -116,32 +112,46 @@
</div>
<!-- CreateFolder & FilePath -->
<div class="flex mb-4">
<va-icon
name="fa fa-plus"
size="1rem"
class="mr-2"
style="cursor: pointer;"
:color="'primary'"
@click.native="createFolderConfirm"
/>
<va-icon
name="fa fa-folder-open"
size="0.9rem"
class="mr-2"
style="cursor: pointer;"
:color="(currentPathIndex === -1)?'primary':'dark'"
@click.native="openHome"
/>
<span
class="mt-0 mb-0 mr-2"
v-for="(item, index) in pathLists" :key="index"
:style="{ color:(currentPathIndex === index)?'#6c7fee':'#34495e', cursor:'pointer'}"
@click="openPath(item,index)"
>
<span class="mr-1" style="color: #34495e; cursor: default;">/</span>
{{ item.name }}
</span>
<div class="row">
<div class="flex d-flex xl8 lg8 sm8 xs8" style="align-items: center;">
<div>
<va-icon
name="fa fa-plus"
size="1rem"
class="mr-2"
style="cursor: pointer;"
:color="'primary'"
@click.native="createFolderConfirm"
/>
<va-icon
name="fa fa-folder-open"
size="0.9rem"
class="mr-2"
style="cursor: pointer;"
:color="(currentPathIndex === -1)?'primary':'dark'"
/>
<span
class="mt-0 mb-0 mr-2"
v-for="(item, index) in pathLists" :key="index"
:style="{ color:(currentPathIndex === index)?'#6c7fee':'#34495e', cursor:'pointer'}"
@click="openPath(item,index)"
>
<span class="mr-1" style="color: #34495e; cursor: default;">/</span>
{{ item.name }}
</span>
</div>
</div>
<div class="flex xl4 lg4 sm4 xs4" style="text-align: end;">
<va-button class="" color="primary" @mousedown.stop="showFolderModal" target="_blank" small>
MOVE
</va-button>
<va-button class="" color="success" @mousedown.stop="downloadSelected" target="_blank" small>
DOWNLOAD
</va-button>
<va-button class="" color="danger" @mousedown.stop="deleteMultiFilesConfirm" target="_blank" small>
DELETE
</va-button>
</div>
</div>
<!-- FileListTable -->
@@ -160,14 +170,16 @@
:fields="fields"
:data="filteredData"
:per-page="parseInt(perPage)"
@row-clicked="openFile"
@row-clicked="clickRow"
@mouseup.native="mouseUp"
@mousedown.native.stop="mouseDown"
hoverable
clickable
v-else
:ref="'datatable_ref'"
v-else
>
<template slot="select" slot-scope="props">
<va-checkbox :value="props.rowData.checked" @input="select(props.rowData)"/>
<va-checkbox :value="props.rowData.checked"/>
</template>
<template slot="name" slot-scope="props">
<va-icon
@@ -195,7 +207,7 @@
{{transDeviceInfo(props.rowData.device)}}
</template>
<template slot="actions" slot-scope="props" >
<va-popover :message="`sdcard ${props.rowData.name}`" placement="top">
<!-- <va-popover :message="`sdcard ${props.rowData.name}`" placement="top">
<sd-card-button
v-if="(props.rowData.type !== 'folder') && (props.rowData.device.library_name.indexOf('Neulive') >= 0) && (props.rowData.sd_data_record === true)"
:meta="props.rowData"
@@ -204,26 +216,26 @@
@refreshPage="refreshPage"
@downloadSdCard="downloadSdCard"
/>
</va-popover>
<va-popover :message="`download ${props.rowData.name} in csv format`" placement="top">
</va-popover> -->
<va-popover :message="`Download csv`" placement="top">
<va-button flat small color="gray" icon="fa fa-download" v-if="props.rowData.type !== 'folder' && props.rowData.device.library_name.indexOf('Neulive') >= 0" @click.stop="downloadCsv(props.rowData)"/>
</va-popover>
<va-popover :message="`download ${props.rowData.name} in excel format`" placement="top">
<va-button flat small color="gray" icon="fa fa-download" v-if="props.rowData.type !== 'folder' && props.rowData.device.library_name.indexOf('Elite') >= 0" @click.stop="downloadExcel(props.rowData)"/>
<va-popover :message="`Download excel`" placement="top">
<va-button flat small color="gray" icon="fa fa-download" v-if="props.rowData.type !== 'folder' && props.rowData.device.library_name.indexOf('Elite') >= 0" @click.stop="newDownload(props.rowData)"/>
</va-popover>
<va-popover :message="`download ${props.rowData.name} in csv-edf format`" placement="top">
<va-popover :message="`Download edf`" placement="top">
<va-button flat small color="gray" icon="fa fa-download" v-if="props.rowData.type !== 'folder' && props.rowData.device.library_name.indexOf('Neulive') >= 0" @click.stop="downloadExcel(props.rowData)"/>
</va-popover>
<va-popover :message="`replay ${props.rowData.name}`" placement="top">
<va-popover :message="`Replay`" placement="top">
<va-button flat small color="gray" icon="fa fa-eye" v-if="props.rowData.type !== 'folder'" @click.stop="replay(props.rowData)"/>
</va-popover>
<va-popover :message="`spike ${props.rowData.name}`" placement="top">
<va-popover :message="`Spike`" placement="top">
<va-button flat small color="gray" icon="fa fa-filter" v-if="props.rowData.type !== 'folder' && props.rowData.device.library_name.indexOf('Neulive') >= 0" @click.stop="spike(props.rowData)"/>
</va-popover>
<va-popover :message="`edit ${props.rowData.name}`" placement="top">
<va-popover :message="`Edit`" placement="top">
<va-button flat small color="gray" icon="fa fa-pencil" @click.stop="editFileConfirm(props.rowData)"/>
</va-popover>
<va-popover :message="`delete ${props.rowData.name}`" placement="top">
<va-popover :message="`Delete`" placement="top">
<va-button flat small color="gray" icon="fa fa-trash" @click.stop="deleteFileConfirm(props.rowData)"/>
</va-popover>
</template>
@@ -237,19 +249,25 @@ import { debounce } from 'lodash'
import { file } from '../../../data/file/File'
import { FulfillingBouncingCircleSpinner } from 'epic-spinners'
import api from '../../../data/api/index'
import SdCardButton from '../sdcard/SdCardButton.vue'
// import SdCardButton from '../sdcard/SdCardButton.vue'
import configTable from '@/data/config-table/index.js'
import FolderModal from './FolderModal.vue'
import Download from '../../download/Download.vue'
import DownloadOffline from '../../download/DownloadOffline.vue'
export default {
name: 'FileTable',
components: {
FulfillingBouncingCircleSpinner,
SdCardButton,
// SdCardButton,
FolderModal,
Download,
DownloadOffline,
},
data () {
return {
term: null,
perPage: '80',
perPage: '40',
perPageOptions: ['20', '40', '80', '160'],
fileLists: [],
@@ -296,6 +314,18 @@ export default {
},
SDuuidList: [],
controllerList: [],
// mouse click times
clickCounter: 0,
// record the selected index
clickRecord: [],
// record the target
clickTarget: null,
// mouseup or not
clickStatus: false,
// record shift+click target
shiftIndexRecord: null,
downloadIDList: [],
}
},
computed: {
@@ -372,6 +402,9 @@ export default {
}
})
},
selectedNumber () {
return this.fileLists.filter(file => file.checked).length
},
selected () {
return this.fileLists.filter(file => file.checked)
},
@@ -380,20 +413,28 @@ export default {
mqttPub: function (topic, mes) {
this.$mqtt.publish(topic, mes)
},
// stopEvent: function (e) {
// console.log(e)
// e.stopPropagation()
// },
select: function (file) {
event.stopPropagation()
const idx = this.fileLists.findIndex(f => f.id === file.id)
showFolderModal: async function () {
this.$refs.folder_modal_ref.selected = this.selected
await this.$refs.folder_modal_ref.refreshCollection()
this.$refs.folder_modal_ref.showModal = true
},
unSelectAll: function () {
this.fileLists.forEach(element => {
element.checked = false
})
},
selectConcat: function (idx) {
this.fileLists[idx].checked = !this.fileLists[idx].checked
},
select: function (idx) {
this.unSelectAll()
this.fileLists[idx].checked = true
},
search: debounce(function (term) {
this.term = term
}, 400),
transFileSize: function (fileSize) {
if (fileSize === undefined) {
if (fileSize === undefined || fileSize === -1) {
return '--'
} else {
return this.GLOBAL.transFileSize(fileSize)
@@ -416,7 +457,98 @@ export default {
return device.device_name + '\n' + this.GLOBAL.transMac(device.device_address)
}
},
clickRow: async function (rowData) {
this.clickCounter += 1
setTimeout(() => { this.clickCounter = 0 }, 500)
if (window.getSelection().toString() !== '' && this.clickEvent.shiftKey === false && this.clickCounter !== 2) return true
window.getSelection().removeAllRanges()
// click target id
const idx = this.fileLists.findIndex(f => f.id === rowData.id)
setTimeout(async () => {
let timeOutTimer
// single click
if (this.clickCounter === 1) {
// meta key or ctrl key
if (this.clickEvent.metaKey === true || this.clickEvent.ctrlKey === true) {
this.selectConcat(idx)
if (this.clickRecord.includes(idx) === false) {
this.clickRecord.push(idx)
}
this.shiftIndexRecord = null
} else if (this.clickEvent.shiftKey === true) {
// shift key
const start = this.clickRecord[this.clickRecord.length - 1]
const end = idx
// if has shift event has trigger before then reset the checked
if (this.shiftIndexRecord !== null) {
if (start > this.shiftIndexRecord) {
for (let i = start; i >= this.shiftIndexRecord; i--) {
this.fileLists[i].checked = false
}
}
if (start < this.shiftIndexRecord) {
for (let i = start; i <= this.shiftIndexRecord; i++) {
this.fileLists[i].checked = false
}
}
}
if (start > end) {
for (let i = start; i >= end; i--) {
this.fileLists[i].checked = true
}
}
if (start < end) {
for (let i = start; i <= end; i++) {
this.fileLists[i].checked = true
}
}
this.shiftIndexRecord = idx
} else {
// without any hotKey
this.shiftIndexRecord = null
this.clickRecord.length = 0
this.selectConcat(idx)
if (this.clickRecord.includes(idx) === false) {
this.clickRecord.push(idx)
}
}
timeOutTimer = setTimeout(() => {
this.clickCounter = 0
}, 300)
} else if (this.clickCounter === 2) {
clearTimeout(timeOutTimer)
this.clickCounter = 0
await this.openFile(rowData)
}
}, 0)
},
mouseDown: async function (e) {
this.clickEvent = e
this.clickStatus = true
},
mouseUp: function () {
this.clickStatus = false
},
mouseMove: async function (e, rowData) {
const idx = this.fileLists.findIndex(f => f.id === rowData.id)
if (e.metaKey === true || e.ctrlKey === true) {
if (this.clickStatus === true) {
const indexOfRecord = this.clickRecord.indexOf(idx)
// if (indexOfRecord === this.clickRecord.length - 1) return
// console.log('indexOfRecord', indexOfRecord)
if (indexOfRecord !== -1) {
console.log(idx, 'false')
this.clickRecord.splice(indexOfRecord, 1)
this.fileLists[idx].checked = false
} else {
console.log(idx, 'true')
this.clickRecord.push(idx)
this.fileLists[idx].checked = true
}
}
}
},
openFile: async function (info) {
if (info.type === 'folder') {
this.currentInfo = info
@@ -529,56 +661,67 @@ export default {
}, 100)
},
editFile: async function () {
// TODO editFile
if (this.editInfo.type !== 'folder') {
await api.meta.update(this.editInfo.info.id, { name: this.editInfo.changedName })
} else {
}
await this.editFileDone()
},
checkFileNameValidate: debounce(function (term) {
const illegalChar = term.match(/[^(\w\-)]+/gm)
this.editInfo.changedName = term
if (term.length === 0) {
// input text empty
this.editInfo.error = true
this.editInfo.success = false
this.editInfo.errorMessages.pop()
this.editInfo.errorMessages.push(this.editInfo.errorMessagesAll[1])
} else if (illegalChar !== null) {
// input text illegal
this.editInfo.error = true
this.editInfo.success = false
this.editInfo.errorMessages.pop()
this.editInfo.errorMessages.push(this.editInfo.errorMessagesAll[0] + ' ' + illegalChar[0])
} else {
const existedFile = this.fileLists.filter((file) => {
if (file.name != null) {
return file.name.replace('/', '') === term
} else {
return false
}
})
if (existedFile.length === 0) {
this.editInfo.error = false
this.editInfo.success = true
} else {
// file name exist
this.editInfo.error = true
this.editInfo.success = false
this.editInfo.errorMessages.pop()
this.editInfo.errorMessages.push(this.editInfo.errorMessagesAll[2])
}
}
}, 200),
editFileDone: async function () {
const tmpCurrentPage = this.$refs.datatable_ref.currentPage
await this.refreshPage()
this.$refs.datatable_ref.currentPage = tmpCurrentPage
this.$refs.datatable_ref.inputPage(tmpCurrentPage)
this.showToast(`${this.editInfo.info.name} -> ${this.editInfo.changedName}`, {
position: 'bottom-right',
})
// TODO editFile
if (this.editInfo.info.type === 'folder') {
await api.collection.update(this.editInfo.info.id, { name: this.editInfo.changedName })
const folder = this.fileLists.find((file) => {
if (file.type === 'folder' && this.editInfo.info.id === file.id) return true
})
folder.name = this.editInfo.changedName
} else {
await api.meta.update(this.editInfo.info.id, { name: this.editInfo.changedName })
const meta = this.fileLists.find((file) => {
if (file.type === undefined && this.editInfo.info.id === file.id) return true
})
meta.name = this.editInfo.changedName
}
// await this.editFileDone()
},
checkFileNameValidate: debounce(function (term) {
// const illegalChar = term.match(/[^(\w\-)]+/gm)
this.editInfo.changedName = term
// if (term.length === 0) {
// // input text empty
// this.editInfo.error = true
// this.editInfo.success = false
// this.editInfo.errorMessages.pop()
// this.editInfo.errorMessages.push(this.editInfo.errorMessagesAll[1])
// } else if (illegalChar !== null) {
// // input text illegal
// this.editInfo.error = true
// this.editInfo.success = false
// this.editInfo.errorMessages.pop()
// this.editInfo.errorMessages.push(this.editInfo.errorMessagesAll[0] + ' ' + illegalChar[0])
// } else {
// const existedFile = this.fileLists.filter((file) => {
// if (file.name != null) {
// return file.name.replace('/', '') === term
// } else {
// return false
// }
// })
// if (existedFile.length === 0) {
// this.editInfo.error = false
// this.editInfo.success = true
// } else {
// // file name exist
// this.editInfo.error = true
// this.editInfo.success = false
// this.editInfo.errorMessages.pop()
// this.editInfo.errorMessages.push(this.editInfo.errorMessagesAll[2])
// }
// }
}, 200),
editFileDone: async function () {
// const tmpCurrentPage = this.$refs.datatable_ref.currentPage
// await this.refreshPage()
// if (this.$refs.datatable_ref) {
// this.$refs.datatable_ref.currentPage = tmpCurrentPage
// this.$refs.datatable_ref.inputPage(tmpCurrentPage)
// }
},
undoEdit: function () {
this.editInfo.success = false
@@ -602,10 +745,19 @@ export default {
},
deleteFolder: async function (id) {
await api.collection.update(id, { deleted: true })
const childrenCollection = await api.collection.getByParent('folder', id)
const childrenMeta = await api.meta.getByParent('folder', id)
for (const collection of childrenCollection.data) {
await this.deleteFolder(collection.id)
}
for (const meta of childrenMeta.data) {
await this.deleteSingleFileByDeleteInfo(meta.id)
}
await api.collection.clearDel()
},
deleteSingleFileByDeleteInfo: async function () {
await api.meta.update(this.deleteInfo.metaID, { deleted: true })
deleteSingleFileByDeleteInfo: async function (metaID) {
if (metaID === undefined) metaID = this.deleteInfo.metaID
await api.meta.update(metaID, { deleted: true })
await api.meta.clearDel()
},
deleteFileConfirm: function (info) {
@@ -629,9 +781,19 @@ export default {
deleteFileDone: async function () {
const tmpCurrentPage = this.$refs.datatable_ref.currentPage
// rebuild table
this.fileLists = this.fileLists.filter(file => {
return file.id !== this.deleteInfo.metaID
})
if (this.deleteInfo.metaID) {
this.fileLists = this.fileLists.filter(file => {
return file.id !== this.deleteInfo.metaID
})
}
if (this.deleteInfo.folderID) {
this.fileLists = this.fileLists.filter(file => {
if (file.type === 'folder') {
return file.id !== this.deleteInfo.folderID
}
return true
})
}
// await this.refreshPage()
await this.$refs.datatable_ref.inputPage(1)
await this.$refs.datatable_ref.inputPage(tmpCurrentPage)
@@ -651,7 +813,7 @@ export default {
this.showToast('deleting file...', {
position: 'bottom-right',
})
this.deleteSelected()
await this.deleteSelected()
},
inputFieldReset: function (info) {
info.name = ''
@@ -689,23 +851,66 @@ export default {
// this.$refs.datatable_ref.refresh()
// this.$refs.datatable_ref.currentPage = 1
},
downloadSelected: function () {
for (let i = 0; i < this.selected.length; i++) {
const meta = this.selected[i]
this.downloadExcel(meta)
getAllChildrenByParent: async function (collection) {
const childrenCollection = await api.collection.getByParent('folder', collection)
const childrenMeta = await api.meta.getByParent('folder', collection)
for (const collection of childrenCollection.data) {
await this.getAllChildrenByParent(collection.id)
}
for (const meta of childrenMeta.data) {
this.downloadIDList.push(meta.id)
}
},
async deleteSelected () {
downloadSelected: async function () {
this.downloadIDList.length = 0
const meta = this.selected
if (Array.isArray(meta) === true) {
for (const ele of meta) {
if (ele.type === 'folder') {
await this.getAllChildrenByParent(ele.id)
} else {
this.downloadIDList.push(ele.id)
}
}
}
const connectCheck = await api.connection.check()
if (connectCheck.status === 200) {
this.$refs.download_ref.count = 0
this.$refs.download_ref.fileNums = this.downloadIDList.length
this.$refs.download_ref.metaListNew.push(...this.downloadIDList)
} else {
this.$refs.download_offline_ref.count = 0
this.$refs.download_offline_ref.fileNums = this.downloadIDList.length
this.$refs.download_offline_ref.metaListNew.push(...this.downloadIDList)
}
},
newDownload: async function (data) {
const connectCheck = await api.connection.check()
if (connectCheck.status === 200) {
this.$refs.download_ref.fileNums = 1
this.$refs.download_ref.metaListNew.push(data.id)
} else {
this.$refs.download_offline_ref.fileNums = 1
this.$refs.download_offline_ref.metaListNew.push(data.id)
}
},
deleteSelected: async function () {
for (let i = 0; i < this.selected.length; i++) {
const meta = this.selected[i]
this.fillDeleteInfo(meta)
await this.deleteSingleFileByDeleteInfo()
if (this.deleteInfo.metaID === undefined) {
await this.deleteFolder(this.deleteInfo.folderID)
} else {
await this.deleteSingleFileByDeleteInfo()
}
this.showToast(`deleted ${this.deleteInfo.name}`, {
position: 'bottom-right',
})
}
const tmpCurrentPage = this.$refs.datatable_ref.currentPage
await this.refreshPage()
// filter the checked files
this.fileLists = this.fileLists.filter((file) => { return file.checked === false })
await this.$refs.datatable_ref.inputPage(1)
await this.$refs.datatable_ref.inputPage(tmpCurrentPage)
},
downloadCsv: async function (meta) {
@@ -718,20 +923,26 @@ export default {
}
},
downloadExcel: async function (meta) {
this.downloadIDList.length = 0
const href = location.href.split('/')[2]
const connectCheck = await api.connection.check()
if (meta.device.library_name.indexOf('Elite') >= 0) {
if (connectCheck.status === 200) {
window.open('http://' + href + '/#/download/online/excel/' + meta.id)
} else {
window.open('http://' + href + '/#/download/offline/excel/' + meta.id)
}
} else if (meta.device.library_name.indexOf('Neulive') >= 0) {
if (connectCheck.status === 200) {
window.open('http://' + href + '/#/download/online/csv-edf/' + meta.id)
} else {
window.open('http://' + href + '/#/download/offline/csv-edf/' + meta.id)
let metaID = ''
if (Array.isArray(meta) === true) {
for (const ele of meta) {
if (ele.type === 'folder') {
await this.getAllChildrenByParent(ele.id)
} else {
this.downloadIDList.push(ele.id)
}
}
} else {
this.downloadIDList.push(meta.id)
}
metaID = this.downloadIDList.join('-')
if (connectCheck.status === 200) {
window.open('http://' + href + '/#/download/online/excel/' + metaID)
} else {
window.open('http://' + href + '/#/download/offline/excel/' + metaID)
}
},
downloadSdCard: async function (meta) {
@@ -792,8 +1003,16 @@ export default {
const controllerList = await api.controller.getAll()
this.controllerList = controllerList.data
this.getSDuuidList()
window.addEventListener('keypress', (e) => {
this.keyboardEvent = e
})
},
destroyed () {
},
}
</script>
<style>
.text-not-select {
user-select: none;
}
</style>
@@ -0,0 +1,101 @@
<template>
<va-modal
class="flex sm12 xl12 md12 xs12"
v-model="showModal"
size="small"
:title="'MOVE'"
:okText=" $t('modal.confirm') "
@ok="moveFolder()"
@cancel="cancel()"
>
<div class="row flex sm12 xl12 md12 xs12">
<va-select
v-model="destination"
:options="option"
class="va-select-without-margin"
searchable
/>
</div>
</va-modal>
</template>
<script>
import api from '@/data/api/index'
export default {
name: 'aaa',
data: () => {
return {
showModal: false,
option: [],
destination: '',
selected: [],
}
},
methods: {
cancel: function () {
this.destination = ''
this.selected = []
},
refreshCollection: async function () {
await this.getAllCollection()
},
moveFolder: async function () {
for (const e of this.selected) {
if (e.type === 'folder') {
await api.collection.update(e.id, {
parent: {
folder: [this.destination.id],
},
})
}
if (e.type === undefined) {
await api.meta.update(e.id, {
parent: {
folder: [this.destination.id],
},
})
}
}
this.cancel()
this.$emit('refreshPage')
},
getAllCollection: async function () {
// get all collections by api
const collectionResponse = await api.collection.getAll()
// filter the root folder & select folder itself
const allCollection = collectionResponse.data.filter((ele) => {
return ele.name !== 'root' && this.selected.findIndex(v => v.id === ele.id && v.type === 'folder') === -1
})
// create a new list of collection contain text for display
const newCollection = allCollection.map((ele) => {
let parentName = ''
// if has parent
if (Object.keys(ele.parent).length > 0) {
// get parent name
for (const id of ele.parent.folder) {
const parent = allCollection.find((v) => {
return v.id === id
})
if (parent) {
parentName = parent.name
}
}
}
// if parent name is admin then the name is remain origin
if (ele.name === 'admin' || parentName === 'admin') {
ele.text = ele.name
} else {
// if not the name contain it's parent
ele.text = parentName + ' / ' + ele.name
}
return ele
})
this.option = newCollection
},
},
mounted () {
},
}
</script>
<style></style>
+4 -8
View File
@@ -15,6 +15,7 @@
:mask-color="'rgba(0, 0, 0, 0)'"
:visible.sync="taskViewPanel.show"
:title="(taskViewPanel.type === 1) ? 'Device' : (taskViewPanel.type === 3) ? 'Condition' : (taskViewPanel.type === 4) ? 'Parameter' : ''"
@closed="onClosing"
resizable
>
<project-task/>
@@ -100,6 +101,9 @@ export default {
},
},
methods: {
onClosing: async function () {
await this.saveProject(this.getSelectProject)
},
pageToast: function (mes) {
this.showToast(
mes,
@@ -163,14 +167,6 @@ export default {
},
saveProject: async function (project) {
this.updateProject({ project: project, api: this.API })
this.showToast(
'project update finish',
{
icon: 'fa-bell',
position: 'bottom-right',
duration: 5000,
},
)
},
detect: async function (device) {
this.mqttPub(taskInfo.getTaskInfo().controllerID + '_user', JSON.stringify({
@@ -40,13 +40,20 @@ export default {
},
computed: {
configList () {
if (this.filterText === '') return this.projectConfigList
return this.projectConfigList.filter(ele => ele.name.includes(this.filterText))
const projectList = this.projectConfigList
projectList.sort((a, b) => {
const date1 = new Date(a.created_at).getTime()
const date2 = new Date(b.created_at).getTime()
return date2 - date1
})
if (this.filterText === '') return projectList
return projectList.filter(ele => ele.name.includes(this.filterText))
},
...mapFields('project', [
'projectConfigList',
'projectSelectIndex',
'projectTableSelectIndex',
]),
},
data () {
@@ -83,6 +90,7 @@ export default {
select: function (index) {
this.selectProjectIndex = index
this.selectDeleteIndex = -1
this.projectTableSelectIndex = -1
this.selectProject({ index: index })
},
@@ -61,7 +61,10 @@ export default {
},
taskDevice () {
return this.getSelectTask.device
if (this.getSelectTask.device) {
return this.getSelectTask.device
}
return null
},
...mapGetters('project', [
types.project.getSelect,
@@ -67,7 +67,8 @@ export default {
condition.select = !condition.select
},
setParameter: function (name, value) {
this.parameter = Object.assign({}, this.parameter)
// this.parameter = Object.assign({}, this.parameter)
this.parameter[name] = value
if (this.parameterUUID === '') {
this.parameterUUID = this.GLOBAL.getUUID()
@@ -106,7 +107,7 @@ export default {
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.$refs.device_parameter_ref.workingModeSelectChange(modeOption, false)
this.parameter = Object.assign(this.parameter, Object.values(parameterSet)[0])
} else {
const defaultMode = this.config.MODE_OPTIONS.find(ele => ele.description === 'Idle')
+1 -1
View File
@@ -13,7 +13,7 @@
</div>
<div v-else>
<project-menu @detect="detect" @save_project="save"/>
<project-table/>
<project-table @save="save"/>
<div align="right" v-if="lockMode === false">
<button class="project-start-btn" @click="start">
<div>
@@ -1,7 +1,8 @@
<template>
<div>
<project-device @showDeviceModal="showDeviceModal" @save="saveProject"></project-device>
<div class="flex d-flex sm12 xs12 md6 xl4 px-0">
<add-task/>
<add-task @save="saveProject"/>
<div>
<button class="add-cycle-btn" @click="showCycleModal">
<div class="add-cycle-text">
@@ -10,23 +11,28 @@
</button>
</div>
<div>
<button class="copy-project-btn" @click="copyTask({ project: getSelectProject, index: projectTableSelectIndex})">
<button class="copy-project-btn" @click="() => {
copyTask({ project: getSelectProject, index: projectTableSelectIndex})
saveProject()
}">
<img class="img-vertical-center" src="@/assets/img/project/copy.svg">
</button>
</div>
<div>
<button class="copy-project-btn" @click="saveProject">
<button class="copy-project-btn" @click="saveProject(true)">
<img class="img-vertical-center" src="@/assets/img/project/save.svg">
</button>
</div>
<div>
<button class="copy-project-btn" @click="deleteTask({ project: getSelectProject, index: projectTableSelectIndex})">
<button class="copy-project-btn" @click="() => {
deleteTask({ project: getSelectProject, index: projectTableSelectIndex})
saveProject()
}">
<img class="img-vertical-center" src="@/assets/img/project/delete.svg">
</button>
</div>
</div>
<project-device @showDeviceModal="showDeviceModal"></project-device>
<new-device-modal ref="device_modal_ref" @detect="detect"></new-device-modal>
<new-device-modal ref="device_modal_ref" @detect="detect" @save="saveProject"></new-device-modal>
<cycle-modal ref="cycle_modal_ref" @createCycle="createCycle"></cycle-modal>
</div>
</template>
@@ -82,7 +88,17 @@ export default {
this.$refs.cycle_modal_ref.show()
this.$refs.cycle_modal_ref.reset()
},
saveProject: function () {
saveProject: function (showMessage = false) {
if (showMessage === true) {
this.showToast(
'project update finish',
{
icon: 'fa-bell',
position: 'bottom-right',
duration: 5000,
},
)
}
this.$emit('save_project', this.getSelectProject)
},
@@ -1,6 +1,9 @@
<template>
<div>
<button class="add-task-btn" @click="createTask">
<button class="add-task-btn" @click="() => {
createTask()
save()
}">
<div class="add-task-text">
<p>Add Task</p>
</div>
@@ -22,13 +25,12 @@ export default {
}
},
methods: {
save: function () {
this.$emit('save')
},
...mapActions('project',
[
types.task.init,
types.task.create,
types.task.save,
types.task.delete,
types.task.select,
],
),
},
@@ -135,7 +135,6 @@ export default {
this.showModal = false
},
createCycle: async function () {
this.showModal = false
const project = this.getSelectProject
if (Object.keys(this.cycleInfo).length === 0) {
this.$emit('createCycle', this.task)
@@ -182,7 +181,8 @@ export default {
await this.swapTask({ project: project, originIndex: originEndIndex, newIndex: newEndIndex + 1 })
}
}
this.$emit('save')
this.showModal = false
return true
},
removeCycle: async function () {
@@ -199,6 +199,7 @@ export default {
const originEndIndex = await this.getIndexTask({ project: project, uuid: this.cycleInfo.range[1] })
await this.deleteTask({ project: project, index: originEndIndex })
this.$emit('save')
this.showModal = false
return true
},
@@ -101,10 +101,12 @@ export default {
if (this.deviceList[this.deviceSelect]) {
this.device.pair = this.deviceList[this.deviceSelect].macAddress
}
this.$emit('save')
this.hide()
},
removeDevice: function () {
this.deleteDeviceProject({ deviceKey: this.key })
this.$emit('save')
this.hide()
},
getDeviceList: async function (device) {
@@ -92,6 +92,7 @@ export default {
pairStatus: 1,
order: this.getDeviceMaxOrderProject,
})
this.$emit('save')
return true
},
clickShowDevice: async function (library) {
@@ -103,6 +104,7 @@ export default {
pairStatus: 0,
order: this.getDeviceMaxOrderProject,
})
this.$emit('save')
return false
},
cancelSelectDevice: function () {
@@ -113,6 +115,7 @@ export default {
},
deleteDevice: function (deviceIndex) {
this.deleteDeviceProject({ index: deviceIndex })
this.$emit('save')
},
handleMove (e) {
const { index, futureIndex } = e.draggedContext
@@ -131,6 +134,7 @@ export default {
deviceList[keyOld][key] = deviceListTemp[this.futureIndex][1][key]
deviceList[keyNew][key] = deviceListTemp[this.index][1][key]
}
this.$emit('save')
},
...mapActions('project',
[
@@ -15,7 +15,10 @@
</tr>
</thead>
<!-- <tbody> -->
<vuedraggable :disabled="lockMode === true || inputMode === true" class="draggable" :list="getSelectProject.task" @end="rearrangeTask({ project: getSelectProject })" tag="tbody" animation="500">
<vuedraggable :disabled="lockMode === true || inputMode === true" class="draggable" :list="getSelectProject.task" @end="()=> {
rearrangeTask({ project: getSelectProject })
saveProject()
}" tag="tbody" animation="500">
<template class="item" v-for="(task, taskIndex) in getSelectProject.task">
<tr
v-if="task.type === 'cycle'"
@@ -254,7 +257,7 @@
</table>
</div>
<div>
<cycle-modal ref="cycle_modal_ref"></cycle-modal>
<cycle-modal ref="cycle_modal_ref" @save="saveProject"></cycle-modal>
</div>
</div>
</template>
@@ -360,6 +363,7 @@ export default {
if (a === undefined) return
newTaskList.filter(ele => ele != null)
this.rearrangeTask({ project: this.getSelectProject })
this.saveProject()
},
swapTask: function (taskIndex, upDown) {
taskIndex = parseInt(taskIndex)
@@ -373,11 +377,13 @@ export default {
this.getSelectProject.task.splice(taskIndex + 1, 1, a)
}
this.rearrangeTask({ project: this.getSelectProject })
this.saveProject()
},
delSelected: function () {
for (const indexSelected of this.tableColumn.checked) {
this.deleteTask({ project: this.getSelectProject, index: indexSelected })
}
this.saveProject()
},
delAction: function (task, actionKey, conditionKey) {
const _action = JSON.parse(JSON.stringify(task.action))
@@ -388,6 +394,12 @@ export default {
task.action = _action
task.condition = _condition
this.saveProject()
},
saveProject: function () {
console.log('saveProject')
this.$emit('save', this.getSelectProject)
},
trigger_button: function (projectID) {
console.log('project', projectID)
@@ -410,6 +422,8 @@ export default {
this.inputMode = false
this.tableColumn[tag] = -1
}
this.saveProject()
},
switchCycle: function (tag, index, projectID, task) {
this.switchInput(tag, index)
@@ -422,6 +436,7 @@ export default {
index: cycleInfo[0],
content: { id: this.inputSaved },
}))
this.$emit('save', this.getSelectProject)
},
selectAll: function (selectedArray) {
const totalRange = [...Array(this.getSelectProject.task.length).keys()].map(idx => String(idx))
+134 -25
View File
@@ -62,12 +62,23 @@
<va-button class="no-dark-style-va-button" color="primary" target="_blank" @click.stop="addChart(false)" small>
ADD CHART
</va-button>
<va-button class="no-dark-style-va-button" color="primary" target="_blank" @click.stop="test()" small>
CONFIG
</va-button>
</va-card>
<slide-out
dock="right"
size="50%"
:mask-color="'rgba(0, 0, 0, 0)'"
:visible.sync="slideShow"
>
<Configuration :ref="'configuration_ref'" @add="addChart(false)" @remove="removeChart" @detect="detect" @reset="reset" @copy="copy"></Configuration>
</slide-out>
</div>
<div :key="taskContentChartPanelKey">
<div
v-for="chart in chartData"
v-for="chart in chartArray"
:key="chart.chartID"
>
<canvas-chart
@@ -78,6 +89,7 @@
:chartID="chart.chartID"
@init="initChart(chart.chartID)"
@remove="removeChartCheck(chart.chartID)"
@detect="detect"
/>
</div>
</div>
@@ -104,10 +116,11 @@ import CanvasChart from './chart/CanvasChart'
import TaskDevicesNew from './controller/TaskDevicesNew'
// import api from '@/data/api'
import { mapFields } from 'vuex-map-fields'
import { mapActions } from 'vuex'
import { mapActions, mapGetters } from 'vuex'
import taskTypes from '@/store/modules/task/content/types'
import TaskFormula from './formula/TaskFormula'
import { v4 as uuid } from 'uuid'
import Configuration from './configuration/Configuration'
// TODO change chart data tag format
@@ -118,6 +131,7 @@ export default {
// TaskDevices,
TaskDevicesNew,
TaskFormula,
Configuration,
},
computed: {
...mapFields('taskContent', [
@@ -129,7 +143,22 @@ export default {
]),
...mapFields('', [
'developerMode',
'controllerID',
]),
...mapGetters('taskContent', [
taskTypes.device.get,
]),
chartArray () {
return Object.values(this.chartData).sort((a, b) => {
if (a.cardName.replace('Chart', '') > b.cardName.replace('Chart', '')) {
return 1
}
if (a.cardName.replace('Chart', '') < b.cardName.replace('Chart', '')) {
return -1
}
return 0
})
},
},
data () {
return {
@@ -144,6 +173,8 @@ export default {
chartAreaClass: ['flex', 'xs12', 'sm12', 'md12', 'xl8', 'pa-0'],
getParmDone: false,
batteryInterval: {},
temp: null,
slideShow: false,
}
},
mqtt: {
@@ -174,7 +205,7 @@ export default {
if (this.$refs.devices_ref != null) {
await this.$refs.devices_ref.loadingDone()
}
await this.taskContentChartInitCustomizedFromCache({ controllerID: taskInfo.getTaskInfo().controllerID })
// await this.taskContentChartInitCustomizedFromCache({ controllerID: taskInfo.getTaskInfo().controllerID })
this.getParmDone = true
},
async '+/get_device_info/+' (data, topic) {
@@ -215,7 +246,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({ controllerID: taskInfo.getTaskInfo().controllerID })
// await this.taskContentChartInitCustomizedFromCache({ controllerID: taskInfo.getTaskInfo().controllerID })
}
},
// listen datastream [ topic: controllerID/data_server/device_data_stream/deviceID/channel ]
@@ -223,7 +254,9 @@ 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))
const device = this.getDevice({ memoryBoard: deviceID })
dataStreamBuffer.into(String.fromCharCode.apply(null, data), device.mac_address, (channel + 1))
},
'+/device_save_path/+' (data, topic) {
taskInfo.deviceSavePath(String.fromCharCode.apply(null, data))
@@ -284,16 +317,16 @@ export default {
_type: 'device',
})
device = this.getDevice({ memoryBoard: mes[1] })
device.status = 1
// remove mapping ID chart series data
for (const chart in this.chartData) {
this.taskContentChartResetSeriesData({
chartID: chart,
mappingID: mes[1],
mappingID: device.mac_address,
})
}
device = this.deviceListNew.find((ele) => ele.memory_board === parseInt(mes[1]))
device.status = 1
break
case 'stop':
if (mes[1] === 'all') {
@@ -312,7 +345,7 @@ export default {
device: parseInt(mes[1]),
instruction: 'interrupt',
}))
this.pageToast('The device [' + taskInfo.getDeviceIDByRaw(parseInt(mes[1])) + '] mission is done.')
this.pageToast('The device [' + taskInfo.getDeviceIDByRaw(parseInt(mes[1])) + '] mission done.')
break
case 'project':
// refresh real-time page when going to next task
@@ -327,6 +360,54 @@ export default {
},
},
methods: {
reset: async function () {
for (const chart in this.chartData) {
await this.removeChart(chart, false)
}
for (let i = 0; i < this.deviceListNew.length; i++) {
await this.addMappingChart(this.deviceListNew[i].mac_address)
await this.taskContentChartDefaultChartGenerator({
_deviceList: this.deviceListNew,
_itemID: this.deviceListNew[i].memory_board,
_chartID: null,
_type: 'device',
_reset: false,
})
}
this.$nextTick(() => {
this.$refs.configuration_ref.buildAccordingBlock()
})
},
copy: async function (selectIndex) {
console.log('copy', selectIndex)
for (const selectID of selectIndex) {
const newChart = JSON.parse(JSON.stringify(this.chartData[selectID]))
const newUUID = this.GLOBAL.getUUID()
newChart.chartID = newUUID
this.chartData[newUUID] = newChart
// register dataStreamBuffer
for (const grid of newChart.grid) {
for (const gridSource of newChart.gridSource[grid.index]) {
dataStreamBuffer.register(newUUID, gridSource.xSource.mac_address, gridSource.xSource.channel)
dataStreamBuffer.register(newUUID, gridSource.ySource.mac_address, gridSource.ySource.channel)
}
}
}
this.taskContentChartPanelKey++
this.chartData = Object.assign({}, this.chartData)
this.$refs.configuration_ref.updateChart()
this.$nextTick(() => {
this.$refs.configuration_ref.buildAccordingBlock()
})
},
test: function () {
this.$refs.configuration_ref.updateChart()
this.slideShow = true
},
getBattery: function (device) {
this.mqttPub(taskInfo.getTaskInfo().controllerID + '_user', JSON.stringify({
header: 'device_battery/0',
@@ -389,7 +470,7 @@ export default {
refreshData: function () {
for (const chart in this.chartData) {
// find each chart mappingID with device memory_board
const device = this.deviceListNew.find(ele => String(ele.memory_board) === String(this.chartData[chart].mappingID))
const device = this.deviceListNew.find(ele => this.chartData[chart].mappingID.includes(ele.mac_address))
// device not found continue
if (device === undefined) {
continue
@@ -436,10 +517,20 @@ export default {
if (!isDefault) {
await this.taskContentChartSaveToCache({ controllerID: taskInfo.getTaskInfo().controllerID })
}
this.pageToast('The chart has been added.')
// this.pageToast('The chart has been added.')
this.chartData = Object.assign({}, this.chartData)
this.$refs.configuration_ref.updateChart()
this.$nextTick(() => {
this.$refs.configuration_ref.buildAccordingBlock()
})
return newChart.chartID
},
saveChart: function () {
this.temp = JSON.parse(JSON.stringify(this.chartData))
},
loadChart: function () {
this.chartData = JSON.parse(JSON.stringify(this.temp))
},
refreshChartSetting: async function () {
if (this.$refs.chart_ref != null) {
this.$refs.chart_ref.forEach(ref => {
@@ -451,10 +542,10 @@ export default {
initChart: function (chartID) {
this.taskContentChartReset({
chartID: chartID,
mappingID: null,
mappingID: [],
cardName: null,
})
this.pageToast('The chart has been Initialized.')
// this.pageToast('The chart has been Initialized.')
},
removeChartCheck: function (chartID) {
this.selectChartID = chartID
@@ -490,7 +581,8 @@ export default {
if (saveCache === true) {
await this.taskContentChartSaveToCache({ controllerID: taskInfo.getTaskInfo().controllerID })
}
this.pageToast('The chart has been removed.')
this.$refs.configuration_ref.updateChart()
// this.pageToast('The chart has been removed.')
},
showDeviceSettingClick: function () {
this.showDeviceSetting = true
@@ -502,16 +594,16 @@ export default {
this.chartAreaClass[3] = 'md12'
this.chartAreaClass[4] = 'xl12'
},
addMappingChart: async function (deviceID) {
addMappingChart: async function (macAddress) {
// if have chart with device ID
for (const chart in this.chartData) {
if (this.chartData[chart].mappingID === deviceID) {
if (this.chartData[chart].mappingID.includes(macAddress)) {
return false
}
}
const chart = await this.addChart(true)
await this.$nextTick(async () => {
this.chartData[chart].mappingID = deviceID
this.chartData[chart].mappingID.push(macAddress)
if (this.$refs.chart_ref != null) {
this.$refs.chart_ref.forEach(ref => {
ref.refreshMappingSelect()
@@ -520,19 +612,21 @@ export default {
})
return chart
},
addDevice: async function (deviceID, memoryBoardID) {
addDevice: async function (device) {
const [macAddress, memoryBoard] = device
// subscribe datastream when add device
this.mqttSub(`${taskInfo.getTaskInfo().controllerID}/data_server/device_data_stream/${deviceID}/+`)
this.mqttSub(`${taskInfo.getTaskInfo().controllerID}/data_server/device_data_stream/${memoryBoard}/+`)
// add mapping chart
await this.addMappingChart(deviceID)
await this.addMappingChart(macAddress)
// register default chart
await this.taskContentChartDefaultChartGenerator({
_deviceList: this.deviceListNew,
_itemID: deviceID,
_itemID: memoryBoard,
_chartID: null,
_type: 'device',
_reset: false,
})
this.pageToast('The device [' + deviceID + '] has been registered.')
// this.pageToast('The device [' + deviceID + '] has been registered.')
},
removeDevice: function (deviceID) {
this.mqttUnSub(taskInfo.getTaskInfo().controllerID + '/data_server/device_data_stream/' + deviceID + '/+')
@@ -542,7 +636,7 @@ export default {
this.removeChart(chart)
}
}
this.pageToast('The device [' + deviceID + '] has been removed.')
// this.pageToast('The device [' + deviceID + '] has been removed.')
},
addFormula: async function (formulaID) {
const chart = await this.addChart(true)
@@ -621,6 +715,20 @@ export default {
path: '/',
})
},
detect: function (device) {
this.mqttPub(taskInfo.getTaskInfo().controllerID + '_user', JSON.stringify({
header: 'device_instruction/0',
device: device,
instruction: 'VIS_DEVICE_DETECT',
}))
setTimeout(() => {
this.mqttPub(taskInfo.getTaskInfo().controllerID + '_user', JSON.stringify({
header: 'device_instruction/0',
device: device,
instruction: 'VIS_DEVICE_DONE',
}))
}, 5000)
},
switchMode: function () {
console.log('switch mode', this.developerMode)
this.developerMode = !this.developerMode
@@ -645,6 +753,7 @@ export default {
if (devMode === 'dev') {
this.developerMode = true
}
this.controllerID = taskInfo.getTaskInfo().controllerID
await taskInfo.updateTaskInfo(this.$route.params.taskID)
this.GLOBAL.refreshCache()
@@ -1,614 +0,0 @@
<template>
<div class="task-content">
<va-modal
v-model="showShutdownModal"
size="small"
:title="'SHUTDOWN'"
:message="'The controller shutdown.'"
:okText=" $t('modal.confirm') "
@ok="exit()"
@cancel="exit()"
/>
<va-modal
v-model="showRemoveChartModal"
size="small"
:title="'REMOVE CHART'"
:message="'The chart will be removed.'"
:okText=" $t('modal.confirm') "
@ok="removeChart(null)"
/>
<div class="row row-equal">
<div v-if="showDeviceSetting" class="flex md12 xl4 xs12 sm12">
<div class="row">
<div class="flex sm12 xl12 md12 xs12">
<task-devices-g-m :ref="'devices_ref'" @add="addDevice($event)" @remove="removeDevice($event)" @refreshSetting="refreshChartSetting($event)" class="pa-0" />
</div>
<!-- <div class="flex sm12 xl12 md12 xs12">
<task-formula :ref="'formula_ref'" @add="addFormula($event)" @remove="removeFormula($event)" class="pa-0" />
</div> -->
</div>
</div>
<div :class="chartAreaClass">
<div class="row" >
<div class="flex sm12 xl12 md12 xs12">
<div class="flex sm12 xl12 md12 xs12" style="text-align: center;">
<va-card
stripe="primary"
>
<va-button class="no-dark-style-va-button" v-if="!showDeviceSetting" color="primary" target="_blank" @click="showDeviceSettingClick()" small>
SHOW DEVICES
</va-button>
<va-button class="no-dark-style-va-button" v-if="showDeviceSetting" color="primary" target="_blank" @click="hideDeviceSettingClick()" small>
HIDE DEVICES
</va-button>
<!-- <va-button class="" color="success" target="_blank" @click="startAllClick()" small>
START ALL
</va-button>
<va-button class="no-dark-style-va-button" color="danger" target="_blank" @click="stopAllClick()" small>
STOP ALL
</va-button> -->
<va-button class="no-dark-style-va-button" color="primary" target="_blank" @click.stop="addChart()" small>
ADD CHART
</va-button>
</va-card>
</div>
<div :key="chartKey">
<div
v-for="chart in chartData"
:key="chart.chartID"
>
<canvas-chart
:id="'chart' + chart.chartID"
:ref="'chart_ref'"
:cardheight="'400px'"
:cardwidth="'auto'"
:chartID="chart.chartID"
@init="initChart(chart.chartID)"
@remove="removeChartCheck(chart.chartID)"
/>
</div>
</div>
<div style="height: 150px;">
</div>
</div>
</div>
</div>
</div>
<task-content-modal />
</div>
</template>
<script>
import { dataStreamBuffer } from '../../../data/task/DataStreamBuffer'
import { taskInfo } from '../../../data/task/TaskInfo'
import CanvasChart from './chart/CanvasChart'
import TaskContentModal from './TaskContentModal.vue'
import { mapFields } from 'vuex-map-fields'
import TaskDevicesGM from './controller/neulive-gimer/TaskDevicesGM.vue'
import { mapActions } from 'vuex'
import taskTypes from '@/store/modules/task/content/types'
// TODO change chart data tag format
export default {
name: 'TaskContentGM',
components: {
CanvasChart,
TaskDevicesGM,
TaskContentModal,
},
computed: {
...mapFields('taskContent', [
'deviceList',
'showTaskModal',
'taskModalText',
'chartData',
]),
},
data () {
return {
// modal
showShutdownModal: false,
showRemoveChartModal: false,
// refresh timer
dataRefreshTimer: null,
// chart refresh key
chartKey: 0,
chartNumber: 0,
selectChartID: null,
showDeviceSetting: true,
chartAreaClass: ['flex', 'xs12', 'sm12', 'md12', 'xl8', 'pa-0'],
getParmDone: false,
}
},
mqtt: {
async '+/get_device_info_all/+' (data, topic) {
await taskInfo.deviceInfo(String.fromCharCode.apply(null, data), this.deviceList)
this.refreshDevicesWindow()
},
async '+/get_device_info/+' (data, topic) {
await taskInfo.deviceInfo(String.fromCharCode.apply(null, data), this.deviceList)
this.refreshDevicesWindow()
this.getParmDone = true
this.checkStiStatus()
},
async '+/device_parameter/+' (data, topic) {
await taskInfo.deviceParameter(String.fromCharCode.apply(null, data))
this.refreshDevicesWindow()
},
async '+/device_parameter_value/+' (data, topic) {
await taskInfo.deviceParameter(String.fromCharCode.apply(null, data))
this.refreshDevicesWindow()
},
async '+/hardware_device/+' (data, topic) {
await taskInfo.deviceInfo(String.fromCharCode.apply(null, data), this.deviceList)
if (this.$refs.devices_ref != null) {
await this.$refs.devices_ref.loadingDone()
}
},
// listen datastream [ topic: controllerID/data_server/device_data_stream/deviceID/channel ]
async '+/data_server/device_data_stream/+/+' (data, topic) {
const topicSplit = topic.split('/')
if (this.getParmDone & !taskInfo.getDeviceInfoByRawID(parseInt(topicSplit[3])).info.isSync) {
const result = await this.taskContentChartDefaultChartGenerator({
_deviceList: this.deviceList,
_itemID: taskInfo.getDeviceIDByRaw(parseInt(topicSplit[3])),
_chartID: null,
_type: 'device',
})
if (result) {
taskInfo.deviceStart(parseInt(topicSplit[3]), this.deviceList)
}
}
dataStreamBuffer.into(String.fromCharCode.apply(null, data), parseInt(topicSplit[3]), (parseInt(topicSplit[4]) + 1))
},
'+/device_save_path/+' (data, topic) {
taskInfo.deviceSavePath(String.fromCharCode.apply(null, data))
// console.log(taskInfo.getTaskInfo())
},
'+/device_save_path_set/+' (data, topic) {
taskInfo.deviceSavePath(String.fromCharCode.apply(null, data))
// console.log(taskInfo.getTaskInfo())
},
async '+/broadcast' (data, topic) {
const mes = String.fromCharCode.apply(null, data).split(':')
// let content
switch (mes[0]) {
case 'state':
switch (mes[1]) {
case 'device_available':
this.mqttPub(taskInfo.getTaskInfo().controllerID + '_user', JSON.stringify({
header: 'hardware_device/0',
}))
break
}
break
case 'disconnected':
taskInfo.deviceDisconnected(mes[1])
this.mqttPub(taskInfo.getTaskInfo().controllerID + '_user', JSON.stringify({
header: 'get_device_info/0',
device: parseInt(mes[1]),
}))
break
case 'connected':
this.mqttPub(taskInfo.getTaskInfo().controllerID + '_user', JSON.stringify({
header: 'get_device_info/0',
device: parseInt(mes[1]),
}))
taskInfo.deviceConnected(mes[1])
break
case 'shutdown':
taskInfo.controllerShutdown(this.deviceList)
this.showShutdownModal = true
break
case 'start':
if (!taskInfo.getDeviceInfoByRawID(parseInt(mes[1])).info.isSync) {
taskInfo.deviceStart(parseInt(mes[1]), this.deviceList)
const result = await this.taskContentChartDefaultChartGenerator({
_deviceList: this.deviceList,
_itemID: taskInfo.getDeviceIDByRaw(parseInt(mes[1])),
_chartID: null,
_type: 'device',
})
if (result) {
taskInfo.deviceStart(parseInt(mes[1]), this.deviceList)
}
}
break
case 'stop':
if (mes[1] === 'all') {
return false
}
taskInfo.deviceStop(parseInt(mes[1]), this.deviceList)
break
case 'device_timeout':
this.pageToast('The device [' + taskInfo.getDeviceIDByRaw(parseInt(mes[1])) + '] is timeout, please check its status or parameters.')
break
case 'device_mission_done':
this.mqttPub(taskInfo.getTaskInfo().controllerID + '_user', JSON.stringify({
header: 'device_instruction/0',
device: parseInt(mes[1]),
instruction: 'interrupt',
}))
this.pageToast('The device [' + taskInfo.getDeviceIDByRaw(parseInt(mes[1])) + '] mission is done.')
break
default:
break
}
// console.log(String.fromCharCode.apply(null, data), topic)
},
},
methods: {
mqttSub: function (val) {
this.$mqtt.subscribe(val)
},
mqttUnSub: function (val) {
this.$mqtt.unsubscribe(val)
},
mqttPub: function (topic, mes) {
this.$mqtt.publish(topic, mes)
},
pageMqttSub: function (id) {
this.mqttSub(id + '/hardware_device/+')
this.mqttSub(id + '/broadcast')
this.mqttSub(id + '/get_device_info_all/+')
this.mqttSub(id + '/get_device_info/+')
this.mqttSub(id + '/device_parameter/+')
this.mqttSub(id + '/device_parameter_value/+')
},
pageMqttUnSub: function (id) {
for (const device in taskInfo.getTaskInfo().deviceList) {
this.mqttUnSub(id + '/data_server/device_data_stream/' + device + '/+')
}
this.mqttUnSub(id + '/hardware_device/+')
this.mqttUnSub(id + '/broadcast')
this.mqttUnSub(id + '/get_device_info_all/+')
this.mqttUnSub(id + '/get_device_info/+')
this.mqttUnSub(id + '/device_parameter/+')
this.mqttUnSub(id + '/device_parameter_value/+')
},
pageInit: async function () {
if (await this.$refs.devices_ref != null) {
await this.$refs.devices_ref.loadingStart()
}
// let _parameter, _content
// this.mqttPub(taskInfo.getTaskInfo().controllerID + '_user', JSON.stringify({
// header: 'device_parameter/0',
// device: 7,
// parameter: 'RECORDING_CH|AXIS_CH',
// content: '7|1',
// }))
this.mqttPub(taskInfo.getTaskInfo().controllerID + '_user', JSON.stringify({
header: 'hardware_device/0',
}))
this.chartNumber = Object.keys(this.chartData).length
},
pageToast: function (mes) {
this.showToast(
mes,
{
icon: 'fa-bell',
position: 'bottom-right',
duration: 4000,
},
)
},
refreshData: function () {
// TODO don't need to refresh chart with stop status
for (const chart in this.chartData) {
this.taskContentChartRefreshData({
chartID: parseInt(chart),
})
}
},
refreshDevicesWindow: function () {
// console.log(taskInfo.getTaskInfo())
if (this.$refs.devices_ref != null) {
this.$refs.devices_ref.refresh()
}
},
checkStiStatus: function () {
this.$refs.devices_ref.checkStiStatus()
},
addChart: async function () {
const defaultID = {}
const update = async () => {
for (const chart in this.chartData) {
defaultID[chart] = this.chartData[chart].mappingID
}
this.taskContentChartAdd({
chartID: this.chartNumber,
maxDots: 4000,
gridLength: 1,
})
this.chartNumber++
this.chartKey++
}
await update()
for (const chart in this.chartData) {
this.chartData[chart].mappingID = defaultID[chart]
}
if (this.$refs.chart_ref != null) {
this.$refs.chart_ref.forEach(ref => {
ref.refreshMappingSelect()
})
}
// this.pageToast('The chart has been added.')
return this.chartNumber - 1
},
refreshChartSetting: async function () {
const defaultID = {}
const update = async () => {
for (const chart in this.chartData) {
defaultID[chart] = this.chartData[chart].mappingID
}
this.chartKey++
}
await update()
for (const chart in this.chartData) {
this.chartData[chart].mappingID = defaultID[chart]
}
if (this.$refs.chart_ref != null) {
this.$refs.chart_ref.forEach(ref => {
ref.refreshMappingSelect()
})
}
},
initChart: function (chartID) {
this.taskContentChartReset({
chartID: chartID,
mappingID: null,
cardName: null,
})
// this.pageToast('The chart has been Initialized.')
},
removeChartCheck: function (chartID) {
this.selectChartID = chartID
this.showRemoveChartModal = true
},
removeChart: async function (chartID) {
if (chartID == null) {
chartID = this.selectChartID
}
dataStreamBuffer.removeByChart(chartID)
if (this.chartData[chartID] != null) {
const defaultID = {}
const update = async () => {
for (const chart in this.chartData) {
if (chart !== chartID) {
defaultID[chart] = this.chartData[chart].mappingID
}
}
delete this.chartData[chartID]
this.chartKey++
}
await update()
for (const chart in this.chartData) {
this.chartData[chart].mappingID = defaultID[chart]
}
if (this.$refs.chart_ref != null) {
this.$refs.chart_ref.forEach(ref => {
ref.refreshMappingSelect()
})
}
}
// this.pageToast('The chart has been removed.')
},
showDeviceSettingClick: function () {
this.showDeviceSetting = true
this.chartAreaClass[3] = 'md12'
this.chartAreaClass[4] = 'xl8'
},
hideDeviceSettingClick: function () {
this.showDeviceSetting = false
this.chartAreaClass[3] = 'md12'
this.chartAreaClass[4] = 'xl12'
},
addMappingChart: async function (deviceID) {
// if have chart with device ID
for (const chart in this.chartData) {
if (this.chartData[chart].mappingID === deviceID) {
return false
}
}
const chart = await this.addChart()
await this.$nextTick(async () => {
this.chartData[chart].mappingID = deviceID
if (this.$refs.chart_ref != null) {
this.$refs.chart_ref.forEach(ref => {
ref.refreshMappingSelect()
})
}
})
return chart
},
addDevice: async function (deviceID) {
this.mqttSub(taskInfo.getTaskInfo().controllerID + '/data_server/device_data_stream/' + taskInfo.getRawDeviceID(deviceID) + '/+')
this.addMappingChart(deviceID)
this.pageToast('The device [' + deviceID + '] has been registered.')
},
removeDevice: function (deviceID) {
this.mqttUnSub(taskInfo.getTaskInfo().controllerID + '/data_server/device_data_stream/' + taskInfo.getRawDeviceID(deviceID) + '/+')
for (const chart in this.chartData) {
if (this.chartData[chart].mappingID === deviceID) {
dataStreamBuffer.removeByChart(chart)
this.removeChart(chart)
}
}
this.pageToast('The device [' + deviceID + '] has been removed.')
},
addFormula: async function (formulaID) {
const chart = await this.addChart()
await this.$nextTick(async () => {
this.chartData[chart].mappingID = formulaID
if (this.$refs.chart_ref != null) {
this.$refs.chart_ref.forEach(ref => {
ref.refreshMappingSelect()
})
}
})
this.pageToast('The formula [' + formulaID + '] has been registered.')
},
removeFormula: function (formulaID) {
for (const chart in this.chartData) {
if (this.chartData[chart].mappingID === formulaID) {
dataStreamBuffer.removeByChart(chart)
this.removeChart(chart)
}
}
this.pageToast('The formula [' + formulaID + '] has been removed.')
},
startAllClick: async function () {
for (const device of this.deviceList) {
if (this.$refs.devices_ref === undefined) {
this.startDevice(device)
} else {
await this.$refs.devices_ref.$refs.pdlist_ref.start(device)
}
}
this.refreshDevicesWindow()
this.pageToast('The all devices have been started')
},
startDevice: async function (device) {
await this.taskContentChartDefaultChartGenerator({
_deviceList: this.deviceList,
_itemID: device.id,
_chartID: null,
_type: 'device',
})
if (!taskInfo.getDeviceInfo(device.id).info.isSync) {
if (taskInfo.getDeviceInfo(device.id).info.library_name.startsWith('Neulive')) {
this.mqttPub(taskInfo.getTaskInfo().controllerID + '_user', JSON.stringify({
header: 'device_instruction/0',
device: taskInfo.getRawDeviceID(device.id),
instruction: 'record',
}))
} else if (taskInfo.getDeviceInfo(device.id).info.library_name.startsWith('Elite')) {
// console.log('elite')
this.mqttPub(taskInfo.getTaskInfo().controllerID + '_user', JSON.stringify({
header: 'device_instruction/0',
device: taskInfo.getRawDeviceID(device.id),
instruction: 'start',
}))
}
device.stopping = false
device.isSync = true
// this.$emit('refreshSetting')
// ### show device info
// console.log(taskInfo.getDeviceInfo(device.id))
}
},
stopAllClick: function () {
for (const device of this.deviceList) {
if (this.$refs.devices_ref === undefined) {
this.stopDevice(device)
} else {
this.$refs.devices_ref.stopDevice(device)
}
}
this.pageToast('The all devices have been stopped')
},
stopDevice: async function (device) {
dataStreamBuffer.removeByDevice(taskInfo.getRawDeviceID(device.id))
if (taskInfo.getDeviceInfo(device.id).info.isSync) {
if (taskInfo.getDeviceInfo(device.id).info.library_name.startsWith('Neulive')) {
this.mqttPub(taskInfo.getTaskInfo().controllerID + '_user', JSON.stringify({
header: 'device_instruction/0',
device: taskInfo.getRawDeviceID(device.id),
instruction: 'stop_record',
}))
} else if (taskInfo.getDeviceInfo(device.id).info.library_name.startsWith('Elite')) {
this.mqttPub(taskInfo.getTaskInfo().controllerID + '_user', JSON.stringify({
header: 'device_instruction/0',
device: taskInfo.getRawDeviceID(device.id),
instruction: 'interrupt',
}))
}
device.stopping = true
}
},
exit: function () {
this.$router.push({
path: '/',
})
},
...mapActions('taskContent', [
taskTypes.chart.add,
taskTypes.chart.refreshData,
taskTypes.chart.defaultChartGenerator,
taskTypes.chart.reset,
]),
},
watch: {
},
async mounted () {
await taskInfo.updateTaskInfo(this.$route.params.taskID)
// console.log(taskInfo.getTaskInfo())
// this.screenHeight = document.documentElement.clientHeight
this.pageMqttSub(taskInfo.getTaskInfo().controllerID)
// console.log(taskInfo.getTaskInfo().controllerID)
await this.pageInit()
// this.chartNumber = taskInfo.getTaskInfo().chartNumber
this.dataRefreshTimer = setInterval(this.refreshData, 100)
// const _this = this
// window.onresize = function () { // define the event of window size changing
// // _this.screenWidth = document.documentElement.clientWidth
// _this.screenHeight = document.documentElement.clientHeight
// }
},
destroyed () {
taskInfo.destroyed(this.deviceList)
for (const chart in this.chartData) {
this.removeChart(chart)
}
clearInterval(this.dataRefreshTimer)
this.pageMqttUnSub(taskInfo.getTaskInfo().controllerID)
},
}
</script>
<style lang="scss">
// .area-style {
// height: 100%;
// overflow-y: hidden;
// overflow-x: hidden;
// @include media-breakpoint-only(xl) {
// height: 94vh;
// overflow-y: scroll;
// overflow-x: hidden;
// }
// }
.no-dark-style-va-button {
&:focus {
filter: brightness(100%);
}
}
</style>
@@ -105,7 +105,7 @@
</div>
</div>
<div v-else-if="tabValue == 1" :style="'width: '+ cardwidth + '; height: ' + cardheight + ';'" >
<canvas-chart-source :chartID="chartID" />
<canvas-chart-source :chartID="chartID" @detect="detect"/>
</div>
<div v-else :style="'width: '+ cardwidth + '; height: ' + cardheight + ';'" >
</div>
@@ -173,8 +173,9 @@ export default {
computed: {
chartInfo () {
if (this.data === undefined || this.data === null) return ''
if (this.data.mappingID === undefined || this.data.mappingID === '-1') return ''
const device = this.deviceListNew.find(ele => String(ele.memory_board) === String(this.data.mappingID))
if (this.data.mappingID.length === 0) return ''
const device = this.deviceListNew.find(ele => this.data.mappingID.includes(ele.mac_address))
if (device === undefined) return ''
const deviceMode = configTable.getModeConfig(device.library_name, device.configuration.MODE).name
return `${device.name}_[${device.memory_board}] | MAC_${device.mac_address.toUpperCase()} | ${this.data.createdBy} chart: ${deviceMode}`
},
@@ -210,6 +211,9 @@ export default {
}
},
methods: {
detect: function (device) {
this.$emit('detect', device)
},
getClicked: function (clicked) {
this.calClicked = clicked
},
@@ -343,15 +347,15 @@ 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) {
taskInfo.getMappingList().forEach(item => {
if (item.id === this.chartData[this.chartID].mappingID) {
// console.log('item.name: ', item.name)
this.setChartName(item.name)
}
})
}
// this.setMappingSelect(this.chartData[this.chartID].mappingID)
// if (this.chartData[this.chartID].mappingID.length === 0 && this.chartData[this.chartID].mappingIDl) {
// taskInfo.getMappingList().forEach(item => {
// if (item.id === this.chartData[this.chartID].mappingID) {
// // console.log('item.name: ', item.name)
// this.setChartName(item.name)
// }
// })
// }
},
setChartName: function (name) {
this.chartData[this.chartID].cardName = name
@@ -290,7 +290,7 @@ export default {
this.getClicked(false)
}
this.data.xAxis[0].type = 'value'
if (this.xName !== 'TIME') {
if (this.xName !== 'Time') {
// console.log('not time')
this.data.xAxis[0].max = (value) => {
if (value.max < 0) {
@@ -314,7 +314,7 @@ export default {
this.$emit('switchModeButton', 'default', 0, 0)
}
// TODO: modify the redundant code
if (this.xName === 'TIME') {
if (this.xName === 'Time') {
this.data.xAxis[0].axisLabel.formatter = function (val) {
return getTimeFormatter(val)
}
@@ -327,7 +327,7 @@ export default {
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))
const device = this.deviceListNew.find(ele => this.data.mappingID.includes(ele.mac_address))
if (device !== undefined) {
if (device.status === 0 || device.status === 1) {
this.watchHandler()
@@ -349,7 +349,7 @@ export default {
this.disableDiff = true
this.disableInt = true
}
const device = this.deviceListNew.find(ele => String(ele.memory_board) === String(this.data.mappingID))
const device = this.deviceListNew.find(ele => this.data.mappingID.includes(ele.mac_address))
if (device !== undefined) {
if (device.status === 0 || device.status === 1) {
this.watchHandler()
@@ -371,7 +371,7 @@ export default {
this.disableDiff = true
this.disableInt = true
}
const device = this.deviceListNew.find(ele => String(ele.memory_board) === String(this.data.mappingID))
const device = this.deviceListNew.find(ele => this.data.mappingID.includes(ele.mac_address))
if (device !== undefined) {
if (device.status === 0 || device.status === 1) {
this.watchHandler()
@@ -382,7 +382,7 @@ export default {
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))
const device = this.deviceListNew.find(ele => this.data.mappingID.includes(ele.mac_address))
if (device !== undefined) {
if (device.status === 0 || device.status === 1) {
this.watchHandler()
@@ -391,22 +391,22 @@ export default {
},
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
const xChannel = this.data.gridSource[0][0].xSource.channel
const yChannel = this.data.gridSource[0][0].ySource.channel
this.xName = xChannel
this.yName = yChannel
if ((xChannel === 1 && yChannel === 2) || (xChannel === 2 && yChannel === 1)) {
this.mode_name = 'I-V Curve'
}
if ((xChannel === 'Time' && yChannel === 1) || (xChannel === 1 && yChannel === 'Time')) {
this.mode_name = 'I-T Graph'
}
}
},
// 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
const xChannel = this.data.gridSource[0][0].xSource.channel
return (xChannel === 'Time') ? 0 : 2
},
// these function below are using for print out the data (debug)
getAlldata: function () {
@@ -423,7 +423,7 @@ export default {
getSampleRate: function () {
try {
const deviceMappingID = this.chartData[this.chartID].mappingID
const device = this.deviceListNew.find(ele => ele.memory_board === deviceMappingID)
const device = this.deviceListNew.find(ele => deviceMappingID.includes(ele.mac_address))
const deviceConfig = configTable.getConfig(deviceMappingID)
const voltStep = deviceConfig.VOLT_STEP.outputReadabilityData(device.configuration.VOLT_STEP)
const sampleRate = deviceConfig.SAMPLE_RATE.outputReadabilityData(device.configuration.SAMPLE_RATE)
@@ -126,21 +126,70 @@ export default {
taskTypes.chart.saveToCache,
]),
getDeviceMode: function () {
const device = this.deviceListNew.find(ele => String(ele.memory_board) === String(this.chartData[this.chartID].mappingID))
const device = this.deviceListNew.find(ele => this.data.mappingID.includes(ele.mac_address))
if (device === undefined) return
return device.configuration.MODE
},
getChannelConfiguration: function () {
const device = this.deviceListNew.find(ele => this.data.mappingID.includes(ele.mac_address))
if (device === undefined) return
return configTable.getChannelConfig(device.configuration._LIBRARY_, device.configuration.MODE)
},
// set a new display tool
setRealTime: function (plotIndex, curveIndex) {
// construct realTime object, i.e., record the coressponding value and unit
// the formate imitates the data.gridSource
const channelInfo = this.getChannelConfiguration()
if (this.data !== undefined && this.data.gridSource !== undefined) {
let _xPhysicsQuantity = this.data.gridSource[plotIndex][curveIndex].name.split('_')[0].split('-').at(-1)
let _yPhysicsQuantity = this.data.gridSource[plotIndex][curveIndex].name.split('_')[1].split('-').at(-1)
// Potential
if (_xPhysicsQuantity === 'P') _xPhysicsQuantity = 'V'
if (_yPhysicsQuantity === 'P') _yPhysicsQuantity = 'V'
const [_xAxis, _yAxis] = this.chartRouter.getChartTable(_xPhysicsQuantity, _yPhysicsQuantity)
const x = this.data.gridSource[plotIndex][curveIndex].xSource
const y = this.data.gridSource[plotIndex][curveIndex].ySource
let _xAxis
let _yAxis
if (channelInfo) {
if (x.name === 'Time') {
_xAxis = { default: channelInfo.time }
} else {
let xInfo = channelInfo[x.channel - 1]
if (xInfo === undefined) {
xInfo = {
name: '',
defaultUnit: '',
unit: {},
}
}
_xAxis = { default: xInfo }
}
if (y.name === 'Time') {
_yAxis = { default: channelInfo.time }
} else {
let yInfo = channelInfo[y.channel - 1]
if (yInfo === undefined) {
yInfo = {
name: '',
defaultUnit: '',
unit: {},
}
}
_yAxis = { default: yInfo }
}
} else {
_xAxis = {
default: {
name: '',
defaultUnit: '',
unit: {},
},
}
_yAxis = {
default: {
name: '',
defaultUnit: '',
unit: {},
},
}
}
const _realTime = JSON.parse(JSON.stringify(this.realTime))
const _newCurve = {}
// set name, sourceIndex in data.series
@@ -276,6 +325,16 @@ export default {
let _xPhysicsQuantity = this.data.gridSource[plotIndex][curveIndex].name.split('_')[0].split('-').at(-1)
let _yPhysicsQuantity = this.data.gridSource[plotIndex][curveIndex].name.split('_')[1].split('-').at(-1)
// Potential
if (!_xPhysicsQuantity.includes('ZReal') && !_xPhysicsQuantity.includes('ZImag')) {
_xPhysicsQuantity = _xPhysicsQuantity.substring(0, 1)
} else {
_xPhysicsQuantity = _xPhysicsQuantity.substring(0, 5)
}
if (!_yPhysicsQuantity.includes('ZReal') && !_yPhysicsQuantity.includes('ZImag')) {
_yPhysicsQuantity = _yPhysicsQuantity.substring(0, 1)
} else {
_yPhysicsQuantity = _yPhysicsQuantity.substring(0, 5)
}
if (_xPhysicsQuantity === 'P') _xPhysicsQuantity = 'V'
if (_yPhysicsQuantity === 'P') _yPhysicsQuantity = 'V'
const [_xAxis, _yAxis] = this.chartRouter.getChartTable(_xPhysicsQuantity, _yPhysicsQuantity)
@@ -1,5 +1,33 @@
<template>
<div style="height: 350px; overflow-y: scroll; overflow-x: hidden;">
<div style="">
<div class="mb-3" v-if="chart">
<div class="row">
<div v-for="id in chart.mappingID" :key="id">
<va-button @click="test(id)">{{id}}</va-button>
</div>
</div>
<va-tree-root>
<va-tree-category
style="font-size: 20px;"
v-for="(grid,index) in chart.grid"
:key="grid.index"
:label="'Subplot ' + index"
isOpen
>
<va-tree-node
v-for="(series, index) in chart.gridSource[grid.index]"
:key="series.name"
>
<div class="row align--center ml-3">
<va-badge class="mb-0" style="font-size: 14px;" color="primary">{{series.name}}</va-badge>
<va-badge class="mb-0" style="font-size: 14px;" color="primary" outline>{{getSourceInfo(series.xSource)}}</va-badge>
<va-badge class="mb-0" style="font-size: 14px;" color="primary" outline>{{getSourceInfo(series.ySource)}}</va-badge>
<va-button @click="removeGridSource(chartID, grid.index, index)" size="small" flat>X</va-button>
</div>
</va-tree-node>
</va-tree-category>
</va-tree-root>
</div>
<div>
<div class="flex row align--center">
<div class="flex md3 xl3 xs3 sm3">
@@ -49,39 +77,17 @@
</div>
<va-button :disabled="sourceAddStatus" class="flex md3 xl3 xs3 sm3 pa-1" @click="addRegisterDeviceChannel(gridSelection.id)" >
Add
</va-button><span class="ml-2" style="color: red;">{{error}}</span>
</va-button>
<!-- <span class="ml-2" style="color: red;">{{error}}</span> -->
<va-button @click="addGrid()">
Add Subplot
</va-button>
<va-button @click="removeGrid(chartID)">
Remove Subplot
</va-button>
</div>
</div>
<va-tree-root>
<va-tree-category
style="font-size: 20px;"
v-for="grid in chartData[chartID].grid"
:key="grid.index"
:label="'Subplot ' + grid.index"
>
<va-tree-node
v-for="series in chartData[chartID].gridSource[grid.index]"
:key="series.name"
>
<div class="flex row align--center">
<va-badge class="mb-0" style="font-size: 14px;" color="primary">{{series.name}}</va-badge>
<va-badge class="mb-0" style="font-size: 14px;" color="primary" outline>{{series.xAxis}}</va-badge>
<va-badge class="mb-0" style="font-size: 14px;" color="primary" outline>{{series.yAxis}}</va-badge>
<!-- <va-icon
name="ion ion-md-close"
color="info"
class="ml-2 pa-1 shrink"
style="cursor: pointer;"
@click.native="removeProduct(product)"
/> -->
</div>
</va-tree-node>
</va-tree-category>
</va-tree-root>
<va-button @click="addGrid()">
Add Subplot
</va-button>
<DeviceModal ref="device_modal_ref" @changeDevice="changeDevice" @detect="detect"></DeviceModal>
</div>
</template>
@@ -91,9 +97,14 @@ import { mapFields } from 'vuex-map-fields'
import { mapActions } from 'vuex'
import taskTypes from '@/store/modules/task/content/types'
import configTable from '../../../../data/config-table'
import { dataStreamBuffer } from '@/data/task/DataStreamBuffer'
import DeviceModal from './DeviceModal.vue'
export default {
name: 'canvas-chart-source',
components: {
DeviceModal,
},
props: {
chartID: {
type: [Number, String],
@@ -119,8 +130,11 @@ export default {
}
},
computed: {
chart () {
return this.chartData[this.chartID]
},
deviceOptions () {
const defaultArray = [{ id: -1, name: 'Time' }]
const defaultArray = [{ id: 'Time', name: 'Time', channel: 'Time' }]
defaultArray.push(...this.deviceListNew.map(ele => {
return {
name: `[${ele.memory_board}] ${ele.name}`,
@@ -292,6 +306,56 @@ export default {
},
},
methods: {
detect (device) {
this.$emit('detect', device)
},
changeDevice (deviceList) {
const [oldDevice, newDevice] = deviceList
const oldMac = oldDevice
const newMac = newDevice
this.chart.mappingID.length = 0
this.chart.mappingID.push(newMac)
for (const grid of this.chart.grid) {
for (const gridSource of this.chart.gridSource[grid.index]) {
if (gridSource.xSource.mac_address === oldMac) {
gridSource.xSource.mac_address = newMac
dataStreamBuffer.register(this.chartID, newMac, gridSource.xSource.channel)
dataStreamBuffer.remove(this.chartID, oldMac)
}
if (gridSource.ySource.mac_address === oldMac) {
gridSource.ySource.mac_address = newMac
dataStreamBuffer.register(this.chartID, newMac, gridSource.ySource.channel)
dataStreamBuffer.remove(this.chartID, oldMac)
}
}
}
for (const series of this.chart.series) {
if (series.xAxisSource[0] === oldMac) {
series.xAxisSource[0] = newMac
series.data.length = 0
}
if (series.yAxisSource[0] === oldMac) {
series.yAxisSource[0] = newMac
series.data.length = 0
}
}
},
test (deviceID) {
this.$refs.device_modal_ref.initSetting(deviceID)
this.$refs.device_modal_ref.show()
},
getSourceInfo (source) {
if (source.name === 'Time') {
return 'Time'
}
if (source.mac_address) {
return `${source.mac_address.slice(12, 18)} Channel ${source.channel}`
}
return ''
},
updateGridOptions () {
this.gridOptions = []
for (let i = 0; i < this.chartData[this.chartID].grid.length; i++) {
@@ -352,9 +416,11 @@ export default {
gridIndex: gridIndex,
deviceNameX: deviceNameX,
deviceIDX: deviceIDX,
deviceX: deviceXInfo,
channelX: channelX,
deviceNameY: deviceNameY,
deviceIDY: deviceIDY,
deviceY: deviceYInfo,
channelY: channelY,
formula: null,
})
@@ -396,9 +462,9 @@ export default {
}
if (this.channelSelectX.id != null && this.channelSelectY.id != null) {
this.sourceAddStatus = false
} else if (this.channelSelectX.id != null && this.deviceSelectY.id < 0) {
} else if (this.channelSelectX.id != null && this.deviceSelectY.id === 'Time') {
this.sourceAddStatus = false
} else if (this.channelSelectY.id != null && this.deviceSelectX.id < 0) {
} else if (this.channelSelectY.id != null && this.deviceSelectX.id === 'Time') {
this.sourceAddStatus = false
} else {
this.sourceAddStatus = true
@@ -407,11 +473,35 @@ export default {
removeProduct (product) {
this.products = this.products.filter(productToFilter => productToFilter !== product)
},
async removeGridSource (chartID, gridIndex, gridSourceIndex) {
await this.taskRemoveGridSource({
chartID: chartID,
gridIndex: gridIndex,
gridSourceIndex: gridSourceIndex,
})
await this.taskContentChartSaveToCache({ controllerID: taskInfo.getTaskInfo().controllerID })
},
async removeGrid (chartID) {
if (this.chartData[chartID].grid.length > 1) {
await this.taskRemoveGrid({
chartID: chartID,
gridIndex: this.chartData[chartID].grid.length - 1,
})
}
this.taskContentChartUpdateGridList({
chartID: this.chartID,
length: this.chartData[this.chartID].grid.length,
})
this.updateGridOptions()
await this.taskContentChartSaveToCache({ controllerID: taskInfo.getTaskInfo().controllerID })
},
...mapActions('taskContent', [
taskTypes.chart.register,
taskTypes.chart.updateGridList,
taskTypes.chart.saveToCache,
taskTypes.chart.removeGridSource,
taskTypes.chart.removeGrid,
]),
},
mounted () {
@@ -0,0 +1,647 @@
<template>
<div style="">
<div class="mb-3" v-if="chart">
<div class="row">
<div v-for="id in chart.mappingID" :key="id">
<va-button @click="test(id)" small>{{id}}</va-button>
</div>
</div>
<va-tree-root>
<va-tree-category
style="font-size: 20px;"
v-for="(grid,index) in chart.grid"
:key="grid.index"
:label="'Subplot ' + index"
isOpen
>
<va-tree-node
v-for="(series, index) in chart.gridSource[grid.index]"
:key="series.name"
>
<div class="row flex d-flex align--center ml-3">
<!-- <va-badge class="mb-0" style="font-size: 14px;" color="primary">{{series.name}}</va-badge> -->
<va-badge class="mb-0" style="font-size: 14px;" color="primary" outline>{{getSourceInfo(series.xSource)}}</va-badge>
<va-badge class="mb-0" style="font-size: 14px;" color="primary" outline>{{getSourceInfo(series.ySource)}}</va-badge>
<div>
<va-button flat small color="gray" icon="fa fa-pencil" @click.stop="changeGridSource(chartID, grid.index, index)"/>
<va-button flat small color="gray" icon="fa fa-trash" @click.stop="removeGridSource(chartID, grid.index, index)"/>
</div>
</div>
</va-tree-node>
<div v-if="grid.index">
<va-icon name="fa fa-plus" color="gray" style="cursor: pointer;" @click.native="createNewGridSource(chartID, grid.index, chartData[chartID].gridSource[grid.index].length)"></va-icon>
</div>
<div v-else>
<va-icon name="fa fa-plus" color="gray" style="cursor: pointer;" @click.native="createNewGridSource(chartID, 0,0)"></va-icon>
</div>
</va-tree-category>
</va-tree-root>
</div>
<div v-if="showChangeInput">
<div class="flex row align--center">
<div class="flex md3 xl3 xs4 sm6">
<va-select
small
:label="'X SOURCE'"
v-model="deviceSelectX"
textBy="name"
:noClear='true'
:options="deviceOptions"
/>
</div>
<div class="flex md3 xl2 xs4 sm6">
<va-select
:on-change="channelSelectXChange()"
:label="'X CHANNEL'"
v-model="channelSelectX"
textBy="channel"
:options="channelOptionsX"
:noClear='true'
:disabled="channelSelectDisableX"
/>
</div>
<div class="flex md3 xl3 xs4 sm6">
<va-select
:label="'Y SOURCE'"
v-model="deviceSelectY"
textBy="name"
:noClear='true'
:options="deviceOptions"
/>
</div>
<div class="flex md2 xl2 xs4 sm6">
<va-select
:on-change="channelSelectYChange()"
:label="'Y CHANNEL'"
v-model="channelSelectY"
textBy="channel"
:noClear='true'
:options="channelOptionsY"
:disabled="channelSelectDisableY"
/>
</div>
<!-- <div class="flex px-0 md3 xl1 xs4 sm6">
<va-select
:label="'SubPlot'"
v-model="gridSelection"
textBy="value"
:noClear='true'
:options="gridOptions"
/>
</div> -->
<div>
<va-icon name="fa fa-times" color="gray" style="cursor: pointer;" @click.native="cancel"></va-icon>
<va-icon class="mx-3" name="fa fa-check" color="gray" style="cursor: pointer;" @click.native="saveGrid" ></va-icon>
</div>
<!-- <span class="ml-2" style="color: red;">{{error}}</span> -->
</div>
<div>
<va-button @click="addGrid()">
Add Subplot
</va-button>
<va-button @click="removeGrid(chartID)">
Remove Subplot
</va-button>
</div>
</div>
<DeviceModal ref="device_modal_ref" @changeDevice="changeDevice" @detect="detect"></DeviceModal>
</div>
</template>
<script>
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 configTable from '../../../../data/config-table'
import { dataStreamBuffer } from '@/data/task/DataStreamBuffer'
import DeviceModal from './DeviceModal.vue'
export default {
name: 'canvas-chart-source',
components: {
DeviceModal,
},
props: {
chartID: {
type: [Number, String],
required: true,
},
},
data () {
return {
showChangeInput: false,
gridIndexSave: -1,
sourceIndexSave: -1,
error: '',
gridSelection: '0',
gridOptions: [],
channelSelectX: '',
channelOptionsX: [],
channelSelectY: '',
channelOptionsY: [],
channelSelectDisableX: false,
channelSelectDisableY: false,
deviceSelectX: '',
deviceSelectY: '',
// deviceOptions:,
sourceAddStatus: true,
sourceList: [],
}
},
computed: {
chart () {
return this.chartData[this.chartID]
},
deviceOptions () {
const defaultArray = [{ id: 'Time', name: 'Time', channel: 'Time' }]
defaultArray.push(...this.deviceListNew.map(ele => {
return {
name: `[${ele.memory_board}] ${ele.name}`,
id: ele.memory_board,
}
}))
return defaultArray
},
...mapFields('taskContent', [
'chartData',
'deviceListNew',
]),
},
watch: {
deviceOptions: function (val) {
this.clearSelectOptions()
},
deviceSelectX: function () {
const channelOptions = []
const deviceInfo = this.deviceListNew.find(ele => ele.id === this.deviceSelectX.id)
// console.log('deviceInfo', deviceInfo.library_name, deviceInfo.configuration.MODE)
// console.log('sourceObj', Object.keys(sourceObj))
if (deviceInfo == null) {
this.channelSelectDisableX = true
} else if (deviceInfo.library_name.includes('Neulive')) {
const channelSet = taskInfo.getDeviceInfo(this.deviceSelectX.id).parameterSet.RECORDING_CH.toString(2).split('').reverse()
channelSet.forEach((element, index) => {
if (parseInt(element) > 0) {
channelOptions.push({
id: index + 1,
channel: 'Channel ' + (index + 1),
})
// console.log(index, element)
}
})
const axisChannelSet = taskInfo.getDeviceInfo(this.deviceSelectX.id).parameterSet.AXIS_CH.toString(2).split('').reverse()
axisChannelSet.forEach((element, index) => {
if (parseInt(element) === 1) {
if (index === 0) {
channelOptions.push({
id: 257,
channel: 'X-AXIS',
})
} else if (index === 1) {
channelOptions.push({
id: 258,
channel: 'Y-AXIS',
})
} else if (index === 2) {
channelOptions.push({
id: 259,
channel: 'Z-AXIS',
})
} else if (index === 3) {
channelOptions.push({
id: 260,
channel: 'M-AXIS',
})
}
}
})
this.channelSelectDisableX = false
} else if (deviceInfo.library_name.includes('Elite')) {
const sourceObj = configTable.getChannelConfig(String(deviceInfo.library_name), deviceInfo.configuration.MODE) // [{id:0 channel:'Current'}, {id:1, channel:'Voltage'}, ]
let channelSet
if (deviceInfo.library_name.includes('EIS') && (deviceInfo.configuration.MODE === 0 || deviceInfo.configuration.MODE === 5)) {
channelSet = ['Zimag_Raw', 'Zreal_Raw', 'Frequency', 'Cycle', 'Zimag', 'Zreal', 'Impedance', 'Phase', 'Current', 'Level gain']
} else {
channelSet = []
const keys = Object.keys(sourceObj)
for (let i = 0; i < keys.length; i++) {
const item = keys[i]
if (sourceObj[item].name !== 'Time' && sourceObj[item].name !== 'Cycle number') {
channelSet.push(String(sourceObj[item].name))
}
}
}
// console.log(channelSet)
channelSet.forEach((element, index) => {
channelOptions.push({
id: index + 1,
channel: element,
})
})
this.channelSelectDisableX = false
} else {
this.channelSelectDisableX = true
}
this.channelSelectX = ''
this.channelOptionsX.length = 0
this.channelOptionsX = channelOptions
this.checkSourceAddStatus()
},
deviceSelectY: function () {
const channelOptions = []
const deviceInfo = this.deviceListNew.find(ele => ele.id === this.deviceSelectY.id)
// console.log(val)
if (deviceInfo == null) {
this.channelSelectDisableY = true
} else if (deviceInfo.library_name.indexOf('Neulive') >= 0) {
const channelSet = taskInfo.getDeviceInfo(this.deviceSelectY.id).parameterSet.RECORDING_CH.toString(2).split('').reverse()
// console.log(channelSet)
channelSet.forEach((element, index) => {
if (parseInt(element) > 0) {
channelOptions.push({
id: index + 1,
channel: 'Channel ' + (index + 1),
})
// console.log(index, element)
}
})
const axisChannelSet = taskInfo.getDeviceInfo(this.deviceSelectY.id).parameterSet.AXIS_CH.toString(2).split('').reverse()
axisChannelSet.forEach((element, index) => {
if (parseInt(element) === 1) {
if (index === 0) {
channelOptions.push({
id: 257,
channel: 'X-AXIS',
})
} else if (index === 1) {
channelOptions.push({
id: 258,
channel: 'Y-AXIS',
})
} else if (index === 2) {
channelOptions.push({
id: 259,
channel: 'Z-AXIS',
})
} else if (index === 3) {
channelOptions.push({
id: 260,
channel: 'M-AXIS',
})
}
}
})
this.channelSelectDisableY = false
} else if (deviceInfo.library_name.indexOf('Elite') >= 0) {
const sourceObj = configTable.getChannelConfig(String(deviceInfo.library_name), deviceInfo.configuration.MODE) // [{id:0 channel:'Current'}, {id:1, channel:'Voltage'}, ]
let channelSet
if (deviceInfo.library_name.includes('EIS') && (deviceInfo.configuration.MODE === 0 || deviceInfo.configuration.MODE === 5)) {
channelSet = ['Zimag_Raw', 'Zreal_Raw', 'Frequency', 'Cycle', 'Zimag', 'Zreal', 'Impedance', 'Phase', 'Current', 'Level gain']
} else {
channelSet = []
const keys = Object.keys(sourceObj)
for (let i = 0; i < keys.length; i++) {
const item = keys[i]
if (sourceObj[item].name !== 'Time' && sourceObj[item].name !== 'Cycle number') {
channelSet.push(String(sourceObj[item].name))
}
}
}
// console.log(channelSet)
channelSet.forEach((element, index) => {
channelOptions.push({
id: index + 1,
channel: element,
})
})
this.channelSelectDisableY = false
} else {
this.channelSelectDisableY = true
}
this.channelSelectY = ''
this.channelOptionsY.length = 0
this.channelOptionsY = channelOptions
this.checkSourceAddStatus()
},
},
methods: {
detect (device) {
this.$emit('detect', device)
},
changeDevice (deviceList) {
const [oldDevice, newDevice] = deviceList
const oldMac = oldDevice
const newMac = newDevice
this.chart.mappingID.length = 0
this.chart.mappingID.push(newMac)
for (const grid of this.chart.grid) {
for (const gridSource of this.chart.gridSource[grid.index]) {
if (gridSource.xSource.mac_address === oldMac) {
gridSource.xSource.mac_address = newMac
dataStreamBuffer.register(this.chartID, newMac, gridSource.xSource.channel)
dataStreamBuffer.remove(this.chartID, oldMac)
}
if (gridSource.ySource.mac_address === oldMac) {
gridSource.ySource.mac_address = newMac
dataStreamBuffer.register(this.chartID, newMac, gridSource.ySource.channel)
dataStreamBuffer.remove(this.chartID, oldMac)
}
}
}
for (const series of this.chart.series) {
if (series.xAxisSource[0] === oldMac) {
series.xAxisSource[0] = newMac
series.data.length = 0
}
if (series.yAxisSource[0] === oldMac) {
series.yAxisSource[0] = newMac
series.data.length = 0
}
}
},
cancel () {
this.showChangeInput = false
this.clearSelectOptions()
},
test (deviceID) {
this.$refs.device_modal_ref.initSetting(deviceID)
this.$refs.device_modal_ref.show()
},
getSourceInfo (source) {
if (source.name === 'Time') {
return 'Time'
}
if (source.mac_address) {
return `${source.mac_address.slice(12, 18)} Channel ${source.channel}`
}
return ''
},
updateGridOptions () {
this.gridOptions = []
for (let i = 0; i < this.chartData[this.chartID].grid.length; i++) {
this.gridOptions.push({
id: i,
value: String(i),
})
}
},
channelSelectYChange: function () {
this.checkSourceAddStatus()
},
channelSelectXChange: function () {
this.checkSourceAddStatus()
},
clearSelectOptions: function () {
this.channelSelectX = ''
this.channelOptionsX = []
this.channelSelectY = ''
this.channelOptionsY = []
this.deviceSelectX = ''
this.deviceSelectY = ''
this.gridSelection = ''
},
async addRegisterDeviceChannel (gridIndex) {
const deviceXInfo = this.deviceListNew.find(ele => ele.id === this.deviceSelectX.id)
const deviceYInfo = this.deviceListNew.find(ele => ele.id === this.deviceSelectY.id)
let deviceNameX
let deviceNameY
const deviceIDX = this.deviceSelectX.id
const deviceIDY = this.deviceSelectY.id
const channelX = this.channelSelectX.id
const channelY = this.channelSelectY.id
if (this.deviceSelectX.name.indexOf('Neulive') >= 0) {
deviceNameX = 'Neulive'
} else if (this.deviceSelectX.name.indexOf('Elite') >= 0) {
if (deviceXInfo.library_name.includes('EIS')) {
deviceNameX = 'EliteEIS'
} else {
deviceNameX = 'Elite'
}
} else if (this.deviceSelectX.name.indexOf('Time') >= 0) {
deviceNameX = 'Time'
}
if (this.deviceSelectY.name.indexOf('Neulive') >= 0) {
deviceNameY = 'Neulive'
} else if (this.deviceSelectY.name.indexOf('Elite') >= 0) {
if (deviceYInfo.library_name.includes('EIS')) {
deviceNameY = 'EliteEIS'
} else {
deviceNameY = 'Elite'
}
} else if (this.deviceSelectY.name.indexOf('Time') >= 0) {
deviceNameY = 'Time'
}
this.taskContentChartRegister({
chartID: this.chartID,
gridIndex: gridIndex,
deviceNameX: deviceNameX,
deviceIDX: deviceIDX,
deviceX: deviceXInfo,
channelX: channelX,
deviceNameY: deviceNameY,
deviceIDY: deviceIDY,
deviceY: deviceYInfo,
channelY: channelY,
formula: null,
})
console.log('deviceSelectX', this.deviceSelectX)
if (deviceNameX !== 'Time') {
this.sourceList.push([this.deviceSelectX.name, deviceIDX, channelX].toString())
}
if (deviceNameY !== 'Time') {
this.sourceList.push([this.deviceSelectY.name, deviceIDY, channelY].toString())
}
this.sourceAddStatus = true
this.clearSelectOptions()
await this.taskContentChartSaveToCache({ controllerID: taskInfo.getTaskInfo().controllerID })
this.$emit('addSource')
},
async addGrid () {
this.taskContentChartUpdateGridList({
chartID: this.chartID,
length: this.chartData[this.chartID].grid.length + 1,
})
this.updateGridOptions()
await this.taskContentChartSaveToCache({ controllerID: taskInfo.getTaskInfo().controllerID })
},
checkSourceAddStatus () {
// if (this.sourceList.indexOf([this.deviceSelectX.name, this.deviceSelectX.id, this.channelSelectX.id].toString()) >= 0) {
// this.error = 'The same source has been selected in a subplot.'
// this.sourceAddStatus = true
// return
// }
// if (this.sourceList.indexOf([this.deviceSelectY.name, this.deviceSelectY.id, this.channelSelectY.id].toString()) >= 0) {
// this.sourceAddStatus = true
// this.error = 'The same source has been selected in a subplot.'
// return
// }
// this.error = ''
// if (this.gridSelection.id == null) {
// this.sourceAddStatus = true
// return
// }
// if (this.channelSelectX.id != null && this.channelSelectY.id != null) {
// this.sourceAddStatus = false
// } else if (this.channelSelectX.id != null && this.deviceSelectY.id === 'Time') {
// this.sourceAddStatus = false
// } else if (this.channelSelectY.id != null && this.deviceSelectX.id === 'Time') {
// this.sourceAddStatus = false
// } else {
// this.sourceAddStatus = true
// }
},
removeProduct (product) {
this.products = this.products.filter(productToFilter => productToFilter !== product)
},
async saveGrid () {
if (this.gridIndexSave !== 0) {
await this.removeGridSource(this.chartID, this.gridIndexSave, this.sourceIndexSave)
}
console.log('saveGrid', this.gridIndexSave)
console.log(this.deviceSelectX, this.deviceSelectY, this.channelSelectX, this.channelSelectY)
const deviceXInfo = this.deviceListNew.find(ele => ele.id === this.deviceSelectX.id)
const deviceYInfo = this.deviceListNew.find(ele => ele.id === this.deviceSelectY.id)
let deviceNameX
let deviceNameY
const deviceIDX = this.deviceSelectX.id
const deviceIDY = this.deviceSelectY.id
const channelX = this.channelSelectX.id
const channelY = this.channelSelectY.id
if (this.deviceSelectX.name.indexOf('Neulive') >= 0) {
deviceNameX = 'Neulive'
} else if (this.deviceSelectX.name.indexOf('Elite') >= 0) {
if (deviceXInfo.library_name.includes('EIS')) {
deviceNameX = 'EliteEIS'
} else {
deviceNameX = 'Elite'
}
} else if (this.deviceSelectX.name.indexOf('Time') >= 0) {
deviceNameX = 'Time'
}
if (this.deviceSelectY.name.indexOf('Neulive') >= 0) {
deviceNameY = 'Neulive'
} else if (this.deviceSelectY.name.indexOf('Elite') >= 0) {
if (deviceYInfo.library_name.includes('EIS')) {
deviceNameY = 'EliteEIS'
} else {
deviceNameY = 'Elite'
}
} else if (this.deviceSelectY.name.indexOf('Time') >= 0) {
deviceNameY = 'Time'
}
this.taskContentChartRegister({
chartID: this.chartID,
gridIndex: this.gridIndexSave,
deviceNameX: deviceNameX,
deviceIDX: deviceIDX,
deviceX: deviceXInfo,
channelX: channelX,
deviceNameY: deviceNameY,
deviceIDY: deviceIDY,
deviceY: deviceYInfo,
channelY: channelY,
formula: null,
})
console.log('saveGrid', this.chartData)
this.sourceAddStatus = true
this.clearSelectOptions()
await this.taskContentChartSaveToCache({ controllerID: taskInfo.getTaskInfo().controllerID })
this.$emit('addSource')
this.showChangeInput = false
},
async removeGridSource (chartID, gridIndex, gridSourceIndex) {
await this.taskRemoveGridSource({
chartID: chartID,
gridIndex: gridIndex,
gridSourceIndex: gridSourceIndex,
})
await this.taskContentChartSaveToCache({ controllerID: taskInfo.getTaskInfo().controllerID })
},
async changeGridSource (chartID, gridIndex, gridSourceIndex) {
this.showChangeInput = true
this.gridIndexSave = gridIndex
this.sourceIndexSave = gridSourceIndex
const gridSource = this.chartData[chartID].gridSource[gridIndex][gridSourceIndex]
console.log(gridSource, chartID, gridIndex, gridSourceIndex)
if (gridSource.xSource.name === 'Time') {
this.deviceSelectX = this.deviceOptions[0]
}
if (gridSource.ySource.name === 'Time') {
this.deviceSelectY = this.deviceOptions[0]
}
if (gridSource.xSource.name !== 'Time') {
const deviceInfoX = this.deviceListNew.find(ele => ele.mac_address === gridSource.xSource.mac_address)
this.deviceSelectX = this.deviceOptions.find(ele => ele.id === deviceInfoX.id)
const xChannelList = configTable.getChannelConfig(String(deviceInfoX.library_name), deviceInfoX.configuration.MODE) // [{id:0 channel:'Current'}, {id:1, channel:'Voltage'}, ]
const xKeys = Object.keys(xChannelList)
this.channelOptionsX.length = 0
for (let i = 0; i < xKeys.length; i++) {
const item = xKeys[i]
if (xChannelList[item].name !== 'Time' && xChannelList[item].name !== 'Cycle number') {
this.channelOptionsX.push({ id: i + 1, channel: String(xChannelList[item].name) })
}
}
setTimeout(() => {
this.channelSelectX = this.channelOptionsX[gridSource.xSource.channel - 1]
}, 0)
}
if (gridSource.ySource.name !== 'Time') {
const deviceInfoY = this.deviceListNew.find(ele => ele.mac_address === gridSource.ySource.mac_address)
this.deviceSelectY = this.deviceOptions.find(ele => ele.id === deviceInfoY.id)
const yChannelList = configTable.getChannelConfig(String(deviceInfoY.library_name), deviceInfoY.configuration.MODE) // [{id:0 channel:'Current'}, {id:1, channel:'Voltage'}, ]
const yKeys = Object.keys(yChannelList)
console.log('ykeys', yKeys)
this.channelOptionsY.length = 0
for (let i = 0; i < yKeys.length; i++) {
const item = yKeys[i]
if (yChannelList[item].name !== 'Time' && yChannelList[item].name !== 'Cycle number') {
this.channelOptionsY.push({ id: i + 1, channel: String(yChannelList[item].name) })
}
}
console.log(this.channelOptionsY, gridSource.ySource.channel)
setTimeout(() => {
this.channelSelectY = this.channelOptionsY[gridSource.ySource.channel - 1]
}, 0)
}
console.log(this.channelSelectX, this.channelSelectY)
// await this.taskContentChartSaveToCache({ controllerID: taskInfo.getTaskInfo().controllerID })
},
createNewGridSource (chartID, gridIndex, gridSourceIndex) {
console.log('createNewGridSource', gridIndex, gridSourceIndex)
this.showChangeInput = true
this.gridIndexSave = gridIndex
this.sourceIndexSave = gridSourceIndex
},
async removeGrid (chartID) {
if (this.chartData[chartID].grid.length > 1) {
await this.taskRemoveGrid({
chartID: chartID,
gridIndex: this.chartData[chartID].grid.length - 1,
})
}
this.taskContentChartUpdateGridList({
chartID: this.chartID,
length: this.chartData[this.chartID].grid.length,
})
this.updateGridOptions()
await this.taskContentChartSaveToCache({ controllerID: taskInfo.getTaskInfo().controllerID })
},
...mapActions('taskContent', [
taskTypes.chart.register,
taskTypes.chart.updateGridList,
taskTypes.chart.saveToCache,
taskTypes.chart.removeGridSource,
taskTypes.chart.removeGrid,
]),
},
mounted () {
this.updateGridOptions()
},
}
</script>
@@ -1,36 +1,6 @@
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: 's',
downloadUnit: 'ms',
},
},
// 1
{
default: {
name: 'Voltage',
unit: {
uV: 1,
mV: 1e3,
V: 1e6,
},
defaultUnit: 'mV',
downloadUnit: 'mV',
},
},
],
T_I: [
// 0
{
@@ -74,168 +44,6 @@ const chartTable = {
},
},
],
T_R: [
// 0
{
default: {
name: 'Time',
unit: {
us: 1,
ms: 1e3,
s: 1e6,
min: 60 * 1e6,
hour: 60 * 60 * 1e6,
},
defaultUnit: 's',
downloadUnit: 'ms',
},
},
// 1
{
default: {
name: 'Resistance',
unit: {
: 1,
Ω: 1e3,
: 1e6,
: 1e9,
},
defaultUnit: 'Ω',
downloadUnit: 'Ω',
},
},
],
T_Impedance: [
// 0
{
default: {
name: 'Time',
unit: {
us: 1,
ms: 1e3,
s: 1e6,
min: 60 * 1e6,
hour: 60 * 60 * 1e6,
},
defaultUnit: 's',
downloadUnit: 'ms',
},
},
// 1
{
default: {
name: 'Resistance',
unit: {
: 1e-3,
Ω: 1,
: 1e3,
: 1e6,
},
defaultUnit: 'Ω',
downloadUnit: 'Ω',
},
},
],
T_Phase: [
// 0
{
default: {
name: 'Time',
unit: {
us: 1,
ms: 1e3,
s: 1e6,
min: 60 * 1e6,
hour: 60 * 60 * 1e6,
},
defaultUnit: 's',
downloadUnit: 'ms',
},
},
// 1
{
default: {
name: 'degree',
unit: {
'°': 1e3,
},
defaultUnit: '°',
downloadUnit: '°',
},
},
],
T_Current: [
// 0
// 0
{
default: {
name: 'Time',
unit: {
us: 1,
ms: 1e3,
s: 1e6,
min: 60 * 1e6,
hour: 60 * 60 * 1e6,
},
defaultUnit: 's',
downloadUnit: 'ms',
},
},
// 1
{
default: {
name: 'Current',
unit: {
nA: 1,
uA: 1e3,
mA: 1e6,
A: 1e9,
},
defaultUnit: (Mode) => { return (Mode === 10 || Mode === 11) ? 'nA' : 'mA' },
downloadUnit: 'mA',
},
// Q = ∫ I dt
integral: {
name: 'Charge',
unit: {
nAh: 3600 * 1e6,
uAh: 1600 * 1e9,
mAh: 3600 * 1e12,
Ah: 3600 * 1e15,
},
defaultUnit: 'mAh',
downloadUnit: 'mAh',
},
},
],
V_V: [
// 0
{
default: {
name: 'Voltage',
unit: {
uV: 1,
mV: 1e3,
V: 1e6,
},
defaultUnit: 'mV',
downloadUnit: 'mV',
},
},
// 1
{
default: {
name: 'Voltage',
unit: {
uV: 1,
mV: 1e3,
V: 1e6,
},
defaultUnit: 'mV',
downloadUnit: 'mV',
},
},
],
V_I: [
// 0
{
@@ -309,94 +117,6 @@ const chartTable = {
},
},
],
V_R: [
// 0
{
default: {
name: 'Voltage',
unit: {
uV: 1,
mV: 1e3,
V: 1e6,
},
defaultUnit: 'mV',
downloadUnit: 'mV',
},
},
// 1
{
default: {
name: 'Resistance',
unit: {
: 1,
Ω: 1e3,
: 1e6,
: 1e9,
},
defaultUnit: 'Ω',
downloadUnit: 'Ω',
},
},
],
I_R: [
// 0
{
default: {
name: 'Voltage',
unit: {
uV: 1,
mV: 1e3,
V: 1e6,
},
defaultUnit: 'mV',
downloadUnit: 'mV',
},
},
// 1
{
default: {
name: 'Current',
unit: {
nA: 1,
uA: 1e3,
mA: 1e6,
A: 1e9,
},
defaultUnit: (Mode) => { return (Mode === 10) ? 'nA' : 'mA' },
downloadUnit: 'mA',
},
},
],
ZReal_ZImag: [
// 0
{
default: {
name: 'Z_real',
unit: {
: 1e-3,
Ω: 1,
: 1e3,
: 1e6,
},
downloadUnit: 'Ω',
defaultUnit: 'Ω',
},
},
// 1
{
default: {
name: 'Z_imag',
unit: {
: 1e-3,
Ω: 1,
: 1e3,
: 1e6,
},
downloadUnit: 'Ω',
defaultUnit: 'Ω',
},
},
],
}
export const chartRouter = {
getChartTable: (xAxis, yAxis) => {
@@ -404,6 +124,6 @@ export const chartRouter = {
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'
else return []
},
}
@@ -0,0 +1,131 @@
<template>
<div>
<va-modal
class="flex sm12 xl12 md12 xs12"
v-model="showModal"
size="small"
:noOutsideDismiss="true"
hide-default-actions
>
<template slot="header">
<div class="d-flex mb-3">
<va-icon name="fa fa-bluetooth-b mr-3" color="primary"/>
<h5 class="mt-0 mb-0">Choose Device</h5>
</div>
</template>
<va-list fit class="mb-2 pb-0">
<va-list-label>
Connect
</va-list-label>
<va-item v-if="deviceList.length === 0">
<va-item-section>
There is no connected device.
</va-item-section>
</va-item>
<div v-else v-for="(device, index) in deviceList" :key="'connect-' + index">
<va-item :class="deviceSelect === index ? 'device-list-focus': ''" @click="selectDevice(device, index)" clickable>
<va-item-section avatar>
<va-avatar style="border-radius: 0;">
<img src='@/assets/img/elite_img.png' :alt="device.mac_address">
</va-avatar>
</va-item-section>
<va-item-section>
{{ device.mac_address }}
</va-item-section>
<va-item-section side>
<va-icon name="fa fa-map-marker" color="gray" @click.native="detect(device.mac_address)"/>
</va-item-section>
</va-item>
<!-- <va-list-separator v-if="index < deviceList.length - 1" :key="'separator-' + index" /> -->
</div>
</va-list>
<div class="flex-center sm12 xl12 md12 xs12">
<va-button @click="hide">Cancel</va-button>
<va-button @click="changeDevice">OK</va-button>
</div>
</va-modal>
</div>
</template>
<script>
import { mapFields } from 'vuex-map-fields'
export default {
name: 'device-modal',
components: {
},
computed: {
optionDeviceVersion () {
return (this.optionDeviceVersionObj[this.device.product.value] !== undefined)
? this.optionDeviceVersionObj[this.device.product.value]
: undefined
},
// ...mapGetters('project', [
// types.project.getSelect,
// types.project.getDeviceShowName,
// ]),
...mapFields('taskContent', [
'deviceListNew',
]),
},
data () {
return {
showModal: false,
showDisplayDevice: false,
key: '',
device: {},
deviceList: [],
deviceSelect: -1,
oldMac: null,
}
},
methods: {
show: function () {
this.showModal = true
},
hide: function () {
this.showModal = false
},
detect: function (device) {
if (device) this.$emit('detect', device)
},
selectDevice: function (device, index) {
this.deviceSelect = index
},
changeDevice: function () {
this.$emit('changeDevice', [this.oldMac, this.deviceList[this.deviceSelect].mac_address])
this.hide()
},
removeDevice: function () {
this.deleteDeviceProject({ deviceKey: this.key })
this.$emit('save')
this.hide()
},
getDeviceList: async function (device) {
const deviceList = this.deviceListNew
this.deviceList = [...deviceList]
},
initSetting: function (deviceID) {
this.oldMac = deviceID
this.deviceList = []
this.getDeviceList(deviceID)
this.deviceSelect = this.deviceList.findIndex(ele => ele.mac_address === deviceID)
this.device = this.deviceList[this.deviceSelect]
},
},
mounted () {
},
}
</script>
<style lang="scss">
.device-list-focus {
background: #ebedff;
border: 1px solid #dbdcf0;
box-shadow: 1px 1px 2px rgba(0, 0, 0, 0.25);
border-radius: 5px;
}
</style>
@@ -0,0 +1,300 @@
<template>
<div class="px-3 mt-3">
<div class="d-flex" style="width: 100%; justify-content: flex-end;">
<div style="margin-right: auto; align-self: center;">{{ configName }}</div>
<div class="flex d-flex px-0" style="width: 50%; background-color: #efefef; border-radius: 12px;">
<div class="d-flex" style="justify-content: space-evenly; border-right: 2.5px white solid;">
<div style="height: 32px; display: flex; align-items: center;" @click="showLibrary">
<img src="@/assets/icons/library.svg"/>
</div>
<div style="height: 32px; display: flex; align-items: center;" @click="showModal">
<img src="@/assets/icons/add-config.svg"/>
</div>
<div style="height: 32px; display: flex; align-items: center;" @click="saveConfig">
<img src="@/assets/icons/save.svg"/>
<div></div>
</div>
<div style="height: 32px; display: flex; align-items: center;" @click="showModal">
<img src="@/assets/icons/save-as.svg"/>
</div>
</div>
<div class="d-flex" style="justify-content: space-evenly;">
<div style="height: 32px; display: flex; align-items: center;" @click="addChart">
<img src="@/assets/icons/add-chart.svg"/>
</div>
<div style="height: 32px; display: flex; align-items: center;" @click="copyChart">
<img src="@/assets/icons/copy.svg"/>
</div>
<div style="height: 32px; display: flex; align-items: center;" @click="reset" >
<img src="@/assets/icons/reset.svg"/>
</div>
</div>
<!-- <div class="flex mt-2 ml-2">
<va-select
width="200px"
v-model="chartSelected"
textBy="name"
:options="chartOptions"
></va-select>
</div>
<div class="flex mt-1 ml-2">
<va-button @click="showModal">NEW</va-button>
<va-button @click="saveConfig" v-if="chartSelected && chartSelected.locked === false">SAVE</va-button>
<va-button @click="loadConfig">LOAD</va-button>
<va-button @click="deleteConfig">DELETE</va-button>
<va-button @click="addChart">ADD CHART</va-button>
</div> -->
</div>
</div>
<!-- <div>
<va-card class="mt-3" style="height: 33vh; background-color: #d9d9d9;">
setInterval
</va-card>
</div> -->
<div v-for="(chart) in chartArray" :key="chart.chartID" class="flex lg12 xl12 sm12 xs12 mt-3" style="background-color: #d9d9d9;">
<button class="accordion">
<div style="display: flex; justify-content: space-between; align-items: center; font-size: 18px;">
<div style="display: flex; margin-right: auto;">
<input type="checkbox" class="mr-3" @click.stop="handleCheckboxClick(chart.chartID)">
<span>{{ chart.cardName }}</span>
</div>
<div style="display: flex; justify-content: flex-end;"><img class="mr-2" src="@/assets/img/project/whitecross.svg" @click.stop="removeChart(chart.chartID)"/></div>
<div>
</div>
</div>
</button>
<div class="panel" style="height: 100%;">
<CanvasChartSource :chartID="chart.chartID" @detect="detect"></CanvasChartSource>
<div class="time"></div>
</div>
</div>
<!-- <div v-for="chart in chartArray" :key="chart.chartID">
<div class="row">
<div class="flex ml-2">
<span style="font-size: 28px; font-weight: 700;">{{chart.cardName}}</span>
</div>
<div class="flex" style="align-self: center;">
<va-button class="pa-0 ma-0 circle-button" small color="dark" @click="removeChart(chart.chartID)">
<va-icon
name="fa fa-times"
color="white"
/>
</va-button>
</div>
</div>
<va-list-separator class="mb-2"/>
<div class="pa-2">
<CanvasChartSource :chartID="chart.chartID" @detect="detect"></CanvasChartSource>
</div>
</div> -->
<Library :ref="'library_modal_ref'" @loadConfig="loadConfig" @deleteConfig="deleteConfig"></Library>
<SaveConfigModal :ref="'save_config_modal_ref'" @confirm="saveChart"></SaveConfigModal>
</div>
</template>
<script>
import { mapFields } from 'vuex-map-fields'
import CanvasChartSource from '../chart/CanvasChartSource1'
import api from '@/data/api/index'
import { mapActions } from 'vuex'
import taskTypes from '@/store/modules/task/content/types'
import SaveConfigModal from './SaveConfigModal.vue'
import localforage from 'localforage'
import Library from './Library.vue'
export default {
name: 'configuration',
components: {
CanvasChartSource,
SaveConfigModal,
Library,
},
computed: {
chartArray () {
if (this.chartInfo === null) return
return Object.values(this.chartInfo).sort((a, b) => {
if (a.cardName.replace('Chart', '') > b.cardName.replace('Chart', '')) {
return 1
}
if (a.cardName.replace('Chart', '') < b.cardName.replace('Chart', '')) {
return -1
}
return 0
})
},
...mapFields('taskContent', [
'chartData',
'deviceListNew',
'taskContentChartPanelKey',
'taskContentChartNumber',
]),
...mapFields('', [
'controllerID',
]),
},
data () {
return {
chartInfo: null,
saveName: '',
chartOptions: [],
chartSelected: {},
configName: '',
selectedConfigID: -1,
checkboxSelect: [],
}
},
methods: {
handleCheckboxClick: function (index) {
const selectIndex = this.checkboxSelect.indexOf(index)
if (selectIndex === -1) {
this.checkboxSelect.push(index)
} else {
this.checkboxSelect.splice(selectIndex, 1)
}
},
reset: async function () {
this.$emit('reset')
this.selectedConfigID = -1
this.configName = ''
await localforage.setItem('chartConfig_' + this.controllerID, null)
},
showLibrary: function () {
this.$refs.library_modal_ref.showModal = true
this.$refs.library_modal_ref.configArray = this.chartOptions
this.$refs.library_modal_ref.chartSelectedID = this.chartOptions.findIndex(ele => ele.id === this.selectedConfigID)
},
detect: function (device) {
this.$emit('detect', device)
},
addChart: function () {
this.$emit('add')
},
copyChart: function () {
this.$emit('copy', this.checkboxSelect)
},
removeChart: function (chartID) {
this.$emit('remove', chartID)
},
showModal: function () {
this.$refs.save_config_modal_ref.show()
},
saveChart: async function (info) {
const [name, locked] = info
const newConfig = await api.configuration.create({ name: name, locked: locked, data: this.removeSeriesDataFromChart() })
if (newConfig.status === 200) {
this.chartOptions.push(newConfig.data)
this.selectedConfigID = newConfig.data.id
this.configName = newConfig.data.name
await localforage.setItem('chartConfig_' + this.controllerID, this.selectedConfigID)
}
},
removeSeriesDataFromChart: function () {
const newChartData = JSON.parse(JSON.stringify(this.chartData))
for (const data in newChartData) {
newChartData[data].series = []
}
return newChartData
},
saveConfig: async function () {
await api.configuration.update(this.selectedConfigID, { data: this.chartData })
},
loadConfig: async function (index) {
this.chartSelected = this.chartOptions[index].data
this.configName = this.chartOptions[index].name
this.selectedConfigID = this.chartOptions[index].id
// if (this.chartSelected.id) {
this.chartData = JSON.parse(JSON.stringify(this.chartOptions[index].data))
if (Object.keys(this.chartData).length > 0) {
for (const _chart of Object.values(this.chartData)) {
_chart.legend.data.length = 0
for (let gridIndex = 0; gridIndex < _chart.grid.length; gridIndex++) {
if (gridIndex in _chart.gridSource) {
this.taskContentChartRegisterFromCache({
chartID: _chart.chartID,
gridIndex: gridIndex,
gridSource: _chart.gridSource[gridIndex],
})
}
}
}
}
await localforage.setItem('chartConfig_' + this.controllerID, this.selectedConfigID)
this.updateChart()
this.$nextTick(() => {
this.buildAccordingBlock()
})
// }
},
deleteConfig: async function (id) {
await api.configuration.update(id, { deleted: true })
await api.configuration.clearDel()
this.chartOptions = this.chartOptions.filter(ele => ele.id !== id)
this.chartSelected = {}
},
updateChart: function () {
this.chartInfo = Object.assign({}, this.chartData)
this.taskContentChartPanelKey++
},
buildAccordingBlock: function () {
const acc = document.getElementsByClassName('accordion')
for (let i = 0; i < acc.length; i++) {
const accrodingHandler = function () {
this.classList.toggle('active')
var panel = this.nextElementSibling
if (panel.style.display === 'block') {
panel.style.display = 'none'
} else {
panel.style.display = 'block'
}
}
if (!acc[i].classList.contains('set-event')) {
acc[i].addEventListener('click', accrodingHandler)
}
acc[i].classList.add('set-event')
}
},
...mapActions('taskContent', [
taskTypes.chart.registerFromCache,
]),
},
async mounted () {
setTimeout(() => {
this.buildAccordingBlock()
}, 1000)
const chartList = await api.configuration.get({})
this.chartOptions.push(...chartList.data)
const configID = await localforage.getItem('chartConfig_' + this.controllerID)
window.setTimeout(() => {
if (configID !== null) {
const configIndex = this.chartOptions.findIndex(ele => ele.id === configID)
if (configIndex >= 0) {
this.loadConfig(configIndex)
}
}
}, 500)
},
watch: {
},
}
</script>
<style>
.accordion {
background-color: #d9d9d9;
cursor: pointer;
width: 100%;
border: none;
text-align: left;
outline: none;
font-size: 15px;
transition: 0.4s;
}
.panel {
padding: 18px 18px;
display: none;
background-color: #d9d9d9;
overflow: hidden;
}
</style>
@@ -0,0 +1,79 @@
<template>
<div>
<va-modal
class="flex sm12 xl12 md12 xs12"
v-model="showModal"
size="small"
:title="'Save Config'"
:okText=" $t('modal.confirm') "
@ok="loadConfig"
@cancel="undo"
>
<va-list>
<va-item v-for="(config, i) in configArray" :class="(chartSelectedID === i) ? 'config-focus': ''" :key="i">
<va-item-section @click.native="selectConfig(config,i)">
{{ config.name }}
</va-item-section>
<va-item-section style="cursor: pointer;" @click.native.stop="deleteConfig(config, i)" side><img class="mr-2" src="@/assets/img/project/delete14_14.svg"/></va-item-section>
</va-item>
</va-list>
</va-modal>
</div>
</template>
<script>
export default {
name: 'library-modal',
components: {
},
props: {
// configArray: {
// type: [Array],
// default: () => {
// return []
// },
// },
},
data () {
return {
showModal: false,
inputValue: '',
lock: false,
chartSelectedID: -1,
configArray: [],
}
},
methods: {
confirm: function () {
this.$emit('confirm', [this.inputValue, this.lock])
},
undo: function () {
this.inputValue = ''
},
show: function () {
this.showModal = true
},
hide: function () {
this.showModal = false
},
deleteConfig: function (config, i) {
this.$emit('deleteConfig', config.id)
this.configArray.splice(i, 1)
},
loadConfig: function () {
this.$emit('loadConfig', this.chartSelectedID)
},
selectConfig: function (config, index) {
this.chartSelectedID = index
},
},
}
</script>
<style>
.config-focus {
background: #ebedff;
border: 1px solid #dbdcf0;
-webkit-box-shadow: 1px 1px 2px rgba(0, 0, 0, 0.25);
box-shadow: 1px 1px 2px rgba(0, 0, 0, 0.25);
border-radius: 5px;
}
</style>
@@ -0,0 +1,52 @@
<template>
<div>
<va-modal
class="flex sm12 xl12 md12 xs12"
v-model="showModal"
size="small"
:title="'Save Config'"
:okText=" $t('modal.confirm') "
@ok="confirm"
@cancel="undo"
>
<va-input
v-model="inputValue"
removable
/>
<va-checkbox v-model="lock">
<template slot="label">
Lock
</template>
</va-checkbox>
</va-modal>
</div>
</template>
<script>
export default {
name: 'save-config-modal',
components: {
},
data () {
return {
showModal: false,
inputValue: '',
lock: false,
}
},
methods: {
confirm: function () {
this.$emit('confirm', [this.inputValue, this.lock])
this.inputValue = ''
},
undo: function () {
this.inputValue = ''
},
show: function () {
this.showModal = true
},
hide: function () {
this.showModal = false
},
},
}
</script>
@@ -140,7 +140,7 @@ export default {
// const status = checkParam.status
// const message = checkParam.message
// if (status === true) {
this.setArchiveSettings()
await this.setArchiveSettings()
// this.$emit('start', device)
setTimeout(() => {
this.$emit('start', device)
@@ -160,7 +160,7 @@ export default {
// const message = checkParam.message
// if (status === true) {
// device.stopping = false
this.setArchiveSettings()
await this.setArchiveSettings()
setTimeout(() => {
this.$emit('record', device)
}, 500)
@@ -176,9 +176,9 @@ export default {
generateChart: function (device) {
this.$emit('generate', device)
},
setArchiveSettings: function () {
this.$refs.fcwindow_ref.forEach(ref => {
ref.setArchiveSettings()
setArchiveSettings: async function () {
this.$refs.fcwindow_ref.forEach(async (ref) => {
await ref.setArchiveSettings()
})
},
refresh: function () {
@@ -25,6 +25,9 @@
<va-item-label v-if="device.library_name.includes('EIS') || device.library_name.includes('TRIG')">
{{ `[${device.memory_board}]` }} {{ device.name }}
</va-item-label>
<va-item-label v-if="device.status !== 0">
{{ `[${device.memory_board}]` }} {{ device.name }} <va-icon class="ml-3 fa fa-battery-full" color="rgb(178 180 178)"/>
</va-item-label>
<va-item-label v-else-if="parseInt((device.battery - 2900) / 10) >= 75">
{{ `[${device.memory_board}]` }} {{ device.name }} <va-icon class="ml-3 fa fa-battery-full" color="#5BC236"/> {{ (parseInt((device.battery - 2900) / 10) > 100 ? 100 : parseInt((device.battery - 2900) / 10)) + '%' }}
</va-item-label>
@@ -94,7 +94,7 @@ export default {
})
for (const device of this.deviceListNew) {
this.$emit('add', device.memory_board)
this.$emit('add', [device.mac_address, device.memory_board])
}
},
startDevice: async function (device) {
@@ -129,9 +129,9 @@ export default {
generateChart: function (device) {
this.$emit('add', device.id)
},
setArchiveSettings: function () {
setArchiveSettings: async function () {
if (this.$refs.pdlist_ref != null) {
this.$refs.pdlist_ref.setArchiveSettings()
await this.$refs.pdlist_ref.setArchiveSettings()
}
},
refresh: function () {
@@ -2,7 +2,7 @@
<div class="flex row mt-0 pt-0 sm12 xl12 md12 xs12">
<div class="flex sm6 xl6 md6 xs6">
<va-select
:on-change="directorySelect(directory)"
@input="directorySelect(directory)"
:label="'DIRECTORY'"
v-model="directory"
textBy="name"
@@ -89,7 +89,7 @@ export default {
}
},
directorySelect: function (directoryInfo) {
if (typeof directoryInfo === 'object') {
if (directoryInfo.parent) {
if (this.device.parent.folder === undefined || this.device.parent.folder.indexOf(directoryInfo.id) === -1) {
if (this.device.status === 0) {
this.device.parent.folder = []
@@ -122,9 +122,9 @@ export default {
// directory init
const collection = await api.collection.getAll()
this.directoryOptions = collection.data.filter(el => el.name !== 'root')
if (Object.keys(this.device.parent).length === 0) {
this.directory = this.directoryOptions[0]
this.directory = this.directoryOptions.find(ele => ele.name === 'admin')
this.directorySelect(this.directory)
} else {
for (const directory of this.directoryOptions) {
if (this.device.parent.folder.includes(directory.id)) {
@@ -143,8 +143,8 @@ export default {
pageInit: async function () {
},
},
mounted () {
this.setArchiveSettings()
async mounted () {
await this.setArchiveSettings()
},
destroyed () {
},
@@ -28,7 +28,23 @@
<!-- split because of styling problem(treenode), combine together furture -->
<!-- Trigger -->
<div v-if="library && library.includes('TRIG')">
<Trigger :parameter="parameter" :parameterTable="parameterTable" @parameterChange="parameterChange"></Trigger>
<Trigger v-if="parameter.MODE === 0" :parameter="parameter" :parameterTable="parameterTable" @parameterChange="parameterChange"></Trigger>
<div v-if="parameter.MODE === 2">
<component
v-for="name in parameterArrayInMode"
:key="name"
:is="parameterTable[name].componentType"
:templateType=1
:withHeader="true"
:parameterName="name"
:inputValue="parameter[name]"
v-bind="parameterTable[name]"
@parameterChange="parameterChange"
@getParameter="getParameter"
@sendInstruction="sendInstruction"
/>
</div>
<TriggerNew v-if="parameter.MODE === 3" :parameter="parameter" :parameterTable="parameterTable" @parameterChange="parameterChange"></TriggerNew>
</div>
<!-- EIS -->
<div v-if="library && library.includes('EIS')">
@@ -48,7 +64,7 @@
/>
</div>
<!-- ZM15-PulseSensingMode -->
<div v-else-if="library && library.includes('EDC') && parameter.MODE === 14">
<div v-else-if="library && (library.includes('EDC') || library.includes('BAT')) && parameter.MODE === 14">
<EliteParameterRecordingElitePulseSensing
:parameter="parameter"
:device="device"
@@ -59,7 +75,7 @@
/>
</div>
<!-- ZM15-DPVMode -->
<div v-else-if="library && library.includes('EDC') && parameter.MODE === 15">
<div v-else-if="library && (library.includes('EDC') || library.includes('BAT')) && parameter.MODE === 15">
<EliteParameterRecordingEliteDPV
:parameter="parameter"
:device="device"
@@ -70,7 +86,7 @@
/>
</div>
<!-- ZM15-OtherModes -->
<div v-else-if="library && library.includes('EDC')">
<div v-else-if="library && (library.includes('EDC') || library.includes('BAT'))">
<va-tree-category
v-for="name in parameterArrayInMode"
:key="name"
@@ -129,6 +145,7 @@ import MultiInputField from '../parameter/itemNew/MultiInputField'
import EliteParameterRecordingEliteDPV from '../parameter/itemNew/DPVNew/EliteParameterRecordingEliteDPV'
import DevMode from '../parameter/itemNew/DevMode'
import Trigger from '../parameter/itemNew/TriggerNew/Trigger'
import TriggerNew from '../parameter/itemNew/TriggerNew/TriggerNew'
import EliteParameterRecordingElitePulseSensing from '../parameter/itemNew/PulseSensingNew/EliteParameterRecordingElitePulseSensing'
import { VueFinalModal } from 'vue-final-modal'
import { mapFields } from 'vuex-map-fields'
@@ -147,6 +164,7 @@ export default {
MultiInputField,
DevMode,
Trigger,
TriggerNew,
},
props: {
parameter: {
@@ -246,9 +264,9 @@ export default {
return ''
}
},
parameterChange: function (name, value, debounce = false) {
parameterChange: function (name, value, debounce = false, force = false) {
/** if parameter is equal to value, then don't change, JSON.stringify is for array & object compare */
if (JSON.stringify(value) !== JSON.stringify(this.parameter[name])) {
if (JSON.stringify(value) !== JSON.stringify(this.parameter[name]) || force === true) {
this.parameter[name] = value
debounce === false
? this.$emit('setParameter', name, value)
@@ -257,16 +275,18 @@ export default {
},
refresh () {
},
workingModeSelectChange (val) {
if (val === undefined) return
workingModeSelectChange (val, reset = true) {
if (val === undefined || this.parameter.MODE === undefined) return
this.workingModeSelect = val
// console.log('workingModeSelectChange', this.workingModeSelect, this.parameter.MODE)
if (this.workingModeSelect.id !== this.parameter.MODE) {
this.parameterChange('MODE', this.workingModeSelect.id)
if (this.resetParameterModeChange === true) {
for (const parameter of this.parameterTable.MODE[this.workingModeSelect.id].parameter) {
this.$emit('setParameter', parameter, this.parameterTable[parameter].defaultValue)
if (reset === true) {
for (const parameter of this.parameterTable.MODE[this.workingModeSelect.id].parameter) {
this.$emit('setParameter', parameter, this.parameterTable[parameter].defaultValue)
}
}
}
@@ -0,0 +1,216 @@
<template>
<div :class="disabled === true ? 'flex d-flex py-1 disabled-text' : 'flex d-flex py-1'" style="align-items: center;">
<div style="flex-basis: 25%;">
<span>{{ showName }}</span>
</div>
<div v-if="onlyButton === true && disabled === true" style="flex-basis: 50%; display: flex; align-items: center; justify-content: center;">
<img class="button-flat" src="@/assets/icons/button-disable.svg"/>
</div>
<div v-else-if="onlyButton === true && inputValue === false" style="flex-basis: 50%; display: flex; align-items: center; justify-content: center;" @click="inputChange(true)">
<img class="button-flat" src="@/assets/icons/button-off.svg"/>
</div>
<div v-else-if="onlyButton === true && inputValue === true" style="flex-basis: 50%; display: flex; align-items: center; justify-content: center;" @click="inputChange(false)">
<img class="button-flat" src="@/assets/icons/button-on.svg"/>
</div>
<div v-else style="flex-basis: 50%; align-items: center; text-align: -webkit-right;">
<va-input class="mr-2" style="margin-bottom: 0; width: 100px; color: green;"
@keyup.enter="inputChange(inputString)"
@blur="inputChange(inputString)"
v-model="inputStringModel"
:disabled="disabled">
<p v-if="withToggleButton === true" slot="append" style="margin-right: 0;" small>
{{ unitSelect }}
</p>
</va-input>
</div>
<div v-if="withToggleButton === false" style="flex-basis: 25%; align-items: center;">
{{ unitSelect }}
</div>
<div v-if="withToggleButton === true && disabled === true" style="flex-basis: 25%; align-items: center; display: inline-flex;">
<img class="button-dot" src="@/assets/icons/button-dot-off.svg">
</div>
<div v-else-if="withToggleButton === true && toggleValue === false" style="flex-basis: 25%; align-items: center; display: inline-flex;" @click="toggleChange(true)">
<img class="button-dot" src="@/assets/icons/button-dot-off.svg">
</div>
<div v-else-if="withToggleButton === true && toggleValue === true" style="flex-basis: 25%; align-items: center; display: inline-flex;" @click="toggleChange(false)">
<img class="button-dot" src="@/assets/icons/button-dot-on.svg">
</div>
</div>
</template>
<script>
export default {
name: 'InputFieldWithHeader',
components: {
},
props: {
templateType: {
type: Number,
default: 0,
},
onlyButton: {
type: Boolean,
default: false,
},
withHeader: {
type: Boolean,
default: false,
},
withUnitButton: {
type: Boolean,
default: false,
},
withToggleButton: {
type: Boolean,
default: false,
},
parameterName: {
type: String,
required: true,
},
showName: {
type: String,
},
range: {
type: Object,
},
inputValue: {
type: [Number, String, Boolean],
required: true,
},
referenceValue: {
type: Object,
},
defaultUnit: {
type: String,
},
unit: {
type: Object,
},
outputReadabilityData: {
type: Function,
default: (val) => val,
},
outputRawData: {
type: Function,
default: (val) => val,
},
disabled: {
type: Boolean,
default: false,
},
index: {
type: Number,
default: -1,
},
toggleParameter: {
type: String,
},
toggleValue: {
type: [Number, Boolean],
},
},
created () {
},
computed: {
inputStringModel: {
get () {
return String(this.outputReadabilityData(this.inputValue))
},
set (val) {
this.inputString = val
},
},
unitLength () {
return Object.keys(this.unit).length
},
},
data () {
return {
unitSelect: this.defaultUnit,
unitButtonClicked: '',
inputString: '',
size: {
12: 'flex sm12 xl12 md12 xs12 px-0 mx-0',
6: 'flex sm6 xl6 md6 xs6 px-0 mx-0',
5: 'flex sm5 xl5 md5 xs5 px-0 mx-0 my-0 py-0',
4: 'flex sm4 xl4 md4 xs4 px-0 mx-0 my-0 py-0',
3: 'flex sm3 xl3 md3 xs3 px-0 mx-0 my-0 py-0',
},
style: {
header: '',
content: '',
unitButton: '',
},
}
},
mqtt: {
},
methods: {
inputChange: function (val) {
/** */
let scale = 1
if (this.unitSelect) {
scale = this.unit[this.unitSelect]
}
// if change from input field
if (typeof (val) === 'string') {
if (isNaN(val) || val === '') {
return false
}
val = this.outputRawData(val, scale)
if (parseFloat(val) < this.range.min) {
val = this.range.min
} else if (parseFloat(val) > this.range.max) {
val = this.range.max
}
}
/** if parameter is array with index needs to return */
if (this.index === -1) {
this.$emit('parameterChange', this.parameterName, val)
} else {
this.$emit('parameterChangeByIndex', this.parameterName, val, this.index)
}
},
unitChange: function () {
this.unitButtonClicked += 1
this.unitSelect = Object.keys(this.unit)[this.unitButtonClicked % this.unitLength]
},
toggleChange: function (val) {
this.$emit('parameterChangeByIndex', this.toggleParameter, val, this.index)
},
},
async mounted () {
if (this.withHeader === true && this.withUnitButton === true) {
this.style.header = this.size[5]
this.style.content = this.size[4]
this.style.unitButton = this.size[3]
} else if (this.withHeader === true) {
this.style.header = this.size[6]
this.style.content = this.size[6]
} else {
this.style.content = this.size[12]
}
},
destroyed () {
},
watch: {
},
}
</script>
<style>
.button-dot {
height: 16px;
width: 16px;
}
.button-flat {
height: 20px;
width: 64px;
}
.disabled-text {
color: #c2c2c2;
}
</style>
@@ -0,0 +1,270 @@
<template>
<div>
<div v-for="channel of [0,1,2,3,4,5,6,7]" :key="channel">
<button class="accordion">
<div style="display: flex; justify-content: space-between; align-items: center;">
<div class="d-flex align--center">
<i v-if="panelSpread.includes(channel) === false" class="va-icon fa fa-angle-right mr-1" style="width: 15px;"></i>
<i v-if="panelSpread.includes(channel) === true" class="va-icon fa fa-angle-down mr-1" style="width: 15px;"></i>
<span>{{ channelName[channel] }}</span>
</div>
<div class="d-flex align--center">
<va-toggle class="mb-0" color="#2CE9A4" :value="parameter.USED[channel]" style="float: right;" flat small @click.native.stop="parameterChangeByIndex('USED', !parameter.USED[channel], channel)"/>
</div>
</div>
</button>
<div class="panel">
<InputFieldWithToggle
v-if="[2,3].indexOf(channel) >= 0"
style="margin-bottom: 0.5rem;"
:index="channel"
:parameterName="'OUTPUT_5V'"
:inputValue="parameter.OUTPUT_5V[channel]"
:onlyButton="true"
:disabled="channel === 2 ? true: !parameter.USED[channel]"
v-bind="parameterTable.OUTPUT_5V"
@parameterChange="parameterChange"
@parameterChangeByIndex="parameterChangeByIndex"
></InputFieldWithToggle>
<InputFieldWithToggle
v-if="[4,5,6,7].indexOf(channel) >= 0"
:index="channel"
:parameterName="'CURRENT'"
:inputValue="parameter.CURRENT[channel]"
:disabled="!parameter.USED[channel]"
v-bind="parameterTable.CURRENT"
@parameterChange="parameterChange"
@parameterChangeByIndex="parameterChangeByIndex"
></InputFieldWithToggle>
<!-- pre-T -->
<InputFieldWithToggle
:index="channel"
:parameterName="'T_EARLY'"
:inputValue="parameter.T_EARLY[channel]"
:withToggleButton="true"
:toggleParameter="'V_EARLY'"
:toggleValue="parameter.V_EARLY[channel]"
:disabled="!parameter.USED[channel]"
v-bind="parameterTable.T_EARLY"
@parameterChange="parameterChange"
@parameterChangeByIndex="parameterChangeByIndex"
></InputFieldWithToggle>
<InputFieldWithToggle
:index="channel"
:parameterName="'CYCLE'"
:inputValue="parameter.CYCLE[channel]"
:disabled="!parameter.USED[channel]"
v-bind="parameterTable.CYCLE"
@parameterChange="parameterChange"
@parameterChangeByIndex="parameterChangeByIndex"
></InputFieldWithToggle>
<InputFieldWithToggle
:index="channel"
:parameterName="'T_MID0'"
:inputValue="parameter.T_MID0[channel]"
:withToggleButton="true"
:toggleParameter="'V_MID0'"
:toggleValue="parameter.V_MID0[channel]"
:disabled="!parameter.USED[channel]"
v-bind="parameterTable.T_MID0"
@parameterChange="parameterChange"
@parameterChangeByIndex="parameterChangeByIndex"
></InputFieldWithToggle>
<InputFieldWithToggle
:index="channel"
:parameterName="'T_MID1'"
:inputValue="parameter.T_MID1[channel]"
:withToggleButton="true"
:toggleParameter="'V_MID1'"
:toggleValue="parameter.V_MID1[channel]"
:disabled="!parameter.USED[channel]"
v-bind="parameterTable.T_MID1"
@parameterChange="parameterChange"
@parameterChangeByIndex="parameterChangeByIndex"
></InputFieldWithToggle>
<InputFieldWithToggle
:index="channel"
:parameterName="'T_MID2'"
:inputValue="parameter.T_MID2[channel]"
:withToggleButton="true"
:toggleParameter="'V_MID2'"
:toggleValue="parameter.V_MID2[channel]"
:disabled="!parameter.USED[channel]"
v-bind="parameterTable.T_MID2"
@parameterChange="parameterChange"
@parameterChangeByIndex="parameterChangeByIndex"
></InputFieldWithToggle>
<InputFieldWithToggle
:index="channel"
:parameterName="'T_MID3'"
:inputValue="parameter.T_MID3[channel]"
:withToggleButton="true"
:toggleParameter="'V_MID3'"
:toggleValue="parameter.V_MID3[channel]"
:disabled="!parameter.USED[channel]"
v-bind="parameterTable.T_MID3"
@parameterChange="parameterChange"
@parameterChangeByIndex="parameterChangeByIndex"
></InputFieldWithToggle>
<InputFieldWithToggle
:index="channel"
:parameterName="'T_LATE'"
:inputValue="parameter.T_LATE[channel]"
:withToggleButton="true"
:toggleParameter="'V_LATE'"
:toggleValue="parameter.V_LATE[channel]"
:disabled="!parameter.USED[channel]"
v-bind="parameterTable.T_LATE"
@parameterChange="parameterChange"
@parameterChangeByIndex="parameterChangeByIndex"
></InputFieldWithToggle>
</div>
</div>
</div>
</template>
<script>
import InputFieldWithToggle from './InputFieldWithToggle.vue'
export default {
name: 'Trigger',
components: {
InputFieldWithToggle,
},
computed: {
},
props: {
parameter: {
type: Object,
default: () => {},
},
parameterTable: {
type: Object,
default: () => {},
},
},
data () {
return {
panelSpread: [],
channelName: [
'Gas valve 1',
'Gas valve 2',
'Gas valve 3',
'5V TTL',
'LED 1',
'LED 2',
'LED 3',
'LED 4',
],
channelList: [0, 1, 2, 3],
triggerList: [0, 1],
openAdvanced: Boolean(this.parameter.TRIG0_en || this.parameter.TRIG1_en),
}
},
methods: {
channelBlockToggle (channelIndex) {
let name = 'ACC_a_out'
if (channelIndex !== undefined) {
name += channelIndex
}
return name
},
channelBlockCurrent (channelIndex) {
let name = 'ACC_a_out'
if (channelIndex !== undefined) {
name += channelIndex
}
name += '_current'
return name
},
triggerBlockEnable (triggerIndex) {
let name = 'TRIG'
if (triggerIndex !== undefined) {
name += triggerIndex
}
name += '_en'
return name
},
triggerBlockType (triggerIndex) {
let name = 'TRIG'
if (triggerIndex !== undefined) {
name += triggerIndex
}
name += '_edge_type'
return name
},
parameterChange: function (name, value, debounce) {
this.$emit('parameterChange', name, value, debounce)
},
parameterChangeByIndex: function (name, value, index) {
if (name.indexOf('V_MID') >= 0) {
console.log('sadsaasdadadad')
if (name === 'V_MID0' || name === 'V_MID2') {
this.parameter.V_MID0.splice(index, 1, value)
this.parameter.V_MID2.splice(index, 1, value)
this.parameter.V_MID1.splice(index, 1, !value)
this.parameter.V_MID3.splice(index, 1, !value)
}
if (name === 'V_MID1' || name === 'V_MID3') {
this.parameter.V_MID1.splice(index, 1, value)
this.parameter.V_MID3.splice(index, 1, value)
this.parameter.V_MID0.splice(index, 1, !value)
this.parameter.V_MID2.splice(index, 1, !value)
}
this.$emit('parameterChange', 'V_MID0', this.parameter.V_MID0, false, true)
this.$emit('parameterChange', 'V_MID1', this.parameter.V_MID1, false, true)
this.$emit('parameterChange', 'V_MID2', this.parameter.V_MID2, false, true)
this.$emit('parameterChange', 'V_MID3', this.parameter.V_MID3, false, true)
}
const _value = [...this.parameter[name]]
_value[index] = value
this.$emit('parameterChange', name, _value)
},
test: function (index) {
console.log('index', index)
// this.triggerUsed.splice(index, 1, !this.triggerUsed[index])
},
},
mounted () {
const acc = document.getElementsByClassName('accordion')
const panelSpread = this.panelSpread
for (let i = 0; i < acc.length; i++) {
acc[i].addEventListener('click', function () {
this.classList.toggle('active')
var panel = this.nextElementSibling
if (panel.style.display === 'block') {
panel.style.display = 'none'
panelSpread.splice(panelSpread.indexOf(i), 1)
} else {
panel.style.display = 'block'
panelSpread.push(i)
}
})
}
},
}
</script>
<style>
.accordion {
background-color: white;
cursor: pointer;
padding: 18px;
width: 100%;
border: none;
text-align: left;
outline: none;
font-size: 15px;
transition: 0.4s;
}
.panel {
padding: 0 18px;
display: none;
background-color: white;
overflow: hidden;
}
.button-dot {
height: 16px;
width: 16px;
}
</style>
+52
View File
@@ -0,0 +1,52 @@
import api from './index'
import auth from './auth'
async function create (attrs) {
const _header = auth.getHeader()
try {
return await api.axios.post('/api/configuration/create', attrs, { headers: _header })
} catch (e) {
console.error(e)
return false
}
}
async function update (id, attrs) {
const _header = auth.getHeader()
try {
return await api.axios.post(`/api/configuration/update/${id}`, attrs, { headers: _header })
} catch (e) {
console.error(e)
return false
}
}
async function clearDel () {
const _header = auth.getHeader()
try {
return await api.axios.get('/api/configuration/clear_deleted', { headers: _header })
} catch (e) {
console.error(e)
return false
}
}
async function get (id) {
const _header = auth.getHeader()
try {
return await api.axios.get('/api/configuration/get', { headers: _header })
} catch (e) {
console.error(e)
return false
}
}
const collection = {
create,
update,
clearDel,
get,
}
export default collection
+2
View File
@@ -11,6 +11,7 @@ import analysis from './analysis'
import sdcard from './sdcard'
import connection from './connection'
import project from './project'
import configuration from './configuration'
// axios.defaults.baseURL = 'http://192.168.3.211:3000'
axios.defaults.baseURL = 'http://' + location.href.split('/')[2].split(':')[0] + ':3000'
@@ -29,6 +30,7 @@ const api = {
sdcard,
connection,
project,
configuration,
}
export default api
@@ -18,6 +18,7 @@ export default {
channels: {
time: {
name: 'Time',
physicalQuantity: 's',
unit: {
us: 1,
ms: 1e3,
@@ -30,6 +31,7 @@ export default {
},
0: {
name: 'I_in',
physicalQuantity: 'A',
unit: {
nA: 1,
},
@@ -37,6 +39,7 @@ export default {
},
1: {
name: 'V_in/V_out',
physicalQuantity: 'V',
unit: {
uV: 1,
},
@@ -44,6 +47,7 @@ export default {
},
2: {
name: 'Gain',
physicalQuantity: '',
unit: {
default: 1,
},
@@ -17,6 +17,7 @@ export default {
channels: {
time: {
name: 'Time',
physicalQuantity: 's',
unit: {
us: 1,
ms: 1e3,
@@ -29,6 +30,7 @@ export default {
},
0: {
name: 'I_in',
physicalQuantity: 'A',
unit: {
nA: 1,
},
@@ -36,6 +38,7 @@ export default {
},
1: {
name: 'V_in/V_out',
physicalQuantity: 'V',
unit: {
uV: 1,
},
@@ -18,6 +18,7 @@ export default {
channels: {
time: {
name: 'Time',
physicalQuantity: 's',
unit: {
us: 1,
ms: 1e3,
@@ -30,6 +31,7 @@ export default {
},
0: {
name: 'I_in',
physicalQuantity: 'A',
unit: {
nA: 1,
uA: 1e3,
@@ -40,6 +42,7 @@ export default {
},
1: {
name: 'Potential',
physicalQuantity: 'V',
unit: {
uV: 1,
mV: 1e3,
@@ -50,6 +53,7 @@ export default {
},
2: {
name: 'V_out',
physicalQuantity: 'V',
unit: {
uV: 1,
mV: 1e3,
@@ -18,6 +18,7 @@ export default {
channels: {
time: {
name: 'Time',
physicalQuantity: 's',
unit: {
us: 1,
ms: 1e3,
@@ -30,6 +31,7 @@ export default {
},
0: {
name: 'I_in',
physicalQuantity: 'A',
unit: {
nA: 1,
uA: 1e3,
@@ -40,6 +42,7 @@ export default {
},
1: {
name: 'Potential',
physicalQuantity: 'V',
unit: {
uV: 1,
mV: 1e3,
@@ -50,6 +53,7 @@ export default {
},
2: {
name: 'V_out',
physicalQuantity: 'V',
unit: {
uV: 1,
mV: 1e3,
@@ -60,6 +64,7 @@ export default {
},
3: {
name: 'sum_cnt',
physicalQuantity: 'V',
unit: {
uV: 1,
mV: 1e3,
@@ -70,6 +75,7 @@ export default {
},
4: {
name: 'sum_adc_delta_Iin',
physicalQuantity: 'V',
unit: {
uV: 1,
mV: 1e3,
@@ -80,6 +86,7 @@ export default {
},
5: {
name: 'sum_adc_delta_Voutin',
physicalQuantity: 'V',
unit: {
uV: 1,
mV: 1e3,
@@ -90,6 +97,7 @@ export default {
},
6: {
name: 'resis',
physicalQuantity: 'V',
unit: {
uV: 1,
mV: 1e3,
@@ -18,6 +18,7 @@ export default {
channels: {
time: {
name: 'Time',
physicalQuantity: 's',
unit: {
us: 1,
ms: 1e3,
@@ -30,6 +31,7 @@ export default {
},
0: {
name: 'I_in',
physicalQuantity: 'A',
unit: {
nA: 1,
uA: 1e3,
@@ -40,6 +42,7 @@ export default {
},
1: {
name: 'V_in',
physicalQuantity: 'V',
unit: {
uV: 1,
mV: 1e3,
@@ -50,6 +53,7 @@ export default {
},
2: {
name: 'V_out',
physicalQuantity: 'V',
unit: {
uV: 1,
mV: 1e3,
@@ -18,6 +18,7 @@ export default {
channels: {
time: {
name: 'Time',
physicalQuantity: 's',
unit: {
us: 1,
ms: 1e3,
@@ -30,6 +31,7 @@ export default {
},
0: {
name: 'I_in',
physicalQuantity: 'A',
unit: {
nA: 1,
uA: 1e3,
@@ -40,6 +42,7 @@ export default {
},
1: {
name: 'V_out',
physicalQuantity: 'V',
unit: {
uV: 1,
mV: 1e3,
@@ -50,6 +53,7 @@ export default {
},
2: {
name: 'V_in',
physicalQuantity: 'V',
unit: {
uV: 1,
mV: 1e3,
@@ -60,6 +64,7 @@ export default {
},
3: {
name: 'Cycle number',
physicalQuantity: '',
unit: {
cycle: 1,
},
@@ -18,6 +18,7 @@ export default {
channels: {
time: {
name: 'Time',
physicalQuantity: 's',
unit: {
us: 1,
ms: 1e3,
@@ -30,6 +31,7 @@ export default {
},
0: {
name: 'I_in',
physicalQuantity: 'A',
unit: {
nA: 1,
uA: 1e3,
@@ -40,6 +42,7 @@ export default {
},
1: {
name: 'Potential',
physicalQuantity: 'V',
unit: {
uV: 1,
mV: 1e3,
@@ -50,6 +53,7 @@ export default {
},
2: {
name: 'V_out',
physicalQuantity: 'V',
unit: {
uV: 1,
mV: 1e3,
@@ -60,6 +64,7 @@ export default {
},
3: {
name: 'Cycle number',
physicalQuantity: '',
unit: {
cycle: 1,
},
+5
View File
@@ -23,6 +23,7 @@ export default {
channels: {
time: {
name: 'Time',
physicalQuantity: 's',
unit: {
us: 1,
ms: 1e3,
@@ -35,6 +36,7 @@ export default {
},
0: {
name: 'I_in',
physicalQuantity: 'A',
unit: {
nA: 1,
uA: 1e3,
@@ -45,6 +47,7 @@ export default {
},
1: {
name: 'Potential',
physicalQuantity: 'V',
unit: {
uV: 1,
mV: 1e3,
@@ -55,6 +58,7 @@ export default {
},
2: {
name: 'V_out',
physicalQuantity: 'V',
unit: {
uV: 1,
mV: 1e3,
@@ -65,6 +69,7 @@ export default {
},
3: {
name: 'Cycle number',
physicalQuantity: '',
unit: {
cycle: 1,
},
@@ -16,6 +16,7 @@ export default {
channels: {
time: {
name: 'Time',
physicalQuantity: 's',
unit: {
us: 1,
ms: 1e3,
@@ -28,6 +29,7 @@ export default {
},
0: {
name: '0',
physicalQuantity: '',
unit: {
default: 1,
},
@@ -35,6 +37,7 @@ export default {
},
1: {
name: '1',
physicalQuantity: '',
unit: {
default: 1,
},
@@ -42,6 +45,7 @@ export default {
},
2: {
name: '2',
physicalQuantity: '',
unit: {
default: 1,
},
@@ -49,6 +53,7 @@ export default {
},
3: {
name: '3',
physicalQuantity: '',
unit: {
default: 1,
},
@@ -18,6 +18,7 @@ export default {
channels: {
time: {
name: 'Time',
physicalQuantity: 's',
unit: {
us: 1,
ms: 1e3,
@@ -30,6 +31,7 @@ export default {
},
0: {
name: 'I_in',
physicalQuantity: 'A',
unit: {
nA: 1,
uA: 1e3,
@@ -40,6 +42,7 @@ export default {
},
1: {
name: 'V_out',
physicalQuantity: 'V',
unit: {
uV: 1,
mV: 1e3,
@@ -50,6 +53,7 @@ export default {
},
2: {
name: 'V_in',
physicalQuantity: 'V',
unit: {
uV: 1,
mV: 1e3,
+4
View File
@@ -18,6 +18,7 @@ export default {
channels: {
time: {
name: 'Time',
physicalQuantity: 's',
unit: {
us: 1,
ms: 1e3,
@@ -30,6 +31,7 @@ export default {
},
0: {
name: 'I_in',
physicalQuantity: 'A',
unit: {
nA: 1,
uA: 1e3,
@@ -40,6 +42,7 @@ export default {
},
1: {
name: 'V_in',
physicalQuantity: 'V',
unit: {
uV: 1,
mV: 1e3,
@@ -50,6 +53,7 @@ export default {
},
2: {
name: 'V_out',
physicalQuantity: 'V',
unit: {
uV: 1,
mV: 1e3,
+4
View File
@@ -18,6 +18,7 @@ export default {
channels: {
time: {
name: 'Time',
physicalQuantity: 's',
unit: {
us: 1,
ms: 1e3,
@@ -30,6 +31,7 @@ export default {
},
0: {
name: 'I_in',
physicalQuantity: 'A',
unit: {
nA: 1,
uA: 1e3,
@@ -40,6 +42,7 @@ export default {
},
1: {
name: 'V_out',
physicalQuantity: 'V',
unit: {
uV: 1,
mV: 1e3,
@@ -50,6 +53,7 @@ export default {
},
2: {
name: 'V_in',
physicalQuantity: 'V',
unit: {
uV: 1,
mV: 1e3,
@@ -18,6 +18,7 @@ export default {
channels: {
time: {
name: 'Time',
physicalQuantity: 's',
unit: {
us: 1,
ms: 1e3,
@@ -30,6 +31,7 @@ export default {
},
0: {
name: 'I_in',
physicalQuantity: 'A',
unit: {
nA: 1,
uA: 1e3,
@@ -40,6 +42,7 @@ export default {
},
1: {
name: 'Potential',
physicalQuantity: 'V',
unit: {
uV: 1,
mV: 1e3,
@@ -50,6 +53,7 @@ export default {
},
2: {
name: 'V_out',
physicalQuantity: 'V',
unit: {
uV: 1,
mV: 1e3,
+4
View File
@@ -18,6 +18,7 @@ export default {
channels: {
time: {
name: 'Time',
physicalQuantity: 's',
unit: {
us: 1,
ms: 1e3,
@@ -30,6 +31,7 @@ export default {
},
0: {
name: 'I_in',
physicalQuantity: 'A',
unit: {
nA: 1,
uA: 1e3,
@@ -40,6 +42,7 @@ export default {
},
1: {
name: 'Potential',
physicalQuantity: 'V',
unit: {
uV: 1,
mV: 1e3,
@@ -50,6 +53,7 @@ export default {
},
2: {
name: 'V_in',
physicalQuantity: 'V',
unit: {
uV: 1,
mV: 1e3,
@@ -34,6 +34,7 @@ export default {
channels: {
time: {
name: 'Time',
physicalQuantity: 's',
unit: {
us: 1,
ms: 1e3,
@@ -46,6 +47,7 @@ export default {
},
0: {
name: 'I_in_pul1',
physicalQuantity: 'A',
unit: {
nA: 1,
uA: 1e3,
@@ -56,6 +58,7 @@ export default {
},
1: {
name: 'I_in_pul2',
physicalQuantity: 'A',
unit: {
nA: 1,
uA: 1e3,
+4
View File
@@ -18,6 +18,7 @@ export default {
channels: {
time: {
name: 'Time',
physicalQuantity: 's',
unit: {
us: 1,
ms: 1e3,
@@ -30,6 +31,7 @@ export default {
},
0: {
name: 'I_in',
physicalQuantity: 'A',
unit: {
nA: 1,
uA: 1e3,
@@ -40,6 +42,7 @@ export default {
},
1: {
name: 'V_out',
physicalQuantity: 'V',
unit: {
uV: 1,
mV: 1e3,
@@ -50,6 +53,7 @@ export default {
},
2: {
name: 'Resistor',
physicalQuantity: 'R',
unit: {
: 1,
mohm: 1,
+3
View File
@@ -18,6 +18,7 @@ export default {
channels: {
time: {
name: 'Time',
physicalQuantity: 's',
unit: {
us: 1,
ms: 1e3,
@@ -30,6 +31,7 @@ export default {
},
0: {
name: 'I_in',
physicalQuantity: 'A',
unit: {
nA: 1,
uA: 1e3,
@@ -40,6 +42,7 @@ export default {
},
1: {
name: 'V_in',
physicalQuantity: 'V',
unit: {
uV: 1,
mV: 1e3,
+1 -1
View File
@@ -520,7 +520,7 @@ const EliteZM15 = {
return parseInt((parseFloat(val) - 25000) / 5) / scale
},
},
VOLT_VSCAN: {
CA_VOLT: {
type: 'number',
showName: 'Volt (v.s. ref)',
componentType: 'input-range',
@@ -18,6 +18,7 @@ export default {
channels: {
time: {
name: 'Time',
physicalQuantity: 's',
unit: {
us: 1,
ms: 1e3,
@@ -30,6 +31,7 @@ export default {
},
0: {
name: 'I_in',
physicalQuantity: 'A',
unit: {
nA: 1,
uA: 1e3,
@@ -40,6 +42,7 @@ export default {
},
1: {
name: 'Potential',
physicalQuantity: 'V',
unit: {
uV: 1,
mV: 1e3,
@@ -50,6 +53,7 @@ export default {
},
2: {
name: 'V_out',
physicalQuantity: 'V',
unit: {
uV: 1,
mV: 1e3,
@@ -18,6 +18,7 @@ export default {
channels: {
time: {
name: 'Time',
physicalQuantity: 's',
unit: {
us: 1,
ms: 1e3,
@@ -31,6 +32,7 @@ export default {
},
0: {
name: 'Z_Imag_Raw',
physicalQuantity: 'R',
unit: {
ohm: 1,
},
@@ -39,14 +41,16 @@ export default {
},
1: {
name: 'Z_Real_Raw',
physicalQuantity: 'R',
unit: {
default: 1,
ohm: 1,
},
downloadUnit: 'ohm',
defaultUnit: 'ohm',
},
2: {
name: 'Frequency',
physicalQuantity: 'Hz',
unit: {
mHz: 1,
Hz: 1e3,
@@ -65,6 +69,7 @@ export default {
// },
4: {
name: 'Z_Imag',
physicalQuantity: 'R',
unit: {
mohm: 1e-3,
: 1e-3,
@@ -80,6 +85,7 @@ export default {
},
5: {
name: 'Z_Real',
physicalQuantity: 'R',
unit: {
mohm: 1e-3,
: 1e-3,
@@ -95,6 +101,7 @@ export default {
},
6: {
name: 'Impedance',
physicalQuantity: 'R',
unit: {
mohm: 1e-3,
: 1e-3,
@@ -110,6 +117,7 @@ export default {
},
7: {
name: 'Phase',
physicalQuantity: 'Degree',
unit: {
millidegree: 1,
'°': 1e3,
@@ -119,6 +127,7 @@ export default {
},
8: {
name: 'Current',
physicalQuantity: 'A',
unit: {
nA: 1,
uA: 1e3,
@@ -129,6 +138,7 @@ export default {
},
9: {
name: 'Level gain',
physicalQuantity: '',
unit: {
default: 1,
},
@@ -137,6 +147,7 @@ export default {
},
10: {
name: 'notify_one',
physicalQuantity: '',
unit: {
default: 1,
},
@@ -145,6 +156,7 @@ export default {
},
11: {
name: 'notify_two',
physicalQuantity: '',
unit: {
default: 1,
},
@@ -153,6 +165,7 @@ export default {
},
12: {
name: 'notify_three',
physicalQuantity: '',
unit: {
default: 1,
},
@@ -161,11 +174,14 @@ export default {
},
13: {
name: 'debug_amp[mV]',
physicalQuantity: 'V',
unit: {
default: 1,
uV: 1,
mV: 1e3,
V: 1e6,
},
downloadUnit: null,
defaultUnit: 'default',
defaultUnit: 'mV',
downloadUnit: 'mV',
},
},
charts: {
@@ -18,6 +18,7 @@ export default {
channels: {
time: {
name: 'Time',
physicalQuantity: 's',
unit: {
us: 1,
ms: 1e3,
@@ -31,6 +32,7 @@ export default {
},
0: {
name: 'I_in',
physicalQuantity: 'A',
unit: {
nA: 1,
uA: 1e3,
@@ -41,6 +43,7 @@ export default {
},
1: {
name: 'V_out-V_in',
physicalQuantity: 'V',
unit: {
uV: 1,
mV: 1e3,
@@ -51,6 +54,7 @@ export default {
},
2: {
name: 'V_out',
physicalQuantity: 'V',
unit: {
uV: 1,
mV: 1e3,
@@ -61,6 +65,7 @@ export default {
},
3: {
name: 'Cycle',
physicalQuantity: '',
unit: {
cycle: 1,
},
@@ -16,6 +16,7 @@ export default {
channels: {
time: {
name: 'Time',
physicalQuantity: 's',
unit: {
us: 1,
ms: 1e3,
@@ -28,6 +29,7 @@ export default {
},
0: {
name: '0',
physicalQuantity: '',
unit: {
default: 1,
},
@@ -35,6 +37,7 @@ export default {
},
1: {
name: '1',
physicalQuantity: '',
unit: {
default: 1,
},
@@ -42,6 +45,7 @@ export default {
},
2: {
name: '2',
physicalQuantity: '',
unit: {
default: 1,
},
@@ -49,6 +53,7 @@ export default {
},
3: {
name: '3',
physicalQuantity: '',
unit: {
default: 1,
},
@@ -18,6 +18,7 @@ export default {
channels: {
time: {
name: 'Time',
physicalQuantity: 's',
unit: {
us: 1,
ms: 1e3,
@@ -31,6 +32,7 @@ export default {
},
0: {
name: 'Z_Imag_Raw',
physicalQuantity: 'R',
unit: {
ohm: 1,
},
@@ -39,14 +41,16 @@ export default {
},
1: {
name: 'Z_Real_Raw',
physicalQuantity: 'R',
unit: {
default: 1,
ohm: 1,
},
downloadUnit: 'ohm',
defaultUnit: 'ohm',
},
2: {
name: 'Frequency',
physicalQuantity: 'Hz',
unit: {
mHz: 1,
Hz: 1e3,
@@ -65,6 +69,7 @@ export default {
// },
4: {
name: 'Z_Imag',
physicalQuantity: 'R',
unit: {
mohm: 1e-3,
: 1e-3,
@@ -80,6 +85,7 @@ export default {
},
5: {
name: 'Z_Real',
physicalQuantity: 'R',
unit: {
mohm: 1e-3,
: 1e-3,
@@ -95,6 +101,7 @@ export default {
},
6: {
name: 'Impedance',
physicalQuantity: 'R',
unit: {
mohm: 1e-3,
: 1e-3,
@@ -110,6 +117,7 @@ export default {
},
7: {
name: 'Phase',
physicalQuantity: 'Degree',
unit: {
millidegree: 1,
'°': 1e3,
@@ -119,6 +127,7 @@ export default {
},
8: {
name: 'Current',
physicalQuantity: 'A',
unit: {
nA: 1,
uA: 1e3,
@@ -129,6 +138,7 @@ export default {
},
9: {
name: 'Level gain',
physicalQuantity: '',
unit: {
default: 1,
},
@@ -137,6 +147,7 @@ export default {
},
10: {
name: 'notify_one',
physicalQuantity: '',
unit: {
default: 1,
},
@@ -145,6 +156,7 @@ export default {
},
11: {
name: 'notify_two',
physicalQuantity: '',
unit: {
default: 1,
},
@@ -153,6 +165,7 @@ export default {
},
12: {
name: 'notify_three',
physicalQuantity: '',
unit: {
default: 1,
},
@@ -161,6 +174,7 @@ export default {
},
13: {
name: 'debug_amp[mV]',
physicalQuantity: 'V',
unit: {
uV: 1,
mV: 1e3,
+4
View File
@@ -18,6 +18,7 @@ export default {
channels: {
time: {
name: 'Time',
physicalQuantity: 's',
unit: {
us: 1,
ms: 1e3,
@@ -30,6 +31,7 @@ export default {
},
0: {
name: 'I_in',
physicalQuantity: 'A',
unit: {
nA: 1,
uA: 1e3,
@@ -40,6 +42,7 @@ export default {
},
1: {
name: 'V_out',
physicalQuantity: 'V',
unit: {
uV: 1,
mV: 1e3,
@@ -50,6 +53,7 @@ export default {
},
2: {
name: 'Resistor',
physicalQuantity: 'R',
unit: {
: 1,
mohm: 1,
+3
View File
@@ -18,6 +18,7 @@ export default {
channels: {
time: {
name: 'Time',
physicalQuantity: 's',
unit: {
us: 1,
ms: 1e3,
@@ -30,6 +31,7 @@ export default {
},
0: {
name: 'I_in',
physicalQuantity: 'A',
unit: {
nA: 1,
uA: 1e3,
@@ -40,6 +42,7 @@ export default {
},
1: {
name: 'V_in',
physicalQuantity: 'V',
unit: {
uV: 1,
mV: 1e3,
+11 -7
View File
@@ -93,16 +93,20 @@ const EliteEIS = {
{ value: 1, label: '2' },
{ value: 2, label: '3' },
{ value: 3, label: '4' },
{ value: 4, label: 'Auto' },
{ value: 4, label: '5' },
{ value: 5, label: '6' },
{ value: 6, label: '7' },
{ value: 7, label: '8' },
{ value: 8, label: 'Auto' },
],
range: ['1', '2', '3', '4', 'Auto'],
defaultValue: 4,
range: ['1', '2', '3', '4', '5', '6', '7', '8', 'Auto'],
defaultValue: 8,
outputRawData: (val) => {
const numArr = ['1', '2', '3', '4', 'Auto']
const numArr = ['1', '2', '3', '4', '5', '6', '7', '8', 'Auto']
return numArr.indexOf(val.toString())
},
outputReadabilityData: (idx) => {
const numArr = ['1', '2', '3', '4', 'Auto']
const numArr = ['1', '2', '3', '4', '5', '6', '7', '8', 'Auto']
return numArr[parseInt(idx)]
},
},
@@ -158,7 +162,7 @@ const EliteEIS = {
outputReadabilityData: (val, scale = 1) => {
return Math.round(parseInt(val) / 2047 * 800) / scale
},
defaultValue: 25,
defaultValue: 26,
defaultUnit: 'mV',
downloadUnit: 'mV',
unit: {
@@ -289,7 +293,7 @@ const EliteEIS = {
outputReadabilityData: (val, scale = 1) => {
return Math.round(parseInt(val) / 2047 * 800) / scale
},
defaultValue: 25,
defaultValue: 26,
defaultUnit: 'mV',
downloadUnit: 'mV',
unit: {
@@ -0,0 +1,98 @@
export default {
name: 'Dev Mode',
parameter: ['ADC_VALUE_I'],
valScales: {
linear: {
func: (val) => {
return val
},
},
log: {
func: (val) => {
return Math.log10(Math.abs(val))
},
},
},
channels: {
time: {
name: 'Time',
physicalQuantity: 's',
unit: {
us: 1,
ms: 1e3,
s: 1e6,
m: 60 * 1e6,
h: 60 * 60 * 1e6,
auto: 1,
},
defaultUnit: 'us',
},
0: {
name: '0',
physicalQuantity: '',
unit: {
default: 1,
},
defaultUnit: 'default',
},
1: {
name: '1',
physicalQuantity: '',
unit: {
default: 1,
},
defaultUnit: 'default',
},
2: {
name: '2',
physicalQuantity: '',
unit: {
default: 1,
},
defaultUnit: 'default',
},
3: {
name: '3',
physicalQuantity: '',
unit: {
default: 1,
},
defaultUnit: 'default',
},
},
charts: {
default: [
{
name: 'Dev Mode',
description: '',
subplot: [
{
x1: {
type: 'time',
valScale: 'linear',
min: 'dataMin',
max: 'dataMax',
},
y1: {
type: 'value',
valScale: 'linear',
min: 'dataMin',
max: 'dataMax',
},
data: [
{
legend: 'dev',
x1: {
channel: 'time',
},
y1: {
channel: 1,
},
},
],
},
],
},
],
},
}
+382
View File
@@ -1,7 +1,374 @@
import Idle from '../Common/Idle'
import ACC from './ACC'
import DevMode from './DevMode'
const EliteTrigger = {
USED: {
type: 'boolean-array',
range: Object.freeze({ min: false, max: true }),
defaultValue: [false, false, false, false, false, false, false, false],
outputRawData: (val, scale = 1, index = -1) => {
if (index === -1) {
return val
} else {
return val[index]
}
},
outputReadabilityData: (val, scale = 1, index = -1) => {
if (index === -1) {
return val
} else {
return val[index]
}
},
},
T_EARLY: {
type: 'number-array',
showName: 'pre-T',
range: Object.freeze({ min: 0, max: 86400 }),
defaultValue: [0, 0, 0, 0, 0, 0, 0, 0],
outputRawData: (val, scale = 1, index = -1) => {
if (index === -1) {
return Number(Number(val).toFixed(1)) * 1000 * scale
} else {
return val[index]
}
},
outputReadabilityData: (val, scale = 1, index = -1) => {
if (index === -1) {
return Number((val / 1000 / scale).toFixed(1))
} else {
return val[index]
}
},
defaultUnit: 's',
downloadUnit: 's',
unit: {
ms: 1e-3,
s: 1,
m: 60,
h: 3600,
},
},
V_EARLY: {
type: 'boolean-array',
range: Object.freeze({ min: false, max: true }),
defaultValue: [false, false, false, false, false, false, false, false],
outputRawData: (val, scale = 1, index = -1) => {
if (index === -1) {
return val
} else {
return val[index]
}
},
outputReadabilityData: (val, scale = 1, index = -1) => {
if (index === -1) {
return val
} else {
return val[index]
}
},
},
CYCLE: {
type: 'number-array',
showName: 'cycle no.',
range: Object.freeze({ min: 1, max: 50000 }),
defaultValue: [1, 1, 1, 1, 1, 1, 1, 1],
outputRawData: (val, scale = 1, index = -1) => {
if (index === -1) {
return Number(val)
} else {
return val[index]
}
},
outputReadabilityData: (val, scale = 1, index = -1) => {
if (index === -1) {
return val
} else {
return val[index]
}
},
},
T_MID0: {
type: 'number-array',
showName: 'T1',
range: Object.freeze({ min: 0, max: 86400 }),
defaultValue: [0, 0, 0, 0, 0, 0, 0, 0],
outputRawData: (val, scale = 1, index = -1) => {
if (index === -1) {
return Number(Number(val).toFixed(1)) * 1000 * scale
} else {
return val[index]
}
},
outputReadabilityData: (val, scale = 1, index = -1) => {
if (index === -1) {
return Number((val / 1000 / scale).toFixed(1))
} else {
return val[index]
}
},
defaultUnit: 's',
downloadUnit: 's',
unit: {
ms: 1e-3,
s: 1,
m: 60,
h: 3600,
},
},
V_MID0: {
type: 'boolean-array',
range: Object.freeze({ min: false, max: true }),
defaultValue: [false, false, false, false, false, false, false, false],
outputRawData: (val, scale = 1, index = -1) => {
if (index === -1) {
return val
} else {
return val[index]
}
},
outputReadabilityData: (val, scale = 1, index = -1) => {
if (index === -1) {
return val
} else {
return val[index]
}
},
},
T_MID1: {
type: 'number-array',
showName: 'T2',
range: Object.freeze({ min: 0, max: 86400 }),
defaultValue: [0, 0, 0, 0, 0, 0, 0, 0],
outputRawData: (val, scale = 1, index = -1) => {
if (index === -1) {
return Number(Number(val).toFixed(1)) * 1000 * scale
} else {
return val[index]
}
},
outputReadabilityData: (val, scale = 1, index = -1) => {
if (index === -1) {
return Number((val / 1000 / scale).toFixed(1))
} else {
return val[index]
}
},
defaultUnit: 's',
downloadUnit: 's',
unit: {
ms: 1e-3,
s: 1,
m: 60,
h: 3600,
},
},
V_MID1: {
type: 'boolean-array',
range: Object.freeze({ min: false, max: true }),
defaultValue: [false, false, false, false, false, false, false, false],
outputRawData: (val, scale = 1, index = -1) => {
if (index === -1) {
return val
} else {
return val[index]
}
},
outputReadabilityData: (val, scale = 1, index = -1) => {
if (index === -1) {
return val
} else {
return val[index]
}
},
},
T_MID2: {
type: 'number-array',
showName: 'T3',
range: Object.freeze({ min: 0, max: 86400 }),
defaultValue: [0, 0, 0, 0, 0, 0, 0, 0],
outputRawData: (val, scale = 1, index = -1) => {
if (index === -1) {
return Number(Number(val).toFixed(1)) * 1000 * scale
} else {
return val[index]
}
},
outputReadabilityData: (val, scale = 1, index = -1) => {
if (index === -1) {
return Number((val / 1000 / scale).toFixed(1))
} else {
return val[index]
}
},
defaultUnit: 's',
downloadUnit: 's',
unit: {
ms: 1e-3,
s: 1,
m: 60,
h: 3600,
},
},
V_MID2: {
type: 'boolean-array',
range: Object.freeze({ min: false, max: true }),
defaultValue: [false, false, false, false, false, false, false, false],
outputRawData: (val, scale = 1, index = -1) => {
if (index === -1) {
return val
} else {
return val[index]
}
},
outputReadabilityData: (val, scale = 1, index = -1) => {
if (index === -1) {
return val
} else {
return val[index]
}
},
},
T_MID3: {
type: 'number-array',
showName: 'T4',
range: Object.freeze({ min: 0, max: 86400 }),
defaultValue: [0, 0, 0, 0, 0, 0, 0, 0],
outputRawData: (val, scale = 1, index = -1) => {
if (index === -1) {
return Number(Number(val).toFixed(1)) * 1000 * scale
} else {
return val[index]
}
},
outputReadabilityData: (val, scale = 1, index = -1) => {
if (index === -1) {
return Number((val / 1000 / scale).toFixed(1))
} else {
return val[index]
}
},
defaultUnit: 's',
downloadUnit: 's',
unit: {
ms: 1e-3,
s: 1,
m: 60,
h: 3600,
},
},
V_MID3: {
type: 'boolean-array',
range: Object.freeze({ min: false, max: true }),
defaultValue: [false, false, false, false, false, false, false, false],
outputRawData: (val, scale = 1, index = -1) => {
if (index === -1) {
return val
} else {
return val[index]
}
},
outputReadabilityData: (val, scale = 1, index = -1) => {
if (index === -1) {
return val
} else {
return val[index]
}
},
},
T_LATE: {
type: 'number-array',
showName: 'post-T',
range: Object.freeze({ min: 0, max: 86400 }),
defaultValue: [0, 0, 0, 0, 0, 0, 0, 0],
outputRawData: (val, scale = 1, index = -1) => {
if (index === -1) {
return Number(Number(val).toFixed(1)) * 1000 * scale
} else {
return val[index]
}
},
outputReadabilityData: (val, scale = 1, index = -1) => {
if (index === -1) {
return Number((val / 1000 / scale).toFixed(1))
} else {
return val[index]
}
},
defaultUnit: 's',
downloadUnit: 's',
unit: {
ms: 1e-3,
s: 1,
m: 60,
h: 3600,
},
},
V_LATE: {
type: 'boolean-array',
range: Object.freeze({ min: false, max: true }),
defaultValue: [false, false, false, false, false, false, false, false],
outputRawData: (val, scale = 1, index = -1) => {
if (index === -1) {
return val
} else {
return val[index]
}
},
outputReadabilityData: (val, scale = 1, index = -1) => {
if (index === -1) {
return val
} else {
return val[index]
}
},
},
CURRENT: {
type: 'number-array',
showName: 'current',
range: Object.freeze({ min: 0, max: 50000 }),
defaultValue: [0, 0, 0, 0, 0, 0, 0, 0],
outputRawData: (val, scale = 1, index = -1) => {
if (index === -1) {
return Number(Number(val).toFixed(1)) * 250 * scale
} else {
return val[index]
}
},
outputReadabilityData: (val, scale = 1, index = -1) => {
if (index === -1) {
return val / 250 / scale
} else {
return val[index]
}
},
defaultUnit: 'mA',
downloadUnit: 'mA',
unit: {
mA: 1,
},
},
OUTPUT_5V: {
type: 'boolean-array',
showName: '5V output',
range: Object.freeze({ min: false, max: true }),
defaultValue: [false, false, false, false, false, false, false, false],
outputRawData: (val, scale = 1, index = -1) => {
if (index === -1) {
return val
} else {
return val[index]
}
},
outputReadabilityData: (val, scale = 1, index = -1) => {
if (index === -1) {
return val
} else {
return val[index]
}
},
},
TIME_DURATION: {
type: 'number',
showName: 'Time duration',
@@ -223,19 +590,34 @@ const EliteTrigger = {
return parseInt(val)
},
},
ADC_VALUE_I: {
type: 'none',
showName: 'Instruction',
componentType: 'dev-mode',
},
MODE_OPTIONS: [
{
id: 1,
description: 'Idle',
},
{
id: 3,
description: 'Trigger',
},
{
id: 0,
description: 'Analog Current Control (ACC)',
},
{
id: 2,
description: 'DEV MODE',
},
],
MODE: {
0: ACC,
1: Idle,
2: DevMode,
3: ACC,
},
}
+3 -2
View File
@@ -33,14 +33,15 @@ const serialNumberMappingTable = {
},
3: {
1: {
0: EliteEDC, // BAT1.0
0: EliteEDC, // BAT0.1
1: EliteEDC, // BAT1.0
},
},
4: {
1: {
0: EliteEIS, // EIS1.0
1: EliteEIS, // EIS1.1
2: EliteEIS, // EIS1.1mini
2: EliteEIS, // EIS mini1.0
},
},
5: {
+22 -8
View File
@@ -48,11 +48,11 @@ export const download = {
while (rawDataIDList.length >= 1000) {
const _rawDataIDList = rawDataIDList.splice(0, 1000)
const _data = await api.raw.getAttrByIDs(channelID, _rawDataIDList, 'id-channel-size-serial_number-start_time-end_time-data')
prevLastTime = await this.parseRawData(_data.data, prevLastTime, meta, result[channelID])
const _data = await api.raw.getAttrByIDs(channelID, _rawDataIDList, 'id-channel-size-serial_number-start_time-end_time-data-bytea_data')
prevLastTime = await this.parseByteData(_data.data, prevLastTime, meta, result[channelID])
}
const _data = await api.raw.getAttrByIDs(channelID, rawDataIDList, 'id-channel-size-serial_number-start_time-end_time-data')
prevLastTime = await this.parseRawData(_data.data, prevLastTime, meta, result[channelID])
const _data = await api.raw.getAttrByIDs(channelID, rawDataIDList, 'id-channel-size-serial_number-start_time-end_time-data-bytea_data')
prevLastTime = await this.parseByteData(_data.data, prevLastTime, meta, result[channelID])
}
return result
},
@@ -62,8 +62,8 @@ export const download = {
result[channelID] = []
const prevLastTime = 0
const _data = await api.raw.getAttrByIDs(channelID, list, 'id-channel-size-serial_number-start_time-end_time-data')
await this.parseRawData(_data.data, prevLastTime, meta, result[channelID])
const _data = await api.raw.getAttrByIDs(channelID, list, 'id-channel-size-serial_number-start_time-end_time-data-bytea_data')
await this.parseByteData(_data.data, prevLastTime, meta, result[channelID])
return result
},
getMiniExistOrNotByID: async function (id, channel) {
@@ -73,7 +73,7 @@ export const download = {
rawByIDChannels: async function (id, channel, meta) {
const data = []
const rawData = await api.raw.getByID(channel, id)
await this.parseRawData(rawData.data, null, meta, data)
await this.parseByteData(rawData.data, null, meta, data)
return data
},
rawSdDataByIDChannels: async function (id, channel, meta) {
@@ -90,6 +90,20 @@ export const download = {
const rawData = await api.mini.getByID(channel, id)
return await this.parseMiniData(rawData, 'data_random', meta)
},
parseByteData: async function (rawData, prevLastTime, meta, dataArray) {
for (const raw of rawData) {
const bytesData = new Int8Array(raw.bytea_data.data)
const integers = []
for (let i = 0; i < bytesData.length; i += 8) {
// Create a DataView for each 8-byte chunk
const view = new DataView(bytesData.buffer, i, 8)
// Read the integer as BigInt (assuming little-endian byte order)
const integer = view.getBigInt64(0)
integers.push(integer)
}
prevLastTime = this.parseDataWithTimeStamp(integers, prevLastTime, meta, dataArray)
}
},
parseRawData: async function (rawData, prevLastTime, meta, dataArray) {
for (const raw of rawData) {
if (raw.data !== null && raw.data.length > 0) {
@@ -188,7 +202,7 @@ export const download = {
if (meta !== undefined) {
if (time <= parseInt(meta.time_duration)) {
const data = currentData[i + 1]
const data = parseInt(currentData[i + 1])
const tmpData = [time, data]
dataArray.push(tmpData)
}
+6 -1
View File
@@ -23,7 +23,12 @@ export const file = {
item.checked = false
item.hovered = false
})
_fileList.push(...mes.data)
const data = mes.data.sort((a, b) => {
const date1 = new Date(a.created_at).getTime()
const date2 = new Date(b.created_at).getTime()
return date2 - date1
})
_fileList.push(...data)
},
getFileList: () => {
return _fileList
+1 -1
View File
@@ -27,7 +27,7 @@ const hasCycleMode = (mode, lib) => {
}
const getDefaultChartTypeByMode = (mode, lib) => {
if (lib === 'EliteZM15' || lib.includes('Elite_EDC')) {
if (lib === 'EliteZM15' || lib.includes('Elite_EDC') || lib.includes('Elite_BAT')) {
const settings = {}
settings[0] = ['Elite', 2, 'Elite', 1]
settings[1] = ['Elite', 2, 'Elite', 1]
+2 -1
View File
@@ -4,6 +4,7 @@ function newChart (chartID, numOfCharts) {
chartType: 'detail',
chartDevice: 'elite', // elite or neulive
chartMode: 0,
order: -1,
chartXUnit: '',
chartYUnit: '',
chartXMode: 'value', // value or time
@@ -11,7 +12,7 @@ function newChart (chartID, numOfCharts) {
cardName: 'Chart' + String(numOfCharts),
cardHeight: '500px',
cardWidth: 'auto',
mappingID: '-1',
mappingID: [],
createdBy: '', // manual ror default
run: false,
timer: 0,
+1
View File
@@ -36,6 +36,7 @@ function newSeries (type, legendName, xAxisIndex, yAxisIndex, xAxisSource, yAxis
showSymbol: false,
showAllSymbol: false,
symbolSize: 4,
sampling: 'lttb',
// [modified 2021/08/10] sampling method managed by vuex
// sampling: 'average',
// sampling: function (frame) {
+1
View File
@@ -22,6 +22,7 @@ function newState () {
licenseCheck: true,
developerMode: false,
controller: null,
controllerID: null,
}
}
@@ -50,6 +50,7 @@ const projectActs = {
const response = await payload.api.project.create(project)
// align project id with column id
project.id = response.data.id
project.created_at = response.data.created_at
state.projectConfigList.push(project)
},
@@ -113,9 +114,13 @@ const projectActs = {
copyProject.uuid = uuidv4()
// create project need to remove
delete copyProject.id
delete copyProject.created_at
delete copyProject.updated_at
const response = await api.project.create(copyProject)
copyProject.id = response.data.id
copyProject.created_at = response.data.created_at
copyProject.updated_at = response.data.updated_at
state.projectList.push(copyProject)
},
+213 -347
View File
@@ -6,7 +6,6 @@ import newSeries from '@/factories/chart/seriesFactory'
import { dataStreamBuffer } from '@/data/task/DataStreamBuffer'
import { taskInfo } from '@/data/task/TaskInfo'
import global_ from '@/data/global/global'
import localforage from 'localforage'
import { IIRFilter } from '@/data/task/filter/IIRFilter.js'
@@ -20,45 +19,46 @@ const chartActs = {
*
**/
[typePath.initCustomizedFromCache]: async ({ state, getters, commit, dispatch }, payload) => {
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)) {
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.chartData[_chart.chartID].createdBy = 'manual'
}
dispatch(typePath.refreshPanel)
}
// 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)) {
// 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.chartData[_chart.chartID].mappingID = _chart.mappingID
// state.chartData[_chart.chartID].createdBy = 'manual'
// }
// dispatch(typePath.refreshPanel)
// }
},
/**
* set chartData to cache (cache will only record non-default chart)
*
*/
[typePath.saveToCache]: async ({ state, getters, commit, dispatch }, payload) => {
const { controllerID } = payload
const _chartData = {}
for (const [_id, _chart] of Object.entries(state.chartData)) {
// manual chart clear series data
if (_chart.createdBy === 'manual') {
_chartData[_id] = JSON.parse(JSON.stringify(_chart))
_chartData[_id].series.map((ele) => { ele.data.length = 0 })
}
}
await localforage.setItem('chart_data_' + controllerID, _chartData)
// const { controllerID } = payload
// const _chartData = {}
// for (const [_id, _chart] of Object.entries(state.chartData)) {
// // manual chart clear series data
// if (_chart.createdBy === 'manual') {
// _chartData[_id] = JSON.parse(JSON.stringify(_chart))
// _chartData[_id].series.map((ele) => { ele.data.length = 0 })
// }
// }
// await localforage.setItem('chart_data_' + controllerID, _chartData)
},
/*
* add chartID to chartData
@@ -91,16 +91,18 @@ const chartActs = {
const { chartID, gridIndex, gridSource } = payload
// one gridSource may have multiple axis (i.e. 疊圖)
gridSource.forEach(grid => {
const xAxisInfo = parseGridSourceAxis(grid.xAxis)
const yAxisInfo = parseGridSourceAxis(grid.yAxis)
const xAxisInfo = parseGridSourceAxis(grid.xSource)
const yAxisInfo = parseGridSourceAxis(grid.ySource)
dispatch(typePath.register, {
chartID: chartID,
gridIndex: gridIndex,
deviceNameX: xAxisInfo.deviceName,
deviceIDX: xAxisInfo.deviceID,
deviceX: xAxisInfo,
channelX: xAxisInfo.channel,
deviceNameY: yAxisInfo.deviceName,
deviceIDY: yAxisInfo.deviceID,
deviceY: yAxisInfo,
channelY: yAxisInfo.channel,
formula: null,
})
@@ -121,16 +123,17 @@ const chartActs = {
* @return {object} : new registered chart
*/
[typePath.register]: ({ state, getters, commit, dispatch }, payload) => {
const { chartID, gridIndex, deviceNameX, deviceIDX, channelX, deviceNameY, deviceIDY, channelY, formula } = payload
const { chartID, gridIndex, deviceNameX, deviceIDX, deviceX, channelX, deviceNameY, deviceIDY, deviceY, channelY, formula } = payload
console.log('register', chartID, gridIndex, deviceNameX, deviceIDX, deviceX, channelX, deviceNameY, deviceIDY, deviceY, channelY, formula)
const sourceList = [
{
name: deviceNameX,
id: deviceIDX,
mac_address: (deviceX) ? deviceX.mac_address : deviceX,
channel: channelX,
},
{
name: deviceNameY,
id: deviceIDY,
mac_address: (deviceY) ? deviceY.mac_address : deviceY,
channel: channelY,
},
]
@@ -156,11 +159,11 @@ const chartActs = {
switch (sourceList[0].name) {
case 'Time':
xAxisType = 'time'
xAxisSource = [-1, -1]
xAxisSource = ['Time', 'Time']
break
default:
xAxisType = 'value'
xAxisSource = [sourceList[0].id, sourceList[0].channel]
xAxisSource = [sourceList[0].mac_address, sourceList[0].channel]
break
}
switch (sourceList[1].name) {
@@ -170,7 +173,7 @@ const chartActs = {
break
default:
yAxisType = 'value'
yAxisSource = [sourceList[1].id, sourceList[1].channel]
yAxisSource = [sourceList[1].mac_address, sourceList[1].channel]
break
}
} else {
@@ -227,11 +230,11 @@ const chartActs = {
// register series
const _series = newSeries('line', legendName, _xAxisIndex, _yAxisIndex, xAxisSource, yAxisSource, formula, formulaSource)
const _seriesIndex = state.chartData[chartID].series.length
// const _seriesIndex = state.chartData[chartID].series.length
state.chartData[chartID].series.push(_series)
state.chartData[chartID].xAxis[_xAxisIndex].seriesIndex.push(_seriesIndex)
state.chartData[chartID].yAxis[_yAxisIndex].seriesIndex.push(_seriesIndex)
// state.chartData[chartID].xAxis[_xAxisIndex].seriesIndex.push(_seriesIndex)
// state.chartData[chartID].yAxis[_yAxisIndex].seriesIndex.push(_seriesIndex)
// state.chartData[chartID].xAxis[_xAxisIndex].boundaryGap = [0, '5%']
// state.chartData[chartID].yAxis[_yAxisIndex].boundaryGap = [0, '10%']
@@ -239,168 +242,10 @@ const chartActs = {
// console.log(state.chartData[chartID])
// set xAxis format
// TODO: need to get the time unit for the CanvasChart
if (sourceList[0].name === 'Time') {
state.chartData[chartID].xAxis[_xAxisIndex].axisLabel.formatter = function (val) {
return getTimeFormatter(val)
}
// state.chartData[chartID].xAxis[_xAxisIndex].interval = 500 * 1000
} else if (sourceList[0].name === 'Elite') {
// state.chartData[chartID].series[state.chartData[chartID].series.length - 1].sampling = false
switch (sourceList[0].channel) {
case 1:
state.chartData[chartID].xAxis[_xAxisIndex].axisLabel.formatter = function (val) {
return parseFloat(val / 1000).toFixed(2) + 'uA'
}
state.chartData[chartID].chartXUnit = 'uA' // nA * 1000
break
case 2:
state.chartData[chartID].xAxis[_xAxisIndex].axisLabel.formatter = function (val) {
return parseFloat(val / 1000).toFixed(2) + 'mV'
}
state.chartData[chartID].chartXUnit = 'mV' // uV * 1000
break
case 3:
state.chartData[chartID].xAxis[_xAxisIndex].axisLabel.formatter = function (val) {
return parseFloat(val / 1000).toFixed(2) + 'Ω'
}
state.chartData[chartID].chartXUnit = 'Ω' // mOhm * 1000
break
default:
break
}
} else if (sourceList[0].name.includes('EIS')) {
switch (sourceList[0].channel) {
case 3:
state.chartData[chartID].xAxis[_xAxisIndex].axisLabel.formatter = function (val) {
return val + 'mHz'
}
state.chartData[chartID].chartXUnit = 'mHz' // nA * 1000
break
case 4:
state.chartData[chartID].xAxis[_xAxisIndex].axisLabel.formatter = function (val) {
return val + 'cycle'
}
state.chartData[chartID].chartXUnit = 'cycle' // nA * 1000
break
case 8:
state.chartData[chartID].xAxis[_xAxisIndex].axisLabel.formatter = function (val) {
return val + '˚'
}
state.chartData[chartID].chartXUnit = '˚' // nA * 1000
break
case 9:
state.chartData[chartID].xAxis[_xAxisIndex].axisLabel.formatter = function (val) {
return val + 'nA'
}
state.chartData[chartID].chartXUnit = 'nA'
break
default:
state.chartData[chartID].xAxis[_xAxisIndex].axisLabel.formatter = function (val) {
return val + 'ohm'
}
state.chartData[chartID].chartXUnit = 'ohm'
break
}
}
// set yAxis format
if (sourceList[1].name === 'Neulive') {
const AcceleratorS = taskInfo.getDeviceInfo(sourceList[1].id).parameterSet.ACCELERATOR_S
let scaleRange
switch (AcceleratorS) {
case 0:
scaleRange = 200
break
case 1:
scaleRange = 400
break
case 2:
scaleRange = 800
break
case 3:
scaleRange = 1600
break
default:
break
}
if (parseInt(sourceList[1].channel) >= 257 && parseInt(sourceList[1].channel) <= 260) {
if (parseInt(sourceList[1].channel) === 260) {
state.chartData[chartID].yAxis[_yAxisIndex].min = 0
state.chartData[chartID].yAxis[_yAxisIndex].max = Math.ceil(Math.sqrt(Math.pow(scaleRange, 2) * 3))
} else {
state.chartData[chartID].yAxis[_yAxisIndex].min = -scaleRange
state.chartData[chartID].yAxis[_yAxisIndex].max = scaleRange
}
state.chartData[chartID].yAxis[_yAxisIndex].axisLabel.formatter = function (val) {
return parseFloat(val / 100) + 'g'
}
} else {
state.chartData[chartID].yAxis[_yAxisIndex].axisLabel.formatter = function (val) {
return parseFloat(val).toFixed(2) + 'uV'
}
}
state.chartData[chartID].chartYUnit = 'uV'
} else if (sourceList[1].name === 'Elite') {
switch (sourceList[1].channel) {
case 1:
state.chartData[chartID].yAxis[_yAxisIndex].axisLabel.formatter = function (val) {
return parseFloat(val / 1000).toFixed(2) + 'uA'
}
state.chartData[chartID].chartYUnit = 'uA' // nA * 1000
break
case 2:
state.chartData[chartID].yAxis[_yAxisIndex].axisLabel.formatter = function (val) {
return parseFloat(val / 1000).toFixed(2) + 'mV'
}
state.chartData[chartID].chartYUnit = 'mV' // uV * 1000
break
case 3:
state.chartData[chartID].yAxis[_yAxisIndex].axisLabel.formatter = function (val) {
return parseFloat(val / 1000).toFixed(2) + 'Ω'
}
state.chartData[chartID].chartYUnit = 'Ω' // mOhm * 1000
break
default:
break
}
} else if (sourceList[1].name.includes('EIS')) {
switch (sourceList[1].channel) {
case 3:
state.chartData[chartID].yAxis[_yAxisIndex].axisLabel.formatter = function (val) {
return val + 'mHz'
}
state.chartData[chartID].chartYUnit = 'mHz' // nA * 1000
break
case 4:
state.chartData[chartID].yAxis[_yAxisIndex].axisLabel.formatter = function (val) {
return val + 'cycle'
}
state.chartData[chartID].chartYUnit = 'cycle' // nA * 1000
break
case 8:
state.chartData[chartID].yAxis[_yAxisIndex].axisLabel.formatter = function (val) {
return val + '˚'
}
state.chartData[chartID].chartYUnit = '˚' // nA * 1000
break
case 9:
state.chartData[chartID].yAxis[_yAxisIndex].axisLabel.formatter = function (val) {
return val + 'nA'
}
state.chartData[chartID].chartYUnit = 'nA'
break
default:
state.chartData[chartID].yAxis[_yAxisIndex].axisLabel.formatter = function (val) {
return val + 'ohm'
}
state.chartData[chartID].chartYUnit = 'ohm'
break
}
}
// register series into grid
const _axisList = []
const sourceArray = []
if (formula == null) {
sourceList.forEach((source, index) => {
@@ -408,6 +253,7 @@ const chartActs = {
if (index !== 0) {
_axis = 'Y'
}
sourceArray.push(source)
switch (source.name) {
case 'Time':
_axisList.push(_axis + ' AXIS = TIME')
@@ -417,31 +263,18 @@ const chartActs = {
_axisList.push(_axis + ' AXIS = NEULIVE ' + source.id + ' CHANNEL ' + source.channel)
break
case 'Elite':
dataStreamBuffer.register(chartID, source.id, source.channel)
switch (source.channel) {
case 1:
_axisList.push(_axis + ' AXIS = ELITE ' + source.id + ' CURRENT')
break
case 2:
_axisList.push(_axis + ' AXIS = ELITE ' + source.id + ' VOLTAGE')
break
case 3:
_axisList.push(_axis + ' AXIS = ELITE ' + source.id + ' RESISTANCE')
break
default:
_axisList.push(_axis + ' AXIS = ELITE ' + source.id + ' CHANNEL ' + source.channel)
break
}
dataStreamBuffer.register(chartID, source.mac_address, source.channel)
_axisList.push(_axis + ' AXIS = ELITE ' + source.id + ' CHANNEL ' + source.channel)
break
case 'EliteEIS':
// eslint-disable-next-line no-case-declarations
const device = state.deviceListNew.find((ele) => String(ele.memory_board) === String(source.id))
if (device === undefined) break
if (Number(device.configuration.MODE) === 0 || Number(device.configuration.MODE) === 5) {
state.chartData[chartID].series[state.chartData[chartID].series.length - 1].showSymbol = true
state.chartData[chartID].series[state.chartData[chartID].series.length - 1].showAllSymbol = true
}
dataStreamBuffer.register(chartID, source.id, source.channel)
// const device = state.deviceListNew.find((ele) => String(ele.memory_board) === String(source.id))
// if (device === undefined) break
// if (Number(device.configuration.MODE) === 0 || Number(device.configuration.MODE) === 5) {
// state.chartData[chartID].series[state.chartData[chartID].series.length - 1].showSymbol = true
// state.chartData[chartID].series[state.chartData[chartID].series.length - 1].showAllSymbol = true
// }
dataStreamBuffer.register(chartID, source.mac_address, source.channel)
switch (source.channel) {
case 1:
_axisList.push(_axis + ' AXIS = ELITEEIS ' + source.id + ' CHANNEL ' + source.channel)
@@ -452,7 +285,7 @@ const chartActs = {
}
break
default:
dataStreamBuffer.register(chartID, source.id, source.channel)
dataStreamBuffer.register(chartID, source.mac_address, source.channel)
_axisList.push(_axis + ' AXIS = DEVICE ' + source.id + ' CHANNEL ' + source.channel)
break
}
@@ -467,8 +300,10 @@ const chartActs = {
const _gridSeries = {
name: legendName,
xAxis: _axisList[0],
yAxis: _axisList[1],
// xAxis: _axisList[0],
// yAxis: _axisList[1],
xSource: sourceArray[0],
ySource: sourceArray[1],
}
if (state.chartData[chartID].gridSource[gridIndex] == null) {
state.chartData[chartID].gridSource[gridIndex] = []
@@ -478,11 +313,15 @@ const chartActs = {
}
// assign mappingID with device ID
if (deviceIDX >= 0) {
state.chartData[chartID].mappingID = deviceIDX
if (deviceX) {
if (state.chartData[chartID].mappingID.indexOf(deviceX.mac_address) === -1 && deviceX.mac_address) {
state.chartData[chartID].mappingID.push(deviceX.mac_address)
}
}
if (deviceIDY >= 0) {
state.chartData[chartID].mappingID = deviceIDY
if (deviceY) {
if (state.chartData[chartID].mappingID.indexOf(deviceY.mac_address) === -1 && deviceY.mac_address) {
state.chartData[chartID].mappingID.push(deviceY.mac_address)
}
}
return state.chartData[chartID]
},
@@ -494,7 +333,7 @@ const chartActs = {
*/
[typePath.updateGridList]: ({ state, getters, commit, dispatch }, payload) => {
const { chartID, length } = payload
state.chartData[chartID].grid = []
state.chartData[chartID].grid.length = 0
for (let i = 0; i < length; i++) {
state.chartData[chartID].grid.push(makeGrid(i, length))
}
@@ -618,10 +457,10 @@ const chartActs = {
}
}
} else {
if (series.xAxisSource[0] === -1 && series.yAxisSource[0] === -1) {
if (series.xAxisSource[0] === 'Time' && series.yAxisSource[0] === 'Time') {
return false
}
if (series.xAxisSource[0] === -1 || series.yAxisSource[0] === -1) {
if (series.xAxisSource[0] === 'Time' || series.yAxisSource[0] === 'Time') {
// x axis is time, y axis is value, so only need a device-channel data stream
let popData = []
@@ -630,7 +469,7 @@ const chartActs = {
const rawDeviceIDY = series.yAxisSource[0]
// pop data
if (series.xAxisSource[0] === -1) {
if (series.xAxisSource[0] === 'Time') {
popData = dataStreamBuffer.pop(chartID, rawDeviceIDY, series.yAxisSource[1])
} else {
popData = dataStreamBuffer.pop(chartID, rawDeviceIDX, series.xAxisSource[1])
@@ -646,7 +485,7 @@ const chartActs = {
})
const _popTime = data.time
// series data is empty or popdata time > last series data time
if (series.xAxisSource[0] === -1) {
if (series.xAxisSource[0] === 'Time') {
if (_popTime < 0) {
series.data.push([])
} else {
@@ -677,11 +516,11 @@ const chartActs = {
// series data list shift by time
if (series.data.length > 0) {
if (series.xAxisSource[0] === -1) {
if (series.xAxisSource[0] === 'Time') {
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) {
} else if (series.yAxisSource[0] === 'Time') {
if (series.data.length > state.chartData[chartID].maxDots) {
series.data.splice(0, series.data.length - state.chartData[chartID].maxDots)
}
@@ -690,7 +529,7 @@ const chartActs = {
// axis shift
if (series.data.length > 0) {
if (series.xAxisSource[0] === -1) {
if (series.xAxisSource[0] === 'Time') {
state.chartData[chartID].xAxis[series.xAxisIndex].max = series.data[series.data.length - 1][0]
state.chartData[chartID].xAxis[series.xAxisIndex].min = series.data[0][0]
} else {
@@ -708,7 +547,6 @@ const chartActs = {
if (rawDeviceIDX == null || rawDeviceIDY == null) {
return false
}
if (dataStreamBuffer.getByChartID(chartID)[rawDeviceIDX][series.xAxisSource[1]].length === 0 &&
dataStreamBuffer.getByChartID(chartID)[rawDeviceIDY][series.yAxisSource[1]].length === 0) {
// all of buffer is empty
@@ -833,7 +671,7 @@ const chartActs = {
* @return {bool}
*/
[typePath.defaultChartGenerator]: async ({ state, getters, commit, dispatch }, payload) => {
const { _deviceList, _itemID, _chartID, _type } = payload
const { _deviceList, _itemID, _chartID, _type, _reset } = payload
let item
_deviceList.forEach(_device => {
if (_itemID === _device.id) {
@@ -853,85 +691,28 @@ const chartActs = {
if (device.library_name.includes('Elite')) {
const setting = global_.getDefaultChartTypeByMode(device.configuration.MODE, device.library_name)
const xType = setting[0]
const xValue = setting[1]
let xValue = setting[1]
const yType = setting[2]
const yValue = setting[3]
let yValue = setting[3]
const xDevice = xType === 'Time' ? undefined : device
const yDevice = yType === 'Time' ? undefined : device
if (xType === 'Time') xValue = 'Time'
if (yType === 'Time') yValue = 'Time'
dispatch(typePath.register, {
chartID: chartID,
gridIndex: 0,
deviceNameX: xType,
deviceIDX: device.id,
deviceX: xDevice,
channelX: xValue,
deviceNameY: yType,
deviceIDY: device.id,
deviceY: yDevice,
channelY: yValue,
formula: null,
})
state.chartData[chartID].chartDevice = 'elite'
state.chartData[chartID].chartMode = device.configuration.MODE
if (device.library_name.includes('EIS')) {
switch (xValue) {
case 3:
state.chartData[chartID].chartXUnit = 'mHz'
break
case 4:
state.chartData[chartID].chartXUnit = 'cycle'
break
case 8:
state.chartData[chartID].chartXUnit = '˚'
break
case 9:
state.chartData[chartID].chartXUnit = 'nA'
break
default:
state.chartData[chartID].chartXUnit = 'ohm'
break
}
switch (yValue) {
case 3:
state.chartData[chartID].chartYUnit = 'mHz'
break
case 4:
state.chartData[chartID].chartYUnit = 'cycle'
break
case 8:
state.chartData[chartID].chartYUnit = '˚'
break
case 9:
state.chartData[chartID].chartYUnit = 'nA'
break
default:
state.chartData[chartID].chartYUnit = 'ohm'
break
}
} else {
switch (xValue) {
case 1:
state.chartData[chartID].chartXUnit = 'uA' // nA * 1000
break
case 2:
state.chartData[chartID].chartXUnit = 'mV' // uV * 1000
break
case 3:
state.chartData[chartID].chartXUnit = 'Ω' // mOhm * 1000
break
default:
break
}
switch (yValue) {
case 1:
state.chartData[chartID].chartYUnit = 'uA'
break
case 2:
state.chartData[chartID].chartYUnit = 'mV'
break
case 3:
state.chartData[chartID].chartYUnit = 'Ω'
break
default:
break
}
}
}
}
@@ -976,15 +757,15 @@ const chartActs = {
let isSetting = false
for (const chartID in state.chartData) {
if (state.chartData[chartID].mappingID === item.id) {
if (state.chartData[chartID].mappingID.includes(item.mac_address)) {
if (state.chartData[chartID].createdBy === 'default') {
isSetting = true
dispatch(typePath.reset, {
chartID: chartID,
mappingID: state.chartData[chartID].mappingID,
cardName: state.chartData[chartID].cardName,
reset: _reset,
})
state.chartData[chartID].mappingID = item.id
switch (_type) {
case 'device':
_chartRegisterDevice(chartID, item)
@@ -1011,17 +792,19 @@ const chartActs = {
* @param {String} cardName
*/
[typePath.reset]: ({ state, getters, commit, dispatch }, payload) => {
const { chartID, mappingID, cardName } = payload
const { chartID, mappingID, cardName, reset } = payload
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
if (reset === undefined) {
if (state.chartData[chartID].series.data != null) {
state.chartData[chartID].series.data.length = 0
}
state.chartData[chartID].series.length = 0
}
state.chartData[chartID].series.length = 0
if (mappingID == null) {
state.chartData[chartID].mappingID = '-1'
state.chartData[chartID].mappingID = []
}
if (cardName == null) {
state.chartData[chartID].cardName = 'Chart' + String(chartID)
@@ -1075,10 +858,83 @@ const chartActs = {
// to avoid overflow
state.taskContentChartPanelKey < 1000 ? state.taskContentChartPanelKey++ : state.taskContentChartPanelKey = 0
},
[typePath.removeGridSource]: async ({ state, getters, commit, dispatch }, payload) => {
const { chartID, gridIndex, gridSourceIndex } = payload
const gridSource = state.chartData[chartID].gridSource[gridIndex][gridSourceIndex]
if (gridSource === undefined) return
// remove series
const seriesIndex = state.chartData[chartID].series.findIndex((val) => {
return val.name === gridSource.name
})
state.chartData[chartID].series.splice(seriesIndex, 1)
// remove legend
state.chartData[chartID].legend.data = state.chartData[chartID].legend.data.filter((val) => {
return val !== gridSource.name
})
// remove xAxis, yAxis seriesIndex
// state.chartData[chartID].xAxis[gridIndex].seriesIndex = state.chartData[chartID].xAxis[gridIndex].seriesIndex.filter((val) => {
// console.log(val, seriesIndex, val !== seriesIndex)
// return val !== seriesIndex
// })
// state.chartData[chartID].yAxis[gridIndex].seriesIndex = state.chartData[chartID].yAxis[gridIndex].seriesIndex.filter(ele => ele !== seriesIndex)
// remove gridsource
state.chartData[chartID].gridSource[gridIndex].splice(gridSourceIndex, 1)
state.chartData[chartID].gridSource = JSON.parse(JSON.stringify(state.chartData[chartID].gridSource))
checkMappingID(state.chartData[chartID])
},
[typePath.removeGrid]: async ({ state, getters, commit, dispatch }, payload) => {
const { chartID, gridIndex } = payload
// remove all grid source & series
if (state.chartData[chartID].gridSource[gridIndex]) {
for (const gridSource in state.chartData[chartID].gridSource[gridIndex]) {
await dispatch(typePath.removeGridSource, {
chartID: chartID,
gridIndex: gridIndex,
gridSourceIndex: gridSource,
})
}
}
state.chartData[chartID].xAxis.splice(gridIndex, 1)
state.chartData[chartID].yAxis.splice(gridIndex, 1)
state.chartData[chartID].grid.splice(gridIndex, 1)
console.log('removeGrid!!!!', state.chartData[chartID])
},
[typePath.reLegendName]: async ({ state, getters, commit, dispatch }, payload) => {
const { chartID } = payload
// remove all grid source & series
getLegendName(state.chartData[chartID].sourceList, null, state.deviceListNew)
},
}
export default chartActs
function checkMappingID (chart) {
// check id is need to remove or not
const idList = [...chart.mappingID]
for (const id of idList) {
const result = checkGridSource(chart, id)
if (result === false) {
chart.mappingID = chart.mappingID.filter(ele => ele !== id)
}
}
}
function checkGridSource (chart, deviceID) {
for (const grid of chart.grid) {
for (const gridSource of chart.gridSource[grid.index]) {
if (gridSource.xSource.mac_address === deviceID) {
return true
}
if (gridSource.ySource.mac_address === deviceID) {
return true
}
}
}
return false
}
function parseGridSourceAxis (gridSourceAxis) {
// gridsource axis example:
// 'X AXIS = TIME'
@@ -1088,36 +944,46 @@ function parseGridSourceAxis (gridSourceAxis) {
deviceID: '',
channel: '',
}
const eliteChannel = ['CURRENT', 'VOLTAGE', 'RESISTANCE']
const parseResult = gridSourceAxis.split(' = ')[1].split(' ')
const _deviceName = parseResult[0]
if (_deviceName === 'TIME') {
if (gridSourceAxis.name === 'Time') {
deviceInfo.deviceName = 'Time'
deviceInfo.deviceID = -1
deviceInfo.channel = undefined
deviceInfo.deviceID = 'Time'
deviceInfo.channel = 'Time'
} else {
switch (_deviceName) {
case 'NEULIVE':
deviceInfo.deviceName = 'Neulive'
deviceInfo.deviceID = parseResult[1]
deviceInfo.channel = parseInt(parseResult[3])
break
case 'ELITE':
deviceInfo.deviceName = 'Elite'
deviceInfo.deviceID = parseResult[1]
deviceInfo.channel = eliteChannel.indexOf(parseResult[2]) + 1
break
case 'ELITEEIS':
deviceInfo.deviceName = 'EliteEIS'
deviceInfo.deviceID = parseResult[1]
deviceInfo.channel = Number(parseResult[3])
break
default:
break
}
deviceInfo.deviceName = gridSourceAxis.name
deviceInfo.deviceID = gridSourceAxis.id
deviceInfo.channel = Number(gridSourceAxis.channel)
deviceInfo.mac_address = gridSourceAxis.mac_address
}
// const eliteChannel = ['CURRENT', 'VOLTAGE', 'RESISTANCE']
// const parseResult = gridSourceAxis.split(' = ')[1].split(' ')
// const _deviceName = parseResult[0]
// if (_deviceName === 'TIME') {
// deviceInfo.deviceName = 'Time'
// deviceInfo.deviceID = 'Time'
// deviceInfo.channel = 'Time'
// } else {
// switch (_deviceName) {
// case 'NEULIVE':
// deviceInfo.deviceName = 'Neulive'
// deviceInfo.deviceID = parseResult[1]
// deviceInfo.channel = parseInt(parseResult[3])
// break
// case 'ELITE':
// deviceInfo.deviceName = 'Elite'
// deviceInfo.deviceID = parseResult[1]
// deviceInfo.channel = eliteChannel.indexOf(parseResult[2]) + 1
// break
// case 'ELITEEIS':
// deviceInfo.deviceName = 'EliteEIS'
// deviceInfo.deviceID = parseResult[1]
// deviceInfo.channel = Number(parseResult[3])
// break
// default:
// break
// }
// }
return deviceInfo
}
@@ -1232,25 +1098,25 @@ function getLegendName (sourceList, formulaID, deviceList) {
break
case 'Elite':
// eslint-disable-next-line no-case-declarations
device = deviceList.find((ele) => String(ele.memory_board) === String(source.id))
device = deviceList.find((ele) => String(ele.mac_address) === String(source.mac_address))
if (device === undefined) break
// eslint-disable-next-line no-case-declarations
channelName = getConfigChannel(device.library_name, device.configuration.MODE, source.channel - 1)
if (!channelName) break
legendName += 'E' + source.id + '-' + channelName.name[0]
legendName += source.mac_address.slice(12, 18) + '-' + channelName.name.replace('_', '')
break
case 'EliteEIS':
// eslint-disable-next-line no-case-declarations
device = deviceList.find((ele) => String(ele.memory_board) === String(source.id))
device = deviceList.find((ele) => String(ele.mac_address) === String(source.mac_address))
if (device === undefined) break
// eslint-disable-next-line no-case-declarations
channelName = getConfigChannel(device.library_name, device.configuration.MODE, source.channel - 1)
if (!channelName) break
if ([0, 5].indexOf(Number(device.configuration.MODE)) !== -1) {
legendName += 'E' + source.id + '-' + channelName.name.split('_').join('')
legendName += source.mac_address.slice(12, 18) + '-' + channelName.name.replace('_', '')
break
}
legendName += 'E' + source.id + '-' + channelName.name[0]
legendName += source.mac_address.slice(12, 18) + '-' + channelName.name.replace('_', '')
break
default:
legendName += 'D' + source.id + 'CH' + source.channel
@@ -0,0 +1,18 @@
import types from '@/store/modules/task/content/types'
const typePath = types.device
const deviceGet = {
[typePath.get]: (state) => (deviceOption) => {
const { macAddress, memoryBoard } = deviceOption
if (macAddress) {
return state.deviceListNew.find(device => device.mac_address === macAddress)
}
if (memoryBoard) {
return state.deviceListNew.find(device => Number(device.memory_board) === Number(memoryBoard))
}
return null
},
}
export default deviceGet
@@ -1,5 +1,7 @@
import { getField } from 'vuex-map-fields'
import deviceGet from './deviceGet'
export default {
...deviceGet,
getField,
}
+5
View File
@@ -13,6 +13,11 @@ const types = {
refreshData: 'taskContentChartRefreshData',
refreshChart: 'taskContentChartRefreshChart',
refreshPanel: 'taskContentChartRefreshPanel',
removeGridSource: 'taskRemoveGridSource',
removeGrid: 'taskRemoveGrid',
},
device: {
get: 'getDevice',
},
param: {
checkIfRecordingSetDone: 'checkIfRecordingSetDoneParam',